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