• 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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::ETC2Block362     static unsigned char clampByte(int value)
363     {
364         return static_cast<unsigned char>(gl::clamp(value, 0, 255));
365     }
366 
clampSByteangle::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::ETC2Block411     static R8G8B8A8 createRGBA(int red, int green, int blue)
412     {
413         return createRGBA(red, green, blue, 255);
414     }
415 
extend_4to8bitsangle::__anon2c2347010111::ETC2Block416     static int extend_4to8bits(int x) { return (x << 4) | x; }
extend_5to8bitsangle::__anon2c2347010111::ETC2Block417     static int extend_5to8bits(int x) { return (x << 3) | (x >> 2); }
extend_6to8bitsangle::__anon2c2347010111::ETC2Block418     static int extend_6to8bits(int x) { return (x << 2) | (x >> 4); }
extend_7to8bitsangle::__anon2c2347010111::ETC2Block419     static int extend_7to8bits(int x) { return (x << 1) | (x >> 6); }
420 
decodeIndividualBlockangle::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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::__anon2c2347010111::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(const ImageLoadContext & context,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(const ImageLoadContext &context,
1417                     size_t width,
1418                     size_t height,
1419                     size_t depth,
1420                     const uint8_t *input,
1421                     size_t inputRowPitch,
1422                     size_t inputDepthPitch,
1423                     uint8_t *output,
1424                     size_t outputRowPitch,
1425                     size_t outputDepthPitch,
1426                     bool isSigned)
1427 {
1428     for (size_t z = 0; z < depth; z++)
1429     {
1430         for (size_t y = 0; y < height; y += 4)
1431         {
1432             const ETC2Block *sourceRow =
1433                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1434             uint8_t *destRow =
1435                 priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
1436 
1437             for (size_t x = 0; x < width; x += 4)
1438             {
1439                 const ETC2Block *sourceBlock = sourceRow + (x / 4);
1440                 uint8_t *destPixels          = destRow + x;
1441 
1442                 sourceBlock->decodeAsSingleETC2Channel(destPixels, x, y, width, height, 1,
1443                                                        outputRowPitch, isSigned);
1444             }
1445         }
1446     }
1447 }
1448 
LoadRG11EACToRG8(const ImageLoadContext & context,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)1449 void LoadRG11EACToRG8(const ImageLoadContext &context,
1450                       size_t width,
1451                       size_t height,
1452                       size_t depth,
1453                       const uint8_t *input,
1454                       size_t inputRowPitch,
1455                       size_t inputDepthPitch,
1456                       uint8_t *output,
1457                       size_t outputRowPitch,
1458                       size_t outputDepthPitch,
1459                       bool isSigned)
1460 {
1461     for (size_t z = 0; z < depth; z++)
1462     {
1463         for (size_t y = 0; y < height; y += 4)
1464         {
1465             const ETC2Block *sourceRow =
1466                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1467             uint8_t *destRow =
1468                 priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
1469 
1470             for (size_t x = 0; x < width; x += 4)
1471             {
1472                 uint8_t *destPixelsRed          = destRow + (x * 2);
1473                 const ETC2Block *sourceBlockRed = sourceRow + (x / 2);
1474                 sourceBlockRed->decodeAsSingleETC2Channel(destPixelsRed, x, y, width, height, 2,
1475                                                           outputRowPitch, isSigned);
1476 
1477                 uint8_t *destPixelsGreen          = destPixelsRed + 1;
1478                 const ETC2Block *sourceBlockGreen = sourceBlockRed + 1;
1479                 sourceBlockGreen->decodeAsSingleETC2Channel(destPixelsGreen, x, y, width, height, 2,
1480                                                             outputRowPitch, isSigned);
1481             }
1482         }
1483     }
1484 }
1485 
LoadR11EACToR16(const ImageLoadContext & context,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)1486 void LoadR11EACToR16(const ImageLoadContext &context,
1487                      size_t width,
1488                      size_t height,
1489                      size_t depth,
1490                      const uint8_t *input,
1491                      size_t inputRowPitch,
1492                      size_t inputDepthPitch,
1493                      uint8_t *output,
1494                      size_t outputRowPitch,
1495                      size_t outputDepthPitch,
1496                      bool isSigned,
1497                      bool isFloat)
1498 {
1499     for (size_t z = 0; z < depth; z++)
1500     {
1501         for (size_t y = 0; y < height; y += 4)
1502         {
1503             const ETC2Block *sourceRow =
1504                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1505             uint16_t *destRow =
1506                 priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
1507 
1508             for (size_t x = 0; x < width; x += 4)
1509             {
1510                 const ETC2Block *sourceBlock = sourceRow + (x / 4);
1511                 uint16_t *destPixels         = destRow + x;
1512 
1513                 sourceBlock->decodeAsSingleEACChannel(destPixels, x, y, width, height, 1,
1514                                                       outputRowPitch, isSigned, isFloat);
1515             }
1516         }
1517     }
1518 }
1519 
LoadRG11EACToRG16(const ImageLoadContext & context,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)1520 void LoadRG11EACToRG16(const ImageLoadContext &context,
1521                        size_t width,
1522                        size_t height,
1523                        size_t depth,
1524                        const uint8_t *input,
1525                        size_t inputRowPitch,
1526                        size_t inputDepthPitch,
1527                        uint8_t *output,
1528                        size_t outputRowPitch,
1529                        size_t outputDepthPitch,
1530                        bool isSigned,
1531                        bool isFloat)
1532 {
1533     for (size_t z = 0; z < depth; z++)
1534     {
1535         for (size_t y = 0; y < height; y += 4)
1536         {
1537             const ETC2Block *sourceRow =
1538                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1539             uint16_t *destRow =
1540                 priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
1541 
1542             for (size_t x = 0; x < width; x += 4)
1543             {
1544                 uint16_t *destPixelsRed         = destRow + (x * 2);
1545                 const ETC2Block *sourceBlockRed = sourceRow + (x / 2);
1546                 sourceBlockRed->decodeAsSingleEACChannel(destPixelsRed, x, y, width, height, 2,
1547                                                          outputRowPitch, isSigned, isFloat);
1548 
1549                 uint16_t *destPixelsGreen         = destPixelsRed + 1;
1550                 const ETC2Block *sourceBlockGreen = sourceBlockRed + 1;
1551                 sourceBlockGreen->decodeAsSingleEACChannel(destPixelsGreen, x, y, width, height, 2,
1552                                                            outputRowPitch, isSigned, isFloat);
1553             }
1554         }
1555     }
1556 }
1557 
LoadETC2RGB8ToRGBA8(const ImageLoadContext & context,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)1558 void LoadETC2RGB8ToRGBA8(const ImageLoadContext &context,
1559                          size_t width,
1560                          size_t height,
1561                          size_t depth,
1562                          const uint8_t *input,
1563                          size_t inputRowPitch,
1564                          size_t inputDepthPitch,
1565                          uint8_t *output,
1566                          size_t outputRowPitch,
1567                          size_t outputDepthPitch,
1568                          bool punchthroughAlpha)
1569 {
1570     for (size_t z = 0; z < depth; z++)
1571     {
1572         for (size_t y = 0; y < height; y += 4)
1573         {
1574             const ETC2Block *sourceRow =
1575                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1576             uint8_t *destRow =
1577                 priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
1578 
1579             for (size_t x = 0; x < width; x += 4)
1580             {
1581                 const ETC2Block *sourceBlock = sourceRow + (x / 4);
1582                 uint8_t *destPixels          = destRow + (x * 4);
1583 
1584                 sourceBlock->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
1585                                          DefaultETCAlphaValues, punchthroughAlpha);
1586             }
1587         }
1588     }
1589 }
1590 
LoadETC2RGB8ToBC1(const ImageLoadContext & context,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)1591 void LoadETC2RGB8ToBC1(const ImageLoadContext &context,
1592                        size_t width,
1593                        size_t height,
1594                        size_t depth,
1595                        const uint8_t *input,
1596                        size_t inputRowPitch,
1597                        size_t inputDepthPitch,
1598                        uint8_t *output,
1599                        size_t outputRowPitch,
1600                        size_t outputDepthPitch,
1601                        bool punchthroughAlpha)
1602 {
1603     for (size_t z = 0; z < depth; z++)
1604     {
1605         for (size_t y = 0; y < height; y += 4)
1606         {
1607             const ETC2Block *sourceRow =
1608                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1609             uint8_t *destRow = priv::OffsetDataPointer<uint8_t>(output, y / 4, z, outputRowPitch,
1610                                                                 outputDepthPitch);
1611 
1612             for (size_t x = 0; x < width; x += 4)
1613             {
1614                 const ETC2Block *sourceBlock = sourceRow + (x / 4);
1615                 uint8_t *destPixels          = destRow + (x * 2);
1616 
1617                 sourceBlock->transcodeAsBC1(destPixels, x, y, width, height, DefaultETCAlphaValues,
1618                                             punchthroughAlpha);
1619             }
1620         }
1621     }
1622 }
1623 
LoadETC2RGBA8ToRGBA8(const ImageLoadContext & context,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)1624 void LoadETC2RGBA8ToRGBA8(const ImageLoadContext &context,
1625                           size_t width,
1626                           size_t height,
1627                           size_t depth,
1628                           const uint8_t *input,
1629                           size_t inputRowPitch,
1630                           size_t inputDepthPitch,
1631                           uint8_t *output,
1632                           size_t outputRowPitch,
1633                           size_t outputDepthPitch,
1634                           bool srgb)
1635 {
1636     uint8_t decodedAlphaValues[4][4];
1637 
1638     for (size_t z = 0; z < depth; z++)
1639     {
1640         for (size_t y = 0; y < height; y += 4)
1641         {
1642             const ETC2Block *sourceRow =
1643                 priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
1644             uint8_t *destRow =
1645                 priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
1646 
1647             for (size_t x = 0; x < width; x += 4)
1648             {
1649                 const ETC2Block *sourceBlockAlpha = sourceRow + (x / 2);
1650                 sourceBlockAlpha->decodeAsSingleETC2Channel(
1651                     reinterpret_cast<uint8_t *>(decodedAlphaValues), x, y, width, height, 1, 4,
1652                     false);
1653 
1654                 uint8_t *destPixels             = destRow + (x * 4);
1655                 const ETC2Block *sourceBlockRGB = sourceBlockAlpha + 1;
1656                 sourceBlockRGB->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
1657                                             decodedAlphaValues, false);
1658             }
1659         }
1660     }
1661 }
1662 
1663 }  // anonymous namespace
1664 
LoadETC1RGB8ToRGBA8(const ImageLoadContext & context,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)1665 void LoadETC1RGB8ToRGBA8(const ImageLoadContext &context,
1666                          size_t width,
1667                          size_t height,
1668                          size_t depth,
1669                          const uint8_t *input,
1670                          size_t inputRowPitch,
1671                          size_t inputDepthPitch,
1672                          uint8_t *output,
1673                          size_t outputRowPitch,
1674                          size_t outputDepthPitch)
1675 {
1676     LoadETC2RGB8ToRGBA8(context, width, height, depth, input, inputRowPitch, inputDepthPitch,
1677                         output, outputRowPitch, outputDepthPitch, false);
1678 }
1679 
LoadETC1RGB8ToBC1(const ImageLoadContext & context,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)1680 void LoadETC1RGB8ToBC1(const ImageLoadContext &context,
1681                        size_t width,
1682                        size_t height,
1683                        size_t depth,
1684                        const uint8_t *input,
1685                        size_t inputRowPitch,
1686                        size_t inputDepthPitch,
1687                        uint8_t *output,
1688                        size_t outputRowPitch,
1689                        size_t outputDepthPitch)
1690 {
1691     LoadETC2RGB8ToBC1(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1692                       outputRowPitch, outputDepthPitch, false);
1693 }
1694 
LoadEACR11ToR8(const ImageLoadContext & context,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)1695 void LoadEACR11ToR8(const ImageLoadContext &context,
1696                     size_t width,
1697                     size_t height,
1698                     size_t depth,
1699                     const uint8_t *input,
1700                     size_t inputRowPitch,
1701                     size_t inputDepthPitch,
1702                     uint8_t *output,
1703                     size_t outputRowPitch,
1704                     size_t outputDepthPitch)
1705 {
1706     LoadR11EACToR8(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1707                    outputRowPitch, outputDepthPitch, false);
1708 }
1709 
LoadEACR11SToR8(const ImageLoadContext & context,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)1710 void LoadEACR11SToR8(const ImageLoadContext &context,
1711                      size_t width,
1712                      size_t height,
1713                      size_t depth,
1714                      const uint8_t *input,
1715                      size_t inputRowPitch,
1716                      size_t inputDepthPitch,
1717                      uint8_t *output,
1718                      size_t outputRowPitch,
1719                      size_t outputDepthPitch)
1720 {
1721     LoadR11EACToR8(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1722                    outputRowPitch, outputDepthPitch, true);
1723 }
1724 
LoadEACRG11ToRG8(const ImageLoadContext & context,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)1725 void LoadEACRG11ToRG8(const ImageLoadContext &context,
1726                       size_t width,
1727                       size_t height,
1728                       size_t depth,
1729                       const uint8_t *input,
1730                       size_t inputRowPitch,
1731                       size_t inputDepthPitch,
1732                       uint8_t *output,
1733                       size_t outputRowPitch,
1734                       size_t outputDepthPitch)
1735 {
1736     LoadRG11EACToRG8(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1737                      outputRowPitch, outputDepthPitch, false);
1738 }
1739 
LoadEACRG11SToRG8(const ImageLoadContext & context,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)1740 void LoadEACRG11SToRG8(const ImageLoadContext &context,
1741                        size_t width,
1742                        size_t height,
1743                        size_t depth,
1744                        const uint8_t *input,
1745                        size_t inputRowPitch,
1746                        size_t inputDepthPitch,
1747                        uint8_t *output,
1748                        size_t outputRowPitch,
1749                        size_t outputDepthPitch)
1750 {
1751     LoadRG11EACToRG8(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1752                      outputRowPitch, outputDepthPitch, true);
1753 }
1754 
LoadEACR11ToR16(const ImageLoadContext & context,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)1755 void LoadEACR11ToR16(const ImageLoadContext &context,
1756                      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(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1767                     outputRowPitch, outputDepthPitch, false, false);
1768 }
1769 
LoadEACR11SToR16(const ImageLoadContext & context,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 LoadEACR11SToR16(const ImageLoadContext &context,
1771                       size_t width,
1772                       size_t height,
1773                       size_t depth,
1774                       const uint8_t *input,
1775                       size_t inputRowPitch,
1776                       size_t inputDepthPitch,
1777                       uint8_t *output,
1778                       size_t outputRowPitch,
1779                       size_t outputDepthPitch)
1780 {
1781     LoadR11EACToR16(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1782                     outputRowPitch, outputDepthPitch, true, false);
1783 }
1784 
LoadEACRG11ToRG16(const ImageLoadContext & context,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)1785 void LoadEACRG11ToRG16(const ImageLoadContext &context,
1786                        size_t width,
1787                        size_t height,
1788                        size_t depth,
1789                        const uint8_t *input,
1790                        size_t inputRowPitch,
1791                        size_t inputDepthPitch,
1792                        uint8_t *output,
1793                        size_t outputRowPitch,
1794                        size_t outputDepthPitch)
1795 {
1796     LoadRG11EACToRG16(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1797                       outputRowPitch, outputDepthPitch, false, false);
1798 }
1799 
LoadEACRG11SToRG16(const ImageLoadContext & context,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)1800 void LoadEACRG11SToRG16(const ImageLoadContext &context,
1801                         size_t width,
1802                         size_t height,
1803                         size_t depth,
1804                         const uint8_t *input,
1805                         size_t inputRowPitch,
1806                         size_t inputDepthPitch,
1807                         uint8_t *output,
1808                         size_t outputRowPitch,
1809                         size_t outputDepthPitch)
1810 {
1811     LoadRG11EACToRG16(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1812                       outputRowPitch, outputDepthPitch, true, false);
1813 }
1814 
LoadEACR11ToR16F(const ImageLoadContext & context,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)1815 void LoadEACR11ToR16F(const ImageLoadContext &context,
1816                       size_t width,
1817                       size_t height,
1818                       size_t depth,
1819                       const uint8_t *input,
1820                       size_t inputRowPitch,
1821                       size_t inputDepthPitch,
1822                       uint8_t *output,
1823                       size_t outputRowPitch,
1824                       size_t outputDepthPitch)
1825 {
1826     LoadR11EACToR16(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1827                     outputRowPitch, outputDepthPitch, false, true);
1828 }
1829 
LoadEACR11SToR16F(const ImageLoadContext & context,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)1830 void LoadEACR11SToR16F(const ImageLoadContext &context,
1831                        size_t width,
1832                        size_t height,
1833                        size_t depth,
1834                        const uint8_t *input,
1835                        size_t inputRowPitch,
1836                        size_t inputDepthPitch,
1837                        uint8_t *output,
1838                        size_t outputRowPitch,
1839                        size_t outputDepthPitch)
1840 {
1841     LoadR11EACToR16(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1842                     outputRowPitch, outputDepthPitch, true, true);
1843 }
1844 
LoadEACRG11ToRG16F(const ImageLoadContext & context,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)1845 void LoadEACRG11ToRG16F(const ImageLoadContext &context,
1846                         size_t width,
1847                         size_t height,
1848                         size_t depth,
1849                         const uint8_t *input,
1850                         size_t inputRowPitch,
1851                         size_t inputDepthPitch,
1852                         uint8_t *output,
1853                         size_t outputRowPitch,
1854                         size_t outputDepthPitch)
1855 {
1856     LoadRG11EACToRG16(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1857                       outputRowPitch, outputDepthPitch, false, true);
1858 }
1859 
LoadEACRG11SToRG16F(const ImageLoadContext & context,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)1860 void LoadEACRG11SToRG16F(const ImageLoadContext &context,
1861                          size_t width,
1862                          size_t height,
1863                          size_t depth,
1864                          const uint8_t *input,
1865                          size_t inputRowPitch,
1866                          size_t inputDepthPitch,
1867                          uint8_t *output,
1868                          size_t outputRowPitch,
1869                          size_t outputDepthPitch)
1870 {
1871     LoadRG11EACToRG16(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1872                       outputRowPitch, outputDepthPitch, true, true);
1873 }
1874 
LoadETC2RGB8ToRGBA8(const ImageLoadContext & context,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)1875 void LoadETC2RGB8ToRGBA8(const ImageLoadContext &context,
1876                          size_t width,
1877                          size_t height,
1878                          size_t depth,
1879                          const uint8_t *input,
1880                          size_t inputRowPitch,
1881                          size_t inputDepthPitch,
1882                          uint8_t *output,
1883                          size_t outputRowPitch,
1884                          size_t outputDepthPitch)
1885 {
1886     LoadETC2RGB8ToRGBA8(context, width, height, depth, input, inputRowPitch, inputDepthPitch,
1887                         output, outputRowPitch, outputDepthPitch, false);
1888 }
1889 
LoadETC2RGB8ToBC1(const ImageLoadContext & context,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)1890 void LoadETC2RGB8ToBC1(const ImageLoadContext &context,
1891                        size_t width,
1892                        size_t height,
1893                        size_t depth,
1894                        const uint8_t *input,
1895                        size_t inputRowPitch,
1896                        size_t inputDepthPitch,
1897                        uint8_t *output,
1898                        size_t outputRowPitch,
1899                        size_t outputDepthPitch)
1900 {
1901     LoadETC2RGB8ToBC1(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1902                       outputRowPitch, outputDepthPitch, false);
1903 }
1904 
LoadETC2SRGB8ToRGBA8(const ImageLoadContext & context,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)1905 void LoadETC2SRGB8ToRGBA8(const ImageLoadContext &context,
1906                           size_t width,
1907                           size_t height,
1908                           size_t depth,
1909                           const uint8_t *input,
1910                           size_t inputRowPitch,
1911                           size_t inputDepthPitch,
1912                           uint8_t *output,
1913                           size_t outputRowPitch,
1914                           size_t outputDepthPitch)
1915 {
1916     LoadETC2RGB8ToRGBA8(context, width, height, depth, input, inputRowPitch, inputDepthPitch,
1917                         output, outputRowPitch, outputDepthPitch, false);
1918 }
1919 
LoadETC2SRGB8ToBC1(const ImageLoadContext & context,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)1920 void LoadETC2SRGB8ToBC1(const ImageLoadContext &context,
1921                         size_t width,
1922                         size_t height,
1923                         size_t depth,
1924                         const uint8_t *input,
1925                         size_t inputRowPitch,
1926                         size_t inputDepthPitch,
1927                         uint8_t *output,
1928                         size_t outputRowPitch,
1929                         size_t outputDepthPitch)
1930 {
1931     LoadETC2RGB8ToBC1(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1932                       outputRowPitch, outputDepthPitch, false);
1933 }
1934 
LoadETC2RGB8A1ToRGBA8(const ImageLoadContext & context,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)1935 void LoadETC2RGB8A1ToRGBA8(const ImageLoadContext &context,
1936                            size_t width,
1937                            size_t height,
1938                            size_t depth,
1939                            const uint8_t *input,
1940                            size_t inputRowPitch,
1941                            size_t inputDepthPitch,
1942                            uint8_t *output,
1943                            size_t outputRowPitch,
1944                            size_t outputDepthPitch)
1945 {
1946     LoadETC2RGB8ToRGBA8(context, width, height, depth, input, inputRowPitch, inputDepthPitch,
1947                         output, outputRowPitch, outputDepthPitch, true);
1948 }
1949 
LoadETC2RGB8A1ToBC1(const ImageLoadContext & context,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)1950 void LoadETC2RGB8A1ToBC1(const ImageLoadContext &context,
1951                          size_t width,
1952                          size_t height,
1953                          size_t depth,
1954                          const uint8_t *input,
1955                          size_t inputRowPitch,
1956                          size_t inputDepthPitch,
1957                          uint8_t *output,
1958                          size_t outputRowPitch,
1959                          size_t outputDepthPitch)
1960 {
1961     LoadETC2RGB8ToBC1(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1962                       outputRowPitch, outputDepthPitch, true);
1963 }
1964 
LoadETC2SRGB8A1ToRGBA8(const ImageLoadContext & context,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)1965 void LoadETC2SRGB8A1ToRGBA8(const ImageLoadContext &context,
1966                             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     LoadETC2RGB8ToRGBA8(context, width, height, depth, input, inputRowPitch, inputDepthPitch,
1977                         output, outputRowPitch, outputDepthPitch, true);
1978 }
1979 
LoadETC2SRGB8A1ToBC1(const ImageLoadContext & context,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 LoadETC2SRGB8A1ToBC1(const ImageLoadContext &context,
1981                           size_t width,
1982                           size_t height,
1983                           size_t depth,
1984                           const uint8_t *input,
1985                           size_t inputRowPitch,
1986                           size_t inputDepthPitch,
1987                           uint8_t *output,
1988                           size_t outputRowPitch,
1989                           size_t outputDepthPitch)
1990 {
1991     LoadETC2RGB8ToBC1(context, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
1992                       outputRowPitch, outputDepthPitch, true);
1993 }
1994 
LoadETC2RGBA8ToRGBA8(const ImageLoadContext & context,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)1995 void LoadETC2RGBA8ToRGBA8(const ImageLoadContext &context,
1996                           size_t width,
1997                           size_t height,
1998                           size_t depth,
1999                           const uint8_t *input,
2000                           size_t inputRowPitch,
2001                           size_t inputDepthPitch,
2002                           uint8_t *output,
2003                           size_t outputRowPitch,
2004                           size_t outputDepthPitch)
2005 {
2006     LoadETC2RGBA8ToRGBA8(context, width, height, depth, input, inputRowPitch, inputDepthPitch,
2007                          output, outputRowPitch, outputDepthPitch, false);
2008 }
2009 
LoadETC2SRGBA8ToSRGBA8(const ImageLoadContext & context,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)2010 void LoadETC2SRGBA8ToSRGBA8(const ImageLoadContext &context,
2011                             size_t width,
2012                             size_t height,
2013                             size_t depth,
2014                             const uint8_t *input,
2015                             size_t inputRowPitch,
2016                             size_t inputDepthPitch,
2017                             uint8_t *output,
2018                             size_t outputRowPitch,
2019                             size_t outputDepthPitch)
2020 {
2021     LoadETC2RGBA8ToRGBA8(context, width, height, depth, input, inputRowPitch, inputDepthPitch,
2022                          output, outputRowPitch, outputDepthPitch, true);
2023 }
2024 
2025 }  // namespace angle
2026