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