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