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