1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "ETC_Decoder.hpp"
16
17namespace
18{
19 inline int clampByte(int value)
20 {
21 return (value < 0) ? 0 : ((value > 255) ? 255 : value);
22 }
23
24 inline int clampSByte(int value)
25 {
26 return (value < -128) ? -128 : ((value > 127) ? 127 : value);
27 }
28
29 inline int clampEAC(int value, bool isSigned)
30 {
31 int min = isSigned ? -1023 : 0;
32 int max = isSigned ? 1023 : 2047;
33 return (value < min) ? min : ((value > max) ? max : value);
34 }
35
36 struct bgra8
37 {
38 unsigned char b;
39 unsigned char g;
40 unsigned char r;
41 unsigned char a;
42
43 inline bgra8()
44 {
45 }
46
47 inline void set(int red, int green, int blue)
48 {
49 r = static_cast<unsigned char>(clampByte(red));
50 g = static_cast<unsigned char>(clampByte(green));
51 b = static_cast<unsigned char>(clampByte(blue));
52 }
53
54 inline void set(int red, int green, int blue, int alpha)
55 {
56 r = static_cast<unsigned char>(clampByte(red));
57 g = static_cast<unsigned char>(clampByte(green));
58 b = static_cast<unsigned char>(clampByte(blue));
59 a = static_cast<unsigned char>(clampByte(alpha));
60 }
61
62 const bgra8& addA(int alpha)
63 {
64 a = alpha;
65 return *this;
66 }
67 };
68
69 inline int extend_4to8bits(int x)
70 {
71 return (x << 4) | x;
72 }
73
74 inline int extend_5to8bits(int x)
75 {
76 return (x << 3) | (x >> 2);
77 }
78
79 inline int extend_6to8bits(int x)
80 {
81 return (x << 2) | (x >> 4);
82 }
83
84 inline int extend_7to8bits(int x)
85 {
86 return (x << 1) | (x >> 6);
87 }
88
89 struct ETC2
90 {
91 // Decodes unsigned single or dual channel block to bytes
92 static void DecodeBlock(const ETC2** sources, unsigned char *dest, int nbChannels, int x, int y, int w, int h, int pitch, bool isSigned, bool isEAC)
93 {
94 if(isEAC)
95 {
96 for(int j = 0; j < 4 && (y + j) < h; j++)
97 {
98 int* sDst = reinterpret_cast<int*>(dest);
99 for(int i = 0; i < 4 && (x + i) < w; i++)
100 {
101 for(int c = nbChannels - 1; c >= 0; c--)
102 {
103 sDst[i * nbChannels + c] = clampEAC(sources[c]->getSingleChannel(i, j, isSigned, true), isSigned);
104 }
105 }
106 dest += pitch;
107 }
108 }
109 else
110 {
111 if(isSigned)
112 {
113 signed char* sDst = reinterpret_cast<signed char*>(dest);
114 for(int j = 0; j < 4 && (y + j) < h; j++)
115 {
116 for(int i = 0; i < 4 && (x + i) < w; i++)
117 {
118 for(int c = nbChannels - 1; c >= 0; c--)
119 {
120 sDst[i * nbChannels + c] = clampSByte(sources[c]->getSingleChannel(i, j, isSigned, false));
121 }
122 }
123 sDst += pitch;
124 }
125 }
126 else
127 {
128 for(int j = 0; j < 4 && (y + j) < h; j++)
129 {
130 for(int i = 0; i < 4 && (x + i) < w; i++)
131 {
132 for(int c = nbChannels - 1; c >= 0; c--)
133 {
134 dest[i * nbChannels + c] = clampByte(sources[c]->getSingleChannel(i, j, isSigned, false));
135 }
136 }
137 dest += pitch;
138 }
139 }
140 }
141 }
142
143 // Decodes RGB block to bgra8
144 void decodeBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4], bool punchThroughAlpha) const
145 {
146 bool opaqueBit = diffbit;
147 bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit;
148
149 // Select mode
150 if(diffbit || punchThroughAlpha)
151 {
152 int r = (R + dR);
153 int g = (G + dG);
154 int b = (B + dB);
155 if(r < 0 || r > 31)
156 {
157 decodeTBlock(dest, x, y, w, h, pitch, alphaValues, nonOpaquePunchThroughAlpha);
158 }
159 else if(g < 0 || g > 31)
160 {
161 decodeHBlock(dest, x, y, w, h, pitch, alphaValues, nonOpaquePunchThroughAlpha);
162 }
163 else if(b < 0 || b > 31)
164 {
165 decodePlanarBlock(dest, x, y, w, h, pitch, alphaValues);
166 }
167 else
168 {
169 decodeDifferentialBlock(dest, x, y, w, h, pitch, alphaValues, nonOpaquePunchThroughAlpha);
170 }
171 }
172 else
173 {
174 decodeIndividualBlock(dest, x, y, w, h, pitch, alphaValues, nonOpaquePunchThroughAlpha);
175 }
176 }
177
178 private:
179 struct
180 {
181 union
182 {
183 // Individual, differential, H and T modes
184 struct
185 {
186 union
187 {
188 // Individual and differential modes
189 struct
190 {
191 union
192 {
193 struct // Individual colors
194 {
195 unsigned char R2 : 4;
196 unsigned char R1 : 4;
197 unsigned char G2 : 4;
198 unsigned char G1 : 4;
199 unsigned char B2 : 4;
200 unsigned char B1 : 4;
201 };
202
203 struct // Differential colors
204 {
205 signed char dR : 3;
206 unsigned char R : 5;
207 signed char dG : 3;
208 unsigned char G : 5;
209 signed char dB : 3;
210 unsigned char B : 5;
211 };
212 };
213
214 bool flipbit : 1;
215 bool diffbit : 1;
216 unsigned char cw2 : 3;
217 unsigned char cw1 : 3;
218 };
219
220 // T mode
221 struct
222 {
223 // Byte 1
224 unsigned char TR1b : 2;
225 unsigned char TdummyB : 1;
226 unsigned char TR1a : 2;
227 unsigned char TdummyA : 3;
228
229 // Byte 2
230 unsigned char TB1 : 4;
231 unsigned char TG1 : 4;
232
233 // Byte 3
234 unsigned char TG2 : 4;
235 unsigned char TR2 : 4;
236
237 // Byte 4
238 unsigned char Tdb : 1;
239 bool Tflipbit : 1;
240 unsigned char Tda : 2;
241 unsigned char TB2 : 4;
242 };
243
244 // H mode
245 struct
246 {
247 // Byte 1
248 unsigned char HG1a : 3;
249 unsigned char HR1 : 4;
250 unsigned char HdummyA : 1;
251
252 // Byte 2
253 unsigned char HB1b : 2;
254 unsigned char HdummyC : 1;
255 unsigned char HB1a : 1;
256 unsigned char HG1b : 1;
257 unsigned char HdummyB : 3;
258
259 // Byte 3
260 unsigned char HG2a : 3;
261 unsigned char HR2 : 4;
262 unsigned char HB1c : 1;
263
264 // Byte 4
265 unsigned char Hdb : 1;
266 bool Hflipbit : 1;
267 unsigned char Hda : 1;
268 unsigned char HB2 : 4;
269 unsigned char HG2b : 1;
270 };
271 };
272
273 unsigned char pixelIndexMSB[2];
274 unsigned char pixelIndexLSB[2];
275 };
276
277 // planar mode
278 struct
279 {
280 // Byte 1
281 unsigned char GO1 : 1;
282 unsigned char RO : 6;
283 unsigned char PdummyA : 1;
284
285 // Byte 2
286 unsigned char BO1 : 1;
287 unsigned char GO2 : 6;
288 unsigned char PdummyB : 1;
289
290 // Byte 3
291 unsigned char BO3a : 2;
292 unsigned char PdummyD : 1;
293 unsigned char BO2 : 2;
294 unsigned char PdummyC : 3;
295
296 // Byte 4
297 unsigned char RH2 : 1;
298 bool Pflipbit : 1;
299 unsigned char RH1 : 5;
300 unsigned char BO3b : 1;
301
302 // Byte 5
303 unsigned char BHa : 1;
304 unsigned char GH : 7;
305
306 // Byte 6
307 unsigned char RVa : 3;
308 unsigned char BHb : 5;
309
310 // Byte 7
311 unsigned char GVa : 5;
312 unsigned char RVb : 3;
313
314 // Byte 8
315 unsigned char BV : 6;
316 unsigned char GVb : 2;
317 };
318
319 // Single channel block
320 struct
321 {
322 union
323 {
324 unsigned char base_codeword;
325 signed char signed_base_codeword;
326 };
327
328 unsigned char table_index : 4;
329 unsigned char multiplier : 4;
330
331 unsigned char mc1 : 2;
332 unsigned char mb : 3;
333 unsigned char ma : 3;
334
335 unsigned char mf1 : 1;
336 unsigned char me : 3;
337 unsigned char md : 3;
338 unsigned char mc2 : 1;
339
340 unsigned char mh : 3;
341 unsigned char mg : 3;
342 unsigned char mf2 : 2;
343
344 unsigned char mk1 : 2;
345 unsigned char mj : 3;
346 unsigned char mi : 3;
347
348 unsigned char mn1 : 1;
349 unsigned char mm : 3;
350 unsigned char ml : 3;
351 unsigned char mk2 : 1;
352
353 unsigned char mp : 3;
354 unsigned char mo : 3;
355 unsigned char mn2 : 2;
356 };
357 };
358 };
359
360 void decodeIndividualBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4], bool nonOpaquePunchThroughAlpha) const
361 {
362 int r1 = extend_4to8bits(R1);
363 int g1 = extend_4to8bits(G1);
364 int b1 = extend_4to8bits(B1);
365
366 int r2 = extend_4to8bits(R2);
367 int g2 = extend_4to8bits(G2);
368 int b2 = extend_4to8bits(B2);
369
370 decodeIndividualOrDifferentialBlock(dest, x, y, w, h, pitch, r1, g1, b1, r2, g2, b2, alphaValues, nonOpaquePunchThroughAlpha);
371 }
372
373 void decodeDifferentialBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4], bool nonOpaquePunchThroughAlpha) const
374 {
375 int b1 = extend_5to8bits(B);
376 int g1 = extend_5to8bits(G);
377 int r1 = extend_5to8bits(R);
378
379 int r2 = extend_5to8bits(R + dR);
380 int g2 = extend_5to8bits(G + dG);
381 int b2 = extend_5to8bits(B + dB);
382
383 decodeIndividualOrDifferentialBlock(dest, x, y, w, h, pitch, r1, g1, b1, r2, g2, b2, alphaValues, nonOpaquePunchThroughAlpha);
384 }
385
386 void decodeIndividualOrDifferentialBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, int r1, int g1, int b1, int r2, int g2, int b2, unsigned char alphaValues[4][4], bool nonOpaquePunchThroughAlpha) const
387 {
388 // Table 3.17.2 sorted according to table 3.17.3
389 static const int intensityModifierDefault[8][4] =
390 {
391 { 2, 8, -2, -8 },
392 { 5, 17, -5, -17 },
393 { 9, 29, -9, -29 },
394 { 13, 42, -13, -42 },
395 { 18, 60, -18, -60 },
396 { 24, 80, -24, -80 },
397 { 33, 106, -33, -106 },
398 { 47, 183, -47, -183 }
399 };
400
401 // Table C.12, intensity modifier for non opaque punchthrough alpha
402 static const int intensityModifierNonOpaque[8][4] =
403 {
404 { 0, 8, 0, -8 },
405 { 0, 17, 0, -17 },
406 { 0, 29, 0, -29 },
407 { 0, 42, 0, -42 },
408 { 0, 60, 0, -60 },
409 { 0, 80, 0, -80 },
410 { 0, 106, 0, -106 },
411 { 0, 183, 0, -183 }
412 };
413
414 const int(&intensityModifier)[8][4] = nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault;
415
416 bgra8 subblockColors0[4];
417 bgra8 subblockColors1[4];
418
419 const int i10 = intensityModifier[cw1][0];
420 const int i11 = intensityModifier[cw1][1];
421 const int i12 = intensityModifier[cw1][2];
422 const int i13 = intensityModifier[cw1][3];
423
424 subblockColors0[0].set(r1 + i10, g1 + i10, b1 + i10);
425 subblockColors0[1].set(r1 + i11, g1 + i11, b1 + i11);
426 subblockColors0[2].set(r1 + i12, g1 + i12, b1 + i12);
427 subblockColors0[3].set(r1 + i13, g1 + i13, b1 + i13);
428
429 const int i20 = intensityModifier[cw2][0];
430 const int i21 = intensityModifier[cw2][1];
431 const int i22 = intensityModifier[cw2][2];
432 const int i23 = intensityModifier[cw2][3];
433
434 subblockColors1[0].set(r2 + i20, g2 + i20, b2 + i20);
435 subblockColors1[1].set(r2 + i21, g2 + i21, b2 + i21);
436 subblockColors1[2].set(r2 + i22, g2 + i22, b2 + i22);
437 subblockColors1[3].set(r2 + i23, g2 + i23, b2 + i23);
438
439 unsigned char* destStart = dest;
440
441 if(flipbit)
442 {
443 for(int j = 0; j < 2 && (y + j) < h; j++)
444 {
445 bgra8* color = (bgra8*)dest;
446 if((x + 0) < w) color[0] = subblockColors0[getIndex(0, j)].addA(alphaValues[j][0]);
447 if((x + 1) < w) color[1] = subblockColors0[getIndex(1, j)].addA(alphaValues[j][1]);
448 if((x + 2) < w) color[2] = subblockColors0[getIndex(2, j)].addA(alphaValues[j][2]);
449 if((x + 3) < w) color[3] = subblockColors0[getIndex(3, j)].addA(alphaValues[j][3]);
450 dest += pitch;
451 }
452
453 for(int j = 2; j < 4 && (y + j) < h; j++)
454 {
455 bgra8* color = (bgra8*)dest;
456 if((x + 0) < w) color[0] = subblockColors1[getIndex(0, j)].addA(alphaValues[j][0]);
457 if((x + 1) < w) color[1] = subblockColors1[getIndex(1, j)].addA(alphaValues[j][1]);
458 if((x + 2) < w) color[2] = subblockColors1[getIndex(2, j)].addA(alphaValues[j][2]);
459 if((x + 3) < w) color[3] = subblockColors1[getIndex(3, j)].addA(alphaValues[j][3]);
460 dest += pitch;
461 }
462 }
463 else
464 {
465 for(int j = 0; j < 4 && (y + j) < h; j++)
466 {
467 bgra8* color = (bgra8*)dest;
468 if((x + 0) < w) color[0] = subblockColors0[getIndex(0, j)].addA(alphaValues[j][0]);
469 if((x + 1) < w) color[1] = subblockColors0[getIndex(1, j)].addA(alphaValues[j][1]);
470 if((x + 2) < w) color[2] = subblockColors1[getIndex(2, j)].addA(alphaValues[j][2]);
471 if((x + 3) < w) color[3] = subblockColors1[getIndex(3, j)].addA(alphaValues[j][3]);
472 dest += pitch;
473 }
474 }
475
476 if(nonOpaquePunchThroughAlpha)
477 {
478 decodePunchThroughAlphaBlock(destStart, x, y, w, h, pitch);
479 }
480 }
481
482 void decodeTBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4], bool nonOpaquePunchThroughAlpha) const
483 {
484 // Table C.8, distance index fot T and H modes
485 static const int distance[8] = { 3, 6, 11, 16, 23, 32, 41, 64 };
486
487 bgra8 paintColors[4];
488
489 int r1 = extend_4to8bits(TR1a << 2 | TR1b);
490 int g1 = extend_4to8bits(TG1);
491 int b1 = extend_4to8bits(TB1);
492
493 int r2 = extend_4to8bits(TR2);
494 int g2 = extend_4to8bits(TG2);
495 int b2 = extend_4to8bits(TB2);
496
497 const int d = distance[Tda << 1 | Tdb];
498
499 paintColors[0].set(r1, g1, b1);
500 paintColors[1].set(r2 + d, g2 + d, b2 + d);
501 paintColors[2].set(r2, g2, b2);
502 paintColors[3].set(r2 - d, g2 - d, b2 - d);
503
504 unsigned char* destStart = dest;
505
506 for(int j = 0; j < 4 && (y + j) < h; j++)
507 {
508 bgra8* color = (bgra8*)dest;
509 if((x + 0) < w) color[0] = paintColors[getIndex(0, j)].addA(alphaValues[j][0]);
510 if((x + 1) < w) color[1] = paintColors[getIndex(1, j)].addA(alphaValues[j][1]);
511 if((x + 2) < w) color[2] = paintColors[getIndex(2, j)].addA(alphaValues[j][2]);
512 if((x + 3) < w) color[3] = paintColors[getIndex(3, j)].addA(alphaValues[j][3]);
513 dest += pitch;
514 }
515
516 if(nonOpaquePunchThroughAlpha)
517 {
518 decodePunchThroughAlphaBlock(destStart, x, y, w, h, pitch);
519 }
520 }
521
522 void decodeHBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4], bool nonOpaquePunchThroughAlpha) const
523 {
524 // Table C.8, distance index fot T and H modes
525 static const int distance[8] = { 3, 6, 11, 16, 23, 32, 41, 64 };
526
527 bgra8 paintColors[4];
528
529 int r1 = extend_4to8bits(HR1);
530 int g1 = extend_4to8bits(HG1a << 1 | HG1b);
531 int b1 = extend_4to8bits(HB1a << 3 | HB1b << 1 | HB1c);
532
533 int r2 = extend_4to8bits(HR2);
534 int g2 = extend_4to8bits(HG2a << 1 | HG2b);
535 int b2 = extend_4to8bits(HB2);
536
537 const int d = distance[(Hda << 2) | (Hdb << 1) | ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0)];
538
539 paintColors[0].set(r1 + d, g1 + d, b1 + d);
540 paintColors[1].set(r1 - d, g1 - d, b1 - d);
541 paintColors[2].set(r2 + d, g2 + d, b2 + d);
542 paintColors[3].set(r2 - d, g2 - d, b2 - d);
543
544 unsigned char* destStart = dest;
545
546 for(int j = 0; j < 4 && (y + j) < h; j++)
547 {
548 bgra8* color = (bgra8*)dest;
549 if((x + 0) < w) color[0] = paintColors[getIndex(0, j)].addA(alphaValues[j][0]);
550 if((x + 1) < w) color[1] = paintColors[getIndex(1, j)].addA(alphaValues[j][1]);
551 if((x + 2) < w) color[2] = paintColors[getIndex(2, j)].addA(alphaValues[j][2]);
552 if((x + 3) < w) color[3] = paintColors[getIndex(3, j)].addA(alphaValues[j][3]);
553 dest += pitch;
554 }
555
556 if(nonOpaquePunchThroughAlpha)
557 {
558 decodePunchThroughAlphaBlock(destStart, x, y, w, h, pitch);
559 }
560 }
561
562 void decodePlanarBlock(unsigned char *dest, int x, int y, int w, int h, int pitch, unsigned char alphaValues[4][4]) const
563 {
564 int ro = extend_6to8bits(RO);
565 int go = extend_7to8bits(GO1 << 6 | GO2);
566 int bo = extend_6to8bits(BO1 << 5 | BO2 << 3 | BO3a << 1 | BO3b);
567
568 int rh = extend_6to8bits(RH1 << 1 | RH2);
569 int gh = extend_7to8bits(GH);
570 int bh = extend_6to8bits(BHa << 5 | BHb);
571
572 int rv = extend_6to8bits(RVa << 3 | RVb);
573 int gv = extend_7to8bits(GVa << 2 | GVb);
574 int bv = extend_6to8bits(BV);
575
576 for(int j = 0; j < 4 && (y + j) < h; j++)
577 {
578 int ry = j * (rv - ro) + 2;
579 int gy = j * (gv - go) + 2;
580 int by = j * (bv - bo) + 2;
581 for(int i = 0; i < 4 && (x + i) < w; i++)
582 {
583 ((bgra8*)(dest))[i].set(((i * (rh - ro) + ry) >> 2) + ro,
584 ((i * (gh - go) + gy) >> 2) + go,
585 ((i * (bh - bo) + by) >> 2) + bo,
586 alphaValues[j][i]);
587 }
588 dest += pitch;
589 }
590 }
591
592 // Index for individual, differential, H and T modes
593 inline int getIndex(int x, int y) const
594 {
595 int bitIndex = x * 4 + y;
596 int bitOffset = bitIndex & 7;
597 int lsb = (pixelIndexLSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
598 int msb = (pixelIndexMSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
599
600 return (msb << 1) | lsb;
601 }
602
603 void decodePunchThroughAlphaBlock(unsigned char *dest, int x, int y, int w, int h, int pitch) const
604 {
605 for(int j = 0; j < 4 && (y + j) < h; j++)
606 {
607 for(int i = 0; i < 4 && (x + i) < w; i++)
608 {
609 if(getIndex(i, j) == 2) // msb == 1 && lsb == 0
610 {
611 ((bgra8*)dest)[i].set(0, 0, 0, 0);
612 }
613 }
614 dest += pitch;
615 }
616 }
617
618 // Single channel utility functions
619 inline int getSingleChannel(int x, int y, bool isSigned, bool isEAC) const
620 {
621 int codeword = isSigned ? signed_base_codeword : base_codeword;
622 return isEAC ?
623 ((multiplier == 0) ?
624 (codeword * 8 + 4 + getSingleChannelModifier(x, y)) :
625 (codeword * 8 + 4 + getSingleChannelModifier(x, y) * multiplier * 8)) :
626 codeword + getSingleChannelModifier(x, y) * multiplier;
627 }
628
629 inline int getSingleChannelIndex(int x, int y) const
630 {
631 switch(x * 4 + y)
632 {
633 case 0: return ma;
634 case 1: return mb;
635 case 2: return mc1 << 1 | mc2;
636 case 3: return md;
637 case 4: return me;
638 case 5: return mf1 << 2 | mf2;
639 case 6: return mg;
640 case 7: return mh;
641 case 8: return mi;
642 case 9: return mj;
643 case 10: return mk1 << 1 | mk2;
644 case 11: return ml;
645 case 12: return mm;
646 case 13: return mn1 << 2 | mn2;
647 case 14: return mo;
648 default: return mp; // 15
649 }
650 }
651
652 inline int getSingleChannelModifier(int x, int y) const
653 {
654 static const int modifierTable[16][8] = { { -3, -6, -9, -15, 2, 5, 8, 14 },
655 { -3, -7, -10, -13, 2, 6, 9, 12 },
656 { -2, -5, -8, -13, 1, 4, 7, 12 },
657 { -2, -4, -6, -13, 1, 3, 5, 12 },
658 { -3, -6, -8, -12, 2, 5, 7, 11 },
659 { -3, -7, -9, -11, 2, 6, 8, 10 },
660 { -4, -7, -8, -11, 3, 6, 7, 10 },
661 { -3, -5, -8, -11, 2, 4, 7, 10 },
662 { -2, -6, -8, -10, 1, 5, 7, 9 },
663 { -2, -5, -8, -10, 1, 4, 7, 9 },
664 { -2, -4, -8, -10, 1, 3, 7, 9 },
665 { -2, -5, -7, -10, 1, 4, 6, 9 },
666 { -3, -4, -7, -10, 2, 3, 6, 9 },
667 { -1, -2, -3, -10, 0, 1, 2, 9 },
668 { -4, -6, -8, -9, 3, 5, 7, 8 },
669 { -3, -5, -7, -9, 2, 4, 6, 8 } };
670
671 return modifierTable[table_index][getSingleChannelIndex(x, y)];
672 }
673 };
674}
675
676// Decodes 1 to 4 channel images to 8 bit output
677bool ETC_Decoder::Decode(const unsigned char* src, unsigned char *dst, int w, int h, int dstW, int dstH, int dstPitch, int dstBpp, InputType inputType)
678{
679 const ETC2* sources[2];
680 sources[0] = (const ETC2*)src;
681
682 unsigned char alphaValues[4][4] = { { 255, 255, 255, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } };
683
684 switch(inputType)
685 {
686 case ETC_R_SIGNED:
687 case ETC_R_UNSIGNED:
688 for(int y = 0; y < h; y += 4)
689 {
690 unsigned char *dstRow = dst + (y * dstPitch);
691 for(int x = 0; x < w; x += 4, sources[0]++)
692 {
693 ETC2::DecodeBlock(sources, dstRow + (x * dstBpp), 1, x, y, dstW, dstH, dstPitch, inputType == ETC_R_SIGNED, true);
694 }
695 }
696 break;
697 case ETC_RG_SIGNED:
698 case ETC_RG_UNSIGNED:
699 sources[1] = sources[0] + 1;
700 for(int y = 0; y < h; y += 4)
701 {
702 unsigned char *dstRow = dst + (y * dstPitch);
703 for(int x = 0; x < w; x += 4, sources[0] += 2, sources[1] += 2)
704 {
705 ETC2::DecodeBlock(sources, dstRow + (x * dstBpp), 2, x, y, dstW, dstH, dstPitch, inputType == ETC_RG_SIGNED, true);
706 }
707 }
708 break;
709 case ETC_RGB:
710 case ETC_RGB_PUNCHTHROUGH_ALPHA:
711 for(int y = 0; y < h; y += 4)
712 {
713 unsigned char *dstRow = dst + (y * dstPitch);
714 for(int x = 0; x < w; x += 4, sources[0]++)
715 {
716 sources[0]->decodeBlock(dstRow + (x * dstBpp), x, y, dstW, dstH, dstPitch, alphaValues, inputType == ETC_RGB_PUNCHTHROUGH_ALPHA);
717 }
718 }
719 break;
720 case ETC_RGBA:
721 for(int y = 0; y < h; y += 4)
722 {
723 unsigned char *dstRow = dst + (y * dstPitch);
724 for(int x = 0; x < w; x += 4)
725 {
726 // Decode Alpha
727 ETC2::DecodeBlock(&sources[0], &(alphaValues[0][0]), 1, x, y, dstW, dstH, 4, false, false);
728 sources[0]++; // RGBA packets are 128 bits, so move on to the next 64 bit packet to decode the RGB color
729
730 // Decode RGB
731 sources[0]->decodeBlock(dstRow + (x * dstBpp), x, y, dstW, dstH, dstPitch, alphaValues, false);
732 sources[0]++;
733 }
734 }
735 break;
736 default:
737 return false;
738 }
739
740 return true;
741}
742