diff options
Diffstat (limited to 'source/blender/imbuf/intern/dds/FlipDXT.cpp')
-rw-r--r-- | source/blender/imbuf/intern/dds/FlipDXT.cpp | 346 |
1 files changed, 172 insertions, 174 deletions
diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp index 50488b923db..0660d5ce5cc 100644 --- a/source/blender/imbuf/intern/dds/FlipDXT.cpp +++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp @@ -50,207 +50,205 @@ typedef void (*FlipBlockFunction)(uint8_t *block); // Flips a full DXT1 block in the y direction. static void FlipDXT1BlockFull(uint8_t *block) { - // A DXT1 block layout is: - // [0-1] color0. - // [2-3] color1. - // [4-7] color bitmap, 2 bits per pixel. - // So each of the 4-7 bytes represents one line, flipping a block is just - // flipping those bytes. - uint8_t tmp = block[4]; - block[4] = block[7]; - block[7] = tmp; - tmp = block[5]; - block[5] = block[6]; - block[6] = tmp; + // A DXT1 block layout is: + // [0-1] color0. + // [2-3] color1. + // [4-7] color bitmap, 2 bits per pixel. + // So each of the 4-7 bytes represents one line, flipping a block is just + // flipping those bytes. + uint8_t tmp = block[4]; + block[4] = block[7]; + block[7] = tmp; + tmp = block[5]; + block[5] = block[6]; + block[6] = tmp; } // Flips the first 2 lines of a DXT1 block in the y direction. static void FlipDXT1BlockHalf(uint8_t *block) { - // See layout above. - uint8_t tmp = block[4]; - block[4] = block[5]; - block[5] = tmp; + // See layout above. + uint8_t tmp = block[4]; + block[4] = block[5]; + block[5] = tmp; } // Flips a full DXT3 block in the y direction. static void FlipDXT3BlockFull(uint8_t *block) { - // A DXT3 block layout is: - // [0-7] alpha bitmap, 4 bits per pixel. - // [8-15] a DXT1 block. - - // We can flip the alpha bits at the byte level (2 bytes per line). - uint8_t tmp = block[0]; - - block[0] = block[6]; - block[6] = tmp; - tmp = block[1]; - block[1] = block[7]; - block[7] = tmp; - tmp = block[2]; - block[2] = block[4]; - block[4] = tmp; - tmp = block[3]; - block[3] = block[5]; - block[5] = tmp; - - // And flip the DXT1 block using the above function. - FlipDXT1BlockFull(block + 8); + // A DXT3 block layout is: + // [0-7] alpha bitmap, 4 bits per pixel. + // [8-15] a DXT1 block. + + // We can flip the alpha bits at the byte level (2 bytes per line). + uint8_t tmp = block[0]; + + block[0] = block[6]; + block[6] = tmp; + tmp = block[1]; + block[1] = block[7]; + block[7] = tmp; + tmp = block[2]; + block[2] = block[4]; + block[4] = tmp; + tmp = block[3]; + block[3] = block[5]; + block[5] = tmp; + + // And flip the DXT1 block using the above function. + FlipDXT1BlockFull(block + 8); } // Flips the first 2 lines of a DXT3 block in the y direction. static void FlipDXT3BlockHalf(uint8_t *block) { - // See layout above. - uint8_t tmp = block[0]; - - block[0] = block[2]; - block[2] = tmp; - tmp = block[1]; - block[1] = block[3]; - block[3] = tmp; - FlipDXT1BlockHalf(block + 8); + // See layout above. + uint8_t tmp = block[0]; + + block[0] = block[2]; + block[2] = tmp; + tmp = block[1]; + block[1] = block[3]; + block[3] = tmp; + FlipDXT1BlockHalf(block + 8); } // Flips a full DXT5 block in the y direction. static void FlipDXT5BlockFull(uint8_t *block) { - // A DXT5 block layout is: - // [0] alpha0. - // [1] alpha1. - // [2-7] alpha bitmap, 3 bits per pixel. - // [8-15] a DXT1 block. - - // The alpha bitmap doesn't easily map lines to bytes, so we have to - // interpret it correctly. Extracted from - // http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt : - // - // The 6 "bits" bytes of the block are decoded into one 48-bit integer: - // - // bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 + - // 256 * (bits_4 + 256 * bits_5)))) - // - // bits is a 48-bit unsigned integer, from which a three-bit control code - // is extracted for a texel at location (x,y) in the block using: - // - // code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0] - // - // where bit 47 is the most significant and bit 0 is the least - // significant bit. - unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]); - unsigned int line_2_3 = block[5] + 256 * (block[6] + 256 * block[7]); - // swap lines 0 and 1 in line_0_1. - unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | - ((line_0_1 & 0xfff000) >> 12); - // swap lines 2 and 3 in line_2_3. - unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) | - ((line_2_3 & 0xfff000) >> 12); - - block[2] = line_3_2 & 0xff; - block[3] = (line_3_2 & 0xff00) >> 8; - block[4] = (line_3_2 & 0xff0000) >> 16; - block[5] = line_1_0 & 0xff; - block[6] = (line_1_0 & 0xff00) >> 8; - block[7] = (line_1_0 & 0xff0000) >> 16; - - // And flip the DXT1 block using the above function. - FlipDXT1BlockFull(block + 8); + // A DXT5 block layout is: + // [0] alpha0. + // [1] alpha1. + // [2-7] alpha bitmap, 3 bits per pixel. + // [8-15] a DXT1 block. + + // The alpha bitmap doesn't easily map lines to bytes, so we have to + // interpret it correctly. Extracted from + // http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt : + // + // The 6 "bits" bytes of the block are decoded into one 48-bit integer: + // + // bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 + + // 256 * (bits_4 + 256 * bits_5)))) + // + // bits is a 48-bit unsigned integer, from which a three-bit control code + // is extracted for a texel at location (x,y) in the block using: + // + // code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0] + // + // where bit 47 is the most significant and bit 0 is the least + // significant bit. + unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]); + unsigned int line_2_3 = block[5] + 256 * (block[6] + 256 * block[7]); + // swap lines 0 and 1 in line_0_1. + unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | ((line_0_1 & 0xfff000) >> 12); + // swap lines 2 and 3 in line_2_3. + unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) | ((line_2_3 & 0xfff000) >> 12); + + block[2] = line_3_2 & 0xff; + block[3] = (line_3_2 & 0xff00) >> 8; + block[4] = (line_3_2 & 0xff0000) >> 16; + block[5] = line_1_0 & 0xff; + block[6] = (line_1_0 & 0xff00) >> 8; + block[7] = (line_1_0 & 0xff0000) >> 16; + + // And flip the DXT1 block using the above function. + FlipDXT1BlockFull(block + 8); } // Flips the first 2 lines of a DXT5 block in the y direction. static void FlipDXT5BlockHalf(uint8_t *block) { - // See layout above. - unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]); - unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | - ((line_0_1 & 0xfff000) >> 12); - block[2] = line_1_0 & 0xff; - block[3] = (line_1_0 & 0xff00) >> 8; - block[4] = (line_1_0 & 0xff0000) >> 16; - FlipDXT1BlockHalf(block + 8); + // See layout above. + unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]); + unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | ((line_0_1 & 0xfff000) >> 12); + block[2] = line_1_0 & 0xff; + block[3] = (line_1_0 & 0xff00) >> 8; + block[4] = (line_1_0 & 0xff0000) >> 16; + FlipDXT1BlockHalf(block + 8); } // Flips a DXTC image, by flipping and swapping DXTC blocks as appropriate. -int FlipDXTCImage(unsigned int width, unsigned int height, unsigned int levels, int fourcc, uint8_t *data) +int FlipDXTCImage( + unsigned int width, unsigned int height, unsigned int levels, int fourcc, uint8_t *data) { - // must have valid dimensions - if (width == 0 || height == 0) - return 0; - // height must be a power-of-two - if ((height & (height - 1)) != 0) - return 0; - - FlipBlockFunction full_block_function; - FlipBlockFunction half_block_function; - unsigned int block_bytes = 0; - - switch (fourcc) { - case FOURCC_DXT1: - full_block_function = FlipDXT1BlockFull; - half_block_function = FlipDXT1BlockHalf; - block_bytes = 8; - break; - case FOURCC_DXT3: - full_block_function = FlipDXT3BlockFull; - half_block_function = FlipDXT3BlockHalf; - block_bytes = 16; - break; - case FOURCC_DXT5: - full_block_function = FlipDXT5BlockFull; - half_block_function = FlipDXT5BlockHalf; - block_bytes = 16; - break; - default: - return 0; - } - - unsigned int mip_width = width; - unsigned int mip_height = height; - - for (unsigned int i = 0; i < levels; ++i) { - unsigned int blocks_per_row = (mip_width + 3) / 4; - unsigned int blocks_per_col = (mip_height + 3) / 4; - unsigned int blocks = blocks_per_row * blocks_per_col; - - if (mip_height == 1) { - // no flip to do, and we're done. - break; - } - else if (mip_height == 2) { - // flip the first 2 lines in each block. - for (unsigned int i = 0; i < blocks_per_row; ++i) { - half_block_function(data + i * block_bytes); - } - } - else { - // flip each block. - for (unsigned int i = 0; i < blocks; ++i) - full_block_function(data + i * block_bytes); - - // swap each block line in the first half of the image with the - // corresponding one in the second half. - // note that this is a no-op if mip_height is 4. - unsigned int row_bytes = block_bytes * blocks_per_row; - uint8_t *temp_line = new uint8_t[row_bytes]; - - for (unsigned int y = 0; y < blocks_per_col / 2; ++y) { - uint8_t *line1 = data + y * row_bytes; - uint8_t *line2 = data + (blocks_per_col - y - 1) * row_bytes; - - memcpy(temp_line, line1, row_bytes); - memcpy(line1, line2, row_bytes); - memcpy(line2, temp_line, row_bytes); - } - - delete[] temp_line; - } - - // mip levels are contiguous. - data += block_bytes * blocks; - mip_width = MAX(1U, mip_width >> 1); - mip_height = MAX(1U, mip_height >> 1); - } - - return 1; + // must have valid dimensions + if (width == 0 || height == 0) + return 0; + // height must be a power-of-two + if ((height & (height - 1)) != 0) + return 0; + + FlipBlockFunction full_block_function; + FlipBlockFunction half_block_function; + unsigned int block_bytes = 0; + + switch (fourcc) { + case FOURCC_DXT1: + full_block_function = FlipDXT1BlockFull; + half_block_function = FlipDXT1BlockHalf; + block_bytes = 8; + break; + case FOURCC_DXT3: + full_block_function = FlipDXT3BlockFull; + half_block_function = FlipDXT3BlockHalf; + block_bytes = 16; + break; + case FOURCC_DXT5: + full_block_function = FlipDXT5BlockFull; + half_block_function = FlipDXT5BlockHalf; + block_bytes = 16; + break; + default: + return 0; + } + + unsigned int mip_width = width; + unsigned int mip_height = height; + + for (unsigned int i = 0; i < levels; ++i) { + unsigned int blocks_per_row = (mip_width + 3) / 4; + unsigned int blocks_per_col = (mip_height + 3) / 4; + unsigned int blocks = blocks_per_row * blocks_per_col; + + if (mip_height == 1) { + // no flip to do, and we're done. + break; + } + else if (mip_height == 2) { + // flip the first 2 lines in each block. + for (unsigned int i = 0; i < blocks_per_row; ++i) { + half_block_function(data + i * block_bytes); + } + } + else { + // flip each block. + for (unsigned int i = 0; i < blocks; ++i) + full_block_function(data + i * block_bytes); + + // swap each block line in the first half of the image with the + // corresponding one in the second half. + // note that this is a no-op if mip_height is 4. + unsigned int row_bytes = block_bytes * blocks_per_row; + uint8_t *temp_line = new uint8_t[row_bytes]; + + for (unsigned int y = 0; y < blocks_per_col / 2; ++y) { + uint8_t *line1 = data + y * row_bytes; + uint8_t *line2 = data + (blocks_per_col - y - 1) * row_bytes; + + memcpy(temp_line, line1, row_bytes); + memcpy(line1, line2, row_bytes); + memcpy(line2, temp_line, row_bytes); + } + + delete[] temp_line; + } + + // mip levels are contiguous. + data += block_bytes * blocks; + mip_width = MAX(1U, mip_width >> 1); + mip_height = MAX(1U, mip_height >> 1); + } + + return 1; } |