151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu/* 251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * Copyright (C) 2011 LunarG, Inc. 351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * 451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * Permission is hereby granted, free of charge, to any person obtaining a 551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * copy of this software and associated documentation files (the "Software"), 651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * to deal in the Software without restriction, including without limitation 751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * the rights to use, copy, modify, merge, publish, distribute, sublicense, 851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * and/or sell copies of the Software, and to permit persons to whom the 951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * Software is furnished to do so, subject to the following conditions: 1051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * 1151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * The above copyright notice and this permission notice (including the next 1251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * paragraph) shall be included in all copies or substantial portions of the 1351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * Software. 1451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * 1551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * DEALINGS IN THE SOFTWARE. 2251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu */ 2351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 2451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu/* 2551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu * Included by texcompress_etc1 and gallium to define ETC1 decoding routines. 2651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu */ 2751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 2851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wustruct TAG(etc1_block) { 2951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu uint32_t pixel_indices; 3051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu int flipped; 3151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu const int *modifier_tables[2]; 3251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu UINT8_TYPE base_colors[2][3]; 3351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu}; 3451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 3551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wustatic UINT8_TYPE 3651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I WuTAG(etc1_base_color_diff_hi)(UINT8_TYPE in) 3751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu{ 3851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu return (in & 0xf8) | (in >> 5); 3951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu} 4051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 4151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wustatic UINT8_TYPE 4251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I WuTAG(etc1_base_color_diff_lo)(UINT8_TYPE in) 4351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu{ 4451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu static const int lookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 }; 4551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 4651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu in = (in >> 3) + lookup[in & 0x7]; 4751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 4851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu return (in << 3) | (in >> 2); 4951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu} 5051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 5151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wustatic UINT8_TYPE 5251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I WuTAG(etc1_base_color_ind_hi)(UINT8_TYPE in) 5351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu{ 5451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu return (in & 0xf0) | ((in & 0xf0) >> 4); 5551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu} 5651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 5751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wustatic UINT8_TYPE 5851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I WuTAG(etc1_base_color_ind_lo)(UINT8_TYPE in) 5951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu{ 6051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu return ((in & 0xf) << 4) | (in & 0xf); 6151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu} 6251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 6351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wustatic UINT8_TYPE 6451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I WuTAG(etc1_clamp)(UINT8_TYPE base, int modifier) 6551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu{ 6651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu int tmp = (int) base + modifier; 6751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 6851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu /* CLAMP(tmp, 0, 255) */ 6951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu return (UINT8_TYPE) ((tmp < 0) ? 0 : ((tmp > 255) ? 255 : tmp)); 7051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu} 7151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 7251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wustatic const int TAG(etc1_modifier_tables)[8][4] = { 7351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu { 2, 8, -2, -8}, 7451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu { 5, 17, -5, -17}, 7551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu { 9, 29, -9, -29}, 7651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu { 13, 42, -13, -42}, 7751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu { 18, 60, -18, -60}, 7851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu { 24, 80, -24, -80}, 7951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu { 33, 106, -33, -106}, 8051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu { 47, 183, -47, -183} 8151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu}; 8251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 8351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wustatic void 8451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I WuTAG(etc1_parse_block)(struct TAG(etc1_block) *block, const UINT8_TYPE *src) 8551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu{ 8651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu if (src[3] & 0x2) { 8751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu /* differential mode */ 8851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[0][0] = (int) TAG(etc1_base_color_diff_hi)(src[0]); 8951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[1][0] = (int) TAG(etc1_base_color_diff_lo)(src[0]); 9051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[0][1] = (int) TAG(etc1_base_color_diff_hi)(src[1]); 9151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[1][1] = (int) TAG(etc1_base_color_diff_lo)(src[1]); 9251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[0][2] = (int) TAG(etc1_base_color_diff_hi)(src[2]); 9351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[1][2] = (int) TAG(etc1_base_color_diff_lo)(src[2]); 9451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu } 9551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu else { 9651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu /* individual mode */ 9751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[0][0] = (int) TAG(etc1_base_color_ind_hi)(src[0]); 9851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[1][0] = (int) TAG(etc1_base_color_ind_lo)(src[0]); 9951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[0][1] = (int) TAG(etc1_base_color_ind_hi)(src[1]); 10051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[1][1] = (int) TAG(etc1_base_color_ind_lo)(src[1]); 10151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[0][2] = (int) TAG(etc1_base_color_ind_hi)(src[2]); 10251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->base_colors[1][2] = (int) TAG(etc1_base_color_ind_lo)(src[2]); 10351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu } 10451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 10551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu /* pick modifier tables */ 10651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->modifier_tables[0] = TAG(etc1_modifier_tables)[(src[3] >> 5) & 0x7]; 10751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->modifier_tables[1] = TAG(etc1_modifier_tables)[(src[3] >> 2) & 0x7]; 10851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 10951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->flipped = (src[3] & 0x1); 11051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 11151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu block->pixel_indices = 11251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7]; 11351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu} 11451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 11551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wustatic void 11651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I WuTAG(etc1_fetch_texel)(const struct TAG(etc1_block) *block, 11751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu int x, int y, UINT8_TYPE *dst) 11851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu{ 11951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu const UINT8_TYPE *base_color; 12051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu int modifier, bit, idx, blk; 12151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 12251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu /* get pixel index */ 12351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu bit = y + x * 4; 12451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu idx = ((block->pixel_indices >> (15 + bit)) & 0x2) | 12551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu ((block->pixel_indices >> (bit)) & 0x1); 12651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 12751f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu /* get subblock */ 12851f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu blk = (block->flipped) ? (y >= 2) : (x >= 2); 12951f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 13051f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu base_color = block->base_colors[blk]; 13151f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu modifier = block->modifier_tables[blk][idx]; 13251f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu 13351f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu dst[0] = TAG(etc1_clamp)(base_color[0], modifier); 13451f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu dst[1] = TAG(etc1_clamp)(base_color[1], modifier); 13551f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu dst[2] = TAG(etc1_clamp)(base_color[2], modifier); 13651f4d2725417088c75d512b69a31a26ae5cb3ef2Chia-I Wu} 137d7458e401e97aea882309855cc72730aa3b39920Chad Versace 138d7458e401e97aea882309855cc72730aa3b39920Chad Versacestatic void 139d7458e401e97aea882309855cc72730aa3b39920Chad Versaceetc1_unpack_rgba8888(uint8_t *dst_row, 140d7458e401e97aea882309855cc72730aa3b39920Chad Versace unsigned dst_stride, 141d7458e401e97aea882309855cc72730aa3b39920Chad Versace const uint8_t *src_row, 142d7458e401e97aea882309855cc72730aa3b39920Chad Versace unsigned src_stride, 143d7458e401e97aea882309855cc72730aa3b39920Chad Versace unsigned width, 144d7458e401e97aea882309855cc72730aa3b39920Chad Versace unsigned height) 145d7458e401e97aea882309855cc72730aa3b39920Chad Versace{ 146d7458e401e97aea882309855cc72730aa3b39920Chad Versace const unsigned bw = 4, bh = 4, bs = 8, comps = 4; 147d7458e401e97aea882309855cc72730aa3b39920Chad Versace struct etc1_block block; 148d7458e401e97aea882309855cc72730aa3b39920Chad Versace unsigned x, y, i, j; 149d7458e401e97aea882309855cc72730aa3b39920Chad Versace 150d7458e401e97aea882309855cc72730aa3b39920Chad Versace for (y = 0; y < height; y += bh) { 151d7458e401e97aea882309855cc72730aa3b39920Chad Versace const uint8_t *src = src_row; 152d7458e401e97aea882309855cc72730aa3b39920Chad Versace 153d7458e401e97aea882309855cc72730aa3b39920Chad Versace for (x = 0; x < width; x+= bw) { 154d7458e401e97aea882309855cc72730aa3b39920Chad Versace etc1_parse_block(&block, src); 155d7458e401e97aea882309855cc72730aa3b39920Chad Versace 156d7458e401e97aea882309855cc72730aa3b39920Chad Versace for (j = 0; j < bh; j++) { 157d7458e401e97aea882309855cc72730aa3b39920Chad Versace uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; 158d7458e401e97aea882309855cc72730aa3b39920Chad Versace for (i = 0; i < bw; i++) { 159d7458e401e97aea882309855cc72730aa3b39920Chad Versace etc1_fetch_texel(&block, i, j, dst); 160d7458e401e97aea882309855cc72730aa3b39920Chad Versace dst[3] = 255; 161d7458e401e97aea882309855cc72730aa3b39920Chad Versace dst += comps; 162d7458e401e97aea882309855cc72730aa3b39920Chad Versace } 163d7458e401e97aea882309855cc72730aa3b39920Chad Versace } 164d7458e401e97aea882309855cc72730aa3b39920Chad Versace 165d7458e401e97aea882309855cc72730aa3b39920Chad Versace src += bs; 166d7458e401e97aea882309855cc72730aa3b39920Chad Versace } 167d7458e401e97aea882309855cc72730aa3b39920Chad Versace 168d7458e401e97aea882309855cc72730aa3b39920Chad Versace src_row += src_stride; 169d7458e401e97aea882309855cc72730aa3b39920Chad Versace } 170d7458e401e97aea882309855cc72730aa3b39920Chad Versace} 171