1848b8605Smrg/* 2848b8605Smrg * Copyright (C) 2011 LunarG, Inc. 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Software"), 6848b8605Smrg * to deal in the Software without restriction, including without limitation 7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 9848b8605Smrg * Software is furnished to do so, subject to the following conditions: 10848b8605Smrg * 11848b8605Smrg * The above copyright notice and this permission notice (including the next 12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 13848b8605Smrg * Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21848b8605Smrg * DEALINGS IN THE SOFTWARE. 22848b8605Smrg */ 23848b8605Smrg 24848b8605Smrg/** 25848b8605Smrg * \file texcompress_etc.c 26848b8605Smrg * GL_OES_compressed_ETC1_RGB8_texture support. 27848b8605Smrg * Supported ETC2 texture formats are: 28848b8605Smrg * GL_COMPRESSED_RGB8_ETC2 29848b8605Smrg * GL_COMPRESSED_SRGB8_ETC2 30848b8605Smrg * GL_COMPRESSED_RGBA8_ETC2_EAC 31848b8605Smrg * GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 32848b8605Smrg * GL_COMPRESSED_R11_EAC 33848b8605Smrg * GL_COMPRESSED_RG11_EAC 34848b8605Smrg * GL_COMPRESSED_SIGNED_R11_EAC 35848b8605Smrg * GL_COMPRESSED_SIGNED_RG11_EAC 36848b8605Smrg * MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1 37848b8605Smrg * MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1 38848b8605Smrg */ 39848b8605Smrg 40848b8605Smrg#include <stdbool.h> 41848b8605Smrg#include "texcompress.h" 42848b8605Smrg#include "texcompress_etc.h" 43848b8605Smrg#include "texstore.h" 44b8e80941Smrg#include "config.h" 45848b8605Smrg#include "macros.h" 46848b8605Smrg#include "format_unpack.h" 47848b8605Smrg#include "util/format_srgb.h" 48848b8605Smrg 49848b8605Smrg 50848b8605Smrgstruct etc2_block { 51848b8605Smrg int distance; 52848b8605Smrg uint64_t pixel_indices[2]; 53848b8605Smrg const int *modifier_tables[2]; 54848b8605Smrg bool flipped; 55848b8605Smrg bool opaque; 56848b8605Smrg bool is_ind_mode; 57848b8605Smrg bool is_diff_mode; 58848b8605Smrg bool is_t_mode; 59848b8605Smrg bool is_h_mode; 60848b8605Smrg bool is_planar_mode; 61848b8605Smrg uint8_t base_colors[3][3]; 62848b8605Smrg uint8_t paint_colors[4][3]; 63848b8605Smrg uint8_t base_codeword; 64848b8605Smrg uint8_t multiplier; 65848b8605Smrg uint8_t table_index; 66848b8605Smrg}; 67848b8605Smrg 68848b8605Smrgstatic const int etc2_distance_table[8] = { 69848b8605Smrg 3, 6, 11, 16, 23, 32, 41, 64 }; 70848b8605Smrg 71848b8605Smrgstatic const int etc2_modifier_tables[16][8] = { 72848b8605Smrg { -3, -6, -9, -15, 2, 5, 8, 14}, 73848b8605Smrg { -3, -7, -10, -13, 2, 6, 9, 12}, 74848b8605Smrg { -2, -5, -8, -13, 1, 4, 7, 12}, 75848b8605Smrg { -2, -4, -6, -13, 1, 3, 5, 12}, 76848b8605Smrg { -3, -6, -8, -12, 2, 5, 7, 11}, 77848b8605Smrg { -3, -7, -9, -11, 2, 6, 8, 10}, 78848b8605Smrg { -4, -7, -8, -11, 3, 6, 7, 10}, 79848b8605Smrg { -3, -5, -8, -11, 2, 4, 7, 10}, 80848b8605Smrg { -2, -6, -8, -10, 1, 5, 7, 9}, 81848b8605Smrg { -2, -5, -8, -10, 1, 4, 7, 9}, 82848b8605Smrg { -2, -4, -8, -10, 1, 3, 7, 9}, 83848b8605Smrg { -2, -5, -7, -10, 1, 4, 6, 9}, 84848b8605Smrg { -3, -4, -7, -10, 2, 3, 6, 9}, 85848b8605Smrg { -1, -2, -3, -10, 0, 1, 2, 9}, 86848b8605Smrg { -4, -6, -8, -9, 3, 5, 7, 8}, 87848b8605Smrg { -3, -5, -7, -9, 2, 4, 6, 8}, 88848b8605Smrg}; 89848b8605Smrg 90848b8605Smrgstatic const int etc2_modifier_tables_non_opaque[8][4] = { 91848b8605Smrg { 0, 8, 0, -8}, 92848b8605Smrg { 0, 17, 0, -17}, 93848b8605Smrg { 0, 29, 0, -29}, 94848b8605Smrg { 0, 42, 0, -42}, 95848b8605Smrg { 0, 60, 0, -60}, 96848b8605Smrg { 0, 80, 0, -80}, 97848b8605Smrg { 0, 106, 0, -106}, 98848b8605Smrg { 0, 183, 0, -183} 99848b8605Smrg}; 100848b8605Smrg 101848b8605Smrg/* define etc1_parse_block and etc. */ 102848b8605Smrg#define UINT8_TYPE GLubyte 103848b8605Smrg#define TAG(x) x 104848b8605Smrg#include "texcompress_etc_tmp.h" 105848b8605Smrg#undef TAG 106848b8605Smrg#undef UINT8_TYPE 107848b8605Smrg 108848b8605SmrgGLboolean 109b8e80941Smrg_mesa_texstore_etc1_rgb8(UNUSED_TEXSTORE_PARAMS) 110848b8605Smrg{ 111848b8605Smrg /* GL_ETC1_RGB8_OES is only valid in glCompressedTexImage2D */ 112b8e80941Smrg assert(0); 113848b8605Smrg 114848b8605Smrg return GL_FALSE; 115848b8605Smrg} 116848b8605Smrg 117848b8605Smrg 118848b8605Smrg/** 119848b8605Smrg * Decode texture data in format `MESA_FORMAT_ETC1_RGB8` to 120848b8605Smrg * `MESA_FORMAT_ABGR8888`. 121848b8605Smrg * 122848b8605Smrg * The size of the source data must be a multiple of the ETC1 block size, 123848b8605Smrg * which is 8, even if the texture image's dimensions are not aligned to 4. 124848b8605Smrg * From the GL_OES_compressed_ETC1_RGB8_texture spec: 125848b8605Smrg * The texture is described as a number of 4x4 pixel blocks. If the 126848b8605Smrg * texture (or a particular mip-level) is smaller than 4 pixels in 127848b8605Smrg * any dimension (such as a 2x2 or a 8x1 texture), the texture is 128848b8605Smrg * found in the upper left part of the block(s), and the rest of the 129848b8605Smrg * pixels are not used. For instance, a texture of size 4x2 will be 130848b8605Smrg * placed in the upper half of a 4x4 block, and the lower half of the 131848b8605Smrg * pixels in the block will not be accessed. 132848b8605Smrg * 133848b8605Smrg * \param src_width in pixels 134848b8605Smrg * \param src_height in pixels 135848b8605Smrg * \param dst_stride in bytes 136848b8605Smrg */ 137848b8605Smrgvoid 138848b8605Smrg_mesa_etc1_unpack_rgba8888(uint8_t *dst_row, 139848b8605Smrg unsigned dst_stride, 140848b8605Smrg const uint8_t *src_row, 141848b8605Smrg unsigned src_stride, 142848b8605Smrg unsigned src_width, 143848b8605Smrg unsigned src_height) 144848b8605Smrg{ 145848b8605Smrg etc1_unpack_rgba8888(dst_row, dst_stride, 146848b8605Smrg src_row, src_stride, 147848b8605Smrg src_width, src_height); 148848b8605Smrg} 149848b8605Smrg 150848b8605Smrgstatic uint8_t 151848b8605Smrgetc2_base_color1_t_mode(const uint8_t *in, GLuint index) 152848b8605Smrg{ 153848b8605Smrg uint8_t R1a = 0, x = 0; 154848b8605Smrg /* base col 1 = extend_4to8bits( (R1a << 2) | R1b, G1, B1) */ 155848b8605Smrg switch(index) { 156848b8605Smrg case 0: 157848b8605Smrg R1a = (in[0] >> 3) & 0x3; 158848b8605Smrg x = ((R1a << 2) | (in[0] & 0x3)); 159848b8605Smrg break; 160848b8605Smrg case 1: 161848b8605Smrg x = ((in[1] >> 4) & 0xf); 162848b8605Smrg break; 163848b8605Smrg case 2: 164848b8605Smrg x = (in[1] & 0xf); 165848b8605Smrg break; 166848b8605Smrg default: 167848b8605Smrg /* invalid index */ 168848b8605Smrg break; 169848b8605Smrg } 170848b8605Smrg return ((x << 4) | (x & 0xf)); 171848b8605Smrg} 172848b8605Smrg 173848b8605Smrgstatic uint8_t 174848b8605Smrgetc2_base_color2_t_mode(const uint8_t *in, GLuint index) 175848b8605Smrg{ 176848b8605Smrg uint8_t x = 0; 177848b8605Smrg /*extend 4to8bits(R2, G2, B2)*/ 178848b8605Smrg switch(index) { 179848b8605Smrg case 0: 180848b8605Smrg x = ((in[2] >> 4) & 0xf ); 181848b8605Smrg break; 182848b8605Smrg case 1: 183848b8605Smrg x = (in[2] & 0xf); 184848b8605Smrg break; 185848b8605Smrg case 2: 186848b8605Smrg x = ((in[3] >> 4) & 0xf); 187848b8605Smrg break; 188848b8605Smrg default: 189848b8605Smrg /* invalid index */ 190848b8605Smrg break; 191848b8605Smrg } 192848b8605Smrg return ((x << 4) | (x & 0xf)); 193848b8605Smrg} 194848b8605Smrg 195848b8605Smrgstatic uint8_t 196848b8605Smrgetc2_base_color1_h_mode(const uint8_t *in, GLuint index) 197848b8605Smrg{ 198848b8605Smrg uint8_t x = 0; 199848b8605Smrg /* base col 1 = extend 4to8bits(R1, (G1a << 1) | G1b, (B1a << 3) | B1b) */ 200848b8605Smrg switch(index) { 201848b8605Smrg case 0: 202848b8605Smrg x = ((in[0] >> 3) & 0xf); 203848b8605Smrg break; 204848b8605Smrg case 1: 205848b8605Smrg x = (((in[0] & 0x7) << 1) | ((in[1] >> 4) & 0x1)); 206848b8605Smrg break; 207848b8605Smrg case 2: 208848b8605Smrg x = ((in[1] & 0x8) | 209848b8605Smrg (((in[1] & 0x3) << 1) | ((in[2] >> 7) & 0x1))); 210848b8605Smrg break; 211848b8605Smrg default: 212848b8605Smrg /* invalid index */ 213848b8605Smrg break; 214848b8605Smrg } 215848b8605Smrg return ((x << 4) | (x & 0xf)); 216848b8605Smrg} 217848b8605Smrg 218848b8605Smrgstatic uint8_t 219848b8605Smrgetc2_base_color2_h_mode(const uint8_t *in, GLuint index) 220848b8605Smrg{ 221848b8605Smrg uint8_t x = 0; 222848b8605Smrg /* base col 2 = extend 4to8bits(R2, G2, B2) */ 223848b8605Smrg switch(index) { 224848b8605Smrg case 0: 225848b8605Smrg x = ((in[2] >> 3) & 0xf ); 226848b8605Smrg break; 227848b8605Smrg case 1: 228848b8605Smrg x = (((in[2] & 0x7) << 1) | ((in[3] >> 7) & 0x1)); 229848b8605Smrg break; 230848b8605Smrg case 2: 231848b8605Smrg x = ((in[3] >> 3) & 0xf); 232848b8605Smrg break; 233848b8605Smrg default: 234848b8605Smrg /* invalid index */ 235848b8605Smrg break; 236848b8605Smrg } 237848b8605Smrg return ((x << 4) | (x & 0xf)); 238848b8605Smrg} 239848b8605Smrg 240848b8605Smrgstatic uint8_t 241848b8605Smrgetc2_base_color_o_planar(const uint8_t *in, GLuint index) 242848b8605Smrg{ 243848b8605Smrg GLuint tmp; 244848b8605Smrg switch(index) { 245848b8605Smrg case 0: 246848b8605Smrg tmp = ((in[0] >> 1) & 0x3f); /* RO */ 247848b8605Smrg return ((tmp << 2) | (tmp >> 4)); 248848b8605Smrg case 1: 249848b8605Smrg tmp = (((in[0] & 0x1) << 6) | /* GO1 */ 250848b8605Smrg ((in[1] >> 1) & 0x3f)); /* GO2 */ 251848b8605Smrg return ((tmp << 1) | (tmp >> 6)); 252848b8605Smrg case 2: 253848b8605Smrg tmp = (((in[1] & 0x1) << 5) | /* BO1 */ 254848b8605Smrg (in[2] & 0x18) | /* BO2 */ 255848b8605Smrg (((in[2] & 0x3) << 1) | ((in[3] >> 7) & 0x1))); /* BO3 */ 256848b8605Smrg return ((tmp << 2) | (tmp >> 4)); 257848b8605Smrg default: 258848b8605Smrg /* invalid index */ 259848b8605Smrg return 0; 260848b8605Smrg } 261848b8605Smrg} 262848b8605Smrg 263848b8605Smrgstatic uint8_t 264848b8605Smrgetc2_base_color_h_planar(const uint8_t *in, GLuint index) 265848b8605Smrg{ 266848b8605Smrg GLuint tmp; 267848b8605Smrg switch(index) { 268848b8605Smrg case 0: 269848b8605Smrg tmp = (((in[3] & 0x7c) >> 1) | /* RH1 */ 270848b8605Smrg (in[3] & 0x1)); /* RH2 */ 271848b8605Smrg return ((tmp << 2) | (tmp >> 4)); 272848b8605Smrg case 1: 273848b8605Smrg tmp = (in[4] >> 1) & 0x7f; /* GH */ 274848b8605Smrg return ((tmp << 1) | (tmp >> 6)); 275848b8605Smrg case 2: 276848b8605Smrg tmp = (((in[4] & 0x1) << 5) | 277848b8605Smrg ((in[5] >> 3) & 0x1f)); /* BH */ 278848b8605Smrg return ((tmp << 2) | (tmp >> 4)); 279848b8605Smrg default: 280848b8605Smrg /* invalid index */ 281848b8605Smrg return 0; 282848b8605Smrg } 283848b8605Smrg} 284848b8605Smrg 285848b8605Smrgstatic uint8_t 286848b8605Smrgetc2_base_color_v_planar(const uint8_t *in, GLuint index) 287848b8605Smrg{ 288848b8605Smrg GLuint tmp; 289848b8605Smrg switch(index) { 290848b8605Smrg case 0: 291848b8605Smrg tmp = (((in[5] & 0x7) << 0x3) | 292848b8605Smrg ((in[6] >> 5) & 0x7)); /* RV */ 293848b8605Smrg return ((tmp << 2) | (tmp >> 4)); 294848b8605Smrg case 1: 295848b8605Smrg tmp = (((in[6] & 0x1f) << 2) | 296848b8605Smrg ((in[7] >> 6) & 0x3)); /* GV */ 297848b8605Smrg return ((tmp << 1) | (tmp >> 6)); 298848b8605Smrg case 2: 299848b8605Smrg tmp = in[7] & 0x3f; /* BV */ 300848b8605Smrg return ((tmp << 2) | (tmp >> 4)); 301848b8605Smrg default: 302848b8605Smrg /* invalid index */ 303848b8605Smrg return 0; 304848b8605Smrg } 305848b8605Smrg} 306848b8605Smrg 307848b8605Smrgstatic GLint 308848b8605Smrgetc2_get_pixel_index(const struct etc2_block *block, int x, int y) 309848b8605Smrg{ 310848b8605Smrg int bit = ((3 - y) + (3 - x) * 4) * 3; 311848b8605Smrg int idx = (block->pixel_indices[1] >> bit) & 0x7; 312848b8605Smrg return idx; 313848b8605Smrg} 314848b8605Smrg 315848b8605Smrgstatic uint8_t 316848b8605Smrgetc2_clamp(int color) 317848b8605Smrg{ 318848b8605Smrg /* CLAMP(color, 0, 255) */ 319848b8605Smrg return (uint8_t) CLAMP(color, 0, 255); 320848b8605Smrg} 321848b8605Smrg 322848b8605Smrgstatic GLushort 323848b8605Smrgetc2_clamp2(int color) 324848b8605Smrg{ 325848b8605Smrg /* CLAMP(color, 0, 2047) */ 326848b8605Smrg return (GLushort) CLAMP(color, 0, 2047); 327848b8605Smrg} 328848b8605Smrg 329848b8605Smrgstatic GLshort 330848b8605Smrgetc2_clamp3(int color) 331848b8605Smrg{ 332848b8605Smrg /* CLAMP(color, -1023, 1023) */ 333848b8605Smrg return (GLshort) CLAMP(color, -1023, 1023); 334848b8605Smrg} 335848b8605Smrg 336848b8605Smrgstatic void 337848b8605Smrgetc2_rgb8_parse_block(struct etc2_block *block, 338848b8605Smrg const uint8_t *src, 339848b8605Smrg GLboolean punchthrough_alpha) 340848b8605Smrg{ 341848b8605Smrg unsigned i; 342848b8605Smrg GLboolean diffbit = false; 343848b8605Smrg static const int lookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 }; 344848b8605Smrg 345848b8605Smrg const int R_plus_dR = (src[0] >> 3) + lookup[src[0] & 0x7]; 346848b8605Smrg const int G_plus_dG = (src[1] >> 3) + lookup[src[1] & 0x7]; 347848b8605Smrg const int B_plus_dB = (src[2] >> 3) + lookup[src[2] & 0x7]; 348848b8605Smrg 349848b8605Smrg /* Reset the mode flags */ 350848b8605Smrg block->is_ind_mode = false; 351848b8605Smrg block->is_diff_mode = false; 352848b8605Smrg block->is_t_mode = false; 353848b8605Smrg block->is_h_mode = false; 354848b8605Smrg block->is_planar_mode = false; 355848b8605Smrg 356848b8605Smrg if (punchthrough_alpha) 357848b8605Smrg block->opaque = src[3] & 0x2; 358848b8605Smrg else 359848b8605Smrg diffbit = src[3] & 0x2; 360848b8605Smrg 361848b8605Smrg if (!diffbit && !punchthrough_alpha) { 362848b8605Smrg /* individual mode */ 363848b8605Smrg block->is_ind_mode = true; 364848b8605Smrg 365848b8605Smrg for (i = 0; i < 3; i++) { 366848b8605Smrg /* Texture decode algorithm is same for individual mode in etc1 367848b8605Smrg * & etc2. 368848b8605Smrg */ 369848b8605Smrg block->base_colors[0][i] = etc1_base_color_ind_hi(src[i]); 370848b8605Smrg block->base_colors[1][i] = etc1_base_color_ind_lo(src[i]); 371848b8605Smrg } 372848b8605Smrg } 373848b8605Smrg else if (R_plus_dR < 0 || R_plus_dR > 31){ 374848b8605Smrg /* T mode */ 375848b8605Smrg block->is_t_mode = true; 376848b8605Smrg 377848b8605Smrg for(i = 0; i < 3; i++) { 378848b8605Smrg block->base_colors[0][i] = etc2_base_color1_t_mode(src, i); 379848b8605Smrg block->base_colors[1][i] = etc2_base_color2_t_mode(src, i); 380848b8605Smrg } 381848b8605Smrg /* pick distance */ 382848b8605Smrg block->distance = 383848b8605Smrg etc2_distance_table[(((src[3] >> 2) & 0x3) << 1) | 384848b8605Smrg (src[3] & 0x1)]; 385848b8605Smrg 386848b8605Smrg for (i = 0; i < 3; i++) { 387848b8605Smrg block->paint_colors[0][i] = etc2_clamp(block->base_colors[0][i]); 388848b8605Smrg block->paint_colors[1][i] = etc2_clamp(block->base_colors[1][i] + 389848b8605Smrg block->distance); 390848b8605Smrg block->paint_colors[2][i] = etc2_clamp(block->base_colors[1][i]); 391848b8605Smrg block->paint_colors[3][i] = etc2_clamp(block->base_colors[1][i] - 392848b8605Smrg block->distance); 393848b8605Smrg } 394848b8605Smrg } 395848b8605Smrg else if (G_plus_dG < 0 || G_plus_dG > 31){ 396848b8605Smrg int base_color_1_value, base_color_2_value; 397848b8605Smrg 398848b8605Smrg /* H mode */ 399848b8605Smrg block->is_h_mode = true; 400848b8605Smrg 401848b8605Smrg for(i = 0; i < 3; i++) { 402848b8605Smrg block->base_colors[0][i] = etc2_base_color1_h_mode(src, i); 403848b8605Smrg block->base_colors[1][i] = etc2_base_color2_h_mode(src, i); 404848b8605Smrg } 405848b8605Smrg 406848b8605Smrg base_color_1_value = (block->base_colors[0][0] << 16) + 407848b8605Smrg (block->base_colors[0][1] << 8) + 408848b8605Smrg block->base_colors[0][2]; 409848b8605Smrg base_color_2_value = (block->base_colors[1][0] << 16) + 410848b8605Smrg (block->base_colors[1][1] << 8) + 411848b8605Smrg block->base_colors[1][2]; 412848b8605Smrg /* pick distance */ 413848b8605Smrg block->distance = 414848b8605Smrg etc2_distance_table[(src[3] & 0x4) | 415848b8605Smrg ((src[3] & 0x1) << 1) | 416848b8605Smrg (base_color_1_value >= base_color_2_value)]; 417848b8605Smrg 418848b8605Smrg for (i = 0; i < 3; i++) { 419848b8605Smrg block->paint_colors[0][i] = etc2_clamp(block->base_colors[0][i] + 420848b8605Smrg block->distance); 421848b8605Smrg block->paint_colors[1][i] = etc2_clamp(block->base_colors[0][i] - 422848b8605Smrg block->distance); 423848b8605Smrg block->paint_colors[2][i] = etc2_clamp(block->base_colors[1][i] + 424848b8605Smrg block->distance); 425848b8605Smrg block->paint_colors[3][i] = etc2_clamp(block->base_colors[1][i] - 426848b8605Smrg block->distance); 427848b8605Smrg } 428848b8605Smrg } 429848b8605Smrg else if (B_plus_dB < 0 || B_plus_dB > 31) { 430848b8605Smrg /* Planar mode */ 431848b8605Smrg block->is_planar_mode = true; 432848b8605Smrg 433848b8605Smrg /* opaque bit must be set in planar mode */ 434848b8605Smrg block->opaque = true; 435848b8605Smrg 436848b8605Smrg for (i = 0; i < 3; i++) { 437848b8605Smrg block->base_colors[0][i] = etc2_base_color_o_planar(src, i); 438848b8605Smrg block->base_colors[1][i] = etc2_base_color_h_planar(src, i); 439848b8605Smrg block->base_colors[2][i] = etc2_base_color_v_planar(src, i); 440848b8605Smrg } 441848b8605Smrg } 442848b8605Smrg else if (diffbit || punchthrough_alpha) { 443848b8605Smrg /* differential mode */ 444848b8605Smrg block->is_diff_mode = true; 445848b8605Smrg 446848b8605Smrg for (i = 0; i < 3; i++) { 447848b8605Smrg /* Texture decode algorithm is same for differential mode in etc1 448848b8605Smrg * & etc2. 449848b8605Smrg */ 450848b8605Smrg block->base_colors[0][i] = etc1_base_color_diff_hi(src[i]); 451848b8605Smrg block->base_colors[1][i] = etc1_base_color_diff_lo(src[i]); 452848b8605Smrg } 453848b8605Smrg } 454848b8605Smrg 455848b8605Smrg if (block->is_ind_mode || block->is_diff_mode) { 456848b8605Smrg int table1_idx = (src[3] >> 5) & 0x7; 457848b8605Smrg int table2_idx = (src[3] >> 2) & 0x7; 458848b8605Smrg 459848b8605Smrg /* Use same modifier tables as for etc1 textures if opaque bit is set 460848b8605Smrg * or if non punchthrough texture format 461848b8605Smrg */ 462b8e80941Smrg block->modifier_tables[0] = (!punchthrough_alpha || block->opaque) ? 463848b8605Smrg etc1_modifier_tables[table1_idx] : 464848b8605Smrg etc2_modifier_tables_non_opaque[table1_idx]; 465b8e80941Smrg block->modifier_tables[1] = (!punchthrough_alpha || block->opaque) ? 466848b8605Smrg etc1_modifier_tables[table2_idx] : 467848b8605Smrg etc2_modifier_tables_non_opaque[table2_idx]; 468848b8605Smrg 469848b8605Smrg block->flipped = (src[3] & 0x1); 470848b8605Smrg } 471848b8605Smrg 472848b8605Smrg block->pixel_indices[0] = 473848b8605Smrg (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7]; 474848b8605Smrg} 475848b8605Smrg 476848b8605Smrgstatic void 477848b8605Smrgetc2_rgb8_fetch_texel(const struct etc2_block *block, 478848b8605Smrg int x, int y, uint8_t *dst, 479848b8605Smrg GLboolean punchthrough_alpha) 480848b8605Smrg{ 481848b8605Smrg const uint8_t *base_color; 482848b8605Smrg int modifier, bit, idx, blk; 483848b8605Smrg 484848b8605Smrg /* get pixel index */ 485848b8605Smrg bit = y + x * 4; 486848b8605Smrg idx = ((block->pixel_indices[0] >> (15 + bit)) & 0x2) | 487848b8605Smrg ((block->pixel_indices[0] >> (bit)) & 0x1); 488848b8605Smrg 489848b8605Smrg if (block->is_ind_mode || block->is_diff_mode) { 490848b8605Smrg /* check for punchthrough_alpha format */ 491848b8605Smrg if (punchthrough_alpha) { 492848b8605Smrg if (!block->opaque && idx == 2) { 493848b8605Smrg dst[0] = dst[1] = dst[2] = dst[3] = 0; 494848b8605Smrg return; 495848b8605Smrg } 496848b8605Smrg else 497848b8605Smrg dst[3] = 255; 498848b8605Smrg } 499848b8605Smrg 500848b8605Smrg /* Use pixel index and subblock to get the modifier */ 501848b8605Smrg blk = (block->flipped) ? (y >= 2) : (x >= 2); 502848b8605Smrg base_color = block->base_colors[blk]; 503848b8605Smrg modifier = block->modifier_tables[blk][idx]; 504848b8605Smrg 505848b8605Smrg dst[0] = etc2_clamp(base_color[0] + modifier); 506848b8605Smrg dst[1] = etc2_clamp(base_color[1] + modifier); 507848b8605Smrg dst[2] = etc2_clamp(base_color[2] + modifier); 508848b8605Smrg } 509848b8605Smrg else if (block->is_t_mode || block->is_h_mode) { 510848b8605Smrg /* check for punchthrough_alpha format */ 511848b8605Smrg if (punchthrough_alpha) { 512848b8605Smrg if (!block->opaque && idx == 2) { 513848b8605Smrg dst[0] = dst[1] = dst[2] = dst[3] = 0; 514848b8605Smrg return; 515848b8605Smrg } 516848b8605Smrg else 517848b8605Smrg dst[3] = 255; 518848b8605Smrg } 519848b8605Smrg 520848b8605Smrg /* Use pixel index to pick one of the paint colors */ 521848b8605Smrg dst[0] = block->paint_colors[idx][0]; 522848b8605Smrg dst[1] = block->paint_colors[idx][1]; 523848b8605Smrg dst[2] = block->paint_colors[idx][2]; 524848b8605Smrg } 525848b8605Smrg else if (block->is_planar_mode) { 526848b8605Smrg /* {R(x, y) = clamp255((x × (RH − RO) + y × (RV − RO) + 4 × RO + 2) >> 2) 527848b8605Smrg * {G(x, y) = clamp255((x × (GH − GO) + y × (GV − GO) + 4 × GO + 2) >> 2) 528848b8605Smrg * {B(x, y) = clamp255((x × (BH − BO) + y × (BV − BO) + 4 × BO + 2) >> 2) 529848b8605Smrg */ 530848b8605Smrg int red, green, blue; 531848b8605Smrg red = (x * (block->base_colors[1][0] - block->base_colors[0][0]) + 532848b8605Smrg y * (block->base_colors[2][0] - block->base_colors[0][0]) + 533848b8605Smrg 4 * block->base_colors[0][0] + 2) >> 2; 534848b8605Smrg 535848b8605Smrg green = (x * (block->base_colors[1][1] - block->base_colors[0][1]) + 536848b8605Smrg y * (block->base_colors[2][1] - block->base_colors[0][1]) + 537848b8605Smrg 4 * block->base_colors[0][1] + 2) >> 2; 538848b8605Smrg 539848b8605Smrg blue = (x * (block->base_colors[1][2] - block->base_colors[0][2]) + 540848b8605Smrg y * (block->base_colors[2][2] - block->base_colors[0][2]) + 541848b8605Smrg 4 * block->base_colors[0][2] + 2) >> 2; 542848b8605Smrg 543848b8605Smrg dst[0] = etc2_clamp(red); 544848b8605Smrg dst[1] = etc2_clamp(green); 545848b8605Smrg dst[2] = etc2_clamp(blue); 546848b8605Smrg 547848b8605Smrg /* check for punchthrough_alpha format */ 548848b8605Smrg if (punchthrough_alpha) 549848b8605Smrg dst[3] = 255; 550848b8605Smrg } 551848b8605Smrg} 552848b8605Smrg 553848b8605Smrgstatic void 554848b8605Smrgetc2_alpha8_fetch_texel(const struct etc2_block *block, 555848b8605Smrg int x, int y, uint8_t *dst) 556848b8605Smrg{ 557848b8605Smrg int modifier, alpha, idx; 558848b8605Smrg /* get pixel index */ 559848b8605Smrg idx = etc2_get_pixel_index(block, x, y); 560848b8605Smrg modifier = etc2_modifier_tables[block->table_index][idx]; 561848b8605Smrg alpha = block->base_codeword + modifier * block->multiplier; 562848b8605Smrg dst[3] = etc2_clamp(alpha); 563848b8605Smrg} 564848b8605Smrg 565848b8605Smrgstatic void 566848b8605Smrgetc2_r11_fetch_texel(const struct etc2_block *block, 567848b8605Smrg int x, int y, uint8_t *dst) 568848b8605Smrg{ 569848b8605Smrg GLint modifier, idx; 570848b8605Smrg GLshort color; 571848b8605Smrg /* Get pixel index */ 572848b8605Smrg idx = etc2_get_pixel_index(block, x, y); 573848b8605Smrg modifier = etc2_modifier_tables[block->table_index][idx]; 574848b8605Smrg 575848b8605Smrg if (block->multiplier != 0) 576848b8605Smrg /* clamp2(base codeword × 8 + 4 + modifier × multiplier × 8) */ 577848b8605Smrg color = etc2_clamp2(((block->base_codeword << 3) | 0x4) + 578848b8605Smrg ((modifier * block->multiplier) << 3)); 579848b8605Smrg else 580848b8605Smrg color = etc2_clamp2(((block->base_codeword << 3) | 0x4) + modifier); 581848b8605Smrg 582848b8605Smrg /* Extend 11 bits color value to 16 bits. OpenGL ES 3.0 specification 583848b8605Smrg * allows extending the color value to any number of bits. But, an 584848b8605Smrg * implementation is not allowed to truncate the 11-bit value to less than 585848b8605Smrg * 11 bits." 586848b8605Smrg */ 587848b8605Smrg color = (color << 5) | (color >> 6); 588848b8605Smrg ((GLushort *)dst)[0] = color; 589848b8605Smrg} 590848b8605Smrg 591848b8605Smrgstatic void 592848b8605Smrgetc2_signed_r11_fetch_texel(const struct etc2_block *block, 593848b8605Smrg int x, int y, uint8_t *dst) 594848b8605Smrg{ 595848b8605Smrg GLint modifier, idx; 596848b8605Smrg GLshort color; 597848b8605Smrg GLbyte base_codeword = (GLbyte) block->base_codeword; 598848b8605Smrg 599848b8605Smrg if (base_codeword == -128) 600848b8605Smrg base_codeword = -127; 601848b8605Smrg 602848b8605Smrg /* Get pixel index */ 603848b8605Smrg idx = etc2_get_pixel_index(block, x, y); 604848b8605Smrg modifier = etc2_modifier_tables[block->table_index][idx]; 605848b8605Smrg 606848b8605Smrg if (block->multiplier != 0) 607848b8605Smrg /* clamp3(base codeword × 8 + modifier × multiplier × 8) */ 608848b8605Smrg color = etc2_clamp3((base_codeword << 3) + 609848b8605Smrg ((modifier * block->multiplier) << 3)); 610848b8605Smrg else 611848b8605Smrg color = etc2_clamp3((base_codeword << 3) + modifier); 612848b8605Smrg 613848b8605Smrg /* Extend 11 bits color value to 16 bits. OpenGL ES 3.0 specification 614848b8605Smrg * allows extending the color value to any number of bits. But, an 615848b8605Smrg * implementation is not allowed to truncate the 11-bit value to less than 616848b8605Smrg * 11 bits. A negative 11-bit value must first be made positive before bit 617848b8605Smrg * replication, and then made negative again 618848b8605Smrg */ 619848b8605Smrg if (color >= 0) 620848b8605Smrg color = (color << 5) | (color >> 5); 621848b8605Smrg else { 622848b8605Smrg color = -color; 623848b8605Smrg color = (color << 5) | (color >> 5); 624848b8605Smrg color = -color; 625848b8605Smrg } 626848b8605Smrg ((GLshort *)dst)[0] = color; 627848b8605Smrg} 628848b8605Smrg 629848b8605Smrgstatic void 630848b8605Smrgetc2_alpha8_parse_block(struct etc2_block *block, const uint8_t *src) 631848b8605Smrg{ 632848b8605Smrg block->base_codeword = src[0]; 633848b8605Smrg block->multiplier = (src[1] >> 4) & 0xf; 634848b8605Smrg block->table_index = src[1] & 0xf; 635848b8605Smrg block->pixel_indices[1] = (((uint64_t)src[2] << 40) | 636848b8605Smrg ((uint64_t)src[3] << 32) | 637848b8605Smrg ((uint64_t)src[4] << 24) | 638848b8605Smrg ((uint64_t)src[5] << 16) | 639848b8605Smrg ((uint64_t)src[6] << 8) | 640848b8605Smrg ((uint64_t)src[7])); 641848b8605Smrg} 642848b8605Smrg 643848b8605Smrgstatic void 644848b8605Smrgetc2_r11_parse_block(struct etc2_block *block, const uint8_t *src) 645848b8605Smrg{ 646848b8605Smrg /* Parsing logic remains same as for etc2_alpha8_parse_block */ 647848b8605Smrg etc2_alpha8_parse_block(block, src); 648848b8605Smrg} 649848b8605Smrg 650848b8605Smrgstatic void 651848b8605Smrgetc2_rgba8_parse_block(struct etc2_block *block, const uint8_t *src) 652848b8605Smrg{ 653848b8605Smrg /* RGB component is parsed the same way as for MESA_FORMAT_ETC2_RGB8 */ 654848b8605Smrg etc2_rgb8_parse_block(block, src + 8, 655848b8605Smrg false /* punchthrough_alpha */); 656848b8605Smrg /* Parse Alpha component */ 657848b8605Smrg etc2_alpha8_parse_block(block, src); 658848b8605Smrg} 659848b8605Smrg 660848b8605Smrgstatic void 661848b8605Smrgetc2_rgba8_fetch_texel(const struct etc2_block *block, 662848b8605Smrg int x, int y, uint8_t *dst) 663848b8605Smrg{ 664848b8605Smrg etc2_rgb8_fetch_texel(block, x, y, dst, 665848b8605Smrg false /* punchthrough_alpha */); 666848b8605Smrg etc2_alpha8_fetch_texel(block, x, y, dst); 667848b8605Smrg} 668848b8605Smrg 669848b8605Smrgstatic void 670848b8605Smrgetc2_unpack_rgb8(uint8_t *dst_row, 671848b8605Smrg unsigned dst_stride, 672848b8605Smrg const uint8_t *src_row, 673848b8605Smrg unsigned src_stride, 674848b8605Smrg unsigned width, 675848b8605Smrg unsigned height) 676848b8605Smrg{ 677848b8605Smrg const unsigned bw = 4, bh = 4, bs = 8, comps = 4; 678848b8605Smrg struct etc2_block block; 679848b8605Smrg unsigned x, y, i, j; 680848b8605Smrg 681848b8605Smrg for (y = 0; y < height; y += bh) { 682848b8605Smrg const uint8_t *src = src_row; 683848b8605Smrg /* 684848b8605Smrg * Destination texture may not be a multiple of four texels in 685848b8605Smrg * height. Compute a safe height to avoid writing outside the texture. 686848b8605Smrg */ 687848b8605Smrg const unsigned h = MIN2(bh, height - y); 688848b8605Smrg 689848b8605Smrg for (x = 0; x < width; x+= bw) { 690848b8605Smrg /* 691848b8605Smrg * Destination texture may not be a multiple of four texels in 692848b8605Smrg * width. Compute a safe width to avoid writing outside the texture. 693848b8605Smrg */ 694848b8605Smrg const unsigned w = MIN2(bw, width - x); 695848b8605Smrg 696848b8605Smrg etc2_rgb8_parse_block(&block, src, 697848b8605Smrg false /* punchthrough_alpha */); 698848b8605Smrg 699848b8605Smrg for (j = 0; j < h; j++) { 700848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; 701848b8605Smrg for (i = 0; i < w; i++) { 702848b8605Smrg etc2_rgb8_fetch_texel(&block, i, j, dst, 703848b8605Smrg false /* punchthrough_alpha */); 704848b8605Smrg dst[3] = 255; 705848b8605Smrg dst += comps; 706848b8605Smrg } 707848b8605Smrg } 708848b8605Smrg 709848b8605Smrg src += bs; 710848b8605Smrg } 711848b8605Smrg 712848b8605Smrg src_row += src_stride; 713848b8605Smrg } 714848b8605Smrg} 715848b8605Smrg 716848b8605Smrgstatic void 717848b8605Smrgetc2_unpack_srgb8(uint8_t *dst_row, 718848b8605Smrg unsigned dst_stride, 719848b8605Smrg const uint8_t *src_row, 720848b8605Smrg unsigned src_stride, 721848b8605Smrg unsigned width, 722b8e80941Smrg unsigned height, 723b8e80941Smrg bool bgra) 724848b8605Smrg{ 725848b8605Smrg const unsigned bw = 4, bh = 4, bs = 8, comps = 4; 726848b8605Smrg struct etc2_block block; 727848b8605Smrg unsigned x, y, i, j; 728848b8605Smrg uint8_t tmp; 729848b8605Smrg 730848b8605Smrg for (y = 0; y < height; y += bh) { 731848b8605Smrg const uint8_t *src = src_row; 732848b8605Smrg const unsigned h = MIN2(bh, height - y); 733848b8605Smrg 734848b8605Smrg for (x = 0; x < width; x+= bw) { 735848b8605Smrg const unsigned w = MIN2(bw, width - x); 736848b8605Smrg etc2_rgb8_parse_block(&block, src, 737848b8605Smrg false /* punchthrough_alpha */); 738848b8605Smrg 739848b8605Smrg 740848b8605Smrg for (j = 0; j < h; j++) { 741848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; 742848b8605Smrg for (i = 0; i < w; i++) { 743848b8605Smrg etc2_rgb8_fetch_texel(&block, i, j, dst, 744848b8605Smrg false /* punchthrough_alpha */); 745b8e80941Smrg 746b8e80941Smrg if (bgra) { 747b8e80941Smrg /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */ 748b8e80941Smrg tmp = dst[0]; 749b8e80941Smrg dst[0] = dst[2]; 750b8e80941Smrg dst[2] = tmp; 751b8e80941Smrg dst[3] = 255; 752b8e80941Smrg } 753848b8605Smrg 754848b8605Smrg dst += comps; 755848b8605Smrg } 756848b8605Smrg } 757848b8605Smrg src += bs; 758848b8605Smrg } 759848b8605Smrg 760848b8605Smrg src_row += src_stride; 761848b8605Smrg } 762848b8605Smrg} 763848b8605Smrg 764848b8605Smrgstatic void 765848b8605Smrgetc2_unpack_rgba8(uint8_t *dst_row, 766848b8605Smrg unsigned dst_stride, 767848b8605Smrg const uint8_t *src_row, 768848b8605Smrg unsigned src_stride, 769848b8605Smrg unsigned width, 770848b8605Smrg unsigned height) 771848b8605Smrg{ 772848b8605Smrg /* If internalformat is COMPRESSED_RGBA8_ETC2_EAC, each 4 × 4 block of 773848b8605Smrg * RGBA8888 information is compressed to 128 bits. To decode a block, the 774848b8605Smrg * two 64-bit integers int64bitAlpha and int64bitColor are calculated. 775848b8605Smrg */ 776848b8605Smrg const unsigned bw = 4, bh = 4, bs = 16, comps = 4; 777848b8605Smrg struct etc2_block block; 778848b8605Smrg unsigned x, y, i, j; 779848b8605Smrg 780848b8605Smrg for (y = 0; y < height; y += bh) { 781848b8605Smrg const uint8_t *src = src_row; 782848b8605Smrg const unsigned h = MIN2(bh, height - y); 783848b8605Smrg 784848b8605Smrg for (x = 0; x < width; x+= bw) { 785848b8605Smrg const unsigned w = MIN2(bw, width - x); 786848b8605Smrg etc2_rgba8_parse_block(&block, src); 787848b8605Smrg 788848b8605Smrg for (j = 0; j < h; j++) { 789848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; 790848b8605Smrg for (i = 0; i < w; i++) { 791848b8605Smrg etc2_rgba8_fetch_texel(&block, i, j, dst); 792848b8605Smrg dst += comps; 793848b8605Smrg } 794848b8605Smrg } 795848b8605Smrg src += bs; 796848b8605Smrg } 797848b8605Smrg 798848b8605Smrg src_row += src_stride; 799848b8605Smrg } 800848b8605Smrg} 801848b8605Smrg 802848b8605Smrgstatic void 803848b8605Smrgetc2_unpack_srgb8_alpha8(uint8_t *dst_row, 804848b8605Smrg unsigned dst_stride, 805848b8605Smrg const uint8_t *src_row, 806848b8605Smrg unsigned src_stride, 807848b8605Smrg unsigned width, 808b8e80941Smrg unsigned height, 809b8e80941Smrg bool bgra) 810848b8605Smrg{ 811848b8605Smrg /* If internalformat is COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, each 4 × 4 block 812848b8605Smrg * of RGBA8888 information is compressed to 128 bits. To decode a block, the 813848b8605Smrg * two 64-bit integers int64bitAlpha and int64bitColor are calculated. 814848b8605Smrg */ 815848b8605Smrg const unsigned bw = 4, bh = 4, bs = 16, comps = 4; 816848b8605Smrg struct etc2_block block; 817848b8605Smrg unsigned x, y, i, j; 818848b8605Smrg uint8_t tmp; 819848b8605Smrg 820848b8605Smrg for (y = 0; y < height; y += bh) { 821848b8605Smrg const unsigned h = MIN2(bh, height - y); 822848b8605Smrg const uint8_t *src = src_row; 823848b8605Smrg 824848b8605Smrg for (x = 0; x < width; x+= bw) { 825848b8605Smrg const unsigned w = MIN2(bw, width - x); 826848b8605Smrg etc2_rgba8_parse_block(&block, src); 827848b8605Smrg 828848b8605Smrg for (j = 0; j < h; j++) { 829848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; 830848b8605Smrg for (i = 0; i < w; i++) { 831848b8605Smrg etc2_rgba8_fetch_texel(&block, i, j, dst); 832848b8605Smrg 833b8e80941Smrg if (bgra) { 834b8e80941Smrg /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */ 835b8e80941Smrg tmp = dst[0]; 836b8e80941Smrg dst[0] = dst[2]; 837b8e80941Smrg dst[2] = tmp; 838b8e80941Smrg dst[3] = dst[3]; 839b8e80941Smrg } 840848b8605Smrg 841848b8605Smrg dst += comps; 842848b8605Smrg } 843848b8605Smrg } 844848b8605Smrg src += bs; 845848b8605Smrg } 846848b8605Smrg 847848b8605Smrg src_row += src_stride; 848848b8605Smrg } 849848b8605Smrg} 850848b8605Smrg 851848b8605Smrgstatic void 852848b8605Smrgetc2_unpack_r11(uint8_t *dst_row, 853848b8605Smrg unsigned dst_stride, 854848b8605Smrg const uint8_t *src_row, 855848b8605Smrg unsigned src_stride, 856848b8605Smrg unsigned width, 857848b8605Smrg unsigned height) 858848b8605Smrg{ 859848b8605Smrg /* If internalformat is COMPRESSED_R11_EAC, each 4 × 4 block of 860848b8605Smrg color information is compressed to 64 bits. 861848b8605Smrg */ 862848b8605Smrg const unsigned bw = 4, bh = 4, bs = 8, comps = 1, comp_size = 2; 863848b8605Smrg struct etc2_block block; 864848b8605Smrg unsigned x, y, i, j; 865848b8605Smrg 866848b8605Smrg for (y = 0; y < height; y += bh) { 867848b8605Smrg const unsigned h = MIN2(bh, height - y); 868848b8605Smrg const uint8_t *src = src_row; 869848b8605Smrg 870848b8605Smrg for (x = 0; x < width; x+= bw) { 871848b8605Smrg const unsigned w = MIN2(bw, width - x); 872848b8605Smrg etc2_r11_parse_block(&block, src); 873848b8605Smrg 874848b8605Smrg for (j = 0; j < h; j++) { 875848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size; 876848b8605Smrg for (i = 0; i < w; i++) { 877848b8605Smrg etc2_r11_fetch_texel(&block, i, j, dst); 878848b8605Smrg dst += comps * comp_size; 879848b8605Smrg } 880848b8605Smrg } 881848b8605Smrg src += bs; 882848b8605Smrg } 883848b8605Smrg 884848b8605Smrg src_row += src_stride; 885848b8605Smrg } 886848b8605Smrg} 887848b8605Smrg 888848b8605Smrgstatic void 889848b8605Smrgetc2_unpack_rg11(uint8_t *dst_row, 890848b8605Smrg unsigned dst_stride, 891848b8605Smrg const uint8_t *src_row, 892848b8605Smrg unsigned src_stride, 893848b8605Smrg unsigned width, 894848b8605Smrg unsigned height) 895848b8605Smrg{ 896848b8605Smrg /* If internalformat is COMPRESSED_RG11_EAC, each 4 × 4 block of 897848b8605Smrg RG color information is compressed to 128 bits. 898848b8605Smrg */ 899848b8605Smrg const unsigned bw = 4, bh = 4, bs = 16, comps = 2, comp_size = 2; 900848b8605Smrg struct etc2_block block; 901848b8605Smrg unsigned x, y, i, j; 902848b8605Smrg 903848b8605Smrg for (y = 0; y < height; y += bh) { 904848b8605Smrg const unsigned h = MIN2(bh, height - y); 905848b8605Smrg const uint8_t *src = src_row; 906848b8605Smrg 907848b8605Smrg for (x = 0; x < width; x+= bw) { 908848b8605Smrg const unsigned w = MIN2(bw, width - x); 909848b8605Smrg /* red component */ 910848b8605Smrg etc2_r11_parse_block(&block, src); 911848b8605Smrg 912848b8605Smrg for (j = 0; j < h; j++) { 913848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + 914848b8605Smrg x * comps * comp_size; 915848b8605Smrg for (i = 0; i < w; i++) { 916848b8605Smrg etc2_r11_fetch_texel(&block, i, j, dst); 917848b8605Smrg dst += comps * comp_size; 918848b8605Smrg } 919848b8605Smrg } 920848b8605Smrg /* green component */ 921848b8605Smrg etc2_r11_parse_block(&block, src + 8); 922848b8605Smrg 923848b8605Smrg for (j = 0; j < h; j++) { 924848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + 925848b8605Smrg x * comps * comp_size; 926848b8605Smrg for (i = 0; i < w; i++) { 927848b8605Smrg etc2_r11_fetch_texel(&block, i, j, dst + comp_size); 928848b8605Smrg dst += comps * comp_size; 929848b8605Smrg } 930848b8605Smrg } 931848b8605Smrg src += bs; 932848b8605Smrg } 933848b8605Smrg 934848b8605Smrg src_row += src_stride; 935848b8605Smrg } 936848b8605Smrg} 937848b8605Smrg 938848b8605Smrgstatic void 939848b8605Smrgetc2_unpack_signed_r11(uint8_t *dst_row, 940848b8605Smrg unsigned dst_stride, 941848b8605Smrg const uint8_t *src_row, 942848b8605Smrg unsigned src_stride, 943848b8605Smrg unsigned width, 944848b8605Smrg unsigned height) 945848b8605Smrg{ 946848b8605Smrg /* If internalformat is COMPRESSED_SIGNED_R11_EAC, each 4 × 4 block of 947848b8605Smrg red color information is compressed to 64 bits. 948848b8605Smrg */ 949848b8605Smrg const unsigned bw = 4, bh = 4, bs = 8, comps = 1, comp_size = 2; 950848b8605Smrg struct etc2_block block; 951848b8605Smrg unsigned x, y, i, j; 952848b8605Smrg 953848b8605Smrg for (y = 0; y < height; y += bh) { 954848b8605Smrg const unsigned h = MIN2(bh, height - y); 955848b8605Smrg const uint8_t *src = src_row; 956848b8605Smrg 957848b8605Smrg for (x = 0; x < width; x+= bw) { 958848b8605Smrg const unsigned w = MIN2(bw, width - x); 959848b8605Smrg etc2_r11_parse_block(&block, src); 960848b8605Smrg 961848b8605Smrg for (j = 0; j < h; j++) { 962848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + 963848b8605Smrg x * comps * comp_size; 964848b8605Smrg for (i = 0; i < w; i++) { 965848b8605Smrg etc2_signed_r11_fetch_texel(&block, i, j, dst); 966848b8605Smrg dst += comps * comp_size; 967848b8605Smrg } 968848b8605Smrg } 969848b8605Smrg src += bs; 970848b8605Smrg } 971848b8605Smrg 972848b8605Smrg src_row += src_stride; 973848b8605Smrg } 974848b8605Smrg} 975848b8605Smrg 976848b8605Smrgstatic void 977848b8605Smrgetc2_unpack_signed_rg11(uint8_t *dst_row, 978848b8605Smrg unsigned dst_stride, 979848b8605Smrg const uint8_t *src_row, 980848b8605Smrg unsigned src_stride, 981848b8605Smrg unsigned width, 982848b8605Smrg unsigned height) 983848b8605Smrg{ 984848b8605Smrg /* If internalformat is COMPRESSED_SIGNED_RG11_EAC, each 4 × 4 block of 985848b8605Smrg RG color information is compressed to 128 bits. 986848b8605Smrg */ 987848b8605Smrg const unsigned bw = 4, bh = 4, bs = 16, comps = 2, comp_size = 2; 988848b8605Smrg struct etc2_block block; 989848b8605Smrg unsigned x, y, i, j; 990848b8605Smrg 991848b8605Smrg for (y = 0; y < height; y += bh) { 992848b8605Smrg const unsigned h = MIN2(bh, height - y); 993848b8605Smrg const uint8_t *src = src_row; 994848b8605Smrg 995848b8605Smrg for (x = 0; x < width; x+= bw) { 996848b8605Smrg const unsigned w = MIN2(bw, width - x); 997848b8605Smrg /* red component */ 998848b8605Smrg etc2_r11_parse_block(&block, src); 999848b8605Smrg 1000848b8605Smrg for (j = 0; j < h; j++) { 1001848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + 1002848b8605Smrg x * comps * comp_size; 1003848b8605Smrg for (i = 0; i < w; i++) { 1004848b8605Smrg etc2_signed_r11_fetch_texel(&block, i, j, dst); 1005848b8605Smrg dst += comps * comp_size; 1006848b8605Smrg } 1007848b8605Smrg } 1008848b8605Smrg /* green component */ 1009848b8605Smrg etc2_r11_parse_block(&block, src + 8); 1010848b8605Smrg 1011848b8605Smrg for (j = 0; j < h; j++) { 1012848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + 1013848b8605Smrg x * comps * comp_size; 1014848b8605Smrg for (i = 0; i < w; i++) { 1015848b8605Smrg etc2_signed_r11_fetch_texel(&block, i, j, dst + comp_size); 1016848b8605Smrg dst += comps * comp_size; 1017848b8605Smrg } 1018848b8605Smrg } 1019848b8605Smrg src += bs; 1020848b8605Smrg } 1021848b8605Smrg 1022848b8605Smrg src_row += src_stride; 1023848b8605Smrg } 1024848b8605Smrg} 1025848b8605Smrg 1026848b8605Smrgstatic void 1027848b8605Smrgetc2_unpack_rgb8_punchthrough_alpha1(uint8_t *dst_row, 1028848b8605Smrg unsigned dst_stride, 1029848b8605Smrg const uint8_t *src_row, 1030848b8605Smrg unsigned src_stride, 1031848b8605Smrg unsigned width, 1032848b8605Smrg unsigned height) 1033848b8605Smrg{ 1034848b8605Smrg const unsigned bw = 4, bh = 4, bs = 8, comps = 4; 1035848b8605Smrg struct etc2_block block; 1036848b8605Smrg unsigned x, y, i, j; 1037848b8605Smrg 1038848b8605Smrg for (y = 0; y < height; y += bh) { 1039848b8605Smrg const unsigned h = MIN2(bh, height - y); 1040848b8605Smrg const uint8_t *src = src_row; 1041848b8605Smrg 1042848b8605Smrg for (x = 0; x < width; x+= bw) { 1043848b8605Smrg const unsigned w = MIN2(bw, width - x); 1044848b8605Smrg etc2_rgb8_parse_block(&block, src, 1045848b8605Smrg true /* punchthrough_alpha */); 1046848b8605Smrg for (j = 0; j < h; j++) { 1047848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; 1048848b8605Smrg for (i = 0; i < w; i++) { 1049848b8605Smrg etc2_rgb8_fetch_texel(&block, i, j, dst, 1050848b8605Smrg true /* punchthrough_alpha */); 1051848b8605Smrg dst += comps; 1052848b8605Smrg } 1053848b8605Smrg } 1054848b8605Smrg 1055848b8605Smrg src += bs; 1056848b8605Smrg } 1057848b8605Smrg 1058848b8605Smrg src_row += src_stride; 1059848b8605Smrg } 1060848b8605Smrg} 1061848b8605Smrg 1062848b8605Smrgstatic void 1063848b8605Smrgetc2_unpack_srgb8_punchthrough_alpha1(uint8_t *dst_row, 1064848b8605Smrg unsigned dst_stride, 1065848b8605Smrg const uint8_t *src_row, 1066848b8605Smrg unsigned src_stride, 1067848b8605Smrg unsigned width, 1068b8e80941Smrg unsigned height, 1069b8e80941Smrg bool bgra) 1070848b8605Smrg{ 1071848b8605Smrg const unsigned bw = 4, bh = 4, bs = 8, comps = 4; 1072848b8605Smrg struct etc2_block block; 1073848b8605Smrg unsigned x, y, i, j; 1074848b8605Smrg uint8_t tmp; 1075848b8605Smrg 1076848b8605Smrg for (y = 0; y < height; y += bh) { 1077848b8605Smrg const unsigned h = MIN2(bh, height - y); 1078848b8605Smrg const uint8_t *src = src_row; 1079848b8605Smrg 1080848b8605Smrg for (x = 0; x < width; x+= bw) { 1081848b8605Smrg const unsigned w = MIN2(bw, width - x); 1082848b8605Smrg etc2_rgb8_parse_block(&block, src, 1083848b8605Smrg true /* punchthrough_alpha */); 1084848b8605Smrg for (j = 0; j < h; j++) { 1085848b8605Smrg uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; 1086848b8605Smrg for (i = 0; i < w; i++) { 1087848b8605Smrg etc2_rgb8_fetch_texel(&block, i, j, dst, 1088848b8605Smrg true /* punchthrough_alpha */); 1089b8e80941Smrg 1090b8e80941Smrg if (bgra) { 1091b8e80941Smrg /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */ 1092b8e80941Smrg tmp = dst[0]; 1093b8e80941Smrg dst[0] = dst[2]; 1094b8e80941Smrg dst[2] = tmp; 1095b8e80941Smrg dst[3] = dst[3]; 1096b8e80941Smrg } 1097848b8605Smrg 1098848b8605Smrg dst += comps; 1099848b8605Smrg } 1100848b8605Smrg } 1101848b8605Smrg 1102848b8605Smrg src += bs; 1103848b8605Smrg } 1104848b8605Smrg 1105848b8605Smrg src_row += src_stride; 1106848b8605Smrg } 1107848b8605Smrg} 1108848b8605Smrg 1109848b8605Smrg/* ETC2 texture formats are valid in glCompressedTexImage2D and 1110848b8605Smrg * glCompressedTexSubImage2D functions */ 1111848b8605SmrgGLboolean 1112b8e80941Smrg_mesa_texstore_etc2_rgb8(UNUSED_TEXSTORE_PARAMS) 1113848b8605Smrg{ 1114b8e80941Smrg assert(0); 1115848b8605Smrg 1116848b8605Smrg return GL_FALSE; 1117848b8605Smrg} 1118848b8605Smrg 1119848b8605SmrgGLboolean 1120b8e80941Smrg_mesa_texstore_etc2_srgb8(UNUSED_TEXSTORE_PARAMS) 1121848b8605Smrg{ 1122b8e80941Smrg assert(0); 1123848b8605Smrg 1124848b8605Smrg return GL_FALSE; 1125848b8605Smrg} 1126848b8605Smrg 1127848b8605SmrgGLboolean 1128b8e80941Smrg_mesa_texstore_etc2_rgba8_eac(UNUSED_TEXSTORE_PARAMS) 1129848b8605Smrg{ 1130b8e80941Smrg assert(0); 1131848b8605Smrg 1132848b8605Smrg return GL_FALSE; 1133848b8605Smrg} 1134848b8605Smrg 1135848b8605SmrgGLboolean 1136b8e80941Smrg_mesa_texstore_etc2_srgb8_alpha8_eac(UNUSED_TEXSTORE_PARAMS) 1137848b8605Smrg{ 1138b8e80941Smrg assert(0); 1139848b8605Smrg 1140848b8605Smrg return GL_FALSE; 1141848b8605Smrg} 1142848b8605Smrg 1143848b8605SmrgGLboolean 1144b8e80941Smrg_mesa_texstore_etc2_r11_eac(UNUSED_TEXSTORE_PARAMS) 1145848b8605Smrg{ 1146b8e80941Smrg assert(0); 1147848b8605Smrg 1148848b8605Smrg return GL_FALSE; 1149848b8605Smrg} 1150848b8605Smrg 1151848b8605SmrgGLboolean 1152b8e80941Smrg_mesa_texstore_etc2_signed_r11_eac(UNUSED_TEXSTORE_PARAMS) 1153848b8605Smrg{ 1154b8e80941Smrg assert(0); 1155848b8605Smrg 1156848b8605Smrg return GL_FALSE; 1157848b8605Smrg} 1158848b8605Smrg 1159848b8605SmrgGLboolean 1160b8e80941Smrg_mesa_texstore_etc2_rg11_eac(UNUSED_TEXSTORE_PARAMS) 1161848b8605Smrg{ 1162b8e80941Smrg assert(0); 1163848b8605Smrg 1164848b8605Smrg return GL_FALSE; 1165848b8605Smrg} 1166848b8605Smrg 1167848b8605SmrgGLboolean 1168b8e80941Smrg_mesa_texstore_etc2_signed_rg11_eac(UNUSED_TEXSTORE_PARAMS) 1169848b8605Smrg{ 1170b8e80941Smrg assert(0); 1171848b8605Smrg 1172848b8605Smrg return GL_FALSE; 1173848b8605Smrg} 1174848b8605Smrg 1175848b8605SmrgGLboolean 1176b8e80941Smrg_mesa_texstore_etc2_rgb8_punchthrough_alpha1(UNUSED_TEXSTORE_PARAMS) 1177848b8605Smrg{ 1178b8e80941Smrg assert(0); 1179848b8605Smrg 1180848b8605Smrg return GL_FALSE; 1181848b8605Smrg} 1182848b8605Smrg 1183848b8605SmrgGLboolean 1184b8e80941Smrg_mesa_texstore_etc2_srgb8_punchthrough_alpha1(UNUSED_TEXSTORE_PARAMS) 1185848b8605Smrg{ 1186b8e80941Smrg assert(0); 1187848b8605Smrg 1188848b8605Smrg return GL_FALSE; 1189848b8605Smrg} 1190848b8605Smrg 1191848b8605Smrg 1192848b8605Smrg/** 1193848b8605Smrg * Decode texture data in any one of following formats: 1194848b8605Smrg * `MESA_FORMAT_ETC2_RGB8` 1195848b8605Smrg * `MESA_FORMAT_ETC2_SRGB8` 1196848b8605Smrg * `MESA_FORMAT_ETC2_RGBA8_EAC` 1197848b8605Smrg * `MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC` 1198848b8605Smrg * `MESA_FORMAT_ETC2_R11_EAC` 1199848b8605Smrg * `MESA_FORMAT_ETC2_RG11_EAC` 1200848b8605Smrg * `MESA_FORMAT_ETC2_SIGNED_R11_EAC` 1201848b8605Smrg * `MESA_FORMAT_ETC2_SIGNED_RG11_EAC` 1202848b8605Smrg * `MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1` 1203848b8605Smrg * `MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1` 1204848b8605Smrg * 1205848b8605Smrg * The size of the source data must be a multiple of the ETC2 block size 1206848b8605Smrg * even if the texture image's dimensions are not aligned to 4. 1207848b8605Smrg * 1208848b8605Smrg * \param src_width in pixels 1209848b8605Smrg * \param src_height in pixels 1210848b8605Smrg * \param dst_stride in bytes 1211848b8605Smrg */ 1212848b8605Smrg 1213848b8605Smrgvoid 1214848b8605Smrg_mesa_unpack_etc2_format(uint8_t *dst_row, 1215848b8605Smrg unsigned dst_stride, 1216848b8605Smrg const uint8_t *src_row, 1217848b8605Smrg unsigned src_stride, 1218848b8605Smrg unsigned src_width, 1219848b8605Smrg unsigned src_height, 1220b8e80941Smrg mesa_format format, 1221b8e80941Smrg bool bgra) 1222848b8605Smrg{ 1223848b8605Smrg if (format == MESA_FORMAT_ETC2_RGB8) 1224848b8605Smrg etc2_unpack_rgb8(dst_row, dst_stride, 1225848b8605Smrg src_row, src_stride, 1226848b8605Smrg src_width, src_height); 1227848b8605Smrg else if (format == MESA_FORMAT_ETC2_SRGB8) 1228848b8605Smrg etc2_unpack_srgb8(dst_row, dst_stride, 1229848b8605Smrg src_row, src_stride, 1230b8e80941Smrg src_width, src_height, bgra); 1231848b8605Smrg else if (format == MESA_FORMAT_ETC2_RGBA8_EAC) 1232848b8605Smrg etc2_unpack_rgba8(dst_row, dst_stride, 1233848b8605Smrg src_row, src_stride, 1234848b8605Smrg src_width, src_height); 1235848b8605Smrg else if (format == MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC) 1236848b8605Smrg etc2_unpack_srgb8_alpha8(dst_row, dst_stride, 1237848b8605Smrg src_row, src_stride, 1238b8e80941Smrg src_width, src_height, bgra); 1239848b8605Smrg else if (format == MESA_FORMAT_ETC2_R11_EAC) 1240848b8605Smrg etc2_unpack_r11(dst_row, dst_stride, 1241848b8605Smrg src_row, src_stride, 1242848b8605Smrg src_width, src_height); 1243848b8605Smrg else if (format == MESA_FORMAT_ETC2_RG11_EAC) 1244848b8605Smrg etc2_unpack_rg11(dst_row, dst_stride, 1245848b8605Smrg src_row, src_stride, 1246848b8605Smrg src_width, src_height); 1247848b8605Smrg else if (format == MESA_FORMAT_ETC2_SIGNED_R11_EAC) 1248848b8605Smrg etc2_unpack_signed_r11(dst_row, dst_stride, 1249848b8605Smrg src_row, src_stride, 1250848b8605Smrg src_width, src_height); 1251848b8605Smrg else if (format == MESA_FORMAT_ETC2_SIGNED_RG11_EAC) 1252848b8605Smrg etc2_unpack_signed_rg11(dst_row, dst_stride, 1253848b8605Smrg src_row, src_stride, 1254848b8605Smrg src_width, src_height); 1255848b8605Smrg else if (format == MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1) 1256848b8605Smrg etc2_unpack_rgb8_punchthrough_alpha1(dst_row, dst_stride, 1257848b8605Smrg src_row, src_stride, 1258848b8605Smrg src_width, src_height); 1259848b8605Smrg else if (format == MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1) 1260848b8605Smrg etc2_unpack_srgb8_punchthrough_alpha1(dst_row, dst_stride, 1261848b8605Smrg src_row, src_stride, 1262b8e80941Smrg src_width, src_height, bgra); 1263848b8605Smrg} 1264848b8605Smrg 1265848b8605Smrg 1266848b8605Smrg 1267848b8605Smrgstatic void 1268848b8605Smrgfetch_etc1_rgb8(const GLubyte *map, 1269848b8605Smrg GLint rowStride, GLint i, GLint j, 1270848b8605Smrg GLfloat *texel) 1271848b8605Smrg{ 1272848b8605Smrg struct etc1_block block; 1273848b8605Smrg GLubyte dst[3]; 1274848b8605Smrg const GLubyte *src; 1275848b8605Smrg 1276848b8605Smrg src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; 1277848b8605Smrg 1278848b8605Smrg etc1_parse_block(&block, src); 1279848b8605Smrg etc1_fetch_texel(&block, i % 4, j % 4, dst); 1280848b8605Smrg 1281848b8605Smrg texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); 1282848b8605Smrg texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); 1283848b8605Smrg texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); 1284848b8605Smrg texel[ACOMP] = 1.0f; 1285848b8605Smrg} 1286848b8605Smrg 1287848b8605Smrg 1288848b8605Smrgstatic void 1289848b8605Smrgfetch_etc2_rgb8(const GLubyte *map, 1290848b8605Smrg GLint rowStride, GLint i, GLint j, GLfloat *texel) 1291848b8605Smrg{ 1292848b8605Smrg struct etc2_block block; 1293848b8605Smrg uint8_t dst[3]; 1294848b8605Smrg const uint8_t *src; 1295848b8605Smrg 1296848b8605Smrg src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; 1297848b8605Smrg 1298848b8605Smrg etc2_rgb8_parse_block(&block, src, 1299848b8605Smrg false /* punchthrough_alpha */); 1300848b8605Smrg etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, 1301848b8605Smrg false /* punchthrough_alpha */); 1302848b8605Smrg 1303848b8605Smrg texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); 1304848b8605Smrg texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); 1305848b8605Smrg texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); 1306848b8605Smrg texel[ACOMP] = 1.0f; 1307848b8605Smrg} 1308848b8605Smrg 1309848b8605Smrgstatic void 1310848b8605Smrgfetch_etc2_srgb8(const GLubyte *map, 1311848b8605Smrg GLint rowStride, GLint i, GLint j, GLfloat *texel) 1312848b8605Smrg{ 1313848b8605Smrg struct etc2_block block; 1314848b8605Smrg uint8_t dst[3]; 1315848b8605Smrg const uint8_t *src; 1316848b8605Smrg 1317848b8605Smrg src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; 1318848b8605Smrg 1319848b8605Smrg etc2_rgb8_parse_block(&block, src, 1320848b8605Smrg false /* punchthrough_alpha */); 1321848b8605Smrg etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, 1322848b8605Smrg false /* punchthrough_alpha */); 1323848b8605Smrg 1324848b8605Smrg texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]); 1325848b8605Smrg texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]); 1326848b8605Smrg texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]); 1327848b8605Smrg texel[ACOMP] = 1.0f; 1328848b8605Smrg} 1329848b8605Smrg 1330848b8605Smrgstatic void 1331848b8605Smrgfetch_etc2_rgba8_eac(const GLubyte *map, 1332848b8605Smrg GLint rowStride, GLint i, GLint j, GLfloat *texel) 1333848b8605Smrg{ 1334848b8605Smrg struct etc2_block block; 1335848b8605Smrg uint8_t dst[4]; 1336848b8605Smrg const uint8_t *src; 1337848b8605Smrg 1338848b8605Smrg src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; 1339848b8605Smrg 1340848b8605Smrg etc2_rgba8_parse_block(&block, src); 1341848b8605Smrg etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst); 1342848b8605Smrg 1343848b8605Smrg texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); 1344848b8605Smrg texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); 1345848b8605Smrg texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); 1346848b8605Smrg texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); 1347848b8605Smrg} 1348848b8605Smrg 1349848b8605Smrgstatic void 1350848b8605Smrgfetch_etc2_srgb8_alpha8_eac(const GLubyte *map, 1351848b8605Smrg GLint rowStride, GLint i, GLint j, GLfloat *texel) 1352848b8605Smrg{ 1353848b8605Smrg struct etc2_block block; 1354848b8605Smrg uint8_t dst[4]; 1355848b8605Smrg const uint8_t *src; 1356848b8605Smrg 1357848b8605Smrg src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; 1358848b8605Smrg 1359848b8605Smrg etc2_rgba8_parse_block(&block, src); 1360848b8605Smrg etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst); 1361848b8605Smrg 1362848b8605Smrg texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]); 1363848b8605Smrg texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]); 1364848b8605Smrg texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]); 1365848b8605Smrg texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); 1366848b8605Smrg} 1367848b8605Smrg 1368848b8605Smrgstatic void 1369848b8605Smrgfetch_etc2_r11_eac(const GLubyte *map, 1370848b8605Smrg GLint rowStride, GLint i, GLint j, GLfloat *texel) 1371848b8605Smrg{ 1372848b8605Smrg struct etc2_block block; 1373848b8605Smrg GLushort dst; 1374848b8605Smrg const uint8_t *src; 1375848b8605Smrg 1376848b8605Smrg src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; 1377848b8605Smrg 1378848b8605Smrg etc2_r11_parse_block(&block, src); 1379848b8605Smrg etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst); 1380848b8605Smrg 1381848b8605Smrg texel[RCOMP] = USHORT_TO_FLOAT(dst); 1382848b8605Smrg texel[GCOMP] = 0.0f; 1383848b8605Smrg texel[BCOMP] = 0.0f; 1384848b8605Smrg texel[ACOMP] = 1.0f; 1385848b8605Smrg} 1386848b8605Smrg 1387848b8605Smrgstatic void 1388848b8605Smrgfetch_etc2_rg11_eac(const GLubyte *map, 1389848b8605Smrg GLint rowStride, GLint i, GLint j, GLfloat *texel) 1390848b8605Smrg{ 1391848b8605Smrg struct etc2_block block; 1392848b8605Smrg GLushort dst[2]; 1393848b8605Smrg const uint8_t *src; 1394848b8605Smrg 1395848b8605Smrg src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; 1396848b8605Smrg 1397848b8605Smrg /* red component */ 1398848b8605Smrg etc2_r11_parse_block(&block, src); 1399848b8605Smrg etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)dst); 1400848b8605Smrg 1401848b8605Smrg /* green component */ 1402848b8605Smrg etc2_r11_parse_block(&block, src + 8); 1403848b8605Smrg etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)(dst + 1)); 1404848b8605Smrg 1405848b8605Smrg texel[RCOMP] = USHORT_TO_FLOAT(dst[0]); 1406848b8605Smrg texel[GCOMP] = USHORT_TO_FLOAT(dst[1]); 1407848b8605Smrg texel[BCOMP] = 0.0f; 1408848b8605Smrg texel[ACOMP] = 1.0f; 1409848b8605Smrg} 1410848b8605Smrg 1411848b8605Smrgstatic void 1412848b8605Smrgfetch_etc2_signed_r11_eac(const GLubyte *map, 1413848b8605Smrg GLint rowStride, GLint i, GLint j, GLfloat *texel) 1414848b8605Smrg{ 1415848b8605Smrg struct etc2_block block; 1416848b8605Smrg GLushort dst; 1417848b8605Smrg const uint8_t *src; 1418848b8605Smrg 1419848b8605Smrg src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; 1420848b8605Smrg 1421848b8605Smrg etc2_r11_parse_block(&block, src); 1422848b8605Smrg etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst); 1423848b8605Smrg 1424848b8605Smrg texel[RCOMP] = SHORT_TO_FLOAT(dst); 1425848b8605Smrg texel[GCOMP] = 0.0f; 1426848b8605Smrg texel[BCOMP] = 0.0f; 1427848b8605Smrg texel[ACOMP] = 1.0f; 1428848b8605Smrg} 1429848b8605Smrg 1430848b8605Smrgstatic void 1431848b8605Smrgfetch_etc2_signed_rg11_eac(const GLubyte *map, 1432848b8605Smrg GLint rowStride, GLint i, GLint j, GLfloat *texel) 1433848b8605Smrg{ 1434848b8605Smrg struct etc2_block block; 1435848b8605Smrg GLushort dst[2]; 1436848b8605Smrg const uint8_t *src; 1437848b8605Smrg 1438848b8605Smrg src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; 1439848b8605Smrg 1440848b8605Smrg /* red component */ 1441848b8605Smrg etc2_r11_parse_block(&block, src); 1442848b8605Smrg etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)dst); 1443848b8605Smrg 1444848b8605Smrg /* green component */ 1445848b8605Smrg etc2_r11_parse_block(&block, src + 8); 1446848b8605Smrg etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)(dst + 1)); 1447848b8605Smrg 1448848b8605Smrg texel[RCOMP] = SHORT_TO_FLOAT(dst[0]); 1449848b8605Smrg texel[GCOMP] = SHORT_TO_FLOAT(dst[1]); 1450848b8605Smrg texel[BCOMP] = 0.0f; 1451848b8605Smrg texel[ACOMP] = 1.0f; 1452848b8605Smrg} 1453848b8605Smrg 1454848b8605Smrgstatic void 1455848b8605Smrgfetch_etc2_rgb8_punchthrough_alpha1(const GLubyte *map, 1456848b8605Smrg GLint rowStride, GLint i, GLint j, 1457848b8605Smrg GLfloat *texel) 1458848b8605Smrg{ 1459848b8605Smrg struct etc2_block block; 1460848b8605Smrg uint8_t dst[4]; 1461848b8605Smrg const uint8_t *src; 1462848b8605Smrg 1463848b8605Smrg src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; 1464848b8605Smrg 1465848b8605Smrg etc2_rgb8_parse_block(&block, src, 1466848b8605Smrg true /* punchthrough alpha */); 1467848b8605Smrg etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, 1468848b8605Smrg true /* punchthrough alpha */); 1469848b8605Smrg texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); 1470848b8605Smrg texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); 1471848b8605Smrg texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); 1472848b8605Smrg texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); 1473848b8605Smrg} 1474848b8605Smrg 1475848b8605Smrgstatic void 1476848b8605Smrgfetch_etc2_srgb8_punchthrough_alpha1(const GLubyte *map, 1477848b8605Smrg GLint rowStride, 1478848b8605Smrg GLint i, GLint j, GLfloat *texel) 1479848b8605Smrg{ 1480848b8605Smrg struct etc2_block block; 1481848b8605Smrg uint8_t dst[4]; 1482848b8605Smrg const uint8_t *src; 1483848b8605Smrg 1484848b8605Smrg src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; 1485848b8605Smrg 1486848b8605Smrg etc2_rgb8_parse_block(&block, src, 1487848b8605Smrg true /* punchthrough alpha */); 1488848b8605Smrg etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, 1489848b8605Smrg true /* punchthrough alpha */); 1490848b8605Smrg texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]); 1491848b8605Smrg texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]); 1492848b8605Smrg texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]); 1493848b8605Smrg texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); 1494848b8605Smrg} 1495848b8605Smrg 1496848b8605Smrg 1497848b8605Smrgcompressed_fetch_func 1498848b8605Smrg_mesa_get_etc_fetch_func(mesa_format format) 1499848b8605Smrg{ 1500848b8605Smrg switch (format) { 1501848b8605Smrg case MESA_FORMAT_ETC1_RGB8: 1502848b8605Smrg return fetch_etc1_rgb8; 1503848b8605Smrg case MESA_FORMAT_ETC2_RGB8: 1504848b8605Smrg return fetch_etc2_rgb8; 1505848b8605Smrg case MESA_FORMAT_ETC2_SRGB8: 1506848b8605Smrg return fetch_etc2_srgb8; 1507848b8605Smrg case MESA_FORMAT_ETC2_RGBA8_EAC: 1508848b8605Smrg return fetch_etc2_rgba8_eac; 1509848b8605Smrg case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: 1510848b8605Smrg return fetch_etc2_srgb8_alpha8_eac; 1511848b8605Smrg case MESA_FORMAT_ETC2_R11_EAC: 1512848b8605Smrg return fetch_etc2_r11_eac; 1513848b8605Smrg case MESA_FORMAT_ETC2_RG11_EAC: 1514848b8605Smrg return fetch_etc2_rg11_eac; 1515848b8605Smrg case MESA_FORMAT_ETC2_SIGNED_R11_EAC: 1516848b8605Smrg return fetch_etc2_signed_r11_eac; 1517848b8605Smrg case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: 1518848b8605Smrg return fetch_etc2_signed_rg11_eac; 1519848b8605Smrg case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: 1520848b8605Smrg return fetch_etc2_rgb8_punchthrough_alpha1; 1521848b8605Smrg case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: 1522848b8605Smrg return fetch_etc2_srgb8_punchthrough_alpha1; 1523848b8605Smrg default: 1524848b8605Smrg return NULL; 1525848b8605Smrg } 1526848b8605Smrg} 1527