• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 LunarG, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /**
25  * \file texcompress_etc.c
26  * GL_OES_compressed_ETC1_RGB8_texture support.
27  * Supported ETC2 texture formats are:
28  * GL_COMPRESSED_RGB8_ETC2
29  * GL_COMPRESSED_SRGB8_ETC2
30  * GL_COMPRESSED_RGBA8_ETC2_EAC
31  * GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
32  * GL_COMPRESSED_R11_EAC
33  * GL_COMPRESSED_RG11_EAC
34  * GL_COMPRESSED_SIGNED_R11_EAC
35  * GL_COMPRESSED_SIGNED_RG11_EAC
36  * MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1
37  * MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1
38  */
39 
40 #include <stdbool.h>
41 #include "texcompress.h"
42 #include "texcompress_etc.h"
43 #include "texstore.h"
44 #include "macros.h"
45 #include "format_unpack.h"
46 #include "util/format_srgb.h"
47 
48 
49 struct etc2_block {
50    int distance;
51    uint64_t pixel_indices[2];
52    const int *modifier_tables[2];
53    bool flipped;
54    bool opaque;
55    bool is_ind_mode;
56    bool is_diff_mode;
57    bool is_t_mode;
58    bool is_h_mode;
59    bool is_planar_mode;
60    uint8_t base_colors[3][3];
61    uint8_t paint_colors[4][3];
62    uint8_t base_codeword;
63    uint8_t multiplier;
64    uint8_t table_index;
65 };
66 
67 static const int etc2_distance_table[8] = {
68    3, 6, 11, 16, 23, 32, 41, 64 };
69 
70 static const int etc2_modifier_tables[16][8] = {
71    {  -3,   -6,   -9,  -15,   2,   5,   8,   14},
72    {  -3,   -7,  -10,  -13,   2,   6,   9,   12},
73    {  -2,   -5,   -8,  -13,   1,   4,   7,   12},
74    {  -2,   -4,   -6,  -13,   1,   3,   5,   12},
75    {  -3,   -6,   -8,  -12,   2,   5,   7,   11},
76    {  -3,   -7,   -9,  -11,   2,   6,   8,   10},
77    {  -4,   -7,   -8,  -11,   3,   6,   7,   10},
78    {  -3,   -5,   -8,  -11,   2,   4,   7,   10},
79    {  -2,   -6,   -8,  -10,   1,   5,   7,    9},
80    {  -2,   -5,   -8,  -10,   1,   4,   7,    9},
81    {  -2,   -4,   -8,  -10,   1,   3,   7,    9},
82    {  -2,   -5,   -7,  -10,   1,   4,   6,    9},
83    {  -3,   -4,   -7,  -10,   2,   3,   6,    9},
84    {  -1,   -2,   -3,  -10,   0,   1,   2,    9},
85    {  -4,   -6,   -8,   -9,   3,   5,   7,    8},
86    {  -3,   -5,   -7,   -9,   2,   4,   6,    8},
87 };
88 
89 static const int etc2_modifier_tables_non_opaque[8][4] = {
90    { 0,   8,   0,    -8},
91    { 0,   17,  0,   -17},
92    { 0,   29,  0,   -29},
93    { 0,   42,  0,   -42},
94    { 0,   60,  0,   -60},
95    { 0,   80,  0,   -80},
96    { 0,   106, 0,  -106},
97    { 0,   183, 0,  -183}
98 };
99 
100 /* define etc1_parse_block and etc. */
101 #define UINT8_TYPE GLubyte
102 #define TAG(x) x
103 #include "texcompress_etc_tmp.h"
104 #undef TAG
105 #undef UINT8_TYPE
106 
107 GLboolean
_mesa_texstore_etc1_rgb8(TEXSTORE_PARAMS)108 _mesa_texstore_etc1_rgb8(TEXSTORE_PARAMS)
109 {
110    /* GL_ETC1_RGB8_OES is only valid in glCompressedTexImage2D */
111    assert(0);
112 
113    return GL_FALSE;
114 }
115 
116 
117 /**
118  * Decode texture data in format `MESA_FORMAT_ETC1_RGB8` to
119  * `MESA_FORMAT_ABGR8888`.
120  *
121  * The size of the source data must be a multiple of the ETC1 block size,
122  * which is 8, even if the texture image's dimensions are not aligned to 4.
123  * From the GL_OES_compressed_ETC1_RGB8_texture spec:
124  *   The texture is described as a number of 4x4 pixel blocks. If the
125  *   texture (or a particular mip-level) is smaller than 4 pixels in
126  *   any dimension (such as a 2x2 or a 8x1 texture), the texture is
127  *   found in the upper left part of the block(s), and the rest of the
128  *   pixels are not used. For instance, a texture of size 4x2 will be
129  *   placed in the upper half of a 4x4 block, and the lower half of the
130  *   pixels in the block will not be accessed.
131  *
132  * \param src_width in pixels
133  * \param src_height in pixels
134  * \param dst_stride in bytes
135  */
136 void
_mesa_etc1_unpack_rgba8888(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned src_width,unsigned src_height)137 _mesa_etc1_unpack_rgba8888(uint8_t *dst_row,
138                            unsigned dst_stride,
139                            const uint8_t *src_row,
140                            unsigned src_stride,
141                            unsigned src_width,
142                            unsigned src_height)
143 {
144    etc1_unpack_rgba8888(dst_row, dst_stride,
145                         src_row, src_stride,
146                         src_width, src_height);
147 }
148 
149 static uint8_t
etc2_base_color1_t_mode(const uint8_t * in,GLuint index)150 etc2_base_color1_t_mode(const uint8_t *in, GLuint index)
151 {
152    uint8_t R1a = 0, x = 0;
153    /* base col 1 = extend_4to8bits( (R1a << 2) | R1b, G1, B1) */
154    switch(index) {
155    case 0:
156       R1a = (in[0] >> 3) & 0x3;
157       x = ((R1a << 2) | (in[0] & 0x3));
158       break;
159    case 1:
160       x = ((in[1] >> 4) & 0xf);
161       break;
162    case 2:
163       x = (in[1] & 0xf);
164       break;
165    default:
166       /* invalid index */
167       break;
168    }
169    return ((x << 4) | (x & 0xf));
170 }
171 
172 static uint8_t
etc2_base_color2_t_mode(const uint8_t * in,GLuint index)173 etc2_base_color2_t_mode(const uint8_t *in, GLuint index)
174 {
175    uint8_t x = 0;
176    /*extend 4to8bits(R2, G2, B2)*/
177    switch(index) {
178    case 0:
179       x = ((in[2] >> 4) & 0xf );
180       break;
181    case 1:
182       x = (in[2] & 0xf);
183       break;
184    case 2:
185       x = ((in[3] >> 4) & 0xf);
186       break;
187    default:
188       /* invalid index */
189       break;
190    }
191    return ((x << 4) | (x & 0xf));
192 }
193 
194 static uint8_t
etc2_base_color1_h_mode(const uint8_t * in,GLuint index)195 etc2_base_color1_h_mode(const uint8_t *in, GLuint index)
196 {
197    uint8_t x = 0;
198    /* base col 1 = extend 4to8bits(R1, (G1a << 1) | G1b, (B1a << 3) | B1b) */
199    switch(index) {
200    case 0:
201       x = ((in[0] >> 3) & 0xf);
202       break;
203    case 1:
204       x = (((in[0] & 0x7) << 1) | ((in[1] >> 4) & 0x1));
205       break;
206    case 2:
207       x = ((in[1] & 0x8) |
208            (((in[1] & 0x3) << 1) | ((in[2] >> 7) & 0x1)));
209       break;
210    default:
211       /* invalid index */
212       break;
213    }
214    return ((x << 4) | (x & 0xf));
215 }
216 
217 static uint8_t
etc2_base_color2_h_mode(const uint8_t * in,GLuint index)218 etc2_base_color2_h_mode(const uint8_t *in, GLuint index)
219 {
220    uint8_t x = 0;
221    /* base col 2 = extend 4to8bits(R2, G2, B2) */
222    switch(index) {
223    case 0:
224       x = ((in[2] >> 3) & 0xf );
225       break;
226    case 1:
227       x = (((in[2] & 0x7) << 1) | ((in[3] >> 7) & 0x1));
228       break;
229    case 2:
230       x = ((in[3] >> 3) & 0xf);
231       break;
232    default:
233       /* invalid index */
234       break;
235    }
236    return ((x << 4) | (x & 0xf));
237 }
238 
239 static uint8_t
etc2_base_color_o_planar(const uint8_t * in,GLuint index)240 etc2_base_color_o_planar(const uint8_t *in, GLuint index)
241 {
242    GLuint tmp;
243    switch(index) {
244    case 0:
245       tmp = ((in[0] >> 1) & 0x3f); /* RO */
246       return ((tmp << 2) | (tmp >> 4));
247    case 1:
248       tmp = (((in[0] & 0x1) << 6) | /* GO1 */
249              ((in[1] >> 1) & 0x3f)); /* GO2 */
250       return ((tmp << 1) | (tmp >> 6));
251    case 2:
252       tmp = (((in[1] & 0x1) << 5) | /* BO1 */
253              (in[2] & 0x18) | /* BO2 */
254              (((in[2] & 0x3) << 1) | ((in[3] >> 7) & 0x1))); /* BO3 */
255       return ((tmp << 2) | (tmp >> 4));
256     default:
257       /* invalid index */
258       return 0;
259    }
260 }
261 
262 static uint8_t
etc2_base_color_h_planar(const uint8_t * in,GLuint index)263 etc2_base_color_h_planar(const uint8_t *in, GLuint index)
264 {
265    GLuint tmp;
266    switch(index) {
267    case 0:
268       tmp = (((in[3] & 0x7c) >> 1) | /* RH1 */
269              (in[3] & 0x1));         /* RH2 */
270       return ((tmp << 2) | (tmp >> 4));
271    case 1:
272       tmp = (in[4] >> 1) & 0x7f; /* GH */
273       return ((tmp << 1) | (tmp >> 6));
274    case 2:
275       tmp = (((in[4] & 0x1) << 5) |
276              ((in[5] >> 3) & 0x1f)); /* BH */
277       return ((tmp << 2) | (tmp >> 4));
278    default:
279       /* invalid index */
280       return 0;
281    }
282 }
283 
284 static uint8_t
etc2_base_color_v_planar(const uint8_t * in,GLuint index)285 etc2_base_color_v_planar(const uint8_t *in, GLuint index)
286 {
287    GLuint tmp;
288    switch(index) {
289    case 0:
290       tmp = (((in[5] & 0x7) << 0x3) |
291              ((in[6] >> 5) & 0x7)); /* RV */
292       return ((tmp << 2) | (tmp >> 4));
293    case 1:
294       tmp = (((in[6] & 0x1f) << 2) |
295              ((in[7] >> 6) & 0x3)); /* GV */
296       return ((tmp << 1) | (tmp >> 6));
297    case 2:
298       tmp = in[7] & 0x3f; /* BV */
299       return ((tmp << 2) | (tmp >> 4));
300    default:
301       /* invalid index */
302       return 0;
303    }
304 }
305 
306 static GLint
etc2_get_pixel_index(const struct etc2_block * block,int x,int y)307 etc2_get_pixel_index(const struct etc2_block *block, int x, int y)
308 {
309    int bit = ((3 - y) + (3 - x) * 4) * 3;
310    int idx = (block->pixel_indices[1] >> bit) & 0x7;
311    return idx;
312 }
313 
314 static uint8_t
etc2_clamp(int color)315 etc2_clamp(int color)
316 {
317    /* CLAMP(color, 0, 255) */
318    return (uint8_t) CLAMP(color, 0, 255);
319 }
320 
321 static GLushort
etc2_clamp2(int color)322 etc2_clamp2(int color)
323 {
324    /* CLAMP(color, 0, 2047) */
325    return (GLushort) CLAMP(color, 0, 2047);
326 }
327 
328 static GLshort
etc2_clamp3(int color)329 etc2_clamp3(int color)
330 {
331    /* CLAMP(color, -1023, 1023) */
332    return (GLshort) CLAMP(color, -1023, 1023);
333 }
334 
335 static void
etc2_rgb8_parse_block(struct etc2_block * block,const uint8_t * src,GLboolean punchthrough_alpha)336 etc2_rgb8_parse_block(struct etc2_block *block,
337                       const uint8_t *src,
338                       GLboolean punchthrough_alpha)
339 {
340    unsigned i;
341    GLboolean diffbit = false;
342    static const int lookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 };
343 
344    const int R_plus_dR = (src[0] >> 3) + lookup[src[0] & 0x7];
345    const int G_plus_dG = (src[1] >> 3) + lookup[src[1] & 0x7];
346    const int B_plus_dB = (src[2] >> 3) + lookup[src[2] & 0x7];
347 
348    /* Reset the mode flags */
349    block->is_ind_mode = false;
350    block->is_diff_mode = false;
351    block->is_t_mode = false;
352    block->is_h_mode = false;
353    block->is_planar_mode = false;
354 
355    if (punchthrough_alpha)
356       block->opaque = src[3] & 0x2;
357    else
358       diffbit = src[3] & 0x2;
359 
360    if (!diffbit && !punchthrough_alpha) {
361       /* individual mode */
362       block->is_ind_mode = true;
363 
364       for (i = 0; i < 3; i++) {
365          /* Texture decode algorithm is same for individual mode in etc1
366           * & etc2.
367           */
368          block->base_colors[0][i] = etc1_base_color_ind_hi(src[i]);
369          block->base_colors[1][i] = etc1_base_color_ind_lo(src[i]);
370       }
371    }
372    else if (R_plus_dR < 0 || R_plus_dR > 31){
373       /* T mode */
374       block->is_t_mode = true;
375 
376       for(i = 0; i < 3; i++) {
377          block->base_colors[0][i] = etc2_base_color1_t_mode(src, i);
378          block->base_colors[1][i] = etc2_base_color2_t_mode(src, i);
379       }
380       /* pick distance */
381       block->distance =
382          etc2_distance_table[(((src[3] >> 2) & 0x3) << 1) |
383                              (src[3] & 0x1)];
384 
385       for (i = 0; i < 3; i++) {
386          block->paint_colors[0][i] = etc2_clamp(block->base_colors[0][i]);
387          block->paint_colors[1][i] = etc2_clamp(block->base_colors[1][i] +
388                                                 block->distance);
389          block->paint_colors[2][i] = etc2_clamp(block->base_colors[1][i]);
390          block->paint_colors[3][i] = etc2_clamp(block->base_colors[1][i] -
391                                                 block->distance);
392       }
393    }
394    else if (G_plus_dG < 0 || G_plus_dG > 31){
395       int base_color_1_value, base_color_2_value;
396 
397       /* H mode */
398       block->is_h_mode = true;
399 
400       for(i = 0; i < 3; i++) {
401          block->base_colors[0][i] = etc2_base_color1_h_mode(src, i);
402          block->base_colors[1][i] = etc2_base_color2_h_mode(src, i);
403       }
404 
405       base_color_1_value = (block->base_colors[0][0] << 16) +
406                            (block->base_colors[0][1] << 8) +
407                            block->base_colors[0][2];
408       base_color_2_value = (block->base_colors[1][0] << 16) +
409                            (block->base_colors[1][1] << 8) +
410                            block->base_colors[1][2];
411       /* pick distance */
412       block->distance =
413          etc2_distance_table[(src[3] & 0x4) |
414                              ((src[3] & 0x1) << 1) |
415                              (base_color_1_value >= base_color_2_value)];
416 
417       for (i = 0; i < 3; i++) {
418          block->paint_colors[0][i] = etc2_clamp(block->base_colors[0][i] +
419                                                 block->distance);
420          block->paint_colors[1][i] = etc2_clamp(block->base_colors[0][i] -
421                                                 block->distance);
422          block->paint_colors[2][i] = etc2_clamp(block->base_colors[1][i] +
423                                                 block->distance);
424          block->paint_colors[3][i] = etc2_clamp(block->base_colors[1][i] -
425                                                 block->distance);
426       }
427    }
428    else if (B_plus_dB < 0 || B_plus_dB > 31) {
429       /* Planar mode */
430       block->is_planar_mode = true;
431 
432       /* opaque bit must be set in planar mode */
433       block->opaque = true;
434 
435       for (i = 0; i < 3; i++) {
436          block->base_colors[0][i] = etc2_base_color_o_planar(src, i);
437          block->base_colors[1][i] = etc2_base_color_h_planar(src, i);
438          block->base_colors[2][i] = etc2_base_color_v_planar(src, i);
439       }
440    }
441    else if (diffbit || punchthrough_alpha) {
442       /* differential mode */
443       block->is_diff_mode = true;
444 
445       for (i = 0; i < 3; i++) {
446          /* Texture decode algorithm is same for differential mode in etc1
447           * & etc2.
448           */
449          block->base_colors[0][i] = etc1_base_color_diff_hi(src[i]);
450          block->base_colors[1][i] = etc1_base_color_diff_lo(src[i]);
451       }
452    }
453 
454    if (block->is_ind_mode || block->is_diff_mode) {
455       int table1_idx = (src[3] >> 5) & 0x7;
456       int table2_idx = (src[3] >> 2) & 0x7;
457 
458       /* Use same modifier tables as for etc1 textures if opaque bit is set
459        * or if non punchthrough texture format
460        */
461       block->modifier_tables[0] = (!punchthrough_alpha || block->opaque) ?
462                                   etc1_modifier_tables[table1_idx] :
463                                   etc2_modifier_tables_non_opaque[table1_idx];
464       block->modifier_tables[1] = (!punchthrough_alpha || block->opaque) ?
465                                   etc1_modifier_tables[table2_idx] :
466                                   etc2_modifier_tables_non_opaque[table2_idx];
467 
468       block->flipped = (src[3] & 0x1);
469    }
470 
471    block->pixel_indices[0] =
472       (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7];
473 }
474 
475 static void
etc2_rgb8_fetch_texel(const struct etc2_block * block,int x,int y,uint8_t * dst,GLboolean punchthrough_alpha)476 etc2_rgb8_fetch_texel(const struct etc2_block *block,
477                       int x, int y, uint8_t *dst,
478                       GLboolean punchthrough_alpha)
479 {
480    const uint8_t *base_color;
481    int modifier, bit, idx, blk;
482 
483    /* get pixel index */
484    bit = y + x * 4;
485    idx = ((block->pixel_indices[0] >> (15 + bit)) & 0x2) |
486          ((block->pixel_indices[0] >>      (bit)) & 0x1);
487 
488    if (block->is_ind_mode || block->is_diff_mode) {
489       /* check for punchthrough_alpha format */
490       if (punchthrough_alpha) {
491          if (!block->opaque && idx == 2) {
492             dst[0] = dst[1] = dst[2] = dst[3] = 0;
493             return;
494          }
495          else
496             dst[3] = 255;
497       }
498 
499       /* Use pixel index and subblock to get the modifier */
500       blk = (block->flipped) ? (y >= 2) : (x >= 2);
501       base_color = block->base_colors[blk];
502       modifier = block->modifier_tables[blk][idx];
503 
504       dst[0] = etc2_clamp(base_color[0] + modifier);
505       dst[1] = etc2_clamp(base_color[1] + modifier);
506       dst[2] = etc2_clamp(base_color[2] + modifier);
507    }
508    else if (block->is_t_mode || block->is_h_mode) {
509       /* check for punchthrough_alpha format */
510       if (punchthrough_alpha) {
511          if (!block->opaque && idx == 2) {
512             dst[0] = dst[1] = dst[2] = dst[3] = 0;
513             return;
514          }
515          else
516             dst[3] = 255;
517       }
518 
519       /* Use pixel index to pick one of the paint colors */
520       dst[0] = block->paint_colors[idx][0];
521       dst[1] = block->paint_colors[idx][1];
522       dst[2] = block->paint_colors[idx][2];
523    }
524    else if (block->is_planar_mode) {
525       /* {R(x, y) = clamp255((x × (RH − RO) + y × (RV − RO) + 4 × RO + 2) >> 2)
526        * {G(x, y) = clamp255((x × (GH − GO) + y × (GV − GO) + 4 × GO + 2) >> 2)
527        * {B(x, y) = clamp255((x × (BH − BO) + y × (BV − BO) + 4 × BO + 2) >> 2)
528        */
529       int red, green, blue;
530       red = (x * (block->base_colors[1][0] - block->base_colors[0][0]) +
531              y * (block->base_colors[2][0] - block->base_colors[0][0]) +
532              4 * block->base_colors[0][0] + 2) >> 2;
533 
534       green = (x * (block->base_colors[1][1] - block->base_colors[0][1]) +
535                y * (block->base_colors[2][1] - block->base_colors[0][1]) +
536                4 * block->base_colors[0][1] + 2) >> 2;
537 
538       blue = (x * (block->base_colors[1][2] - block->base_colors[0][2]) +
539               y * (block->base_colors[2][2] - block->base_colors[0][2]) +
540               4 * block->base_colors[0][2] + 2) >> 2;
541 
542       dst[0] = etc2_clamp(red);
543       dst[1] = etc2_clamp(green);
544       dst[2] = etc2_clamp(blue);
545 
546       /* check for punchthrough_alpha format */
547       if (punchthrough_alpha)
548          dst[3] = 255;
549    }
550 }
551 
552 static void
etc2_alpha8_fetch_texel(const struct etc2_block * block,int x,int y,uint8_t * dst)553 etc2_alpha8_fetch_texel(const struct etc2_block *block,
554       int x, int y, uint8_t *dst)
555 {
556    int modifier, alpha, idx;
557    /* get pixel index */
558    idx = etc2_get_pixel_index(block, x, y);
559    modifier = etc2_modifier_tables[block->table_index][idx];
560    alpha = block->base_codeword + modifier * block->multiplier;
561    dst[3] = etc2_clamp(alpha);
562 }
563 
564 static void
etc2_r11_fetch_texel(const struct etc2_block * block,int x,int y,uint8_t * dst)565 etc2_r11_fetch_texel(const struct etc2_block *block,
566                      int x, int y, uint8_t *dst)
567 {
568    GLint modifier, idx;
569    GLshort color;
570    /* Get pixel index */
571    idx = etc2_get_pixel_index(block, x, y);
572    modifier = etc2_modifier_tables[block->table_index][idx];
573 
574    if (block->multiplier != 0)
575       /* clamp2(base codeword × 8 + 4 + modifier × multiplier × 8) */
576       color = etc2_clamp2(((block->base_codeword << 3) | 0x4)  +
577                           ((modifier * block->multiplier) << 3));
578    else
579       color = etc2_clamp2(((block->base_codeword << 3) | 0x4)  + modifier);
580 
581    /* Extend 11 bits color value to 16 bits. OpenGL ES 3.0 specification
582     * allows extending the color value to any number of bits. But, an
583     * implementation is not allowed to truncate the 11-bit value to less than
584     * 11 bits."
585     */
586    color = (color << 5) | (color >> 6);
587    ((GLushort *)dst)[0] = color;
588 }
589 
590 static void
etc2_signed_r11_fetch_texel(const struct etc2_block * block,int x,int y,uint8_t * dst)591 etc2_signed_r11_fetch_texel(const struct etc2_block *block,
592                             int x, int y, uint8_t *dst)
593 {
594    GLint modifier, idx;
595    GLshort color;
596    GLbyte base_codeword = (GLbyte) block->base_codeword;
597 
598    if (base_codeword == -128)
599       base_codeword = -127;
600 
601    /* Get pixel index */
602    idx = etc2_get_pixel_index(block, x, y);
603    modifier = etc2_modifier_tables[block->table_index][idx];
604 
605    if (block->multiplier != 0)
606       /* clamp3(base codeword × 8 + modifier × multiplier × 8) */
607       color = etc2_clamp3((base_codeword << 3)  +
608                          ((modifier * block->multiplier) << 3));
609    else
610       color = etc2_clamp3((base_codeword << 3)  + modifier);
611 
612    /* Extend 11 bits color value to 16 bits. OpenGL ES 3.0 specification
613     * allows extending the color value to any number of bits. But, an
614     * implementation is not allowed to truncate the 11-bit value to less than
615     * 11 bits. A negative 11-bit value must first be made positive before bit
616     * replication, and then made negative again
617     */
618    if (color >= 0)
619       color = (color << 5) | (color >> 5);
620    else {
621       color = -color;
622       color = (color << 5) | (color >> 5);
623       color = -color;
624    }
625    ((GLshort *)dst)[0] = color;
626 }
627 
628 static void
etc2_alpha8_parse_block(struct etc2_block * block,const uint8_t * src)629 etc2_alpha8_parse_block(struct etc2_block *block, const uint8_t *src)
630 {
631    block->base_codeword = src[0];
632    block->multiplier = (src[1] >> 4) & 0xf;
633    block->table_index = src[1] & 0xf;
634    block->pixel_indices[1] = (((uint64_t)src[2] << 40) |
635                               ((uint64_t)src[3] << 32) |
636                               ((uint64_t)src[4] << 24) |
637                               ((uint64_t)src[5] << 16) |
638                               ((uint64_t)src[6] << 8)  |
639                               ((uint64_t)src[7]));
640 }
641 
642 static void
etc2_r11_parse_block(struct etc2_block * block,const uint8_t * src)643 etc2_r11_parse_block(struct etc2_block *block, const uint8_t *src)
644 {
645    /* Parsing logic remains same as for etc2_alpha8_parse_block */
646     etc2_alpha8_parse_block(block, src);
647 }
648 
649 static void
etc2_rgba8_parse_block(struct etc2_block * block,const uint8_t * src)650 etc2_rgba8_parse_block(struct etc2_block *block, const uint8_t *src)
651 {
652    /* RGB component is parsed the same way as for MESA_FORMAT_ETC2_RGB8 */
653    etc2_rgb8_parse_block(block, src + 8,
654                          false /* punchthrough_alpha */);
655    /* Parse Alpha component */
656    etc2_alpha8_parse_block(block, src);
657 }
658 
659 static void
etc2_rgba8_fetch_texel(const struct etc2_block * block,int x,int y,uint8_t * dst)660 etc2_rgba8_fetch_texel(const struct etc2_block *block,
661       int x, int y, uint8_t *dst)
662 {
663    etc2_rgb8_fetch_texel(block, x, y, dst,
664                          false /* punchthrough_alpha */);
665    etc2_alpha8_fetch_texel(block, x, y, dst);
666 }
667 
668 static void
etc2_unpack_rgb8(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)669 etc2_unpack_rgb8(uint8_t *dst_row,
670                  unsigned dst_stride,
671                  const uint8_t *src_row,
672                  unsigned src_stride,
673                  unsigned width,
674                  unsigned height)
675 {
676    const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
677    struct etc2_block block;
678    unsigned x, y, i, j;
679 
680    for (y = 0; y < height; y += bh) {
681       const uint8_t *src = src_row;
682       /*
683        * Destination texture may not be a multiple of four texels in
684        * height. Compute a safe height to avoid writing outside the texture.
685        */
686       const unsigned h = MIN2(bh, height - y);
687 
688       for (x = 0; x < width; x+= bw) {
689          /*
690           * Destination texture may not be a multiple of four texels in
691           * width. Compute a safe width to avoid writing outside the texture.
692           */
693          const unsigned w = MIN2(bw, width - x);
694 
695          etc2_rgb8_parse_block(&block, src,
696                                false /* punchthrough_alpha */);
697 
698          for (j = 0; j < h; j++) {
699             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
700             for (i = 0; i < w; i++) {
701                etc2_rgb8_fetch_texel(&block, i, j, dst,
702                                      false /* punchthrough_alpha */);
703                dst[3] = 255;
704                dst += comps;
705             }
706          }
707 
708          src += bs;
709       }
710 
711       src_row += src_stride;
712    }
713 }
714 
715 static void
etc2_unpack_srgb8(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)716 etc2_unpack_srgb8(uint8_t *dst_row,
717                   unsigned dst_stride,
718                   const uint8_t *src_row,
719                   unsigned src_stride,
720                   unsigned width,
721                   unsigned height)
722 {
723    const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
724    struct etc2_block block;
725    unsigned x, y, i, j;
726    uint8_t tmp;
727 
728    for (y = 0; y < height; y += bh) {
729       const uint8_t *src = src_row;
730       const unsigned h = MIN2(bh, height - y);
731 
732       for (x = 0; x < width; x+= bw) {
733          const unsigned w = MIN2(bw, width - x);
734          etc2_rgb8_parse_block(&block, src,
735                                false /* punchthrough_alpha */);
736 
737 
738          for (j = 0; j < h; j++) {
739             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
740             for (i = 0; i < w; i++) {
741                etc2_rgb8_fetch_texel(&block, i, j, dst,
742                                      false /* punchthrough_alpha */);
743                /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
744                tmp = dst[0];
745                dst[0] = dst[2];
746                dst[2] = tmp;
747                dst[3] = 255;
748 
749                dst += comps;
750             }
751          }
752          src += bs;
753       }
754 
755       src_row += src_stride;
756    }
757 }
758 
759 static void
etc2_unpack_rgba8(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)760 etc2_unpack_rgba8(uint8_t *dst_row,
761                   unsigned dst_stride,
762                   const uint8_t *src_row,
763                   unsigned src_stride,
764                   unsigned width,
765                   unsigned height)
766 {
767    /* If internalformat is COMPRESSED_RGBA8_ETC2_EAC, each 4 × 4 block of
768     * RGBA8888 information is compressed to 128 bits. To decode a block, the
769     * two 64-bit integers int64bitAlpha and int64bitColor are calculated.
770    */
771    const unsigned bw = 4, bh = 4, bs = 16, comps = 4;
772    struct etc2_block block;
773    unsigned x, y, i, j;
774 
775    for (y = 0; y < height; y += bh) {
776       const uint8_t *src = src_row;
777       const unsigned h = MIN2(bh, height - y);
778 
779       for (x = 0; x < width; x+= bw) {
780          const unsigned w = MIN2(bw, width - x);
781          etc2_rgba8_parse_block(&block, src);
782 
783          for (j = 0; j < h; j++) {
784             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
785             for (i = 0; i < w; i++) {
786                etc2_rgba8_fetch_texel(&block, i, j, dst);
787                dst += comps;
788             }
789          }
790          src += bs;
791       }
792 
793       src_row += src_stride;
794    }
795 }
796 
797 static void
etc2_unpack_srgb8_alpha8(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)798 etc2_unpack_srgb8_alpha8(uint8_t *dst_row,
799                          unsigned dst_stride,
800                          const uint8_t *src_row,
801                          unsigned src_stride,
802                          unsigned width,
803                          unsigned height)
804 {
805    /* If internalformat is COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, each 4 × 4 block
806     * of RGBA8888 information is compressed to 128 bits. To decode a block, the
807     * two 64-bit integers int64bitAlpha and int64bitColor are calculated.
808     */
809    const unsigned bw = 4, bh = 4, bs = 16, comps = 4;
810    struct etc2_block block;
811    unsigned x, y, i, j;
812    uint8_t tmp;
813 
814    for (y = 0; y < height; y += bh) {
815       const unsigned h = MIN2(bh, height - y);
816       const uint8_t *src = src_row;
817 
818       for (x = 0; x < width; x+= bw) {
819          const unsigned w = MIN2(bw, width - x);
820          etc2_rgba8_parse_block(&block, src);
821 
822          for (j = 0; j < h; j++) {
823             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
824             for (i = 0; i < w; i++) {
825                etc2_rgba8_fetch_texel(&block, i, j, dst);
826 
827                /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
828                tmp = dst[0];
829                dst[0] = dst[2];
830                dst[2] = tmp;
831                dst[3] = dst[3];
832 
833                dst += comps;
834             }
835          }
836          src += bs;
837       }
838 
839       src_row += src_stride;
840    }
841 }
842 
843 static void
etc2_unpack_r11(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)844 etc2_unpack_r11(uint8_t *dst_row,
845                 unsigned dst_stride,
846                 const uint8_t *src_row,
847                 unsigned src_stride,
848                 unsigned width,
849                 unsigned height)
850 {
851    /* If internalformat is COMPRESSED_R11_EAC, each 4 × 4 block of
852       color information is compressed to 64 bits.
853    */
854    const unsigned bw = 4, bh = 4, bs = 8, comps = 1, comp_size = 2;
855    struct etc2_block block;
856    unsigned x, y, i, j;
857 
858    for (y = 0; y < height; y += bh) {
859       const unsigned h = MIN2(bh, height - y);
860       const uint8_t *src = src_row;
861 
862       for (x = 0; x < width; x+= bw) {
863          const unsigned w = MIN2(bw, width - x);
864          etc2_r11_parse_block(&block, src);
865 
866          for (j = 0; j < h; j++) {
867             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size;
868             for (i = 0; i < w; i++) {
869                etc2_r11_fetch_texel(&block, i, j, dst);
870                dst += comps * comp_size;
871             }
872          }
873          src += bs;
874       }
875 
876       src_row += src_stride;
877    }
878 }
879 
880 static void
etc2_unpack_rg11(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)881 etc2_unpack_rg11(uint8_t *dst_row,
882                  unsigned dst_stride,
883                  const uint8_t *src_row,
884                  unsigned src_stride,
885                  unsigned width,
886                  unsigned height)
887 {
888    /* If internalformat is COMPRESSED_RG11_EAC, each 4 × 4 block of
889       RG color information is compressed to 128 bits.
890    */
891    const unsigned bw = 4, bh = 4, bs = 16, comps = 2, comp_size = 2;
892    struct etc2_block block;
893    unsigned x, y, i, j;
894 
895    for (y = 0; y < height; y += bh) {
896       const unsigned h = MIN2(bh, height - y);
897       const uint8_t *src = src_row;
898 
899       for (x = 0; x < width; x+= bw) {
900          const unsigned w = MIN2(bw, width - x);
901          /* red component */
902          etc2_r11_parse_block(&block, src);
903 
904          for (j = 0; j < h; j++) {
905             uint8_t *dst = dst_row + (y + j) * dst_stride +
906                            x * comps * comp_size;
907             for (i = 0; i < w; i++) {
908                etc2_r11_fetch_texel(&block, i, j, dst);
909                dst += comps * comp_size;
910             }
911          }
912          /* green component */
913          etc2_r11_parse_block(&block, src + 8);
914 
915          for (j = 0; j < h; j++) {
916             uint8_t *dst = dst_row + (y + j) * dst_stride +
917                            x * comps * comp_size;
918             for (i = 0; i < w; i++) {
919                etc2_r11_fetch_texel(&block, i, j, dst + comp_size);
920                dst += comps * comp_size;
921             }
922          }
923          src += bs;
924       }
925 
926       src_row += src_stride;
927    }
928 }
929 
930 static void
etc2_unpack_signed_r11(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)931 etc2_unpack_signed_r11(uint8_t *dst_row,
932                        unsigned dst_stride,
933                        const uint8_t *src_row,
934                        unsigned src_stride,
935                        unsigned width,
936                        unsigned height)
937 {
938    /* If internalformat is COMPRESSED_SIGNED_R11_EAC, each 4 × 4 block of
939       red color information is compressed to 64 bits.
940    */
941    const unsigned bw = 4, bh = 4, bs = 8, comps = 1, comp_size = 2;
942    struct etc2_block block;
943    unsigned x, y, i, j;
944 
945    for (y = 0; y < height; y += bh) {
946       const unsigned h = MIN2(bh, height - y);
947       const uint8_t *src = src_row;
948 
949       for (x = 0; x < width; x+= bw) {
950          const unsigned w = MIN2(bw, width - x);
951          etc2_r11_parse_block(&block, src);
952 
953          for (j = 0; j < h; j++) {
954             uint8_t *dst = dst_row + (y + j) * dst_stride +
955                            x * comps * comp_size;
956             for (i = 0; i < w; i++) {
957                etc2_signed_r11_fetch_texel(&block, i, j, dst);
958                dst += comps * comp_size;
959             }
960          }
961          src += bs;
962       }
963 
964       src_row += src_stride;
965    }
966 }
967 
968 static void
etc2_unpack_signed_rg11(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)969 etc2_unpack_signed_rg11(uint8_t *dst_row,
970                         unsigned dst_stride,
971                         const uint8_t *src_row,
972                         unsigned src_stride,
973                         unsigned width,
974                         unsigned height)
975 {
976    /* If internalformat is COMPRESSED_SIGNED_RG11_EAC, each 4 × 4 block of
977       RG color information is compressed to 128 bits.
978    */
979    const unsigned bw = 4, bh = 4, bs = 16, comps = 2, comp_size = 2;
980    struct etc2_block block;
981    unsigned x, y, i, j;
982 
983    for (y = 0; y < height; y += bh) {
984       const unsigned h = MIN2(bh, height - y);
985       const uint8_t *src = src_row;
986 
987       for (x = 0; x < width; x+= bw) {
988          const unsigned w = MIN2(bw, width - x);
989          /* red component */
990          etc2_r11_parse_block(&block, src);
991 
992          for (j = 0; j < h; j++) {
993             uint8_t *dst = dst_row + (y + j) * dst_stride +
994                           x * comps * comp_size;
995             for (i = 0; i < w; i++) {
996                etc2_signed_r11_fetch_texel(&block, i, j, dst);
997                dst += comps * comp_size;
998             }
999          }
1000          /* green component */
1001          etc2_r11_parse_block(&block, src + 8);
1002 
1003          for (j = 0; j < h; j++) {
1004             uint8_t *dst = dst_row + (y + j) * dst_stride +
1005                            x * comps * comp_size;
1006             for (i = 0; i < w; i++) {
1007                etc2_signed_r11_fetch_texel(&block, i, j, dst + comp_size);
1008                dst += comps * comp_size;
1009             }
1010          }
1011          src += bs;
1012       }
1013 
1014       src_row += src_stride;
1015    }
1016 }
1017 
1018 static void
etc2_unpack_rgb8_punchthrough_alpha1(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)1019 etc2_unpack_rgb8_punchthrough_alpha1(uint8_t *dst_row,
1020                                      unsigned dst_stride,
1021                                      const uint8_t *src_row,
1022                                      unsigned src_stride,
1023                                      unsigned width,
1024                                      unsigned height)
1025 {
1026    const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
1027    struct etc2_block block;
1028    unsigned x, y, i, j;
1029 
1030    for (y = 0; y < height; y += bh) {
1031       const unsigned h = MIN2(bh, height - y);
1032       const uint8_t *src = src_row;
1033 
1034       for (x = 0; x < width; x+= bw) {
1035          const unsigned w = MIN2(bw, width - x);
1036          etc2_rgb8_parse_block(&block, src,
1037                                true /* punchthrough_alpha */);
1038          for (j = 0; j < h; j++) {
1039             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
1040             for (i = 0; i < w; i++) {
1041                etc2_rgb8_fetch_texel(&block, i, j, dst,
1042                                      true /* punchthrough_alpha */);
1043                dst += comps;
1044             }
1045          }
1046 
1047          src += bs;
1048       }
1049 
1050       src_row += src_stride;
1051    }
1052 }
1053 
1054 static void
etc2_unpack_srgb8_punchthrough_alpha1(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)1055 etc2_unpack_srgb8_punchthrough_alpha1(uint8_t *dst_row,
1056                                      unsigned dst_stride,
1057                                      const uint8_t *src_row,
1058                                      unsigned src_stride,
1059                                      unsigned width,
1060                                      unsigned height)
1061 {
1062    const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
1063    struct etc2_block block;
1064    unsigned x, y, i, j;
1065    uint8_t tmp;
1066 
1067    for (y = 0; y < height; y += bh) {
1068       const unsigned h = MIN2(bh, height - y);
1069       const uint8_t *src = src_row;
1070 
1071       for (x = 0; x < width; x+= bw) {
1072          const unsigned w = MIN2(bw, width - x);
1073          etc2_rgb8_parse_block(&block, src,
1074                                true /* punchthrough_alpha */);
1075          for (j = 0; j < h; j++) {
1076             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
1077             for (i = 0; i < w; i++) {
1078                etc2_rgb8_fetch_texel(&block, i, j, dst,
1079                                      true /* punchthrough_alpha */);
1080                /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
1081                tmp = dst[0];
1082                dst[0] = dst[2];
1083                dst[2] = tmp;
1084                dst[3] = dst[3];
1085 
1086                dst += comps;
1087             }
1088          }
1089 
1090          src += bs;
1091       }
1092 
1093       src_row += src_stride;
1094    }
1095 }
1096 
1097 /* ETC2 texture formats are valid in glCompressedTexImage2D and
1098  * glCompressedTexSubImage2D functions */
1099 GLboolean
_mesa_texstore_etc2_rgb8(TEXSTORE_PARAMS)1100 _mesa_texstore_etc2_rgb8(TEXSTORE_PARAMS)
1101 {
1102    assert(0);
1103 
1104    return GL_FALSE;
1105 }
1106 
1107 GLboolean
_mesa_texstore_etc2_srgb8(TEXSTORE_PARAMS)1108 _mesa_texstore_etc2_srgb8(TEXSTORE_PARAMS)
1109 {
1110    assert(0);
1111 
1112    return GL_FALSE;
1113 }
1114 
1115 GLboolean
_mesa_texstore_etc2_rgba8_eac(TEXSTORE_PARAMS)1116 _mesa_texstore_etc2_rgba8_eac(TEXSTORE_PARAMS)
1117 {
1118    assert(0);
1119 
1120    return GL_FALSE;
1121 }
1122 
1123 GLboolean
_mesa_texstore_etc2_srgb8_alpha8_eac(TEXSTORE_PARAMS)1124 _mesa_texstore_etc2_srgb8_alpha8_eac(TEXSTORE_PARAMS)
1125 {
1126    assert(0);
1127 
1128    return GL_FALSE;
1129 }
1130 
1131 GLboolean
_mesa_texstore_etc2_r11_eac(TEXSTORE_PARAMS)1132 _mesa_texstore_etc2_r11_eac(TEXSTORE_PARAMS)
1133 {
1134    assert(0);
1135 
1136    return GL_FALSE;
1137 }
1138 
1139 GLboolean
_mesa_texstore_etc2_signed_r11_eac(TEXSTORE_PARAMS)1140 _mesa_texstore_etc2_signed_r11_eac(TEXSTORE_PARAMS)
1141 {
1142    assert(0);
1143 
1144    return GL_FALSE;
1145 }
1146 
1147 GLboolean
_mesa_texstore_etc2_rg11_eac(TEXSTORE_PARAMS)1148 _mesa_texstore_etc2_rg11_eac(TEXSTORE_PARAMS)
1149 {
1150    assert(0);
1151 
1152    return GL_FALSE;
1153 }
1154 
1155 GLboolean
_mesa_texstore_etc2_signed_rg11_eac(TEXSTORE_PARAMS)1156 _mesa_texstore_etc2_signed_rg11_eac(TEXSTORE_PARAMS)
1157 {
1158    assert(0);
1159 
1160    return GL_FALSE;
1161 }
1162 
1163 GLboolean
_mesa_texstore_etc2_rgb8_punchthrough_alpha1(TEXSTORE_PARAMS)1164 _mesa_texstore_etc2_rgb8_punchthrough_alpha1(TEXSTORE_PARAMS)
1165 {
1166    assert(0);
1167 
1168    return GL_FALSE;
1169 }
1170 
1171 GLboolean
_mesa_texstore_etc2_srgb8_punchthrough_alpha1(TEXSTORE_PARAMS)1172 _mesa_texstore_etc2_srgb8_punchthrough_alpha1(TEXSTORE_PARAMS)
1173 {
1174    assert(0);
1175 
1176    return GL_FALSE;
1177 }
1178 
1179 
1180 /**
1181  * Decode texture data in any one of following formats:
1182  * `MESA_FORMAT_ETC2_RGB8`
1183  * `MESA_FORMAT_ETC2_SRGB8`
1184  * `MESA_FORMAT_ETC2_RGBA8_EAC`
1185  * `MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC`
1186  * `MESA_FORMAT_ETC2_R11_EAC`
1187  * `MESA_FORMAT_ETC2_RG11_EAC`
1188  * `MESA_FORMAT_ETC2_SIGNED_R11_EAC`
1189  * `MESA_FORMAT_ETC2_SIGNED_RG11_EAC`
1190  * `MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1`
1191  * `MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1`
1192  *
1193  * The size of the source data must be a multiple of the ETC2 block size
1194  * even if the texture image's dimensions are not aligned to 4.
1195  *
1196  * \param src_width in pixels
1197  * \param src_height in pixels
1198  * \param dst_stride in bytes
1199  */
1200 
1201 void
_mesa_unpack_etc2_format(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned src_width,unsigned src_height,mesa_format format)1202 _mesa_unpack_etc2_format(uint8_t *dst_row,
1203                          unsigned dst_stride,
1204                          const uint8_t *src_row,
1205                          unsigned src_stride,
1206                          unsigned src_width,
1207                          unsigned src_height,
1208                          mesa_format format)
1209 {
1210    if (format == MESA_FORMAT_ETC2_RGB8)
1211       etc2_unpack_rgb8(dst_row, dst_stride,
1212                        src_row, src_stride,
1213                        src_width, src_height);
1214    else if (format == MESA_FORMAT_ETC2_SRGB8)
1215       etc2_unpack_srgb8(dst_row, dst_stride,
1216                         src_row, src_stride,
1217                         src_width, src_height);
1218    else if (format == MESA_FORMAT_ETC2_RGBA8_EAC)
1219       etc2_unpack_rgba8(dst_row, dst_stride,
1220                         src_row, src_stride,
1221                         src_width, src_height);
1222    else if (format == MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC)
1223       etc2_unpack_srgb8_alpha8(dst_row, dst_stride,
1224                                src_row, src_stride,
1225                                src_width, src_height);
1226    else if (format == MESA_FORMAT_ETC2_R11_EAC)
1227       etc2_unpack_r11(dst_row, dst_stride,
1228                       src_row, src_stride,
1229                       src_width, src_height);
1230    else if (format == MESA_FORMAT_ETC2_RG11_EAC)
1231       etc2_unpack_rg11(dst_row, dst_stride,
1232                        src_row, src_stride,
1233                        src_width, src_height);
1234    else if (format == MESA_FORMAT_ETC2_SIGNED_R11_EAC)
1235       etc2_unpack_signed_r11(dst_row, dst_stride,
1236                              src_row, src_stride,
1237                              src_width, src_height);
1238    else if (format == MESA_FORMAT_ETC2_SIGNED_RG11_EAC)
1239       etc2_unpack_signed_rg11(dst_row, dst_stride,
1240                               src_row, src_stride,
1241                               src_width, src_height);
1242    else if (format == MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1)
1243       etc2_unpack_rgb8_punchthrough_alpha1(dst_row, dst_stride,
1244                                            src_row, src_stride,
1245                                            src_width, src_height);
1246    else if (format == MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1)
1247       etc2_unpack_srgb8_punchthrough_alpha1(dst_row, dst_stride,
1248                                             src_row, src_stride,
1249                                             src_width, src_height);
1250 }
1251 
1252 
1253 
1254 static void
fetch_etc1_rgb8(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)1255 fetch_etc1_rgb8(const GLubyte *map,
1256                 GLint rowStride, GLint i, GLint j,
1257                 GLfloat *texel)
1258 {
1259    struct etc1_block block;
1260    GLubyte dst[3];
1261    const GLubyte *src;
1262 
1263    src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1264 
1265    etc1_parse_block(&block, src);
1266    etc1_fetch_texel(&block, i % 4, j % 4, dst);
1267 
1268    texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]);
1269    texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]);
1270    texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]);
1271    texel[ACOMP] = 1.0f;
1272 }
1273 
1274 
1275 static void
fetch_etc2_rgb8(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)1276 fetch_etc2_rgb8(const GLubyte *map,
1277                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
1278 {
1279    struct etc2_block block;
1280    uint8_t dst[3];
1281    const uint8_t *src;
1282 
1283    src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1284 
1285    etc2_rgb8_parse_block(&block, src,
1286                          false /* punchthrough_alpha */);
1287    etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst,
1288                          false /* punchthrough_alpha */);
1289 
1290    texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]);
1291    texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]);
1292    texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]);
1293    texel[ACOMP] = 1.0f;
1294 }
1295 
1296 static void
fetch_etc2_srgb8(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)1297 fetch_etc2_srgb8(const GLubyte *map,
1298                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
1299 {
1300    struct etc2_block block;
1301    uint8_t dst[3];
1302    const uint8_t *src;
1303 
1304    src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1305 
1306    etc2_rgb8_parse_block(&block, src,
1307                          false /* punchthrough_alpha */);
1308    etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst,
1309                          false /* punchthrough_alpha */);
1310 
1311    texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]);
1312    texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]);
1313    texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]);
1314    texel[ACOMP] = 1.0f;
1315 }
1316 
1317 static void
fetch_etc2_rgba8_eac(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)1318 fetch_etc2_rgba8_eac(const GLubyte *map,
1319                      GLint rowStride, GLint i, GLint j, GLfloat *texel)
1320 {
1321    struct etc2_block block;
1322    uint8_t dst[4];
1323    const uint8_t *src;
1324 
1325    src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
1326 
1327    etc2_rgba8_parse_block(&block, src);
1328    etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst);
1329 
1330    texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]);
1331    texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]);
1332    texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]);
1333    texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]);
1334 }
1335 
1336 static void
fetch_etc2_srgb8_alpha8_eac(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)1337 fetch_etc2_srgb8_alpha8_eac(const GLubyte *map,
1338                             GLint rowStride, GLint i, GLint j, GLfloat *texel)
1339 {
1340    struct etc2_block block;
1341    uint8_t dst[4];
1342    const uint8_t *src;
1343 
1344    src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
1345 
1346    etc2_rgba8_parse_block(&block, src);
1347    etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst);
1348 
1349    texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]);
1350    texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]);
1351    texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]);
1352    texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]);
1353 }
1354 
1355 static void
fetch_etc2_r11_eac(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)1356 fetch_etc2_r11_eac(const GLubyte *map,
1357                    GLint rowStride, GLint i, GLint j, GLfloat *texel)
1358 {
1359    struct etc2_block block;
1360    GLushort dst;
1361    const uint8_t *src;
1362 
1363    src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1364 
1365    etc2_r11_parse_block(&block, src);
1366    etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst);
1367 
1368    texel[RCOMP] = USHORT_TO_FLOAT(dst);
1369    texel[GCOMP] = 0.0f;
1370    texel[BCOMP] = 0.0f;
1371    texel[ACOMP] = 1.0f;
1372 }
1373 
1374 static void
fetch_etc2_rg11_eac(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)1375 fetch_etc2_rg11_eac(const GLubyte *map,
1376                     GLint rowStride, GLint i, GLint j, GLfloat *texel)
1377 {
1378    struct etc2_block block;
1379    GLushort dst[2];
1380    const uint8_t *src;
1381 
1382    src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
1383 
1384    /* red component */
1385    etc2_r11_parse_block(&block, src);
1386    etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)dst);
1387 
1388    /* green component */
1389    etc2_r11_parse_block(&block, src + 8);
1390    etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)(dst + 1));
1391 
1392    texel[RCOMP] = USHORT_TO_FLOAT(dst[0]);
1393    texel[GCOMP] = USHORT_TO_FLOAT(dst[1]);
1394    texel[BCOMP] = 0.0f;
1395    texel[ACOMP] = 1.0f;
1396 }
1397 
1398 static void
fetch_etc2_signed_r11_eac(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)1399 fetch_etc2_signed_r11_eac(const GLubyte *map,
1400                           GLint rowStride, GLint i, GLint j, GLfloat *texel)
1401 {
1402    struct etc2_block block;
1403    GLushort dst;
1404    const uint8_t *src;
1405 
1406    src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1407 
1408    etc2_r11_parse_block(&block, src);
1409    etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst);
1410 
1411    texel[RCOMP] = SHORT_TO_FLOAT(dst);
1412    texel[GCOMP] = 0.0f;
1413    texel[BCOMP] = 0.0f;
1414    texel[ACOMP] = 1.0f;
1415 }
1416 
1417 static void
fetch_etc2_signed_rg11_eac(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)1418 fetch_etc2_signed_rg11_eac(const GLubyte *map,
1419                            GLint rowStride, GLint i, GLint j, GLfloat *texel)
1420 {
1421    struct etc2_block block;
1422    GLushort dst[2];
1423    const uint8_t *src;
1424 
1425    src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
1426 
1427    /* red component */
1428    etc2_r11_parse_block(&block, src);
1429    etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)dst);
1430 
1431    /* green component */
1432    etc2_r11_parse_block(&block, src + 8);
1433    etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)(dst + 1));
1434 
1435    texel[RCOMP] = SHORT_TO_FLOAT(dst[0]);
1436    texel[GCOMP] = SHORT_TO_FLOAT(dst[1]);
1437    texel[BCOMP] = 0.0f;
1438    texel[ACOMP] = 1.0f;
1439 }
1440 
1441 static void
fetch_etc2_rgb8_punchthrough_alpha1(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)1442 fetch_etc2_rgb8_punchthrough_alpha1(const GLubyte *map,
1443                                     GLint rowStride, GLint i, GLint j,
1444                                     GLfloat *texel)
1445 {
1446    struct etc2_block block;
1447    uint8_t dst[4];
1448    const uint8_t *src;
1449 
1450    src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1451 
1452    etc2_rgb8_parse_block(&block, src,
1453                          true /* punchthrough alpha */);
1454    etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst,
1455                          true /* punchthrough alpha */);
1456    texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]);
1457    texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]);
1458    texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]);
1459    texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]);
1460 }
1461 
1462 static void
fetch_etc2_srgb8_punchthrough_alpha1(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)1463 fetch_etc2_srgb8_punchthrough_alpha1(const GLubyte *map,
1464                                      GLint rowStride,
1465                                      GLint i, GLint j, GLfloat *texel)
1466 {
1467    struct etc2_block block;
1468    uint8_t dst[4];
1469    const uint8_t *src;
1470 
1471    src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1472 
1473    etc2_rgb8_parse_block(&block, src,
1474                          true /* punchthrough alpha */);
1475    etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst,
1476                          true /* punchthrough alpha */);
1477    texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]);
1478    texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]);
1479    texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]);
1480    texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]);
1481 }
1482 
1483 
1484 compressed_fetch_func
_mesa_get_etc_fetch_func(mesa_format format)1485 _mesa_get_etc_fetch_func(mesa_format format)
1486 {
1487    switch (format) {
1488    case MESA_FORMAT_ETC1_RGB8:
1489       return fetch_etc1_rgb8;
1490    case MESA_FORMAT_ETC2_RGB8:
1491       return fetch_etc2_rgb8;
1492    case MESA_FORMAT_ETC2_SRGB8:
1493       return fetch_etc2_srgb8;
1494    case MESA_FORMAT_ETC2_RGBA8_EAC:
1495       return fetch_etc2_rgba8_eac;
1496    case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
1497       return fetch_etc2_srgb8_alpha8_eac;
1498    case MESA_FORMAT_ETC2_R11_EAC:
1499       return fetch_etc2_r11_eac;
1500    case MESA_FORMAT_ETC2_RG11_EAC:
1501       return fetch_etc2_rg11_eac;
1502    case MESA_FORMAT_ETC2_SIGNED_R11_EAC:
1503       return fetch_etc2_signed_r11_eac;
1504    case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
1505       return fetch_etc2_signed_rg11_eac;
1506    case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
1507       return fetch_etc2_rgb8_punchthrough_alpha1;
1508    case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
1509       return fetch_etc2_srgb8_punchthrough_alpha1;
1510    default:
1511       return NULL;
1512    }
1513 }
1514