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 }
754 dst[3] = 255;
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