xref: /aosp_15_r20/external/deqp/framework/common/tcuCompressedTexture.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program Tester Core
3*35238bceSAndroid Build Coastguard Worker  * ----------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Compressed Texture Utilities.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "tcuCompressedTexture.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "tcuTextureUtil.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuAstcUtil.hpp"
27*35238bceSAndroid Build Coastguard Worker 
28*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "deFloat16.h"
30*35238bceSAndroid Build Coastguard Worker 
31*35238bceSAndroid Build Coastguard Worker #include <algorithm>
32*35238bceSAndroid Build Coastguard Worker 
33*35238bceSAndroid Build Coastguard Worker namespace tcu
34*35238bceSAndroid Build Coastguard Worker {
35*35238bceSAndroid Build Coastguard Worker 
getBlockSize(CompressedTexFormat format)36*35238bceSAndroid Build Coastguard Worker int getBlockSize(CompressedTexFormat format)
37*35238bceSAndroid Build Coastguard Worker {
38*35238bceSAndroid Build Coastguard Worker     if (isAstcFormat(format))
39*35238bceSAndroid Build Coastguard Worker     {
40*35238bceSAndroid Build Coastguard Worker         return astc::BLOCK_SIZE_BYTES;
41*35238bceSAndroid Build Coastguard Worker     }
42*35238bceSAndroid Build Coastguard Worker     else if (isEtcFormat(format))
43*35238bceSAndroid Build Coastguard Worker     {
44*35238bceSAndroid Build Coastguard Worker         switch (format)
45*35238bceSAndroid Build Coastguard Worker         {
46*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC1_RGB8:
47*35238bceSAndroid Build Coastguard Worker             return 8;
48*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_EAC_R11:
49*35238bceSAndroid Build Coastguard Worker             return 8;
50*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_EAC_SIGNED_R11:
51*35238bceSAndroid Build Coastguard Worker             return 8;
52*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_EAC_RG11:
53*35238bceSAndroid Build Coastguard Worker             return 16;
54*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11:
55*35238bceSAndroid Build Coastguard Worker             return 16;
56*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_RGB8:
57*35238bceSAndroid Build Coastguard Worker             return 8;
58*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_SRGB8:
59*35238bceSAndroid Build Coastguard Worker             return 8;
60*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
61*35238bceSAndroid Build Coastguard Worker             return 8;
62*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
63*35238bceSAndroid Build Coastguard Worker             return 8;
64*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_EAC_RGBA8:
65*35238bceSAndroid Build Coastguard Worker             return 16;
66*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_EAC_SRGB8_ALPHA8:
67*35238bceSAndroid Build Coastguard Worker             return 16;
68*35238bceSAndroid Build Coastguard Worker 
69*35238bceSAndroid Build Coastguard Worker         default:
70*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
71*35238bceSAndroid Build Coastguard Worker             return -1;
72*35238bceSAndroid Build Coastguard Worker         }
73*35238bceSAndroid Build Coastguard Worker     }
74*35238bceSAndroid Build Coastguard Worker     else if (isBcFormat(format))
75*35238bceSAndroid Build Coastguard Worker     {
76*35238bceSAndroid Build Coastguard Worker         switch (format)
77*35238bceSAndroid Build Coastguard Worker         {
78*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC1_RGB_UNORM_BLOCK:
79*35238bceSAndroid Build Coastguard Worker             return 8;
80*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC1_RGB_SRGB_BLOCK:
81*35238bceSAndroid Build Coastguard Worker             return 8;
82*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC1_RGBA_UNORM_BLOCK:
83*35238bceSAndroid Build Coastguard Worker             return 8;
84*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC1_RGBA_SRGB_BLOCK:
85*35238bceSAndroid Build Coastguard Worker             return 8;
86*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC2_UNORM_BLOCK:
87*35238bceSAndroid Build Coastguard Worker             return 16;
88*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC2_SRGB_BLOCK:
89*35238bceSAndroid Build Coastguard Worker             return 16;
90*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC3_UNORM_BLOCK:
91*35238bceSAndroid Build Coastguard Worker             return 16;
92*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC3_SRGB_BLOCK:
93*35238bceSAndroid Build Coastguard Worker             return 16;
94*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK:
95*35238bceSAndroid Build Coastguard Worker             return 8;
96*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK:
97*35238bceSAndroid Build Coastguard Worker             return 8;
98*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK:
99*35238bceSAndroid Build Coastguard Worker             return 16;
100*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK:
101*35238bceSAndroid Build Coastguard Worker             return 16;
102*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK:
103*35238bceSAndroid Build Coastguard Worker             return 16;
104*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK:
105*35238bceSAndroid Build Coastguard Worker             return 16;
106*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK:
107*35238bceSAndroid Build Coastguard Worker             return 16;
108*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK:
109*35238bceSAndroid Build Coastguard Worker             return 16;
110*35238bceSAndroid Build Coastguard Worker 
111*35238bceSAndroid Build Coastguard Worker         default:
112*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
113*35238bceSAndroid Build Coastguard Worker             return -1;
114*35238bceSAndroid Build Coastguard Worker         }
115*35238bceSAndroid Build Coastguard Worker     }
116*35238bceSAndroid Build Coastguard Worker     else if (isAhbRawFormat(format))
117*35238bceSAndroid Build Coastguard Worker     {
118*35238bceSAndroid Build Coastguard Worker         switch (format)
119*35238bceSAndroid Build Coastguard Worker         {
120*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_AHB_RAW10:
121*35238bceSAndroid Build Coastguard Worker             return 5;
122*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_AHB_RAW12:
123*35238bceSAndroid Build Coastguard Worker             return 3;
124*35238bceSAndroid Build Coastguard Worker 
125*35238bceSAndroid Build Coastguard Worker         default:
126*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
127*35238bceSAndroid Build Coastguard Worker             return -1;
128*35238bceSAndroid Build Coastguard Worker         }
129*35238bceSAndroid Build Coastguard Worker     }
130*35238bceSAndroid Build Coastguard Worker     else
131*35238bceSAndroid Build Coastguard Worker     {
132*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
133*35238bceSAndroid Build Coastguard Worker         return -1;
134*35238bceSAndroid Build Coastguard Worker     }
135*35238bceSAndroid Build Coastguard Worker }
136*35238bceSAndroid Build Coastguard Worker 
getBlockPixelSize(CompressedTexFormat format)137*35238bceSAndroid Build Coastguard Worker IVec3 getBlockPixelSize(CompressedTexFormat format)
138*35238bceSAndroid Build Coastguard Worker {
139*35238bceSAndroid Build Coastguard Worker     if (isEtcFormat(format))
140*35238bceSAndroid Build Coastguard Worker     {
141*35238bceSAndroid Build Coastguard Worker         return IVec3(4, 4, 1);
142*35238bceSAndroid Build Coastguard Worker     }
143*35238bceSAndroid Build Coastguard Worker     else if (isAstcFormat(format))
144*35238bceSAndroid Build Coastguard Worker     {
145*35238bceSAndroid Build Coastguard Worker         switch (format)
146*35238bceSAndroid Build Coastguard Worker         {
147*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_4x4_RGBA:
148*35238bceSAndroid Build Coastguard Worker             return IVec3(4, 4, 1);
149*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_5x4_RGBA:
150*35238bceSAndroid Build Coastguard Worker             return IVec3(5, 4, 1);
151*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_5x5_RGBA:
152*35238bceSAndroid Build Coastguard Worker             return IVec3(5, 5, 1);
153*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_6x5_RGBA:
154*35238bceSAndroid Build Coastguard Worker             return IVec3(6, 5, 1);
155*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_6x6_RGBA:
156*35238bceSAndroid Build Coastguard Worker             return IVec3(6, 6, 1);
157*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_8x5_RGBA:
158*35238bceSAndroid Build Coastguard Worker             return IVec3(8, 5, 1);
159*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_8x6_RGBA:
160*35238bceSAndroid Build Coastguard Worker             return IVec3(8, 6, 1);
161*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_8x8_RGBA:
162*35238bceSAndroid Build Coastguard Worker             return IVec3(8, 8, 1);
163*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_10x5_RGBA:
164*35238bceSAndroid Build Coastguard Worker             return IVec3(10, 5, 1);
165*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_10x6_RGBA:
166*35238bceSAndroid Build Coastguard Worker             return IVec3(10, 6, 1);
167*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_10x8_RGBA:
168*35238bceSAndroid Build Coastguard Worker             return IVec3(10, 8, 1);
169*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_10x10_RGBA:
170*35238bceSAndroid Build Coastguard Worker             return IVec3(10, 10, 1);
171*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_12x10_RGBA:
172*35238bceSAndroid Build Coastguard Worker             return IVec3(12, 10, 1);
173*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA:
174*35238bceSAndroid Build Coastguard Worker             return IVec3(12, 12, 1);
175*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8:
176*35238bceSAndroid Build Coastguard Worker             return IVec3(4, 4, 1);
177*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_5x4_SRGB8_ALPHA8:
178*35238bceSAndroid Build Coastguard Worker             return IVec3(5, 4, 1);
179*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8:
180*35238bceSAndroid Build Coastguard Worker             return IVec3(5, 5, 1);
181*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8:
182*35238bceSAndroid Build Coastguard Worker             return IVec3(6, 5, 1);
183*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8:
184*35238bceSAndroid Build Coastguard Worker             return IVec3(6, 6, 1);
185*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_8x5_SRGB8_ALPHA8:
186*35238bceSAndroid Build Coastguard Worker             return IVec3(8, 5, 1);
187*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8:
188*35238bceSAndroid Build Coastguard Worker             return IVec3(8, 6, 1);
189*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8:
190*35238bceSAndroid Build Coastguard Worker             return IVec3(8, 8, 1);
191*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8:
192*35238bceSAndroid Build Coastguard Worker             return IVec3(10, 5, 1);
193*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8:
194*35238bceSAndroid Build Coastguard Worker             return IVec3(10, 6, 1);
195*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8:
196*35238bceSAndroid Build Coastguard Worker             return IVec3(10, 8, 1);
197*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8:
198*35238bceSAndroid Build Coastguard Worker             return IVec3(10, 10, 1);
199*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8:
200*35238bceSAndroid Build Coastguard Worker             return IVec3(12, 10, 1);
201*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8:
202*35238bceSAndroid Build Coastguard Worker             return IVec3(12, 12, 1);
203*35238bceSAndroid Build Coastguard Worker 
204*35238bceSAndroid Build Coastguard Worker         default:
205*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
206*35238bceSAndroid Build Coastguard Worker             return IVec3();
207*35238bceSAndroid Build Coastguard Worker         }
208*35238bceSAndroid Build Coastguard Worker     }
209*35238bceSAndroid Build Coastguard Worker     else if (isBcFormat(format))
210*35238bceSAndroid Build Coastguard Worker     {
211*35238bceSAndroid Build Coastguard Worker         return IVec3(4, 4, 1);
212*35238bceSAndroid Build Coastguard Worker     }
213*35238bceSAndroid Build Coastguard Worker     else if (isAhbRawFormat(format))
214*35238bceSAndroid Build Coastguard Worker     {
215*35238bceSAndroid Build Coastguard Worker         switch (format)
216*35238bceSAndroid Build Coastguard Worker         {
217*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_AHB_RAW10:
218*35238bceSAndroid Build Coastguard Worker             return IVec3(4, 1, 1);
219*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_AHB_RAW12:
220*35238bceSAndroid Build Coastguard Worker             return IVec3(2, 1, 1);
221*35238bceSAndroid Build Coastguard Worker 
222*35238bceSAndroid Build Coastguard Worker         default:
223*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
224*35238bceSAndroid Build Coastguard Worker             return IVec3();
225*35238bceSAndroid Build Coastguard Worker         }
226*35238bceSAndroid Build Coastguard Worker     }
227*35238bceSAndroid Build Coastguard Worker     else
228*35238bceSAndroid Build Coastguard Worker     {
229*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
230*35238bceSAndroid Build Coastguard Worker         return IVec3(-1);
231*35238bceSAndroid Build Coastguard Worker     }
232*35238bceSAndroid Build Coastguard Worker }
233*35238bceSAndroid Build Coastguard Worker 
isEtcFormat(CompressedTexFormat format)234*35238bceSAndroid Build Coastguard Worker bool isEtcFormat(CompressedTexFormat format)
235*35238bceSAndroid Build Coastguard Worker {
236*35238bceSAndroid Build Coastguard Worker     switch (format)
237*35238bceSAndroid Build Coastguard Worker     {
238*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC1_RGB8:
239*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_EAC_R11:
240*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_EAC_SIGNED_R11:
241*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_EAC_RG11:
242*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11:
243*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_RGB8:
244*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_SRGB8:
245*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
246*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
247*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_EAC_RGBA8:
248*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_EAC_SRGB8_ALPHA8:
249*35238bceSAndroid Build Coastguard Worker         return true;
250*35238bceSAndroid Build Coastguard Worker 
251*35238bceSAndroid Build Coastguard Worker     default:
252*35238bceSAndroid Build Coastguard Worker         return false;
253*35238bceSAndroid Build Coastguard Worker     }
254*35238bceSAndroid Build Coastguard Worker }
255*35238bceSAndroid Build Coastguard Worker 
isBcFormat(CompressedTexFormat format)256*35238bceSAndroid Build Coastguard Worker bool isBcFormat(CompressedTexFormat format)
257*35238bceSAndroid Build Coastguard Worker {
258*35238bceSAndroid Build Coastguard Worker     switch (format)
259*35238bceSAndroid Build Coastguard Worker     {
260*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC1_RGB_UNORM_BLOCK:
261*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC1_RGB_SRGB_BLOCK:
262*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC1_RGBA_UNORM_BLOCK:
263*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC1_RGBA_SRGB_BLOCK:
264*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC2_UNORM_BLOCK:
265*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC2_SRGB_BLOCK:
266*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC3_UNORM_BLOCK:
267*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC3_SRGB_BLOCK:
268*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK:
269*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK:
270*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK:
271*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK:
272*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK:
273*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK:
274*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK:
275*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK:
276*35238bceSAndroid Build Coastguard Worker         return true;
277*35238bceSAndroid Build Coastguard Worker 
278*35238bceSAndroid Build Coastguard Worker     default:
279*35238bceSAndroid Build Coastguard Worker         return false;
280*35238bceSAndroid Build Coastguard Worker     }
281*35238bceSAndroid Build Coastguard Worker }
282*35238bceSAndroid Build Coastguard Worker 
isBcBitExactFormat(CompressedTexFormat format)283*35238bceSAndroid Build Coastguard Worker bool isBcBitExactFormat(CompressedTexFormat format)
284*35238bceSAndroid Build Coastguard Worker {
285*35238bceSAndroid Build Coastguard Worker     switch (format)
286*35238bceSAndroid Build Coastguard Worker     {
287*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK:
288*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK:
289*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK:
290*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK:
291*35238bceSAndroid Build Coastguard Worker         return true;
292*35238bceSAndroid Build Coastguard Worker 
293*35238bceSAndroid Build Coastguard Worker     default:
294*35238bceSAndroid Build Coastguard Worker         return false;
295*35238bceSAndroid Build Coastguard Worker     }
296*35238bceSAndroid Build Coastguard Worker }
297*35238bceSAndroid Build Coastguard Worker 
isBcSRGBFormat(CompressedTexFormat format)298*35238bceSAndroid Build Coastguard Worker bool isBcSRGBFormat(CompressedTexFormat format)
299*35238bceSAndroid Build Coastguard Worker {
300*35238bceSAndroid Build Coastguard Worker     switch (format)
301*35238bceSAndroid Build Coastguard Worker     {
302*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC1_RGB_SRGB_BLOCK:
303*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC1_RGBA_SRGB_BLOCK:
304*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC2_SRGB_BLOCK:
305*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC3_SRGB_BLOCK:
306*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK:
307*35238bceSAndroid Build Coastguard Worker         return true;
308*35238bceSAndroid Build Coastguard Worker 
309*35238bceSAndroid Build Coastguard Worker     default:
310*35238bceSAndroid Build Coastguard Worker         return false;
311*35238bceSAndroid Build Coastguard Worker     }
312*35238bceSAndroid Build Coastguard Worker }
313*35238bceSAndroid Build Coastguard Worker 
isAstcFormat(CompressedTexFormat format)314*35238bceSAndroid Build Coastguard Worker bool isAstcFormat(CompressedTexFormat format)
315*35238bceSAndroid Build Coastguard Worker {
316*35238bceSAndroid Build Coastguard Worker     switch (format)
317*35238bceSAndroid Build Coastguard Worker     {
318*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_4x4_RGBA:
319*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_5x4_RGBA:
320*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_5x5_RGBA:
321*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_6x5_RGBA:
322*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_6x6_RGBA:
323*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x5_RGBA:
324*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x6_RGBA:
325*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x8_RGBA:
326*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x5_RGBA:
327*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x6_RGBA:
328*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x8_RGBA:
329*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x10_RGBA:
330*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_12x10_RGBA:
331*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA:
332*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8:
333*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_5x4_SRGB8_ALPHA8:
334*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8:
335*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8:
336*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8:
337*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x5_SRGB8_ALPHA8:
338*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8:
339*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8:
340*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8:
341*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8:
342*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8:
343*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8:
344*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8:
345*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8:
346*35238bceSAndroid Build Coastguard Worker         return true;
347*35238bceSAndroid Build Coastguard Worker 
348*35238bceSAndroid Build Coastguard Worker     default:
349*35238bceSAndroid Build Coastguard Worker         return false;
350*35238bceSAndroid Build Coastguard Worker     }
351*35238bceSAndroid Build Coastguard Worker }
352*35238bceSAndroid Build Coastguard Worker 
isAstcSRGBFormat(CompressedTexFormat format)353*35238bceSAndroid Build Coastguard Worker bool isAstcSRGBFormat(CompressedTexFormat format)
354*35238bceSAndroid Build Coastguard Worker {
355*35238bceSAndroid Build Coastguard Worker     switch (format)
356*35238bceSAndroid Build Coastguard Worker     {
357*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8:
358*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_5x4_SRGB8_ALPHA8:
359*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8:
360*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8:
361*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8:
362*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x5_SRGB8_ALPHA8:
363*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8:
364*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8:
365*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8:
366*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8:
367*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8:
368*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8:
369*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8:
370*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8:
371*35238bceSAndroid Build Coastguard Worker         return true;
372*35238bceSAndroid Build Coastguard Worker 
373*35238bceSAndroid Build Coastguard Worker     default:
374*35238bceSAndroid Build Coastguard Worker         return false;
375*35238bceSAndroid Build Coastguard Worker     }
376*35238bceSAndroid Build Coastguard Worker }
377*35238bceSAndroid Build Coastguard Worker 
isAhbRawFormat(CompressedTexFormat format)378*35238bceSAndroid Build Coastguard Worker bool isAhbRawFormat(CompressedTexFormat format)
379*35238bceSAndroid Build Coastguard Worker {
380*35238bceSAndroid Build Coastguard Worker     switch (format)
381*35238bceSAndroid Build Coastguard Worker     {
382*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_AHB_RAW10:
383*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_AHB_RAW12:
384*35238bceSAndroid Build Coastguard Worker         return true;
385*35238bceSAndroid Build Coastguard Worker 
386*35238bceSAndroid Build Coastguard Worker     default:
387*35238bceSAndroid Build Coastguard Worker         return false;
388*35238bceSAndroid Build Coastguard Worker     }
389*35238bceSAndroid Build Coastguard Worker }
390*35238bceSAndroid Build Coastguard Worker 
getUncompressedFormat(CompressedTexFormat format)391*35238bceSAndroid Build Coastguard Worker TextureFormat getUncompressedFormat(CompressedTexFormat format)
392*35238bceSAndroid Build Coastguard Worker {
393*35238bceSAndroid Build Coastguard Worker     if (isEtcFormat(format))
394*35238bceSAndroid Build Coastguard Worker     {
395*35238bceSAndroid Build Coastguard Worker         switch (format)
396*35238bceSAndroid Build Coastguard Worker         {
397*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC1_RGB8:
398*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8);
399*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_EAC_R11:
400*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::R, TextureFormat::UNORM_INT16);
401*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_EAC_SIGNED_R11:
402*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::R, TextureFormat::SNORM_INT16);
403*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_EAC_RG11:
404*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::RG, TextureFormat::UNORM_INT16);
405*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11:
406*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::RG, TextureFormat::SNORM_INT16);
407*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_RGB8:
408*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8);
409*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_SRGB8:
410*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::sRGB, TextureFormat::UNORM_INT8);
411*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
412*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
413*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
414*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::sRGBA, TextureFormat::UNORM_INT8);
415*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_EAC_RGBA8:
416*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
417*35238bceSAndroid Build Coastguard Worker         case COMPRESSEDTEXFORMAT_ETC2_EAC_SRGB8_ALPHA8:
418*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::sRGBA, TextureFormat::UNORM_INT8);
419*35238bceSAndroid Build Coastguard Worker 
420*35238bceSAndroid Build Coastguard Worker         default:
421*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
422*35238bceSAndroid Build Coastguard Worker             return TextureFormat();
423*35238bceSAndroid Build Coastguard Worker         }
424*35238bceSAndroid Build Coastguard Worker     }
425*35238bceSAndroid Build Coastguard Worker     else if (isAstcFormat(format))
426*35238bceSAndroid Build Coastguard Worker     {
427*35238bceSAndroid Build Coastguard Worker         if (isAstcSRGBFormat(format))
428*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::sRGBA, TextureFormat::UNORM_INT8);
429*35238bceSAndroid Build Coastguard Worker         else
430*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::RGBA, TextureFormat::HALF_FLOAT);
431*35238bceSAndroid Build Coastguard Worker     }
432*35238bceSAndroid Build Coastguard Worker     else if (isBcFormat(format))
433*35238bceSAndroid Build Coastguard Worker     {
434*35238bceSAndroid Build Coastguard Worker         if (format == COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK || format == COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK)
435*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::R, TextureFormat::FLOAT);
436*35238bceSAndroid Build Coastguard Worker         else if (format == COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK || format == COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK)
437*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::RG, TextureFormat::FLOAT);
438*35238bceSAndroid Build Coastguard Worker         else if (format == COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK || format == COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK)
439*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::RGB, TextureFormat::HALF_FLOAT);
440*35238bceSAndroid Build Coastguard Worker         else if (isBcSRGBFormat(format))
441*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::sRGBA, TextureFormat::UNORM_INT8);
442*35238bceSAndroid Build Coastguard Worker         else
443*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
444*35238bceSAndroid Build Coastguard Worker     }
445*35238bceSAndroid Build Coastguard Worker     else if (isAhbRawFormat(format))
446*35238bceSAndroid Build Coastguard Worker     {
447*35238bceSAndroid Build Coastguard Worker         if (format == COMPRESSEDTEXFORMAT_AHB_RAW10)
448*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::R,
449*35238bceSAndroid Build Coastguard Worker                                  TextureFormat::UNORM_SHORT_10); // Can be changed to a more fitting value if needed
450*35238bceSAndroid Build Coastguard Worker         else                                                     // COMPRESSEDTEXFORMAT_AHB_RAW12
451*35238bceSAndroid Build Coastguard Worker             return TextureFormat(TextureFormat::R,
452*35238bceSAndroid Build Coastguard Worker                                  TextureFormat::UNORM_SHORT_12); // Can be changed to a more fitting value if needed
453*35238bceSAndroid Build Coastguard Worker     }
454*35238bceSAndroid Build Coastguard Worker     else
455*35238bceSAndroid Build Coastguard Worker     {
456*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
457*35238bceSAndroid Build Coastguard Worker         return TextureFormat();
458*35238bceSAndroid Build Coastguard Worker     }
459*35238bceSAndroid Build Coastguard Worker }
460*35238bceSAndroid Build Coastguard Worker 
getAstcFormatByBlockSize(const IVec3 & size,bool isSRGB)461*35238bceSAndroid Build Coastguard Worker CompressedTexFormat getAstcFormatByBlockSize(const IVec3 &size, bool isSRGB)
462*35238bceSAndroid Build Coastguard Worker {
463*35238bceSAndroid Build Coastguard Worker     if (size.z() > 1)
464*35238bceSAndroid Build Coastguard Worker         throw InternalError("3D ASTC textures not currently supported");
465*35238bceSAndroid Build Coastguard Worker 
466*35238bceSAndroid Build Coastguard Worker     for (int fmtI = 0; fmtI < COMPRESSEDTEXFORMAT_LAST; fmtI++)
467*35238bceSAndroid Build Coastguard Worker     {
468*35238bceSAndroid Build Coastguard Worker         const CompressedTexFormat fmt = (CompressedTexFormat)fmtI;
469*35238bceSAndroid Build Coastguard Worker 
470*35238bceSAndroid Build Coastguard Worker         if (isAstcFormat(fmt) && getBlockPixelSize(fmt) == size && isAstcSRGBFormat(fmt) == isSRGB)
471*35238bceSAndroid Build Coastguard Worker             return fmt;
472*35238bceSAndroid Build Coastguard Worker     }
473*35238bceSAndroid Build Coastguard Worker 
474*35238bceSAndroid Build Coastguard Worker     throw InternalError("Invalid ASTC block size " + de::toString(size.x()) + "x" + de::toString(size.y()) + "x" +
475*35238bceSAndroid Build Coastguard Worker                         de::toString(size.z()));
476*35238bceSAndroid Build Coastguard Worker }
477*35238bceSAndroid Build Coastguard Worker 
478*35238bceSAndroid Build Coastguard Worker namespace
479*35238bceSAndroid Build Coastguard Worker {
480*35238bceSAndroid Build Coastguard Worker 
extend4To8(uint8_t src)481*35238bceSAndroid Build Coastguard Worker inline uint8_t extend4To8(uint8_t src)
482*35238bceSAndroid Build Coastguard Worker {
483*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((src & ~((1 << 4) - 1)) == 0);
484*35238bceSAndroid Build Coastguard Worker     return (uint8_t)((src << 4) | src);
485*35238bceSAndroid Build Coastguard Worker }
486*35238bceSAndroid Build Coastguard Worker 
extend5To8(uint8_t src)487*35238bceSAndroid Build Coastguard Worker inline uint8_t extend5To8(uint8_t src)
488*35238bceSAndroid Build Coastguard Worker {
489*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((src & ~((1 << 5) - 1)) == 0);
490*35238bceSAndroid Build Coastguard Worker     return (uint8_t)((src << 3) | (src >> 2));
491*35238bceSAndroid Build Coastguard Worker }
492*35238bceSAndroid Build Coastguard Worker 
extend6To8(uint8_t src)493*35238bceSAndroid Build Coastguard Worker inline uint8_t extend6To8(uint8_t src)
494*35238bceSAndroid Build Coastguard Worker {
495*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((src & ~((1 << 6) - 1)) == 0);
496*35238bceSAndroid Build Coastguard Worker     return (uint8_t)((src << 2) | (src >> 4));
497*35238bceSAndroid Build Coastguard Worker }
498*35238bceSAndroid Build Coastguard Worker 
499*35238bceSAndroid Build Coastguard Worker // \todo [2013-08-06 nuutti] ETC and ASTC decompression codes are rather unrelated, and are already in their own "private" namespaces - should this be split to multiple files?
500*35238bceSAndroid Build Coastguard Worker 
501*35238bceSAndroid Build Coastguard Worker namespace EtcDecompressInternal
502*35238bceSAndroid Build Coastguard Worker {
503*35238bceSAndroid Build Coastguard Worker 
504*35238bceSAndroid Build Coastguard Worker enum
505*35238bceSAndroid Build Coastguard Worker {
506*35238bceSAndroid Build Coastguard Worker     ETC2_BLOCK_WIDTH                   = 4,
507*35238bceSAndroid Build Coastguard Worker     ETC2_BLOCK_HEIGHT                  = 4,
508*35238bceSAndroid Build Coastguard Worker     ETC2_UNCOMPRESSED_PIXEL_SIZE_A8    = 1,
509*35238bceSAndroid Build Coastguard Worker     ETC2_UNCOMPRESSED_PIXEL_SIZE_R11   = 2,
510*35238bceSAndroid Build Coastguard Worker     ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11  = 4,
511*35238bceSAndroid Build Coastguard Worker     ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8  = 3,
512*35238bceSAndroid Build Coastguard Worker     ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 = 4,
513*35238bceSAndroid Build Coastguard Worker     ETC2_UNCOMPRESSED_BLOCK_SIZE_A8    = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8,
514*35238bceSAndroid Build Coastguard Worker     ETC2_UNCOMPRESSED_BLOCK_SIZE_R11   = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_R11,
515*35238bceSAndroid Build Coastguard Worker     ETC2_UNCOMPRESSED_BLOCK_SIZE_RG11  = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11,
516*35238bceSAndroid Build Coastguard Worker     ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8  = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8,
517*35238bceSAndroid Build Coastguard Worker     ETC2_UNCOMPRESSED_BLOCK_SIZE_RGBA8 = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8
518*35238bceSAndroid Build Coastguard Worker };
519*35238bceSAndroid Build Coastguard Worker 
get64BitBlock(const uint8_t * src,int blockNdx)520*35238bceSAndroid Build Coastguard Worker inline uint64_t get64BitBlock(const uint8_t *src, int blockNdx)
521*35238bceSAndroid Build Coastguard Worker {
522*35238bceSAndroid Build Coastguard Worker     // Stored in big-endian form.
523*35238bceSAndroid Build Coastguard Worker     uint64_t block = 0;
524*35238bceSAndroid Build Coastguard Worker 
525*35238bceSAndroid Build Coastguard Worker     for (int i = 0; i < 8; i++)
526*35238bceSAndroid Build Coastguard Worker         block = (block << 8ull) | (uint64_t)(src[blockNdx * 8 + i]);
527*35238bceSAndroid Build Coastguard Worker 
528*35238bceSAndroid Build Coastguard Worker     return block;
529*35238bceSAndroid Build Coastguard Worker }
530*35238bceSAndroid Build Coastguard Worker 
531*35238bceSAndroid Build Coastguard Worker // Return the first 64 bits of a 128 bit block.
get128BitBlockStart(const uint8_t * src,int blockNdx)532*35238bceSAndroid Build Coastguard Worker inline uint64_t get128BitBlockStart(const uint8_t *src, int blockNdx)
533*35238bceSAndroid Build Coastguard Worker {
534*35238bceSAndroid Build Coastguard Worker     return get64BitBlock(src, 2 * blockNdx);
535*35238bceSAndroid Build Coastguard Worker }
536*35238bceSAndroid Build Coastguard Worker 
537*35238bceSAndroid Build Coastguard Worker // Return the last 64 bits of a 128 bit block.
get128BitBlockEnd(const uint8_t * src,int blockNdx)538*35238bceSAndroid Build Coastguard Worker inline uint64_t get128BitBlockEnd(const uint8_t *src, int blockNdx)
539*35238bceSAndroid Build Coastguard Worker {
540*35238bceSAndroid Build Coastguard Worker     return get64BitBlock(src, 2 * blockNdx + 1);
541*35238bceSAndroid Build Coastguard Worker }
542*35238bceSAndroid Build Coastguard Worker 
getBit(uint64_t src,int bit)543*35238bceSAndroid Build Coastguard Worker inline uint32_t getBit(uint64_t src, int bit)
544*35238bceSAndroid Build Coastguard Worker {
545*35238bceSAndroid Build Coastguard Worker     return (src >> bit) & 1;
546*35238bceSAndroid Build Coastguard Worker }
547*35238bceSAndroid Build Coastguard Worker 
getBits(uint64_t src,int low,int high)548*35238bceSAndroid Build Coastguard Worker inline uint32_t getBits(uint64_t src, int low, int high)
549*35238bceSAndroid Build Coastguard Worker {
550*35238bceSAndroid Build Coastguard Worker     const int numBits = (high - low) + 1;
551*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(numBits, 1, 32));
552*35238bceSAndroid Build Coastguard Worker     if (numBits < 32)
553*35238bceSAndroid Build Coastguard Worker         return (uint32_t)((src >> low) & ((1u << numBits) - 1));
554*35238bceSAndroid Build Coastguard Worker     else
555*35238bceSAndroid Build Coastguard Worker         return (uint32_t)((src >> low) & 0xFFFFFFFFu);
556*35238bceSAndroid Build Coastguard Worker }
557*35238bceSAndroid Build Coastguard Worker 
extend7To8(uint8_t src)558*35238bceSAndroid Build Coastguard Worker inline uint8_t extend7To8(uint8_t src)
559*35238bceSAndroid Build Coastguard Worker {
560*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((src & ~((1 << 7) - 1)) == 0);
561*35238bceSAndroid Build Coastguard Worker     return (uint8_t)((src << 1) | (src >> 6));
562*35238bceSAndroid Build Coastguard Worker }
563*35238bceSAndroid Build Coastguard Worker 
extendSigned3To8(uint8_t src)564*35238bceSAndroid Build Coastguard Worker inline int8_t extendSigned3To8(uint8_t src)
565*35238bceSAndroid Build Coastguard Worker {
566*35238bceSAndroid Build Coastguard Worker     const bool isNeg = (src & (1 << 2)) != 0;
567*35238bceSAndroid Build Coastguard Worker     return (int8_t)((isNeg ? ~((1 << 3) - 1) : 0) | src);
568*35238bceSAndroid Build Coastguard Worker }
569*35238bceSAndroid Build Coastguard Worker 
extend5Delta3To8(uint8_t base5,uint8_t delta3)570*35238bceSAndroid Build Coastguard Worker inline uint8_t extend5Delta3To8(uint8_t base5, uint8_t delta3)
571*35238bceSAndroid Build Coastguard Worker {
572*35238bceSAndroid Build Coastguard Worker     const uint8_t t = (uint8_t)((int8_t)base5 + extendSigned3To8(delta3));
573*35238bceSAndroid Build Coastguard Worker     return extend5To8(t);
574*35238bceSAndroid Build Coastguard Worker }
575*35238bceSAndroid Build Coastguard Worker 
extend11To16(uint16_t src)576*35238bceSAndroid Build Coastguard Worker inline uint16_t extend11To16(uint16_t src)
577*35238bceSAndroid Build Coastguard Worker {
578*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((src & ~((1 << 11) - 1)) == 0);
579*35238bceSAndroid Build Coastguard Worker     return (uint16_t)((src << 5) | (src >> 6));
580*35238bceSAndroid Build Coastguard Worker }
581*35238bceSAndroid Build Coastguard Worker 
extend11To16WithSign(int16_t src)582*35238bceSAndroid Build Coastguard Worker inline int16_t extend11To16WithSign(int16_t src)
583*35238bceSAndroid Build Coastguard Worker {
584*35238bceSAndroid Build Coastguard Worker     if (src < 0)
585*35238bceSAndroid Build Coastguard Worker         return (int16_t)(-(int16_t)extend11To16((uint16_t)(-src)));
586*35238bceSAndroid Build Coastguard Worker     else
587*35238bceSAndroid Build Coastguard Worker         return (int16_t)extend11To16(src);
588*35238bceSAndroid Build Coastguard Worker }
589*35238bceSAndroid Build Coastguard Worker 
decompressETC1Block(uint8_t dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8],uint64_t src)590*35238bceSAndroid Build Coastguard Worker void decompressETC1Block(uint8_t dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8], uint64_t src)
591*35238bceSAndroid Build Coastguard Worker {
592*35238bceSAndroid Build Coastguard Worker     const int diffBit       = (int)getBit(src, 33);
593*35238bceSAndroid Build Coastguard Worker     const int flipBit       = (int)getBit(src, 32);
594*35238bceSAndroid Build Coastguard Worker     const uint32_t table[2] = {getBits(src, 37, 39), getBits(src, 34, 36)};
595*35238bceSAndroid Build Coastguard Worker     uint8_t baseR[2];
596*35238bceSAndroid Build Coastguard Worker     uint8_t baseG[2];
597*35238bceSAndroid Build Coastguard Worker     uint8_t baseB[2];
598*35238bceSAndroid Build Coastguard Worker 
599*35238bceSAndroid Build Coastguard Worker     if (diffBit == 0)
600*35238bceSAndroid Build Coastguard Worker     {
601*35238bceSAndroid Build Coastguard Worker         // Individual mode.
602*35238bceSAndroid Build Coastguard Worker         baseR[0] = extend4To8((uint8_t)getBits(src, 60, 63));
603*35238bceSAndroid Build Coastguard Worker         baseR[1] = extend4To8((uint8_t)getBits(src, 56, 59));
604*35238bceSAndroid Build Coastguard Worker         baseG[0] = extend4To8((uint8_t)getBits(src, 52, 55));
605*35238bceSAndroid Build Coastguard Worker         baseG[1] = extend4To8((uint8_t)getBits(src, 48, 51));
606*35238bceSAndroid Build Coastguard Worker         baseB[0] = extend4To8((uint8_t)getBits(src, 44, 47));
607*35238bceSAndroid Build Coastguard Worker         baseB[1] = extend4To8((uint8_t)getBits(src, 40, 43));
608*35238bceSAndroid Build Coastguard Worker     }
609*35238bceSAndroid Build Coastguard Worker     else
610*35238bceSAndroid Build Coastguard Worker     {
611*35238bceSAndroid Build Coastguard Worker         // Differential mode (diffBit == 1).
612*35238bceSAndroid Build Coastguard Worker         uint8_t bR = (uint8_t)getBits(src, 59, 63); // 5b
613*35238bceSAndroid Build Coastguard Worker         uint8_t dR = (uint8_t)getBits(src, 56, 58); // 3b
614*35238bceSAndroid Build Coastguard Worker         uint8_t bG = (uint8_t)getBits(src, 51, 55);
615*35238bceSAndroid Build Coastguard Worker         uint8_t dG = (uint8_t)getBits(src, 48, 50);
616*35238bceSAndroid Build Coastguard Worker         uint8_t bB = (uint8_t)getBits(src, 43, 47);
617*35238bceSAndroid Build Coastguard Worker         uint8_t dB = (uint8_t)getBits(src, 40, 42);
618*35238bceSAndroid Build Coastguard Worker 
619*35238bceSAndroid Build Coastguard Worker         baseR[0] = extend5To8(bR);
620*35238bceSAndroid Build Coastguard Worker         baseG[0] = extend5To8(bG);
621*35238bceSAndroid Build Coastguard Worker         baseB[0] = extend5To8(bB);
622*35238bceSAndroid Build Coastguard Worker 
623*35238bceSAndroid Build Coastguard Worker         baseR[1] = extend5Delta3To8(bR, dR);
624*35238bceSAndroid Build Coastguard Worker         baseG[1] = extend5Delta3To8(bG, dG);
625*35238bceSAndroid Build Coastguard Worker         baseB[1] = extend5Delta3To8(bB, dB);
626*35238bceSAndroid Build Coastguard Worker     }
627*35238bceSAndroid Build Coastguard Worker 
628*35238bceSAndroid Build Coastguard Worker     static const int modifierTable[8][4] = {//      00   01   10    11
629*35238bceSAndroid Build Coastguard Worker                                             {2, 8, -2, -8},       {5, 17, -5, -17},    {9, 29, -9, -29},
630*35238bceSAndroid Build Coastguard Worker                                             {13, 42, -13, -42},   {18, 60, -18, -60},  {24, 80, -24, -80},
631*35238bceSAndroid Build Coastguard Worker                                             {33, 106, -33, -106}, {47, 183, -47, -183}};
632*35238bceSAndroid Build Coastguard Worker 
633*35238bceSAndroid Build Coastguard Worker     // Write final pixels.
634*35238bceSAndroid Build Coastguard Worker     for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT * ETC2_BLOCK_WIDTH; pixelNdx++)
635*35238bceSAndroid Build Coastguard Worker     {
636*35238bceSAndroid Build Coastguard Worker         const int x                = pixelNdx / ETC2_BLOCK_HEIGHT;
637*35238bceSAndroid Build Coastguard Worker         const int y                = pixelNdx % ETC2_BLOCK_HEIGHT;
638*35238bceSAndroid Build Coastguard Worker         const int dstOffset        = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
639*35238bceSAndroid Build Coastguard Worker         const int subBlock         = ((flipBit ? y : x) >= 2) ? 1 : 0;
640*35238bceSAndroid Build Coastguard Worker         const uint32_t tableNdx    = table[subBlock];
641*35238bceSAndroid Build Coastguard Worker         const uint32_t modifierNdx = (getBit(src, 16 + pixelNdx) << 1) | getBit(src, pixelNdx);
642*35238bceSAndroid Build Coastguard Worker         const int modifier         = modifierTable[tableNdx][modifierNdx];
643*35238bceSAndroid Build Coastguard Worker 
644*35238bceSAndroid Build Coastguard Worker         dst[dstOffset + 0] = (uint8_t)deClamp32((int)baseR[subBlock] + modifier, 0, 255);
645*35238bceSAndroid Build Coastguard Worker         dst[dstOffset + 1] = (uint8_t)deClamp32((int)baseG[subBlock] + modifier, 0, 255);
646*35238bceSAndroid Build Coastguard Worker         dst[dstOffset + 2] = (uint8_t)deClamp32((int)baseB[subBlock] + modifier, 0, 255);
647*35238bceSAndroid Build Coastguard Worker     }
648*35238bceSAndroid Build Coastguard Worker }
649*35238bceSAndroid Build Coastguard Worker 
650*35238bceSAndroid Build Coastguard Worker // if alphaMode is true, do PUNCHTHROUGH and store alpha to alphaDst; otherwise do ordinary ETC2 RGB8.
decompressETC2Block(uint8_t dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8],uint64_t src,uint8_t alphaDst[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8],bool alphaMode)651*35238bceSAndroid Build Coastguard Worker void decompressETC2Block(uint8_t dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8], uint64_t src,
652*35238bceSAndroid Build Coastguard Worker                          uint8_t alphaDst[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8], bool alphaMode)
653*35238bceSAndroid Build Coastguard Worker {
654*35238bceSAndroid Build Coastguard Worker     enum Etc2Mode
655*35238bceSAndroid Build Coastguard Worker     {
656*35238bceSAndroid Build Coastguard Worker         MODE_INDIVIDUAL = 0,
657*35238bceSAndroid Build Coastguard Worker         MODE_DIFFERENTIAL,
658*35238bceSAndroid Build Coastguard Worker         MODE_T,
659*35238bceSAndroid Build Coastguard Worker         MODE_H,
660*35238bceSAndroid Build Coastguard Worker         MODE_PLANAR,
661*35238bceSAndroid Build Coastguard Worker 
662*35238bceSAndroid Build Coastguard Worker         MODE_LAST
663*35238bceSAndroid Build Coastguard Worker     };
664*35238bceSAndroid Build Coastguard Worker 
665*35238bceSAndroid Build Coastguard Worker     const int diffOpaqueBit = (int)getBit(src, 33);
666*35238bceSAndroid Build Coastguard Worker     const int8_t selBR      = (int8_t)getBits(src, 59, 63); // 5 bits.
667*35238bceSAndroid Build Coastguard Worker     const int8_t selBG      = (int8_t)getBits(src, 51, 55);
668*35238bceSAndroid Build Coastguard Worker     const int8_t selBB      = (int8_t)getBits(src, 43, 47);
669*35238bceSAndroid Build Coastguard Worker     const int8_t selDR      = extendSigned3To8((uint8_t)getBits(src, 56, 58)); // 3 bits.
670*35238bceSAndroid Build Coastguard Worker     const int8_t selDG      = extendSigned3To8((uint8_t)getBits(src, 48, 50));
671*35238bceSAndroid Build Coastguard Worker     const int8_t selDB      = extendSigned3To8((uint8_t)getBits(src, 40, 42));
672*35238bceSAndroid Build Coastguard Worker     Etc2Mode mode;
673*35238bceSAndroid Build Coastguard Worker 
674*35238bceSAndroid Build Coastguard Worker     if (!alphaMode && diffOpaqueBit == 0)
675*35238bceSAndroid Build Coastguard Worker         mode = MODE_INDIVIDUAL;
676*35238bceSAndroid Build Coastguard Worker     else if (!de::inRange(selBR + selDR, 0, 31))
677*35238bceSAndroid Build Coastguard Worker         mode = MODE_T;
678*35238bceSAndroid Build Coastguard Worker     else if (!de::inRange(selBG + selDG, 0, 31))
679*35238bceSAndroid Build Coastguard Worker         mode = MODE_H;
680*35238bceSAndroid Build Coastguard Worker     else if (!de::inRange(selBB + selDB, 0, 31))
681*35238bceSAndroid Build Coastguard Worker         mode = MODE_PLANAR;
682*35238bceSAndroid Build Coastguard Worker     else
683*35238bceSAndroid Build Coastguard Worker         mode = MODE_DIFFERENTIAL;
684*35238bceSAndroid Build Coastguard Worker 
685*35238bceSAndroid Build Coastguard Worker     if (mode == MODE_INDIVIDUAL || mode == MODE_DIFFERENTIAL)
686*35238bceSAndroid Build Coastguard Worker     {
687*35238bceSAndroid Build Coastguard Worker         // Individual and differential modes have some steps in common, handle them here.
688*35238bceSAndroid Build Coastguard Worker         static const int modifierTable[8][4] = {//      00   01   10    11
689*35238bceSAndroid Build Coastguard Worker                                                 {2, 8, -2, -8},       {5, 17, -5, -17},    {9, 29, -9, -29},
690*35238bceSAndroid Build Coastguard Worker                                                 {13, 42, -13, -42},   {18, 60, -18, -60},  {24, 80, -24, -80},
691*35238bceSAndroid Build Coastguard Worker                                                 {33, 106, -33, -106}, {47, 183, -47, -183}};
692*35238bceSAndroid Build Coastguard Worker 
693*35238bceSAndroid Build Coastguard Worker         const int flipBit       = (int)getBit(src, 32);
694*35238bceSAndroid Build Coastguard Worker         const uint32_t table[2] = {getBits(src, 37, 39), getBits(src, 34, 36)};
695*35238bceSAndroid Build Coastguard Worker         uint8_t baseR[2];
696*35238bceSAndroid Build Coastguard Worker         uint8_t baseG[2];
697*35238bceSAndroid Build Coastguard Worker         uint8_t baseB[2];
698*35238bceSAndroid Build Coastguard Worker 
699*35238bceSAndroid Build Coastguard Worker         if (mode == MODE_INDIVIDUAL)
700*35238bceSAndroid Build Coastguard Worker         {
701*35238bceSAndroid Build Coastguard Worker             // Individual mode, initial values.
702*35238bceSAndroid Build Coastguard Worker             baseR[0] = extend4To8((uint8_t)getBits(src, 60, 63));
703*35238bceSAndroid Build Coastguard Worker             baseR[1] = extend4To8((uint8_t)getBits(src, 56, 59));
704*35238bceSAndroid Build Coastguard Worker             baseG[0] = extend4To8((uint8_t)getBits(src, 52, 55));
705*35238bceSAndroid Build Coastguard Worker             baseG[1] = extend4To8((uint8_t)getBits(src, 48, 51));
706*35238bceSAndroid Build Coastguard Worker             baseB[0] = extend4To8((uint8_t)getBits(src, 44, 47));
707*35238bceSAndroid Build Coastguard Worker             baseB[1] = extend4To8((uint8_t)getBits(src, 40, 43));
708*35238bceSAndroid Build Coastguard Worker         }
709*35238bceSAndroid Build Coastguard Worker         else
710*35238bceSAndroid Build Coastguard Worker         {
711*35238bceSAndroid Build Coastguard Worker             // Differential mode, initial values.
712*35238bceSAndroid Build Coastguard Worker             baseR[0] = extend5To8(selBR);
713*35238bceSAndroid Build Coastguard Worker             baseG[0] = extend5To8(selBG);
714*35238bceSAndroid Build Coastguard Worker             baseB[0] = extend5To8(selBB);
715*35238bceSAndroid Build Coastguard Worker 
716*35238bceSAndroid Build Coastguard Worker             baseR[1] = extend5To8((uint8_t)(selBR + selDR));
717*35238bceSAndroid Build Coastguard Worker             baseG[1] = extend5To8((uint8_t)(selBG + selDG));
718*35238bceSAndroid Build Coastguard Worker             baseB[1] = extend5To8((uint8_t)(selBB + selDB));
719*35238bceSAndroid Build Coastguard Worker         }
720*35238bceSAndroid Build Coastguard Worker 
721*35238bceSAndroid Build Coastguard Worker         // Write final pixels for individual or differential mode.
722*35238bceSAndroid Build Coastguard Worker         for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT * ETC2_BLOCK_WIDTH; pixelNdx++)
723*35238bceSAndroid Build Coastguard Worker         {
724*35238bceSAndroid Build Coastguard Worker             const int x                = pixelNdx / ETC2_BLOCK_HEIGHT;
725*35238bceSAndroid Build Coastguard Worker             const int y                = pixelNdx % ETC2_BLOCK_HEIGHT;
726*35238bceSAndroid Build Coastguard Worker             const int dstOffset        = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
727*35238bceSAndroid Build Coastguard Worker             const int subBlock         = ((flipBit ? y : x) >= 2) ? 1 : 0;
728*35238bceSAndroid Build Coastguard Worker             const uint32_t tableNdx    = table[subBlock];
729*35238bceSAndroid Build Coastguard Worker             const uint32_t modifierNdx = (getBit(src, 16 + pixelNdx) << 1) | getBit(src, pixelNdx);
730*35238bceSAndroid Build Coastguard Worker             const int alphaDstOffset =
731*35238bceSAndroid Build Coastguard Worker                 (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
732*35238bceSAndroid Build Coastguard Worker 
733*35238bceSAndroid Build Coastguard Worker             // If doing PUNCHTHROUGH version (alphaMode), opaque bit may affect colors.
734*35238bceSAndroid Build Coastguard Worker             if (alphaMode && diffOpaqueBit == 0 && modifierNdx == 2)
735*35238bceSAndroid Build Coastguard Worker             {
736*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 0]       = 0;
737*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 1]       = 0;
738*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 2]       = 0;
739*35238bceSAndroid Build Coastguard Worker                 alphaDst[alphaDstOffset] = 0;
740*35238bceSAndroid Build Coastguard Worker             }
741*35238bceSAndroid Build Coastguard Worker             else
742*35238bceSAndroid Build Coastguard Worker             {
743*35238bceSAndroid Build Coastguard Worker                 int modifier;
744*35238bceSAndroid Build Coastguard Worker 
745*35238bceSAndroid Build Coastguard Worker                 // PUNCHTHROUGH version and opaque bit may also affect modifiers.
746*35238bceSAndroid Build Coastguard Worker                 if (alphaMode && diffOpaqueBit == 0 && (modifierNdx == 0 || modifierNdx == 2))
747*35238bceSAndroid Build Coastguard Worker                     modifier = 0;
748*35238bceSAndroid Build Coastguard Worker                 else
749*35238bceSAndroid Build Coastguard Worker                     modifier = modifierTable[tableNdx][modifierNdx];
750*35238bceSAndroid Build Coastguard Worker 
751*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 0] = (uint8_t)deClamp32((int)baseR[subBlock] + modifier, 0, 255);
752*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 1] = (uint8_t)deClamp32((int)baseG[subBlock] + modifier, 0, 255);
753*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 2] = (uint8_t)deClamp32((int)baseB[subBlock] + modifier, 0, 255);
754*35238bceSAndroid Build Coastguard Worker 
755*35238bceSAndroid Build Coastguard Worker                 if (alphaMode)
756*35238bceSAndroid Build Coastguard Worker                     alphaDst[alphaDstOffset] = 255;
757*35238bceSAndroid Build Coastguard Worker             }
758*35238bceSAndroid Build Coastguard Worker         }
759*35238bceSAndroid Build Coastguard Worker     }
760*35238bceSAndroid Build Coastguard Worker     else if (mode == MODE_T || mode == MODE_H)
761*35238bceSAndroid Build Coastguard Worker     {
762*35238bceSAndroid Build Coastguard Worker         // T and H modes have some steps in common, handle them here.
763*35238bceSAndroid Build Coastguard Worker         static const int distTable[8] = {3, 6, 11, 16, 23, 32, 41, 64};
764*35238bceSAndroid Build Coastguard Worker 
765*35238bceSAndroid Build Coastguard Worker         uint8_t paintR[4];
766*35238bceSAndroid Build Coastguard Worker         uint8_t paintG[4];
767*35238bceSAndroid Build Coastguard Worker         uint8_t paintB[4];
768*35238bceSAndroid Build Coastguard Worker 
769*35238bceSAndroid Build Coastguard Worker         if (mode == MODE_T)
770*35238bceSAndroid Build Coastguard Worker         {
771*35238bceSAndroid Build Coastguard Worker             // T mode, calculate paint values.
772*35238bceSAndroid Build Coastguard Worker             const uint8_t R1a      = (uint8_t)getBits(src, 59, 60);
773*35238bceSAndroid Build Coastguard Worker             const uint8_t R1b      = (uint8_t)getBits(src, 56, 57);
774*35238bceSAndroid Build Coastguard Worker             const uint8_t G1       = (uint8_t)getBits(src, 52, 55);
775*35238bceSAndroid Build Coastguard Worker             const uint8_t B1       = (uint8_t)getBits(src, 48, 51);
776*35238bceSAndroid Build Coastguard Worker             const uint8_t R2       = (uint8_t)getBits(src, 44, 47);
777*35238bceSAndroid Build Coastguard Worker             const uint8_t G2       = (uint8_t)getBits(src, 40, 43);
778*35238bceSAndroid Build Coastguard Worker             const uint8_t B2       = (uint8_t)getBits(src, 36, 39);
779*35238bceSAndroid Build Coastguard Worker             const uint32_t distNdx = (getBits(src, 34, 35) << 1) | getBit(src, 32);
780*35238bceSAndroid Build Coastguard Worker             const int dist         = distTable[distNdx];
781*35238bceSAndroid Build Coastguard Worker 
782*35238bceSAndroid Build Coastguard Worker             paintR[0] = extend4To8((uint8_t)((R1a << 2) | R1b));
783*35238bceSAndroid Build Coastguard Worker             paintG[0] = extend4To8(G1);
784*35238bceSAndroid Build Coastguard Worker             paintB[0] = extend4To8(B1);
785*35238bceSAndroid Build Coastguard Worker             paintR[2] = extend4To8(R2);
786*35238bceSAndroid Build Coastguard Worker             paintG[2] = extend4To8(G2);
787*35238bceSAndroid Build Coastguard Worker             paintB[2] = extend4To8(B2);
788*35238bceSAndroid Build Coastguard Worker             paintR[1] = (uint8_t)deClamp32((int)paintR[2] + dist, 0, 255);
789*35238bceSAndroid Build Coastguard Worker             paintG[1] = (uint8_t)deClamp32((int)paintG[2] + dist, 0, 255);
790*35238bceSAndroid Build Coastguard Worker             paintB[1] = (uint8_t)deClamp32((int)paintB[2] + dist, 0, 255);
791*35238bceSAndroid Build Coastguard Worker             paintR[3] = (uint8_t)deClamp32((int)paintR[2] - dist, 0, 255);
792*35238bceSAndroid Build Coastguard Worker             paintG[3] = (uint8_t)deClamp32((int)paintG[2] - dist, 0, 255);
793*35238bceSAndroid Build Coastguard Worker             paintB[3] = (uint8_t)deClamp32((int)paintB[2] - dist, 0, 255);
794*35238bceSAndroid Build Coastguard Worker         }
795*35238bceSAndroid Build Coastguard Worker         else
796*35238bceSAndroid Build Coastguard Worker         {
797*35238bceSAndroid Build Coastguard Worker             // H mode, calculate paint values.
798*35238bceSAndroid Build Coastguard Worker             const uint8_t R1  = (uint8_t)getBits(src, 59, 62);
799*35238bceSAndroid Build Coastguard Worker             const uint8_t G1a = (uint8_t)getBits(src, 56, 58);
800*35238bceSAndroid Build Coastguard Worker             const uint8_t G1b = (uint8_t)getBit(src, 52);
801*35238bceSAndroid Build Coastguard Worker             const uint8_t B1a = (uint8_t)getBit(src, 51);
802*35238bceSAndroid Build Coastguard Worker             const uint8_t B1b = (uint8_t)getBits(src, 47, 49);
803*35238bceSAndroid Build Coastguard Worker             const uint8_t R2  = (uint8_t)getBits(src, 43, 46);
804*35238bceSAndroid Build Coastguard Worker             const uint8_t G2  = (uint8_t)getBits(src, 39, 42);
805*35238bceSAndroid Build Coastguard Worker             const uint8_t B2  = (uint8_t)getBits(src, 35, 38);
806*35238bceSAndroid Build Coastguard Worker             uint8_t baseR[2];
807*35238bceSAndroid Build Coastguard Worker             uint8_t baseG[2];
808*35238bceSAndroid Build Coastguard Worker             uint8_t baseB[2];
809*35238bceSAndroid Build Coastguard Worker             uint32_t baseValue[2];
810*35238bceSAndroid Build Coastguard Worker             uint32_t distNdx;
811*35238bceSAndroid Build Coastguard Worker             int dist;
812*35238bceSAndroid Build Coastguard Worker 
813*35238bceSAndroid Build Coastguard Worker             baseR[0]     = extend4To8(R1);
814*35238bceSAndroid Build Coastguard Worker             baseG[0]     = extend4To8((uint8_t)((G1a << 1) | G1b));
815*35238bceSAndroid Build Coastguard Worker             baseB[0]     = extend4To8((uint8_t)((B1a << 3) | B1b));
816*35238bceSAndroid Build Coastguard Worker             baseR[1]     = extend4To8(R2);
817*35238bceSAndroid Build Coastguard Worker             baseG[1]     = extend4To8(G2);
818*35238bceSAndroid Build Coastguard Worker             baseB[1]     = extend4To8(B2);
819*35238bceSAndroid Build Coastguard Worker             baseValue[0] = (((uint32_t)baseR[0]) << 16) | (((uint32_t)baseG[0]) << 8) | baseB[0];
820*35238bceSAndroid Build Coastguard Worker             baseValue[1] = (((uint32_t)baseR[1]) << 16) | (((uint32_t)baseG[1]) << 8) | baseB[1];
821*35238bceSAndroid Build Coastguard Worker             distNdx      = (getBit(src, 34) << 2) | (getBit(src, 32) << 1) | (uint32_t)(baseValue[0] >= baseValue[1]);
822*35238bceSAndroid Build Coastguard Worker             dist         = distTable[distNdx];
823*35238bceSAndroid Build Coastguard Worker 
824*35238bceSAndroid Build Coastguard Worker             paintR[0] = (uint8_t)deClamp32((int)baseR[0] + dist, 0, 255);
825*35238bceSAndroid Build Coastguard Worker             paintG[0] = (uint8_t)deClamp32((int)baseG[0] + dist, 0, 255);
826*35238bceSAndroid Build Coastguard Worker             paintB[0] = (uint8_t)deClamp32((int)baseB[0] + dist, 0, 255);
827*35238bceSAndroid Build Coastguard Worker             paintR[1] = (uint8_t)deClamp32((int)baseR[0] - dist, 0, 255);
828*35238bceSAndroid Build Coastguard Worker             paintG[1] = (uint8_t)deClamp32((int)baseG[0] - dist, 0, 255);
829*35238bceSAndroid Build Coastguard Worker             paintB[1] = (uint8_t)deClamp32((int)baseB[0] - dist, 0, 255);
830*35238bceSAndroid Build Coastguard Worker             paintR[2] = (uint8_t)deClamp32((int)baseR[1] + dist, 0, 255);
831*35238bceSAndroid Build Coastguard Worker             paintG[2] = (uint8_t)deClamp32((int)baseG[1] + dist, 0, 255);
832*35238bceSAndroid Build Coastguard Worker             paintB[2] = (uint8_t)deClamp32((int)baseB[1] + dist, 0, 255);
833*35238bceSAndroid Build Coastguard Worker             paintR[3] = (uint8_t)deClamp32((int)baseR[1] - dist, 0, 255);
834*35238bceSAndroid Build Coastguard Worker             paintG[3] = (uint8_t)deClamp32((int)baseG[1] - dist, 0, 255);
835*35238bceSAndroid Build Coastguard Worker             paintB[3] = (uint8_t)deClamp32((int)baseB[1] - dist, 0, 255);
836*35238bceSAndroid Build Coastguard Worker         }
837*35238bceSAndroid Build Coastguard Worker 
838*35238bceSAndroid Build Coastguard Worker         // Write final pixels for T or H mode.
839*35238bceSAndroid Build Coastguard Worker         for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT * ETC2_BLOCK_WIDTH; pixelNdx++)
840*35238bceSAndroid Build Coastguard Worker         {
841*35238bceSAndroid Build Coastguard Worker             const int x             = pixelNdx / ETC2_BLOCK_HEIGHT;
842*35238bceSAndroid Build Coastguard Worker             const int y             = pixelNdx % ETC2_BLOCK_HEIGHT;
843*35238bceSAndroid Build Coastguard Worker             const int dstOffset     = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
844*35238bceSAndroid Build Coastguard Worker             const uint32_t paintNdx = (getBit(src, 16 + pixelNdx) << 1) | getBit(src, pixelNdx);
845*35238bceSAndroid Build Coastguard Worker             const int alphaDstOffset =
846*35238bceSAndroid Build Coastguard Worker                 (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
847*35238bceSAndroid Build Coastguard Worker 
848*35238bceSAndroid Build Coastguard Worker             if (alphaMode && diffOpaqueBit == 0 && paintNdx == 2)
849*35238bceSAndroid Build Coastguard Worker             {
850*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 0]       = 0;
851*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 1]       = 0;
852*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 2]       = 0;
853*35238bceSAndroid Build Coastguard Worker                 alphaDst[alphaDstOffset] = 0;
854*35238bceSAndroid Build Coastguard Worker             }
855*35238bceSAndroid Build Coastguard Worker             else
856*35238bceSAndroid Build Coastguard Worker             {
857*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 0] = (uint8_t)deClamp32((int)paintR[paintNdx], 0, 255);
858*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 1] = (uint8_t)deClamp32((int)paintG[paintNdx], 0, 255);
859*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 2] = (uint8_t)deClamp32((int)paintB[paintNdx], 0, 255);
860*35238bceSAndroid Build Coastguard Worker 
861*35238bceSAndroid Build Coastguard Worker                 if (alphaMode)
862*35238bceSAndroid Build Coastguard Worker                     alphaDst[alphaDstOffset] = 255;
863*35238bceSAndroid Build Coastguard Worker             }
864*35238bceSAndroid Build Coastguard Worker         }
865*35238bceSAndroid Build Coastguard Worker     }
866*35238bceSAndroid Build Coastguard Worker     else
867*35238bceSAndroid Build Coastguard Worker     {
868*35238bceSAndroid Build Coastguard Worker         // Planar mode.
869*35238bceSAndroid Build Coastguard Worker         const uint8_t GO1 = (uint8_t)getBit(src, 56);
870*35238bceSAndroid Build Coastguard Worker         const uint8_t GO2 = (uint8_t)getBits(src, 49, 54);
871*35238bceSAndroid Build Coastguard Worker         const uint8_t BO1 = (uint8_t)getBit(src, 48);
872*35238bceSAndroid Build Coastguard Worker         const uint8_t BO2 = (uint8_t)getBits(src, 43, 44);
873*35238bceSAndroid Build Coastguard Worker         const uint8_t BO3 = (uint8_t)getBits(src, 39, 41);
874*35238bceSAndroid Build Coastguard Worker         const uint8_t RH1 = (uint8_t)getBits(src, 34, 38);
875*35238bceSAndroid Build Coastguard Worker         const uint8_t RH2 = (uint8_t)getBit(src, 32);
876*35238bceSAndroid Build Coastguard Worker         const uint8_t RO  = extend6To8((uint8_t)getBits(src, 57, 62));
877*35238bceSAndroid Build Coastguard Worker         const uint8_t GO  = extend7To8((uint8_t)((GO1 << 6) | GO2));
878*35238bceSAndroid Build Coastguard Worker         const uint8_t BO  = extend6To8((uint8_t)((BO1 << 5) | (BO2 << 3) | BO3));
879*35238bceSAndroid Build Coastguard Worker         const uint8_t RH  = extend6To8((uint8_t)((RH1 << 1) | RH2));
880*35238bceSAndroid Build Coastguard Worker         const uint8_t GH  = extend7To8((uint8_t)getBits(src, 25, 31));
881*35238bceSAndroid Build Coastguard Worker         const uint8_t BH  = extend6To8((uint8_t)getBits(src, 19, 24));
882*35238bceSAndroid Build Coastguard Worker         const uint8_t RV  = extend6To8((uint8_t)getBits(src, 13, 18));
883*35238bceSAndroid Build Coastguard Worker         const uint8_t GV  = extend7To8((uint8_t)getBits(src, 6, 12));
884*35238bceSAndroid Build Coastguard Worker         const uint8_t BV  = extend6To8((uint8_t)getBits(src, 0, 5));
885*35238bceSAndroid Build Coastguard Worker 
886*35238bceSAndroid Build Coastguard Worker         // Write final pixels for planar mode.
887*35238bceSAndroid Build Coastguard Worker         for (int y = 0; y < 4; y++)
888*35238bceSAndroid Build Coastguard Worker         {
889*35238bceSAndroid Build Coastguard Worker             for (int x = 0; x < 4; x++)
890*35238bceSAndroid Build Coastguard Worker             {
891*35238bceSAndroid Build Coastguard Worker                 const int dstOffset      = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
892*35238bceSAndroid Build Coastguard Worker                 const int unclampedR     = (x * ((int)RH - (int)RO) + y * ((int)RV - (int)RO) + 4 * (int)RO + 2) >> 2;
893*35238bceSAndroid Build Coastguard Worker                 const int unclampedG     = (x * ((int)GH - (int)GO) + y * ((int)GV - (int)GO) + 4 * (int)GO + 2) >> 2;
894*35238bceSAndroid Build Coastguard Worker                 const int unclampedB     = (x * ((int)BH - (int)BO) + y * ((int)BV - (int)BO) + 4 * (int)BO + 2) >> 2;
895*35238bceSAndroid Build Coastguard Worker                 const int alphaDstOffset = (y * ETC2_BLOCK_WIDTH + x) *
896*35238bceSAndroid Build Coastguard Worker                                            ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
897*35238bceSAndroid Build Coastguard Worker 
898*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 0] = (uint8_t)deClamp32(unclampedR, 0, 255);
899*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 1] = (uint8_t)deClamp32(unclampedG, 0, 255);
900*35238bceSAndroid Build Coastguard Worker                 dst[dstOffset + 2] = (uint8_t)deClamp32(unclampedB, 0, 255);
901*35238bceSAndroid Build Coastguard Worker 
902*35238bceSAndroid Build Coastguard Worker                 if (alphaMode)
903*35238bceSAndroid Build Coastguard Worker                     alphaDst[alphaDstOffset] = 255;
904*35238bceSAndroid Build Coastguard Worker             }
905*35238bceSAndroid Build Coastguard Worker         }
906*35238bceSAndroid Build Coastguard Worker     }
907*35238bceSAndroid Build Coastguard Worker }
908*35238bceSAndroid Build Coastguard Worker 
decompressEAC8Block(uint8_t dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8],uint64_t src)909*35238bceSAndroid Build Coastguard Worker void decompressEAC8Block(uint8_t dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8], uint64_t src)
910*35238bceSAndroid Build Coastguard Worker {
911*35238bceSAndroid Build Coastguard Worker     static const int modifierTable[16][8] = {
912*35238bceSAndroid Build Coastguard Worker         {-3, -6, -9, -15, 2, 5, 8, 14}, {-3, -7, -10, -13, 2, 6, 9, 12}, {-2, -5, -8, -13, 1, 4, 7, 12},
913*35238bceSAndroid Build Coastguard Worker         {-2, -4, -6, -13, 1, 3, 5, 12}, {-3, -6, -8, -12, 2, 5, 7, 11},  {-3, -7, -9, -11, 2, 6, 8, 10},
914*35238bceSAndroid Build Coastguard Worker         {-4, -7, -8, -11, 3, 6, 7, 10}, {-3, -5, -8, -11, 2, 4, 7, 10},  {-2, -6, -8, -10, 1, 5, 7, 9},
915*35238bceSAndroid Build Coastguard Worker         {-2, -5, -8, -10, 1, 4, 7, 9},  {-2, -4, -8, -10, 1, 3, 7, 9},   {-2, -5, -7, -10, 1, 4, 6, 9},
916*35238bceSAndroid Build Coastguard Worker         {-3, -4, -7, -10, 2, 3, 6, 9},  {-1, -2, -3, -10, 0, 1, 2, 9},   {-4, -6, -8, -9, 3, 5, 7, 8},
917*35238bceSAndroid Build Coastguard Worker         {-3, -5, -7, -9, 2, 4, 6, 8}};
918*35238bceSAndroid Build Coastguard Worker 
919*35238bceSAndroid Build Coastguard Worker     const uint8_t baseCodeword = (uint8_t)getBits(src, 56, 63);
920*35238bceSAndroid Build Coastguard Worker     const uint8_t multiplier   = (uint8_t)getBits(src, 52, 55);
921*35238bceSAndroid Build Coastguard Worker     const uint32_t tableNdx    = getBits(src, 48, 51);
922*35238bceSAndroid Build Coastguard Worker 
923*35238bceSAndroid Build Coastguard Worker     for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT * ETC2_BLOCK_WIDTH; pixelNdx++)
924*35238bceSAndroid Build Coastguard Worker     {
925*35238bceSAndroid Build Coastguard Worker         const int x           = pixelNdx / ETC2_BLOCK_HEIGHT;
926*35238bceSAndroid Build Coastguard Worker         const int y           = pixelNdx % ETC2_BLOCK_HEIGHT;
927*35238bceSAndroid Build Coastguard Worker         const int dstOffset   = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8;
928*35238bceSAndroid Build Coastguard Worker         const int pixelBitNdx = 45 - 3 * pixelNdx;
929*35238bceSAndroid Build Coastguard Worker         const uint32_t modifierNdx =
930*35238bceSAndroid Build Coastguard Worker             (getBit(src, pixelBitNdx + 2) << 2) | (getBit(src, pixelBitNdx + 1) << 1) | getBit(src, pixelBitNdx);
931*35238bceSAndroid Build Coastguard Worker         const int modifier = modifierTable[tableNdx][modifierNdx];
932*35238bceSAndroid Build Coastguard Worker 
933*35238bceSAndroid Build Coastguard Worker         dst[dstOffset] = (uint8_t)deClamp32((int)baseCodeword + (int)multiplier * modifier, 0, 255);
934*35238bceSAndroid Build Coastguard Worker     }
935*35238bceSAndroid Build Coastguard Worker }
936*35238bceSAndroid Build Coastguard Worker 
decompressEAC11Block(uint8_t dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_R11],uint64_t src,bool signedMode)937*35238bceSAndroid Build Coastguard Worker void decompressEAC11Block(uint8_t dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_R11], uint64_t src, bool signedMode)
938*35238bceSAndroid Build Coastguard Worker {
939*35238bceSAndroid Build Coastguard Worker     static const int modifierTable[16][8] = {
940*35238bceSAndroid Build Coastguard Worker         {-3, -6, -9, -15, 2, 5, 8, 14}, {-3, -7, -10, -13, 2, 6, 9, 12}, {-2, -5, -8, -13, 1, 4, 7, 12},
941*35238bceSAndroid Build Coastguard Worker         {-2, -4, -6, -13, 1, 3, 5, 12}, {-3, -6, -8, -12, 2, 5, 7, 11},  {-3, -7, -9, -11, 2, 6, 8, 10},
942*35238bceSAndroid Build Coastguard Worker         {-4, -7, -8, -11, 3, 6, 7, 10}, {-3, -5, -8, -11, 2, 4, 7, 10},  {-2, -6, -8, -10, 1, 5, 7, 9},
943*35238bceSAndroid Build Coastguard Worker         {-2, -5, -8, -10, 1, 4, 7, 9},  {-2, -4, -8, -10, 1, 3, 7, 9},   {-2, -5, -7, -10, 1, 4, 6, 9},
944*35238bceSAndroid Build Coastguard Worker         {-3, -4, -7, -10, 2, 3, 6, 9},  {-1, -2, -3, -10, 0, 1, 2, 9},   {-4, -6, -8, -9, 3, 5, 7, 8},
945*35238bceSAndroid Build Coastguard Worker         {-3, -5, -7, -9, 2, 4, 6, 8}};
946*35238bceSAndroid Build Coastguard Worker 
947*35238bceSAndroid Build Coastguard Worker     const int32_t multiplier = (int32_t)getBits(src, 52, 55);
948*35238bceSAndroid Build Coastguard Worker     const int32_t tableNdx   = (int32_t)getBits(src, 48, 51);
949*35238bceSAndroid Build Coastguard Worker     int32_t baseCodeword     = (int32_t)getBits(src, 56, 63);
950*35238bceSAndroid Build Coastguard Worker 
951*35238bceSAndroid Build Coastguard Worker     if (signedMode)
952*35238bceSAndroid Build Coastguard Worker     {
953*35238bceSAndroid Build Coastguard Worker         if (baseCodeword > 127)
954*35238bceSAndroid Build Coastguard Worker             baseCodeword -= 256;
955*35238bceSAndroid Build Coastguard Worker         if (baseCodeword == -128)
956*35238bceSAndroid Build Coastguard Worker             baseCodeword = -127;
957*35238bceSAndroid Build Coastguard Worker     }
958*35238bceSAndroid Build Coastguard Worker 
959*35238bceSAndroid Build Coastguard Worker     for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT * ETC2_BLOCK_WIDTH; pixelNdx++)
960*35238bceSAndroid Build Coastguard Worker     {
961*35238bceSAndroid Build Coastguard Worker         const int x           = pixelNdx / ETC2_BLOCK_HEIGHT;
962*35238bceSAndroid Build Coastguard Worker         const int y           = pixelNdx % ETC2_BLOCK_HEIGHT;
963*35238bceSAndroid Build Coastguard Worker         const int dstOffset   = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_R11;
964*35238bceSAndroid Build Coastguard Worker         const int pixelBitNdx = 45 - 3 * pixelNdx;
965*35238bceSAndroid Build Coastguard Worker         const uint32_t modifierNdx =
966*35238bceSAndroid Build Coastguard Worker             (getBit(src, pixelBitNdx + 2) << 2) | (getBit(src, pixelBitNdx + 1) << 1) | getBit(src, pixelBitNdx);
967*35238bceSAndroid Build Coastguard Worker         const int modifier = modifierTable[tableNdx][modifierNdx];
968*35238bceSAndroid Build Coastguard Worker 
969*35238bceSAndroid Build Coastguard Worker         if (signedMode)
970*35238bceSAndroid Build Coastguard Worker         {
971*35238bceSAndroid Build Coastguard Worker             int16_t value;
972*35238bceSAndroid Build Coastguard Worker 
973*35238bceSAndroid Build Coastguard Worker             if (multiplier != 0)
974*35238bceSAndroid Build Coastguard Worker                 value = (int16_t)deClamp32(baseCodeword * 8 + multiplier * modifier * 8, -1023, 1023);
975*35238bceSAndroid Build Coastguard Worker             else
976*35238bceSAndroid Build Coastguard Worker                 value = (int16_t)deClamp32(baseCodeword * 8 + modifier, -1023, 1023);
977*35238bceSAndroid Build Coastguard Worker 
978*35238bceSAndroid Build Coastguard Worker             *((int16_t *)(dst + dstOffset)) = value;
979*35238bceSAndroid Build Coastguard Worker         }
980*35238bceSAndroid Build Coastguard Worker         else
981*35238bceSAndroid Build Coastguard Worker         {
982*35238bceSAndroid Build Coastguard Worker             uint16_t value;
983*35238bceSAndroid Build Coastguard Worker 
984*35238bceSAndroid Build Coastguard Worker             if (multiplier != 0)
985*35238bceSAndroid Build Coastguard Worker                 value = (uint16_t)deClamp32(baseCodeword * 8 + 4 + multiplier * modifier * 8, 0, 2047);
986*35238bceSAndroid Build Coastguard Worker             else
987*35238bceSAndroid Build Coastguard Worker                 value = (uint16_t)deClamp32(baseCodeword * 8 + 4 + modifier, 0, 2047);
988*35238bceSAndroid Build Coastguard Worker 
989*35238bceSAndroid Build Coastguard Worker             *((uint16_t *)(dst + dstOffset)) = value;
990*35238bceSAndroid Build Coastguard Worker         }
991*35238bceSAndroid Build Coastguard Worker     }
992*35238bceSAndroid Build Coastguard Worker }
993*35238bceSAndroid Build Coastguard Worker 
994*35238bceSAndroid Build Coastguard Worker } // namespace EtcDecompressInternal
995*35238bceSAndroid Build Coastguard Worker 
decompressETC1(const PixelBufferAccess & dst,const uint8_t * src)996*35238bceSAndroid Build Coastguard Worker void decompressETC1(const PixelBufferAccess &dst, const uint8_t *src)
997*35238bceSAndroid Build Coastguard Worker {
998*35238bceSAndroid Build Coastguard Worker     using namespace EtcDecompressInternal;
999*35238bceSAndroid Build Coastguard Worker 
1000*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr          = (uint8_t *)dst.getDataPtr();
1001*35238bceSAndroid Build Coastguard Worker     const uint64_t compressedBlock = get64BitBlock(src, 0);
1002*35238bceSAndroid Build Coastguard Worker 
1003*35238bceSAndroid Build Coastguard Worker     decompressETC1Block(dstPtr, compressedBlock);
1004*35238bceSAndroid Build Coastguard Worker }
1005*35238bceSAndroid Build Coastguard Worker 
decompressETC2(const PixelBufferAccess & dst,const uint8_t * src)1006*35238bceSAndroid Build Coastguard Worker void decompressETC2(const PixelBufferAccess &dst, const uint8_t *src)
1007*35238bceSAndroid Build Coastguard Worker {
1008*35238bceSAndroid Build Coastguard Worker     using namespace EtcDecompressInternal;
1009*35238bceSAndroid Build Coastguard Worker 
1010*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr          = (uint8_t *)dst.getDataPtr();
1011*35238bceSAndroid Build Coastguard Worker     const uint64_t compressedBlock = get64BitBlock(src, 0);
1012*35238bceSAndroid Build Coastguard Worker 
1013*35238bceSAndroid Build Coastguard Worker     decompressETC2Block(dstPtr, compressedBlock, NULL, false);
1014*35238bceSAndroid Build Coastguard Worker }
1015*35238bceSAndroid Build Coastguard Worker 
decompressETC2_EAC_RGBA8(const PixelBufferAccess & dst,const uint8_t * src)1016*35238bceSAndroid Build Coastguard Worker void decompressETC2_EAC_RGBA8(const PixelBufferAccess &dst, const uint8_t *src)
1017*35238bceSAndroid Build Coastguard Worker {
1018*35238bceSAndroid Build Coastguard Worker     using namespace EtcDecompressInternal;
1019*35238bceSAndroid Build Coastguard Worker 
1020*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr  = (uint8_t *)dst.getDataPtr();
1021*35238bceSAndroid Build Coastguard Worker     const int dstRowPitch  = dst.getRowPitch();
1022*35238bceSAndroid Build Coastguard Worker     const int dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8;
1023*35238bceSAndroid Build Coastguard Worker 
1024*35238bceSAndroid Build Coastguard Worker     const uint64_t compressedBlockAlpha = get128BitBlockStart(src, 0);
1025*35238bceSAndroid Build Coastguard Worker     const uint64_t compressedBlockRGB   = get128BitBlockEnd(src, 0);
1026*35238bceSAndroid Build Coastguard Worker     uint8_t uncompressedBlockAlpha[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8];
1027*35238bceSAndroid Build Coastguard Worker     uint8_t uncompressedBlockRGB[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8];
1028*35238bceSAndroid Build Coastguard Worker 
1029*35238bceSAndroid Build Coastguard Worker     // Decompress.
1030*35238bceSAndroid Build Coastguard Worker     decompressETC2Block(uncompressedBlockRGB, compressedBlockRGB, NULL, false);
1031*35238bceSAndroid Build Coastguard Worker     decompressEAC8Block(uncompressedBlockAlpha, compressedBlockAlpha);
1032*35238bceSAndroid Build Coastguard Worker 
1033*35238bceSAndroid Build Coastguard Worker     // Write to dst.
1034*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < (int)ETC2_BLOCK_HEIGHT; y++)
1035*35238bceSAndroid Build Coastguard Worker     {
1036*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < (int)ETC2_BLOCK_WIDTH; x++)
1037*35238bceSAndroid Build Coastguard Worker         {
1038*35238bceSAndroid Build Coastguard Worker             const uint8_t *const srcPixelRGB =
1039*35238bceSAndroid Build Coastguard Worker                 &uncompressedBlockRGB[(y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8];
1040*35238bceSAndroid Build Coastguard Worker             const uint8_t *const srcPixelAlpha =
1041*35238bceSAndroid Build Coastguard Worker                 &uncompressedBlockAlpha[(y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8];
1042*35238bceSAndroid Build Coastguard Worker             uint8_t *const dstPixel = dstPtr + y * dstRowPitch + x * dstPixelSize;
1043*35238bceSAndroid Build Coastguard Worker 
1044*35238bceSAndroid Build Coastguard Worker             DE_STATIC_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 == 4);
1045*35238bceSAndroid Build Coastguard Worker             dstPixel[0] = srcPixelRGB[0];
1046*35238bceSAndroid Build Coastguard Worker             dstPixel[1] = srcPixelRGB[1];
1047*35238bceSAndroid Build Coastguard Worker             dstPixel[2] = srcPixelRGB[2];
1048*35238bceSAndroid Build Coastguard Worker             dstPixel[3] = srcPixelAlpha[0];
1049*35238bceSAndroid Build Coastguard Worker         }
1050*35238bceSAndroid Build Coastguard Worker     }
1051*35238bceSAndroid Build Coastguard Worker }
1052*35238bceSAndroid Build Coastguard Worker 
decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1(const PixelBufferAccess & dst,const uint8_t * src)1053*35238bceSAndroid Build Coastguard Worker void decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1(const PixelBufferAccess &dst, const uint8_t *src)
1054*35238bceSAndroid Build Coastguard Worker {
1055*35238bceSAndroid Build Coastguard Worker     using namespace EtcDecompressInternal;
1056*35238bceSAndroid Build Coastguard Worker 
1057*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr  = (uint8_t *)dst.getDataPtr();
1058*35238bceSAndroid Build Coastguard Worker     const int dstRowPitch  = dst.getRowPitch();
1059*35238bceSAndroid Build Coastguard Worker     const int dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8;
1060*35238bceSAndroid Build Coastguard Worker 
1061*35238bceSAndroid Build Coastguard Worker     const uint64_t compressedBlockRGBA = get64BitBlock(src, 0);
1062*35238bceSAndroid Build Coastguard Worker     uint8_t uncompressedBlockRGB[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8];
1063*35238bceSAndroid Build Coastguard Worker     uint8_t uncompressedBlockAlpha[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8];
1064*35238bceSAndroid Build Coastguard Worker 
1065*35238bceSAndroid Build Coastguard Worker     // Decompress.
1066*35238bceSAndroid Build Coastguard Worker     decompressETC2Block(uncompressedBlockRGB, compressedBlockRGBA, uncompressedBlockAlpha, true);
1067*35238bceSAndroid Build Coastguard Worker 
1068*35238bceSAndroid Build Coastguard Worker     // Write to dst.
1069*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < (int)ETC2_BLOCK_HEIGHT; y++)
1070*35238bceSAndroid Build Coastguard Worker     {
1071*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < (int)ETC2_BLOCK_WIDTH; x++)
1072*35238bceSAndroid Build Coastguard Worker         {
1073*35238bceSAndroid Build Coastguard Worker             const uint8_t *const srcPixel =
1074*35238bceSAndroid Build Coastguard Worker                 &uncompressedBlockRGB[(y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8];
1075*35238bceSAndroid Build Coastguard Worker             const uint8_t *const srcPixelAlpha =
1076*35238bceSAndroid Build Coastguard Worker                 &uncompressedBlockAlpha[(y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8];
1077*35238bceSAndroid Build Coastguard Worker             uint8_t *const dstPixel = dstPtr + y * dstRowPitch + x * dstPixelSize;
1078*35238bceSAndroid Build Coastguard Worker 
1079*35238bceSAndroid Build Coastguard Worker             DE_STATIC_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 == 4);
1080*35238bceSAndroid Build Coastguard Worker             dstPixel[0] = srcPixel[0];
1081*35238bceSAndroid Build Coastguard Worker             dstPixel[1] = srcPixel[1];
1082*35238bceSAndroid Build Coastguard Worker             dstPixel[2] = srcPixel[2];
1083*35238bceSAndroid Build Coastguard Worker             dstPixel[3] = srcPixelAlpha[0];
1084*35238bceSAndroid Build Coastguard Worker         }
1085*35238bceSAndroid Build Coastguard Worker     }
1086*35238bceSAndroid Build Coastguard Worker }
1087*35238bceSAndroid Build Coastguard Worker 
decompressEAC_R11(const PixelBufferAccess & dst,const uint8_t * src,bool signedMode)1088*35238bceSAndroid Build Coastguard Worker void decompressEAC_R11(const PixelBufferAccess &dst, const uint8_t *src, bool signedMode)
1089*35238bceSAndroid Build Coastguard Worker {
1090*35238bceSAndroid Build Coastguard Worker     using namespace EtcDecompressInternal;
1091*35238bceSAndroid Build Coastguard Worker 
1092*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr  = (uint8_t *)dst.getDataPtr();
1093*35238bceSAndroid Build Coastguard Worker     const int dstRowPitch  = dst.getRowPitch();
1094*35238bceSAndroid Build Coastguard Worker     const int dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_R11;
1095*35238bceSAndroid Build Coastguard Worker 
1096*35238bceSAndroid Build Coastguard Worker     const uint64_t compressedBlock = get64BitBlock(src, 0);
1097*35238bceSAndroid Build Coastguard Worker     uint8_t uncompressedBlock[ETC2_UNCOMPRESSED_BLOCK_SIZE_R11];
1098*35238bceSAndroid Build Coastguard Worker 
1099*35238bceSAndroid Build Coastguard Worker     // Decompress.
1100*35238bceSAndroid Build Coastguard Worker     decompressEAC11Block(uncompressedBlock, compressedBlock, signedMode);
1101*35238bceSAndroid Build Coastguard Worker 
1102*35238bceSAndroid Build Coastguard Worker     // Write to dst.
1103*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < (int)ETC2_BLOCK_HEIGHT; y++)
1104*35238bceSAndroid Build Coastguard Worker     {
1105*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < (int)ETC2_BLOCK_WIDTH; x++)
1106*35238bceSAndroid Build Coastguard Worker         {
1107*35238bceSAndroid Build Coastguard Worker             DE_STATIC_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_R11 == 2);
1108*35238bceSAndroid Build Coastguard Worker 
1109*35238bceSAndroid Build Coastguard Worker             if (signedMode)
1110*35238bceSAndroid Build Coastguard Worker             {
1111*35238bceSAndroid Build Coastguard Worker                 const int16_t *const srcPixel =
1112*35238bceSAndroid Build Coastguard Worker                     (int16_t *)&uncompressedBlock[(y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1113*35238bceSAndroid Build Coastguard Worker                 int16_t *const dstPixel = (int16_t *)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1114*35238bceSAndroid Build Coastguard Worker 
1115*35238bceSAndroid Build Coastguard Worker                 dstPixel[0] = extend11To16WithSign(srcPixel[0]);
1116*35238bceSAndroid Build Coastguard Worker             }
1117*35238bceSAndroid Build Coastguard Worker             else
1118*35238bceSAndroid Build Coastguard Worker             {
1119*35238bceSAndroid Build Coastguard Worker                 const uint16_t *const srcPixel =
1120*35238bceSAndroid Build Coastguard Worker                     (uint16_t *)&uncompressedBlock[(y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1121*35238bceSAndroid Build Coastguard Worker                 uint16_t *const dstPixel = (uint16_t *)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1122*35238bceSAndroid Build Coastguard Worker 
1123*35238bceSAndroid Build Coastguard Worker                 dstPixel[0] = extend11To16(srcPixel[0]);
1124*35238bceSAndroid Build Coastguard Worker             }
1125*35238bceSAndroid Build Coastguard Worker         }
1126*35238bceSAndroid Build Coastguard Worker     }
1127*35238bceSAndroid Build Coastguard Worker }
1128*35238bceSAndroid Build Coastguard Worker 
decompressEAC_RG11(const PixelBufferAccess & dst,const uint8_t * src,bool signedMode)1129*35238bceSAndroid Build Coastguard Worker void decompressEAC_RG11(const PixelBufferAccess &dst, const uint8_t *src, bool signedMode)
1130*35238bceSAndroid Build Coastguard Worker {
1131*35238bceSAndroid Build Coastguard Worker     using namespace EtcDecompressInternal;
1132*35238bceSAndroid Build Coastguard Worker 
1133*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr  = (uint8_t *)dst.getDataPtr();
1134*35238bceSAndroid Build Coastguard Worker     const int dstRowPitch  = dst.getRowPitch();
1135*35238bceSAndroid Build Coastguard Worker     const int dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11;
1136*35238bceSAndroid Build Coastguard Worker 
1137*35238bceSAndroid Build Coastguard Worker     const uint64_t compressedBlockR = get128BitBlockStart(src, 0);
1138*35238bceSAndroid Build Coastguard Worker     const uint64_t compressedBlockG = get128BitBlockEnd(src, 0);
1139*35238bceSAndroid Build Coastguard Worker     uint8_t uncompressedBlockR[ETC2_UNCOMPRESSED_BLOCK_SIZE_R11];
1140*35238bceSAndroid Build Coastguard Worker     uint8_t uncompressedBlockG[ETC2_UNCOMPRESSED_BLOCK_SIZE_R11];
1141*35238bceSAndroid Build Coastguard Worker 
1142*35238bceSAndroid Build Coastguard Worker     // Decompress.
1143*35238bceSAndroid Build Coastguard Worker     decompressEAC11Block(uncompressedBlockR, compressedBlockR, signedMode);
1144*35238bceSAndroid Build Coastguard Worker     decompressEAC11Block(uncompressedBlockG, compressedBlockG, signedMode);
1145*35238bceSAndroid Build Coastguard Worker 
1146*35238bceSAndroid Build Coastguard Worker     // Write to dst.
1147*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < (int)ETC2_BLOCK_HEIGHT; y++)
1148*35238bceSAndroid Build Coastguard Worker     {
1149*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < (int)ETC2_BLOCK_WIDTH; x++)
1150*35238bceSAndroid Build Coastguard Worker         {
1151*35238bceSAndroid Build Coastguard Worker             DE_STATIC_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11 == 4);
1152*35238bceSAndroid Build Coastguard Worker 
1153*35238bceSAndroid Build Coastguard Worker             if (signedMode)
1154*35238bceSAndroid Build Coastguard Worker             {
1155*35238bceSAndroid Build Coastguard Worker                 const int16_t *const srcPixelR =
1156*35238bceSAndroid Build Coastguard Worker                     (int16_t *)&uncompressedBlockR[(y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1157*35238bceSAndroid Build Coastguard Worker                 const int16_t *const srcPixelG =
1158*35238bceSAndroid Build Coastguard Worker                     (int16_t *)&uncompressedBlockG[(y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1159*35238bceSAndroid Build Coastguard Worker                 int16_t *const dstPixel = (int16_t *)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1160*35238bceSAndroid Build Coastguard Worker 
1161*35238bceSAndroid Build Coastguard Worker                 dstPixel[0] = extend11To16WithSign(srcPixelR[0]);
1162*35238bceSAndroid Build Coastguard Worker                 dstPixel[1] = extend11To16WithSign(srcPixelG[0]);
1163*35238bceSAndroid Build Coastguard Worker             }
1164*35238bceSAndroid Build Coastguard Worker             else
1165*35238bceSAndroid Build Coastguard Worker             {
1166*35238bceSAndroid Build Coastguard Worker                 const uint16_t *const srcPixelR =
1167*35238bceSAndroid Build Coastguard Worker                     (uint16_t *)&uncompressedBlockR[(y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1168*35238bceSAndroid Build Coastguard Worker                 const uint16_t *const srcPixelG =
1169*35238bceSAndroid Build Coastguard Worker                     (uint16_t *)&uncompressedBlockG[(y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1170*35238bceSAndroid Build Coastguard Worker                 uint16_t *const dstPixel = (uint16_t *)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1171*35238bceSAndroid Build Coastguard Worker 
1172*35238bceSAndroid Build Coastguard Worker                 dstPixel[0] = extend11To16(srcPixelR[0]);
1173*35238bceSAndroid Build Coastguard Worker                 dstPixel[1] = extend11To16(srcPixelG[0]);
1174*35238bceSAndroid Build Coastguard Worker             }
1175*35238bceSAndroid Build Coastguard Worker         }
1176*35238bceSAndroid Build Coastguard Worker     }
1177*35238bceSAndroid Build Coastguard Worker }
1178*35238bceSAndroid Build Coastguard Worker 
1179*35238bceSAndroid Build Coastguard Worker namespace BcDecompressInternal
1180*35238bceSAndroid Build Coastguard Worker {
1181*35238bceSAndroid Build Coastguard Worker 
1182*35238bceSAndroid Build Coastguard Worker enum
1183*35238bceSAndroid Build Coastguard Worker {
1184*35238bceSAndroid Build Coastguard Worker     BC_BLOCK_WIDTH  = 4,
1185*35238bceSAndroid Build Coastguard Worker     BC_BLOCK_HEIGHT = 4
1186*35238bceSAndroid Build Coastguard Worker };
1187*35238bceSAndroid Build Coastguard Worker 
1188*35238bceSAndroid Build Coastguard Worker static const uint8_t epBits[14] = {10, 7, 11, 11, 11, 9, 8, 8, 8, 6, 10, 11, 12, 16};
1189*35238bceSAndroid Build Coastguard Worker 
1190*35238bceSAndroid Build Coastguard Worker static const uint8_t partitions2[64][16] = {
1191*35238bceSAndroid Build Coastguard Worker     {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}, {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1},
1192*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1}, {0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1},
1193*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1}, {0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1},
1194*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1},
1195*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1}, {0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
1196*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1},
1197*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
1198*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1},
1199*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1}, {0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
1200*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0}, {0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0},
1201*35238bceSAndroid Build Coastguard Worker     {0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0},
1202*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0}, {0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1},
1203*35238bceSAndroid Build Coastguard Worker     {0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0},
1204*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0},
1205*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0},
1206*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0}, {0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0},
1207*35238bceSAndroid Build Coastguard Worker     {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}, {0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1},
1208*35238bceSAndroid Build Coastguard Worker     {0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0}, {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0},
1209*35238bceSAndroid Build Coastguard Worker     {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0},
1210*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1}, {0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1},
1211*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0}, {0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0},
1212*35238bceSAndroid Build Coastguard Worker     {0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0}, {0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0},
1213*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1},
1214*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1}, {0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0},
1215*35238bceSAndroid Build Coastguard Worker     {0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0},
1216*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0},
1217*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1}, {0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1},
1218*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0}, {0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0},
1219*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1}, {0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1},
1220*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1},
1221*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}, {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0},
1222*35238bceSAndroid Build Coastguard Worker     {0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0}, {0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1}};
1223*35238bceSAndroid Build Coastguard Worker 
1224*35238bceSAndroid Build Coastguard Worker static const uint8_t partitions3[64][16] = {
1225*35238bceSAndroid Build Coastguard Worker     {0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 2}, {0, 0, 0, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1},
1226*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 2, 0, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1}, {0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 1, 1},
1227*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2}, {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 2, 2},
1228*35238bceSAndroid Build Coastguard Worker     {0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1},
1229*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2}, {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2},
1230*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2}, {0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2},
1231*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2}, {0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2},
1232*35238bceSAndroid Build Coastguard Worker     {0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2}, {0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0},
1233*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2}, {0, 1, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0},
1234*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2}, {0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1},
1235*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2}, {0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 2, 1},
1236*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2}, {0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 1, 0, 2, 2, 1, 0},
1237*35238bceSAndroid Build Coastguard Worker     {0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0}, {0, 0, 1, 2, 0, 0, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2},
1238*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1, 0, 1, 1, 0}, {0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1},
1239*35238bceSAndroid Build Coastguard Worker     {0, 0, 2, 2, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 2, 2}, {0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 0, 2, 2, 2, 2, 2},
1240*35238bceSAndroid Build Coastguard Worker     {0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1}, {0, 0, 0, 0, 2, 0, 0, 0, 2, 2, 1, 1, 2, 2, 2, 1},
1241*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 2, 2, 2}, {0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 2, 0, 0, 1, 1},
1242*35238bceSAndroid Build Coastguard Worker     {0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 2, 2, 2}, {0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0},
1243*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0}, {0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0},
1244*35238bceSAndroid Build Coastguard Worker     {0, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 0, 1, 2, 0}, {0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1},
1245*35238bceSAndroid Build Coastguard Worker     {0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1}, {0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2},
1246*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1}, {0, 0, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 2, 2},
1247*35238bceSAndroid Build Coastguard Worker     {0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1}, {0, 2, 2, 0, 1, 2, 2, 1, 0, 2, 2, 0, 1, 2, 2, 1},
1248*35238bceSAndroid Build Coastguard Worker     {0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1}, {0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1},
1249*35238bceSAndroid Build Coastguard Worker     {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2}, {0, 2, 2, 2, 0, 1, 1, 1, 0, 2, 2, 2, 0, 1, 1, 1},
1250*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 2, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 2}, {0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2},
1251*35238bceSAndroid Build Coastguard Worker     {0, 2, 2, 2, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2}, {0, 0, 0, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2},
1252*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2}, {0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2},
1253*35238bceSAndroid Build Coastguard Worker     {0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2}, {0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2},
1254*35238bceSAndroid Build Coastguard Worker     {0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2},
1255*35238bceSAndroid Build Coastguard Worker     {0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1}, {0, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2},
1256*35238bceSAndroid Build Coastguard Worker     {0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, {0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 2, 2, 2, 0}};
1257*35238bceSAndroid Build Coastguard Worker 
1258*35238bceSAndroid Build Coastguard Worker static const uint8_t anchorIndicesSecondSubset2[64] = {15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
1259*35238bceSAndroid Build Coastguard Worker                                                        15, 2,  8,  2,  2,  8,  8,  15, 2,  8,  2,  2,  8,  8,  2,  2,
1260*35238bceSAndroid Build Coastguard Worker                                                        15, 15, 6,  8,  2,  8,  15, 15, 2,  8,  2,  2,  2,  15, 15, 6,
1261*35238bceSAndroid Build Coastguard Worker                                                        6,  2,  6,  8,  15, 15, 2,  2,  15, 15, 15, 15, 15, 2,  2,  15};
1262*35238bceSAndroid Build Coastguard Worker 
1263*35238bceSAndroid Build Coastguard Worker static const uint8_t anchorIndicesSecondSubset3[64] = {
1264*35238bceSAndroid Build Coastguard Worker     3, 3,  15, 15, 8, 3,  15, 15, 8,  8, 6,  6, 6,  5,  3,  3,  3, 3,  8, 15, 3, 3, 6, 10, 5, 8,  8, 6,  8,  5,  15, 15,
1265*35238bceSAndroid Build Coastguard Worker     8, 15, 3,  5,  6, 10, 8,  15, 15, 3, 15, 5, 15, 15, 15, 15, 3, 15, 5, 5,  5, 8, 5, 10, 5, 10, 8, 13, 15, 12, 3,  3};
1266*35238bceSAndroid Build Coastguard Worker 
1267*35238bceSAndroid Build Coastguard Worker static const uint8_t anchorIndicesThirdSubset[64] = {15, 8, 8,  3,  15, 15, 3,  8,  15, 15, 15, 15, 15, 15, 15, 8,
1268*35238bceSAndroid Build Coastguard Worker                                                      15, 8, 15, 3,  15, 8,  15, 8,  3,  15, 6,  10, 15, 15, 10, 8,
1269*35238bceSAndroid Build Coastguard Worker                                                      15, 3, 15, 10, 10, 8,  9,  10, 6,  15, 8,  15, 3,  6,  6,  8,
1270*35238bceSAndroid Build Coastguard Worker                                                      15, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3,  15, 15, 8};
1271*35238bceSAndroid Build Coastguard Worker 
1272*35238bceSAndroid Build Coastguard Worker static const uint16_t weights2[4]  = {0, 21, 43, 64};
1273*35238bceSAndroid Build Coastguard Worker static const uint16_t weights3[8]  = {0, 9, 18, 27, 37, 46, 55, 64};
1274*35238bceSAndroid Build Coastguard Worker static const uint16_t weights4[16] = {0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64};
1275*35238bceSAndroid Build Coastguard Worker 
uint8ToFloat(uint8_t src)1276*35238bceSAndroid Build Coastguard Worker inline float uint8ToFloat(uint8_t src)
1277*35238bceSAndroid Build Coastguard Worker {
1278*35238bceSAndroid Build Coastguard Worker     return ((float)src / 255.0f);
1279*35238bceSAndroid Build Coastguard Worker }
1280*35238bceSAndroid Build Coastguard Worker 
int8ToFloat(int8_t src)1281*35238bceSAndroid Build Coastguard Worker inline float int8ToFloat(int8_t src)
1282*35238bceSAndroid Build Coastguard Worker {
1283*35238bceSAndroid Build Coastguard Worker     return ((float)src / 128.0f);
1284*35238bceSAndroid Build Coastguard Worker }
1285*35238bceSAndroid Build Coastguard Worker 
bgr16torgba32(uint16_t src)1286*35238bceSAndroid Build Coastguard Worker inline uint32_t bgr16torgba32(uint16_t src)
1287*35238bceSAndroid Build Coastguard Worker {
1288*35238bceSAndroid Build Coastguard Worker     const uint32_t src32 = src;
1289*35238bceSAndroid Build Coastguard Worker     const uint8_t b5     = (src32 & 0x1f);
1290*35238bceSAndroid Build Coastguard Worker     const uint8_t g6     = (src32 >> 5) & 0x3f;
1291*35238bceSAndroid Build Coastguard Worker     const uint8_t r5     = (src32 >> 11) & 0x1f;
1292*35238bceSAndroid Build Coastguard Worker     const uint32_t a8    = 0xff;
1293*35238bceSAndroid Build Coastguard Worker     const uint32_t b8    = extend5To8(b5);
1294*35238bceSAndroid Build Coastguard Worker     const uint32_t g8    = extend6To8(g6);
1295*35238bceSAndroid Build Coastguard Worker     const uint32_t r8    = extend5To8(r5);
1296*35238bceSAndroid Build Coastguard Worker 
1297*35238bceSAndroid Build Coastguard Worker     return (r8 | (g8 << 8) | (b8 << 16) | (a8 << 24));
1298*35238bceSAndroid Build Coastguard Worker }
1299*35238bceSAndroid Build Coastguard Worker 
1300*35238bceSAndroid Build Coastguard Worker // Interpolates color = 1/3 * c0 + 2/3 * c1
interpolateColor(uint32_t c0,uint32_t c1)1301*35238bceSAndroid Build Coastguard Worker inline uint32_t interpolateColor(uint32_t c0, uint32_t c1)
1302*35238bceSAndroid Build Coastguard Worker {
1303*35238bceSAndroid Build Coastguard Worker     const uint32_t r0 = c0 & 0xff;
1304*35238bceSAndroid Build Coastguard Worker     const uint32_t g0 = (c0 >> 8) & 0xff;
1305*35238bceSAndroid Build Coastguard Worker     const uint32_t b0 = (c0 >> 16) & 0xff;
1306*35238bceSAndroid Build Coastguard Worker     const uint32_t a0 = (c0 >> 24) & 0xff;
1307*35238bceSAndroid Build Coastguard Worker 
1308*35238bceSAndroid Build Coastguard Worker     const uint32_t r1 = c1 & 0xff;
1309*35238bceSAndroid Build Coastguard Worker     const uint32_t g1 = (c1 >> 8) & 0xff;
1310*35238bceSAndroid Build Coastguard Worker     const uint32_t b1 = (c1 >> 16) & 0xff;
1311*35238bceSAndroid Build Coastguard Worker     const uint32_t a1 = (c1 >> 24) & 0xff;
1312*35238bceSAndroid Build Coastguard Worker 
1313*35238bceSAndroid Build Coastguard Worker     const uint32_t r = (r0 + (r1 << 1)) / 3;
1314*35238bceSAndroid Build Coastguard Worker     const uint32_t g = (g0 + (g1 << 1)) / 3;
1315*35238bceSAndroid Build Coastguard Worker     const uint32_t b = (b0 + (b1 << 1)) / 3;
1316*35238bceSAndroid Build Coastguard Worker     const uint32_t a = (a0 + (a1 << 1)) / 3;
1317*35238bceSAndroid Build Coastguard Worker 
1318*35238bceSAndroid Build Coastguard Worker     return (r | (g << 8) | (b << 16) | (a << 24));
1319*35238bceSAndroid Build Coastguard Worker }
1320*35238bceSAndroid Build Coastguard Worker 
1321*35238bceSAndroid Build Coastguard Worker // Average of two colors
averageColor(uint32_t c0,uint32_t c1)1322*35238bceSAndroid Build Coastguard Worker inline uint32_t averageColor(uint32_t c0, uint32_t c1)
1323*35238bceSAndroid Build Coastguard Worker {
1324*35238bceSAndroid Build Coastguard Worker     const uint32_t r0 = c0 & 0xff;
1325*35238bceSAndroid Build Coastguard Worker     const uint32_t g0 = (c0 >> 8) & 0xff;
1326*35238bceSAndroid Build Coastguard Worker     const uint32_t b0 = (c0 >> 16) & 0xff;
1327*35238bceSAndroid Build Coastguard Worker     const uint32_t a0 = (c0 >> 24) & 0xff;
1328*35238bceSAndroid Build Coastguard Worker 
1329*35238bceSAndroid Build Coastguard Worker     const uint32_t r1 = c1 & 0xff;
1330*35238bceSAndroid Build Coastguard Worker     const uint32_t g1 = (c1 >> 8) & 0xff;
1331*35238bceSAndroid Build Coastguard Worker     const uint32_t b1 = (c1 >> 16) & 0xff;
1332*35238bceSAndroid Build Coastguard Worker     const uint32_t a1 = (c1 >> 24) & 0xff;
1333*35238bceSAndroid Build Coastguard Worker 
1334*35238bceSAndroid Build Coastguard Worker     const uint32_t r = (r0 + r1) >> 1;
1335*35238bceSAndroid Build Coastguard Worker     const uint32_t g = (g0 + g1) >> 1;
1336*35238bceSAndroid Build Coastguard Worker     const uint32_t b = (b0 + b1) >> 1;
1337*35238bceSAndroid Build Coastguard Worker     const uint32_t a = (a0 + a1) >> 1;
1338*35238bceSAndroid Build Coastguard Worker 
1339*35238bceSAndroid Build Coastguard Worker     return (r | (g << 8) | (b << 16) | (a << 24));
1340*35238bceSAndroid Build Coastguard Worker }
1341*35238bceSAndroid Build Coastguard Worker 
extractModeBc6(uint8_t src)1342*35238bceSAndroid Build Coastguard Worker inline int8_t extractModeBc6(uint8_t src)
1343*35238bceSAndroid Build Coastguard Worker {
1344*35238bceSAndroid Build Coastguard Worker     // Catch illegal modes
1345*35238bceSAndroid Build Coastguard Worker     switch (src & 0x1f)
1346*35238bceSAndroid Build Coastguard Worker     {
1347*35238bceSAndroid Build Coastguard Worker     case 0x13:
1348*35238bceSAndroid Build Coastguard Worker     case 0x17:
1349*35238bceSAndroid Build Coastguard Worker     case 0x1b:
1350*35238bceSAndroid Build Coastguard Worker     case 0x1f:
1351*35238bceSAndroid Build Coastguard Worker         return -1;
1352*35238bceSAndroid Build Coastguard Worker     }
1353*35238bceSAndroid Build Coastguard Worker 
1354*35238bceSAndroid Build Coastguard Worker     switch (src & 0x3)
1355*35238bceSAndroid Build Coastguard Worker     {
1356*35238bceSAndroid Build Coastguard Worker     case 0:
1357*35238bceSAndroid Build Coastguard Worker         return 0;
1358*35238bceSAndroid Build Coastguard Worker     case 1:
1359*35238bceSAndroid Build Coastguard Worker         return 1;
1360*35238bceSAndroid Build Coastguard Worker     case 2:
1361*35238bceSAndroid Build Coastguard Worker         return (int8_t)(2 + ((src >> 2) & 0x7));
1362*35238bceSAndroid Build Coastguard Worker     case 3:
1363*35238bceSAndroid Build Coastguard Worker         return (int8_t)(10 + ((src >> 2) & 0x7));
1364*35238bceSAndroid Build Coastguard Worker     }
1365*35238bceSAndroid Build Coastguard Worker 
1366*35238bceSAndroid Build Coastguard Worker     return -1;
1367*35238bceSAndroid Build Coastguard Worker }
1368*35238bceSAndroid Build Coastguard Worker 
extractModeBc7(uint8_t src)1369*35238bceSAndroid Build Coastguard Worker inline int8_t extractModeBc7(uint8_t src)
1370*35238bceSAndroid Build Coastguard Worker {
1371*35238bceSAndroid Build Coastguard Worker     for (int8_t i = 0; i < 8; i++)
1372*35238bceSAndroid Build Coastguard Worker         if (src & (1 << i))
1373*35238bceSAndroid Build Coastguard Worker             return i;
1374*35238bceSAndroid Build Coastguard Worker 
1375*35238bceSAndroid Build Coastguard Worker     return -1;
1376*35238bceSAndroid Build Coastguard Worker }
1377*35238bceSAndroid Build Coastguard Worker 
get64BitBlockLE(const uint8_t * src,int blockNdx)1378*35238bceSAndroid Build Coastguard Worker inline uint64_t get64BitBlockLE(const uint8_t *src, int blockNdx)
1379*35238bceSAndroid Build Coastguard Worker {
1380*35238bceSAndroid Build Coastguard Worker     // Same as get64BitBlock, but little-endian.
1381*35238bceSAndroid Build Coastguard Worker     uint64_t block = 0;
1382*35238bceSAndroid Build Coastguard Worker 
1383*35238bceSAndroid Build Coastguard Worker     for (int i = 0; i < 8; i++)
1384*35238bceSAndroid Build Coastguard Worker         block |= (uint64_t)(src[blockNdx * 8 + i]) << (8ull * i);
1385*35238bceSAndroid Build Coastguard Worker 
1386*35238bceSAndroid Build Coastguard Worker     return block;
1387*35238bceSAndroid Build Coastguard Worker }
1388*35238bceSAndroid Build Coastguard Worker 
getBits128(uint64_t low,uint64_t high,uint32_t first,uint32_t last)1389*35238bceSAndroid Build Coastguard Worker inline uint32_t getBits128(uint64_t low, uint64_t high, uint32_t first, uint32_t last)
1390*35238bceSAndroid Build Coastguard Worker {
1391*35238bceSAndroid Build Coastguard Worker     const uint64_t d[2] = {low, high};
1392*35238bceSAndroid Build Coastguard Worker     const bool reverse  = first > last;
1393*35238bceSAndroid Build Coastguard Worker     uint32_t ret        = 0;
1394*35238bceSAndroid Build Coastguard Worker 
1395*35238bceSAndroid Build Coastguard Worker     if (reverse)
1396*35238bceSAndroid Build Coastguard Worker     {
1397*35238bceSAndroid Build Coastguard Worker         const uint32_t tmp = first;
1398*35238bceSAndroid Build Coastguard Worker         first              = last;
1399*35238bceSAndroid Build Coastguard Worker         last               = tmp;
1400*35238bceSAndroid Build Coastguard Worker     }
1401*35238bceSAndroid Build Coastguard Worker 
1402*35238bceSAndroid Build Coastguard Worker     const int elementFirst = first / 64;
1403*35238bceSAndroid Build Coastguard Worker     const int elementLast  = last / 64;
1404*35238bceSAndroid Build Coastguard Worker 
1405*35238bceSAndroid Build Coastguard Worker     if (elementFirst == elementLast)
1406*35238bceSAndroid Build Coastguard Worker     {
1407*35238bceSAndroid Build Coastguard Worker         // Bits contained in one of the 64bit elements
1408*35238bceSAndroid Build Coastguard Worker         const uint32_t shift = first % 64;
1409*35238bceSAndroid Build Coastguard Worker         const uint32_t len   = last - first + 1;
1410*35238bceSAndroid Build Coastguard Worker         const uint32_t mask  = (1 << len) - 1;
1411*35238bceSAndroid Build Coastguard Worker         ret                  = (uint32_t)((d[elementFirst] >> shift) & mask);
1412*35238bceSAndroid Build Coastguard Worker     }
1413*35238bceSAndroid Build Coastguard Worker     else
1414*35238bceSAndroid Build Coastguard Worker     {
1415*35238bceSAndroid Build Coastguard Worker         // Bits contained in both of the 64bit elements
1416*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(last > 63);
1417*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(first < 64);
1418*35238bceSAndroid Build Coastguard Worker         const uint32_t len0  = 64 - first;
1419*35238bceSAndroid Build Coastguard Worker         const uint32_t mask0 = (1 << len0) - 1;
1420*35238bceSAndroid Build Coastguard Worker         const uint32_t data0 = (uint32_t)(low >> first) & mask0;
1421*35238bceSAndroid Build Coastguard Worker         const uint32_t len1  = last - 63;
1422*35238bceSAndroid Build Coastguard Worker         const uint32_t mask1 = (1 << len1) - 1;
1423*35238bceSAndroid Build Coastguard Worker         const uint32_t data1 = (uint32_t)(high & mask1);
1424*35238bceSAndroid Build Coastguard Worker         ret                  = (uint32_t)((data1 << len0) | data0);
1425*35238bceSAndroid Build Coastguard Worker     }
1426*35238bceSAndroid Build Coastguard Worker 
1427*35238bceSAndroid Build Coastguard Worker     if (reverse)
1428*35238bceSAndroid Build Coastguard Worker     {
1429*35238bceSAndroid Build Coastguard Worker         const uint32_t len  = last - first + 1;
1430*35238bceSAndroid Build Coastguard Worker         const uint32_t orig = ret;
1431*35238bceSAndroid Build Coastguard Worker         ret                 = 0;
1432*35238bceSAndroid Build Coastguard Worker 
1433*35238bceSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < len; i++)
1434*35238bceSAndroid Build Coastguard Worker         {
1435*35238bceSAndroid Build Coastguard Worker             ret |= ((orig >> (len - 1 - i)) & 1) << i;
1436*35238bceSAndroid Build Coastguard Worker         }
1437*35238bceSAndroid Build Coastguard Worker     }
1438*35238bceSAndroid Build Coastguard Worker 
1439*35238bceSAndroid Build Coastguard Worker     return ret;
1440*35238bceSAndroid Build Coastguard Worker }
1441*35238bceSAndroid Build Coastguard Worker 
signExtend(int32_t value,int32_t srcBits,int32_t dstBits)1442*35238bceSAndroid Build Coastguard Worker inline int32_t signExtend(int32_t value, int32_t srcBits, int32_t dstBits)
1443*35238bceSAndroid Build Coastguard Worker {
1444*35238bceSAndroid Build Coastguard Worker     uint32_t sign = value & (1 << (srcBits - 1));
1445*35238bceSAndroid Build Coastguard Worker 
1446*35238bceSAndroid Build Coastguard Worker     if (!sign)
1447*35238bceSAndroid Build Coastguard Worker         return value;
1448*35238bceSAndroid Build Coastguard Worker 
1449*35238bceSAndroid Build Coastguard Worker     int32_t dstMask      = (int32_t)(((uint64_t)1 << dstBits) - 1);
1450*35238bceSAndroid Build Coastguard Worker     int32_t extendedBits = 0xffffffff << srcBits;
1451*35238bceSAndroid Build Coastguard Worker     return (value | extendedBits) & dstMask;
1452*35238bceSAndroid Build Coastguard Worker }
1453*35238bceSAndroid Build Coastguard Worker 
unquantize(int32_t x,int mode,bool hasSign)1454*35238bceSAndroid Build Coastguard Worker inline int32_t unquantize(int32_t x, int mode, bool hasSign)
1455*35238bceSAndroid Build Coastguard Worker {
1456*35238bceSAndroid Build Coastguard Worker     if (hasSign)
1457*35238bceSAndroid Build Coastguard Worker     {
1458*35238bceSAndroid Build Coastguard Worker         bool s = false;
1459*35238bceSAndroid Build Coastguard Worker 
1460*35238bceSAndroid Build Coastguard Worker         if (epBits[mode] >= 16)
1461*35238bceSAndroid Build Coastguard Worker             return x;
1462*35238bceSAndroid Build Coastguard Worker 
1463*35238bceSAndroid Build Coastguard Worker         if (x < 0)
1464*35238bceSAndroid Build Coastguard Worker         {
1465*35238bceSAndroid Build Coastguard Worker             s = true;
1466*35238bceSAndroid Build Coastguard Worker             x = -x;
1467*35238bceSAndroid Build Coastguard Worker         }
1468*35238bceSAndroid Build Coastguard Worker 
1469*35238bceSAndroid Build Coastguard Worker         if (x == 0)
1470*35238bceSAndroid Build Coastguard Worker             x = 0;
1471*35238bceSAndroid Build Coastguard Worker         else if (x >= (((int32_t)1 << (epBits[mode] - 1)) - 1))
1472*35238bceSAndroid Build Coastguard Worker             x = 0x7fff;
1473*35238bceSAndroid Build Coastguard Worker         else
1474*35238bceSAndroid Build Coastguard Worker             x = (((int32_t)x << 15) + 0x4000) >> (epBits[mode] - 1);
1475*35238bceSAndroid Build Coastguard Worker 
1476*35238bceSAndroid Build Coastguard Worker         if (s)
1477*35238bceSAndroid Build Coastguard Worker             x = -x;
1478*35238bceSAndroid Build Coastguard Worker 
1479*35238bceSAndroid Build Coastguard Worker         return x;
1480*35238bceSAndroid Build Coastguard Worker     }
1481*35238bceSAndroid Build Coastguard Worker     else
1482*35238bceSAndroid Build Coastguard Worker     {
1483*35238bceSAndroid Build Coastguard Worker         if (epBits[mode] >= 15)
1484*35238bceSAndroid Build Coastguard Worker             return x;
1485*35238bceSAndroid Build Coastguard Worker         else if (x == 0)
1486*35238bceSAndroid Build Coastguard Worker             return 0;
1487*35238bceSAndroid Build Coastguard Worker         else if (x == (((int32_t)1 << epBits[mode]) - 1))
1488*35238bceSAndroid Build Coastguard Worker             return 0xffff;
1489*35238bceSAndroid Build Coastguard Worker         else
1490*35238bceSAndroid Build Coastguard Worker             return ((((int32_t)x << 15) + 0x4000) >> (epBits[mode] - 1));
1491*35238bceSAndroid Build Coastguard Worker     }
1492*35238bceSAndroid Build Coastguard Worker }
1493*35238bceSAndroid Build Coastguard Worker 
interpolate(int32_t a,int32_t b,uint32_t index,uint32_t indexPrecision)1494*35238bceSAndroid Build Coastguard Worker inline int32_t interpolate(int32_t a, int32_t b, uint32_t index, uint32_t indexPrecision)
1495*35238bceSAndroid Build Coastguard Worker {
1496*35238bceSAndroid Build Coastguard Worker     const uint16_t *weights[] = {weights2, weights3, weights4};
1497*35238bceSAndroid Build Coastguard Worker     const uint16_t *weight    = weights[indexPrecision - 2];
1498*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(indexPrecision >= 2 && indexPrecision <= 4);
1499*35238bceSAndroid Build Coastguard Worker 
1500*35238bceSAndroid Build Coastguard Worker     return (((64 - weight[index]) * a + weight[index] * b + 32) >> 6);
1501*35238bceSAndroid Build Coastguard Worker }
1502*35238bceSAndroid Build Coastguard Worker 
finishUnquantize(int32_t x,bool hasSign)1503*35238bceSAndroid Build Coastguard Worker inline int16_t finishUnquantize(int32_t x, bool hasSign)
1504*35238bceSAndroid Build Coastguard Worker {
1505*35238bceSAndroid Build Coastguard Worker     if (hasSign)
1506*35238bceSAndroid Build Coastguard Worker     {
1507*35238bceSAndroid Build Coastguard Worker         if (x < 0)
1508*35238bceSAndroid Build Coastguard Worker             x = -(((-x) * 31) >> 5);
1509*35238bceSAndroid Build Coastguard Worker         else
1510*35238bceSAndroid Build Coastguard Worker             x = (x * 31) >> 5;
1511*35238bceSAndroid Build Coastguard Worker 
1512*35238bceSAndroid Build Coastguard Worker         if (x < 0)
1513*35238bceSAndroid Build Coastguard Worker             x = (-x) | 0x8000;
1514*35238bceSAndroid Build Coastguard Worker     }
1515*35238bceSAndroid Build Coastguard Worker     else
1516*35238bceSAndroid Build Coastguard Worker     {
1517*35238bceSAndroid Build Coastguard Worker         x = (x * 31) / 64;
1518*35238bceSAndroid Build Coastguard Worker     }
1519*35238bceSAndroid Build Coastguard Worker 
1520*35238bceSAndroid Build Coastguard Worker     return (int16_t)x;
1521*35238bceSAndroid Build Coastguard Worker }
1522*35238bceSAndroid Build Coastguard Worker 
1523*35238bceSAndroid Build Coastguard Worker } // namespace BcDecompressInternal
1524*35238bceSAndroid Build Coastguard Worker 
decompressBc1(const PixelBufferAccess & dst,const uint8_t * src,bool hasAlpha)1525*35238bceSAndroid Build Coastguard Worker void decompressBc1(const PixelBufferAccess &dst, const uint8_t *src, bool hasAlpha)
1526*35238bceSAndroid Build Coastguard Worker {
1527*35238bceSAndroid Build Coastguard Worker     using namespace BcDecompressInternal;
1528*35238bceSAndroid Build Coastguard Worker 
1529*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr         = (uint8_t *)dst.getDataPtr();
1530*35238bceSAndroid Build Coastguard Worker     const uint32_t dstRowPitch    = dst.getRowPitch();
1531*35238bceSAndroid Build Coastguard Worker     const uint32_t dstPixelSize   = 4;
1532*35238bceSAndroid Build Coastguard Worker     const uint16_t color0_16      = ((uint16_t *)src)[0];
1533*35238bceSAndroid Build Coastguard Worker     const uint16_t color1_16      = ((uint16_t *)src)[1];
1534*35238bceSAndroid Build Coastguard Worker     const uint32_t color0         = bgr16torgba32(color0_16);
1535*35238bceSAndroid Build Coastguard Worker     const uint32_t color1         = bgr16torgba32(color1_16);
1536*35238bceSAndroid Build Coastguard Worker     const uint8_t *const indices8 = &src[4];
1537*35238bceSAndroid Build Coastguard Worker 
1538*35238bceSAndroid Build Coastguard Worker     const bool alphaMode = color1_16 > color0_16;
1539*35238bceSAndroid Build Coastguard Worker 
1540*35238bceSAndroid Build Coastguard Worker     const int32_t indices[16] = {
1541*35238bceSAndroid Build Coastguard Worker         (indices8[0] >> 0) & 0x3, (indices8[0] >> 2) & 0x3, (indices8[0] >> 4) & 0x3, (indices8[0] >> 6) & 0x3,
1542*35238bceSAndroid Build Coastguard Worker         (indices8[1] >> 0) & 0x3, (indices8[1] >> 2) & 0x3, (indices8[1] >> 4) & 0x3, (indices8[1] >> 6) & 0x3,
1543*35238bceSAndroid Build Coastguard Worker         (indices8[2] >> 0) & 0x3, (indices8[2] >> 2) & 0x3, (indices8[2] >> 4) & 0x3, (indices8[2] >> 6) & 0x3,
1544*35238bceSAndroid Build Coastguard Worker         (indices8[3] >> 0) & 0x3, (indices8[3] >> 2) & 0x3, (indices8[3] >> 4) & 0x3, (indices8[3] >> 6) & 0x3};
1545*35238bceSAndroid Build Coastguard Worker 
1546*35238bceSAndroid Build Coastguard Worker     const uint32_t colors[4] = {color0, color1,
1547*35238bceSAndroid Build Coastguard Worker                                 alphaMode ? averageColor(color0, color1) : interpolateColor(color1, color0),
1548*35238bceSAndroid Build Coastguard Worker                                 alphaMode ? (hasAlpha ? 0 : 0xff000000) : interpolateColor(color0, color1)};
1549*35238bceSAndroid Build Coastguard Worker 
1550*35238bceSAndroid Build Coastguard Worker     for (uint32_t y = 0; y < (uint32_t)BC_BLOCK_HEIGHT; y++)
1551*35238bceSAndroid Build Coastguard Worker     {
1552*35238bceSAndroid Build Coastguard Worker         for (uint32_t x = 0; x < (uint32_t)BC_BLOCK_WIDTH; x++)
1553*35238bceSAndroid Build Coastguard Worker         {
1554*35238bceSAndroid Build Coastguard Worker             uint32_t *const dstPixel = (uint32_t *)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1555*35238bceSAndroid Build Coastguard Worker             *dstPixel                = colors[indices[y * BC_BLOCK_WIDTH + x]];
1556*35238bceSAndroid Build Coastguard Worker         }
1557*35238bceSAndroid Build Coastguard Worker     }
1558*35238bceSAndroid Build Coastguard Worker }
1559*35238bceSAndroid Build Coastguard Worker 
decompressBc2(const PixelBufferAccess & dst,const uint8_t * src)1560*35238bceSAndroid Build Coastguard Worker void decompressBc2(const PixelBufferAccess &dst, const uint8_t *src)
1561*35238bceSAndroid Build Coastguard Worker {
1562*35238bceSAndroid Build Coastguard Worker     using namespace BcDecompressInternal;
1563*35238bceSAndroid Build Coastguard Worker 
1564*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr         = (uint8_t *)dst.getDataPtr();
1565*35238bceSAndroid Build Coastguard Worker     const uint32_t dstRowPitch    = dst.getRowPitch();
1566*35238bceSAndroid Build Coastguard Worker     const uint32_t dstPixelSize   = 4;
1567*35238bceSAndroid Build Coastguard Worker     const uint16_t color0_16      = ((uint16_t *)src)[4];
1568*35238bceSAndroid Build Coastguard Worker     const uint16_t color1_16      = ((uint16_t *)src)[5];
1569*35238bceSAndroid Build Coastguard Worker     const uint32_t color0         = bgr16torgba32(color0_16);
1570*35238bceSAndroid Build Coastguard Worker     const uint32_t color1         = bgr16torgba32(color1_16);
1571*35238bceSAndroid Build Coastguard Worker     const uint8_t *const indices8 = &src[12];
1572*35238bceSAndroid Build Coastguard Worker     const uint8_t *const alphas8  = src;
1573*35238bceSAndroid Build Coastguard Worker 
1574*35238bceSAndroid Build Coastguard Worker     const int32_t indices[16] = {
1575*35238bceSAndroid Build Coastguard Worker         (indices8[0] >> 0) & 0x3, (indices8[0] >> 2) & 0x3, (indices8[0] >> 4) & 0x3, (indices8[0] >> 6) & 0x3,
1576*35238bceSAndroid Build Coastguard Worker         (indices8[1] >> 0) & 0x3, (indices8[1] >> 2) & 0x3, (indices8[1] >> 4) & 0x3, (indices8[1] >> 6) & 0x3,
1577*35238bceSAndroid Build Coastguard Worker         (indices8[2] >> 0) & 0x3, (indices8[2] >> 2) & 0x3, (indices8[2] >> 4) & 0x3, (indices8[2] >> 6) & 0x3,
1578*35238bceSAndroid Build Coastguard Worker         (indices8[3] >> 0) & 0x3, (indices8[3] >> 2) & 0x3, (indices8[3] >> 4) & 0x3, (indices8[3] >> 6) & 0x3};
1579*35238bceSAndroid Build Coastguard Worker 
1580*35238bceSAndroid Build Coastguard Worker     const int32_t alphas[16] = {
1581*35238bceSAndroid Build Coastguard Worker         extend4To8(((alphas8[0] >> 0) & 0xf)) << 24, extend4To8(((alphas8[0] >> 4) & 0xf)) << 24,
1582*35238bceSAndroid Build Coastguard Worker         extend4To8(((alphas8[1] >> 0) & 0xf)) << 24, extend4To8(((alphas8[1] >> 4) & 0xf)) << 24,
1583*35238bceSAndroid Build Coastguard Worker         extend4To8(((alphas8[2] >> 0) & 0xf)) << 24, extend4To8(((alphas8[2] >> 4) & 0xf)) << 24,
1584*35238bceSAndroid Build Coastguard Worker         extend4To8(((alphas8[3] >> 0) & 0xf)) << 24, extend4To8(((alphas8[3] >> 4) & 0xf)) << 24,
1585*35238bceSAndroid Build Coastguard Worker         extend4To8(((alphas8[4] >> 0) & 0xf)) << 24, extend4To8(((alphas8[4] >> 4) & 0xf)) << 24,
1586*35238bceSAndroid Build Coastguard Worker         extend4To8(((alphas8[5] >> 0) & 0xf)) << 24, extend4To8(((alphas8[5] >> 4) & 0xf)) << 24,
1587*35238bceSAndroid Build Coastguard Worker         extend4To8(((alphas8[6] >> 0) & 0xf)) << 24, extend4To8(((alphas8[6] >> 4) & 0xf)) << 24,
1588*35238bceSAndroid Build Coastguard Worker         extend4To8(((alphas8[7] >> 0) & 0xf)) << 24, extend4To8(((alphas8[7] >> 4) & 0xf)) << 24};
1589*35238bceSAndroid Build Coastguard Worker 
1590*35238bceSAndroid Build Coastguard Worker     const uint32_t colors[4] = {color0, color1, interpolateColor(color1, color0), interpolateColor(color0, color1)};
1591*35238bceSAndroid Build Coastguard Worker 
1592*35238bceSAndroid Build Coastguard Worker     for (uint32_t y = 0; y < (uint32_t)BC_BLOCK_HEIGHT; y++)
1593*35238bceSAndroid Build Coastguard Worker     {
1594*35238bceSAndroid Build Coastguard Worker         for (uint32_t x = 0; x < (uint32_t)BC_BLOCK_WIDTH; x++)
1595*35238bceSAndroid Build Coastguard Worker         {
1596*35238bceSAndroid Build Coastguard Worker             uint32_t *const dstPixel = (uint32_t *)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1597*35238bceSAndroid Build Coastguard Worker             *dstPixel = (colors[indices[y * BC_BLOCK_WIDTH + x]] & 0x00ffffff) | alphas[y * BC_BLOCK_WIDTH + x];
1598*35238bceSAndroid Build Coastguard Worker         }
1599*35238bceSAndroid Build Coastguard Worker     }
1600*35238bceSAndroid Build Coastguard Worker }
1601*35238bceSAndroid Build Coastguard Worker 
decompressBc3(const PixelBufferAccess & dst,const uint8_t * src)1602*35238bceSAndroid Build Coastguard Worker void decompressBc3(const PixelBufferAccess &dst, const uint8_t *src)
1603*35238bceSAndroid Build Coastguard Worker {
1604*35238bceSAndroid Build Coastguard Worker     using namespace BcDecompressInternal;
1605*35238bceSAndroid Build Coastguard Worker 
1606*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr         = (uint8_t *)dst.getDataPtr();
1607*35238bceSAndroid Build Coastguard Worker     const uint32_t dstRowPitch    = dst.getRowPitch();
1608*35238bceSAndroid Build Coastguard Worker     const uint32_t dstPixelSize   = 4;
1609*35238bceSAndroid Build Coastguard Worker     const uint8_t alpha0          = src[0];
1610*35238bceSAndroid Build Coastguard Worker     const uint8_t alpha1          = src[1];
1611*35238bceSAndroid Build Coastguard Worker     const uint16_t color0_16      = ((uint16_t *)src)[4];
1612*35238bceSAndroid Build Coastguard Worker     const uint16_t color1_16      = ((uint16_t *)src)[5];
1613*35238bceSAndroid Build Coastguard Worker     const uint32_t color0         = bgr16torgba32(color0_16);
1614*35238bceSAndroid Build Coastguard Worker     const uint32_t color1         = bgr16torgba32(color1_16);
1615*35238bceSAndroid Build Coastguard Worker     const uint8_t *const indices8 = &src[12];
1616*35238bceSAndroid Build Coastguard Worker     const uint64_t alphaBits      = get64BitBlockLE(src, 0) >> 16;
1617*35238bceSAndroid Build Coastguard Worker     uint32_t alphas[8];
1618*35238bceSAndroid Build Coastguard Worker 
1619*35238bceSAndroid Build Coastguard Worker     const int32_t indices[16] = {
1620*35238bceSAndroid Build Coastguard Worker         (indices8[0] >> 0) & 0x3, (indices8[0] >> 2) & 0x3, (indices8[0] >> 4) & 0x3, (indices8[0] >> 6) & 0x3,
1621*35238bceSAndroid Build Coastguard Worker         (indices8[1] >> 0) & 0x3, (indices8[1] >> 2) & 0x3, (indices8[1] >> 4) & 0x3, (indices8[1] >> 6) & 0x3,
1622*35238bceSAndroid Build Coastguard Worker         (indices8[2] >> 0) & 0x3, (indices8[2] >> 2) & 0x3, (indices8[2] >> 4) & 0x3, (indices8[2] >> 6) & 0x3,
1623*35238bceSAndroid Build Coastguard Worker         (indices8[3] >> 0) & 0x3, (indices8[3] >> 2) & 0x3, (indices8[3] >> 4) & 0x3, (indices8[3] >> 6) & 0x3};
1624*35238bceSAndroid Build Coastguard Worker 
1625*35238bceSAndroid Build Coastguard Worker     const int32_t alphaIndices[16] = {
1626*35238bceSAndroid Build Coastguard Worker         (int32_t)((alphaBits >> 0) & 0x7),  (int32_t)((alphaBits >> 3) & 0x7),  (int32_t)((alphaBits >> 6) & 0x7),
1627*35238bceSAndroid Build Coastguard Worker         (int32_t)((alphaBits >> 9) & 0x7),  (int32_t)((alphaBits >> 12) & 0x7), (int32_t)((alphaBits >> 15) & 0x7),
1628*35238bceSAndroid Build Coastguard Worker         (int32_t)((alphaBits >> 18) & 0x7), (int32_t)((alphaBits >> 21) & 0x7), (int32_t)((alphaBits >> 24) & 0x7),
1629*35238bceSAndroid Build Coastguard Worker         (int32_t)((alphaBits >> 27) & 0x7), (int32_t)((alphaBits >> 30) & 0x7), (int32_t)((alphaBits >> 33) & 0x7),
1630*35238bceSAndroid Build Coastguard Worker         (int32_t)((alphaBits >> 36) & 0x7), (int32_t)((alphaBits >> 39) & 0x7), (int32_t)((alphaBits >> 42) & 0x7),
1631*35238bceSAndroid Build Coastguard Worker         (int32_t)((alphaBits >> 45) & 0x7)};
1632*35238bceSAndroid Build Coastguard Worker 
1633*35238bceSAndroid Build Coastguard Worker     const uint32_t colors[4] = {color0, color1, interpolateColor(color1, color0), interpolateColor(color0, color1)};
1634*35238bceSAndroid Build Coastguard Worker 
1635*35238bceSAndroid Build Coastguard Worker     alphas[0] = alpha0 << 24;
1636*35238bceSAndroid Build Coastguard Worker     alphas[1] = alpha1 << 24;
1637*35238bceSAndroid Build Coastguard Worker 
1638*35238bceSAndroid Build Coastguard Worker     if (alpha0 > alpha1)
1639*35238bceSAndroid Build Coastguard Worker     {
1640*35238bceSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < 6; i++)
1641*35238bceSAndroid Build Coastguard Worker             alphas[i + 2] = (((uint32_t)alpha0 * (6 - i) + (uint32_t)alpha1 * (1 + i)) / 7) << 24;
1642*35238bceSAndroid Build Coastguard Worker     }
1643*35238bceSAndroid Build Coastguard Worker     else
1644*35238bceSAndroid Build Coastguard Worker     {
1645*35238bceSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < 4; i++)
1646*35238bceSAndroid Build Coastguard Worker             alphas[i + 2] = (((uint32_t)alpha0 * (4 - i) + (uint32_t)alpha1 * (1 + i)) / 5) << 24;
1647*35238bceSAndroid Build Coastguard Worker         alphas[6] = 0;
1648*35238bceSAndroid Build Coastguard Worker         alphas[7] = 0xff000000;
1649*35238bceSAndroid Build Coastguard Worker     }
1650*35238bceSAndroid Build Coastguard Worker 
1651*35238bceSAndroid Build Coastguard Worker     for (uint32_t y = 0; y < (uint32_t)BC_BLOCK_HEIGHT; y++)
1652*35238bceSAndroid Build Coastguard Worker     {
1653*35238bceSAndroid Build Coastguard Worker         for (uint32_t x = 0; x < (uint32_t)BC_BLOCK_WIDTH; x++)
1654*35238bceSAndroid Build Coastguard Worker         {
1655*35238bceSAndroid Build Coastguard Worker             uint32_t *const dstPixel = (uint32_t *)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1656*35238bceSAndroid Build Coastguard Worker             *dstPixel =
1657*35238bceSAndroid Build Coastguard Worker                 (colors[indices[y * BC_BLOCK_WIDTH + x]] & 0x00ffffff) | alphas[alphaIndices[y * BC_BLOCK_WIDTH + x]];
1658*35238bceSAndroid Build Coastguard Worker         }
1659*35238bceSAndroid Build Coastguard Worker     }
1660*35238bceSAndroid Build Coastguard Worker }
1661*35238bceSAndroid Build Coastguard Worker 
decompressBc4(const PixelBufferAccess & dst,const uint8_t * src,bool hasSign)1662*35238bceSAndroid Build Coastguard Worker void decompressBc4(const PixelBufferAccess &dst, const uint8_t *src, bool hasSign)
1663*35238bceSAndroid Build Coastguard Worker {
1664*35238bceSAndroid Build Coastguard Worker     using namespace BcDecompressInternal;
1665*35238bceSAndroid Build Coastguard Worker 
1666*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr       = (uint8_t *)dst.getDataPtr();
1667*35238bceSAndroid Build Coastguard Worker     const uint32_t dstRowPitch  = dst.getRowPitch();
1668*35238bceSAndroid Build Coastguard Worker     const uint32_t dstPixelSize = 4;
1669*35238bceSAndroid Build Coastguard Worker     const uint8_t red0          = src[0];
1670*35238bceSAndroid Build Coastguard Worker     const uint8_t red1          = src[1];
1671*35238bceSAndroid Build Coastguard Worker     const int8_t red0s          = ((int8_t *)src)[0];
1672*35238bceSAndroid Build Coastguard Worker     const int8_t red1s          = ((int8_t *)src)[1];
1673*35238bceSAndroid Build Coastguard Worker     const uint64_t indexBits    = get64BitBlockLE(src, 0) >> 16;
1674*35238bceSAndroid Build Coastguard Worker     float reds[8];
1675*35238bceSAndroid Build Coastguard Worker 
1676*35238bceSAndroid Build Coastguard Worker     const int32_t indices[16] = {
1677*35238bceSAndroid Build Coastguard Worker         (int32_t)((indexBits >> 0) & 0x7),  (int32_t)((indexBits >> 3) & 0x7),  (int32_t)((indexBits >> 6) & 0x7),
1678*35238bceSAndroid Build Coastguard Worker         (int32_t)((indexBits >> 9) & 0x7),  (int32_t)((indexBits >> 12) & 0x7), (int32_t)((indexBits >> 15) & 0x7),
1679*35238bceSAndroid Build Coastguard Worker         (int32_t)((indexBits >> 18) & 0x7), (int32_t)((indexBits >> 21) & 0x7), (int32_t)((indexBits >> 24) & 0x7),
1680*35238bceSAndroid Build Coastguard Worker         (int32_t)((indexBits >> 27) & 0x7), (int32_t)((indexBits >> 30) & 0x7), (int32_t)((indexBits >> 33) & 0x7),
1681*35238bceSAndroid Build Coastguard Worker         (int32_t)((indexBits >> 36) & 0x7), (int32_t)((indexBits >> 39) & 0x7), (int32_t)((indexBits >> 42) & 0x7),
1682*35238bceSAndroid Build Coastguard Worker         (int32_t)((indexBits >> 45) & 0x7)};
1683*35238bceSAndroid Build Coastguard Worker 
1684*35238bceSAndroid Build Coastguard Worker     reds[0] = hasSign ? int8ToFloat(red0s) : uint8ToFloat(red0);
1685*35238bceSAndroid Build Coastguard Worker     reds[1] = hasSign ? int8ToFloat(red1s) : uint8ToFloat(red1);
1686*35238bceSAndroid Build Coastguard Worker 
1687*35238bceSAndroid Build Coastguard Worker     if (reds[0] > reds[1])
1688*35238bceSAndroid Build Coastguard Worker     {
1689*35238bceSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < 6; i++)
1690*35238bceSAndroid Build Coastguard Worker             reds[i + 2] = (reds[0] * (6.0f - (float)i) + reds[1] * (1.0f + (float)i)) / 7.0f;
1691*35238bceSAndroid Build Coastguard Worker     }
1692*35238bceSAndroid Build Coastguard Worker     else
1693*35238bceSAndroid Build Coastguard Worker     {
1694*35238bceSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < 4; i++)
1695*35238bceSAndroid Build Coastguard Worker             reds[i + 2] = (reds[0] * (4.0f - (float)i) + reds[1] * (1.0f + (float)i)) / 5.0f;
1696*35238bceSAndroid Build Coastguard Worker         reds[6] = hasSign ? -1.0f : 0.0f;
1697*35238bceSAndroid Build Coastguard Worker         reds[7] = 1.0f;
1698*35238bceSAndroid Build Coastguard Worker     }
1699*35238bceSAndroid Build Coastguard Worker 
1700*35238bceSAndroid Build Coastguard Worker     for (uint32_t y = 0; y < (uint32_t)BC_BLOCK_HEIGHT; y++)
1701*35238bceSAndroid Build Coastguard Worker     {
1702*35238bceSAndroid Build Coastguard Worker         for (uint32_t x = 0; x < (uint32_t)BC_BLOCK_WIDTH; x++)
1703*35238bceSAndroid Build Coastguard Worker         {
1704*35238bceSAndroid Build Coastguard Worker             float *const dstPixel = (float *)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1705*35238bceSAndroid Build Coastguard Worker             *dstPixel             = reds[indices[y * BC_BLOCK_WIDTH + x]];
1706*35238bceSAndroid Build Coastguard Worker         }
1707*35238bceSAndroid Build Coastguard Worker     }
1708*35238bceSAndroid Build Coastguard Worker }
1709*35238bceSAndroid Build Coastguard Worker 
decompressBc5(const PixelBufferAccess & dst,const uint8_t * src,bool hasSign)1710*35238bceSAndroid Build Coastguard Worker void decompressBc5(const PixelBufferAccess &dst, const uint8_t *src, bool hasSign)
1711*35238bceSAndroid Build Coastguard Worker {
1712*35238bceSAndroid Build Coastguard Worker     using namespace BcDecompressInternal;
1713*35238bceSAndroid Build Coastguard Worker 
1714*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr       = (uint8_t *)dst.getDataPtr();
1715*35238bceSAndroid Build Coastguard Worker     const uint32_t dstRowPitch  = dst.getRowPitch();
1716*35238bceSAndroid Build Coastguard Worker     const uint32_t dstPixelSize = 8;
1717*35238bceSAndroid Build Coastguard Worker     float rg[2][8];
1718*35238bceSAndroid Build Coastguard Worker     uint32_t indices[2][16];
1719*35238bceSAndroid Build Coastguard Worker 
1720*35238bceSAndroid Build Coastguard Worker     for (uint32_t c = 0; c < 2; c++)
1721*35238bceSAndroid Build Coastguard Worker     {
1722*35238bceSAndroid Build Coastguard Worker         const uint32_t offset    = c * 8;
1723*35238bceSAndroid Build Coastguard Worker         const uint8_t rg0        = src[offset];
1724*35238bceSAndroid Build Coastguard Worker         const uint8_t rg1        = src[offset + 1];
1725*35238bceSAndroid Build Coastguard Worker         const int8_t rg0s        = ((int8_t *)src)[offset];
1726*35238bceSAndroid Build Coastguard Worker         const int8_t rg1s        = ((int8_t *)src)[offset + 1];
1727*35238bceSAndroid Build Coastguard Worker         const uint64_t indexBits = get64BitBlockLE(src, c) >> 16;
1728*35238bceSAndroid Build Coastguard Worker 
1729*35238bceSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < 16; i++)
1730*35238bceSAndroid Build Coastguard Worker             indices[c][i] = (indexBits >> (i * 3)) & 0x7;
1731*35238bceSAndroid Build Coastguard Worker 
1732*35238bceSAndroid Build Coastguard Worker         rg[c][0] = hasSign ? int8ToFloat(rg0s) : uint8ToFloat(rg0);
1733*35238bceSAndroid Build Coastguard Worker         rg[c][1] = hasSign ? int8ToFloat(rg1s) : uint8ToFloat(rg1);
1734*35238bceSAndroid Build Coastguard Worker 
1735*35238bceSAndroid Build Coastguard Worker         if (rg[c][0] > rg[c][1])
1736*35238bceSAndroid Build Coastguard Worker         {
1737*35238bceSAndroid Build Coastguard Worker             for (uint32_t i = 0; i < 6; i++)
1738*35238bceSAndroid Build Coastguard Worker                 rg[c][i + 2] = (rg[c][0] * (6.0f - (float)i) + rg[c][1] * (1.0f + (float)i)) / 7.0f;
1739*35238bceSAndroid Build Coastguard Worker         }
1740*35238bceSAndroid Build Coastguard Worker         else
1741*35238bceSAndroid Build Coastguard Worker         {
1742*35238bceSAndroid Build Coastguard Worker             for (uint32_t i = 0; i < 4; i++)
1743*35238bceSAndroid Build Coastguard Worker                 rg[c][i + 2] = (rg[c][0] * (4.0f - (float)i) + rg[c][1] * (1.0f + (float)i)) / 5.0f;
1744*35238bceSAndroid Build Coastguard Worker             rg[c][6] = hasSign ? -1.0f : 0.0f;
1745*35238bceSAndroid Build Coastguard Worker             rg[c][7] = 1.0f;
1746*35238bceSAndroid Build Coastguard Worker         }
1747*35238bceSAndroid Build Coastguard Worker     }
1748*35238bceSAndroid Build Coastguard Worker 
1749*35238bceSAndroid Build Coastguard Worker     for (uint32_t y = 0; y < (uint32_t)BC_BLOCK_HEIGHT; y++)
1750*35238bceSAndroid Build Coastguard Worker     {
1751*35238bceSAndroid Build Coastguard Worker         for (uint32_t x = 0; x < (uint32_t)BC_BLOCK_WIDTH; x++)
1752*35238bceSAndroid Build Coastguard Worker         {
1753*35238bceSAndroid Build Coastguard Worker             float *const dstPixel = (float *)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1754*35238bceSAndroid Build Coastguard Worker             for (uint32_t i = 0; i < 2; i++)
1755*35238bceSAndroid Build Coastguard Worker                 dstPixel[i] = rg[i][indices[i][y * BC_BLOCK_WIDTH + x]];
1756*35238bceSAndroid Build Coastguard Worker         }
1757*35238bceSAndroid Build Coastguard Worker     }
1758*35238bceSAndroid Build Coastguard Worker }
1759*35238bceSAndroid Build Coastguard Worker 
decompressBc6H(const PixelBufferAccess & dst,const uint8_t * src,bool hasSign)1760*35238bceSAndroid Build Coastguard Worker void decompressBc6H(const PixelBufferAccess &dst, const uint8_t *src, bool hasSign)
1761*35238bceSAndroid Build Coastguard Worker {
1762*35238bceSAndroid Build Coastguard Worker     using namespace BcDecompressInternal;
1763*35238bceSAndroid Build Coastguard Worker 
1764*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr       = (uint8_t *)dst.getDataPtr();
1765*35238bceSAndroid Build Coastguard Worker     const uint32_t dstRowPitch  = dst.getRowPitch();
1766*35238bceSAndroid Build Coastguard Worker     const uint32_t dstPixelSize = 6;
1767*35238bceSAndroid Build Coastguard Worker 
1768*35238bceSAndroid Build Coastguard Worker     int32_t mode = extractModeBc6(src[0]);
1769*35238bceSAndroid Build Coastguard Worker     IVec4 r(0);
1770*35238bceSAndroid Build Coastguard Worker     IVec4 g(0);
1771*35238bceSAndroid Build Coastguard Worker     IVec4 b(0);
1772*35238bceSAndroid Build Coastguard Worker     uint32_t deltaBitsR           = 0;
1773*35238bceSAndroid Build Coastguard Worker     uint32_t deltaBitsG           = 0;
1774*35238bceSAndroid Build Coastguard Worker     uint32_t deltaBitsB           = 0;
1775*35238bceSAndroid Build Coastguard Worker     const uint64_t low            = ((uint64_t *)src)[0];
1776*35238bceSAndroid Build Coastguard Worker     const uint64_t high           = ((uint64_t *)src)[1];
1777*35238bceSAndroid Build Coastguard Worker     const uint32_t d              = mode < 10 ? getBits128(low, high, 77, 81) : 0;
1778*35238bceSAndroid Build Coastguard Worker     const uint32_t numRegions     = mode > 9 ? 1 : 2;
1779*35238bceSAndroid Build Coastguard Worker     const uint32_t numEndpoints   = numRegions * 2;
1780*35238bceSAndroid Build Coastguard Worker     const bool transformed        = mode != 9 && mode != 10;
1781*35238bceSAndroid Build Coastguard Worker     const uint32_t colorIndexBC   = mode < 10 ? 3 : 4;
1782*35238bceSAndroid Build Coastguard Worker     uint64_t colorIndexData       = high >> (mode < 10 ? 18 : 1);
1783*35238bceSAndroid Build Coastguard Worker     const uint32_t anchorIndex[2] = {0, anchorIndicesSecondSubset2[d]};
1784*35238bceSAndroid Build Coastguard Worker 
1785*35238bceSAndroid Build Coastguard Worker     switch (mode)
1786*35238bceSAndroid Build Coastguard Worker     {
1787*35238bceSAndroid Build Coastguard Worker     case 0:
1788*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 2, 2) << 4;
1789*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 3, 3) << 4;
1790*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 4, 4) << 4;
1791*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 14);
1792*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 24);
1793*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 34);
1794*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 39);
1795*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 40, 40) << 4;
1796*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 41, 44);
1797*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 49);
1798*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 50, 50);
1799*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 51, 54);
1800*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 59);
1801*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 60, 60) << 1;
1802*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 61, 64);
1803*35238bceSAndroid Build Coastguard Worker         r[2] |= getBits128(low, high, 65, 69);
1804*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 70, 70) << 2;
1805*35238bceSAndroid Build Coastguard Worker         r[3] |= getBits128(low, high, 71, 75);
1806*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 76, 76) << 3;
1807*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsG = deltaBitsB = 5;
1808*35238bceSAndroid Build Coastguard Worker         break;
1809*35238bceSAndroid Build Coastguard Worker 
1810*35238bceSAndroid Build Coastguard Worker     case 1:
1811*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 2, 2) << 5;
1812*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 3, 3) << 4;
1813*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 4, 4) << 5;
1814*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 11);
1815*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 12, 12);
1816*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 13, 13) << 1;
1817*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 14, 14) << 4;
1818*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 21);
1819*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 22, 22) << 5;
1820*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 23, 23) << 2;
1821*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 24, 24) << 4;
1822*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 31);
1823*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 32, 32) << 3;
1824*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 33, 33) << 5;
1825*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 34, 34) << 4;
1826*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 40);
1827*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 41, 44);
1828*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 50);
1829*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 51, 54);
1830*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 60);
1831*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 61, 64);
1832*35238bceSAndroid Build Coastguard Worker         r[2] |= getBits128(low, high, 65, 70);
1833*35238bceSAndroid Build Coastguard Worker         r[3] |= getBits128(low, high, 71, 76);
1834*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsG = deltaBitsB = 6;
1835*35238bceSAndroid Build Coastguard Worker         break;
1836*35238bceSAndroid Build Coastguard Worker 
1837*35238bceSAndroid Build Coastguard Worker     case 2:
1838*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 14);
1839*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 24);
1840*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 34);
1841*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 39);
1842*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 40, 40) << 10;
1843*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 41, 44);
1844*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 48);
1845*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 49, 49) << 10;
1846*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 50, 50);
1847*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 51, 54);
1848*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 58);
1849*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 59, 59) << 10;
1850*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 60, 60) << 1;
1851*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 61, 64);
1852*35238bceSAndroid Build Coastguard Worker         r[2] |= getBits128(low, high, 65, 69);
1853*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 70, 70) << 2;
1854*35238bceSAndroid Build Coastguard Worker         r[3] |= getBits128(low, high, 71, 75);
1855*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 76, 76) << 3;
1856*35238bceSAndroid Build Coastguard Worker         deltaBitsR = 5;
1857*35238bceSAndroid Build Coastguard Worker         deltaBitsG = deltaBitsB = 4;
1858*35238bceSAndroid Build Coastguard Worker         break;
1859*35238bceSAndroid Build Coastguard Worker 
1860*35238bceSAndroid Build Coastguard Worker     case 3:
1861*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 14);
1862*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 24);
1863*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 34);
1864*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 38);
1865*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 39, 39) << 10;
1866*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 40, 40) << 4;
1867*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 41, 44);
1868*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 49);
1869*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 50, 50) << 10;
1870*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 51, 54);
1871*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 58);
1872*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 59, 59) << 10;
1873*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 60, 60) << 1;
1874*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 61, 64);
1875*35238bceSAndroid Build Coastguard Worker         r[2] |= getBits128(low, high, 65, 68);
1876*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 69, 69);
1877*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 70, 70) << 2;
1878*35238bceSAndroid Build Coastguard Worker         r[3] |= getBits128(low, high, 71, 74);
1879*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 75, 75) << 4;
1880*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 76, 76) << 3;
1881*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsB = 4;
1882*35238bceSAndroid Build Coastguard Worker         deltaBitsG              = 5;
1883*35238bceSAndroid Build Coastguard Worker         break;
1884*35238bceSAndroid Build Coastguard Worker 
1885*35238bceSAndroid Build Coastguard Worker     case 4:
1886*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 14);
1887*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 24);
1888*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 34);
1889*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 38);
1890*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 39, 39) << 10;
1891*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 40, 40) << 4;
1892*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 41, 44);
1893*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 48);
1894*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 49, 49) << 10;
1895*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 50, 50);
1896*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 51, 54);
1897*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 59);
1898*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 60, 60) << 10;
1899*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 61, 64);
1900*35238bceSAndroid Build Coastguard Worker         r[2] |= getBits128(low, high, 65, 68);
1901*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 69, 69) << 1;
1902*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 70, 70) << 2;
1903*35238bceSAndroid Build Coastguard Worker         r[3] |= getBits128(low, high, 71, 74);
1904*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 75, 75) << 4;
1905*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 76, 76) << 3;
1906*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsG = 4;
1907*35238bceSAndroid Build Coastguard Worker         deltaBitsB              = 5;
1908*35238bceSAndroid Build Coastguard Worker         break;
1909*35238bceSAndroid Build Coastguard Worker 
1910*35238bceSAndroid Build Coastguard Worker     case 5:
1911*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 13);
1912*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 14, 14) << 4;
1913*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 23);
1914*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 24, 24) << 4;
1915*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 33);
1916*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 34, 34) << 4;
1917*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 39);
1918*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 40, 40) << 4;
1919*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 41, 44);
1920*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 49);
1921*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 50, 50);
1922*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 51, 54);
1923*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 59);
1924*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 60, 60) << 1;
1925*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 61, 64);
1926*35238bceSAndroid Build Coastguard Worker         r[2] |= getBits128(low, high, 65, 69);
1927*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 70, 70) << 2;
1928*35238bceSAndroid Build Coastguard Worker         r[3] |= getBits128(low, high, 71, 75);
1929*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 76, 76) << 3;
1930*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsG = deltaBitsB = 5;
1931*35238bceSAndroid Build Coastguard Worker         break;
1932*35238bceSAndroid Build Coastguard Worker 
1933*35238bceSAndroid Build Coastguard Worker     case 6:
1934*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 12);
1935*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 13, 13) << 4;
1936*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 14, 14) << 4;
1937*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 22);
1938*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 23, 23) << 2;
1939*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 24, 24) << 4;
1940*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 32);
1941*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 33, 33) << 3;
1942*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 34, 34) << 4;
1943*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 40);
1944*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 41, 44);
1945*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 49);
1946*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 50, 50);
1947*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 51, 54);
1948*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 59);
1949*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 60, 60) << 1;
1950*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 61, 64);
1951*35238bceSAndroid Build Coastguard Worker         r[2] |= getBits128(low, high, 65, 70);
1952*35238bceSAndroid Build Coastguard Worker         r[3] |= getBits128(low, high, 71, 76);
1953*35238bceSAndroid Build Coastguard Worker         deltaBitsR = 6;
1954*35238bceSAndroid Build Coastguard Worker         deltaBitsG = deltaBitsB = 5;
1955*35238bceSAndroid Build Coastguard Worker         break;
1956*35238bceSAndroid Build Coastguard Worker 
1957*35238bceSAndroid Build Coastguard Worker     case 7:
1958*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 12);
1959*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 13, 13);
1960*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 14, 14) << 4;
1961*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 22);
1962*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 23, 23) << 5;
1963*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 24, 24) << 4;
1964*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 32);
1965*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 33, 33) << 5;
1966*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 34, 34) << 4;
1967*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 39);
1968*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 40, 40) << 4;
1969*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 41, 44);
1970*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 50);
1971*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 51, 54);
1972*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 59);
1973*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 60, 60) << 1;
1974*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 61, 64);
1975*35238bceSAndroid Build Coastguard Worker         r[2] |= getBits128(low, high, 65, 69);
1976*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 70, 70) << 2;
1977*35238bceSAndroid Build Coastguard Worker         r[3] |= getBits128(low, high, 71, 75);
1978*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 76, 76) << 3;
1979*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsB = 5;
1980*35238bceSAndroid Build Coastguard Worker         deltaBitsG              = 6;
1981*35238bceSAndroid Build Coastguard Worker         break;
1982*35238bceSAndroid Build Coastguard Worker 
1983*35238bceSAndroid Build Coastguard Worker     case 8:
1984*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 12);
1985*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 13, 13) << 1;
1986*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 14, 14) << 4;
1987*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 22);
1988*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 23, 23) << 5;
1989*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 24, 24) << 4;
1990*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 32);
1991*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 33, 33) << 5;
1992*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 34, 34) << 4;
1993*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 39);
1994*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 40, 40) << 4;
1995*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 41, 44);
1996*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 49);
1997*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 50, 50);
1998*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 51, 54);
1999*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 60);
2000*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 61, 64);
2001*35238bceSAndroid Build Coastguard Worker         r[2] |= getBits128(low, high, 65, 69);
2002*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 70, 70) << 2;
2003*35238bceSAndroid Build Coastguard Worker         r[3] |= getBits128(low, high, 71, 75);
2004*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 76, 76) << 3;
2005*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsG = 5;
2006*35238bceSAndroid Build Coastguard Worker         deltaBitsB              = 6;
2007*35238bceSAndroid Build Coastguard Worker         break;
2008*35238bceSAndroid Build Coastguard Worker 
2009*35238bceSAndroid Build Coastguard Worker     case 9:
2010*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 10);
2011*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 11, 11) << 4;
2012*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 12, 13);
2013*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 14, 14) << 4;
2014*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 20);
2015*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 21, 21) << 5;
2016*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 22, 22) << 5;
2017*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 23, 23) << 2;
2018*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 24, 24) << 4;
2019*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 30);
2020*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 31, 31) << 5;
2021*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 32, 32) << 3;
2022*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 33, 33) << 5;
2023*35238bceSAndroid Build Coastguard Worker         b[3] |= getBits128(low, high, 34, 34) << 4;
2024*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 40);
2025*35238bceSAndroid Build Coastguard Worker         g[2] |= getBits128(low, high, 41, 44);
2026*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 50);
2027*35238bceSAndroid Build Coastguard Worker         g[3] |= getBits128(low, high, 51, 54);
2028*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 60);
2029*35238bceSAndroid Build Coastguard Worker         b[2] |= getBits128(low, high, 61, 64);
2030*35238bceSAndroid Build Coastguard Worker         r[2] |= getBits128(low, high, 65, 70);
2031*35238bceSAndroid Build Coastguard Worker         r[3] |= getBits128(low, high, 71, 76);
2032*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsG = deltaBitsB = 6;
2033*35238bceSAndroid Build Coastguard Worker         break;
2034*35238bceSAndroid Build Coastguard Worker 
2035*35238bceSAndroid Build Coastguard Worker     case 10:
2036*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 14);
2037*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 24);
2038*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 34);
2039*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 44);
2040*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 54);
2041*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 64);
2042*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsG = deltaBitsB = 10;
2043*35238bceSAndroid Build Coastguard Worker         break;
2044*35238bceSAndroid Build Coastguard Worker 
2045*35238bceSAndroid Build Coastguard Worker     case 11:
2046*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 14);
2047*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 24);
2048*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 34);
2049*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 43);
2050*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 44, 44) << 10;
2051*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 53);
2052*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 54, 54) << 10;
2053*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 63);
2054*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 64, 64) << 10;
2055*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsG = deltaBitsB = 9;
2056*35238bceSAndroid Build Coastguard Worker         break;
2057*35238bceSAndroid Build Coastguard Worker 
2058*35238bceSAndroid Build Coastguard Worker     case 12:
2059*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 14);
2060*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 24);
2061*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 34);
2062*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 42);
2063*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 44, 43) << 10;
2064*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 52);
2065*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 54, 53) << 10;
2066*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 62);
2067*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 64, 63) << 10;
2068*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsG = deltaBitsB = 8;
2069*35238bceSAndroid Build Coastguard Worker         break;
2070*35238bceSAndroid Build Coastguard Worker 
2071*35238bceSAndroid Build Coastguard Worker     case 13:
2072*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 5, 14);
2073*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 15, 24);
2074*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 25, 34);
2075*35238bceSAndroid Build Coastguard Worker         r[1] |= getBits128(low, high, 35, 38);
2076*35238bceSAndroid Build Coastguard Worker         r[0] |= getBits128(low, high, 44, 39) << 10;
2077*35238bceSAndroid Build Coastguard Worker         g[1] |= getBits128(low, high, 45, 48);
2078*35238bceSAndroid Build Coastguard Worker         g[0] |= getBits128(low, high, 54, 49) << 10;
2079*35238bceSAndroid Build Coastguard Worker         b[1] |= getBits128(low, high, 55, 58);
2080*35238bceSAndroid Build Coastguard Worker         b[0] |= getBits128(low, high, 64, 59) << 10;
2081*35238bceSAndroid Build Coastguard Worker         deltaBitsR = deltaBitsG = deltaBitsB = 4;
2082*35238bceSAndroid Build Coastguard Worker         break;
2083*35238bceSAndroid Build Coastguard Worker     }
2084*35238bceSAndroid Build Coastguard Worker 
2085*35238bceSAndroid Build Coastguard Worker     if (hasSign)
2086*35238bceSAndroid Build Coastguard Worker     {
2087*35238bceSAndroid Build Coastguard Worker         r[0] = signExtend(r[0], epBits[mode], 32);
2088*35238bceSAndroid Build Coastguard Worker         g[0] = signExtend(g[0], epBits[mode], 32);
2089*35238bceSAndroid Build Coastguard Worker         b[0] = signExtend(b[0], epBits[mode], 32);
2090*35238bceSAndroid Build Coastguard Worker     }
2091*35238bceSAndroid Build Coastguard Worker 
2092*35238bceSAndroid Build Coastguard Worker     if (transformed)
2093*35238bceSAndroid Build Coastguard Worker     {
2094*35238bceSAndroid Build Coastguard Worker         for (uint32_t i = 1; i < numEndpoints; i++)
2095*35238bceSAndroid Build Coastguard Worker         {
2096*35238bceSAndroid Build Coastguard Worker             r[i] = signExtend(r[i], deltaBitsR, 32);
2097*35238bceSAndroid Build Coastguard Worker             r[i] = (r[0] + r[i]) & (((uint32_t)1 << epBits[mode]) - 1);
2098*35238bceSAndroid Build Coastguard Worker             g[i] = signExtend(g[i], deltaBitsG, 32);
2099*35238bceSAndroid Build Coastguard Worker             g[i] = (g[0] + g[i]) & (((uint32_t)1 << epBits[mode]) - 1);
2100*35238bceSAndroid Build Coastguard Worker             b[i] = signExtend(b[i], deltaBitsB, 32);
2101*35238bceSAndroid Build Coastguard Worker             b[i] = (b[0] + b[i]) & (((uint32_t)1 << epBits[mode]) - 1);
2102*35238bceSAndroid Build Coastguard Worker         }
2103*35238bceSAndroid Build Coastguard Worker     }
2104*35238bceSAndroid Build Coastguard Worker 
2105*35238bceSAndroid Build Coastguard Worker     if (hasSign)
2106*35238bceSAndroid Build Coastguard Worker     {
2107*35238bceSAndroid Build Coastguard Worker         for (uint32_t i = 1; i < 4; i++)
2108*35238bceSAndroid Build Coastguard Worker         {
2109*35238bceSAndroid Build Coastguard Worker             r[i] = signExtend(r[i], epBits[mode], 32);
2110*35238bceSAndroid Build Coastguard Worker             g[i] = signExtend(g[i], epBits[mode], 32);
2111*35238bceSAndroid Build Coastguard Worker             b[i] = signExtend(b[i], epBits[mode], 32);
2112*35238bceSAndroid Build Coastguard Worker         }
2113*35238bceSAndroid Build Coastguard Worker     }
2114*35238bceSAndroid Build Coastguard Worker 
2115*35238bceSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < numEndpoints; i++)
2116*35238bceSAndroid Build Coastguard Worker     {
2117*35238bceSAndroid Build Coastguard Worker         r[i] = unquantize(r[i], mode, hasSign);
2118*35238bceSAndroid Build Coastguard Worker         g[i] = unquantize(g[i], mode, hasSign);
2119*35238bceSAndroid Build Coastguard Worker         b[i] = unquantize(b[i], mode, hasSign);
2120*35238bceSAndroid Build Coastguard Worker     }
2121*35238bceSAndroid Build Coastguard Worker 
2122*35238bceSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < 16; i++)
2123*35238bceSAndroid Build Coastguard Worker     {
2124*35238bceSAndroid Build Coastguard Worker         const uint32_t subsetIndex   = (numRegions == 1 ? 0 : partitions2[d][i]);
2125*35238bceSAndroid Build Coastguard Worker         const uint32_t bits          = (i == anchorIndex[subsetIndex]) ? (colorIndexBC - 1) : colorIndexBC;
2126*35238bceSAndroid Build Coastguard Worker         const uint32_t colorIndex    = (uint32_t)(colorIndexData & ((1 << bits) - 1));
2127*35238bceSAndroid Build Coastguard Worker         const int32_t endpointStartR = r[2 * subsetIndex];
2128*35238bceSAndroid Build Coastguard Worker         const int32_t endpointEndR   = r[2 * subsetIndex + 1];
2129*35238bceSAndroid Build Coastguard Worker         const int32_t endpointStartG = g[2 * subsetIndex];
2130*35238bceSAndroid Build Coastguard Worker         const int32_t endpointEndG   = g[2 * subsetIndex + 1];
2131*35238bceSAndroid Build Coastguard Worker         const int32_t endpointStartB = b[2 * subsetIndex];
2132*35238bceSAndroid Build Coastguard Worker         const int32_t endpointEndB   = b[2 * subsetIndex + 1];
2133*35238bceSAndroid Build Coastguard Worker         const int16_t r16 =
2134*35238bceSAndroid Build Coastguard Worker             finishUnquantize(interpolate(endpointStartR, endpointEndR, colorIndex, colorIndexBC), hasSign);
2135*35238bceSAndroid Build Coastguard Worker         const int16_t g16 =
2136*35238bceSAndroid Build Coastguard Worker             finishUnquantize(interpolate(endpointStartG, endpointEndG, colorIndex, colorIndexBC), hasSign);
2137*35238bceSAndroid Build Coastguard Worker         const int16_t b16 =
2138*35238bceSAndroid Build Coastguard Worker             finishUnquantize(interpolate(endpointStartB, endpointEndB, colorIndex, colorIndexBC), hasSign);
2139*35238bceSAndroid Build Coastguard Worker         const int32_t y         = i / 4;
2140*35238bceSAndroid Build Coastguard Worker         const int32_t x         = i % 4;
2141*35238bceSAndroid Build Coastguard Worker         int16_t *const dstPixel = (int16_t *)(dstPtr + y * dstRowPitch + x * dstPixelSize);
2142*35238bceSAndroid Build Coastguard Worker 
2143*35238bceSAndroid Build Coastguard Worker         if (mode == -1)
2144*35238bceSAndroid Build Coastguard Worker         {
2145*35238bceSAndroid Build Coastguard Worker             dstPixel[0] = 0;
2146*35238bceSAndroid Build Coastguard Worker             dstPixel[1] = 0;
2147*35238bceSAndroid Build Coastguard Worker             dstPixel[2] = 0;
2148*35238bceSAndroid Build Coastguard Worker         }
2149*35238bceSAndroid Build Coastguard Worker         else
2150*35238bceSAndroid Build Coastguard Worker         {
2151*35238bceSAndroid Build Coastguard Worker             dstPixel[0] = r16;
2152*35238bceSAndroid Build Coastguard Worker             dstPixel[1] = g16;
2153*35238bceSAndroid Build Coastguard Worker             dstPixel[2] = b16;
2154*35238bceSAndroid Build Coastguard Worker         }
2155*35238bceSAndroid Build Coastguard Worker 
2156*35238bceSAndroid Build Coastguard Worker         colorIndexData >>= bits;
2157*35238bceSAndroid Build Coastguard Worker     }
2158*35238bceSAndroid Build Coastguard Worker }
2159*35238bceSAndroid Build Coastguard Worker 
decompressBc7(const PixelBufferAccess & dst,const uint8_t * src)2160*35238bceSAndroid Build Coastguard Worker void decompressBc7(const PixelBufferAccess &dst, const uint8_t *src)
2161*35238bceSAndroid Build Coastguard Worker {
2162*35238bceSAndroid Build Coastguard Worker     using namespace BcDecompressInternal;
2163*35238bceSAndroid Build Coastguard Worker 
2164*35238bceSAndroid Build Coastguard Worker     static const uint8_t subsets[]          = {3, 2, 3, 2, 1, 1, 1, 2};
2165*35238bceSAndroid Build Coastguard Worker     static const uint8_t partitionBits[]    = {4, 6, 6, 6, 0, 0, 0, 6};
2166*35238bceSAndroid Build Coastguard Worker     static const uint8_t endpointBits[8][5] = {//r, g, b, a, p
2167*35238bceSAndroid Build Coastguard Worker                                                {4, 4, 4, 0, 1}, {6, 6, 6, 0, 1}, {5, 5, 5, 0, 0}, {7, 7, 7, 0, 1},
2168*35238bceSAndroid Build Coastguard Worker                                                {5, 5, 5, 6, 0}, {7, 7, 7, 8, 0}, {7, 7, 7, 7, 1}, {5, 5, 5, 5, 1}};
2169*35238bceSAndroid Build Coastguard Worker     static const uint8_t indexBits[]        = {3, 3, 2, 2, 2, 2, 4, 2};
2170*35238bceSAndroid Build Coastguard Worker 
2171*35238bceSAndroid Build Coastguard Worker     uint8_t *const dstPtr       = (uint8_t *)dst.getDataPtr();
2172*35238bceSAndroid Build Coastguard Worker     const uint32_t dstRowPitch  = dst.getRowPitch();
2173*35238bceSAndroid Build Coastguard Worker     const uint32_t dstPixelSize = 4;
2174*35238bceSAndroid Build Coastguard Worker 
2175*35238bceSAndroid Build Coastguard Worker     const uint64_t low  = ((uint64_t *)src)[0];
2176*35238bceSAndroid Build Coastguard Worker     const uint64_t high = ((uint64_t *)src)[1];
2177*35238bceSAndroid Build Coastguard Worker     const int32_t mode  = extractModeBc7(src[0]);
2178*35238bceSAndroid Build Coastguard Worker     uint32_t numSubsets = 1;
2179*35238bceSAndroid Build Coastguard Worker     uint32_t offset     = mode + 1;
2180*35238bceSAndroid Build Coastguard Worker     uint32_t rotation   = 0;
2181*35238bceSAndroid Build Coastguard Worker     uint32_t idxMode    = 0;
2182*35238bceSAndroid Build Coastguard Worker     uint32_t endpoints[6][5];
2183*35238bceSAndroid Build Coastguard Worker     uint32_t partitionSetId = 0;
2184*35238bceSAndroid Build Coastguard Worker 
2185*35238bceSAndroid Build Coastguard Worker     // Decode partition data from explicit partition bits
2186*35238bceSAndroid Build Coastguard Worker     if (mode == 0 || mode == 1 || mode == 2 || mode == 3 || mode == 7)
2187*35238bceSAndroid Build Coastguard Worker     {
2188*35238bceSAndroid Build Coastguard Worker         numSubsets     = subsets[mode];
2189*35238bceSAndroid Build Coastguard Worker         partitionSetId = getBits128(low, high, offset, offset + partitionBits[mode] - 1);
2190*35238bceSAndroid Build Coastguard Worker         offset += partitionBits[mode];
2191*35238bceSAndroid Build Coastguard Worker     }
2192*35238bceSAndroid Build Coastguard Worker 
2193*35238bceSAndroid Build Coastguard Worker     // Extract rotation bits
2194*35238bceSAndroid Build Coastguard Worker     if (mode == 4 || mode == 5)
2195*35238bceSAndroid Build Coastguard Worker     {
2196*35238bceSAndroid Build Coastguard Worker         rotation = getBits128(low, high, offset, offset + 1);
2197*35238bceSAndroid Build Coastguard Worker         offset += 2;
2198*35238bceSAndroid Build Coastguard Worker         if (mode == 4)
2199*35238bceSAndroid Build Coastguard Worker         {
2200*35238bceSAndroid Build Coastguard Worker             idxMode = getBits128(low, high, offset, offset);
2201*35238bceSAndroid Build Coastguard Worker             offset++;
2202*35238bceSAndroid Build Coastguard Worker         }
2203*35238bceSAndroid Build Coastguard Worker     }
2204*35238bceSAndroid Build Coastguard Worker 
2205*35238bceSAndroid Build Coastguard Worker     {
2206*35238bceSAndroid Build Coastguard Worker         const uint32_t numEndpoints = numSubsets * 2;
2207*35238bceSAndroid Build Coastguard Worker 
2208*35238bceSAndroid Build Coastguard Worker         // Extract raw, compressed endpoint bits
2209*35238bceSAndroid Build Coastguard Worker         for (uint32_t cpnt = 0; cpnt < 5; cpnt++)
2210*35238bceSAndroid Build Coastguard Worker         {
2211*35238bceSAndroid Build Coastguard Worker             for (uint32_t ep = 0; ep < numEndpoints; ep++)
2212*35238bceSAndroid Build Coastguard Worker             {
2213*35238bceSAndroid Build Coastguard Worker                 if (mode == 1 && cpnt == 4 && ep > 1)
2214*35238bceSAndroid Build Coastguard Worker                     continue; // Mode 1 has shared P bits
2215*35238bceSAndroid Build Coastguard Worker 
2216*35238bceSAndroid Build Coastguard Worker                 int n = mode == -1 ? 0 : endpointBits[mode][cpnt];
2217*35238bceSAndroid Build Coastguard Worker                 if (n > 0)
2218*35238bceSAndroid Build Coastguard Worker                     endpoints[ep][cpnt] = getBits128(low, high, offset, offset + n - 1);
2219*35238bceSAndroid Build Coastguard Worker                 offset += n;
2220*35238bceSAndroid Build Coastguard Worker             }
2221*35238bceSAndroid Build Coastguard Worker         }
2222*35238bceSAndroid Build Coastguard Worker 
2223*35238bceSAndroid Build Coastguard Worker         // Decode endpoints
2224*35238bceSAndroid Build Coastguard Worker         if (mode == 0 || mode == 1 || mode == 3 || mode == 6 || mode == 7)
2225*35238bceSAndroid Build Coastguard Worker         {
2226*35238bceSAndroid Build Coastguard Worker             // First handle modes that have P-bits
2227*35238bceSAndroid Build Coastguard Worker             for (uint32_t ep = 0; ep < numEndpoints; ep++)
2228*35238bceSAndroid Build Coastguard Worker             {
2229*35238bceSAndroid Build Coastguard Worker                 for (uint32_t cpnt = 0; cpnt < 4; cpnt++)
2230*35238bceSAndroid Build Coastguard Worker                 {
2231*35238bceSAndroid Build Coastguard Worker                     endpoints[ep][cpnt] <<= 1;
2232*35238bceSAndroid Build Coastguard Worker                 }
2233*35238bceSAndroid Build Coastguard Worker             }
2234*35238bceSAndroid Build Coastguard Worker 
2235*35238bceSAndroid Build Coastguard Worker             if (mode == 1)
2236*35238bceSAndroid Build Coastguard Worker             {
2237*35238bceSAndroid Build Coastguard Worker                 // P-bit is shared
2238*35238bceSAndroid Build Coastguard Worker                 const uint32_t pbitZero = endpoints[0][4];
2239*35238bceSAndroid Build Coastguard Worker                 const uint32_t pbitOne  = endpoints[1][4];
2240*35238bceSAndroid Build Coastguard Worker 
2241*35238bceSAndroid Build Coastguard Worker                 for (uint32_t cpnt = 0; cpnt < 3; cpnt++)
2242*35238bceSAndroid Build Coastguard Worker                 {
2243*35238bceSAndroid Build Coastguard Worker                     endpoints[0][cpnt] |= pbitZero;
2244*35238bceSAndroid Build Coastguard Worker                     endpoints[1][cpnt] |= pbitZero;
2245*35238bceSAndroid Build Coastguard Worker                     endpoints[2][cpnt] |= pbitOne;
2246*35238bceSAndroid Build Coastguard Worker                     endpoints[3][cpnt] |= pbitOne;
2247*35238bceSAndroid Build Coastguard Worker                 }
2248*35238bceSAndroid Build Coastguard Worker             }
2249*35238bceSAndroid Build Coastguard Worker             else
2250*35238bceSAndroid Build Coastguard Worker             {
2251*35238bceSAndroid Build Coastguard Worker                 // Unique p-bit per endpoint
2252*35238bceSAndroid Build Coastguard Worker                 for (uint32_t ep = 0; ep < numEndpoints; ep++)
2253*35238bceSAndroid Build Coastguard Worker                 {
2254*35238bceSAndroid Build Coastguard Worker                     for (uint32_t cpnt = 0; cpnt < 4; cpnt++)
2255*35238bceSAndroid Build Coastguard Worker                     {
2256*35238bceSAndroid Build Coastguard Worker                         endpoints[ep][cpnt] |= endpoints[ep][4];
2257*35238bceSAndroid Build Coastguard Worker                     }
2258*35238bceSAndroid Build Coastguard Worker                 }
2259*35238bceSAndroid Build Coastguard Worker             }
2260*35238bceSAndroid Build Coastguard Worker         }
2261*35238bceSAndroid Build Coastguard Worker 
2262*35238bceSAndroid Build Coastguard Worker         for (uint32_t ep = 0; ep < numEndpoints; ep++)
2263*35238bceSAndroid Build Coastguard Worker         {
2264*35238bceSAndroid Build Coastguard Worker             // Left shift endpoint components so that their MSB lies in bit 7
2265*35238bceSAndroid Build Coastguard Worker             for (uint32_t cpnt = 0; cpnt < 4; cpnt++)
2266*35238bceSAndroid Build Coastguard Worker                 endpoints[ep][cpnt] <<= 8 - (endpointBits[mode][cpnt] + endpointBits[mode][4]);
2267*35238bceSAndroid Build Coastguard Worker 
2268*35238bceSAndroid Build Coastguard Worker             // Replicate each component's MSB into the LSBs revealed by the left-shift operation above
2269*35238bceSAndroid Build Coastguard Worker             for (uint32_t cpnt = 0; cpnt < 4; cpnt++)
2270*35238bceSAndroid Build Coastguard Worker                 endpoints[ep][cpnt] |= endpoints[ep][cpnt] >> (endpointBits[mode][cpnt] + endpointBits[mode][4]);
2271*35238bceSAndroid Build Coastguard Worker         }
2272*35238bceSAndroid Build Coastguard Worker 
2273*35238bceSAndroid Build Coastguard Worker         // If this mode does not explicitly define the alpha component set alpha equal to 1.0
2274*35238bceSAndroid Build Coastguard Worker         if (mode < 4)
2275*35238bceSAndroid Build Coastguard Worker         {
2276*35238bceSAndroid Build Coastguard Worker             for (uint32_t ep = 0; ep < numEndpoints; ep++)
2277*35238bceSAndroid Build Coastguard Worker                 endpoints[ep][3] = 255;
2278*35238bceSAndroid Build Coastguard Worker         }
2279*35238bceSAndroid Build Coastguard Worker     }
2280*35238bceSAndroid Build Coastguard Worker 
2281*35238bceSAndroid Build Coastguard Worker     {
2282*35238bceSAndroid Build Coastguard Worker         uint32_t colorIdxOffset = offset + ((mode == 4 && idxMode) ? 31 : 0);
2283*35238bceSAndroid Build Coastguard Worker         uint32_t alphaIdxOffset = offset + ((mode == 5 || (mode == 4 && !idxMode)) ? 31 : 0);
2284*35238bceSAndroid Build Coastguard Worker 
2285*35238bceSAndroid Build Coastguard Worker         for (uint32_t pixel = 0; pixel < 16; pixel++)
2286*35238bceSAndroid Build Coastguard Worker         {
2287*35238bceSAndroid Build Coastguard Worker             const uint32_t y         = pixel / 4;
2288*35238bceSAndroid Build Coastguard Worker             const uint32_t x         = pixel % 4;
2289*35238bceSAndroid Build Coastguard Worker             uint32_t *const dstPixel = (uint32_t *)(dstPtr + y * dstRowPitch + x * dstPixelSize);
2290*35238bceSAndroid Build Coastguard Worker             uint32_t subsetIndex     = 0;
2291*35238bceSAndroid Build Coastguard Worker             uint32_t anchorIndex     = 0;
2292*35238bceSAndroid Build Coastguard Worker             uint32_t endpointStart[4];
2293*35238bceSAndroid Build Coastguard Worker             uint32_t endpointEnd[4];
2294*35238bceSAndroid Build Coastguard Worker 
2295*35238bceSAndroid Build Coastguard Worker             if (mode == -1)
2296*35238bceSAndroid Build Coastguard Worker             {
2297*35238bceSAndroid Build Coastguard Worker                 *dstPixel = 0;
2298*35238bceSAndroid Build Coastguard Worker                 continue;
2299*35238bceSAndroid Build Coastguard Worker             }
2300*35238bceSAndroid Build Coastguard Worker 
2301*35238bceSAndroid Build Coastguard Worker             if (numSubsets == 2)
2302*35238bceSAndroid Build Coastguard Worker                 subsetIndex = partitions2[partitionSetId][pixel];
2303*35238bceSAndroid Build Coastguard Worker             else if (numSubsets == 3)
2304*35238bceSAndroid Build Coastguard Worker                 subsetIndex = partitions3[partitionSetId][pixel];
2305*35238bceSAndroid Build Coastguard Worker 
2306*35238bceSAndroid Build Coastguard Worker             if (numSubsets == 2 && subsetIndex == 1)
2307*35238bceSAndroid Build Coastguard Worker             {
2308*35238bceSAndroid Build Coastguard Worker                 anchorIndex = anchorIndicesSecondSubset2[partitionSetId];
2309*35238bceSAndroid Build Coastguard Worker             }
2310*35238bceSAndroid Build Coastguard Worker             else if (numSubsets == 3)
2311*35238bceSAndroid Build Coastguard Worker             {
2312*35238bceSAndroid Build Coastguard Worker                 if (subsetIndex == 1)
2313*35238bceSAndroid Build Coastguard Worker                     anchorIndex = anchorIndicesSecondSubset3[partitionSetId];
2314*35238bceSAndroid Build Coastguard Worker                 else if (subsetIndex == 2)
2315*35238bceSAndroid Build Coastguard Worker                     anchorIndex = anchorIndicesThirdSubset[partitionSetId];
2316*35238bceSAndroid Build Coastguard Worker             }
2317*35238bceSAndroid Build Coastguard Worker 
2318*35238bceSAndroid Build Coastguard Worker             for (uint32_t cpnt = 0; cpnt < 4; cpnt++)
2319*35238bceSAndroid Build Coastguard Worker             {
2320*35238bceSAndroid Build Coastguard Worker                 endpointStart[cpnt] = endpoints[2 * subsetIndex][cpnt];
2321*35238bceSAndroid Build Coastguard Worker                 endpointEnd[cpnt]   = endpoints[2 * subsetIndex + 1][cpnt];
2322*35238bceSAndroid Build Coastguard Worker             }
2323*35238bceSAndroid Build Coastguard Worker 
2324*35238bceSAndroid Build Coastguard Worker             {
2325*35238bceSAndroid Build Coastguard Worker                 const uint32_t colorInterpolationBits = indexBits[mode] + idxMode;
2326*35238bceSAndroid Build Coastguard Worker                 const uint32_t colorIndexBits         = colorInterpolationBits - ((anchorIndex == pixel) ? 1 : 0);
2327*35238bceSAndroid Build Coastguard Worker                 const uint32_t alphaInterpolationBits =
2328*35238bceSAndroid Build Coastguard Worker                     mode == 4 ? 3 - idxMode : (mode == 5 ? 2 : colorInterpolationBits);
2329*35238bceSAndroid Build Coastguard Worker                 const uint32_t alphaIndexBits = alphaInterpolationBits - ((anchorIndex == pixel) ? 1 : 0);
2330*35238bceSAndroid Build Coastguard Worker                 const uint32_t colorIdx = getBits128(low, high, colorIdxOffset, colorIdxOffset + colorIndexBits - 1);
2331*35238bceSAndroid Build Coastguard Worker                 const uint32_t alphaIdx = (mode == 4 || mode == 5) ? getBits128(low, high, alphaIdxOffset,
2332*35238bceSAndroid Build Coastguard Worker                                                                                 alphaIdxOffset + alphaIndexBits - 1) :
2333*35238bceSAndroid Build Coastguard Worker                                                                      colorIdx;
2334*35238bceSAndroid Build Coastguard Worker                 const uint32_t r = interpolate(endpointStart[0], endpointEnd[0], colorIdx, colorInterpolationBits);
2335*35238bceSAndroid Build Coastguard Worker                 const uint32_t g = interpolate(endpointStart[1], endpointEnd[1], colorIdx, colorInterpolationBits);
2336*35238bceSAndroid Build Coastguard Worker                 const uint32_t b = interpolate(endpointStart[2], endpointEnd[2], colorIdx, colorInterpolationBits);
2337*35238bceSAndroid Build Coastguard Worker                 const uint32_t a = interpolate(endpointStart[3], endpointEnd[3], alphaIdx, alphaInterpolationBits);
2338*35238bceSAndroid Build Coastguard Worker 
2339*35238bceSAndroid Build Coastguard Worker                 colorIdxOffset += colorIndexBits;
2340*35238bceSAndroid Build Coastguard Worker                 alphaIdxOffset += alphaIndexBits;
2341*35238bceSAndroid Build Coastguard Worker 
2342*35238bceSAndroid Build Coastguard Worker                 if ((mode == 4 || mode == 5) && rotation != 0)
2343*35238bceSAndroid Build Coastguard Worker                 {
2344*35238bceSAndroid Build Coastguard Worker                     if (rotation == 1)
2345*35238bceSAndroid Build Coastguard Worker                         *dstPixel = a | (g << 8) | (b << 16) | (r << 24);
2346*35238bceSAndroid Build Coastguard Worker                     else if (rotation == 2)
2347*35238bceSAndroid Build Coastguard Worker                         *dstPixel = r | (a << 8) | (b << 16) | (g << 24);
2348*35238bceSAndroid Build Coastguard Worker                     else
2349*35238bceSAndroid Build Coastguard Worker                         *dstPixel = r | (g << 8) | (a << 16) | (b << 24);
2350*35238bceSAndroid Build Coastguard Worker                 }
2351*35238bceSAndroid Build Coastguard Worker                 else
2352*35238bceSAndroid Build Coastguard Worker                 {
2353*35238bceSAndroid Build Coastguard Worker                     *dstPixel = r | (g << 8) | (b << 16) | (a << 24);
2354*35238bceSAndroid Build Coastguard Worker                 }
2355*35238bceSAndroid Build Coastguard Worker             }
2356*35238bceSAndroid Build Coastguard Worker         }
2357*35238bceSAndroid Build Coastguard Worker     }
2358*35238bceSAndroid Build Coastguard Worker }
2359*35238bceSAndroid Build Coastguard Worker 
decompressAhbRaw10(const PixelBufferAccess & dst,const uint8_t * src)2360*35238bceSAndroid Build Coastguard Worker void decompressAhbRaw10(const PixelBufferAccess &dst, const uint8_t *src)
2361*35238bceSAndroid Build Coastguard Worker {
2362*35238bceSAndroid Build Coastguard Worker     // Packed format with 4 pixels in 5 bytes
2363*35238bceSAndroid Build Coastguard Worker     // Layout: https://developer.android.com/reference/android/graphics/ImageFormat#RAW10
2364*35238bceSAndroid Build Coastguard Worker 
2365*35238bceSAndroid Build Coastguard Worker     uint32_t firstPixel  = (*(src + 0u));
2366*35238bceSAndroid Build Coastguard Worker     uint32_t secondPixel = (*(src + 1u));
2367*35238bceSAndroid Build Coastguard Worker     uint32_t thirdPixel  = (*(src + 2u));
2368*35238bceSAndroid Build Coastguard Worker     uint32_t fourthPixel = (*(src + 3u));
2369*35238bceSAndroid Build Coastguard Worker     uint32_t packedPixel = (*(src + 4u));
2370*35238bceSAndroid Build Coastguard Worker 
2371*35238bceSAndroid Build Coastguard Worker     // We now need to take last bits for each pixel from the packed pixel to build all pixel values
2372*35238bceSAndroid Build Coastguard Worker     firstPixel  = ((firstPixel << 2u) | ((packedPixel >> 0u) & 0b00000011u));
2373*35238bceSAndroid Build Coastguard Worker     secondPixel = ((secondPixel << 2u) | ((packedPixel >> 2u) & 0b00000011u));
2374*35238bceSAndroid Build Coastguard Worker     thirdPixel  = ((thirdPixel << 2u) | ((packedPixel >> 4u) & 0b00000011u));
2375*35238bceSAndroid Build Coastguard Worker     fourthPixel = ((fourthPixel << 2u) | ((packedPixel >> 6u) & 0b00000011u));
2376*35238bceSAndroid Build Coastguard Worker 
2377*35238bceSAndroid Build Coastguard Worker     // Store values in buffer (higher bits is were data is stored)
2378*35238bceSAndroid Build Coastguard Worker     uint16_t *pixel = static_cast<uint16_t *>(dst.getDataPtr());
2379*35238bceSAndroid Build Coastguard Worker     (*pixel)        = static_cast<uint16_t>(firstPixel << 6u);
2380*35238bceSAndroid Build Coastguard Worker 
2381*35238bceSAndroid Build Coastguard Worker     pixel++;
2382*35238bceSAndroid Build Coastguard Worker     (*pixel) = static_cast<uint16_t>(secondPixel << 6u);
2383*35238bceSAndroid Build Coastguard Worker 
2384*35238bceSAndroid Build Coastguard Worker     pixel++;
2385*35238bceSAndroid Build Coastguard Worker     (*pixel) = static_cast<uint16_t>(thirdPixel << 6u);
2386*35238bceSAndroid Build Coastguard Worker 
2387*35238bceSAndroid Build Coastguard Worker     pixel++;
2388*35238bceSAndroid Build Coastguard Worker     (*pixel) = static_cast<uint16_t>(fourthPixel << 6u);
2389*35238bceSAndroid Build Coastguard Worker }
2390*35238bceSAndroid Build Coastguard Worker 
decompressAhbRaw12(const PixelBufferAccess & dst,const uint8_t * src)2391*35238bceSAndroid Build Coastguard Worker void decompressAhbRaw12(const PixelBufferAccess &dst, const uint8_t *src)
2392*35238bceSAndroid Build Coastguard Worker {
2393*35238bceSAndroid Build Coastguard Worker     // Packed format with 2 pixels in 3 bytes
2394*35238bceSAndroid Build Coastguard Worker     // Layout: https://developer.android.com/reference/android/graphics/ImageFormat#RAW12
2395*35238bceSAndroid Build Coastguard Worker 
2396*35238bceSAndroid Build Coastguard Worker     uint32_t firstPixel  = (*(src + 0));
2397*35238bceSAndroid Build Coastguard Worker     uint32_t secondPixel = (*(src + 1));
2398*35238bceSAndroid Build Coastguard Worker     uint32_t packedPixel = (*(src + 2));
2399*35238bceSAndroid Build Coastguard Worker 
2400*35238bceSAndroid Build Coastguard Worker     // We now need to take last bits for each pixel from the packed pixel to build all pixel values
2401*35238bceSAndroid Build Coastguard Worker     firstPixel  = ((firstPixel << 4u) | ((packedPixel >> 0u) & 0b00001111u));
2402*35238bceSAndroid Build Coastguard Worker     secondPixel = ((secondPixel << 4u) | ((packedPixel >> 4u) & 0b00001111u));
2403*35238bceSAndroid Build Coastguard Worker 
2404*35238bceSAndroid Build Coastguard Worker     // Store values in buffer (higher bits is were data is stored)
2405*35238bceSAndroid Build Coastguard Worker     uint16_t *pixel = static_cast<uint16_t *>(dst.getDataPtr());
2406*35238bceSAndroid Build Coastguard Worker     (*pixel)        = static_cast<uint16_t>(firstPixel << 6u);
2407*35238bceSAndroid Build Coastguard Worker 
2408*35238bceSAndroid Build Coastguard Worker     pixel++;
2409*35238bceSAndroid Build Coastguard Worker     (*pixel) = static_cast<uint16_t>(secondPixel << 6u);
2410*35238bceSAndroid Build Coastguard Worker }
2411*35238bceSAndroid Build Coastguard Worker 
decompressBlock(CompressedTexFormat format,const PixelBufferAccess & dst,const uint8_t * src,const TexDecompressionParams & params)2412*35238bceSAndroid Build Coastguard Worker void decompressBlock(CompressedTexFormat format, const PixelBufferAccess &dst, const uint8_t *src,
2413*35238bceSAndroid Build Coastguard Worker                      const TexDecompressionParams &params)
2414*35238bceSAndroid Build Coastguard Worker {
2415*35238bceSAndroid Build Coastguard Worker     // No 3D blocks supported right now
2416*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(dst.getDepth() == 1);
2417*35238bceSAndroid Build Coastguard Worker 
2418*35238bceSAndroid Build Coastguard Worker     switch (format)
2419*35238bceSAndroid Build Coastguard Worker     {
2420*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC1_RGB8:
2421*35238bceSAndroid Build Coastguard Worker         decompressETC1(dst, src);
2422*35238bceSAndroid Build Coastguard Worker         break;
2423*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_EAC_R11:
2424*35238bceSAndroid Build Coastguard Worker         decompressEAC_R11(dst, src, false);
2425*35238bceSAndroid Build Coastguard Worker         break;
2426*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_EAC_SIGNED_R11:
2427*35238bceSAndroid Build Coastguard Worker         decompressEAC_R11(dst, src, true);
2428*35238bceSAndroid Build Coastguard Worker         break;
2429*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_EAC_RG11:
2430*35238bceSAndroid Build Coastguard Worker         decompressEAC_RG11(dst, src, false);
2431*35238bceSAndroid Build Coastguard Worker         break;
2432*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11:
2433*35238bceSAndroid Build Coastguard Worker         decompressEAC_RG11(dst, src, true);
2434*35238bceSAndroid Build Coastguard Worker         break;
2435*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_RGB8:
2436*35238bceSAndroid Build Coastguard Worker         decompressETC2(dst, src);
2437*35238bceSAndroid Build Coastguard Worker         break;
2438*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_SRGB8:
2439*35238bceSAndroid Build Coastguard Worker         decompressETC2(dst, src);
2440*35238bceSAndroid Build Coastguard Worker         break;
2441*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
2442*35238bceSAndroid Build Coastguard Worker         decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1(dst, src);
2443*35238bceSAndroid Build Coastguard Worker         break;
2444*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
2445*35238bceSAndroid Build Coastguard Worker         decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1(dst, src);
2446*35238bceSAndroid Build Coastguard Worker         break;
2447*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_EAC_RGBA8:
2448*35238bceSAndroid Build Coastguard Worker         decompressETC2_EAC_RGBA8(dst, src);
2449*35238bceSAndroid Build Coastguard Worker         break;
2450*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ETC2_EAC_SRGB8_ALPHA8:
2451*35238bceSAndroid Build Coastguard Worker         decompressETC2_EAC_RGBA8(dst, src);
2452*35238bceSAndroid Build Coastguard Worker         break;
2453*35238bceSAndroid Build Coastguard Worker 
2454*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_4x4_RGBA:
2455*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_5x4_RGBA:
2456*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_5x5_RGBA:
2457*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_6x5_RGBA:
2458*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_6x6_RGBA:
2459*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x5_RGBA:
2460*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x6_RGBA:
2461*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x8_RGBA:
2462*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x5_RGBA:
2463*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x6_RGBA:
2464*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x8_RGBA:
2465*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x10_RGBA:
2466*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_12x10_RGBA:
2467*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA:
2468*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8:
2469*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_5x4_SRGB8_ALPHA8:
2470*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8:
2471*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8:
2472*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8:
2473*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x5_SRGB8_ALPHA8:
2474*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8:
2475*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8:
2476*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8:
2477*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8:
2478*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8:
2479*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8:
2480*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8:
2481*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8:
2482*35238bceSAndroid Build Coastguard Worker         astc::decompress(dst, src, format, params.astcMode);
2483*35238bceSAndroid Build Coastguard Worker         break;
2484*35238bceSAndroid Build Coastguard Worker 
2485*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC1_RGB_UNORM_BLOCK:
2486*35238bceSAndroid Build Coastguard Worker         decompressBc1(dst, src, false);
2487*35238bceSAndroid Build Coastguard Worker         break;
2488*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC1_RGB_SRGB_BLOCK:
2489*35238bceSAndroid Build Coastguard Worker         decompressBc1(dst, src, false);
2490*35238bceSAndroid Build Coastguard Worker         break;
2491*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC1_RGBA_UNORM_BLOCK:
2492*35238bceSAndroid Build Coastguard Worker         decompressBc1(dst, src, true);
2493*35238bceSAndroid Build Coastguard Worker         break;
2494*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC1_RGBA_SRGB_BLOCK:
2495*35238bceSAndroid Build Coastguard Worker         decompressBc1(dst, src, true);
2496*35238bceSAndroid Build Coastguard Worker         break;
2497*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC2_UNORM_BLOCK:
2498*35238bceSAndroid Build Coastguard Worker         decompressBc2(dst, src);
2499*35238bceSAndroid Build Coastguard Worker         break;
2500*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC2_SRGB_BLOCK:
2501*35238bceSAndroid Build Coastguard Worker         decompressBc2(dst, src);
2502*35238bceSAndroid Build Coastguard Worker         break;
2503*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC3_UNORM_BLOCK:
2504*35238bceSAndroid Build Coastguard Worker         decompressBc3(dst, src);
2505*35238bceSAndroid Build Coastguard Worker         break;
2506*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC3_SRGB_BLOCK:
2507*35238bceSAndroid Build Coastguard Worker         decompressBc3(dst, src);
2508*35238bceSAndroid Build Coastguard Worker         break;
2509*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK:
2510*35238bceSAndroid Build Coastguard Worker         decompressBc4(dst, src, false);
2511*35238bceSAndroid Build Coastguard Worker         break;
2512*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK:
2513*35238bceSAndroid Build Coastguard Worker         decompressBc4(dst, src, true);
2514*35238bceSAndroid Build Coastguard Worker         break;
2515*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK:
2516*35238bceSAndroid Build Coastguard Worker         decompressBc5(dst, src, false);
2517*35238bceSAndroid Build Coastguard Worker         break;
2518*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK:
2519*35238bceSAndroid Build Coastguard Worker         decompressBc5(dst, src, true);
2520*35238bceSAndroid Build Coastguard Worker         break;
2521*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK:
2522*35238bceSAndroid Build Coastguard Worker         decompressBc6H(dst, src, false);
2523*35238bceSAndroid Build Coastguard Worker         break;
2524*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK:
2525*35238bceSAndroid Build Coastguard Worker         decompressBc6H(dst, src, true);
2526*35238bceSAndroid Build Coastguard Worker         break;
2527*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK:
2528*35238bceSAndroid Build Coastguard Worker         decompressBc7(dst, src);
2529*35238bceSAndroid Build Coastguard Worker         break;
2530*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK:
2531*35238bceSAndroid Build Coastguard Worker         decompressBc7(dst, src);
2532*35238bceSAndroid Build Coastguard Worker         break;
2533*35238bceSAndroid Build Coastguard Worker 
2534*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_AHB_RAW10:
2535*35238bceSAndroid Build Coastguard Worker         decompressAhbRaw10(dst, src);
2536*35238bceSAndroid Build Coastguard Worker         break;
2537*35238bceSAndroid Build Coastguard Worker     case COMPRESSEDTEXFORMAT_AHB_RAW12:
2538*35238bceSAndroid Build Coastguard Worker         decompressAhbRaw12(dst, src);
2539*35238bceSAndroid Build Coastguard Worker         break;
2540*35238bceSAndroid Build Coastguard Worker 
2541*35238bceSAndroid Build Coastguard Worker     default:
2542*35238bceSAndroid Build Coastguard Worker         DE_FATAL("Unexpected format");
2543*35238bceSAndroid Build Coastguard Worker         break;
2544*35238bceSAndroid Build Coastguard Worker     }
2545*35238bceSAndroid Build Coastguard Worker }
2546*35238bceSAndroid Build Coastguard Worker 
componentSum(const IVec3 & vec)2547*35238bceSAndroid Build Coastguard Worker int componentSum(const IVec3 &vec)
2548*35238bceSAndroid Build Coastguard Worker {
2549*35238bceSAndroid Build Coastguard Worker     return vec.x() + vec.y() + vec.z();
2550*35238bceSAndroid Build Coastguard Worker }
2551*35238bceSAndroid Build Coastguard Worker 
2552*35238bceSAndroid Build Coastguard Worker } // namespace
2553*35238bceSAndroid Build Coastguard Worker 
decompress(const PixelBufferAccess & dst,CompressedTexFormat fmt,const uint8_t * src,const TexDecompressionParams & params)2554*35238bceSAndroid Build Coastguard Worker void decompress(const PixelBufferAccess &dst, CompressedTexFormat fmt, const uint8_t *src,
2555*35238bceSAndroid Build Coastguard Worker                 const TexDecompressionParams &params)
2556*35238bceSAndroid Build Coastguard Worker {
2557*35238bceSAndroid Build Coastguard Worker     const int blockSize = getBlockSize(fmt);
2558*35238bceSAndroid Build Coastguard Worker     const IVec3 blockPixelSize(getBlockPixelSize(fmt));
2559*35238bceSAndroid Build Coastguard Worker     const IVec3 blockCount(deDivRoundUp32(dst.getWidth(), blockPixelSize.x()),
2560*35238bceSAndroid Build Coastguard Worker                            deDivRoundUp32(dst.getHeight(), blockPixelSize.y()),
2561*35238bceSAndroid Build Coastguard Worker                            deDivRoundUp32(dst.getDepth(), blockPixelSize.z()));
2562*35238bceSAndroid Build Coastguard Worker     const IVec3 blockPitches(blockSize, blockSize * blockCount.x(), blockSize * blockCount.x() * blockCount.y());
2563*35238bceSAndroid Build Coastguard Worker 
2564*35238bceSAndroid Build Coastguard Worker     std::vector<uint8_t> uncompressedBlock(dst.getFormat().getPixelSize() * blockPixelSize.x() * blockPixelSize.y() *
2565*35238bceSAndroid Build Coastguard Worker                                            blockPixelSize.z());
2566*35238bceSAndroid Build Coastguard Worker     const PixelBufferAccess blockAccess(getUncompressedFormat(fmt), blockPixelSize.x(), blockPixelSize.y(),
2567*35238bceSAndroid Build Coastguard Worker                                         blockPixelSize.z(), &uncompressedBlock[0]);
2568*35238bceSAndroid Build Coastguard Worker 
2569*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(dst.getFormat() == getUncompressedFormat(fmt));
2570*35238bceSAndroid Build Coastguard Worker 
2571*35238bceSAndroid Build Coastguard Worker     for (int blockZ = 0; blockZ < blockCount.z(); blockZ++)
2572*35238bceSAndroid Build Coastguard Worker         for (int blockY = 0; blockY < blockCount.y(); blockY++)
2573*35238bceSAndroid Build Coastguard Worker             for (int blockX = 0; blockX < blockCount.x(); blockX++)
2574*35238bceSAndroid Build Coastguard Worker             {
2575*35238bceSAndroid Build Coastguard Worker                 const IVec3 blockPos(blockX, blockY, blockZ);
2576*35238bceSAndroid Build Coastguard Worker                 const uint8_t *const blockPtr = src + componentSum(blockPos * blockPitches);
2577*35238bceSAndroid Build Coastguard Worker                 const IVec3 copySize(de::min(blockPixelSize.x(), dst.getWidth() - blockPos.x() * blockPixelSize.x()),
2578*35238bceSAndroid Build Coastguard Worker                                      de::min(blockPixelSize.y(), dst.getHeight() - blockPos.y() * blockPixelSize.y()),
2579*35238bceSAndroid Build Coastguard Worker                                      de::min(blockPixelSize.z(), dst.getDepth() - blockPos.z() * blockPixelSize.z()));
2580*35238bceSAndroid Build Coastguard Worker                 const IVec3 dstPixelPos = blockPos * blockPixelSize;
2581*35238bceSAndroid Build Coastguard Worker 
2582*35238bceSAndroid Build Coastguard Worker                 decompressBlock(fmt, blockAccess, blockPtr, params);
2583*35238bceSAndroid Build Coastguard Worker 
2584*35238bceSAndroid Build Coastguard Worker                 copy(getSubregion(dst, dstPixelPos.x(), dstPixelPos.y(), dstPixelPos.z(), copySize.x(), copySize.y(),
2585*35238bceSAndroid Build Coastguard Worker                                   copySize.z()),
2586*35238bceSAndroid Build Coastguard Worker                      getSubregion(blockAccess, 0, 0, 0, copySize.x(), copySize.y(), copySize.z()));
2587*35238bceSAndroid Build Coastguard Worker             }
2588*35238bceSAndroid Build Coastguard Worker }
2589*35238bceSAndroid Build Coastguard Worker 
CompressedTexture(void)2590*35238bceSAndroid Build Coastguard Worker CompressedTexture::CompressedTexture(void) : m_format(COMPRESSEDTEXFORMAT_LAST), m_width(0), m_height(0), m_depth(0)
2591*35238bceSAndroid Build Coastguard Worker {
2592*35238bceSAndroid Build Coastguard Worker }
2593*35238bceSAndroid Build Coastguard Worker 
CompressedTexture(CompressedTexFormat format,int width,int height,int depth)2594*35238bceSAndroid Build Coastguard Worker CompressedTexture::CompressedTexture(CompressedTexFormat format, int width, int height, int depth)
2595*35238bceSAndroid Build Coastguard Worker     : m_format(COMPRESSEDTEXFORMAT_LAST)
2596*35238bceSAndroid Build Coastguard Worker     , m_width(0)
2597*35238bceSAndroid Build Coastguard Worker     , m_height(0)
2598*35238bceSAndroid Build Coastguard Worker     , m_depth(0)
2599*35238bceSAndroid Build Coastguard Worker {
2600*35238bceSAndroid Build Coastguard Worker     setStorage(format, width, height, depth);
2601*35238bceSAndroid Build Coastguard Worker }
2602*35238bceSAndroid Build Coastguard Worker 
~CompressedTexture(void)2603*35238bceSAndroid Build Coastguard Worker CompressedTexture::~CompressedTexture(void)
2604*35238bceSAndroid Build Coastguard Worker {
2605*35238bceSAndroid Build Coastguard Worker }
2606*35238bceSAndroid Build Coastguard Worker 
setStorage(CompressedTexFormat format,int width,int height,int depth)2607*35238bceSAndroid Build Coastguard Worker void CompressedTexture::setStorage(CompressedTexFormat format, int width, int height, int depth)
2608*35238bceSAndroid Build Coastguard Worker {
2609*35238bceSAndroid Build Coastguard Worker     m_format = format;
2610*35238bceSAndroid Build Coastguard Worker     m_width  = width;
2611*35238bceSAndroid Build Coastguard Worker     m_height = height;
2612*35238bceSAndroid Build Coastguard Worker     m_depth  = depth;
2613*35238bceSAndroid Build Coastguard Worker 
2614*35238bceSAndroid Build Coastguard Worker     if (m_format != COMPRESSEDTEXFORMAT_LAST)
2615*35238bceSAndroid Build Coastguard Worker     {
2616*35238bceSAndroid Build Coastguard Worker         const IVec3 blockPixelSize = getBlockPixelSize(m_format);
2617*35238bceSAndroid Build Coastguard Worker         const int blockSize        = getBlockSize(m_format);
2618*35238bceSAndroid Build Coastguard Worker 
2619*35238bceSAndroid Build Coastguard Worker         m_data.resize(deDivRoundUp32(m_width, blockPixelSize.x()) * deDivRoundUp32(m_height, blockPixelSize.y()) *
2620*35238bceSAndroid Build Coastguard Worker                       deDivRoundUp32(m_depth, blockPixelSize.z()) * blockSize);
2621*35238bceSAndroid Build Coastguard Worker     }
2622*35238bceSAndroid Build Coastguard Worker     else
2623*35238bceSAndroid Build Coastguard Worker     {
2624*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(m_format == COMPRESSEDTEXFORMAT_LAST);
2625*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(m_width == 0 && m_height == 0 && m_depth == 0);
2626*35238bceSAndroid Build Coastguard Worker         m_data.resize(0);
2627*35238bceSAndroid Build Coastguard Worker     }
2628*35238bceSAndroid Build Coastguard Worker }
2629*35238bceSAndroid Build Coastguard Worker 
2630*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
2631*35238bceSAndroid Build Coastguard Worker  * \brief Decode to uncompressed pixel data
2632*35238bceSAndroid Build Coastguard Worker  * \param dst Destination buffer
2633*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
decompress(const PixelBufferAccess & dst,const TexDecompressionParams & params) const2634*35238bceSAndroid Build Coastguard Worker void CompressedTexture::decompress(const PixelBufferAccess &dst, const TexDecompressionParams &params) const
2635*35238bceSAndroid Build Coastguard Worker {
2636*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(dst.getWidth() == m_width && dst.getHeight() == m_height && dst.getDepth() == m_depth);
2637*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(dst.getFormat() == getUncompressedFormat(m_format));
2638*35238bceSAndroid Build Coastguard Worker 
2639*35238bceSAndroid Build Coastguard Worker     tcu::decompress(dst, m_format, &m_data[0], params);
2640*35238bceSAndroid Build Coastguard Worker }
2641*35238bceSAndroid Build Coastguard Worker 
2642*35238bceSAndroid Build Coastguard Worker } // namespace tcu
2643