1848b8605Smrg/*
2848b8605Smrg * Copyright (C) 2011 LunarG, Inc.
3848b8605Smrg *
4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5848b8605Smrg * copy of this software and associated documentation files (the "Software"),
6848b8605Smrg * to deal in the Software without restriction, including without limitation
7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
9848b8605Smrg * Software is furnished to do so, subject to the following conditions:
10848b8605Smrg *
11848b8605Smrg * The above copyright notice and this permission notice (including the next
12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the
13848b8605Smrg * Software.
14848b8605Smrg *
15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21848b8605Smrg * DEALINGS IN THE SOFTWARE.
22848b8605Smrg */
23848b8605Smrg
24848b8605Smrg/**
25848b8605Smrg * \file texcompress_etc.c
26848b8605Smrg * GL_OES_compressed_ETC1_RGB8_texture support.
27848b8605Smrg * Supported ETC2 texture formats are:
28848b8605Smrg * GL_COMPRESSED_RGB8_ETC2
29848b8605Smrg * GL_COMPRESSED_SRGB8_ETC2
30848b8605Smrg * GL_COMPRESSED_RGBA8_ETC2_EAC
31848b8605Smrg * GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
32848b8605Smrg * GL_COMPRESSED_R11_EAC
33848b8605Smrg * GL_COMPRESSED_RG11_EAC
34848b8605Smrg * GL_COMPRESSED_SIGNED_R11_EAC
35848b8605Smrg * GL_COMPRESSED_SIGNED_RG11_EAC
36848b8605Smrg * MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1
37848b8605Smrg * MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1
38848b8605Smrg */
39848b8605Smrg
40848b8605Smrg#include <stdbool.h>
41848b8605Smrg#include "texcompress.h"
42848b8605Smrg#include "texcompress_etc.h"
43848b8605Smrg#include "texstore.h"
44b8e80941Smrg#include "config.h"
45848b8605Smrg#include "macros.h"
46848b8605Smrg#include "format_unpack.h"
47848b8605Smrg#include "util/format_srgb.h"
48848b8605Smrg
49848b8605Smrg
50848b8605Smrgstruct etc2_block {
51848b8605Smrg   int distance;
52848b8605Smrg   uint64_t pixel_indices[2];
53848b8605Smrg   const int *modifier_tables[2];
54848b8605Smrg   bool flipped;
55848b8605Smrg   bool opaque;
56848b8605Smrg   bool is_ind_mode;
57848b8605Smrg   bool is_diff_mode;
58848b8605Smrg   bool is_t_mode;
59848b8605Smrg   bool is_h_mode;
60848b8605Smrg   bool is_planar_mode;
61848b8605Smrg   uint8_t base_colors[3][3];
62848b8605Smrg   uint8_t paint_colors[4][3];
63848b8605Smrg   uint8_t base_codeword;
64848b8605Smrg   uint8_t multiplier;
65848b8605Smrg   uint8_t table_index;
66848b8605Smrg};
67848b8605Smrg
68848b8605Smrgstatic const int etc2_distance_table[8] = {
69848b8605Smrg   3, 6, 11, 16, 23, 32, 41, 64 };
70848b8605Smrg
71848b8605Smrgstatic const int etc2_modifier_tables[16][8] = {
72848b8605Smrg   {  -3,   -6,   -9,  -15,   2,   5,   8,   14},
73848b8605Smrg   {  -3,   -7,  -10,  -13,   2,   6,   9,   12},
74848b8605Smrg   {  -2,   -5,   -8,  -13,   1,   4,   7,   12},
75848b8605Smrg   {  -2,   -4,   -6,  -13,   1,   3,   5,   12},
76848b8605Smrg   {  -3,   -6,   -8,  -12,   2,   5,   7,   11},
77848b8605Smrg   {  -3,   -7,   -9,  -11,   2,   6,   8,   10},
78848b8605Smrg   {  -4,   -7,   -8,  -11,   3,   6,   7,   10},
79848b8605Smrg   {  -3,   -5,   -8,  -11,   2,   4,   7,   10},
80848b8605Smrg   {  -2,   -6,   -8,  -10,   1,   5,   7,    9},
81848b8605Smrg   {  -2,   -5,   -8,  -10,   1,   4,   7,    9},
82848b8605Smrg   {  -2,   -4,   -8,  -10,   1,   3,   7,    9},
83848b8605Smrg   {  -2,   -5,   -7,  -10,   1,   4,   6,    9},
84848b8605Smrg   {  -3,   -4,   -7,  -10,   2,   3,   6,    9},
85848b8605Smrg   {  -1,   -2,   -3,  -10,   0,   1,   2,    9},
86848b8605Smrg   {  -4,   -6,   -8,   -9,   3,   5,   7,    8},
87848b8605Smrg   {  -3,   -5,   -7,   -9,   2,   4,   6,    8},
88848b8605Smrg};
89848b8605Smrg
90848b8605Smrgstatic const int etc2_modifier_tables_non_opaque[8][4] = {
91848b8605Smrg   { 0,   8,   0,    -8},
92848b8605Smrg   { 0,   17,  0,   -17},
93848b8605Smrg   { 0,   29,  0,   -29},
94848b8605Smrg   { 0,   42,  0,   -42},
95848b8605Smrg   { 0,   60,  0,   -60},
96848b8605Smrg   { 0,   80,  0,   -80},
97848b8605Smrg   { 0,   106, 0,  -106},
98848b8605Smrg   { 0,   183, 0,  -183}
99848b8605Smrg};
100848b8605Smrg
101848b8605Smrg/* define etc1_parse_block and etc. */
102848b8605Smrg#define UINT8_TYPE GLubyte
103848b8605Smrg#define TAG(x) x
104848b8605Smrg#include "texcompress_etc_tmp.h"
105848b8605Smrg#undef TAG
106848b8605Smrg#undef UINT8_TYPE
107848b8605Smrg
108848b8605SmrgGLboolean
109b8e80941Smrg_mesa_texstore_etc1_rgb8(UNUSED_TEXSTORE_PARAMS)
110848b8605Smrg{
111848b8605Smrg   /* GL_ETC1_RGB8_OES is only valid in glCompressedTexImage2D */
112b8e80941Smrg   assert(0);
113848b8605Smrg
114848b8605Smrg   return GL_FALSE;
115848b8605Smrg}
116848b8605Smrg
117848b8605Smrg
118848b8605Smrg/**
119848b8605Smrg * Decode texture data in format `MESA_FORMAT_ETC1_RGB8` to
120848b8605Smrg * `MESA_FORMAT_ABGR8888`.
121848b8605Smrg *
122848b8605Smrg * The size of the source data must be a multiple of the ETC1 block size,
123848b8605Smrg * which is 8, even if the texture image's dimensions are not aligned to 4.
124848b8605Smrg * From the GL_OES_compressed_ETC1_RGB8_texture spec:
125848b8605Smrg *   The texture is described as a number of 4x4 pixel blocks. If the
126848b8605Smrg *   texture (or a particular mip-level) is smaller than 4 pixels in
127848b8605Smrg *   any dimension (such as a 2x2 or a 8x1 texture), the texture is
128848b8605Smrg *   found in the upper left part of the block(s), and the rest of the
129848b8605Smrg *   pixels are not used. For instance, a texture of size 4x2 will be
130848b8605Smrg *   placed in the upper half of a 4x4 block, and the lower half of the
131848b8605Smrg *   pixels in the block will not be accessed.
132848b8605Smrg *
133848b8605Smrg * \param src_width in pixels
134848b8605Smrg * \param src_height in pixels
135848b8605Smrg * \param dst_stride in bytes
136848b8605Smrg */
137848b8605Smrgvoid
138848b8605Smrg_mesa_etc1_unpack_rgba8888(uint8_t *dst_row,
139848b8605Smrg                           unsigned dst_stride,
140848b8605Smrg                           const uint8_t *src_row,
141848b8605Smrg                           unsigned src_stride,
142848b8605Smrg                           unsigned src_width,
143848b8605Smrg                           unsigned src_height)
144848b8605Smrg{
145848b8605Smrg   etc1_unpack_rgba8888(dst_row, dst_stride,
146848b8605Smrg                        src_row, src_stride,
147848b8605Smrg                        src_width, src_height);
148848b8605Smrg}
149848b8605Smrg
150848b8605Smrgstatic uint8_t
151848b8605Smrgetc2_base_color1_t_mode(const uint8_t *in, GLuint index)
152848b8605Smrg{
153848b8605Smrg   uint8_t R1a = 0, x = 0;
154848b8605Smrg   /* base col 1 = extend_4to8bits( (R1a << 2) | R1b, G1, B1) */
155848b8605Smrg   switch(index) {
156848b8605Smrg   case 0:
157848b8605Smrg      R1a = (in[0] >> 3) & 0x3;
158848b8605Smrg      x = ((R1a << 2) | (in[0] & 0x3));
159848b8605Smrg      break;
160848b8605Smrg   case 1:
161848b8605Smrg      x = ((in[1] >> 4) & 0xf);
162848b8605Smrg      break;
163848b8605Smrg   case 2:
164848b8605Smrg      x = (in[1] & 0xf);
165848b8605Smrg      break;
166848b8605Smrg   default:
167848b8605Smrg      /* invalid index */
168848b8605Smrg      break;
169848b8605Smrg   }
170848b8605Smrg   return ((x << 4) | (x & 0xf));
171848b8605Smrg}
172848b8605Smrg
173848b8605Smrgstatic uint8_t
174848b8605Smrgetc2_base_color2_t_mode(const uint8_t *in, GLuint index)
175848b8605Smrg{
176848b8605Smrg   uint8_t x = 0;
177848b8605Smrg   /*extend 4to8bits(R2, G2, B2)*/
178848b8605Smrg   switch(index) {
179848b8605Smrg   case 0:
180848b8605Smrg      x = ((in[2] >> 4) & 0xf );
181848b8605Smrg      break;
182848b8605Smrg   case 1:
183848b8605Smrg      x = (in[2] & 0xf);
184848b8605Smrg      break;
185848b8605Smrg   case 2:
186848b8605Smrg      x = ((in[3] >> 4) & 0xf);
187848b8605Smrg      break;
188848b8605Smrg   default:
189848b8605Smrg      /* invalid index */
190848b8605Smrg      break;
191848b8605Smrg   }
192848b8605Smrg   return ((x << 4) | (x & 0xf));
193848b8605Smrg}
194848b8605Smrg
195848b8605Smrgstatic uint8_t
196848b8605Smrgetc2_base_color1_h_mode(const uint8_t *in, GLuint index)
197848b8605Smrg{
198848b8605Smrg   uint8_t x = 0;
199848b8605Smrg   /* base col 1 = extend 4to8bits(R1, (G1a << 1) | G1b, (B1a << 3) | B1b) */
200848b8605Smrg   switch(index) {
201848b8605Smrg   case 0:
202848b8605Smrg      x = ((in[0] >> 3) & 0xf);
203848b8605Smrg      break;
204848b8605Smrg   case 1:
205848b8605Smrg      x = (((in[0] & 0x7) << 1) | ((in[1] >> 4) & 0x1));
206848b8605Smrg      break;
207848b8605Smrg   case 2:
208848b8605Smrg      x = ((in[1] & 0x8) |
209848b8605Smrg           (((in[1] & 0x3) << 1) | ((in[2] >> 7) & 0x1)));
210848b8605Smrg      break;
211848b8605Smrg   default:
212848b8605Smrg      /* invalid index */
213848b8605Smrg      break;
214848b8605Smrg   }
215848b8605Smrg   return ((x << 4) | (x & 0xf));
216848b8605Smrg}
217848b8605Smrg
218848b8605Smrgstatic uint8_t
219848b8605Smrgetc2_base_color2_h_mode(const uint8_t *in, GLuint index)
220848b8605Smrg{
221848b8605Smrg   uint8_t x = 0;
222848b8605Smrg   /* base col 2 = extend 4to8bits(R2, G2, B2) */
223848b8605Smrg   switch(index) {
224848b8605Smrg   case 0:
225848b8605Smrg      x = ((in[2] >> 3) & 0xf );
226848b8605Smrg      break;
227848b8605Smrg   case 1:
228848b8605Smrg      x = (((in[2] & 0x7) << 1) | ((in[3] >> 7) & 0x1));
229848b8605Smrg      break;
230848b8605Smrg   case 2:
231848b8605Smrg      x = ((in[3] >> 3) & 0xf);
232848b8605Smrg      break;
233848b8605Smrg   default:
234848b8605Smrg      /* invalid index */
235848b8605Smrg      break;
236848b8605Smrg   }
237848b8605Smrg   return ((x << 4) | (x & 0xf));
238848b8605Smrg}
239848b8605Smrg
240848b8605Smrgstatic uint8_t
241848b8605Smrgetc2_base_color_o_planar(const uint8_t *in, GLuint index)
242848b8605Smrg{
243848b8605Smrg   GLuint tmp;
244848b8605Smrg   switch(index) {
245848b8605Smrg   case 0:
246848b8605Smrg      tmp = ((in[0] >> 1) & 0x3f); /* RO */
247848b8605Smrg      return ((tmp << 2) | (tmp >> 4));
248848b8605Smrg   case 1:
249848b8605Smrg      tmp = (((in[0] & 0x1) << 6) | /* GO1 */
250848b8605Smrg             ((in[1] >> 1) & 0x3f)); /* GO2 */
251848b8605Smrg      return ((tmp << 1) | (tmp >> 6));
252848b8605Smrg   case 2:
253848b8605Smrg      tmp = (((in[1] & 0x1) << 5) | /* BO1 */
254848b8605Smrg             (in[2] & 0x18) | /* BO2 */
255848b8605Smrg             (((in[2] & 0x3) << 1) | ((in[3] >> 7) & 0x1))); /* BO3 */
256848b8605Smrg      return ((tmp << 2) | (tmp >> 4));
257848b8605Smrg    default:
258848b8605Smrg      /* invalid index */
259848b8605Smrg      return 0;
260848b8605Smrg   }
261848b8605Smrg}
262848b8605Smrg
263848b8605Smrgstatic uint8_t
264848b8605Smrgetc2_base_color_h_planar(const uint8_t *in, GLuint index)
265848b8605Smrg{
266848b8605Smrg   GLuint tmp;
267848b8605Smrg   switch(index) {
268848b8605Smrg   case 0:
269848b8605Smrg      tmp = (((in[3] & 0x7c) >> 1) | /* RH1 */
270848b8605Smrg             (in[3] & 0x1));         /* RH2 */
271848b8605Smrg      return ((tmp << 2) | (tmp >> 4));
272848b8605Smrg   case 1:
273848b8605Smrg      tmp = (in[4] >> 1) & 0x7f; /* GH */
274848b8605Smrg      return ((tmp << 1) | (tmp >> 6));
275848b8605Smrg   case 2:
276848b8605Smrg      tmp = (((in[4] & 0x1) << 5) |
277848b8605Smrg             ((in[5] >> 3) & 0x1f)); /* BH */
278848b8605Smrg      return ((tmp << 2) | (tmp >> 4));
279848b8605Smrg   default:
280848b8605Smrg      /* invalid index */
281848b8605Smrg      return 0;
282848b8605Smrg   }
283848b8605Smrg}
284848b8605Smrg
285848b8605Smrgstatic uint8_t
286848b8605Smrgetc2_base_color_v_planar(const uint8_t *in, GLuint index)
287848b8605Smrg{
288848b8605Smrg   GLuint tmp;
289848b8605Smrg   switch(index) {
290848b8605Smrg   case 0:
291848b8605Smrg      tmp = (((in[5] & 0x7) << 0x3) |
292848b8605Smrg             ((in[6] >> 5) & 0x7)); /* RV */
293848b8605Smrg      return ((tmp << 2) | (tmp >> 4));
294848b8605Smrg   case 1:
295848b8605Smrg      tmp = (((in[6] & 0x1f) << 2) |
296848b8605Smrg             ((in[7] >> 6) & 0x3)); /* GV */
297848b8605Smrg      return ((tmp << 1) | (tmp >> 6));
298848b8605Smrg   case 2:
299848b8605Smrg      tmp = in[7] & 0x3f; /* BV */
300848b8605Smrg      return ((tmp << 2) | (tmp >> 4));
301848b8605Smrg   default:
302848b8605Smrg      /* invalid index */
303848b8605Smrg      return 0;
304848b8605Smrg   }
305848b8605Smrg}
306848b8605Smrg
307848b8605Smrgstatic GLint
308848b8605Smrgetc2_get_pixel_index(const struct etc2_block *block, int x, int y)
309848b8605Smrg{
310848b8605Smrg   int bit = ((3 - y) + (3 - x) * 4) * 3;
311848b8605Smrg   int idx = (block->pixel_indices[1] >> bit) & 0x7;
312848b8605Smrg   return idx;
313848b8605Smrg}
314848b8605Smrg
315848b8605Smrgstatic uint8_t
316848b8605Smrgetc2_clamp(int color)
317848b8605Smrg{
318848b8605Smrg   /* CLAMP(color, 0, 255) */
319848b8605Smrg   return (uint8_t) CLAMP(color, 0, 255);
320848b8605Smrg}
321848b8605Smrg
322848b8605Smrgstatic GLushort
323848b8605Smrgetc2_clamp2(int color)
324848b8605Smrg{
325848b8605Smrg   /* CLAMP(color, 0, 2047) */
326848b8605Smrg   return (GLushort) CLAMP(color, 0, 2047);
327848b8605Smrg}
328848b8605Smrg
329848b8605Smrgstatic GLshort
330848b8605Smrgetc2_clamp3(int color)
331848b8605Smrg{
332848b8605Smrg   /* CLAMP(color, -1023, 1023) */
333848b8605Smrg   return (GLshort) CLAMP(color, -1023, 1023);
334848b8605Smrg}
335848b8605Smrg
336848b8605Smrgstatic void
337848b8605Smrgetc2_rgb8_parse_block(struct etc2_block *block,
338848b8605Smrg                      const uint8_t *src,
339848b8605Smrg                      GLboolean punchthrough_alpha)
340848b8605Smrg{
341848b8605Smrg   unsigned i;
342848b8605Smrg   GLboolean diffbit = false;
343848b8605Smrg   static const int lookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 };
344848b8605Smrg
345848b8605Smrg   const int R_plus_dR = (src[0] >> 3) + lookup[src[0] & 0x7];
346848b8605Smrg   const int G_plus_dG = (src[1] >> 3) + lookup[src[1] & 0x7];
347848b8605Smrg   const int B_plus_dB = (src[2] >> 3) + lookup[src[2] & 0x7];
348848b8605Smrg
349848b8605Smrg   /* Reset the mode flags */
350848b8605Smrg   block->is_ind_mode = false;
351848b8605Smrg   block->is_diff_mode = false;
352848b8605Smrg   block->is_t_mode = false;
353848b8605Smrg   block->is_h_mode = false;
354848b8605Smrg   block->is_planar_mode = false;
355848b8605Smrg
356848b8605Smrg   if (punchthrough_alpha)
357848b8605Smrg      block->opaque = src[3] & 0x2;
358848b8605Smrg   else
359848b8605Smrg      diffbit = src[3] & 0x2;
360848b8605Smrg
361848b8605Smrg   if (!diffbit && !punchthrough_alpha) {
362848b8605Smrg      /* individual mode */
363848b8605Smrg      block->is_ind_mode = true;
364848b8605Smrg
365848b8605Smrg      for (i = 0; i < 3; i++) {
366848b8605Smrg         /* Texture decode algorithm is same for individual mode in etc1
367848b8605Smrg          * & etc2.
368848b8605Smrg          */
369848b8605Smrg         block->base_colors[0][i] = etc1_base_color_ind_hi(src[i]);
370848b8605Smrg         block->base_colors[1][i] = etc1_base_color_ind_lo(src[i]);
371848b8605Smrg      }
372848b8605Smrg   }
373848b8605Smrg   else if (R_plus_dR < 0 || R_plus_dR > 31){
374848b8605Smrg      /* T mode */
375848b8605Smrg      block->is_t_mode = true;
376848b8605Smrg
377848b8605Smrg      for(i = 0; i < 3; i++) {
378848b8605Smrg         block->base_colors[0][i] = etc2_base_color1_t_mode(src, i);
379848b8605Smrg         block->base_colors[1][i] = etc2_base_color2_t_mode(src, i);
380848b8605Smrg      }
381848b8605Smrg      /* pick distance */
382848b8605Smrg      block->distance =
383848b8605Smrg         etc2_distance_table[(((src[3] >> 2) & 0x3) << 1) |
384848b8605Smrg                             (src[3] & 0x1)];
385848b8605Smrg
386848b8605Smrg      for (i = 0; i < 3; i++) {
387848b8605Smrg         block->paint_colors[0][i] = etc2_clamp(block->base_colors[0][i]);
388848b8605Smrg         block->paint_colors[1][i] = etc2_clamp(block->base_colors[1][i] +
389848b8605Smrg                                                block->distance);
390848b8605Smrg         block->paint_colors[2][i] = etc2_clamp(block->base_colors[1][i]);
391848b8605Smrg         block->paint_colors[3][i] = etc2_clamp(block->base_colors[1][i] -
392848b8605Smrg                                                block->distance);
393848b8605Smrg      }
394848b8605Smrg   }
395848b8605Smrg   else if (G_plus_dG < 0 || G_plus_dG > 31){
396848b8605Smrg      int base_color_1_value, base_color_2_value;
397848b8605Smrg
398848b8605Smrg      /* H mode */
399848b8605Smrg      block->is_h_mode = true;
400848b8605Smrg
401848b8605Smrg      for(i = 0; i < 3; i++) {
402848b8605Smrg         block->base_colors[0][i] = etc2_base_color1_h_mode(src, i);
403848b8605Smrg         block->base_colors[1][i] = etc2_base_color2_h_mode(src, i);
404848b8605Smrg      }
405848b8605Smrg
406848b8605Smrg      base_color_1_value = (block->base_colors[0][0] << 16) +
407848b8605Smrg                           (block->base_colors[0][1] << 8) +
408848b8605Smrg                           block->base_colors[0][2];
409848b8605Smrg      base_color_2_value = (block->base_colors[1][0] << 16) +
410848b8605Smrg                           (block->base_colors[1][1] << 8) +
411848b8605Smrg                           block->base_colors[1][2];
412848b8605Smrg      /* pick distance */
413848b8605Smrg      block->distance =
414848b8605Smrg         etc2_distance_table[(src[3] & 0x4) |
415848b8605Smrg                             ((src[3] & 0x1) << 1) |
416848b8605Smrg                             (base_color_1_value >= base_color_2_value)];
417848b8605Smrg
418848b8605Smrg      for (i = 0; i < 3; i++) {
419848b8605Smrg         block->paint_colors[0][i] = etc2_clamp(block->base_colors[0][i] +
420848b8605Smrg                                                block->distance);
421848b8605Smrg         block->paint_colors[1][i] = etc2_clamp(block->base_colors[0][i] -
422848b8605Smrg                                                block->distance);
423848b8605Smrg         block->paint_colors[2][i] = etc2_clamp(block->base_colors[1][i] +
424848b8605Smrg                                                block->distance);
425848b8605Smrg         block->paint_colors[3][i] = etc2_clamp(block->base_colors[1][i] -
426848b8605Smrg                                                block->distance);
427848b8605Smrg      }
428848b8605Smrg   }
429848b8605Smrg   else if (B_plus_dB < 0 || B_plus_dB > 31) {
430848b8605Smrg      /* Planar mode */
431848b8605Smrg      block->is_planar_mode = true;
432848b8605Smrg
433848b8605Smrg      /* opaque bit must be set in planar mode */
434848b8605Smrg      block->opaque = true;
435848b8605Smrg
436848b8605Smrg      for (i = 0; i < 3; i++) {
437848b8605Smrg         block->base_colors[0][i] = etc2_base_color_o_planar(src, i);
438848b8605Smrg         block->base_colors[1][i] = etc2_base_color_h_planar(src, i);
439848b8605Smrg         block->base_colors[2][i] = etc2_base_color_v_planar(src, i);
440848b8605Smrg      }
441848b8605Smrg   }
442848b8605Smrg   else if (diffbit || punchthrough_alpha) {
443848b8605Smrg      /* differential mode */
444848b8605Smrg      block->is_diff_mode = true;
445848b8605Smrg
446848b8605Smrg      for (i = 0; i < 3; i++) {
447848b8605Smrg         /* Texture decode algorithm is same for differential mode in etc1
448848b8605Smrg          * & etc2.
449848b8605Smrg          */
450848b8605Smrg         block->base_colors[0][i] = etc1_base_color_diff_hi(src[i]);
451848b8605Smrg         block->base_colors[1][i] = etc1_base_color_diff_lo(src[i]);
452848b8605Smrg      }
453848b8605Smrg   }
454848b8605Smrg
455848b8605Smrg   if (block->is_ind_mode || block->is_diff_mode) {
456848b8605Smrg      int table1_idx = (src[3] >> 5) & 0x7;
457848b8605Smrg      int table2_idx = (src[3] >> 2) & 0x7;
458848b8605Smrg
459848b8605Smrg      /* Use same modifier tables as for etc1 textures if opaque bit is set
460848b8605Smrg       * or if non punchthrough texture format
461848b8605Smrg       */
462b8e80941Smrg      block->modifier_tables[0] = (!punchthrough_alpha || block->opaque) ?
463848b8605Smrg                                  etc1_modifier_tables[table1_idx] :
464848b8605Smrg                                  etc2_modifier_tables_non_opaque[table1_idx];
465b8e80941Smrg      block->modifier_tables[1] = (!punchthrough_alpha || block->opaque) ?
466848b8605Smrg                                  etc1_modifier_tables[table2_idx] :
467848b8605Smrg                                  etc2_modifier_tables_non_opaque[table2_idx];
468848b8605Smrg
469848b8605Smrg      block->flipped = (src[3] & 0x1);
470848b8605Smrg   }
471848b8605Smrg
472848b8605Smrg   block->pixel_indices[0] =
473848b8605Smrg      (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7];
474848b8605Smrg}
475848b8605Smrg
476848b8605Smrgstatic void
477848b8605Smrgetc2_rgb8_fetch_texel(const struct etc2_block *block,
478848b8605Smrg                      int x, int y, uint8_t *dst,
479848b8605Smrg                      GLboolean punchthrough_alpha)
480848b8605Smrg{
481848b8605Smrg   const uint8_t *base_color;
482848b8605Smrg   int modifier, bit, idx, blk;
483848b8605Smrg
484848b8605Smrg   /* get pixel index */
485848b8605Smrg   bit = y + x * 4;
486848b8605Smrg   idx = ((block->pixel_indices[0] >> (15 + bit)) & 0x2) |
487848b8605Smrg         ((block->pixel_indices[0] >>      (bit)) & 0x1);
488848b8605Smrg
489848b8605Smrg   if (block->is_ind_mode || block->is_diff_mode) {
490848b8605Smrg      /* check for punchthrough_alpha format */
491848b8605Smrg      if (punchthrough_alpha) {
492848b8605Smrg         if (!block->opaque && idx == 2) {
493848b8605Smrg            dst[0] = dst[1] = dst[2] = dst[3] = 0;
494848b8605Smrg            return;
495848b8605Smrg         }
496848b8605Smrg         else
497848b8605Smrg            dst[3] = 255;
498848b8605Smrg      }
499848b8605Smrg
500848b8605Smrg      /* Use pixel index and subblock to get the modifier */
501848b8605Smrg      blk = (block->flipped) ? (y >= 2) : (x >= 2);
502848b8605Smrg      base_color = block->base_colors[blk];
503848b8605Smrg      modifier = block->modifier_tables[blk][idx];
504848b8605Smrg
505848b8605Smrg      dst[0] = etc2_clamp(base_color[0] + modifier);
506848b8605Smrg      dst[1] = etc2_clamp(base_color[1] + modifier);
507848b8605Smrg      dst[2] = etc2_clamp(base_color[2] + modifier);
508848b8605Smrg   }
509848b8605Smrg   else if (block->is_t_mode || block->is_h_mode) {
510848b8605Smrg      /* check for punchthrough_alpha format */
511848b8605Smrg      if (punchthrough_alpha) {
512848b8605Smrg         if (!block->opaque && idx == 2) {
513848b8605Smrg            dst[0] = dst[1] = dst[2] = dst[3] = 0;
514848b8605Smrg            return;
515848b8605Smrg         }
516848b8605Smrg         else
517848b8605Smrg            dst[3] = 255;
518848b8605Smrg      }
519848b8605Smrg
520848b8605Smrg      /* Use pixel index to pick one of the paint colors */
521848b8605Smrg      dst[0] = block->paint_colors[idx][0];
522848b8605Smrg      dst[1] = block->paint_colors[idx][1];
523848b8605Smrg      dst[2] = block->paint_colors[idx][2];
524848b8605Smrg   }
525848b8605Smrg   else if (block->is_planar_mode) {
526848b8605Smrg      /* {R(x, y) = clamp255((x × (RH − RO) + y × (RV − RO) + 4 × RO + 2) >> 2)
527848b8605Smrg       * {G(x, y) = clamp255((x × (GH − GO) + y × (GV − GO) + 4 × GO + 2) >> 2)
528848b8605Smrg       * {B(x, y) = clamp255((x × (BH − BO) + y × (BV − BO) + 4 × BO + 2) >> 2)
529848b8605Smrg       */
530848b8605Smrg      int red, green, blue;
531848b8605Smrg      red = (x * (block->base_colors[1][0] - block->base_colors[0][0]) +
532848b8605Smrg             y * (block->base_colors[2][0] - block->base_colors[0][0]) +
533848b8605Smrg             4 * block->base_colors[0][0] + 2) >> 2;
534848b8605Smrg
535848b8605Smrg      green = (x * (block->base_colors[1][1] - block->base_colors[0][1]) +
536848b8605Smrg               y * (block->base_colors[2][1] - block->base_colors[0][1]) +
537848b8605Smrg               4 * block->base_colors[0][1] + 2) >> 2;
538848b8605Smrg
539848b8605Smrg      blue = (x * (block->base_colors[1][2] - block->base_colors[0][2]) +
540848b8605Smrg              y * (block->base_colors[2][2] - block->base_colors[0][2]) +
541848b8605Smrg              4 * block->base_colors[0][2] + 2) >> 2;
542848b8605Smrg
543848b8605Smrg      dst[0] = etc2_clamp(red);
544848b8605Smrg      dst[1] = etc2_clamp(green);
545848b8605Smrg      dst[2] = etc2_clamp(blue);
546848b8605Smrg
547848b8605Smrg      /* check for punchthrough_alpha format */
548848b8605Smrg      if (punchthrough_alpha)
549848b8605Smrg         dst[3] = 255;
550848b8605Smrg   }
551848b8605Smrg}
552848b8605Smrg
553848b8605Smrgstatic void
554848b8605Smrgetc2_alpha8_fetch_texel(const struct etc2_block *block,
555848b8605Smrg      int x, int y, uint8_t *dst)
556848b8605Smrg{
557848b8605Smrg   int modifier, alpha, idx;
558848b8605Smrg   /* get pixel index */
559848b8605Smrg   idx = etc2_get_pixel_index(block, x, y);
560848b8605Smrg   modifier = etc2_modifier_tables[block->table_index][idx];
561848b8605Smrg   alpha = block->base_codeword + modifier * block->multiplier;
562848b8605Smrg   dst[3] = etc2_clamp(alpha);
563848b8605Smrg}
564848b8605Smrg
565848b8605Smrgstatic void
566848b8605Smrgetc2_r11_fetch_texel(const struct etc2_block *block,
567848b8605Smrg                     int x, int y, uint8_t *dst)
568848b8605Smrg{
569848b8605Smrg   GLint modifier, idx;
570848b8605Smrg   GLshort color;
571848b8605Smrg   /* Get pixel index */
572848b8605Smrg   idx = etc2_get_pixel_index(block, x, y);
573848b8605Smrg   modifier = etc2_modifier_tables[block->table_index][idx];
574848b8605Smrg
575848b8605Smrg   if (block->multiplier != 0)
576848b8605Smrg      /* clamp2(base codeword × 8 + 4 + modifier × multiplier × 8) */
577848b8605Smrg      color = etc2_clamp2(((block->base_codeword << 3) | 0x4)  +
578848b8605Smrg                          ((modifier * block->multiplier) << 3));
579848b8605Smrg   else
580848b8605Smrg      color = etc2_clamp2(((block->base_codeword << 3) | 0x4)  + modifier);
581848b8605Smrg
582848b8605Smrg   /* Extend 11 bits color value to 16 bits. OpenGL ES 3.0 specification
583848b8605Smrg    * allows extending the color value to any number of bits. But, an
584848b8605Smrg    * implementation is not allowed to truncate the 11-bit value to less than
585848b8605Smrg    * 11 bits."
586848b8605Smrg    */
587848b8605Smrg   color = (color << 5) | (color >> 6);
588848b8605Smrg   ((GLushort *)dst)[0] = color;
589848b8605Smrg}
590848b8605Smrg
591848b8605Smrgstatic void
592848b8605Smrgetc2_signed_r11_fetch_texel(const struct etc2_block *block,
593848b8605Smrg                            int x, int y, uint8_t *dst)
594848b8605Smrg{
595848b8605Smrg   GLint modifier, idx;
596848b8605Smrg   GLshort color;
597848b8605Smrg   GLbyte base_codeword = (GLbyte) block->base_codeword;
598848b8605Smrg
599848b8605Smrg   if (base_codeword == -128)
600848b8605Smrg      base_codeword = -127;
601848b8605Smrg
602848b8605Smrg   /* Get pixel index */
603848b8605Smrg   idx = etc2_get_pixel_index(block, x, y);
604848b8605Smrg   modifier = etc2_modifier_tables[block->table_index][idx];
605848b8605Smrg
606848b8605Smrg   if (block->multiplier != 0)
607848b8605Smrg      /* clamp3(base codeword × 8 + modifier × multiplier × 8) */
608848b8605Smrg      color = etc2_clamp3((base_codeword << 3)  +
609848b8605Smrg                         ((modifier * block->multiplier) << 3));
610848b8605Smrg   else
611848b8605Smrg      color = etc2_clamp3((base_codeword << 3)  + modifier);
612848b8605Smrg
613848b8605Smrg   /* Extend 11 bits color value to 16 bits. OpenGL ES 3.0 specification
614848b8605Smrg    * allows extending the color value to any number of bits. But, an
615848b8605Smrg    * implementation is not allowed to truncate the 11-bit value to less than
616848b8605Smrg    * 11 bits. A negative 11-bit value must first be made positive before bit
617848b8605Smrg    * replication, and then made negative again
618848b8605Smrg    */
619848b8605Smrg   if (color >= 0)
620848b8605Smrg      color = (color << 5) | (color >> 5);
621848b8605Smrg   else {
622848b8605Smrg      color = -color;
623848b8605Smrg      color = (color << 5) | (color >> 5);
624848b8605Smrg      color = -color;
625848b8605Smrg   }
626848b8605Smrg   ((GLshort *)dst)[0] = color;
627848b8605Smrg}
628848b8605Smrg
629848b8605Smrgstatic void
630848b8605Smrgetc2_alpha8_parse_block(struct etc2_block *block, const uint8_t *src)
631848b8605Smrg{
632848b8605Smrg   block->base_codeword = src[0];
633848b8605Smrg   block->multiplier = (src[1] >> 4) & 0xf;
634848b8605Smrg   block->table_index = src[1] & 0xf;
635848b8605Smrg   block->pixel_indices[1] = (((uint64_t)src[2] << 40) |
636848b8605Smrg                              ((uint64_t)src[3] << 32) |
637848b8605Smrg                              ((uint64_t)src[4] << 24) |
638848b8605Smrg                              ((uint64_t)src[5] << 16) |
639848b8605Smrg                              ((uint64_t)src[6] << 8)  |
640848b8605Smrg                              ((uint64_t)src[7]));
641848b8605Smrg}
642848b8605Smrg
643848b8605Smrgstatic void
644848b8605Smrgetc2_r11_parse_block(struct etc2_block *block, const uint8_t *src)
645848b8605Smrg{
646848b8605Smrg   /* Parsing logic remains same as for etc2_alpha8_parse_block */
647848b8605Smrg    etc2_alpha8_parse_block(block, src);
648848b8605Smrg}
649848b8605Smrg
650848b8605Smrgstatic void
651848b8605Smrgetc2_rgba8_parse_block(struct etc2_block *block, const uint8_t *src)
652848b8605Smrg{
653848b8605Smrg   /* RGB component is parsed the same way as for MESA_FORMAT_ETC2_RGB8 */
654848b8605Smrg   etc2_rgb8_parse_block(block, src + 8,
655848b8605Smrg                         false /* punchthrough_alpha */);
656848b8605Smrg   /* Parse Alpha component */
657848b8605Smrg   etc2_alpha8_parse_block(block, src);
658848b8605Smrg}
659848b8605Smrg
660848b8605Smrgstatic void
661848b8605Smrgetc2_rgba8_fetch_texel(const struct etc2_block *block,
662848b8605Smrg      int x, int y, uint8_t *dst)
663848b8605Smrg{
664848b8605Smrg   etc2_rgb8_fetch_texel(block, x, y, dst,
665848b8605Smrg                         false /* punchthrough_alpha */);
666848b8605Smrg   etc2_alpha8_fetch_texel(block, x, y, dst);
667848b8605Smrg}
668848b8605Smrg
669848b8605Smrgstatic void
670848b8605Smrgetc2_unpack_rgb8(uint8_t *dst_row,
671848b8605Smrg                 unsigned dst_stride,
672848b8605Smrg                 const uint8_t *src_row,
673848b8605Smrg                 unsigned src_stride,
674848b8605Smrg                 unsigned width,
675848b8605Smrg                 unsigned height)
676848b8605Smrg{
677848b8605Smrg   const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
678848b8605Smrg   struct etc2_block block;
679848b8605Smrg   unsigned x, y, i, j;
680848b8605Smrg
681848b8605Smrg   for (y = 0; y < height; y += bh) {
682848b8605Smrg      const uint8_t *src = src_row;
683848b8605Smrg      /*
684848b8605Smrg       * Destination texture may not be a multiple of four texels in
685848b8605Smrg       * height. Compute a safe height to avoid writing outside the texture.
686848b8605Smrg       */
687848b8605Smrg      const unsigned h = MIN2(bh, height - y);
688848b8605Smrg
689848b8605Smrg      for (x = 0; x < width; x+= bw) {
690848b8605Smrg         /*
691848b8605Smrg          * Destination texture may not be a multiple of four texels in
692848b8605Smrg          * width. Compute a safe width to avoid writing outside the texture.
693848b8605Smrg          */
694848b8605Smrg         const unsigned w = MIN2(bw, width - x);
695848b8605Smrg
696848b8605Smrg         etc2_rgb8_parse_block(&block, src,
697848b8605Smrg                               false /* punchthrough_alpha */);
698848b8605Smrg
699848b8605Smrg         for (j = 0; j < h; j++) {
700848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
701848b8605Smrg            for (i = 0; i < w; i++) {
702848b8605Smrg               etc2_rgb8_fetch_texel(&block, i, j, dst,
703848b8605Smrg                                     false /* punchthrough_alpha */);
704848b8605Smrg               dst[3] = 255;
705848b8605Smrg               dst += comps;
706848b8605Smrg            }
707848b8605Smrg         }
708848b8605Smrg
709848b8605Smrg         src += bs;
710848b8605Smrg      }
711848b8605Smrg
712848b8605Smrg      src_row += src_stride;
713848b8605Smrg   }
714848b8605Smrg}
715848b8605Smrg
716848b8605Smrgstatic void
717848b8605Smrgetc2_unpack_srgb8(uint8_t *dst_row,
718848b8605Smrg                  unsigned dst_stride,
719848b8605Smrg                  const uint8_t *src_row,
720848b8605Smrg                  unsigned src_stride,
721848b8605Smrg                  unsigned width,
722b8e80941Smrg		  unsigned height,
723b8e80941Smrg		  bool bgra)
724848b8605Smrg{
725848b8605Smrg   const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
726848b8605Smrg   struct etc2_block block;
727848b8605Smrg   unsigned x, y, i, j;
728848b8605Smrg   uint8_t tmp;
729848b8605Smrg
730848b8605Smrg   for (y = 0; y < height; y += bh) {
731848b8605Smrg      const uint8_t *src = src_row;
732848b8605Smrg      const unsigned h = MIN2(bh, height - y);
733848b8605Smrg
734848b8605Smrg      for (x = 0; x < width; x+= bw) {
735848b8605Smrg         const unsigned w = MIN2(bw, width - x);
736848b8605Smrg         etc2_rgb8_parse_block(&block, src,
737848b8605Smrg                               false /* punchthrough_alpha */);
738848b8605Smrg
739848b8605Smrg
740848b8605Smrg         for (j = 0; j < h; j++) {
741848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
742848b8605Smrg            for (i = 0; i < w; i++) {
743848b8605Smrg               etc2_rgb8_fetch_texel(&block, i, j, dst,
744848b8605Smrg                                     false /* punchthrough_alpha */);
745b8e80941Smrg
746b8e80941Smrg	       if (bgra) {
747b8e80941Smrg		  /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
748b8e80941Smrg		  tmp = dst[0];
749b8e80941Smrg		  dst[0] = dst[2];
750b8e80941Smrg		  dst[2] = tmp;
751b8e80941Smrg		  dst[3] = 255;
752b8e80941Smrg	       }
753848b8605Smrg
754848b8605Smrg               dst += comps;
755848b8605Smrg            }
756848b8605Smrg         }
757848b8605Smrg         src += bs;
758848b8605Smrg      }
759848b8605Smrg
760848b8605Smrg      src_row += src_stride;
761848b8605Smrg   }
762848b8605Smrg}
763848b8605Smrg
764848b8605Smrgstatic void
765848b8605Smrgetc2_unpack_rgba8(uint8_t *dst_row,
766848b8605Smrg                  unsigned dst_stride,
767848b8605Smrg                  const uint8_t *src_row,
768848b8605Smrg                  unsigned src_stride,
769848b8605Smrg                  unsigned width,
770848b8605Smrg                  unsigned height)
771848b8605Smrg{
772848b8605Smrg   /* If internalformat is COMPRESSED_RGBA8_ETC2_EAC, each 4 × 4 block of
773848b8605Smrg    * RGBA8888 information is compressed to 128 bits. To decode a block, the
774848b8605Smrg    * two 64-bit integers int64bitAlpha and int64bitColor are calculated.
775848b8605Smrg   */
776848b8605Smrg   const unsigned bw = 4, bh = 4, bs = 16, comps = 4;
777848b8605Smrg   struct etc2_block block;
778848b8605Smrg   unsigned x, y, i, j;
779848b8605Smrg
780848b8605Smrg   for (y = 0; y < height; y += bh) {
781848b8605Smrg      const uint8_t *src = src_row;
782848b8605Smrg      const unsigned h = MIN2(bh, height - y);
783848b8605Smrg
784848b8605Smrg      for (x = 0; x < width; x+= bw) {
785848b8605Smrg         const unsigned w = MIN2(bw, width - x);
786848b8605Smrg         etc2_rgba8_parse_block(&block, src);
787848b8605Smrg
788848b8605Smrg         for (j = 0; j < h; j++) {
789848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
790848b8605Smrg            for (i = 0; i < w; i++) {
791848b8605Smrg               etc2_rgba8_fetch_texel(&block, i, j, dst);
792848b8605Smrg               dst += comps;
793848b8605Smrg            }
794848b8605Smrg         }
795848b8605Smrg         src += bs;
796848b8605Smrg      }
797848b8605Smrg
798848b8605Smrg      src_row += src_stride;
799848b8605Smrg   }
800848b8605Smrg}
801848b8605Smrg
802848b8605Smrgstatic void
803848b8605Smrgetc2_unpack_srgb8_alpha8(uint8_t *dst_row,
804848b8605Smrg                         unsigned dst_stride,
805848b8605Smrg                         const uint8_t *src_row,
806848b8605Smrg                         unsigned src_stride,
807848b8605Smrg                         unsigned width,
808b8e80941Smrg			 unsigned height,
809b8e80941Smrg			 bool bgra)
810848b8605Smrg{
811848b8605Smrg   /* If internalformat is COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, each 4 × 4 block
812848b8605Smrg    * of RGBA8888 information is compressed to 128 bits. To decode a block, the
813848b8605Smrg    * two 64-bit integers int64bitAlpha and int64bitColor are calculated.
814848b8605Smrg    */
815848b8605Smrg   const unsigned bw = 4, bh = 4, bs = 16, comps = 4;
816848b8605Smrg   struct etc2_block block;
817848b8605Smrg   unsigned x, y, i, j;
818848b8605Smrg   uint8_t tmp;
819848b8605Smrg
820848b8605Smrg   for (y = 0; y < height; y += bh) {
821848b8605Smrg      const unsigned h = MIN2(bh, height - y);
822848b8605Smrg      const uint8_t *src = src_row;
823848b8605Smrg
824848b8605Smrg      for (x = 0; x < width; x+= bw) {
825848b8605Smrg         const unsigned w = MIN2(bw, width - x);
826848b8605Smrg         etc2_rgba8_parse_block(&block, src);
827848b8605Smrg
828848b8605Smrg         for (j = 0; j < h; j++) {
829848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
830848b8605Smrg            for (i = 0; i < w; i++) {
831848b8605Smrg               etc2_rgba8_fetch_texel(&block, i, j, dst);
832848b8605Smrg
833b8e80941Smrg	       if (bgra) {
834b8e80941Smrg		  /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
835b8e80941Smrg		  tmp = dst[0];
836b8e80941Smrg		  dst[0] = dst[2];
837b8e80941Smrg		  dst[2] = tmp;
838b8e80941Smrg		  dst[3] = dst[3];
839b8e80941Smrg	       }
840848b8605Smrg
841848b8605Smrg               dst += comps;
842848b8605Smrg            }
843848b8605Smrg         }
844848b8605Smrg         src += bs;
845848b8605Smrg      }
846848b8605Smrg
847848b8605Smrg      src_row += src_stride;
848848b8605Smrg   }
849848b8605Smrg}
850848b8605Smrg
851848b8605Smrgstatic void
852848b8605Smrgetc2_unpack_r11(uint8_t *dst_row,
853848b8605Smrg                unsigned dst_stride,
854848b8605Smrg                const uint8_t *src_row,
855848b8605Smrg                unsigned src_stride,
856848b8605Smrg                unsigned width,
857848b8605Smrg                unsigned height)
858848b8605Smrg{
859848b8605Smrg   /* If internalformat is COMPRESSED_R11_EAC, each 4 × 4 block of
860848b8605Smrg      color information is compressed to 64 bits.
861848b8605Smrg   */
862848b8605Smrg   const unsigned bw = 4, bh = 4, bs = 8, comps = 1, comp_size = 2;
863848b8605Smrg   struct etc2_block block;
864848b8605Smrg   unsigned x, y, i, j;
865848b8605Smrg
866848b8605Smrg   for (y = 0; y < height; y += bh) {
867848b8605Smrg      const unsigned h = MIN2(bh, height - y);
868848b8605Smrg      const uint8_t *src = src_row;
869848b8605Smrg
870848b8605Smrg      for (x = 0; x < width; x+= bw) {
871848b8605Smrg         const unsigned w = MIN2(bw, width - x);
872848b8605Smrg         etc2_r11_parse_block(&block, src);
873848b8605Smrg
874848b8605Smrg         for (j = 0; j < h; j++) {
875848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size;
876848b8605Smrg            for (i = 0; i < w; i++) {
877848b8605Smrg               etc2_r11_fetch_texel(&block, i, j, dst);
878848b8605Smrg               dst += comps * comp_size;
879848b8605Smrg            }
880848b8605Smrg         }
881848b8605Smrg         src += bs;
882848b8605Smrg      }
883848b8605Smrg
884848b8605Smrg      src_row += src_stride;
885848b8605Smrg   }
886848b8605Smrg}
887848b8605Smrg
888848b8605Smrgstatic void
889848b8605Smrgetc2_unpack_rg11(uint8_t *dst_row,
890848b8605Smrg                 unsigned dst_stride,
891848b8605Smrg                 const uint8_t *src_row,
892848b8605Smrg                 unsigned src_stride,
893848b8605Smrg                 unsigned width,
894848b8605Smrg                 unsigned height)
895848b8605Smrg{
896848b8605Smrg   /* If internalformat is COMPRESSED_RG11_EAC, each 4 × 4 block of
897848b8605Smrg      RG color information is compressed to 128 bits.
898848b8605Smrg   */
899848b8605Smrg   const unsigned bw = 4, bh = 4, bs = 16, comps = 2, comp_size = 2;
900848b8605Smrg   struct etc2_block block;
901848b8605Smrg   unsigned x, y, i, j;
902848b8605Smrg
903848b8605Smrg   for (y = 0; y < height; y += bh) {
904848b8605Smrg      const unsigned h = MIN2(bh, height - y);
905848b8605Smrg      const uint8_t *src = src_row;
906848b8605Smrg
907848b8605Smrg      for (x = 0; x < width; x+= bw) {
908848b8605Smrg         const unsigned w = MIN2(bw, width - x);
909848b8605Smrg         /* red component */
910848b8605Smrg         etc2_r11_parse_block(&block, src);
911848b8605Smrg
912848b8605Smrg         for (j = 0; j < h; j++) {
913848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride +
914848b8605Smrg                           x * comps * comp_size;
915848b8605Smrg            for (i = 0; i < w; i++) {
916848b8605Smrg               etc2_r11_fetch_texel(&block, i, j, dst);
917848b8605Smrg               dst += comps * comp_size;
918848b8605Smrg            }
919848b8605Smrg         }
920848b8605Smrg         /* green component */
921848b8605Smrg         etc2_r11_parse_block(&block, src + 8);
922848b8605Smrg
923848b8605Smrg         for (j = 0; j < h; j++) {
924848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride +
925848b8605Smrg                           x * comps * comp_size;
926848b8605Smrg            for (i = 0; i < w; i++) {
927848b8605Smrg               etc2_r11_fetch_texel(&block, i, j, dst + comp_size);
928848b8605Smrg               dst += comps * comp_size;
929848b8605Smrg            }
930848b8605Smrg         }
931848b8605Smrg         src += bs;
932848b8605Smrg      }
933848b8605Smrg
934848b8605Smrg      src_row += src_stride;
935848b8605Smrg   }
936848b8605Smrg}
937848b8605Smrg
938848b8605Smrgstatic void
939848b8605Smrgetc2_unpack_signed_r11(uint8_t *dst_row,
940848b8605Smrg                       unsigned dst_stride,
941848b8605Smrg                       const uint8_t *src_row,
942848b8605Smrg                       unsigned src_stride,
943848b8605Smrg                       unsigned width,
944848b8605Smrg                       unsigned height)
945848b8605Smrg{
946848b8605Smrg   /* If internalformat is COMPRESSED_SIGNED_R11_EAC, each 4 × 4 block of
947848b8605Smrg      red color information is compressed to 64 bits.
948848b8605Smrg   */
949848b8605Smrg   const unsigned bw = 4, bh = 4, bs = 8, comps = 1, comp_size = 2;
950848b8605Smrg   struct etc2_block block;
951848b8605Smrg   unsigned x, y, i, j;
952848b8605Smrg
953848b8605Smrg   for (y = 0; y < height; y += bh) {
954848b8605Smrg      const unsigned h = MIN2(bh, height - y);
955848b8605Smrg      const uint8_t *src = src_row;
956848b8605Smrg
957848b8605Smrg      for (x = 0; x < width; x+= bw) {
958848b8605Smrg         const unsigned w = MIN2(bw, width - x);
959848b8605Smrg         etc2_r11_parse_block(&block, src);
960848b8605Smrg
961848b8605Smrg         for (j = 0; j < h; j++) {
962848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride +
963848b8605Smrg                           x * comps * comp_size;
964848b8605Smrg            for (i = 0; i < w; i++) {
965848b8605Smrg               etc2_signed_r11_fetch_texel(&block, i, j, dst);
966848b8605Smrg               dst += comps * comp_size;
967848b8605Smrg            }
968848b8605Smrg         }
969848b8605Smrg         src += bs;
970848b8605Smrg      }
971848b8605Smrg
972848b8605Smrg      src_row += src_stride;
973848b8605Smrg   }
974848b8605Smrg}
975848b8605Smrg
976848b8605Smrgstatic void
977848b8605Smrgetc2_unpack_signed_rg11(uint8_t *dst_row,
978848b8605Smrg                        unsigned dst_stride,
979848b8605Smrg                        const uint8_t *src_row,
980848b8605Smrg                        unsigned src_stride,
981848b8605Smrg                        unsigned width,
982848b8605Smrg                        unsigned height)
983848b8605Smrg{
984848b8605Smrg   /* If internalformat is COMPRESSED_SIGNED_RG11_EAC, each 4 × 4 block of
985848b8605Smrg      RG color information is compressed to 128 bits.
986848b8605Smrg   */
987848b8605Smrg   const unsigned bw = 4, bh = 4, bs = 16, comps = 2, comp_size = 2;
988848b8605Smrg   struct etc2_block block;
989848b8605Smrg   unsigned x, y, i, j;
990848b8605Smrg
991848b8605Smrg   for (y = 0; y < height; y += bh) {
992848b8605Smrg      const unsigned h = MIN2(bh, height - y);
993848b8605Smrg      const uint8_t *src = src_row;
994848b8605Smrg
995848b8605Smrg      for (x = 0; x < width; x+= bw) {
996848b8605Smrg         const unsigned w = MIN2(bw, width - x);
997848b8605Smrg         /* red component */
998848b8605Smrg         etc2_r11_parse_block(&block, src);
999848b8605Smrg
1000848b8605Smrg         for (j = 0; j < h; j++) {
1001848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride +
1002848b8605Smrg                          x * comps * comp_size;
1003848b8605Smrg            for (i = 0; i < w; i++) {
1004848b8605Smrg               etc2_signed_r11_fetch_texel(&block, i, j, dst);
1005848b8605Smrg               dst += comps * comp_size;
1006848b8605Smrg            }
1007848b8605Smrg         }
1008848b8605Smrg         /* green component */
1009848b8605Smrg         etc2_r11_parse_block(&block, src + 8);
1010848b8605Smrg
1011848b8605Smrg         for (j = 0; j < h; j++) {
1012848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride +
1013848b8605Smrg                           x * comps * comp_size;
1014848b8605Smrg            for (i = 0; i < w; i++) {
1015848b8605Smrg               etc2_signed_r11_fetch_texel(&block, i, j, dst + comp_size);
1016848b8605Smrg               dst += comps * comp_size;
1017848b8605Smrg            }
1018848b8605Smrg         }
1019848b8605Smrg         src += bs;
1020848b8605Smrg      }
1021848b8605Smrg
1022848b8605Smrg      src_row += src_stride;
1023848b8605Smrg   }
1024848b8605Smrg}
1025848b8605Smrg
1026848b8605Smrgstatic void
1027848b8605Smrgetc2_unpack_rgb8_punchthrough_alpha1(uint8_t *dst_row,
1028848b8605Smrg                                     unsigned dst_stride,
1029848b8605Smrg                                     const uint8_t *src_row,
1030848b8605Smrg                                     unsigned src_stride,
1031848b8605Smrg                                     unsigned width,
1032848b8605Smrg                                     unsigned height)
1033848b8605Smrg{
1034848b8605Smrg   const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
1035848b8605Smrg   struct etc2_block block;
1036848b8605Smrg   unsigned x, y, i, j;
1037848b8605Smrg
1038848b8605Smrg   for (y = 0; y < height; y += bh) {
1039848b8605Smrg      const unsigned h = MIN2(bh, height - y);
1040848b8605Smrg      const uint8_t *src = src_row;
1041848b8605Smrg
1042848b8605Smrg      for (x = 0; x < width; x+= bw) {
1043848b8605Smrg         const unsigned w = MIN2(bw, width - x);
1044848b8605Smrg         etc2_rgb8_parse_block(&block, src,
1045848b8605Smrg                               true /* punchthrough_alpha */);
1046848b8605Smrg         for (j = 0; j < h; j++) {
1047848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
1048848b8605Smrg            for (i = 0; i < w; i++) {
1049848b8605Smrg               etc2_rgb8_fetch_texel(&block, i, j, dst,
1050848b8605Smrg                                     true /* punchthrough_alpha */);
1051848b8605Smrg               dst += comps;
1052848b8605Smrg            }
1053848b8605Smrg         }
1054848b8605Smrg
1055848b8605Smrg         src += bs;
1056848b8605Smrg      }
1057848b8605Smrg
1058848b8605Smrg      src_row += src_stride;
1059848b8605Smrg   }
1060848b8605Smrg}
1061848b8605Smrg
1062848b8605Smrgstatic void
1063848b8605Smrgetc2_unpack_srgb8_punchthrough_alpha1(uint8_t *dst_row,
1064848b8605Smrg                                     unsigned dst_stride,
1065848b8605Smrg                                     const uint8_t *src_row,
1066848b8605Smrg                                     unsigned src_stride,
1067848b8605Smrg                                     unsigned width,
1068b8e80941Smrg				     unsigned height,
1069b8e80941Smrg				     bool bgra)
1070848b8605Smrg{
1071848b8605Smrg   const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
1072848b8605Smrg   struct etc2_block block;
1073848b8605Smrg   unsigned x, y, i, j;
1074848b8605Smrg   uint8_t tmp;
1075848b8605Smrg
1076848b8605Smrg   for (y = 0; y < height; y += bh) {
1077848b8605Smrg      const unsigned h = MIN2(bh, height - y);
1078848b8605Smrg      const uint8_t *src = src_row;
1079848b8605Smrg
1080848b8605Smrg      for (x = 0; x < width; x+= bw) {
1081848b8605Smrg         const unsigned w = MIN2(bw, width - x);
1082848b8605Smrg         etc2_rgb8_parse_block(&block, src,
1083848b8605Smrg                               true /* punchthrough_alpha */);
1084848b8605Smrg         for (j = 0; j < h; j++) {
1085848b8605Smrg            uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
1086848b8605Smrg            for (i = 0; i < w; i++) {
1087848b8605Smrg               etc2_rgb8_fetch_texel(&block, i, j, dst,
1088848b8605Smrg                                     true /* punchthrough_alpha */);
1089b8e80941Smrg
1090b8e80941Smrg	       if (bgra) {
1091b8e80941Smrg		  /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
1092b8e80941Smrg		  tmp = dst[0];
1093b8e80941Smrg		  dst[0] = dst[2];
1094b8e80941Smrg		  dst[2] = tmp;
1095b8e80941Smrg		  dst[3] = dst[3];
1096b8e80941Smrg	       }
1097848b8605Smrg
1098848b8605Smrg               dst += comps;
1099848b8605Smrg            }
1100848b8605Smrg         }
1101848b8605Smrg
1102848b8605Smrg         src += bs;
1103848b8605Smrg      }
1104848b8605Smrg
1105848b8605Smrg      src_row += src_stride;
1106848b8605Smrg   }
1107848b8605Smrg}
1108848b8605Smrg
1109848b8605Smrg/* ETC2 texture formats are valid in glCompressedTexImage2D and
1110848b8605Smrg * glCompressedTexSubImage2D functions */
1111848b8605SmrgGLboolean
1112b8e80941Smrg_mesa_texstore_etc2_rgb8(UNUSED_TEXSTORE_PARAMS)
1113848b8605Smrg{
1114b8e80941Smrg   assert(0);
1115848b8605Smrg
1116848b8605Smrg   return GL_FALSE;
1117848b8605Smrg}
1118848b8605Smrg
1119848b8605SmrgGLboolean
1120b8e80941Smrg_mesa_texstore_etc2_srgb8(UNUSED_TEXSTORE_PARAMS)
1121848b8605Smrg{
1122b8e80941Smrg   assert(0);
1123848b8605Smrg
1124848b8605Smrg   return GL_FALSE;
1125848b8605Smrg}
1126848b8605Smrg
1127848b8605SmrgGLboolean
1128b8e80941Smrg_mesa_texstore_etc2_rgba8_eac(UNUSED_TEXSTORE_PARAMS)
1129848b8605Smrg{
1130b8e80941Smrg   assert(0);
1131848b8605Smrg
1132848b8605Smrg   return GL_FALSE;
1133848b8605Smrg}
1134848b8605Smrg
1135848b8605SmrgGLboolean
1136b8e80941Smrg_mesa_texstore_etc2_srgb8_alpha8_eac(UNUSED_TEXSTORE_PARAMS)
1137848b8605Smrg{
1138b8e80941Smrg   assert(0);
1139848b8605Smrg
1140848b8605Smrg   return GL_FALSE;
1141848b8605Smrg}
1142848b8605Smrg
1143848b8605SmrgGLboolean
1144b8e80941Smrg_mesa_texstore_etc2_r11_eac(UNUSED_TEXSTORE_PARAMS)
1145848b8605Smrg{
1146b8e80941Smrg   assert(0);
1147848b8605Smrg
1148848b8605Smrg   return GL_FALSE;
1149848b8605Smrg}
1150848b8605Smrg
1151848b8605SmrgGLboolean
1152b8e80941Smrg_mesa_texstore_etc2_signed_r11_eac(UNUSED_TEXSTORE_PARAMS)
1153848b8605Smrg{
1154b8e80941Smrg   assert(0);
1155848b8605Smrg
1156848b8605Smrg   return GL_FALSE;
1157848b8605Smrg}
1158848b8605Smrg
1159848b8605SmrgGLboolean
1160b8e80941Smrg_mesa_texstore_etc2_rg11_eac(UNUSED_TEXSTORE_PARAMS)
1161848b8605Smrg{
1162b8e80941Smrg   assert(0);
1163848b8605Smrg
1164848b8605Smrg   return GL_FALSE;
1165848b8605Smrg}
1166848b8605Smrg
1167848b8605SmrgGLboolean
1168b8e80941Smrg_mesa_texstore_etc2_signed_rg11_eac(UNUSED_TEXSTORE_PARAMS)
1169848b8605Smrg{
1170b8e80941Smrg   assert(0);
1171848b8605Smrg
1172848b8605Smrg   return GL_FALSE;
1173848b8605Smrg}
1174848b8605Smrg
1175848b8605SmrgGLboolean
1176b8e80941Smrg_mesa_texstore_etc2_rgb8_punchthrough_alpha1(UNUSED_TEXSTORE_PARAMS)
1177848b8605Smrg{
1178b8e80941Smrg   assert(0);
1179848b8605Smrg
1180848b8605Smrg   return GL_FALSE;
1181848b8605Smrg}
1182848b8605Smrg
1183848b8605SmrgGLboolean
1184b8e80941Smrg_mesa_texstore_etc2_srgb8_punchthrough_alpha1(UNUSED_TEXSTORE_PARAMS)
1185848b8605Smrg{
1186b8e80941Smrg   assert(0);
1187848b8605Smrg
1188848b8605Smrg   return GL_FALSE;
1189848b8605Smrg}
1190848b8605Smrg
1191848b8605Smrg
1192848b8605Smrg/**
1193848b8605Smrg * Decode texture data in any one of following formats:
1194848b8605Smrg * `MESA_FORMAT_ETC2_RGB8`
1195848b8605Smrg * `MESA_FORMAT_ETC2_SRGB8`
1196848b8605Smrg * `MESA_FORMAT_ETC2_RGBA8_EAC`
1197848b8605Smrg * `MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC`
1198848b8605Smrg * `MESA_FORMAT_ETC2_R11_EAC`
1199848b8605Smrg * `MESA_FORMAT_ETC2_RG11_EAC`
1200848b8605Smrg * `MESA_FORMAT_ETC2_SIGNED_R11_EAC`
1201848b8605Smrg * `MESA_FORMAT_ETC2_SIGNED_RG11_EAC`
1202848b8605Smrg * `MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1`
1203848b8605Smrg * `MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1`
1204848b8605Smrg *
1205848b8605Smrg * The size of the source data must be a multiple of the ETC2 block size
1206848b8605Smrg * even if the texture image's dimensions are not aligned to 4.
1207848b8605Smrg *
1208848b8605Smrg * \param src_width in pixels
1209848b8605Smrg * \param src_height in pixels
1210848b8605Smrg * \param dst_stride in bytes
1211848b8605Smrg */
1212848b8605Smrg
1213848b8605Smrgvoid
1214848b8605Smrg_mesa_unpack_etc2_format(uint8_t *dst_row,
1215848b8605Smrg                         unsigned dst_stride,
1216848b8605Smrg                         const uint8_t *src_row,
1217848b8605Smrg                         unsigned src_stride,
1218848b8605Smrg                         unsigned src_width,
1219848b8605Smrg                         unsigned src_height,
1220b8e80941Smrg			 mesa_format format,
1221b8e80941Smrg			 bool bgra)
1222848b8605Smrg{
1223848b8605Smrg   if (format == MESA_FORMAT_ETC2_RGB8)
1224848b8605Smrg      etc2_unpack_rgb8(dst_row, dst_stride,
1225848b8605Smrg                       src_row, src_stride,
1226848b8605Smrg                       src_width, src_height);
1227848b8605Smrg   else if (format == MESA_FORMAT_ETC2_SRGB8)
1228848b8605Smrg      etc2_unpack_srgb8(dst_row, dst_stride,
1229848b8605Smrg                        src_row, src_stride,
1230b8e80941Smrg			src_width, src_height, bgra);
1231848b8605Smrg   else if (format == MESA_FORMAT_ETC2_RGBA8_EAC)
1232848b8605Smrg      etc2_unpack_rgba8(dst_row, dst_stride,
1233848b8605Smrg                        src_row, src_stride,
1234848b8605Smrg                        src_width, src_height);
1235848b8605Smrg   else if (format == MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC)
1236848b8605Smrg      etc2_unpack_srgb8_alpha8(dst_row, dst_stride,
1237848b8605Smrg                               src_row, src_stride,
1238b8e80941Smrg			       src_width, src_height, bgra);
1239848b8605Smrg   else if (format == MESA_FORMAT_ETC2_R11_EAC)
1240848b8605Smrg      etc2_unpack_r11(dst_row, dst_stride,
1241848b8605Smrg                      src_row, src_stride,
1242848b8605Smrg                      src_width, src_height);
1243848b8605Smrg   else if (format == MESA_FORMAT_ETC2_RG11_EAC)
1244848b8605Smrg      etc2_unpack_rg11(dst_row, dst_stride,
1245848b8605Smrg                       src_row, src_stride,
1246848b8605Smrg                       src_width, src_height);
1247848b8605Smrg   else if (format == MESA_FORMAT_ETC2_SIGNED_R11_EAC)
1248848b8605Smrg      etc2_unpack_signed_r11(dst_row, dst_stride,
1249848b8605Smrg                             src_row, src_stride,
1250848b8605Smrg                             src_width, src_height);
1251848b8605Smrg   else if (format == MESA_FORMAT_ETC2_SIGNED_RG11_EAC)
1252848b8605Smrg      etc2_unpack_signed_rg11(dst_row, dst_stride,
1253848b8605Smrg                              src_row, src_stride,
1254848b8605Smrg                              src_width, src_height);
1255848b8605Smrg   else if (format == MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1)
1256848b8605Smrg      etc2_unpack_rgb8_punchthrough_alpha1(dst_row, dst_stride,
1257848b8605Smrg                                           src_row, src_stride,
1258848b8605Smrg                                           src_width, src_height);
1259848b8605Smrg   else if (format == MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1)
1260848b8605Smrg      etc2_unpack_srgb8_punchthrough_alpha1(dst_row, dst_stride,
1261848b8605Smrg                                            src_row, src_stride,
1262b8e80941Smrg					    src_width, src_height, bgra);
1263848b8605Smrg}
1264848b8605Smrg
1265848b8605Smrg
1266848b8605Smrg
1267848b8605Smrgstatic void
1268848b8605Smrgfetch_etc1_rgb8(const GLubyte *map,
1269848b8605Smrg                GLint rowStride, GLint i, GLint j,
1270848b8605Smrg                GLfloat *texel)
1271848b8605Smrg{
1272848b8605Smrg   struct etc1_block block;
1273848b8605Smrg   GLubyte dst[3];
1274848b8605Smrg   const GLubyte *src;
1275848b8605Smrg
1276848b8605Smrg   src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1277848b8605Smrg
1278848b8605Smrg   etc1_parse_block(&block, src);
1279848b8605Smrg   etc1_fetch_texel(&block, i % 4, j % 4, dst);
1280848b8605Smrg
1281848b8605Smrg   texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]);
1282848b8605Smrg   texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]);
1283848b8605Smrg   texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]);
1284848b8605Smrg   texel[ACOMP] = 1.0f;
1285848b8605Smrg}
1286848b8605Smrg
1287848b8605Smrg
1288848b8605Smrgstatic void
1289848b8605Smrgfetch_etc2_rgb8(const GLubyte *map,
1290848b8605Smrg                GLint rowStride, GLint i, GLint j, GLfloat *texel)
1291848b8605Smrg{
1292848b8605Smrg   struct etc2_block block;
1293848b8605Smrg   uint8_t dst[3];
1294848b8605Smrg   const uint8_t *src;
1295848b8605Smrg
1296848b8605Smrg   src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1297848b8605Smrg
1298848b8605Smrg   etc2_rgb8_parse_block(&block, src,
1299848b8605Smrg                         false /* punchthrough_alpha */);
1300848b8605Smrg   etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst,
1301848b8605Smrg                         false /* punchthrough_alpha */);
1302848b8605Smrg
1303848b8605Smrg   texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]);
1304848b8605Smrg   texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]);
1305848b8605Smrg   texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]);
1306848b8605Smrg   texel[ACOMP] = 1.0f;
1307848b8605Smrg}
1308848b8605Smrg
1309848b8605Smrgstatic void
1310848b8605Smrgfetch_etc2_srgb8(const GLubyte *map,
1311848b8605Smrg                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
1312848b8605Smrg{
1313848b8605Smrg   struct etc2_block block;
1314848b8605Smrg   uint8_t dst[3];
1315848b8605Smrg   const uint8_t *src;
1316848b8605Smrg
1317848b8605Smrg   src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1318848b8605Smrg
1319848b8605Smrg   etc2_rgb8_parse_block(&block, src,
1320848b8605Smrg                         false /* punchthrough_alpha */);
1321848b8605Smrg   etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst,
1322848b8605Smrg                         false /* punchthrough_alpha */);
1323848b8605Smrg
1324848b8605Smrg   texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]);
1325848b8605Smrg   texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]);
1326848b8605Smrg   texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]);
1327848b8605Smrg   texel[ACOMP] = 1.0f;
1328848b8605Smrg}
1329848b8605Smrg
1330848b8605Smrgstatic void
1331848b8605Smrgfetch_etc2_rgba8_eac(const GLubyte *map,
1332848b8605Smrg                     GLint rowStride, GLint i, GLint j, GLfloat *texel)
1333848b8605Smrg{
1334848b8605Smrg   struct etc2_block block;
1335848b8605Smrg   uint8_t dst[4];
1336848b8605Smrg   const uint8_t *src;
1337848b8605Smrg
1338848b8605Smrg   src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
1339848b8605Smrg
1340848b8605Smrg   etc2_rgba8_parse_block(&block, src);
1341848b8605Smrg   etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst);
1342848b8605Smrg
1343848b8605Smrg   texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]);
1344848b8605Smrg   texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]);
1345848b8605Smrg   texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]);
1346848b8605Smrg   texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]);
1347848b8605Smrg}
1348848b8605Smrg
1349848b8605Smrgstatic void
1350848b8605Smrgfetch_etc2_srgb8_alpha8_eac(const GLubyte *map,
1351848b8605Smrg                            GLint rowStride, GLint i, GLint j, GLfloat *texel)
1352848b8605Smrg{
1353848b8605Smrg   struct etc2_block block;
1354848b8605Smrg   uint8_t dst[4];
1355848b8605Smrg   const uint8_t *src;
1356848b8605Smrg
1357848b8605Smrg   src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
1358848b8605Smrg
1359848b8605Smrg   etc2_rgba8_parse_block(&block, src);
1360848b8605Smrg   etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst);
1361848b8605Smrg
1362848b8605Smrg   texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]);
1363848b8605Smrg   texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]);
1364848b8605Smrg   texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]);
1365848b8605Smrg   texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]);
1366848b8605Smrg}
1367848b8605Smrg
1368848b8605Smrgstatic void
1369848b8605Smrgfetch_etc2_r11_eac(const GLubyte *map,
1370848b8605Smrg                   GLint rowStride, GLint i, GLint j, GLfloat *texel)
1371848b8605Smrg{
1372848b8605Smrg   struct etc2_block block;
1373848b8605Smrg   GLushort dst;
1374848b8605Smrg   const uint8_t *src;
1375848b8605Smrg
1376848b8605Smrg   src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1377848b8605Smrg
1378848b8605Smrg   etc2_r11_parse_block(&block, src);
1379848b8605Smrg   etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst);
1380848b8605Smrg
1381848b8605Smrg   texel[RCOMP] = USHORT_TO_FLOAT(dst);
1382848b8605Smrg   texel[GCOMP] = 0.0f;
1383848b8605Smrg   texel[BCOMP] = 0.0f;
1384848b8605Smrg   texel[ACOMP] = 1.0f;
1385848b8605Smrg}
1386848b8605Smrg
1387848b8605Smrgstatic void
1388848b8605Smrgfetch_etc2_rg11_eac(const GLubyte *map,
1389848b8605Smrg                    GLint rowStride, GLint i, GLint j, GLfloat *texel)
1390848b8605Smrg{
1391848b8605Smrg   struct etc2_block block;
1392848b8605Smrg   GLushort dst[2];
1393848b8605Smrg   const uint8_t *src;
1394848b8605Smrg
1395848b8605Smrg   src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
1396848b8605Smrg
1397848b8605Smrg   /* red component */
1398848b8605Smrg   etc2_r11_parse_block(&block, src);
1399848b8605Smrg   etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)dst);
1400848b8605Smrg
1401848b8605Smrg   /* green component */
1402848b8605Smrg   etc2_r11_parse_block(&block, src + 8);
1403848b8605Smrg   etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)(dst + 1));
1404848b8605Smrg
1405848b8605Smrg   texel[RCOMP] = USHORT_TO_FLOAT(dst[0]);
1406848b8605Smrg   texel[GCOMP] = USHORT_TO_FLOAT(dst[1]);
1407848b8605Smrg   texel[BCOMP] = 0.0f;
1408848b8605Smrg   texel[ACOMP] = 1.0f;
1409848b8605Smrg}
1410848b8605Smrg
1411848b8605Smrgstatic void
1412848b8605Smrgfetch_etc2_signed_r11_eac(const GLubyte *map,
1413848b8605Smrg                          GLint rowStride, GLint i, GLint j, GLfloat *texel)
1414848b8605Smrg{
1415848b8605Smrg   struct etc2_block block;
1416848b8605Smrg   GLushort dst;
1417848b8605Smrg   const uint8_t *src;
1418848b8605Smrg
1419848b8605Smrg   src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1420848b8605Smrg
1421848b8605Smrg   etc2_r11_parse_block(&block, src);
1422848b8605Smrg   etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst);
1423848b8605Smrg
1424848b8605Smrg   texel[RCOMP] = SHORT_TO_FLOAT(dst);
1425848b8605Smrg   texel[GCOMP] = 0.0f;
1426848b8605Smrg   texel[BCOMP] = 0.0f;
1427848b8605Smrg   texel[ACOMP] = 1.0f;
1428848b8605Smrg}
1429848b8605Smrg
1430848b8605Smrgstatic void
1431848b8605Smrgfetch_etc2_signed_rg11_eac(const GLubyte *map,
1432848b8605Smrg                           GLint rowStride, GLint i, GLint j, GLfloat *texel)
1433848b8605Smrg{
1434848b8605Smrg   struct etc2_block block;
1435848b8605Smrg   GLushort dst[2];
1436848b8605Smrg   const uint8_t *src;
1437848b8605Smrg
1438848b8605Smrg   src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
1439848b8605Smrg
1440848b8605Smrg   /* red component */
1441848b8605Smrg   etc2_r11_parse_block(&block, src);
1442848b8605Smrg   etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)dst);
1443848b8605Smrg
1444848b8605Smrg   /* green component */
1445848b8605Smrg   etc2_r11_parse_block(&block, src + 8);
1446848b8605Smrg   etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)(dst + 1));
1447848b8605Smrg
1448848b8605Smrg   texel[RCOMP] = SHORT_TO_FLOAT(dst[0]);
1449848b8605Smrg   texel[GCOMP] = SHORT_TO_FLOAT(dst[1]);
1450848b8605Smrg   texel[BCOMP] = 0.0f;
1451848b8605Smrg   texel[ACOMP] = 1.0f;
1452848b8605Smrg}
1453848b8605Smrg
1454848b8605Smrgstatic void
1455848b8605Smrgfetch_etc2_rgb8_punchthrough_alpha1(const GLubyte *map,
1456848b8605Smrg                                    GLint rowStride, GLint i, GLint j,
1457848b8605Smrg                                    GLfloat *texel)
1458848b8605Smrg{
1459848b8605Smrg   struct etc2_block block;
1460848b8605Smrg   uint8_t dst[4];
1461848b8605Smrg   const uint8_t *src;
1462848b8605Smrg
1463848b8605Smrg   src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1464848b8605Smrg
1465848b8605Smrg   etc2_rgb8_parse_block(&block, src,
1466848b8605Smrg                         true /* punchthrough alpha */);
1467848b8605Smrg   etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst,
1468848b8605Smrg                         true /* punchthrough alpha */);
1469848b8605Smrg   texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]);
1470848b8605Smrg   texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]);
1471848b8605Smrg   texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]);
1472848b8605Smrg   texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]);
1473848b8605Smrg}
1474848b8605Smrg
1475848b8605Smrgstatic void
1476848b8605Smrgfetch_etc2_srgb8_punchthrough_alpha1(const GLubyte *map,
1477848b8605Smrg                                     GLint rowStride,
1478848b8605Smrg                                     GLint i, GLint j, GLfloat *texel)
1479848b8605Smrg{
1480848b8605Smrg   struct etc2_block block;
1481848b8605Smrg   uint8_t dst[4];
1482848b8605Smrg   const uint8_t *src;
1483848b8605Smrg
1484848b8605Smrg   src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8;
1485848b8605Smrg
1486848b8605Smrg   etc2_rgb8_parse_block(&block, src,
1487848b8605Smrg                         true /* punchthrough alpha */);
1488848b8605Smrg   etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst,
1489848b8605Smrg                         true /* punchthrough alpha */);
1490848b8605Smrg   texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]);
1491848b8605Smrg   texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]);
1492848b8605Smrg   texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]);
1493848b8605Smrg   texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]);
1494848b8605Smrg}
1495848b8605Smrg
1496848b8605Smrg
1497848b8605Smrgcompressed_fetch_func
1498848b8605Smrg_mesa_get_etc_fetch_func(mesa_format format)
1499848b8605Smrg{
1500848b8605Smrg   switch (format) {
1501848b8605Smrg   case MESA_FORMAT_ETC1_RGB8:
1502848b8605Smrg      return fetch_etc1_rgb8;
1503848b8605Smrg   case MESA_FORMAT_ETC2_RGB8:
1504848b8605Smrg      return fetch_etc2_rgb8;
1505848b8605Smrg   case MESA_FORMAT_ETC2_SRGB8:
1506848b8605Smrg      return fetch_etc2_srgb8;
1507848b8605Smrg   case MESA_FORMAT_ETC2_RGBA8_EAC:
1508848b8605Smrg      return fetch_etc2_rgba8_eac;
1509848b8605Smrg   case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
1510848b8605Smrg      return fetch_etc2_srgb8_alpha8_eac;
1511848b8605Smrg   case MESA_FORMAT_ETC2_R11_EAC:
1512848b8605Smrg      return fetch_etc2_r11_eac;
1513848b8605Smrg   case MESA_FORMAT_ETC2_RG11_EAC:
1514848b8605Smrg      return fetch_etc2_rg11_eac;
1515848b8605Smrg   case MESA_FORMAT_ETC2_SIGNED_R11_EAC:
1516848b8605Smrg      return fetch_etc2_signed_r11_eac;
1517848b8605Smrg   case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
1518848b8605Smrg      return fetch_etc2_signed_rg11_eac;
1519848b8605Smrg   case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
1520848b8605Smrg      return fetch_etc2_rgb8_punchthrough_alpha1;
1521848b8605Smrg   case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
1522848b8605Smrg      return fetch_etc2_srgb8_punchthrough_alpha1;
1523848b8605Smrg   default:
1524848b8605Smrg      return NULL;
1525848b8605Smrg   }
1526848b8605Smrg}
1527