xref: /aosp_15_r20/external/swiftshader/src/Device/ETC_Decoder.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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