mesa: Add decoding functions for GL_COMPRESSED_RGB8_ETC2
[mesa.git] / src / mesa / main / texcompress_etc.c
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 */
30
31 #include <stdbool.h>
32 #include "mfeatures.h"
33 #include "texcompress.h"
34 #include "texcompress_etc.h"
35 #include "texstore.h"
36 #include "macros.h"
37 #include "swrast/s_context.h"
38
39 struct etc2_block {
40 int distance;
41 uint32_t pixel_indices;
42 const int *modifier_tables[2];
43 bool flipped;
44 bool is_ind_mode;
45 bool is_diff_mode;
46 bool is_t_mode;
47 bool is_h_mode;
48 bool is_planar_mode;
49 uint8_t base_colors[3][3];
50 uint8_t paint_colors[4][3];
51 };
52
53 static const int etc2_distance_table[8] = {
54 3, 6, 11, 16, 23, 32, 41, 64 };
55
56 /* define etc1_parse_block and etc. */
57 #define UINT8_TYPE GLubyte
58 #define TAG(x) x
59 #include "texcompress_etc_tmp.h"
60 #undef TAG
61 #undef UINT8_TYPE
62
63 GLboolean
64 _mesa_texstore_etc1_rgb8(TEXSTORE_PARAMS)
65 {
66 /* GL_ETC1_RGB8_OES is only valid in glCompressedTexImage2D */
67 ASSERT(0);
68
69 return GL_FALSE;
70 }
71
72 void
73 _mesa_fetch_texel_2d_f_etc1_rgb8(const struct swrast_texture_image *texImage,
74 GLint i, GLint j, GLint k, GLfloat *texel)
75 {
76 struct etc1_block block;
77 GLubyte dst[3];
78 const GLubyte *src;
79
80 src = (const GLubyte *) texImage->Map +
81 (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
82
83 etc1_parse_block(&block, src);
84 etc1_fetch_texel(&block, i % 4, j % 4, dst);
85
86 texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]);
87 texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]);
88 texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]);
89 texel[ACOMP] = 1.0f;
90 }
91
92 /**
93 * Decode texture data in format `MESA_FORMAT_ETC1_RGB8` to
94 * `MESA_FORMAT_ABGR8888`.
95 *
96 * The size of the source data must be a multiple of the ETC1 block size,
97 * which is 8, even if the texture image's dimensions are not aligned to 4.
98 * From the GL_OES_compressed_ETC1_RGB8_texture spec:
99 * The texture is described as a number of 4x4 pixel blocks. If the
100 * texture (or a particular mip-level) is smaller than 4 pixels in
101 * any dimension (such as a 2x2 or a 8x1 texture), the texture is
102 * found in the upper left part of the block(s), and the rest of the
103 * pixels are not used. For instance, a texture of size 4x2 will be
104 * placed in the upper half of a 4x4 block, and the lower half of the
105 * pixels in the block will not be accessed.
106 *
107 * \param src_width in pixels
108 * \param src_height in pixels
109 * \param dst_stride in bytes
110 */
111 void
112 _mesa_etc1_unpack_rgba8888(uint8_t *dst_row,
113 unsigned dst_stride,
114 const uint8_t *src_row,
115 unsigned src_stride,
116 unsigned src_width,
117 unsigned src_height)
118 {
119 etc1_unpack_rgba8888(dst_row, dst_stride,
120 src_row, src_stride,
121 src_width, src_height);
122 }
123
124 static uint8_t
125 etc2_base_color1_t_mode(const uint8_t *in, GLuint index)
126 {
127 uint8_t R1a = 0, x = 0;
128 /* base col 1 = extend_4to8bits( (R1a << 2) | R1b, G1, B1) */
129 switch(index) {
130 case 0:
131 R1a = (in[0] >> 3) & 0x3;
132 x = ((R1a << 2) | (in[0] & 0x3));
133 break;
134 case 1:
135 x = ((in[1] >> 4) & 0xf);
136 break;
137 case 2:
138 x = (in[1] & 0xf);
139 break;
140 default:
141 /* invalid index */
142 break;
143 }
144 return ((x << 4) | (x & 0xf));
145 }
146
147 static uint8_t
148 etc2_base_color2_t_mode(const uint8_t *in, GLuint index)
149 {
150 uint8_t x = 0;
151 /*extend 4to8bits(R2, G2, B2)*/
152 switch(index) {
153 case 0:
154 x = ((in[2] >> 4) & 0xf );
155 break;
156 case 1:
157 x = (in[2] & 0xf);
158 break;
159 case 2:
160 x = ((in[3] >> 4) & 0xf);
161 break;
162 default:
163 /* invalid index */
164 break;
165 }
166 return ((x << 4) | (x & 0xf));
167 }
168
169 static uint8_t
170 etc2_base_color1_h_mode(const uint8_t *in, GLuint index)
171 {
172 uint8_t x = 0;
173 /* base col 1 = extend 4to8bits(R1, (G1a << 1) | G1b, (B1a << 3) | B1b) */
174 switch(index) {
175 case 0:
176 x = ((in[0] >> 3) & 0xf);
177 break;
178 case 1:
179 x = (((in[0] & 0x7) << 1) | ((in[1] >> 4) & 0x1));
180 break;
181 case 2:
182 x = ((in[1] & 0x8) |
183 (((in[1] & 0x3) << 1) | ((in[2] >> 7) & 0x1)));
184 break;
185 default:
186 /* invalid index */
187 break;
188 }
189 return ((x << 4) | (x & 0xf));
190 }
191
192 static uint8_t
193 etc2_base_color2_h_mode(const uint8_t *in, GLuint index)
194 {
195 uint8_t x = 0;
196 /* base col 2 = extend 4to8bits(R2, G2, B2) */
197 switch(index) {
198 case 0:
199 x = ((in[2] >> 3) & 0xf );
200 break;
201 case 1:
202 x = (((in[2] & 0x7) << 1) | ((in[3] >> 7) & 0x1));
203 break;
204 case 2:
205 x = ((in[3] >> 3) & 0xf);
206 break;
207 default:
208 /* invalid index */
209 break;
210 }
211 return ((x << 4) | (x & 0xf));
212 }
213
214 static uint8_t
215 etc2_base_color_o_planar(const uint8_t *in, GLuint index)
216 {
217 GLuint tmp;
218 switch(index) {
219 case 0:
220 tmp = ((in[0] >> 1) & 0x3f); /* RO */
221 return ((tmp << 2) | (tmp >> 4));
222 case 1:
223 tmp = (((in[0] & 0x1) << 6) | /* GO1 */
224 ((in[1] >> 1) & 0x3f)); /* GO2 */
225 return ((tmp << 1) | (tmp >> 6));
226 case 2:
227 tmp = (((in[1] & 0x1) << 5) | /* BO1 */
228 (in[2] & 0x18) | /* BO2 */
229 (((in[2] & 0x3) << 1) | ((in[3] >> 7) & 0x1))); /* BO3 */
230 return ((tmp << 2) | (tmp >> 4));
231 default:
232 /* invalid index */
233 return 0;
234 }
235 }
236
237 static uint8_t
238 etc2_base_color_h_planar(const uint8_t *in, GLuint index)
239 {
240 GLuint tmp;
241 switch(index) {
242 case 0:
243 tmp = (((in[3] & 0x7c) >> 1) | /* RH1 */
244 (in[3] & 0x1)); /* RH2 */
245 return ((tmp << 2) | (tmp >> 4));
246 case 1:
247 tmp = (in[4] >> 1) & 0x7f; /* GH */
248 return ((tmp << 1) | (tmp >> 6));
249 case 2:
250 tmp = (((in[4] & 0x1) << 5) |
251 ((in[5] >> 3) & 0x1f)); /* BH */
252 return ((tmp << 2) | (tmp >> 4));
253 default:
254 /* invalid index */
255 return 0;
256 }
257 }
258
259 static uint8_t
260 etc2_base_color_v_planar(const uint8_t *in, GLuint index)
261 {
262 GLuint tmp;
263 switch(index) {
264 case 0:
265 tmp = (((in[5] & 0x7) << 0x3) |
266 ((in[6] >> 5) & 0x7)); /* RV */
267 return ((tmp << 2) | (tmp >> 4));
268 case 1:
269 tmp = (((in[6] & 0x1f) << 2) |
270 ((in[7] >> 6) & 0x3)); /* GV */
271 return ((tmp << 1) | (tmp >> 6));
272 case 2:
273 tmp = in[7] & 0x3f; /* BV */
274 return ((tmp << 2) | (tmp >> 4));
275 default:
276 /* invalid index */
277 return 0;
278 }
279 }
280
281 static uint8_t
282 etc2_clamp(int color)
283 {
284 /* CLAMP(color, 0, 255) */
285 return (uint8_t) CLAMP(color, 0, 255);
286 }
287
288 static void
289 etc2_rgb8_parse_block(struct etc2_block *block, const uint8_t *src)
290 {
291 unsigned i;
292 GLboolean diffbit = src[3] & 0x2;
293 static const int lookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 };
294
295 const int R_plus_dR = (src[0] >> 3) + lookup[src[0] & 0x7];
296 const int G_plus_dG = (src[1] >> 3) + lookup[src[1] & 0x7];
297 const int B_plus_dB = (src[2] >> 3) + lookup[src[2] & 0x7];
298
299 /* Reset the mode flags */
300 block->is_ind_mode = false;
301 block->is_diff_mode = false;
302 block->is_t_mode = false;
303 block->is_h_mode = false;
304 block->is_planar_mode = false;
305
306 if (!diffbit) {
307 /* individual mode */
308 block->is_ind_mode = true;
309
310 for (i = 0; i < 3; i++) {
311 /* Texture decode algorithm is same for individual mode in etc1
312 * & etc2.
313 */
314 block->base_colors[0][i] = etc1_base_color_ind_hi(src[i]);
315 block->base_colors[1][i] = etc1_base_color_ind_lo(src[i]);
316 }
317 }
318 else if (R_plus_dR < 0 || R_plus_dR > 31){
319 /* T mode */
320 block->is_t_mode = true;
321
322 for(i = 0; i < 3; i++) {
323 block->base_colors[0][i] = etc2_base_color1_t_mode(src, i);
324 block->base_colors[1][i] = etc2_base_color2_t_mode(src, i);
325 }
326 /* pick distance */
327 block->distance =
328 etc2_distance_table[(((src[3] >> 2) & 0x3) << 1) |
329 (src[3] & 0x1)];
330
331 for (i = 0; i < 3; i++) {
332 block->paint_colors[0][i] = etc2_clamp(block->base_colors[0][i]);
333 block->paint_colors[1][i] = etc2_clamp(block->base_colors[1][i] +
334 block->distance);
335 block->paint_colors[2][i] = etc2_clamp(block->base_colors[1][i]);
336 block->paint_colors[3][i] = etc2_clamp(block->base_colors[1][i] -
337 block->distance);
338 }
339 }
340 else if (G_plus_dG < 0 || G_plus_dG > 31){
341 /* H mode */
342 block->is_h_mode = true;
343 int base_color_1_value, base_color_2_value;
344
345 for(i = 0; i < 3; i++) {
346 block->base_colors[0][i] = etc2_base_color1_h_mode(src, i);
347 block->base_colors[1][i] = etc2_base_color2_h_mode(src, i);
348 }
349
350 base_color_1_value = (block->base_colors[0][0] << 16) +
351 (block->base_colors[0][1] << 8) +
352 block->base_colors[0][2];
353 base_color_2_value = (block->base_colors[1][0] << 16) +
354 (block->base_colors[1][1] << 8) +
355 block->base_colors[1][2];
356 /* pick distance */
357 block->distance =
358 etc2_distance_table[(src[3] & 0x4) |
359 ((src[3] & 0x1) << 1) |
360 (base_color_1_value >= base_color_2_value)];
361
362 for (i = 0; i < 3; i++) {
363 block->paint_colors[0][i] = etc2_clamp(block->base_colors[0][i] +
364 block->distance);
365 block->paint_colors[1][i] = etc2_clamp(block->base_colors[0][i] -
366 block->distance);
367 block->paint_colors[2][i] = etc2_clamp(block->base_colors[1][i] +
368 block->distance);
369 block->paint_colors[3][i] = etc2_clamp(block->base_colors[1][i] -
370 block->distance);
371 }
372 }
373 else if (B_plus_dB < 0 || B_plus_dB > 31){
374 /* Planar mode */
375 block->is_planar_mode = true;
376
377 for (i = 0; i < 3; i++) {
378 block->base_colors[0][i] = etc2_base_color_o_planar(src, i);
379 block->base_colors[1][i] = etc2_base_color_h_planar(src, i);
380 block->base_colors[2][i] = etc2_base_color_v_planar(src, i);
381 }
382 }
383 else if (diffbit) {
384 /* differential mode */
385 block->is_diff_mode = true;
386
387 for (i = 0; i < 3; i++) {
388 /* Texture decode algorithm is same for differential mode in etc1
389 * & etc2.
390 */
391 block->base_colors[0][i] = etc1_base_color_diff_hi(src[i]);
392 block->base_colors[1][i] = etc1_base_color_diff_lo(src[i]);
393 }
394 }
395
396 if (block->is_ind_mode || block->is_diff_mode) {
397 /* pick modifier tables. same for etc1 & etc2 textures */
398 block->modifier_tables[0] = etc1_modifier_tables[(src[3] >> 5) & 0x7];
399 block->modifier_tables[1] = etc1_modifier_tables[(src[3] >> 2) & 0x7];
400 block->flipped = (src[3] & 0x1);
401 }
402
403 block->pixel_indices =
404 (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7];
405 }
406
407 static void
408 etc2_rgb8_fetch_texel(const struct etc2_block *block,
409 int x, int y, uint8_t *dst)
410 {
411 const uint8_t *base_color;
412 int modifier, bit, idx, blk;
413
414 /* get pixel index */
415 bit = y + x * 4;
416 idx = ((block->pixel_indices >> (15 + bit)) & 0x2) |
417 ((block->pixel_indices >> (bit)) & 0x1);
418
419 if (block->is_ind_mode || block->is_diff_mode) {
420 /* Use pixel index and subblock to get the modifier */
421 blk = (block->flipped) ? (y >= 2) : (x >= 2);
422 base_color = block->base_colors[blk];
423 modifier = block->modifier_tables[blk][idx];
424
425 dst[0] = etc2_clamp(base_color[0] + modifier);
426 dst[1] = etc2_clamp(base_color[1] + modifier);
427 dst[2] = etc2_clamp(base_color[2] + modifier);
428 }
429 else if (block->is_t_mode || block->is_h_mode) {
430 /* Use pixel index to pick one of the paint colors */
431 dst[0] = block->paint_colors[idx][0];
432 dst[1] = block->paint_colors[idx][1];
433 dst[2] = block->paint_colors[idx][2];
434 }
435 else if (block->is_planar_mode) {
436 /* {R(x, y) = clamp255((x × (RH − RO) + y × (RV − RO) + 4 × RO + 2) >> 2)
437 * {G(x, y) = clamp255((x × (GH − GO) + y × (GV − GO) + 4 × GO + 2) >> 2)
438 * {B(x, y) = clamp255((x × (BH − BO) + y × (BV − BO) + 4 × BO + 2) >> 2)
439 */
440 int red, green, blue;
441 red = (x * (block->base_colors[1][0] - block->base_colors[0][0]) +
442 y * (block->base_colors[2][0] - block->base_colors[0][0]) +
443 4 * block->base_colors[0][0] + 2) >> 2;
444
445 green = (x * (block->base_colors[1][1] - block->base_colors[0][1]) +
446 y * (block->base_colors[2][1] - block->base_colors[0][1]) +
447 4 * block->base_colors[0][1] + 2) >> 2;
448
449 blue = (x * (block->base_colors[1][2] - block->base_colors[0][2]) +
450 y * (block->base_colors[2][2] - block->base_colors[0][2]) +
451 4 * block->base_colors[0][2] + 2) >> 2;
452
453 dst[0] = etc2_clamp(red);
454 dst[1] = etc2_clamp(green);
455 dst[2] = etc2_clamp(blue);
456 }
457 }
458
459 static void
460 etc2_unpack_rgb8(uint8_t *dst_row,
461 unsigned dst_stride,
462 const uint8_t *src_row,
463 unsigned src_stride,
464 unsigned width,
465 unsigned height)
466 {
467 const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
468 struct etc2_block block;
469 unsigned x, y, i, j;
470
471 for (y = 0; y < height; y += bh) {
472 const uint8_t *src = src_row;
473
474 for (x = 0; x < width; x+= bw) {
475 etc2_rgb8_parse_block(&block, src);
476
477 for (j = 0; j < bh; j++) {
478 uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
479 for (i = 0; i < bw; i++) {
480 etc2_rgb8_fetch_texel(&block, i, j, dst);
481 dst[3] = 255;
482 dst += comps;
483 }
484 }
485
486 src += bs;
487 }
488
489 src_row += src_stride;
490 }
491 }
492
493 /* ETC2 texture formats are valid in glCompressedTexImage2D and
494 * glCompressedTexSubImage2D functions */
495 GLboolean
496 _mesa_texstore_etc2_rgb8(TEXSTORE_PARAMS)
497 {
498 ASSERT(0);
499
500 return GL_FALSE;
501 }
502
503 void
504 _mesa_fetch_texel_2d_f_etc2_rgb8(const struct swrast_texture_image *texImage,
505 GLint i, GLint j, GLint k, GLfloat *texel)
506 {
507 struct etc2_block block;
508 uint8_t dst[3];
509 const uint8_t *src;
510
511 src = texImage->Map +
512 (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
513
514 etc2_rgb8_parse_block(&block, src);
515 etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst);
516
517 texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]);
518 texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]);
519 texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]);
520 texel[ACOMP] = 1.0f;
521 }
522
523
524 /**
525 * Decode texture data in format `MESA_FORMAT_ETC2_RGB8`
526 *
527 * The size of the source data must be a multiple of the ETC2 block size
528 * even if the texture image's dimensions are not aligned to 4.
529 *
530 * \param src_width in pixels
531 * \param src_height in pixels
532 * \param dst_stride in bytes
533 */
534
535 void
536 _mesa_unpack_etc2_format(uint8_t *dst_row,
537 unsigned dst_stride,
538 const uint8_t *src_row,
539 unsigned src_stride,
540 unsigned src_width,
541 unsigned src_height,
542 gl_format format)
543 {
544 etc2_unpack_rgb8(dst_row, dst_stride,
545 src_row, src_stride,
546 src_width, src_height);
547 }