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