Flipping ATI2/3DC/BC5/RGTC/LATC DXT blocks

Some people prefer to vertically flip DDS images (without decompressing) in their texture loaders. There’s code around (nv_dds.cpp) that does this for DXT1/DXT3/DXT5 but not for ATI2/3DC/BC5/RGTC/LATC (which should all be one and the same format).

So does anyone have a code snippet, or could give someone a pointer/hint on how to do this? Plain DXT5 block flipping doesn’t work for this format.

See: nv_dds/nv_dds.cpp at master · paroj/nv_dds · GitHub

Well I realized shortly after posting that the answer was right under my nose. The ATI2 format of course uses the same compression format for both channels, so the code is already there to do the trick.

The relevant DXT5 flipping code (from the above linked source file):


void flip_blocks_dxtc5(DXTColBlock *line, unsigned int numBlocks)
{
 DXTColBlock *curblock = line;
 DXT5AlphaBlock *alphablock;
 
 for (unsigned int i = 0; i < numBlocks; i++)
 {
  // this flips DXT5 alpha block
  alphablock = (DXT5AlphaBlock*) curblock;
  flip_dxt5_alpha(alphablock);
  curblock++;
  
  // this flips DXT5 color block
  std::swap(curblock->row[0], curblock->row[3]);
  std::swap(curblock->row[1], curblock->row[2]);
  curblock++;
 }
}

For ATI2 format, the added code becomes:


void flip_blocks_ati2(DXTColBlock *line, unsigned int numBlocks)
{
 DXTColBlock *curblock = line;
 DXT5AlphaBlock *colorblock;
 DXT5AlphaBlock *alphablock;

 for (unsigned int i = 0; i < numBlocks; i++)
 {
  // this flips ATI2 R block
  alphablock = (DXT5AlphaBlock*) curblock;
  flip_dxt5_alpha(alphablock);
  curblock++;
  
  // this flips ATI2 G block
  colorblock = (DXT5AlphaBlock*) curblock;
  flip_dxt5_alpha(colorblock);
  curblock++;
 }
}

So effectively both channel sub-blocks are treated as DXT5 alpha channel blocks to flip them, which works like a charm.

Of course you need to register the flip_blocks_ati2 callback based on the DDS FOURCC elsewhere in the code.

Cheers!