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