• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // loadimage_etc.cpp: Decodes ETC and EAC encoded textures.
8 
9 #include "image_util/loadimage.h"
10 
11 #include <type_traits>
12 #include "common/mathutil.h"
13 
14 #include "image_util/imageformats.h"
15 
16 namespace angle
17 {
18 namespace
19 {
20 
21 using IntensityModifier = const int[4];
22 
23 // Table 3.17.2 sorted according to table 3.17.3
24 // clang-format off
25 static IntensityModifier intensityModifierDefault[] =
26 {
27     {  2,   8,  -2,   -8 },
28     {  5,  17,  -5,  -17 },
29     {  9,  29,  -9,  -29 },
30     { 13,  42, -13,  -42 },
31     { 18,  60, -18,  -60 },
32     { 24,  80, -24,  -80 },
33     { 33, 106, -33, -106 },
34     { 47, 183, -47, -183 },
35 };
36 // clang-format on
37 
38 // Table C.12, intensity modifier for non opaque punchthrough alpha
39 // clang-format off
40 static IntensityModifier intensityModifierNonOpaque[] =
41 {
42     { 0,   8, 0,   -8 },
43     { 0,  17, 0,  -17 },
44     { 0,  29, 0,  -29 },
45     { 0,  42, 0,  -42 },
46     { 0,  60, 0,  -60 },
47     { 0,  80, 0,  -80 },
48     { 0, 106, 0, -106 },
49     { 0, 183, 0, -183 },
50 };
51 // clang-format on
52 
53 static const int kNumPixelsInBlock = 16;
54 
55 struct ETC2Block
56 {
57     // Decodes unsigned single or dual channel ETC2 block to 8-bit color
decodeAsSingleETC2Channelangle::__anon380671230111::ETC2Block58     void decodeAsSingleETC2Channel(uint8_t *dest,
59                                    size_t x,
60                                    size_t y,
61                                    size_t w,
62                                    size_t h,
63                                    size_t destPixelStride,
64                                    size_t destRowPitch,
65                                    bool isSigned) const
66     {
67         for (size_t j = 0; j < 4 && (y + j) < h; j++)
68         {
69             uint8_t *row = dest + (j * destRowPitch);
70             for (size_t i = 0; i < 4 && (x + i) < w; i++)
71             {
72                 uint8_t *pixel = row + (i * destPixelStride);
73                 if (isSigned)
74                 {
75                     *pixel = clampSByte(getSingleETC2Channel(i, j, isSigned));
76                 }
77                 else
78                 {
79                     *pixel = clampByte(getSingleETC2Channel(i, j, isSigned));
80                 }
81             }
82         }
83     }
84 
85     // Decodes unsigned single or dual channel EAC block to 16-bit color
decodeAsSingleEACChannelangle::__anon380671230111::ETC2Block86     void decodeAsSingleEACChannel(uint16_t *dest,
87                                   size_t x,
88                                   size_t y,
89                                   size_t w,
90                                   size_t h,
91                                   size_t destPixelStride,
92                                   size_t destRowPitch,
93                                   bool isSigned,
94                                   bool isFloat) const
95     {
96         for (size_t j = 0; j < 4 && (y + j) < h; j++)
97         {
98             uint16_t *row = reinterpret_cast<uint16_t *>(reinterpret_cast<uint8_t *>(dest) +
99                                                          (j * destRowPitch));
100             for (size_t i = 0; i < 4 && (x + i) < w; i++)
101             {
102                 uint16_t *pixel = row + (i * destPixelStride);
103                 if (isSigned)
104                 {
105                     int16_t tempPixel =
106                         renormalizeEAC<int16_t>(getSingleEACChannel(i, j, isSigned));
107                     *pixel =
108                         isFloat ? gl::float32ToFloat16(float(gl::normalize(tempPixel))) : tempPixel;
109                 }
110                 else
111                 {
112                     uint16_t tempPixel =
113                         renormalizeEAC<uint16_t>(getSingleEACChannel(i, j, isSigned));
114                     *pixel =
115                         isFloat ? gl::float32ToFloat16(float(gl::normalize(tempPixel))) : tempPixel;
116                 }
117             }
118         }
119     }
120 
121     // Decodes RGB block to rgba8
decodeAsRGBangle::__anon380671230111::ETC2Block122     void decodeAsRGB(uint8_t *dest,
123                      size_t x,
124                      size_t y,
125                      size_t w,
126                      size_t h,
127                      size_t destRowPitch,
128                      const uint8_t alphaValues[4][4],
129                      bool punchThroughAlpha) const
130     {
131         bool opaqueBit                  = u.idht.mode.idm.diffbit;
132         bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit;
133         // Select mode
134         if (u.idht.mode.idm.diffbit || punchThroughAlpha)
135         {
136             const auto &block = u.idht.mode.idm.colors.diff;
137             int r             = (block.R + block.dR);
138             int g             = (block.G + block.dG);
139             int b             = (block.B + block.dB);
140             if (r < 0 || r > 31)
141             {
142                 decodeTBlock(dest, x, y, w, h, destRowPitch, alphaValues,
143                              nonOpaquePunchThroughAlpha);
144             }
145             else if (g < 0 || g > 31)
146             {
147                 decodeHBlock(dest, x, y, w, h, destRowPitch, alphaValues,
148                              nonOpaquePunchThroughAlpha);
149             }
150             else if (b < 0 || b > 31)
151             {
152                 decodePlanarBlock(dest, x, y, w, h, destRowPitch, alphaValues);
153             }
154             else
155             {
156                 decodeDifferentialBlock(dest, x, y, w, h, destRowPitch, alphaValues,
157                                         nonOpaquePunchThroughAlpha);
158             }
159         }
160         else
161         {
162             decodeIndividualBlock(dest, x, y, w, h, destRowPitch, alphaValues,
163                                   nonOpaquePunchThroughAlpha);
164         }
165     }
166 
167     // Transcodes RGB block to BC1
transcodeAsBC1angle::__anon380671230111::ETC2Block168     void transcodeAsBC1(uint8_t *dest,
169                         size_t x,
170                         size_t y,
171                         size_t w,
172                         size_t h,
173                         const uint8_t alphaValues[4][4],
174                         bool punchThroughAlpha) const
175     {
176         bool opaqueBit                  = u.idht.mode.idm.diffbit;
177         bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit;
178         // Select mode
179         if (u.idht.mode.idm.diffbit || punchThroughAlpha)
180         {
181             const auto &block = u.idht.mode.idm.colors.diff;
182             int r             = (block.R + block.dR);
183             int g             = (block.G + block.dG);
184             int b             = (block.B + block.dB);
185             if (r < 0 || r > 31)
186             {
187                 transcodeTBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha);
188             }
189             else if (g < 0 || g > 31)
190             {
191                 transcodeHBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha);
192             }
193             else if (b < 0 || b > 31)
194             {
195                 transcodePlanarBlockToBC1(dest, x, y, w, h, alphaValues);
196             }
197             else
198             {
199                 transcodeDifferentialBlockToBC1(dest, x, y, w, h, alphaValues,
200                                                 nonOpaquePunchThroughAlpha);
201             }
202         }
203         else
204         {
205             transcodeIndividualBlockToBC1(dest, x, y, w, h, alphaValues,
206                                           nonOpaquePunchThroughAlpha);
207         }
208     }
209 
210   private:
211     union
212     {
213         // Individual, differential, H and T modes
214         struct
215         {
216             union
217             {
218                 // Individual and differential modes
219                 struct
220                 {
221                     union
222                     {
223                         struct  // Individual colors
224                         {
225                             unsigned char R2 : 4;
226                             unsigned char R1 : 4;
227                             unsigned char G2 : 4;
228                             unsigned char G1 : 4;
229                             unsigned char B2 : 4;
230                             unsigned char B1 : 4;
231                         } indiv;
232                         struct  // Differential colors
233                         {
234                             signed char dR : 3;
235                             unsigned char R : 5;
236                             signed char dG : 3;
237                             unsigned char G : 5;
238                             signed char dB : 3;
239                             unsigned char B : 5;
240                         } diff;
241                     } colors;
242                     bool flipbit : 1;
243                     bool diffbit : 1;
244                     unsigned char cw2 : 3;
245                     unsigned char cw1 : 3;
246                 } idm;
247                 // T mode
248                 struct
249                 {
250                     // Byte 1
251                     unsigned char TR1b : 2;
252                     unsigned char TunusedB : 1;
253                     unsigned char TR1a : 2;
254                     unsigned char TunusedA : 3;
255                     // Byte 2
256                     unsigned char TB1 : 4;
257                     unsigned char TG1 : 4;
258                     // Byte 3
259                     unsigned char TG2 : 4;
260                     unsigned char TR2 : 4;
261                     // Byte 4
262                     unsigned char Tdb : 1;
263                     bool Tflipbit : 1;
264                     unsigned char Tda : 2;
265                     unsigned char TB2 : 4;
266                 } tm;
267                 // H mode
268                 struct
269                 {
270                     // Byte 1
271                     unsigned char HG1a : 3;
272                     unsigned char HR1 : 4;
273                     unsigned char HunusedA : 1;
274                     // Byte 2
275                     unsigned char HB1b : 2;
276                     unsigned char HunusedC : 1;
277                     unsigned char HB1a : 1;
278                     unsigned char HG1b : 1;
279                     unsigned char HunusedB : 3;
280                     // Byte 3
281                     unsigned char HG2a : 3;
282                     unsigned char HR2 : 4;
283                     unsigned char HB1c : 1;
284                     // Byte 4
285                     unsigned char Hdb : 1;
286                     bool Hflipbit : 1;
287                     unsigned char Hda : 1;
288                     unsigned char HB2 : 4;
289                     unsigned char HG2b : 1;
290                 } hm;
291             } mode;
292             unsigned char pixelIndexMSB[2];
293             unsigned char pixelIndexLSB[2];
294         } idht;
295         // planar mode
296         struct
297         {
298             // Byte 1
299             unsigned char GO1 : 1;
300             unsigned char RO : 6;
301             unsigned char PunusedA : 1;
302             // Byte 2
303             unsigned char BO1 : 1;
304             unsigned char GO2 : 6;
305             unsigned char PunusedB : 1;
306             // Byte 3
307             unsigned char BO3a : 2;
308             unsigned char PunusedD : 1;
309             unsigned char BO2 : 2;
310             unsigned char PunusedC : 3;
311             // Byte 4
312             unsigned char RH2 : 1;
313             bool Pflipbit : 1;
314             unsigned char RH1 : 5;
315             unsigned char BO3b : 1;
316             // Byte 5
317             unsigned char BHa : 1;
318             unsigned char GH : 7;
319             // Byte 6
320             unsigned char RVa : 3;
321             unsigned char BHb : 5;
322             // Byte 7
323             unsigned char GVa : 5;
324             unsigned char RVb : 3;
325             // Byte 8
326             unsigned char BV : 6;
327             unsigned char GVb : 2;
328         } pblk;
329         // Single channel block
330         struct
331         {
332             union
333             {
334                 unsigned char us;
335                 signed char s;
336             } base_codeword;
337             unsigned char table_index : 4;
338             unsigned char multiplier : 4;
339             unsigned char mc1 : 2;
340             unsigned char mb : 3;
341             unsigned char ma : 3;
342             unsigned char mf1 : 1;
343             unsigned char me : 3;
344             unsigned char md : 3;
345             unsigned char mc2 : 1;
346             unsigned char mh : 3;
347             unsigned char mg : 3;
348             unsigned char mf2 : 2;
349             unsigned char mk1 : 2;
350             unsigned char mj : 3;
351             unsigned char mi : 3;
352             unsigned char mn1 : 1;
353             unsigned char mm : 3;
354             unsigned char ml : 3;
355             unsigned char mk2 : 1;
356             unsigned char mp : 3;
357             unsigned char mo : 3;
358             unsigned char mn2 : 2;
359         } scblk;
360     } u;
361 
clampByteangle::__anon380671230111::ETC2Block362     static unsigned char clampByte(int value)
363     {
364         return static_cast<unsigned char>(gl::clamp(value, 0, 255));
365     }
366 
clampSByteangle::__anon380671230111::ETC2Block367     static signed char clampSByte(int value)
368     {
369         return static_cast<signed char>(gl::clamp(value, -128, 127));
370     }
371 
372     template <typename T>
renormalizeEACangle::__anon380671230111::ETC2Block373     static T renormalizeEAC(int value)
374     {
375         int upper = 0;
376         int lower = 0;
377         int shift = 0;
378 
379         if (std::is_same<T, int16_t>::value)
380         {
381             // The spec states that -1024 invalid and should be clamped to -1023
382             upper = 1023;
383             lower = -1023;
384             shift = 5;
385         }
386         else if (std::is_same<T, uint16_t>::value)
387         {
388             upper = 2047;
389             lower = 0;
390             shift = 5;
391         }
392         else
393         {
394             // We currently only support renormalizing int16_t or uint16_t
395             UNREACHABLE();
396         }
397 
398         return static_cast<T>(gl::clamp(value, lower, upper)) << shift;
399     }
400 
createRGBAangle::__anon380671230111::ETC2Block401     static R8G8B8A8 createRGBA(int red, int green, int blue, int alpha)
402     {
403         R8G8B8A8 rgba;
404         rgba.R = clampByte(red);
405         rgba.G = clampByte(green);
406         rgba.B = clampByte(blue);
407         rgba.A = clampByte(alpha);
408         return rgba;
409     }
410 
createRGBAangle::__anon380671230111::ETC2Block411     static R8G8B8A8 createRGBA(int red, int green, int blue)
412     {
413         return createRGBA(red, green, blue, 255);
414     }
415 
extend_4to8bitsangle::__anon380671230111::ETC2Block416     static int extend_4to8bits(int x) { return (x << 4) | x; }
extend_5to8bitsangle::__anon380671230111::ETC2Block417     static int extend_5to8bits(int x) { return (x << 3) | (x >> 2); }
extend_6to8bitsangle::__anon380671230111::ETC2Block418     static int extend_6to8bits(int x) { return (x << 2) | (x >> 4); }
extend_7to8bitsangle::__anon380671230111::ETC2Block419     static int extend_7to8bits(int x) { return (x << 1) | (x >> 6); }
420 
decodeIndividualBlockangle::__anon380671230111::ETC2Block421     void decodeIndividualBlock(uint8_t *dest,
422                                size_t x,
423                                size_t y,
424                                size_t w,
425                                size_t h,
426                                size_t destRowPitch,
427                                const uint8_t alphaValues[4][4],
428                                bool nonOpaquePunchThroughAlpha) const
429     {
430         const auto &block = u.idht.mode.idm.colors.indiv;
431         int r1            = extend_4to8bits(block.R1);
432         int g1            = extend_4to8bits(block.G1);
433         int b1            = extend_4to8bits(block.B1);
434         int r2            = extend_4to8bits(block.R2);
435         int g2            = extend_4to8bits(block.G2);
436         int b2            = extend_4to8bits(block.B2);
437         decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2,
438                                             alphaValues, nonOpaquePunchThroughAlpha);
439     }
440 
decodeDifferentialBlockangle::__anon380671230111::ETC2Block441     void decodeDifferentialBlock(uint8_t *dest,
442                                  size_t x,
443                                  size_t y,
444                                  size_t w,
445                                  size_t h,
446                                  size_t destRowPitch,
447                                  const uint8_t alphaValues[4][4],
448                                  bool nonOpaquePunchThroughAlpha) const
449     {
450         const auto &block = u.idht.mode.idm.colors.diff;
451         int b1            = extend_5to8bits(block.B);
452         int g1            = extend_5to8bits(block.G);
453         int r1            = extend_5to8bits(block.R);
454         int r2            = extend_5to8bits(block.R + block.dR);
455         int g2            = extend_5to8bits(block.G + block.dG);
456         int b2            = extend_5to8bits(block.B + block.dB);
457         decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2,
458                                             alphaValues, nonOpaquePunchThroughAlpha);
459     }
460 
decodeIndividualOrDifferentialBlockangle::__anon380671230111::ETC2Block461     void decodeIndividualOrDifferentialBlock(uint8_t *dest,
462                                              size_t x,
463                                              size_t y,
464                                              size_t w,
465                                              size_t h,
466                                              size_t destRowPitch,
467                                              int r1,
468                                              int g1,
469                                              int b1,
470                                              int r2,
471                                              int g2,
472                                              int b2,
473                                              const uint8_t alphaValues[4][4],
474                                              bool nonOpaquePunchThroughAlpha) const
475     {
476         const IntensityModifier *intensityModifier =
477             nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault;
478 
479         R8G8B8A8 subblockColors0[4];
480         R8G8B8A8 subblockColors1[4];
481         for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++)
482         {
483             const int i1                 = intensityModifier[u.idht.mode.idm.cw1][modifierIdx];
484             subblockColors0[modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1);
485 
486             const int i2                 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx];
487             subblockColors1[modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2);
488         }
489 
490         if (u.idht.mode.idm.flipbit)
491         {
492             uint8_t *curPixel = dest;
493             for (size_t j = 0; j < 2 && (y + j) < h; j++)
494             {
495                 R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
496                 for (size_t i = 0; i < 4 && (x + i) < w; i++)
497                 {
498                     row[i]   = subblockColors0[getIndex(i, j)];
499                     row[i].A = alphaValues[j][i];
500                 }
501                 curPixel += destRowPitch;
502             }
503             for (size_t j = 2; j < 4 && (y + j) < h; j++)
504             {
505                 R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
506                 for (size_t i = 0; i < 4 && (x + i) < w; i++)
507                 {
508                     row[i]   = subblockColors1[getIndex(i, j)];
509                     row[i].A = alphaValues[j][i];
510                 }
511                 curPixel += destRowPitch;
512             }
513         }
514         else
515         {
516             uint8_t *curPixel = dest;
517             for (size_t j = 0; j < 4 && (y + j) < h; j++)
518             {
519                 R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
520                 for (size_t i = 0; i < 2 && (x + i) < w; i++)
521                 {
522                     row[i]   = subblockColors0[getIndex(i, j)];
523                     row[i].A = alphaValues[j][i];
524                 }
525                 for (size_t i = 2; i < 4 && (x + i) < w; i++)
526                 {
527                     row[i]   = subblockColors1[getIndex(i, j)];
528                     row[i].A = alphaValues[j][i];
529                 }
530                 curPixel += destRowPitch;
531             }
532         }
533         if (nonOpaquePunchThroughAlpha)
534         {
535             decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
536         }
537     }
538 
decodeTBlockangle::__anon380671230111::ETC2Block539     void decodeTBlock(uint8_t *dest,
540                       size_t x,
541                       size_t y,
542                       size_t w,
543                       size_t h,
544                       size_t destRowPitch,
545                       const uint8_t alphaValues[4][4],
546                       bool nonOpaquePunchThroughAlpha) const
547     {
548         // Table C.8, distance index for T and H modes
549         const auto &block = u.idht.mode.tm;
550 
551         int r1 = extend_4to8bits(block.TR1a << 2 | block.TR1b);
552         int g1 = extend_4to8bits(block.TG1);
553         int b1 = extend_4to8bits(block.TB1);
554         int r2 = extend_4to8bits(block.TR2);
555         int g2 = extend_4to8bits(block.TG2);
556         int b2 = extend_4to8bits(block.TB2);
557 
558         static int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
559         const int d            = distance[block.Tda << 1 | block.Tdb];
560 
561         const R8G8B8A8 paintColors[4] = {
562             createRGBA(r1, g1, b1),
563             createRGBA(r2 + d, g2 + d, b2 + d),
564             createRGBA(r2, g2, b2),
565             createRGBA(r2 - d, g2 - d, b2 - d),
566         };
567 
568         uint8_t *curPixel = dest;
569         for (size_t j = 0; j < 4 && (y + j) < h; j++)
570         {
571             R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
572             for (size_t i = 0; i < 4 && (x + i) < w; i++)
573             {
574                 row[i]   = paintColors[getIndex(i, j)];
575                 row[i].A = alphaValues[j][i];
576             }
577             curPixel += destRowPitch;
578         }
579 
580         if (nonOpaquePunchThroughAlpha)
581         {
582             decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
583         }
584     }
585 
decodeHBlockangle::__anon380671230111::ETC2Block586     void decodeHBlock(uint8_t *dest,
587                       size_t x,
588                       size_t y,
589                       size_t w,
590                       size_t h,
591                       size_t destRowPitch,
592                       const uint8_t alphaValues[4][4],
593                       bool nonOpaquePunchThroughAlpha) const
594     {
595         // Table C.8, distance index for T and H modes
596         const auto &block = u.idht.mode.hm;
597 
598         int r1 = extend_4to8bits(block.HR1);
599         int g1 = extend_4to8bits(block.HG1a << 1 | block.HG1b);
600         int b1 = extend_4to8bits(block.HB1a << 3 | block.HB1b << 1 | block.HB1c);
601         int r2 = extend_4to8bits(block.HR2);
602         int g2 = extend_4to8bits(block.HG2a << 1 | block.HG2b);
603         int b2 = extend_4to8bits(block.HB2);
604 
605         static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
606         const int orderingTrickBit =
607             ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0);
608         const int d = distance[(block.Hda << 2) | (block.Hdb << 1) | orderingTrickBit];
609 
610         const R8G8B8A8 paintColors[4] = {
611             createRGBA(r1 + d, g1 + d, b1 + d),
612             createRGBA(r1 - d, g1 - d, b1 - d),
613             createRGBA(r2 + d, g2 + d, b2 + d),
614             createRGBA(r2 - d, g2 - d, b2 - d),
615         };
616 
617         uint8_t *curPixel = dest;
618         for (size_t j = 0; j < 4 && (y + j) < h; j++)
619         {
620             R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
621             for (size_t i = 0; i < 4 && (x + i) < w; i++)
622             {
623                 row[i]   = paintColors[getIndex(i, j)];
624                 row[i].A = alphaValues[j][i];
625             }
626             curPixel += destRowPitch;
627         }
628 
629         if (nonOpaquePunchThroughAlpha)
630         {
631             decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
632         }
633     }
634 
decodePlanarBlockangle::__anon380671230111::ETC2Block635     void decodePlanarBlock(uint8_t *dest,
636                            size_t x,
637                            size_t y,
638                            size_t w,
639                            size_t h,
640                            size_t pitch,
641                            const uint8_t alphaValues[4][4]) const
642     {
643         int ro = extend_6to8bits(u.pblk.RO);
644         int go = extend_7to8bits(u.pblk.GO1 << 6 | u.pblk.GO2);
645         int bo =
646             extend_6to8bits(u.pblk.BO1 << 5 | u.pblk.BO2 << 3 | u.pblk.BO3a << 1 | u.pblk.BO3b);
647         int rh = extend_6to8bits(u.pblk.RH1 << 1 | u.pblk.RH2);
648         int gh = extend_7to8bits(u.pblk.GH);
649         int bh = extend_6to8bits(u.pblk.BHa << 5 | u.pblk.BHb);
650         int rv = extend_6to8bits(u.pblk.RVa << 3 | u.pblk.RVb);
651         int gv = extend_7to8bits(u.pblk.GVa << 2 | u.pblk.GVb);
652         int bv = extend_6to8bits(u.pblk.BV);
653 
654         uint8_t *curPixel = dest;
655         for (size_t j = 0; j < 4 && (y + j) < h; j++)
656         {
657             R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
658 
659             int ry = static_cast<int>(j) * (rv - ro) + 2;
660             int gy = static_cast<int>(j) * (gv - go) + 2;
661             int by = static_cast<int>(j) * (bv - bo) + 2;
662             for (size_t i = 0; i < 4 && (x + i) < w; i++)
663             {
664                 row[i] = createRGBA(((static_cast<int>(i) * (rh - ro) + ry) >> 2) + ro,
665                                     ((static_cast<int>(i) * (gh - go) + gy) >> 2) + go,
666                                     ((static_cast<int>(i) * (bh - bo) + by) >> 2) + bo,
667                                     alphaValues[j][i]);
668             }
669             curPixel += pitch;
670         }
671     }
672 
673     // Index for individual, differential, H and T modes
getIndexangle::__anon380671230111::ETC2Block674     size_t getIndex(size_t x, size_t y) const
675     {
676         size_t bitIndex  = x * 4 + y;
677         size_t bitOffset = bitIndex & 7;
678         size_t lsb       = (u.idht.pixelIndexLSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
679         size_t msb       = (u.idht.pixelIndexMSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
680         return (msb << 1) | lsb;
681     }
682 
decodePunchThroughAlphaBlockangle::__anon380671230111::ETC2Block683     void decodePunchThroughAlphaBlock(uint8_t *dest,
684                                       size_t x,
685                                       size_t y,
686                                       size_t w,
687                                       size_t h,
688                                       size_t destRowPitch) const
689     {
690         uint8_t *curPixel = dest;
691         for (size_t j = 0; j < 4 && (y + j) < h; j++)
692         {
693             R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
694             for (size_t i = 0; i < 4 && (x + i) < w; i++)
695             {
696                 if (getIndex(i, j) == 2)  //  msb == 1 && lsb == 0
697                 {
698                     row[i] = createRGBA(0, 0, 0, 0);
699                 }
700             }
701             curPixel += destRowPitch;
702         }
703     }
704 
RGB8ToRGB565angle::__anon380671230111::ETC2Block705     uint16_t RGB8ToRGB565(const R8G8B8A8 &rgba) const
706     {
707         return (static_cast<uint16_t>(rgba.R >> 3) << 11) |
708                (static_cast<uint16_t>(rgba.G >> 2) << 5) |
709                (static_cast<uint16_t>(rgba.B >> 3) << 0);
710     }
711 
matchBC1Bitsangle::__anon380671230111::ETC2Block712     uint32_t matchBC1Bits(const int *pixelIndices,
713                           const int *pixelIndexCounts,
714                           const R8G8B8A8 *subblockColors,
715                           size_t numColors,
716                           const R8G8B8A8 &minColor,
717                           const R8G8B8A8 &maxColor,
718                           bool nonOpaquePunchThroughAlpha) const
719     {
720         // Project each pixel on the (maxColor, minColor) line to decide which
721         // BC1 code to assign to it.
722 
723         uint8_t decodedColors[2][3] = {{maxColor.R, maxColor.G, maxColor.B},
724                                        {minColor.R, minColor.G, minColor.B}};
725 
726         int direction[3];
727         for (int ch = 0; ch < 3; ch++)
728         {
729             direction[ch] = decodedColors[0][ch] - decodedColors[1][ch];
730         }
731 
732         int stops[2];
733         for (int i = 0; i < 2; i++)
734         {
735             stops[i] = decodedColors[i][0] * direction[0] + decodedColors[i][1] * direction[1] +
736                        decodedColors[i][2] * direction[2];
737         }
738 
739         ASSERT(numColors <= kNumPixelsInBlock);
740 
741         int encodedColors[kNumPixelsInBlock];
742         if (nonOpaquePunchThroughAlpha)
743         {
744             for (size_t i = 0; i < numColors; i++)
745             {
746                 const int count = pixelIndexCounts[i];
747                 if (count > 0)
748                 {
749                     // In non-opaque mode, 3 is for tranparent pixels.
750 
751                     if (0 == subblockColors[i].A)
752                     {
753                         encodedColors[i] = 3;
754                     }
755                     else
756                     {
757                         const R8G8B8A8 &pixel = subblockColors[i];
758                         const int dot         = pixel.R * direction[0] + pixel.G * direction[1] +
759                                         pixel.B * direction[2];
760                         const int factor = gl::clamp(
761                             static_cast<int>(
762                                 (static_cast<float>(dot - stops[1]) / (stops[0] - stops[1])) * 2 +
763                                 0.5f),
764                             0, 2);
765                         switch (factor)
766                         {
767                             case 0:
768                                 encodedColors[i] = 0;
769                                 break;
770                             case 1:
771                                 encodedColors[i] = 2;
772                                 break;
773                             case 2:
774                             default:
775                                 encodedColors[i] = 1;
776                                 break;
777                         }
778                     }
779                 }
780             }
781         }
782         else
783         {
784             for (size_t i = 0; i < numColors; i++)
785             {
786                 const int count = pixelIndexCounts[i];
787                 if (count > 0)
788                 {
789                     // In opaque mode, the code is from 0 to 3.
790 
791                     const R8G8B8A8 &pixel = subblockColors[i];
792                     const int dot =
793                         pixel.R * direction[0] + pixel.G * direction[1] + pixel.B * direction[2];
794                     const int factor = gl::clamp(
795                         static_cast<int>(
796                             (static_cast<float>(dot - stops[1]) / (stops[0] - stops[1])) * 3 +
797                             0.5f),
798                         0, 3);
799                     switch (factor)
800                     {
801                         case 0:
802                             encodedColors[i] = 1;
803                             break;
804                         case 1:
805                             encodedColors[i] = 3;
806                             break;
807                         case 2:
808                             encodedColors[i] = 2;
809                             break;
810                         case 3:
811                         default:
812                             encodedColors[i] = 0;
813                             break;
814                     }
815                 }
816             }
817         }
818 
819         uint32_t bits = 0;
820         for (int i = kNumPixelsInBlock - 1; i >= 0; i--)
821         {
822             bits <<= 2;
823             bits |= encodedColors[pixelIndices[i]];
824         }
825 
826         return bits;
827     }
828 
packBC1angle::__anon380671230111::ETC2Block829     void packBC1(void *bc1,
830                  const int *pixelIndices,
831                  const int *pixelIndexCounts,
832                  const R8G8B8A8 *subblockColors,
833                  size_t numColors,
834                  int minColorIndex,
835                  int maxColorIndex,
836                  bool nonOpaquePunchThroughAlpha) const
837     {
838         const R8G8B8A8 &minColor = subblockColors[minColorIndex];
839         const R8G8B8A8 &maxColor = subblockColors[maxColorIndex];
840 
841         uint32_t bits;
842         uint16_t max16 = RGB8ToRGB565(maxColor);
843         uint16_t min16 = RGB8ToRGB565(minColor);
844         if (max16 != min16)
845         {
846             // Find the best BC1 code for each pixel
847             bits = matchBC1Bits(pixelIndices, pixelIndexCounts, subblockColors, numColors, minColor,
848                                 maxColor, nonOpaquePunchThroughAlpha);
849         }
850         else
851         {
852             // Same colors, BC1 index 0 is the color in both opaque and transparent mode
853             bits = 0;
854             // BC1 index 3 is transparent
855             if (nonOpaquePunchThroughAlpha)
856             {
857                 for (int i = 0; i < kNumPixelsInBlock; i++)
858                 {
859                     if (0 == subblockColors[pixelIndices[i]].A)
860                     {
861                         bits |= (3 << (i * 2));
862                     }
863                 }
864             }
865         }
866 
867         if (max16 < min16)
868         {
869             std::swap(max16, min16);
870 
871             uint32_t xorMask = 0;
872             if (nonOpaquePunchThroughAlpha)
873             {
874                 // In transparent mode switching the colors is doing the
875                 // following code swap: 0 <-> 1. 0xA selects the second bit of
876                 // each code, bits >> 1 selects the first bit of the code when
877                 // the seconds bit is set (case 2 and 3). We invert all the
878                 // non-selected bits, that is the first bit when the code is
879                 // 0 or 1.
880                 xorMask = ~((bits >> 1) | 0xAAAAAAAA);
881             }
882             else
883             {
884                 // In opaque mode switching the two colors is doing the
885                 // following code swaps: 0 <-> 1 and 2 <-> 3. This is
886                 // equivalent to flipping the first bit of each code
887                 // (5 = 0b0101)
888                 xorMask = 0x55555555;
889             }
890             bits ^= xorMask;
891         }
892 
893         struct BC1Block
894         {
895             uint16_t color0;
896             uint16_t color1;
897             uint32_t bits;
898         };
899 
900         // Encode the opaqueness in the order of the two BC1 colors
901         BC1Block *dest = reinterpret_cast<BC1Block *>(bc1);
902         if (nonOpaquePunchThroughAlpha)
903         {
904             dest->color0 = min16;
905             dest->color1 = max16;
906         }
907         else
908         {
909             dest->color0 = max16;
910             dest->color1 = min16;
911         }
912         dest->bits = bits;
913     }
914 
transcodeIndividualBlockToBC1angle::__anon380671230111::ETC2Block915     void transcodeIndividualBlockToBC1(uint8_t *dest,
916                                        size_t x,
917                                        size_t y,
918                                        size_t w,
919                                        size_t h,
920                                        const uint8_t alphaValues[4][4],
921                                        bool nonOpaquePunchThroughAlpha) const
922     {
923         const auto &block = u.idht.mode.idm.colors.indiv;
924         int r1            = extend_4to8bits(block.R1);
925         int g1            = extend_4to8bits(block.G1);
926         int b1            = extend_4to8bits(block.B1);
927         int r2            = extend_4to8bits(block.R2);
928         int g2            = extend_4to8bits(block.G2);
929         int b2            = extend_4to8bits(block.B2);
930         transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2,
931                                                     alphaValues, nonOpaquePunchThroughAlpha);
932     }
933 
transcodeDifferentialBlockToBC1angle::__anon380671230111::ETC2Block934     void transcodeDifferentialBlockToBC1(uint8_t *dest,
935                                          size_t x,
936                                          size_t y,
937                                          size_t w,
938                                          size_t h,
939                                          const uint8_t alphaValues[4][4],
940                                          bool nonOpaquePunchThroughAlpha) const
941     {
942         const auto &block = u.idht.mode.idm.colors.diff;
943         int b1            = extend_5to8bits(block.B);
944         int g1            = extend_5to8bits(block.G);
945         int r1            = extend_5to8bits(block.R);
946         int r2            = extend_5to8bits(block.R + block.dR);
947         int g2            = extend_5to8bits(block.G + block.dG);
948         int b2            = extend_5to8bits(block.B + block.dB);
949         transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2,
950                                                     alphaValues, nonOpaquePunchThroughAlpha);
951     }
952 
extractPixelIndicesangle::__anon380671230111::ETC2Block953     void extractPixelIndices(int *pixelIndices,
954                              int *pixelIndicesCounts,
955                              size_t x,
956                              size_t y,
957                              size_t w,
958                              size_t h,
959                              bool flipbit,
960                              size_t subblockIdx) const
961     {
962         size_t dxBegin = 0;
963         size_t dxEnd   = 4;
964         size_t dyBegin = subblockIdx * 2;
965         size_t dyEnd   = dyBegin + 2;
966         if (!flipbit)
967         {
968             std::swap(dxBegin, dyBegin);
969             std::swap(dxEnd, dyEnd);
970         }
971 
972         for (size_t j = dyBegin; j < dyEnd; j++)
973         {
974             int *row = &pixelIndices[j * 4];
975             for (size_t i = dxBegin; i < dxEnd; i++)
976             {
977                 const size_t pixelIndex = subblockIdx * 4 + getIndex(i, j);
978                 row[i]                  = static_cast<int>(pixelIndex);
979                 pixelIndicesCounts[pixelIndex]++;
980             }
981         }
982     }
983 
selectEndPointPCAangle::__anon380671230111::ETC2Block984     void selectEndPointPCA(const int *pixelIndexCounts,
985                            const R8G8B8A8 *subblockColors,
986                            size_t numColors,
987                            int *minColorIndex,
988                            int *maxColorIndex) const
989     {
990         // determine color distribution
991         int mu[3], min[3], max[3];
992         for (int ch = 0; ch < 3; ch++)
993         {
994             int muv  = 0;
995             int minv = 255;
996             int maxv = 0;
997             for (size_t i = 0; i < numColors; i++)
998             {
999                 const int count = pixelIndexCounts[i];
1000                 if (count > 0)
1001                 {
1002                     const auto &pixel = subblockColors[i];
1003                     if (pixel.A > 0)
1004                     {
1005                         // Non-transparent pixels
1006                         muv += (&pixel.R)[ch] * count;
1007                         minv = std::min<int>(minv, (&pixel.R)[ch]);
1008                         maxv = std::max<int>(maxv, (&pixel.R)[ch]);
1009                     }
1010                 }
1011             }
1012 
1013             mu[ch]  = (muv + kNumPixelsInBlock / 2) / kNumPixelsInBlock;
1014             min[ch] = minv;
1015             max[ch] = maxv;
1016         }
1017 
1018         // determine covariance matrix
1019         int cov[6] = {0, 0, 0, 0, 0, 0};
1020         for (size_t i = 0; i < numColors; i++)
1021         {
1022             const int count = pixelIndexCounts[i];
1023             if (count > 0)
1024             {
1025                 const auto &pixel = subblockColors[i];
1026                 if (pixel.A > 0)
1027                 {
1028                     int r = pixel.R - mu[0];
1029                     int g = pixel.G - mu[1];
1030                     int b = pixel.B - mu[2];
1031 
1032                     cov[0] += r * r * count;
1033                     cov[1] += r * g * count;
1034                     cov[2] += r * b * count;
1035                     cov[3] += g * g * count;
1036                     cov[4] += g * b * count;
1037                     cov[5] += b * b * count;
1038                 }
1039             }
1040         }
1041 
1042         // Power iteration algorithm to get the eigenvalues and eigenvector
1043 
1044         // Starts with diagonal vector
1045         float vfr        = static_cast<float>(max[0] - min[0]);
1046         float vfg        = static_cast<float>(max[1] - min[1]);
1047         float vfb        = static_cast<float>(max[2] - min[2]);
1048         float eigenvalue = 0.0f;
1049 
1050         constexpr size_t kPowerIterations = 4;
1051         for (size_t i = 0; i < kPowerIterations; i++)
1052         {
1053             float r = vfr * cov[0] + vfg * cov[1] + vfb * cov[2];
1054             float g = vfr * cov[1] + vfg * cov[3] + vfb * cov[4];
1055             float b = vfr * cov[2] + vfg * cov[4] + vfb * cov[5];
1056 
1057             vfr = r;
1058             vfg = g;
1059             vfb = b;
1060 
1061             eigenvalue = sqrt(r * r + g * g + b * b);
1062             if (eigenvalue > 0)
1063             {
1064                 float invNorm = 1.0f / eigenvalue;
1065                 vfr *= invNorm;
1066                 vfg *= invNorm;
1067                 vfb *= invNorm;
1068             }
1069         }
1070 
1071         int vr, vg, vb;
1072 
1073         static const float kDefaultLuminanceThreshold = 4.0f * 255;
1074         static const float kQuantizeRange             = 512.0f;
1075         if (eigenvalue < kDefaultLuminanceThreshold)  // too small, default to luminance
1076         {
1077             // Luminance weights defined by ITU-R Recommendation BT.601, scaled by 1000
1078             vr = 299;
1079             vg = 587;
1080             vb = 114;
1081         }
1082         else
1083         {
1084             // From the eigenvalue and eigenvector, choose the axis to project
1085             // colors on. When projecting colors we want to do integer computations
1086             // for speed, so we normalize the eigenvector to the [0, 512] range.
1087             float magn = std::max(std::max(std::abs(vfr), std::abs(vfg)), std::abs(vfb));
1088             magn       = kQuantizeRange / magn;
1089             vr         = static_cast<int>(vfr * magn);
1090             vg         = static_cast<int>(vfg * magn);
1091             vb         = static_cast<int>(vfb * magn);
1092         }
1093 
1094         // Pick colors at extreme points
1095         int minD        = INT_MAX;
1096         int maxD        = 0;
1097         size_t minIndex = 0;
1098         size_t maxIndex = 0;
1099         for (size_t i = 0; i < numColors; i++)
1100         {
1101             const int count = pixelIndexCounts[i];
1102             if (count > 0)
1103             {
1104                 const auto &pixel = subblockColors[i];
1105                 if (pixel.A > 0)
1106                 {
1107                     int dot = pixel.R * vr + pixel.G * vg + pixel.B * vb;
1108                     if (dot < minD)
1109                     {
1110                         minD     = dot;
1111                         minIndex = i;
1112                     }
1113                     if (dot > maxD)
1114                     {
1115                         maxD     = dot;
1116                         maxIndex = i;
1117                     }
1118                 }
1119             }
1120         }
1121 
1122         *minColorIndex = static_cast<int>(minIndex);
1123         *maxColorIndex = static_cast<int>(maxIndex);
1124     }
1125 
transcodeIndividualOrDifferentialBlockToBC1angle::__anon380671230111::ETC2Block1126     void transcodeIndividualOrDifferentialBlockToBC1(uint8_t *dest,
1127                                                      size_t x,
1128                                                      size_t y,
1129                                                      size_t w,
1130                                                      size_t h,
1131                                                      int r1,
1132                                                      int g1,
1133                                                      int b1,
1134                                                      int r2,
1135                                                      int g2,
1136                                                      int b2,
1137                                                      const uint8_t alphaValues[4][4],
1138                                                      bool nonOpaquePunchThroughAlpha) const
1139     {
1140         // A BC1 block has 2 endpoints, pixels is encoded as linear
1141         // interpolations of them. A ETC1/ETC2 individual or differential block
1142         // has 2 subblocks. Each subblock has one color and a modifier. We
1143         // select axis by principal component analysis (PCA) to use as
1144         // our two BC1 endpoints and then map pixels to BC1 by projecting on the
1145         // line between the two endpoints and choosing the right fraction.
1146 
1147         // The goal of this algorithm is make it faster than decode ETC to RGBs
1148         //   and then encode to BC. To achieve this, we only extract subblock
1149         //   colors, pixel indices, and counts of each pixel indices from ETC.
1150         //   With those information, we can only encode used subblock colors
1151         //   to BC1, and copy the bits to the right pixels.
1152         // Fully decode and encode need to process 16 RGBA pixels. With this
1153         //   algorithm, it's 8 pixels at maximum for a individual or
1154         //   differential block. Saves us bandwidth and computations.
1155 
1156         static const size_t kNumColors = 8;
1157 
1158         const IntensityModifier *intensityModifier =
1159             nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault;
1160 
1161         // Compute the colors that pixels can have in each subblock both for
1162         // the decoding of the RGBA data and BC1 encoding
1163         R8G8B8A8 subblockColors[kNumColors];
1164         for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++)
1165         {
1166             if (nonOpaquePunchThroughAlpha && (modifierIdx == 2))
1167             {
1168                 // In ETC opaque punch through formats, individual and
1169                 // differential blocks take index 2 as transparent pixel.
1170                 // Thus we don't need to compute its color, just assign it
1171                 // as black.
1172                 subblockColors[modifierIdx]     = createRGBA(0, 0, 0, 0);
1173                 subblockColors[4 + modifierIdx] = createRGBA(0, 0, 0, 0);
1174             }
1175             else
1176             {
1177                 const int i1                = intensityModifier[u.idht.mode.idm.cw1][modifierIdx];
1178                 subblockColors[modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1);
1179 
1180                 const int i2 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx];
1181                 subblockColors[4 + modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2);
1182             }
1183         }
1184 
1185         int pixelIndices[kNumPixelsInBlock];
1186         int pixelIndexCounts[kNumColors] = {0};
1187         // Extract pixel indices from a ETC block.
1188         for (size_t blockIdx = 0; blockIdx < 2; blockIdx++)
1189         {
1190             extractPixelIndices(pixelIndices, pixelIndexCounts, x, y, w, h, u.idht.mode.idm.flipbit,
1191                                 blockIdx);
1192         }
1193 
1194         int minColorIndex, maxColorIndex;
1195         selectEndPointPCA(pixelIndexCounts, subblockColors, kNumColors, &minColorIndex,
1196                           &maxColorIndex);
1197 
1198         packBC1(dest, pixelIndices, pixelIndexCounts, subblockColors, kNumColors, minColorIndex,
1199                 maxColorIndex, nonOpaquePunchThroughAlpha);
1200     }
1201 
transcodeTBlockToBC1angle::__anon380671230111::ETC2Block1202     void transcodeTBlockToBC1(uint8_t *dest,
1203                               size_t x,
1204                               size_t y,
1205                               size_t w,
1206                               size_t h,
1207                               const uint8_t alphaValues[4][4],
1208                               bool nonOpaquePunchThroughAlpha) const
1209     {
1210         static const size_t kNumColors = 4;
1211 
1212         // Table C.8, distance index for T and H modes
1213         const auto &block = u.idht.mode.tm;
1214 
1215         int r1 = extend_4to8bits(block.TR1a << 2 | block.TR1b);
1216         int g1 = extend_4to8bits(block.TG1);
1217         int b1 = extend_4to8bits(block.TB1);
1218         int r2 = extend_4to8bits(block.TR2);
1219         int g2 = extend_4to8bits(block.TG2);
1220         int b2 = extend_4to8bits(block.TB2);
1221 
1222         static int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
1223         const int d            = distance[block.Tda << 1 | block.Tdb];
1224 
1225         // In ETC opaque punch through formats, index == 2 means transparent pixel.
1226         // Thus we don't need to compute its color, just assign it as black.
1227         const R8G8B8A8 paintColors[kNumColors] = {
1228             createRGBA(r1, g1, b1),
1229             createRGBA(r2 + d, g2 + d, b2 + d),
1230             nonOpaquePunchThroughAlpha ? createRGBA(0, 0, 0, 0) : createRGBA(r2, g2, b2),
1231             createRGBA(r2 - d, g2 - d, b2 - d),
1232         };
1233 
1234         int pixelIndices[kNumPixelsInBlock];
1235         int pixelIndexCounts[kNumColors] = {0};
1236         for (size_t j = 0; j < 4; j++)
1237         {
1238             int *row = &pixelIndices[j * 4];
1239             for (size_t i = 0; i < 4; i++)
1240             {
1241                 const size_t pixelIndex = getIndex(i, j);
1242                 row[i]                  = static_cast<int>(pixelIndex);
1243                 pixelIndexCounts[pixelIndex]++;
1244             }
1245         }
1246 
1247         int minColorIndex, maxColorIndex;
1248         selectEndPointPCA(pixelIndexCounts, paintColors, kNumColors, &minColorIndex,
1249                           &maxColorIndex);
1250 
1251         packBC1(dest, pixelIndices, pixelIndexCounts, paintColors, kNumColors, minColorIndex,
1252                 maxColorIndex, nonOpaquePunchThroughAlpha);
1253     }
1254 
transcodeHBlockToBC1angle::__anon380671230111::ETC2Block1255     void transcodeHBlockToBC1(uint8_t *dest,
1256                               size_t x,
1257                               size_t y,
1258                               size_t w,
1259                               size_t h,
1260                               const uint8_t alphaValues[4][4],
1261                               bool nonOpaquePunchThroughAlpha) const
1262     {
1263         static const size_t kNumColors = 4;
1264 
1265         // Table C.8, distance index for T and H modes
1266         const auto &block = u.idht.mode.hm;
1267 
1268         int r1 = extend_4to8bits(block.HR1);
1269         int g1 = extend_4to8bits(block.HG1a << 1 | block.HG1b);
1270         int b1 = extend_4to8bits(block.HB1a << 3 | block.HB1b << 1 | block.HB1c);
1271         int r2 = extend_4to8bits(block.HR2);
1272         int g2 = extend_4to8bits(block.HG2a << 1 | block.HG2b);
1273         int b2 = extend_4to8bits(block.HB2);
1274 
1275         static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
1276         const int orderingTrickBit =
1277             ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0);
1278         const int d = distance[(block.Hda << 2) | (block.Hdb << 1) | orderingTrickBit];
1279 
1280         // In ETC opaque punch through formats, index == 2 means transparent pixel.
1281         // Thus we don't need to compute its color, just assign it as black.
1282         const R8G8B8A8 paintColors[kNumColors] = {
1283             createRGBA(r1 + d, g1 + d, b1 + d),
1284             createRGBA(r1 - d, g1 - d, b1 - d),
1285             nonOpaquePunchThroughAlpha ? createRGBA(0, 0, 0, 0)
1286                                        : createRGBA(r2 + d, g2 + d, b2 + d),
1287             createRGBA(r2 - d, g2 - d, b2 - d),
1288         };
1289 
1290         int pixelIndices[kNumPixelsInBlock];
1291         int pixelIndexCounts[kNumColors] = {0};
1292         for (size_t j = 0; j < 4; j++)
1293         {
1294             int *row = &pixelIndices[j * 4];
1295             for (size_t i = 0; i < 4; i++)
1296             {
1297                 const size_t pixelIndex = getIndex(i, j);
1298                 row[i]                  = static_cast<int>(pixelIndex);
1299                 pixelIndexCounts[pixelIndex]++;
1300             }
1301         }
1302 
1303         int minColorIndex, maxColorIndex;
1304         selectEndPointPCA(pixelIndexCounts, paintColors, kNumColors, &minColorIndex,
1305                           &maxColorIndex);
1306 
1307         packBC1(dest, pixelIndices, pixelIndexCounts, paintColors, kNumColors, minColorIndex,
1308                 maxColorIndex, nonOpaquePunchThroughAlpha);
1309     }
1310 
transcodePlanarBlockToBC1angle::__anon380671230111::ETC2Block1311     void transcodePlanarBlockToBC1(uint8_t *dest,
1312                                    size_t x,
1313                                    size_t y,
1314                                    size_t w,
1315                                    size_t h,
1316                                    const uint8_t alphaValues[4][4]) const
1317     {
1318         static const size_t kNumColors = kNumPixelsInBlock;
1319 
1320         R8G8B8A8 rgbaBlock[kNumColors];
1321         decodePlanarBlock(reinterpret_cast<uint8_t *>(rgbaBlock), x, y, w, h, sizeof(R8G8B8A8) * 4,
1322                           alphaValues);
1323 
1324         // Planar block doesn't have a color table, fill indices as full
1325         int pixelIndices[kNumPixelsInBlock] = {0, 1, 2,  3,  4,  5,  6,  7,
1326                                                8, 9, 10, 11, 12, 13, 14, 15};
1327         int pixelIndexCounts[kNumColors]    = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
1328 
1329         int minColorIndex, maxColorIndex;
1330         selectEndPointPCA(pixelIndexCounts, rgbaBlock, kNumColors, &minColorIndex, &maxColorIndex);
1331 
1332         packBC1(dest, pixelIndices, pixelIndexCounts, rgbaBlock, kNumColors, minColorIndex,
1333                 maxColorIndex, false);
1334     }
1335 
1336     // Single channel utility functions
getSingleEACChannelangle::__anon380671230111::ETC2Block1337     int getSingleEACChannel(size_t x, size_t y, bool isSigned) const
1338     {
1339         int codeword   = isSigned ? u.scblk.base_codeword.s : u.scblk.base_codeword.us;
1340         int multiplier = (u.scblk.multiplier == 0) ? 1 : u.scblk.multiplier * 8;
1341         return codeword * 8 + 4 + getSingleChannelModifier(x, y) * multiplier;
1342     }
1343 
getSingleETC2Channelangle::__anon380671230111::ETC2Block1344     int getSingleETC2Channel(size_t x, size_t y, bool isSigned) const
1345     {
1346         int codeword = isSigned ? u.scblk.base_codeword.s : u.scblk.base_codeword.us;
1347         return codeword + getSingleChannelModifier(x, y) * u.scblk.multiplier;
1348     }
1349 
getSingleChannelIndexangle::__anon380671230111::ETC2Block1350     int getSingleChannelIndex(size_t x, size_t y) const
1351     {
1352         ASSERT(x < 4 && y < 4);
1353 
1354         // clang-format off
1355         switch (x * 4 + y)
1356         {
1357             case 0: return u.scblk.ma;
1358             case 1: return u.scblk.mb;
1359             case 2: return u.scblk.mc1 << 1 | u.scblk.mc2;
1360             case 3: return u.scblk.md;
1361             case 4: return u.scblk.me;
1362             case 5: return u.scblk.mf1 << 2 | u.scblk.mf2;
1363             case 6: return u.scblk.mg;
1364             case 7: return u.scblk.mh;
1365             case 8: return u.scblk.mi;
1366             case 9: return u.scblk.mj;
1367             case 10: return u.scblk.mk1 << 1 | u.scblk.mk2;
1368             case 11: return u.scblk.ml;
1369             case 12: return u.scblk.mm;
1370             case 13: return u.scblk.mn1 << 2 | u.scblk.mn2;
1371             case 14: return u.scblk.mo;
1372             case 15: return u.scblk.mp;
1373             default: UNREACHABLE(); return 0;
1374         }
1375         // clang-format on
1376     }
1377 
getSingleChannelModifierangle::__anon380671230111::ETC2Block1378     int getSingleChannelModifier(size_t x, size_t y) const
1379     {
1380         // clang-format off
1381         static const int modifierTable[16][8] =
1382         {
1383             { -3, -6,  -9, -15, 2, 5, 8, 14 },
1384             { -3, -7, -10, -13, 2, 6, 9, 12 },
1385             { -2, -5,  -8, -13, 1, 4, 7, 12 },
1386             { -2, -4,  -6, -13, 1, 3, 5, 12 },
1387             { -3, -6,  -8, -12, 2, 5, 7, 11 },
1388             { -3, -7,  -9, -11, 2, 6, 8, 10 },
1389             { -4, -7,  -8, -11, 3, 6, 7, 10 },
1390             { -3, -5,  -8, -11, 2, 4, 7, 10 },
1391             { -2, -6,  -8, -10, 1, 5, 7,  9 },
1392             { -2, -5,  -8, -10, 1, 4, 7,  9 },
1393             { -2, -4,  -8, -10, 1, 3, 7,  9 },
1394             { -2, -5,  -7, -10, 1, 4, 6,  9 },
1395             { -3, -4,  -7, -10, 2, 3, 6,  9 },
1396             { -1, -2,  -3, -10, 0, 1, 2,  9 },
1397             { -4, -6,  -8,  -9, 3, 5, 7,  8 },
1398             { -3, -5,  -7,  -9, 2, 4, 6,  8 }
1399         };
1400         // clang-format on
1401 
1402         return modifierTable[u.scblk.table_index][getSingleChannelIndex(x, y)];
1403     }
1404 };
1405 
1406 // clang-format off
1407 static const uint8_t DefaultETCAlphaValues[4][4] =
1408 {
1409     { 255, 255, 255, 255 },
1410     { 255, 255, 255, 255 },
1411     { 255, 255, 255, 255 },
1412     { 255, 255, 255, 255 },
1413 };
1414 
1415 // clang-format on
LoadR11EACToR8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch,bool isSigned)1416 void LoadR11EACToR8(size_t width,
1417                     size_t height,
1418                     size_t depth,
1419                     const uint8_t *input,
1420                     size_t inputRowPitch,
1421                     size_t inputDepthPitch,
1422                     uint8_t *output,
1423                     size_t outputRowPitch,
1424                     size_t outputDepthPitch,
1425                     bool isSigned)
1426 {
1427     for (size_t z = 0; z < depth; z++)
1428     {
1429         for (size_t y = 0; y < height; y += 4)
1430         {
1431             const ETC2Block *sourceRow =
1432                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1433             uint8_t *destRow =
1434                 priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
1435 
1436             for (size_t x = 0; x < width; x += 4)
1437             {
1438                 const ETC2Block *sourceBlock = sourceRow + (x / 4);
1439                 uint8_t *destPixels          = destRow + x;
1440 
1441                 sourceBlock->decodeAsSingleETC2Channel(destPixels, x, y, width, height, 1,
1442                                                        outputRowPitch, isSigned);
1443             }
1444         }
1445     }
1446 }
1447 
LoadRG11EACToRG8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch,bool isSigned)1448 void LoadRG11EACToRG8(size_t width,
1449                       size_t height,
1450                       size_t depth,
1451                       const uint8_t *input,
1452                       size_t inputRowPitch,
1453                       size_t inputDepthPitch,
1454                       uint8_t *output,
1455                       size_t outputRowPitch,
1456                       size_t outputDepthPitch,
1457                       bool isSigned)
1458 {
1459     for (size_t z = 0; z < depth; z++)
1460     {
1461         for (size_t y = 0; y < height; y += 4)
1462         {
1463             const ETC2Block *sourceRow =
1464                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1465             uint8_t *destRow =
1466                 priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
1467 
1468             for (size_t x = 0; x < width; x += 4)
1469             {
1470                 uint8_t *destPixelsRed          = destRow + (x * 2);
1471                 const ETC2Block *sourceBlockRed = sourceRow + (x / 2);
1472                 sourceBlockRed->decodeAsSingleETC2Channel(destPixelsRed, x, y, width, height, 2,
1473                                                           outputRowPitch, isSigned);
1474 
1475                 uint8_t *destPixelsGreen          = destPixelsRed + 1;
1476                 const ETC2Block *sourceBlockGreen = sourceBlockRed + 1;
1477                 sourceBlockGreen->decodeAsSingleETC2Channel(destPixelsGreen, x, y, width, height, 2,
1478                                                             outputRowPitch, isSigned);
1479             }
1480         }
1481     }
1482 }
1483 
LoadR11EACToR16(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch,bool isSigned,bool isFloat)1484 void LoadR11EACToR16(size_t width,
1485                      size_t height,
1486                      size_t depth,
1487                      const uint8_t *input,
1488                      size_t inputRowPitch,
1489                      size_t inputDepthPitch,
1490                      uint8_t *output,
1491                      size_t outputRowPitch,
1492                      size_t outputDepthPitch,
1493                      bool isSigned,
1494                      bool isFloat)
1495 {
1496     for (size_t z = 0; z < depth; z++)
1497     {
1498         for (size_t y = 0; y < height; y += 4)
1499         {
1500             const ETC2Block *sourceRow =
1501                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1502             uint16_t *destRow =
1503                 priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
1504 
1505             for (size_t x = 0; x < width; x += 4)
1506             {
1507                 const ETC2Block *sourceBlock = sourceRow + (x / 4);
1508                 uint16_t *destPixels         = destRow + x;
1509 
1510                 sourceBlock->decodeAsSingleEACChannel(destPixels, x, y, width, height, 1,
1511                                                       outputRowPitch, isSigned, isFloat);
1512             }
1513         }
1514     }
1515 }
1516 
LoadRG11EACToRG16(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch,bool isSigned,bool isFloat)1517 void LoadRG11EACToRG16(size_t width,
1518                        size_t height,
1519                        size_t depth,
1520                        const uint8_t *input,
1521                        size_t inputRowPitch,
1522                        size_t inputDepthPitch,
1523                        uint8_t *output,
1524                        size_t outputRowPitch,
1525                        size_t outputDepthPitch,
1526                        bool isSigned,
1527                        bool isFloat)
1528 {
1529     for (size_t z = 0; z < depth; z++)
1530     {
1531         for (size_t y = 0; y < height; y += 4)
1532         {
1533             const ETC2Block *sourceRow =
1534                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1535             uint16_t *destRow =
1536                 priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
1537 
1538             for (size_t x = 0; x < width; x += 4)
1539             {
1540                 uint16_t *destPixelsRed         = destRow + (x * 2);
1541                 const ETC2Block *sourceBlockRed = sourceRow + (x / 2);
1542                 sourceBlockRed->decodeAsSingleEACChannel(destPixelsRed, x, y, width, height, 2,
1543                                                          outputRowPitch, isSigned, isFloat);
1544 
1545                 uint16_t *destPixelsGreen         = destPixelsRed + 1;
1546                 const ETC2Block *sourceBlockGreen = sourceBlockRed + 1;
1547                 sourceBlockGreen->decodeAsSingleEACChannel(destPixelsGreen, x, y, width, height, 2,
1548                                                            outputRowPitch, isSigned, isFloat);
1549             }
1550         }
1551     }
1552 }
1553 
LoadETC2RGB8ToRGBA8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch,bool punchthroughAlpha)1554 void LoadETC2RGB8ToRGBA8(size_t width,
1555                          size_t height,
1556                          size_t depth,
1557                          const uint8_t *input,
1558                          size_t inputRowPitch,
1559                          size_t inputDepthPitch,
1560                          uint8_t *output,
1561                          size_t outputRowPitch,
1562                          size_t outputDepthPitch,
1563                          bool punchthroughAlpha)
1564 {
1565     for (size_t z = 0; z < depth; z++)
1566     {
1567         for (size_t y = 0; y < height; y += 4)
1568         {
1569             const ETC2Block *sourceRow =
1570                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1571             uint8_t *destRow =
1572                 priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
1573 
1574             for (size_t x = 0; x < width; x += 4)
1575             {
1576                 const ETC2Block *sourceBlock = sourceRow + (x / 4);
1577                 uint8_t *destPixels          = destRow + (x * 4);
1578 
1579                 sourceBlock->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
1580                                          DefaultETCAlphaValues, punchthroughAlpha);
1581             }
1582         }
1583     }
1584 }
1585 
LoadETC2RGB8ToBC1(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch,bool punchthroughAlpha)1586 void LoadETC2RGB8ToBC1(size_t width,
1587                        size_t height,
1588                        size_t depth,
1589                        const uint8_t *input,
1590                        size_t inputRowPitch,
1591                        size_t inputDepthPitch,
1592                        uint8_t *output,
1593                        size_t outputRowPitch,
1594                        size_t outputDepthPitch,
1595                        bool punchthroughAlpha)
1596 {
1597     for (size_t z = 0; z < depth; z++)
1598     {
1599         for (size_t y = 0; y < height; y += 4)
1600         {
1601             const ETC2Block *sourceRow =
1602                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1603             uint8_t *destRow = priv::OffsetDataPointer<uint8_t>(output, y / 4, z, outputRowPitch,
1604                                                                 outputDepthPitch);
1605 
1606             for (size_t x = 0; x < width; x += 4)
1607             {
1608                 const ETC2Block *sourceBlock = sourceRow + (x / 4);
1609                 uint8_t *destPixels          = destRow + (x * 2);
1610 
1611                 sourceBlock->transcodeAsBC1(destPixels, x, y, width, height, DefaultETCAlphaValues,
1612                                             punchthroughAlpha);
1613             }
1614         }
1615     }
1616 }
1617 
LoadETC2RGBA8ToRGBA8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch,bool srgb)1618 void LoadETC2RGBA8ToRGBA8(size_t width,
1619                           size_t height,
1620                           size_t depth,
1621                           const uint8_t *input,
1622                           size_t inputRowPitch,
1623                           size_t inputDepthPitch,
1624                           uint8_t *output,
1625                           size_t outputRowPitch,
1626                           size_t outputDepthPitch,
1627                           bool srgb)
1628 {
1629     uint8_t decodedAlphaValues[4][4];
1630 
1631     for (size_t z = 0; z < depth; z++)
1632     {
1633         for (size_t y = 0; y < height; y += 4)
1634         {
1635             const ETC2Block *sourceRow =
1636                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1637             uint8_t *destRow =
1638                 priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
1639 
1640             for (size_t x = 0; x < width; x += 4)
1641             {
1642                 const ETC2Block *sourceBlockAlpha = sourceRow + (x / 2);
1643                 sourceBlockAlpha->decodeAsSingleETC2Channel(
1644                     reinterpret_cast<uint8_t *>(decodedAlphaValues), x, y, width, height, 1, 4,
1645                     false);
1646 
1647                 uint8_t *destPixels             = destRow + (x * 4);
1648                 const ETC2Block *sourceBlockRGB = sourceBlockAlpha + 1;
1649                 sourceBlockRGB->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
1650                                             decodedAlphaValues, false);
1651             }
1652         }
1653     }
1654 }
1655 
1656 }  // anonymous namespace
1657 
LoadETC1RGB8ToRGBA8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1658 void LoadETC1RGB8ToRGBA8(size_t width,
1659                          size_t height,
1660                          size_t depth,
1661                          const uint8_t *input,
1662                          size_t inputRowPitch,
1663                          size_t inputDepthPitch,
1664                          uint8_t *output,
1665                          size_t outputRowPitch,
1666                          size_t outputDepthPitch)
1667 {
1668     LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1669                         outputRowPitch, outputDepthPitch, false);
1670 }
1671 
LoadETC1RGB8ToBC1(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1672 void LoadETC1RGB8ToBC1(size_t width,
1673                        size_t height,
1674                        size_t depth,
1675                        const uint8_t *input,
1676                        size_t inputRowPitch,
1677                        size_t inputDepthPitch,
1678                        uint8_t *output,
1679                        size_t outputRowPitch,
1680                        size_t outputDepthPitch)
1681 {
1682     LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1683                       outputRowPitch, outputDepthPitch, false);
1684 }
1685 
LoadEACR11ToR8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1686 void LoadEACR11ToR8(size_t width,
1687                     size_t height,
1688                     size_t depth,
1689                     const uint8_t *input,
1690                     size_t inputRowPitch,
1691                     size_t inputDepthPitch,
1692                     uint8_t *output,
1693                     size_t outputRowPitch,
1694                     size_t outputDepthPitch)
1695 {
1696     LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1697                    outputRowPitch, outputDepthPitch, false);
1698 }
1699 
LoadEACR11SToR8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1700 void LoadEACR11SToR8(size_t width,
1701                      size_t height,
1702                      size_t depth,
1703                      const uint8_t *input,
1704                      size_t inputRowPitch,
1705                      size_t inputDepthPitch,
1706                      uint8_t *output,
1707                      size_t outputRowPitch,
1708                      size_t outputDepthPitch)
1709 {
1710     LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1711                    outputRowPitch, outputDepthPitch, true);
1712 }
1713 
LoadEACRG11ToRG8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1714 void LoadEACRG11ToRG8(size_t width,
1715                       size_t height,
1716                       size_t depth,
1717                       const uint8_t *input,
1718                       size_t inputRowPitch,
1719                       size_t inputDepthPitch,
1720                       uint8_t *output,
1721                       size_t outputRowPitch,
1722                       size_t outputDepthPitch)
1723 {
1724     LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1725                      outputRowPitch, outputDepthPitch, false);
1726 }
1727 
LoadEACRG11SToRG8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1728 void LoadEACRG11SToRG8(size_t width,
1729                        size_t height,
1730                        size_t depth,
1731                        const uint8_t *input,
1732                        size_t inputRowPitch,
1733                        size_t inputDepthPitch,
1734                        uint8_t *output,
1735                        size_t outputRowPitch,
1736                        size_t outputDepthPitch)
1737 {
1738     LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1739                      outputRowPitch, outputDepthPitch, true);
1740 }
1741 
LoadEACR11ToR16(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1742 void LoadEACR11ToR16(size_t width,
1743                      size_t height,
1744                      size_t depth,
1745                      const uint8_t *input,
1746                      size_t inputRowPitch,
1747                      size_t inputDepthPitch,
1748                      uint8_t *output,
1749                      size_t outputRowPitch,
1750                      size_t outputDepthPitch)
1751 {
1752     LoadR11EACToR16(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1753                     outputRowPitch, outputDepthPitch, false, false);
1754 }
1755 
LoadEACR11SToR16(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1756 void LoadEACR11SToR16(size_t width,
1757                       size_t height,
1758                       size_t depth,
1759                       const uint8_t *input,
1760                       size_t inputRowPitch,
1761                       size_t inputDepthPitch,
1762                       uint8_t *output,
1763                       size_t outputRowPitch,
1764                       size_t outputDepthPitch)
1765 {
1766     LoadR11EACToR16(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1767                     outputRowPitch, outputDepthPitch, true, false);
1768 }
1769 
LoadEACRG11ToRG16(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1770 void LoadEACRG11ToRG16(size_t width,
1771                        size_t height,
1772                        size_t depth,
1773                        const uint8_t *input,
1774                        size_t inputRowPitch,
1775                        size_t inputDepthPitch,
1776                        uint8_t *output,
1777                        size_t outputRowPitch,
1778                        size_t outputDepthPitch)
1779 {
1780     LoadRG11EACToRG16(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1781                       outputRowPitch, outputDepthPitch, false, false);
1782 }
1783 
LoadEACRG11SToRG16(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1784 void LoadEACRG11SToRG16(size_t width,
1785                         size_t height,
1786                         size_t depth,
1787                         const uint8_t *input,
1788                         size_t inputRowPitch,
1789                         size_t inputDepthPitch,
1790                         uint8_t *output,
1791                         size_t outputRowPitch,
1792                         size_t outputDepthPitch)
1793 {
1794     LoadRG11EACToRG16(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1795                       outputRowPitch, outputDepthPitch, true, false);
1796 }
1797 
LoadEACR11ToR16F(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1798 void LoadEACR11ToR16F(size_t width,
1799                       size_t height,
1800                       size_t depth,
1801                       const uint8_t *input,
1802                       size_t inputRowPitch,
1803                       size_t inputDepthPitch,
1804                       uint8_t *output,
1805                       size_t outputRowPitch,
1806                       size_t outputDepthPitch)
1807 {
1808     LoadR11EACToR16(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1809                     outputRowPitch, outputDepthPitch, false, true);
1810 }
1811 
LoadEACR11SToR16F(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1812 void LoadEACR11SToR16F(size_t width,
1813                        size_t height,
1814                        size_t depth,
1815                        const uint8_t *input,
1816                        size_t inputRowPitch,
1817                        size_t inputDepthPitch,
1818                        uint8_t *output,
1819                        size_t outputRowPitch,
1820                        size_t outputDepthPitch)
1821 {
1822     LoadR11EACToR16(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1823                     outputRowPitch, outputDepthPitch, true, true);
1824 }
1825 
LoadEACRG11ToRG16F(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1826 void LoadEACRG11ToRG16F(size_t width,
1827                         size_t height,
1828                         size_t depth,
1829                         const uint8_t *input,
1830                         size_t inputRowPitch,
1831                         size_t inputDepthPitch,
1832                         uint8_t *output,
1833                         size_t outputRowPitch,
1834                         size_t outputDepthPitch)
1835 {
1836     LoadRG11EACToRG16(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1837                       outputRowPitch, outputDepthPitch, false, true);
1838 }
1839 
LoadEACRG11SToRG16F(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1840 void LoadEACRG11SToRG16F(size_t width,
1841                          size_t height,
1842                          size_t depth,
1843                          const uint8_t *input,
1844                          size_t inputRowPitch,
1845                          size_t inputDepthPitch,
1846                          uint8_t *output,
1847                          size_t outputRowPitch,
1848                          size_t outputDepthPitch)
1849 {
1850     LoadRG11EACToRG16(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1851                       outputRowPitch, outputDepthPitch, true, true);
1852 }
1853 
LoadETC2RGB8ToRGBA8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1854 void LoadETC2RGB8ToRGBA8(size_t width,
1855                          size_t height,
1856                          size_t depth,
1857                          const uint8_t *input,
1858                          size_t inputRowPitch,
1859                          size_t inputDepthPitch,
1860                          uint8_t *output,
1861                          size_t outputRowPitch,
1862                          size_t outputDepthPitch)
1863 {
1864     LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1865                         outputRowPitch, outputDepthPitch, false);
1866 }
1867 
LoadETC2RGB8ToBC1(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1868 void LoadETC2RGB8ToBC1(size_t width,
1869                        size_t height,
1870                        size_t depth,
1871                        const uint8_t *input,
1872                        size_t inputRowPitch,
1873                        size_t inputDepthPitch,
1874                        uint8_t *output,
1875                        size_t outputRowPitch,
1876                        size_t outputDepthPitch)
1877 {
1878     LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1879                       outputRowPitch, outputDepthPitch, false);
1880 }
1881 
LoadETC2SRGB8ToRGBA8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1882 void LoadETC2SRGB8ToRGBA8(size_t width,
1883                           size_t height,
1884                           size_t depth,
1885                           const uint8_t *input,
1886                           size_t inputRowPitch,
1887                           size_t inputDepthPitch,
1888                           uint8_t *output,
1889                           size_t outputRowPitch,
1890                           size_t outputDepthPitch)
1891 {
1892     LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1893                         outputRowPitch, outputDepthPitch, false);
1894 }
1895 
LoadETC2SRGB8ToBC1(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1896 void LoadETC2SRGB8ToBC1(size_t width,
1897                         size_t height,
1898                         size_t depth,
1899                         const uint8_t *input,
1900                         size_t inputRowPitch,
1901                         size_t inputDepthPitch,
1902                         uint8_t *output,
1903                         size_t outputRowPitch,
1904                         size_t outputDepthPitch)
1905 {
1906     LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1907                       outputRowPitch, outputDepthPitch, false);
1908 }
1909 
LoadETC2RGB8A1ToRGBA8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1910 void LoadETC2RGB8A1ToRGBA8(size_t width,
1911                            size_t height,
1912                            size_t depth,
1913                            const uint8_t *input,
1914                            size_t inputRowPitch,
1915                            size_t inputDepthPitch,
1916                            uint8_t *output,
1917                            size_t outputRowPitch,
1918                            size_t outputDepthPitch)
1919 {
1920     LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1921                         outputRowPitch, outputDepthPitch, true);
1922 }
1923 
LoadETC2RGB8A1ToBC1(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1924 void LoadETC2RGB8A1ToBC1(size_t width,
1925                          size_t height,
1926                          size_t depth,
1927                          const uint8_t *input,
1928                          size_t inputRowPitch,
1929                          size_t inputDepthPitch,
1930                          uint8_t *output,
1931                          size_t outputRowPitch,
1932                          size_t outputDepthPitch)
1933 {
1934     LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1935                       outputRowPitch, outputDepthPitch, true);
1936 }
1937 
LoadETC2SRGB8A1ToRGBA8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1938 void LoadETC2SRGB8A1ToRGBA8(size_t width,
1939                             size_t height,
1940                             size_t depth,
1941                             const uint8_t *input,
1942                             size_t inputRowPitch,
1943                             size_t inputDepthPitch,
1944                             uint8_t *output,
1945                             size_t outputRowPitch,
1946                             size_t outputDepthPitch)
1947 {
1948     LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1949                         outputRowPitch, outputDepthPitch, true);
1950 }
1951 
LoadETC2SRGB8A1ToBC1(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1952 void LoadETC2SRGB8A1ToBC1(size_t width,
1953                           size_t height,
1954                           size_t depth,
1955                           const uint8_t *input,
1956                           size_t inputRowPitch,
1957                           size_t inputDepthPitch,
1958                           uint8_t *output,
1959                           size_t outputRowPitch,
1960                           size_t outputDepthPitch)
1961 {
1962     LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1963                       outputRowPitch, outputDepthPitch, true);
1964 }
1965 
LoadETC2RGBA8ToRGBA8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1966 void LoadETC2RGBA8ToRGBA8(size_t width,
1967                           size_t height,
1968                           size_t depth,
1969                           const uint8_t *input,
1970                           size_t inputRowPitch,
1971                           size_t inputDepthPitch,
1972                           uint8_t *output,
1973                           size_t outputRowPitch,
1974                           size_t outputDepthPitch)
1975 {
1976     LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1977                          outputRowPitch, outputDepthPitch, false);
1978 }
1979 
LoadETC2SRGBA8ToSRGBA8(size_t width,size_t height,size_t depth,const uint8_t * input,size_t inputRowPitch,size_t inputDepthPitch,uint8_t * output,size_t outputRowPitch,size_t outputDepthPitch)1980 void LoadETC2SRGBA8ToSRGBA8(size_t width,
1981                             size_t height,
1982                             size_t depth,
1983                             const uint8_t *input,
1984                             size_t inputRowPitch,
1985                             size_t inputDepthPitch,
1986                             uint8_t *output,
1987                             size_t outputRowPitch,
1988                             size_t outputDepthPitch)
1989 {
1990     LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1991                          outputRowPitch, outputDepthPitch, true);
1992 }
1993 
1994 }  // namespace angle
1995