1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker #include "BC_Decoder.hpp"
16*03ce13f7SAndroid Build Coastguard Worker
17*03ce13f7SAndroid Build Coastguard Worker #include "System/Debug.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "System/Math.hpp"
19*03ce13f7SAndroid Build Coastguard Worker
20*03ce13f7SAndroid Build Coastguard Worker #include <algorithm>
21*03ce13f7SAndroid Build Coastguard Worker #include <array>
22*03ce13f7SAndroid Build Coastguard Worker #include <cstddef>
23*03ce13f7SAndroid Build Coastguard Worker #include <vector>
24*03ce13f7SAndroid Build Coastguard Worker
25*03ce13f7SAndroid Build Coastguard Worker #include <assert.h>
26*03ce13f7SAndroid Build Coastguard Worker #include <stdint.h>
27*03ce13f7SAndroid Build Coastguard Worker
28*03ce13f7SAndroid Build Coastguard Worker namespace {
29*03ce13f7SAndroid Build Coastguard Worker static constexpr int BlockWidth = 4;
30*03ce13f7SAndroid Build Coastguard Worker static constexpr int BlockHeight = 4;
31*03ce13f7SAndroid Build Coastguard Worker
32*03ce13f7SAndroid Build Coastguard Worker struct BC_color
33*03ce13f7SAndroid Build Coastguard Worker {
decode__anon204fc45b0111::BC_color34*03ce13f7SAndroid Build Coastguard Worker void decode(uint8_t *dst, int x, int y, int dstW, int dstH, int dstPitch, int dstBpp, bool hasAlphaChannel, bool hasSeparateAlpha) const
35*03ce13f7SAndroid Build Coastguard Worker {
36*03ce13f7SAndroid Build Coastguard Worker Color c[4];
37*03ce13f7SAndroid Build Coastguard Worker c[0].extract565(c0);
38*03ce13f7SAndroid Build Coastguard Worker c[1].extract565(c1);
39*03ce13f7SAndroid Build Coastguard Worker if(hasSeparateAlpha || (c0 > c1))
40*03ce13f7SAndroid Build Coastguard Worker {
41*03ce13f7SAndroid Build Coastguard Worker c[2] = ((c[0] * 2) + c[1]) / 3;
42*03ce13f7SAndroid Build Coastguard Worker c[3] = ((c[1] * 2) + c[0]) / 3;
43*03ce13f7SAndroid Build Coastguard Worker }
44*03ce13f7SAndroid Build Coastguard Worker else
45*03ce13f7SAndroid Build Coastguard Worker {
46*03ce13f7SAndroid Build Coastguard Worker c[2] = (c[0] + c[1]) >> 1;
47*03ce13f7SAndroid Build Coastguard Worker if(hasAlphaChannel)
48*03ce13f7SAndroid Build Coastguard Worker {
49*03ce13f7SAndroid Build Coastguard Worker c[3].clearAlpha();
50*03ce13f7SAndroid Build Coastguard Worker }
51*03ce13f7SAndroid Build Coastguard Worker }
52*03ce13f7SAndroid Build Coastguard Worker
53*03ce13f7SAndroid Build Coastguard Worker for(int j = 0; j < BlockHeight && (y + j) < dstH; j++)
54*03ce13f7SAndroid Build Coastguard Worker {
55*03ce13f7SAndroid Build Coastguard Worker int dstOffset = j * dstPitch;
56*03ce13f7SAndroid Build Coastguard Worker int idxOffset = j * BlockHeight;
57*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < BlockWidth && (x + i) < dstW; i++, idxOffset++, dstOffset += dstBpp)
58*03ce13f7SAndroid Build Coastguard Worker {
59*03ce13f7SAndroid Build Coastguard Worker *reinterpret_cast<unsigned int *>(dst + dstOffset) = c[getIdx(idxOffset)].pack8888();
60*03ce13f7SAndroid Build Coastguard Worker }
61*03ce13f7SAndroid Build Coastguard Worker }
62*03ce13f7SAndroid Build Coastguard Worker }
63*03ce13f7SAndroid Build Coastguard Worker
64*03ce13f7SAndroid Build Coastguard Worker private:
65*03ce13f7SAndroid Build Coastguard Worker struct Color
66*03ce13f7SAndroid Build Coastguard Worker {
Color__anon204fc45b0111::BC_color::Color67*03ce13f7SAndroid Build Coastguard Worker Color()
68*03ce13f7SAndroid Build Coastguard Worker {
69*03ce13f7SAndroid Build Coastguard Worker c[0] = c[1] = c[2] = 0;
70*03ce13f7SAndroid Build Coastguard Worker c[3] = 0xFF000000;
71*03ce13f7SAndroid Build Coastguard Worker }
72*03ce13f7SAndroid Build Coastguard Worker
extract565__anon204fc45b0111::BC_color::Color73*03ce13f7SAndroid Build Coastguard Worker void extract565(const unsigned int c565)
74*03ce13f7SAndroid Build Coastguard Worker {
75*03ce13f7SAndroid Build Coastguard Worker c[0] = ((c565 & 0x0000001F) << 3) | ((c565 & 0x0000001C) >> 2);
76*03ce13f7SAndroid Build Coastguard Worker c[1] = ((c565 & 0x000007E0) >> 3) | ((c565 & 0x00000600) >> 9);
77*03ce13f7SAndroid Build Coastguard Worker c[2] = ((c565 & 0x0000F800) >> 8) | ((c565 & 0x0000E000) >> 13);
78*03ce13f7SAndroid Build Coastguard Worker }
79*03ce13f7SAndroid Build Coastguard Worker
pack8888__anon204fc45b0111::BC_color::Color80*03ce13f7SAndroid Build Coastguard Worker unsigned int pack8888() const
81*03ce13f7SAndroid Build Coastguard Worker {
82*03ce13f7SAndroid Build Coastguard Worker return ((c[2] & 0xFF) << 16) | ((c[1] & 0xFF) << 8) | (c[0] & 0xFF) | c[3];
83*03ce13f7SAndroid Build Coastguard Worker }
84*03ce13f7SAndroid Build Coastguard Worker
clearAlpha__anon204fc45b0111::BC_color::Color85*03ce13f7SAndroid Build Coastguard Worker void clearAlpha()
86*03ce13f7SAndroid Build Coastguard Worker {
87*03ce13f7SAndroid Build Coastguard Worker c[3] = 0;
88*03ce13f7SAndroid Build Coastguard Worker }
89*03ce13f7SAndroid Build Coastguard Worker
operator *__anon204fc45b0111::BC_color::Color90*03ce13f7SAndroid Build Coastguard Worker Color operator*(int factor) const
91*03ce13f7SAndroid Build Coastguard Worker {
92*03ce13f7SAndroid Build Coastguard Worker Color res;
93*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < 4; ++i)
94*03ce13f7SAndroid Build Coastguard Worker {
95*03ce13f7SAndroid Build Coastguard Worker res.c[i] = c[i] * factor;
96*03ce13f7SAndroid Build Coastguard Worker }
97*03ce13f7SAndroid Build Coastguard Worker return res;
98*03ce13f7SAndroid Build Coastguard Worker }
99*03ce13f7SAndroid Build Coastguard Worker
operator /__anon204fc45b0111::BC_color::Color100*03ce13f7SAndroid Build Coastguard Worker Color operator/(int factor) const
101*03ce13f7SAndroid Build Coastguard Worker {
102*03ce13f7SAndroid Build Coastguard Worker Color res;
103*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < 4; ++i)
104*03ce13f7SAndroid Build Coastguard Worker {
105*03ce13f7SAndroid Build Coastguard Worker res.c[i] = c[i] / factor;
106*03ce13f7SAndroid Build Coastguard Worker }
107*03ce13f7SAndroid Build Coastguard Worker return res;
108*03ce13f7SAndroid Build Coastguard Worker }
109*03ce13f7SAndroid Build Coastguard Worker
operator >>__anon204fc45b0111::BC_color::Color110*03ce13f7SAndroid Build Coastguard Worker Color operator>>(int shift) const
111*03ce13f7SAndroid Build Coastguard Worker {
112*03ce13f7SAndroid Build Coastguard Worker Color res;
113*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < 4; ++i)
114*03ce13f7SAndroid Build Coastguard Worker {
115*03ce13f7SAndroid Build Coastguard Worker res.c[i] = c[i] >> shift;
116*03ce13f7SAndroid Build Coastguard Worker }
117*03ce13f7SAndroid Build Coastguard Worker return res;
118*03ce13f7SAndroid Build Coastguard Worker }
119*03ce13f7SAndroid Build Coastguard Worker
operator +__anon204fc45b0111::BC_color::Color120*03ce13f7SAndroid Build Coastguard Worker Color operator+(const Color &obj) const
121*03ce13f7SAndroid Build Coastguard Worker {
122*03ce13f7SAndroid Build Coastguard Worker Color res;
123*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < 4; ++i)
124*03ce13f7SAndroid Build Coastguard Worker {
125*03ce13f7SAndroid Build Coastguard Worker res.c[i] = c[i] + obj.c[i];
126*03ce13f7SAndroid Build Coastguard Worker }
127*03ce13f7SAndroid Build Coastguard Worker return res;
128*03ce13f7SAndroid Build Coastguard Worker }
129*03ce13f7SAndroid Build Coastguard Worker
130*03ce13f7SAndroid Build Coastguard Worker private:
131*03ce13f7SAndroid Build Coastguard Worker int c[4];
132*03ce13f7SAndroid Build Coastguard Worker };
133*03ce13f7SAndroid Build Coastguard Worker
getIdx__anon204fc45b0111::BC_color134*03ce13f7SAndroid Build Coastguard Worker unsigned int getIdx(int i) const
135*03ce13f7SAndroid Build Coastguard Worker {
136*03ce13f7SAndroid Build Coastguard Worker int offset = i << 1; // 2 bytes per index
137*03ce13f7SAndroid Build Coastguard Worker return (idx & (0x3 << offset)) >> offset;
138*03ce13f7SAndroid Build Coastguard Worker }
139*03ce13f7SAndroid Build Coastguard Worker
140*03ce13f7SAndroid Build Coastguard Worker unsigned short c0;
141*03ce13f7SAndroid Build Coastguard Worker unsigned short c1;
142*03ce13f7SAndroid Build Coastguard Worker unsigned int idx;
143*03ce13f7SAndroid Build Coastguard Worker };
144*03ce13f7SAndroid Build Coastguard Worker
145*03ce13f7SAndroid Build Coastguard Worker struct BC_channel
146*03ce13f7SAndroid Build Coastguard Worker {
decode__anon204fc45b0111::BC_channel147*03ce13f7SAndroid Build Coastguard Worker void decode(uint8_t *dst, int x, int y, int dstW, int dstH, int dstPitch, int dstBpp, int channel, bool isSigned) const
148*03ce13f7SAndroid Build Coastguard Worker {
149*03ce13f7SAndroid Build Coastguard Worker int c[8] = { 0 };
150*03ce13f7SAndroid Build Coastguard Worker
151*03ce13f7SAndroid Build Coastguard Worker if(isSigned)
152*03ce13f7SAndroid Build Coastguard Worker {
153*03ce13f7SAndroid Build Coastguard Worker c[0] = static_cast<signed char>(data & 0xFF);
154*03ce13f7SAndroid Build Coastguard Worker c[1] = static_cast<signed char>((data & 0xFF00) >> 8);
155*03ce13f7SAndroid Build Coastguard Worker }
156*03ce13f7SAndroid Build Coastguard Worker else
157*03ce13f7SAndroid Build Coastguard Worker {
158*03ce13f7SAndroid Build Coastguard Worker c[0] = static_cast<uint8_t>(data & 0xFF);
159*03ce13f7SAndroid Build Coastguard Worker c[1] = static_cast<uint8_t>((data & 0xFF00) >> 8);
160*03ce13f7SAndroid Build Coastguard Worker }
161*03ce13f7SAndroid Build Coastguard Worker
162*03ce13f7SAndroid Build Coastguard Worker if(c[0] > c[1])
163*03ce13f7SAndroid Build Coastguard Worker {
164*03ce13f7SAndroid Build Coastguard Worker for(int i = 2; i < 8; ++i)
165*03ce13f7SAndroid Build Coastguard Worker {
166*03ce13f7SAndroid Build Coastguard Worker c[i] = ((8 - i) * c[0] + (i - 1) * c[1]) / 7;
167*03ce13f7SAndroid Build Coastguard Worker }
168*03ce13f7SAndroid Build Coastguard Worker }
169*03ce13f7SAndroid Build Coastguard Worker else
170*03ce13f7SAndroid Build Coastguard Worker {
171*03ce13f7SAndroid Build Coastguard Worker for(int i = 2; i < 6; ++i)
172*03ce13f7SAndroid Build Coastguard Worker {
173*03ce13f7SAndroid Build Coastguard Worker c[i] = ((6 - i) * c[0] + (i - 1) * c[1]) / 5;
174*03ce13f7SAndroid Build Coastguard Worker }
175*03ce13f7SAndroid Build Coastguard Worker c[6] = isSigned ? -128 : 0;
176*03ce13f7SAndroid Build Coastguard Worker c[7] = isSigned ? 127 : 255;
177*03ce13f7SAndroid Build Coastguard Worker }
178*03ce13f7SAndroid Build Coastguard Worker
179*03ce13f7SAndroid Build Coastguard Worker for(int j = 0; j < BlockHeight && (y + j) < dstH; j++)
180*03ce13f7SAndroid Build Coastguard Worker {
181*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < BlockWidth && (x + i) < dstW; i++)
182*03ce13f7SAndroid Build Coastguard Worker {
183*03ce13f7SAndroid Build Coastguard Worker dst[channel + (i * dstBpp) + (j * dstPitch)] = static_cast<uint8_t>(c[getIdx((j * BlockHeight) + i)]);
184*03ce13f7SAndroid Build Coastguard Worker }
185*03ce13f7SAndroid Build Coastguard Worker }
186*03ce13f7SAndroid Build Coastguard Worker }
187*03ce13f7SAndroid Build Coastguard Worker
188*03ce13f7SAndroid Build Coastguard Worker private:
getIdx__anon204fc45b0111::BC_channel189*03ce13f7SAndroid Build Coastguard Worker uint8_t getIdx(int i) const
190*03ce13f7SAndroid Build Coastguard Worker {
191*03ce13f7SAndroid Build Coastguard Worker int offset = i * 3 + 16;
192*03ce13f7SAndroid Build Coastguard Worker return static_cast<uint8_t>((data & (0x7ull << offset)) >> offset);
193*03ce13f7SAndroid Build Coastguard Worker }
194*03ce13f7SAndroid Build Coastguard Worker
195*03ce13f7SAndroid Build Coastguard Worker uint64_t data;
196*03ce13f7SAndroid Build Coastguard Worker };
197*03ce13f7SAndroid Build Coastguard Worker
198*03ce13f7SAndroid Build Coastguard Worker struct BC_alpha
199*03ce13f7SAndroid Build Coastguard Worker {
decode__anon204fc45b0111::BC_alpha200*03ce13f7SAndroid Build Coastguard Worker void decode(uint8_t *dst, int x, int y, int dstW, int dstH, int dstPitch, int dstBpp) const
201*03ce13f7SAndroid Build Coastguard Worker {
202*03ce13f7SAndroid Build Coastguard Worker dst += 3; // Write only to alpha (channel 3)
203*03ce13f7SAndroid Build Coastguard Worker for(int j = 0; j < BlockHeight && (y + j) < dstH; j++, dst += dstPitch)
204*03ce13f7SAndroid Build Coastguard Worker {
205*03ce13f7SAndroid Build Coastguard Worker uint8_t *dstRow = dst;
206*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < BlockWidth && (x + i) < dstW; i++, dstRow += dstBpp)
207*03ce13f7SAndroid Build Coastguard Worker {
208*03ce13f7SAndroid Build Coastguard Worker *dstRow = getAlpha(j * BlockHeight + i);
209*03ce13f7SAndroid Build Coastguard Worker }
210*03ce13f7SAndroid Build Coastguard Worker }
211*03ce13f7SAndroid Build Coastguard Worker }
212*03ce13f7SAndroid Build Coastguard Worker
213*03ce13f7SAndroid Build Coastguard Worker private:
getAlpha__anon204fc45b0111::BC_alpha214*03ce13f7SAndroid Build Coastguard Worker uint8_t getAlpha(int i) const
215*03ce13f7SAndroid Build Coastguard Worker {
216*03ce13f7SAndroid Build Coastguard Worker int offset = i << 2;
217*03ce13f7SAndroid Build Coastguard Worker int alpha = (data & (0xFull << offset)) >> offset;
218*03ce13f7SAndroid Build Coastguard Worker return static_cast<uint8_t>(alpha | (alpha << 4));
219*03ce13f7SAndroid Build Coastguard Worker }
220*03ce13f7SAndroid Build Coastguard Worker
221*03ce13f7SAndroid Build Coastguard Worker uint64_t data;
222*03ce13f7SAndroid Build Coastguard Worker };
223*03ce13f7SAndroid Build Coastguard Worker
224*03ce13f7SAndroid Build Coastguard Worker namespace BC6H {
225*03ce13f7SAndroid Build Coastguard Worker
226*03ce13f7SAndroid Build Coastguard Worker static constexpr int MaxPartitions = 64;
227*03ce13f7SAndroid Build Coastguard Worker
228*03ce13f7SAndroid Build Coastguard Worker static constexpr uint8_t PartitionTable2[MaxPartitions][16] = {
229*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 },
230*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 },
231*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
232*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 },
233*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 },
234*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
235*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
236*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1 },
237*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1 },
238*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
239*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
240*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 },
241*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
242*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
243*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
244*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 },
245*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1 },
246*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
247*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 },
248*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
249*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
250*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 },
251*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 },
252*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 },
253*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
254*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 },
255*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0 },
256*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0 },
257*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 },
258*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
259*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0 },
260*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 },
261*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 },
262*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 },
263*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0 },
264*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0 },
265*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 },
266*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 },
267*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 },
268*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 },
269*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0 },
270*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 },
271*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 },
272*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0 },
273*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 },
274*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 },
275*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 },
276*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
277*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
278*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 },
279*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0 },
280*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0 },
281*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 },
282*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1 },
283*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0 },
284*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0 },
285*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 },
286*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1 },
287*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 },
288*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1 },
289*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 },
290*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
291*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0 },
292*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1 },
293*03ce13f7SAndroid Build Coastguard Worker };
294*03ce13f7SAndroid Build Coastguard Worker
295*03ce13f7SAndroid Build Coastguard Worker static constexpr uint8_t AnchorTable2[MaxPartitions] = {
296*03ce13f7SAndroid Build Coastguard Worker // clang-format off
297*03ce13f7SAndroid Build Coastguard Worker 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
298*03ce13f7SAndroid Build Coastguard Worker 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
299*03ce13f7SAndroid Build Coastguard Worker 0xf, 0x2, 0x8, 0x2, 0x2, 0x8, 0x8, 0xf,
300*03ce13f7SAndroid Build Coastguard Worker 0x2, 0x8, 0x2, 0x2, 0x8, 0x8, 0x2, 0x2,
301*03ce13f7SAndroid Build Coastguard Worker 0xf, 0xf, 0x6, 0x8, 0x2, 0x8, 0xf, 0xf,
302*03ce13f7SAndroid Build Coastguard Worker 0x2, 0x8, 0x2, 0x2, 0x2, 0xf, 0xf, 0x6,
303*03ce13f7SAndroid Build Coastguard Worker 0x6, 0x2, 0x6, 0x8, 0xf, 0xf, 0x2, 0x2,
304*03ce13f7SAndroid Build Coastguard Worker 0xf, 0xf, 0xf, 0xf, 0xf, 0x2, 0x2, 0xf,
305*03ce13f7SAndroid Build Coastguard Worker // clang-format on
306*03ce13f7SAndroid Build Coastguard Worker };
307*03ce13f7SAndroid Build Coastguard Worker
308*03ce13f7SAndroid Build Coastguard Worker // 1.0f in half-precision floating point format
309*03ce13f7SAndroid Build Coastguard Worker static constexpr uint16_t halfFloat1 = 0x3C00;
310*03ce13f7SAndroid Build Coastguard Worker union Color
311*03ce13f7SAndroid Build Coastguard Worker {
312*03ce13f7SAndroid Build Coastguard Worker struct RGBA
313*03ce13f7SAndroid Build Coastguard Worker {
314*03ce13f7SAndroid Build Coastguard Worker uint16_t r = 0;
315*03ce13f7SAndroid Build Coastguard Worker uint16_t g = 0;
316*03ce13f7SAndroid Build Coastguard Worker uint16_t b = 0;
317*03ce13f7SAndroid Build Coastguard Worker uint16_t a = halfFloat1;
318*03ce13f7SAndroid Build Coastguard Worker
RGBA__anon204fc45b0111::BC6H::Color::RGBA319*03ce13f7SAndroid Build Coastguard Worker RGBA(uint16_t r, uint16_t g, uint16_t b)
320*03ce13f7SAndroid Build Coastguard Worker : r(r)
321*03ce13f7SAndroid Build Coastguard Worker , g(g)
322*03ce13f7SAndroid Build Coastguard Worker , b(b)
323*03ce13f7SAndroid Build Coastguard Worker {
324*03ce13f7SAndroid Build Coastguard Worker }
325*03ce13f7SAndroid Build Coastguard Worker
operator =__anon204fc45b0111::BC6H::Color::RGBA326*03ce13f7SAndroid Build Coastguard Worker RGBA &operator=(const RGBA &other)
327*03ce13f7SAndroid Build Coastguard Worker {
328*03ce13f7SAndroid Build Coastguard Worker this->r = other.r;
329*03ce13f7SAndroid Build Coastguard Worker this->g = other.g;
330*03ce13f7SAndroid Build Coastguard Worker this->b = other.b;
331*03ce13f7SAndroid Build Coastguard Worker this->a = halfFloat1;
332*03ce13f7SAndroid Build Coastguard Worker
333*03ce13f7SAndroid Build Coastguard Worker return *this;
334*03ce13f7SAndroid Build Coastguard Worker }
335*03ce13f7SAndroid Build Coastguard Worker };
336*03ce13f7SAndroid Build Coastguard Worker
Color(uint16_t r,uint16_t g,uint16_t b)337*03ce13f7SAndroid Build Coastguard Worker Color(uint16_t r, uint16_t g, uint16_t b)
338*03ce13f7SAndroid Build Coastguard Worker : rgba(r, g, b)
339*03ce13f7SAndroid Build Coastguard Worker {
340*03ce13f7SAndroid Build Coastguard Worker }
341*03ce13f7SAndroid Build Coastguard Worker
Color(int r,int g,int b)342*03ce13f7SAndroid Build Coastguard Worker Color(int r, int g, int b)
343*03ce13f7SAndroid Build Coastguard Worker : rgba((uint16_t)r, (uint16_t)g, (uint16_t)b)
344*03ce13f7SAndroid Build Coastguard Worker {
345*03ce13f7SAndroid Build Coastguard Worker }
346*03ce13f7SAndroid Build Coastguard Worker
Color()347*03ce13f7SAndroid Build Coastguard Worker Color()
348*03ce13f7SAndroid Build Coastguard Worker {
349*03ce13f7SAndroid Build Coastguard Worker }
350*03ce13f7SAndroid Build Coastguard Worker
Color(const Color & other)351*03ce13f7SAndroid Build Coastguard Worker Color(const Color &other)
352*03ce13f7SAndroid Build Coastguard Worker {
353*03ce13f7SAndroid Build Coastguard Worker this->rgba = other.rgba;
354*03ce13f7SAndroid Build Coastguard Worker }
355*03ce13f7SAndroid Build Coastguard Worker
operator =(const Color & other)356*03ce13f7SAndroid Build Coastguard Worker Color &operator=(const Color &other)
357*03ce13f7SAndroid Build Coastguard Worker {
358*03ce13f7SAndroid Build Coastguard Worker this->rgba = other.rgba;
359*03ce13f7SAndroid Build Coastguard Worker
360*03ce13f7SAndroid Build Coastguard Worker return *this;
361*03ce13f7SAndroid Build Coastguard Worker }
362*03ce13f7SAndroid Build Coastguard Worker
363*03ce13f7SAndroid Build Coastguard Worker RGBA rgba;
364*03ce13f7SAndroid Build Coastguard Worker uint16_t channel[4];
365*03ce13f7SAndroid Build Coastguard Worker };
366*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(Color) == 8, "BC6h::Color must be 8 bytes long");
367*03ce13f7SAndroid Build Coastguard Worker
extendSign(int32_t val,size_t size)368*03ce13f7SAndroid Build Coastguard Worker inline int32_t extendSign(int32_t val, size_t size)
369*03ce13f7SAndroid Build Coastguard Worker {
370*03ce13f7SAndroid Build Coastguard Worker // Suppose we have a 2-bit integer being stored in 4 bit variable:
371*03ce13f7SAndroid Build Coastguard Worker // x = 0b00AB
372*03ce13f7SAndroid Build Coastguard Worker //
373*03ce13f7SAndroid Build Coastguard Worker // In order to sign extend x, we need to turn the 0s into A's:
374*03ce13f7SAndroid Build Coastguard Worker // x_extend = 0bAAAB
375*03ce13f7SAndroid Build Coastguard Worker //
376*03ce13f7SAndroid Build Coastguard Worker // We can do that by flipping A in x then subtracting 0b0010 from x.
377*03ce13f7SAndroid Build Coastguard Worker // Suppose A is 1:
378*03ce13f7SAndroid Build Coastguard Worker // x = 0b001B
379*03ce13f7SAndroid Build Coastguard Worker // x_flip = 0b000B
380*03ce13f7SAndroid Build Coastguard Worker // x_minus = 0b111B
381*03ce13f7SAndroid Build Coastguard Worker // Since A is flipped to 0, subtracting the mask sets it and all the bits above it to 1.
382*03ce13f7SAndroid Build Coastguard Worker // And if A is 0:
383*03ce13f7SAndroid Build Coastguard Worker // x = 0b000B
384*03ce13f7SAndroid Build Coastguard Worker // x_flip = 0b001B
385*03ce13f7SAndroid Build Coastguard Worker // x_minus = 0b000B
386*03ce13f7SAndroid Build Coastguard Worker // We unset the bit we flipped, and touch no other bit
387*03ce13f7SAndroid Build Coastguard Worker uint16_t mask = 1u << (size - 1);
388*03ce13f7SAndroid Build Coastguard Worker return (val ^ mask) - mask;
389*03ce13f7SAndroid Build Coastguard Worker }
390*03ce13f7SAndroid Build Coastguard Worker
391*03ce13f7SAndroid Build Coastguard Worker static int constexpr RGBfChannels = 3;
392*03ce13f7SAndroid Build Coastguard Worker struct RGBf
393*03ce13f7SAndroid Build Coastguard Worker {
394*03ce13f7SAndroid Build Coastguard Worker uint16_t channel[RGBfChannels];
395*03ce13f7SAndroid Build Coastguard Worker size_t size[RGBfChannels];
396*03ce13f7SAndroid Build Coastguard Worker bool isSigned;
397*03ce13f7SAndroid Build Coastguard Worker
RGBf__anon204fc45b0111::BC6H::RGBf398*03ce13f7SAndroid Build Coastguard Worker RGBf()
399*03ce13f7SAndroid Build Coastguard Worker {
400*03ce13f7SAndroid Build Coastguard Worker static_assert(RGBfChannels == 3, "RGBf must have exactly 3 channels");
401*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(channel) / sizeof(channel[0]) == RGBfChannels, "RGBf must have exactly 3 channels");
402*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(channel) / sizeof(channel[0]) == sizeof(size) / sizeof(size[0]), "RGBf requires equally sized arrays for channels and channel sizes");
403*03ce13f7SAndroid Build Coastguard Worker
404*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < RGBfChannels; i++)
405*03ce13f7SAndroid Build Coastguard Worker {
406*03ce13f7SAndroid Build Coastguard Worker channel[i] = 0;
407*03ce13f7SAndroid Build Coastguard Worker size[i] = 0;
408*03ce13f7SAndroid Build Coastguard Worker }
409*03ce13f7SAndroid Build Coastguard Worker
410*03ce13f7SAndroid Build Coastguard Worker isSigned = false;
411*03ce13f7SAndroid Build Coastguard Worker }
412*03ce13f7SAndroid Build Coastguard Worker
extendSign__anon204fc45b0111::BC6H::RGBf413*03ce13f7SAndroid Build Coastguard Worker void extendSign()
414*03ce13f7SAndroid Build Coastguard Worker {
415*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < RGBfChannels; i++)
416*03ce13f7SAndroid Build Coastguard Worker {
417*03ce13f7SAndroid Build Coastguard Worker channel[i] = BC6H::extendSign(channel[i], size[i]);
418*03ce13f7SAndroid Build Coastguard Worker }
419*03ce13f7SAndroid Build Coastguard Worker }
420*03ce13f7SAndroid Build Coastguard Worker
421*03ce13f7SAndroid Build Coastguard Worker // Assuming this is the delta, take the base-endpoint and transform this into
422*03ce13f7SAndroid Build Coastguard Worker // a proper endpoint.
423*03ce13f7SAndroid Build Coastguard Worker //
424*03ce13f7SAndroid Build Coastguard Worker // The final computed endpoint is truncated to the base-endpoint's size;
resolveDelta__anon204fc45b0111::BC6H::RGBf425*03ce13f7SAndroid Build Coastguard Worker void resolveDelta(RGBf base)
426*03ce13f7SAndroid Build Coastguard Worker {
427*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < RGBfChannels; i++)
428*03ce13f7SAndroid Build Coastguard Worker {
429*03ce13f7SAndroid Build Coastguard Worker size[i] = base.size[i];
430*03ce13f7SAndroid Build Coastguard Worker channel[i] = (base.channel[i] + channel[i]) & ((1 << base.size[i]) - 1);
431*03ce13f7SAndroid Build Coastguard Worker }
432*03ce13f7SAndroid Build Coastguard Worker
433*03ce13f7SAndroid Build Coastguard Worker // Per the spec:
434*03ce13f7SAndroid Build Coastguard Worker // "For signed formats, the results of the delta calculation must be sign
435*03ce13f7SAndroid Build Coastguard Worker // extended as well."
436*03ce13f7SAndroid Build Coastguard Worker if(isSigned)
437*03ce13f7SAndroid Build Coastguard Worker {
438*03ce13f7SAndroid Build Coastguard Worker extendSign();
439*03ce13f7SAndroid Build Coastguard Worker }
440*03ce13f7SAndroid Build Coastguard Worker }
441*03ce13f7SAndroid Build Coastguard Worker
unquantize__anon204fc45b0111::BC6H::RGBf442*03ce13f7SAndroid Build Coastguard Worker void unquantize()
443*03ce13f7SAndroid Build Coastguard Worker {
444*03ce13f7SAndroid Build Coastguard Worker if(isSigned)
445*03ce13f7SAndroid Build Coastguard Worker {
446*03ce13f7SAndroid Build Coastguard Worker unquantizeSigned();
447*03ce13f7SAndroid Build Coastguard Worker }
448*03ce13f7SAndroid Build Coastguard Worker else
449*03ce13f7SAndroid Build Coastguard Worker {
450*03ce13f7SAndroid Build Coastguard Worker unquantizeUnsigned();
451*03ce13f7SAndroid Build Coastguard Worker }
452*03ce13f7SAndroid Build Coastguard Worker }
453*03ce13f7SAndroid Build Coastguard Worker
unquantizeUnsigned__anon204fc45b0111::BC6H::RGBf454*03ce13f7SAndroid Build Coastguard Worker void unquantizeUnsigned()
455*03ce13f7SAndroid Build Coastguard Worker {
456*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < RGBfChannels; i++)
457*03ce13f7SAndroid Build Coastguard Worker {
458*03ce13f7SAndroid Build Coastguard Worker if(size[i] >= 15 || channel[i] == 0)
459*03ce13f7SAndroid Build Coastguard Worker {
460*03ce13f7SAndroid Build Coastguard Worker continue;
461*03ce13f7SAndroid Build Coastguard Worker }
462*03ce13f7SAndroid Build Coastguard Worker else if(channel[i] == ((1u << size[i]) - 1))
463*03ce13f7SAndroid Build Coastguard Worker {
464*03ce13f7SAndroid Build Coastguard Worker channel[i] = 0xFFFFu;
465*03ce13f7SAndroid Build Coastguard Worker }
466*03ce13f7SAndroid Build Coastguard Worker else
467*03ce13f7SAndroid Build Coastguard Worker {
468*03ce13f7SAndroid Build Coastguard Worker // Need 32 bits to avoid overflow
469*03ce13f7SAndroid Build Coastguard Worker uint32_t tmp = channel[i];
470*03ce13f7SAndroid Build Coastguard Worker channel[i] = (uint16_t)(((tmp << 16) + 0x8000) >> size[i]);
471*03ce13f7SAndroid Build Coastguard Worker }
472*03ce13f7SAndroid Build Coastguard Worker size[i] = 16;
473*03ce13f7SAndroid Build Coastguard Worker }
474*03ce13f7SAndroid Build Coastguard Worker }
475*03ce13f7SAndroid Build Coastguard Worker
unquantizeSigned__anon204fc45b0111::BC6H::RGBf476*03ce13f7SAndroid Build Coastguard Worker void unquantizeSigned()
477*03ce13f7SAndroid Build Coastguard Worker {
478*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < RGBfChannels; i++)
479*03ce13f7SAndroid Build Coastguard Worker {
480*03ce13f7SAndroid Build Coastguard Worker if(size[i] >= 16 || channel[i] == 0)
481*03ce13f7SAndroid Build Coastguard Worker {
482*03ce13f7SAndroid Build Coastguard Worker continue;
483*03ce13f7SAndroid Build Coastguard Worker }
484*03ce13f7SAndroid Build Coastguard Worker
485*03ce13f7SAndroid Build Coastguard Worker int16_t value = sw::bit_cast<int16_t>(channel[i]);
486*03ce13f7SAndroid Build Coastguard Worker int32_t result = value;
487*03ce13f7SAndroid Build Coastguard Worker bool signBit = value < 0;
488*03ce13f7SAndroid Build Coastguard Worker if(signBit)
489*03ce13f7SAndroid Build Coastguard Worker {
490*03ce13f7SAndroid Build Coastguard Worker value = -value;
491*03ce13f7SAndroid Build Coastguard Worker }
492*03ce13f7SAndroid Build Coastguard Worker
493*03ce13f7SAndroid Build Coastguard Worker if(value >= ((1 << (size[i] - 1)) - 1))
494*03ce13f7SAndroid Build Coastguard Worker {
495*03ce13f7SAndroid Build Coastguard Worker result = 0x7FFF;
496*03ce13f7SAndroid Build Coastguard Worker }
497*03ce13f7SAndroid Build Coastguard Worker else
498*03ce13f7SAndroid Build Coastguard Worker {
499*03ce13f7SAndroid Build Coastguard Worker // Need 32 bits to avoid overflow
500*03ce13f7SAndroid Build Coastguard Worker int32_t tmp = value;
501*03ce13f7SAndroid Build Coastguard Worker result = (((tmp << 15) + 0x4000) >> (size[i] - 1));
502*03ce13f7SAndroid Build Coastguard Worker }
503*03ce13f7SAndroid Build Coastguard Worker
504*03ce13f7SAndroid Build Coastguard Worker if(signBit)
505*03ce13f7SAndroid Build Coastguard Worker {
506*03ce13f7SAndroid Build Coastguard Worker result = -result;
507*03ce13f7SAndroid Build Coastguard Worker }
508*03ce13f7SAndroid Build Coastguard Worker
509*03ce13f7SAndroid Build Coastguard Worker channel[i] = (uint16_t)result;
510*03ce13f7SAndroid Build Coastguard Worker size[i] = 16;
511*03ce13f7SAndroid Build Coastguard Worker }
512*03ce13f7SAndroid Build Coastguard Worker }
513*03ce13f7SAndroid Build Coastguard Worker };
514*03ce13f7SAndroid Build Coastguard Worker
515*03ce13f7SAndroid Build Coastguard Worker struct Data
516*03ce13f7SAndroid Build Coastguard Worker {
517*03ce13f7SAndroid Build Coastguard Worker uint64_t low64;
518*03ce13f7SAndroid Build Coastguard Worker uint64_t high64;
519*03ce13f7SAndroid Build Coastguard Worker
520*03ce13f7SAndroid Build Coastguard Worker Data() = default;
Data__anon204fc45b0111::BC6H::Data521*03ce13f7SAndroid Build Coastguard Worker Data(uint64_t low64, uint64_t high64)
522*03ce13f7SAndroid Build Coastguard Worker : low64(low64)
523*03ce13f7SAndroid Build Coastguard Worker , high64(high64)
524*03ce13f7SAndroid Build Coastguard Worker {
525*03ce13f7SAndroid Build Coastguard Worker }
526*03ce13f7SAndroid Build Coastguard Worker
527*03ce13f7SAndroid Build Coastguard Worker // Consumes the lowest N bits from from low64 and high64 where N is:
528*03ce13f7SAndroid Build Coastguard Worker // abs(MSB - LSB)
529*03ce13f7SAndroid Build Coastguard Worker // MSB and LSB come from the block description of the BC6h spec and specify
530*03ce13f7SAndroid Build Coastguard Worker // the location of the bits in the returned bitstring.
531*03ce13f7SAndroid Build Coastguard Worker //
532*03ce13f7SAndroid Build Coastguard Worker // If MSB < LSB, then the bits are reversed. Otherwise, the bitstring is read and
533*03ce13f7SAndroid Build Coastguard Worker // shifted without further modification.
534*03ce13f7SAndroid Build Coastguard Worker //
consumeBits__anon204fc45b0111::BC6H::Data535*03ce13f7SAndroid Build Coastguard Worker uint32_t consumeBits(uint32_t MSB, uint32_t LSB)
536*03ce13f7SAndroid Build Coastguard Worker {
537*03ce13f7SAndroid Build Coastguard Worker bool reversed = MSB < LSB;
538*03ce13f7SAndroid Build Coastguard Worker if(reversed)
539*03ce13f7SAndroid Build Coastguard Worker {
540*03ce13f7SAndroid Build Coastguard Worker std::swap(MSB, LSB);
541*03ce13f7SAndroid Build Coastguard Worker }
542*03ce13f7SAndroid Build Coastguard Worker ASSERT(MSB - LSB + 1 < sizeof(uint32_t) * 8);
543*03ce13f7SAndroid Build Coastguard Worker
544*03ce13f7SAndroid Build Coastguard Worker uint32_t numBits = MSB - LSB + 1;
545*03ce13f7SAndroid Build Coastguard Worker uint32_t mask = (1 << numBits) - 1;
546*03ce13f7SAndroid Build Coastguard Worker // Read the low N bits
547*03ce13f7SAndroid Build Coastguard Worker uint32_t bits = (low64 & mask);
548*03ce13f7SAndroid Build Coastguard Worker
549*03ce13f7SAndroid Build Coastguard Worker low64 >>= numBits;
550*03ce13f7SAndroid Build Coastguard Worker // Put the low N bits of high64 into the high 64-N bits of low64
551*03ce13f7SAndroid Build Coastguard Worker low64 |= (high64 & mask) << (sizeof(high64) * 8 - numBits);
552*03ce13f7SAndroid Build Coastguard Worker high64 >>= numBits;
553*03ce13f7SAndroid Build Coastguard Worker
554*03ce13f7SAndroid Build Coastguard Worker if(reversed)
555*03ce13f7SAndroid Build Coastguard Worker {
556*03ce13f7SAndroid Build Coastguard Worker uint32_t tmp = 0;
557*03ce13f7SAndroid Build Coastguard Worker for(uint32_t numSwaps = 0; numSwaps < numBits; numSwaps++)
558*03ce13f7SAndroid Build Coastguard Worker {
559*03ce13f7SAndroid Build Coastguard Worker tmp <<= 1;
560*03ce13f7SAndroid Build Coastguard Worker tmp |= (bits & 1);
561*03ce13f7SAndroid Build Coastguard Worker bits >>= 1;
562*03ce13f7SAndroid Build Coastguard Worker }
563*03ce13f7SAndroid Build Coastguard Worker
564*03ce13f7SAndroid Build Coastguard Worker bits = tmp;
565*03ce13f7SAndroid Build Coastguard Worker }
566*03ce13f7SAndroid Build Coastguard Worker
567*03ce13f7SAndroid Build Coastguard Worker return bits << LSB;
568*03ce13f7SAndroid Build Coastguard Worker }
569*03ce13f7SAndroid Build Coastguard Worker };
570*03ce13f7SAndroid Build Coastguard Worker
571*03ce13f7SAndroid Build Coastguard Worker struct IndexInfo
572*03ce13f7SAndroid Build Coastguard Worker {
573*03ce13f7SAndroid Build Coastguard Worker uint64_t value;
574*03ce13f7SAndroid Build Coastguard Worker int numBits;
575*03ce13f7SAndroid Build Coastguard Worker };
576*03ce13f7SAndroid Build Coastguard Worker
577*03ce13f7SAndroid Build Coastguard Worker // Interpolates between two endpoints, then does a final unquantization step
interpolate(RGBf e0,RGBf e1,const IndexInfo & index,bool isSigned)578*03ce13f7SAndroid Build Coastguard Worker Color interpolate(RGBf e0, RGBf e1, const IndexInfo &index, bool isSigned)
579*03ce13f7SAndroid Build Coastguard Worker {
580*03ce13f7SAndroid Build Coastguard Worker static constexpr uint32_t weights3[] = { 0, 9, 18, 27, 37, 46, 55, 64 };
581*03ce13f7SAndroid Build Coastguard Worker static constexpr uint32_t weights4[] = { 0, 4, 9, 13, 17, 21, 26, 30,
582*03ce13f7SAndroid Build Coastguard Worker 34, 38, 43, 47, 51, 55, 60, 64 };
583*03ce13f7SAndroid Build Coastguard Worker static const uint32_t constexpr *weightsN[] = {
584*03ce13f7SAndroid Build Coastguard Worker nullptr, nullptr, nullptr, weights3, weights4
585*03ce13f7SAndroid Build Coastguard Worker };
586*03ce13f7SAndroid Build Coastguard Worker const uint32_t *weights = weightsN[index.numBits];
587*03ce13f7SAndroid Build Coastguard Worker ASSERT_MSG(weights != nullptr, "Unexpected number of index bits: %d", (int)index.numBits);
588*03ce13f7SAndroid Build Coastguard Worker Color color;
589*03ce13f7SAndroid Build Coastguard Worker uint32_t e0Weight = 64 - weights[index.value];
590*03ce13f7SAndroid Build Coastguard Worker uint32_t e1Weight = weights[index.value];
591*03ce13f7SAndroid Build Coastguard Worker
592*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < RGBfChannels; i++)
593*03ce13f7SAndroid Build Coastguard Worker {
594*03ce13f7SAndroid Build Coastguard Worker int32_t e0Channel = e0.channel[i];
595*03ce13f7SAndroid Build Coastguard Worker int32_t e1Channel = e1.channel[i];
596*03ce13f7SAndroid Build Coastguard Worker
597*03ce13f7SAndroid Build Coastguard Worker if(isSigned)
598*03ce13f7SAndroid Build Coastguard Worker {
599*03ce13f7SAndroid Build Coastguard Worker e0Channel = extendSign(e0Channel, 16);
600*03ce13f7SAndroid Build Coastguard Worker e1Channel = extendSign(e1Channel, 16);
601*03ce13f7SAndroid Build Coastguard Worker }
602*03ce13f7SAndroid Build Coastguard Worker
603*03ce13f7SAndroid Build Coastguard Worker int32_t e0Value = e0Channel * e0Weight;
604*03ce13f7SAndroid Build Coastguard Worker int32_t e1Value = e1Channel * e1Weight;
605*03ce13f7SAndroid Build Coastguard Worker
606*03ce13f7SAndroid Build Coastguard Worker uint32_t tmp = ((e0Value + e1Value + 32) >> 6);
607*03ce13f7SAndroid Build Coastguard Worker
608*03ce13f7SAndroid Build Coastguard Worker // Need to unquantize value to limit it to the legal range of half-precision
609*03ce13f7SAndroid Build Coastguard Worker // floats. We do this by scaling by 31/32 or 31/64 depending on if the value
610*03ce13f7SAndroid Build Coastguard Worker // is signed or unsigned.
611*03ce13f7SAndroid Build Coastguard Worker if(isSigned)
612*03ce13f7SAndroid Build Coastguard Worker {
613*03ce13f7SAndroid Build Coastguard Worker tmp = ((tmp & 0x80000000) != 0) ? (((~tmp + 1) * 31) >> 5) | 0x8000 : (tmp * 31) >> 5;
614*03ce13f7SAndroid Build Coastguard Worker // Don't return -0.0f, just normalize it to 0.0f.
615*03ce13f7SAndroid Build Coastguard Worker if(tmp == 0x8000)
616*03ce13f7SAndroid Build Coastguard Worker tmp = 0;
617*03ce13f7SAndroid Build Coastguard Worker }
618*03ce13f7SAndroid Build Coastguard Worker else
619*03ce13f7SAndroid Build Coastguard Worker {
620*03ce13f7SAndroid Build Coastguard Worker tmp = (tmp * 31) >> 6;
621*03ce13f7SAndroid Build Coastguard Worker }
622*03ce13f7SAndroid Build Coastguard Worker
623*03ce13f7SAndroid Build Coastguard Worker color.channel[i] = (uint16_t)tmp;
624*03ce13f7SAndroid Build Coastguard Worker }
625*03ce13f7SAndroid Build Coastguard Worker
626*03ce13f7SAndroid Build Coastguard Worker return color;
627*03ce13f7SAndroid Build Coastguard Worker }
628*03ce13f7SAndroid Build Coastguard Worker
629*03ce13f7SAndroid Build Coastguard Worker enum DataType
630*03ce13f7SAndroid Build Coastguard Worker {
631*03ce13f7SAndroid Build Coastguard Worker // Endpoints
632*03ce13f7SAndroid Build Coastguard Worker EP0 = 0,
633*03ce13f7SAndroid Build Coastguard Worker EP1 = 1,
634*03ce13f7SAndroid Build Coastguard Worker EP2 = 2,
635*03ce13f7SAndroid Build Coastguard Worker EP3 = 3,
636*03ce13f7SAndroid Build Coastguard Worker Mode,
637*03ce13f7SAndroid Build Coastguard Worker Partition,
638*03ce13f7SAndroid Build Coastguard Worker End,
639*03ce13f7SAndroid Build Coastguard Worker };
640*03ce13f7SAndroid Build Coastguard Worker
641*03ce13f7SAndroid Build Coastguard Worker enum Channel
642*03ce13f7SAndroid Build Coastguard Worker {
643*03ce13f7SAndroid Build Coastguard Worker R = 0,
644*03ce13f7SAndroid Build Coastguard Worker G = 1,
645*03ce13f7SAndroid Build Coastguard Worker B = 2,
646*03ce13f7SAndroid Build Coastguard Worker None,
647*03ce13f7SAndroid Build Coastguard Worker };
648*03ce13f7SAndroid Build Coastguard Worker
649*03ce13f7SAndroid Build Coastguard Worker struct DeltaBits
650*03ce13f7SAndroid Build Coastguard Worker {
651*03ce13f7SAndroid Build Coastguard Worker size_t channel[3];
652*03ce13f7SAndroid Build Coastguard Worker
DeltaBits__anon204fc45b0111::BC6H::DeltaBits653*03ce13f7SAndroid Build Coastguard Worker constexpr DeltaBits()
654*03ce13f7SAndroid Build Coastguard Worker : channel{ 0, 0, 0 }
655*03ce13f7SAndroid Build Coastguard Worker {
656*03ce13f7SAndroid Build Coastguard Worker }
657*03ce13f7SAndroid Build Coastguard Worker
DeltaBits__anon204fc45b0111::BC6H::DeltaBits658*03ce13f7SAndroid Build Coastguard Worker constexpr DeltaBits(size_t r, size_t g, size_t b)
659*03ce13f7SAndroid Build Coastguard Worker : channel{ r, g, b }
660*03ce13f7SAndroid Build Coastguard Worker {
661*03ce13f7SAndroid Build Coastguard Worker }
662*03ce13f7SAndroid Build Coastguard Worker };
663*03ce13f7SAndroid Build Coastguard Worker
664*03ce13f7SAndroid Build Coastguard Worker struct ModeDesc
665*03ce13f7SAndroid Build Coastguard Worker {
666*03ce13f7SAndroid Build Coastguard Worker int number;
667*03ce13f7SAndroid Build Coastguard Worker bool hasDelta;
668*03ce13f7SAndroid Build Coastguard Worker int partitionCount;
669*03ce13f7SAndroid Build Coastguard Worker int endpointBits;
670*03ce13f7SAndroid Build Coastguard Worker DeltaBits deltaBits;
671*03ce13f7SAndroid Build Coastguard Worker
ModeDesc__anon204fc45b0111::BC6H::ModeDesc672*03ce13f7SAndroid Build Coastguard Worker constexpr ModeDesc()
673*03ce13f7SAndroid Build Coastguard Worker : number(-1)
674*03ce13f7SAndroid Build Coastguard Worker , hasDelta(false)
675*03ce13f7SAndroid Build Coastguard Worker , partitionCount(0)
676*03ce13f7SAndroid Build Coastguard Worker , endpointBits(0)
677*03ce13f7SAndroid Build Coastguard Worker {
678*03ce13f7SAndroid Build Coastguard Worker }
679*03ce13f7SAndroid Build Coastguard Worker
ModeDesc__anon204fc45b0111::BC6H::ModeDesc680*03ce13f7SAndroid Build Coastguard Worker constexpr ModeDesc(int number, bool hasDelta, int partitionCount, int endpointBits, DeltaBits deltaBits)
681*03ce13f7SAndroid Build Coastguard Worker : number(number)
682*03ce13f7SAndroid Build Coastguard Worker , hasDelta(hasDelta)
683*03ce13f7SAndroid Build Coastguard Worker , partitionCount(partitionCount)
684*03ce13f7SAndroid Build Coastguard Worker , endpointBits(endpointBits)
685*03ce13f7SAndroid Build Coastguard Worker , deltaBits(deltaBits)
686*03ce13f7SAndroid Build Coastguard Worker {
687*03ce13f7SAndroid Build Coastguard Worker }
688*03ce13f7SAndroid Build Coastguard Worker };
689*03ce13f7SAndroid Build Coastguard Worker
690*03ce13f7SAndroid Build Coastguard Worker struct BlockDesc
691*03ce13f7SAndroid Build Coastguard Worker {
692*03ce13f7SAndroid Build Coastguard Worker DataType type;
693*03ce13f7SAndroid Build Coastguard Worker Channel channel;
694*03ce13f7SAndroid Build Coastguard Worker int MSB;
695*03ce13f7SAndroid Build Coastguard Worker int LSB;
696*03ce13f7SAndroid Build Coastguard Worker ModeDesc modeDesc;
697*03ce13f7SAndroid Build Coastguard Worker
BlockDesc__anon204fc45b0111::BC6H::BlockDesc698*03ce13f7SAndroid Build Coastguard Worker constexpr BlockDesc()
699*03ce13f7SAndroid Build Coastguard Worker : type(End)
700*03ce13f7SAndroid Build Coastguard Worker , channel(None)
701*03ce13f7SAndroid Build Coastguard Worker , MSB(0)
702*03ce13f7SAndroid Build Coastguard Worker , LSB(0)
703*03ce13f7SAndroid Build Coastguard Worker , modeDesc()
704*03ce13f7SAndroid Build Coastguard Worker {
705*03ce13f7SAndroid Build Coastguard Worker }
706*03ce13f7SAndroid Build Coastguard Worker
BlockDesc__anon204fc45b0111::BC6H::BlockDesc707*03ce13f7SAndroid Build Coastguard Worker constexpr BlockDesc(const DataType type, Channel channel, int MSB, int LSB, ModeDesc modeDesc)
708*03ce13f7SAndroid Build Coastguard Worker : type(type)
709*03ce13f7SAndroid Build Coastguard Worker , channel(channel)
710*03ce13f7SAndroid Build Coastguard Worker , MSB(MSB)
711*03ce13f7SAndroid Build Coastguard Worker , LSB(LSB)
712*03ce13f7SAndroid Build Coastguard Worker , modeDesc(modeDesc)
713*03ce13f7SAndroid Build Coastguard Worker {
714*03ce13f7SAndroid Build Coastguard Worker }
715*03ce13f7SAndroid Build Coastguard Worker
BlockDesc__anon204fc45b0111::BC6H::BlockDesc716*03ce13f7SAndroid Build Coastguard Worker constexpr BlockDesc(DataType type, Channel channel, int MSB, int LSB)
717*03ce13f7SAndroid Build Coastguard Worker : type(type)
718*03ce13f7SAndroid Build Coastguard Worker , channel(channel)
719*03ce13f7SAndroid Build Coastguard Worker , MSB(MSB)
720*03ce13f7SAndroid Build Coastguard Worker , LSB(LSB)
721*03ce13f7SAndroid Build Coastguard Worker , modeDesc()
722*03ce13f7SAndroid Build Coastguard Worker {
723*03ce13f7SAndroid Build Coastguard Worker }
724*03ce13f7SAndroid Build Coastguard Worker };
725*03ce13f7SAndroid Build Coastguard Worker
726*03ce13f7SAndroid Build Coastguard Worker // Turns a legal mode into an index into the BlockDesc table.
727*03ce13f7SAndroid Build Coastguard Worker // Illegal or reserved modes return -1.
modeToIndex(uint8_t mode)728*03ce13f7SAndroid Build Coastguard Worker static int modeToIndex(uint8_t mode)
729*03ce13f7SAndroid Build Coastguard Worker {
730*03ce13f7SAndroid Build Coastguard Worker if(mode <= 3)
731*03ce13f7SAndroid Build Coastguard Worker {
732*03ce13f7SAndroid Build Coastguard Worker return mode;
733*03ce13f7SAndroid Build Coastguard Worker }
734*03ce13f7SAndroid Build Coastguard Worker else if((mode & 0x2) != 0)
735*03ce13f7SAndroid Build Coastguard Worker {
736*03ce13f7SAndroid Build Coastguard Worker if(mode <= 18)
737*03ce13f7SAndroid Build Coastguard Worker {
738*03ce13f7SAndroid Build Coastguard Worker // Turns 6 into 4, 7 into 5, 10 into 6, etc.
739*03ce13f7SAndroid Build Coastguard Worker return (mode / 2) + 1 + (mode & 0x1);
740*03ce13f7SAndroid Build Coastguard Worker }
741*03ce13f7SAndroid Build Coastguard Worker else if(mode == 22 || mode == 26 || mode == 30)
742*03ce13f7SAndroid Build Coastguard Worker {
743*03ce13f7SAndroid Build Coastguard Worker // Turns 22 into 11, 26 into 12, etc.
744*03ce13f7SAndroid Build Coastguard Worker return mode / 4 + 6;
745*03ce13f7SAndroid Build Coastguard Worker }
746*03ce13f7SAndroid Build Coastguard Worker }
747*03ce13f7SAndroid Build Coastguard Worker
748*03ce13f7SAndroid Build Coastguard Worker return -1;
749*03ce13f7SAndroid Build Coastguard Worker }
750*03ce13f7SAndroid Build Coastguard Worker
751*03ce13f7SAndroid Build Coastguard Worker // Returns a description of the bitfields for each mode from the LSB
752*03ce13f7SAndroid Build Coastguard Worker // to the MSB before the index data starts.
753*03ce13f7SAndroid Build Coastguard Worker //
754*03ce13f7SAndroid Build Coastguard Worker // The numbers come from the BC6h block description. Each BlockDesc in the
755*03ce13f7SAndroid Build Coastguard Worker // {Type, Channel, MSB, LSB}
756*03ce13f7SAndroid Build Coastguard Worker // * Type describes which endpoint this is, or if this is a mode, a partition
757*03ce13f7SAndroid Build Coastguard Worker // number, or the end of the block description.
758*03ce13f7SAndroid Build Coastguard Worker // * Channel describes one of the 3 color channels within an endpoint
759*03ce13f7SAndroid Build Coastguard Worker // * MSB and LSB specificy:
760*03ce13f7SAndroid Build Coastguard Worker // * The size of the bitfield being read
761*03ce13f7SAndroid Build Coastguard Worker // * The position of the bitfield within the variable it is being read to
762*03ce13f7SAndroid Build Coastguard Worker // * If the bitfield is stored in reverse bit order
763*03ce13f7SAndroid Build Coastguard Worker // If MSB < LSB then the bitfield is stored in reverse order. The size of
764*03ce13f7SAndroid Build Coastguard Worker // the bitfield is abs(MSB-LSB+1). And the position of the bitfield within
765*03ce13f7SAndroid Build Coastguard Worker // the variable is min(LSB, MSB).
766*03ce13f7SAndroid Build Coastguard Worker //
767*03ce13f7SAndroid Build Coastguard Worker // Invalid or reserved modes return an empty list.
768*03ce13f7SAndroid Build Coastguard Worker static constexpr int NumBlocks = 14;
769*03ce13f7SAndroid Build Coastguard Worker // The largest number of descriptions within a block.
770*03ce13f7SAndroid Build Coastguard Worker static constexpr int MaxBlockDescIndex = 26;
771*03ce13f7SAndroid Build Coastguard Worker static constexpr BlockDesc blockDescs[NumBlocks][MaxBlockDescIndex] = {
772*03ce13f7SAndroid Build Coastguard Worker // clang-format off
773*03ce13f7SAndroid Build Coastguard Worker // Mode 0, Index 0
774*03ce13f7SAndroid Build Coastguard Worker {
775*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 1, 0, { 0, true, 2, 10, { 5, 5, 5 } } },
776*03ce13f7SAndroid Build Coastguard Worker { EP2, G, 4, 4 }, { EP2, B, 4, 4 }, { EP3, B, 4, 4 },
777*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
778*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 4, 0 }, { EP3, G, 4, 4 }, { EP2, G, 3, 0 },
779*03ce13f7SAndroid Build Coastguard Worker { EP1, G, 4, 0 }, { EP3, B, 0, 0 }, { EP3, G, 3, 0 },
780*03ce13f7SAndroid Build Coastguard Worker { EP1, B, 4, 0 }, { EP3, B, 1, 1 }, { EP2, B, 3, 0 },
781*03ce13f7SAndroid Build Coastguard Worker { EP2, R, 4, 0 }, { EP3, B, 2, 2 }, { EP3, R, 4, 0 },
782*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 3, 3 },
783*03ce13f7SAndroid Build Coastguard Worker { Partition, None, 4, 0 },
784*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
785*03ce13f7SAndroid Build Coastguard Worker },
786*03ce13f7SAndroid Build Coastguard Worker // Mode 1, Index 1
787*03ce13f7SAndroid Build Coastguard Worker {
788*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 1, 0, { 1, true, 2, 7, { 6, 6, 6 } } },
789*03ce13f7SAndroid Build Coastguard Worker { EP2, G, 5, 5 }, { EP3, G, 5, 4 }, { EP0, R, 6, 0 },
790*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 1, 0 }, { EP2, B, 4, 4 }, { EP0, G, 6, 0 },
791*03ce13f7SAndroid Build Coastguard Worker { EP2, B, 5, 5 }, { EP3, B, 2, 2 }, { EP2, G, 4, 4 },
792*03ce13f7SAndroid Build Coastguard Worker { EP0, B, 6, 0 }, { EP3, B, 3, 3 }, { EP3, B, 5, 5 },
793*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 4, 4 }, { EP1, R, 5, 0 }, { EP2, G, 3, 0 },
794*03ce13f7SAndroid Build Coastguard Worker { EP1, G, 5, 0 }, { EP3, G, 3, 0 }, { EP1, B, 5, 0 },
795*03ce13f7SAndroid Build Coastguard Worker { EP2, B, 3, 0 }, { EP2, R, 5, 0 }, { EP3, R, 5, 0 },
796*03ce13f7SAndroid Build Coastguard Worker { Partition, None, 4, 0 },
797*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
798*03ce13f7SAndroid Build Coastguard Worker },
799*03ce13f7SAndroid Build Coastguard Worker // Mode 2, Index 2
800*03ce13f7SAndroid Build Coastguard Worker {
801*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 2, true, 2, 11, { 5, 4, 4 } } },
802*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
803*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 4, 0 }, { EP0, R, 10, 10 }, { EP2, G, 3, 0 },
804*03ce13f7SAndroid Build Coastguard Worker { EP1, G, 3, 0 }, { EP0, G, 10, 10 }, { EP3, B, 0, 0 },
805*03ce13f7SAndroid Build Coastguard Worker { EP3, G, 3, 0 }, { EP1, B, 3, 0 }, { EP0, B, 10, 10 },
806*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 1, 1 }, { EP2, B, 3, 0 }, { EP2, R, 4, 0 },
807*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 2, 2 }, { EP3, R, 4, 0 }, { EP3, B, 3, 3 },
808*03ce13f7SAndroid Build Coastguard Worker { Partition, None, 4, 0 },
809*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
810*03ce13f7SAndroid Build Coastguard Worker },
811*03ce13f7SAndroid Build Coastguard Worker // Mode 3, Index 3
812*03ce13f7SAndroid Build Coastguard Worker {
813*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 3, false, 1, 10, { 0, 0, 0 } } },
814*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
815*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 9, 0 }, { EP1, G, 9, 0 }, { EP1, B, 9, 0 },
816*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
817*03ce13f7SAndroid Build Coastguard Worker },
818*03ce13f7SAndroid Build Coastguard Worker // Mode 6, Index 4
819*03ce13f7SAndroid Build Coastguard Worker {
820*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 6, true, 2, 11, { 4, 5, 4 } } }, // 1 1
821*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
822*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 3, 0 }, { EP0, R, 10, 10 }, { EP3, G, 4, 4 },
823*03ce13f7SAndroid Build Coastguard Worker { EP2, G, 3, 0 }, { EP1, G, 4, 0 }, { EP0, G, 10, 10 },
824*03ce13f7SAndroid Build Coastguard Worker { EP3, G, 3, 0 }, { EP1, B, 3, 0 }, { EP0, B, 10, 10 },
825*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 1, 1 }, { EP2, B, 3, 0 }, { EP2, R, 3, 0 },
826*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 0, 0 }, { EP3, B, 2, 2 }, { EP3, R, 3, 0 }, // 18 19
827*03ce13f7SAndroid Build Coastguard Worker { EP2, G, 4, 4 }, { EP3, B, 3, 3 }, // 2 21
828*03ce13f7SAndroid Build Coastguard Worker { Partition, None, 4, 0 },
829*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
830*03ce13f7SAndroid Build Coastguard Worker },
831*03ce13f7SAndroid Build Coastguard Worker // Mode 7, Index 5
832*03ce13f7SAndroid Build Coastguard Worker {
833*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 7, true, 1, 11, { 9, 9, 9 } } },
834*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
835*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 8, 0 }, { EP0, R, 10, 10 }, { EP1, G, 8, 0 },
836*03ce13f7SAndroid Build Coastguard Worker { EP0, G, 10, 10 }, { EP1, B, 8, 0 }, { EP0, B, 10, 10 },
837*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
838*03ce13f7SAndroid Build Coastguard Worker },
839*03ce13f7SAndroid Build Coastguard Worker // Mode 10, Index 6
840*03ce13f7SAndroid Build Coastguard Worker {
841*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 10, true, 2, 11, { 4, 4, 5 } } },
842*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
843*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 3, 0 }, { EP0, R, 10, 10 }, { EP2, B, 4, 4 },
844*03ce13f7SAndroid Build Coastguard Worker { EP2, G, 3, 0 }, { EP1, G, 3, 0 }, { EP0, G, 10, 10 },
845*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 0, 0 }, { EP3, G, 3, 0 }, { EP1, B, 4, 0 },
846*03ce13f7SAndroid Build Coastguard Worker { EP0, B, 10, 10 }, { EP2, B, 3, 0 }, { EP2, R, 3, 0 },
847*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 1, 1 }, { EP3, B, 2, 2 }, { EP3, R, 3, 0 },
848*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 4, 4 }, { EP3, B, 3, 3 },
849*03ce13f7SAndroid Build Coastguard Worker { Partition, None, 4, 0 },
850*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
851*03ce13f7SAndroid Build Coastguard Worker },
852*03ce13f7SAndroid Build Coastguard Worker // Mode 11, Index 7
853*03ce13f7SAndroid Build Coastguard Worker {
854*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 11, true, 1, 12, { 8, 8, 8 } } },
855*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
856*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 7, 0 }, { EP0, R, 10, 11 }, { EP1, G, 7, 0 },
857*03ce13f7SAndroid Build Coastguard Worker { EP0, G, 10, 11 }, { EP1, B, 7, 0 }, { EP0, B, 10, 11 },
858*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
859*03ce13f7SAndroid Build Coastguard Worker },
860*03ce13f7SAndroid Build Coastguard Worker // Mode 14, Index 8
861*03ce13f7SAndroid Build Coastguard Worker {
862*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 14, true, 2, 9, { 5, 5, 5 } } },
863*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 8, 0 }, { EP2, B, 4, 4 }, { EP0, G, 8, 0 },
864*03ce13f7SAndroid Build Coastguard Worker { EP2, G, 4, 4 }, { EP0, B, 8, 0 }, { EP3, B, 4, 4 },
865*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 4, 0 }, { EP3, G, 4, 4 }, { EP2, G, 3, 0 },
866*03ce13f7SAndroid Build Coastguard Worker { EP1, G, 4, 0 }, { EP3, B, 0, 0 }, { EP3, G, 3, 0 },
867*03ce13f7SAndroid Build Coastguard Worker { EP1, B, 4, 0 }, { EP3, B, 1, 1 }, { EP2, B, 3, 0 },
868*03ce13f7SAndroid Build Coastguard Worker { EP2, R, 4, 0 }, { EP3, B, 2, 2 }, { EP3, R, 4, 0 },
869*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 3, 3 },
870*03ce13f7SAndroid Build Coastguard Worker { Partition, None, 4, 0 },
871*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
872*03ce13f7SAndroid Build Coastguard Worker },
873*03ce13f7SAndroid Build Coastguard Worker // Mode 15, Index 9
874*03ce13f7SAndroid Build Coastguard Worker {
875*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 15, true, 1, 16, { 4, 4, 4 } } },
876*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
877*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 3, 0 }, { EP0, R, 10, 15 }, { EP1, G, 3, 0 },
878*03ce13f7SAndroid Build Coastguard Worker { EP0, G, 10, 15 }, { EP1, B, 3, 0 }, { EP0, B, 10, 15 },
879*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
880*03ce13f7SAndroid Build Coastguard Worker },
881*03ce13f7SAndroid Build Coastguard Worker // Mode 18, Index 10
882*03ce13f7SAndroid Build Coastguard Worker {
883*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 18, true, 2, 8, { 6, 5, 5 } } },
884*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 7, 0 }, { EP3, G, 4, 4 }, { EP2, B, 4, 4 },
885*03ce13f7SAndroid Build Coastguard Worker { EP0, G, 7, 0 }, { EP3, B, 2, 2 }, { EP2, G, 4, 4 },
886*03ce13f7SAndroid Build Coastguard Worker { EP0, B, 7, 0 }, { EP3, B, 3, 3 }, { EP3, B, 4, 4 },
887*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 5, 0 }, { EP2, G, 3, 0 }, { EP1, G, 4, 0 },
888*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 0, 0 }, { EP3, G, 3, 0 }, { EP1, B, 4, 0 },
889*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 1, 1 }, { EP2, B, 3, 0 }, { EP2, R, 5, 0 },
890*03ce13f7SAndroid Build Coastguard Worker { EP3, R, 5, 0 },
891*03ce13f7SAndroid Build Coastguard Worker { Partition, None, 4, 0 },
892*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
893*03ce13f7SAndroid Build Coastguard Worker },
894*03ce13f7SAndroid Build Coastguard Worker // Mode 22, Index 11
895*03ce13f7SAndroid Build Coastguard Worker {
896*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 22, true, 2, 8, { 5, 6, 5 } } },
897*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 7, 0 }, { EP3, B, 0, 0 }, { EP2, B, 4, 4 },
898*03ce13f7SAndroid Build Coastguard Worker { EP0, G, 7, 0 }, { EP2, G, 5, 5 }, { EP2, G, 4, 4 },
899*03ce13f7SAndroid Build Coastguard Worker { EP0, B, 7, 0 }, { EP3, G, 5, 5 }, { EP3, B, 4, 4 },
900*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 4, 0 }, { EP3, G, 4, 4 }, { EP2, G, 3, 0 },
901*03ce13f7SAndroid Build Coastguard Worker { EP1, G, 5, 0 }, { EP3, G, 3, 0 }, { EP1, B, 4, 0 },
902*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 1, 1 }, { EP2, B, 3, 0 }, { EP2, R, 4, 0 },
903*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 2, 2 }, { EP3, R, 4, 0 }, { EP3, B, 3, 3 },
904*03ce13f7SAndroid Build Coastguard Worker { Partition, None, 4, 0 },
905*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
906*03ce13f7SAndroid Build Coastguard Worker },
907*03ce13f7SAndroid Build Coastguard Worker // Mode 26, Index 12
908*03ce13f7SAndroid Build Coastguard Worker {
909*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 26, true, 2, 8, { 5, 5, 6 } } },
910*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 7, 0 }, { EP3, B, 1, 1 }, { EP2, B, 4, 4 },
911*03ce13f7SAndroid Build Coastguard Worker { EP0, G, 7, 0 }, { EP2, B, 5, 5 }, { EP2, G, 4, 4 },
912*03ce13f7SAndroid Build Coastguard Worker { EP0, B, 7, 0 }, { EP3, B, 5, 5 }, { EP3, B, 4, 4 },
913*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 4, 0 }, { EP3, G, 4, 4 }, { EP2, G, 3, 0 },
914*03ce13f7SAndroid Build Coastguard Worker { EP1, G, 4, 0 }, { EP3, B, 0, 0 }, { EP3, G, 3, 0 },
915*03ce13f7SAndroid Build Coastguard Worker { EP1, B, 5, 0 }, { EP2, B, 3, 0 }, { EP2, R, 4, 0 },
916*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 2, 2 }, { EP3, R, 4, 0 }, { EP3, B, 3, 3 },
917*03ce13f7SAndroid Build Coastguard Worker { Partition, None, 4, 0 },
918*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
919*03ce13f7SAndroid Build Coastguard Worker },
920*03ce13f7SAndroid Build Coastguard Worker // Mode 30, Index 13
921*03ce13f7SAndroid Build Coastguard Worker {
922*03ce13f7SAndroid Build Coastguard Worker { Mode, None, 4, 0, { 30, false, 2, 6, { 0, 0, 0 } } },
923*03ce13f7SAndroid Build Coastguard Worker { EP0, R, 5, 0 }, { EP3, G, 4, 4 }, { EP3, B, 0, 0 },
924*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 1, 1 }, { EP2, B, 4, 4 }, { EP0, G, 5, 0 },
925*03ce13f7SAndroid Build Coastguard Worker { EP2, G, 5, 5 }, { EP2, B, 5, 5 }, { EP3, B, 2, 2 },
926*03ce13f7SAndroid Build Coastguard Worker { EP2, G, 4, 4 }, { EP0, B, 5, 0 }, { EP3, G, 5, 5 },
927*03ce13f7SAndroid Build Coastguard Worker { EP3, B, 3, 3 }, { EP3, B, 5, 5 }, { EP3, B, 4, 4 },
928*03ce13f7SAndroid Build Coastguard Worker { EP1, R, 5, 0 }, { EP2, G, 3, 0 }, { EP1, G, 5, 0 },
929*03ce13f7SAndroid Build Coastguard Worker { EP3, G, 3, 0 }, { EP1, B, 5, 0 }, { EP2, B, 3, 0 },
930*03ce13f7SAndroid Build Coastguard Worker { EP2, R, 5, 0 }, { EP3, R, 5, 0 },
931*03ce13f7SAndroid Build Coastguard Worker { Partition, None, 4, 0 },
932*03ce13f7SAndroid Build Coastguard Worker { End, None, 0, 0},
933*03ce13f7SAndroid Build Coastguard Worker }
934*03ce13f7SAndroid Build Coastguard Worker // clang-format on
935*03ce13f7SAndroid Build Coastguard Worker };
936*03ce13f7SAndroid Build Coastguard Worker
937*03ce13f7SAndroid Build Coastguard Worker struct Block
938*03ce13f7SAndroid Build Coastguard Worker {
939*03ce13f7SAndroid Build Coastguard Worker uint64_t low64;
940*03ce13f7SAndroid Build Coastguard Worker uint64_t high64;
941*03ce13f7SAndroid Build Coastguard Worker
decode__anon204fc45b0111::BC6H::Block942*03ce13f7SAndroid Build Coastguard Worker void decode(uint8_t *dst, int dstX, int dstY, int dstWidth, int dstHeight, size_t dstPitch, size_t dstBpp, bool isSigned) const
943*03ce13f7SAndroid Build Coastguard Worker {
944*03ce13f7SAndroid Build Coastguard Worker uint8_t mode = 0;
945*03ce13f7SAndroid Build Coastguard Worker Data data(low64, high64);
946*03ce13f7SAndroid Build Coastguard Worker ASSERT(dstBpp == sizeof(Color));
947*03ce13f7SAndroid Build Coastguard Worker
948*03ce13f7SAndroid Build Coastguard Worker if((data.low64 & 0x2) == 0)
949*03ce13f7SAndroid Build Coastguard Worker {
950*03ce13f7SAndroid Build Coastguard Worker mode = data.consumeBits(1, 0);
951*03ce13f7SAndroid Build Coastguard Worker }
952*03ce13f7SAndroid Build Coastguard Worker else
953*03ce13f7SAndroid Build Coastguard Worker {
954*03ce13f7SAndroid Build Coastguard Worker mode = data.consumeBits(4, 0);
955*03ce13f7SAndroid Build Coastguard Worker }
956*03ce13f7SAndroid Build Coastguard Worker
957*03ce13f7SAndroid Build Coastguard Worker int blockIndex = modeToIndex(mode);
958*03ce13f7SAndroid Build Coastguard Worker // Handle illegal or reserved mode
959*03ce13f7SAndroid Build Coastguard Worker if(blockIndex == -1)
960*03ce13f7SAndroid Build Coastguard Worker {
961*03ce13f7SAndroid Build Coastguard Worker for(int y = 0; y < 4 && y + dstY < dstHeight; y++)
962*03ce13f7SAndroid Build Coastguard Worker {
963*03ce13f7SAndroid Build Coastguard Worker for(int x = 0; x < 4 && x + dstX < dstWidth; x++)
964*03ce13f7SAndroid Build Coastguard Worker {
965*03ce13f7SAndroid Build Coastguard Worker auto out = reinterpret_cast<Color *>(dst + sizeof(Color) * x + dstPitch * y);
966*03ce13f7SAndroid Build Coastguard Worker out->rgba = { 0, 0, 0 };
967*03ce13f7SAndroid Build Coastguard Worker }
968*03ce13f7SAndroid Build Coastguard Worker }
969*03ce13f7SAndroid Build Coastguard Worker return;
970*03ce13f7SAndroid Build Coastguard Worker }
971*03ce13f7SAndroid Build Coastguard Worker const BlockDesc *blockDesc = blockDescs[blockIndex];
972*03ce13f7SAndroid Build Coastguard Worker
973*03ce13f7SAndroid Build Coastguard Worker RGBf e[4];
974*03ce13f7SAndroid Build Coastguard Worker e[0].isSigned = e[1].isSigned = e[2].isSigned = e[3].isSigned = isSigned;
975*03ce13f7SAndroid Build Coastguard Worker
976*03ce13f7SAndroid Build Coastguard Worker int partition = 0;
977*03ce13f7SAndroid Build Coastguard Worker ModeDesc modeDesc;
978*03ce13f7SAndroid Build Coastguard Worker for(int index = 0; blockDesc[index].type != End; index++)
979*03ce13f7SAndroid Build Coastguard Worker {
980*03ce13f7SAndroid Build Coastguard Worker const BlockDesc desc = blockDesc[index];
981*03ce13f7SAndroid Build Coastguard Worker
982*03ce13f7SAndroid Build Coastguard Worker switch(desc.type)
983*03ce13f7SAndroid Build Coastguard Worker {
984*03ce13f7SAndroid Build Coastguard Worker case Mode:
985*03ce13f7SAndroid Build Coastguard Worker modeDesc = desc.modeDesc;
986*03ce13f7SAndroid Build Coastguard Worker ASSERT(modeDesc.number == mode);
987*03ce13f7SAndroid Build Coastguard Worker
988*03ce13f7SAndroid Build Coastguard Worker e[0].size[0] = e[0].size[1] = e[0].size[2] = modeDesc.endpointBits;
989*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < RGBfChannels; i++)
990*03ce13f7SAndroid Build Coastguard Worker {
991*03ce13f7SAndroid Build Coastguard Worker if(modeDesc.hasDelta)
992*03ce13f7SAndroid Build Coastguard Worker {
993*03ce13f7SAndroid Build Coastguard Worker e[1].size[i] = e[2].size[i] = e[3].size[i] = modeDesc.deltaBits.channel[i];
994*03ce13f7SAndroid Build Coastguard Worker }
995*03ce13f7SAndroid Build Coastguard Worker else
996*03ce13f7SAndroid Build Coastguard Worker {
997*03ce13f7SAndroid Build Coastguard Worker e[1].size[i] = e[2].size[i] = e[3].size[i] = modeDesc.endpointBits;
998*03ce13f7SAndroid Build Coastguard Worker }
999*03ce13f7SAndroid Build Coastguard Worker }
1000*03ce13f7SAndroid Build Coastguard Worker break;
1001*03ce13f7SAndroid Build Coastguard Worker case Partition:
1002*03ce13f7SAndroid Build Coastguard Worker partition |= data.consumeBits(desc.MSB, desc.LSB);
1003*03ce13f7SAndroid Build Coastguard Worker break;
1004*03ce13f7SAndroid Build Coastguard Worker case EP0:
1005*03ce13f7SAndroid Build Coastguard Worker case EP1:
1006*03ce13f7SAndroid Build Coastguard Worker case EP2:
1007*03ce13f7SAndroid Build Coastguard Worker case EP3:
1008*03ce13f7SAndroid Build Coastguard Worker e[desc.type].channel[desc.channel] |= data.consumeBits(desc.MSB, desc.LSB);
1009*03ce13f7SAndroid Build Coastguard Worker break;
1010*03ce13f7SAndroid Build Coastguard Worker default:
1011*03ce13f7SAndroid Build Coastguard Worker ASSERT_MSG(false, "Unexpected enum value: %d", (int)desc.type);
1012*03ce13f7SAndroid Build Coastguard Worker return;
1013*03ce13f7SAndroid Build Coastguard Worker }
1014*03ce13f7SAndroid Build Coastguard Worker }
1015*03ce13f7SAndroid Build Coastguard Worker
1016*03ce13f7SAndroid Build Coastguard Worker // Sign extension
1017*03ce13f7SAndroid Build Coastguard Worker if(isSigned)
1018*03ce13f7SAndroid Build Coastguard Worker {
1019*03ce13f7SAndroid Build Coastguard Worker for(int ep = 0; ep < modeDesc.partitionCount * 2; ep++)
1020*03ce13f7SAndroid Build Coastguard Worker {
1021*03ce13f7SAndroid Build Coastguard Worker e[ep].extendSign();
1022*03ce13f7SAndroid Build Coastguard Worker }
1023*03ce13f7SAndroid Build Coastguard Worker }
1024*03ce13f7SAndroid Build Coastguard Worker else if(modeDesc.hasDelta)
1025*03ce13f7SAndroid Build Coastguard Worker {
1026*03ce13f7SAndroid Build Coastguard Worker // Don't sign-extend the base endpoint in an unsigned format.
1027*03ce13f7SAndroid Build Coastguard Worker for(int ep = 1; ep < modeDesc.partitionCount * 2; ep++)
1028*03ce13f7SAndroid Build Coastguard Worker {
1029*03ce13f7SAndroid Build Coastguard Worker e[ep].extendSign();
1030*03ce13f7SAndroid Build Coastguard Worker }
1031*03ce13f7SAndroid Build Coastguard Worker }
1032*03ce13f7SAndroid Build Coastguard Worker
1033*03ce13f7SAndroid Build Coastguard Worker // Turn the deltas into endpoints
1034*03ce13f7SAndroid Build Coastguard Worker if(modeDesc.hasDelta)
1035*03ce13f7SAndroid Build Coastguard Worker {
1036*03ce13f7SAndroid Build Coastguard Worker for(int ep = 1; ep < modeDesc.partitionCount * 2; ep++)
1037*03ce13f7SAndroid Build Coastguard Worker {
1038*03ce13f7SAndroid Build Coastguard Worker e[ep].resolveDelta(e[0]);
1039*03ce13f7SAndroid Build Coastguard Worker }
1040*03ce13f7SAndroid Build Coastguard Worker }
1041*03ce13f7SAndroid Build Coastguard Worker
1042*03ce13f7SAndroid Build Coastguard Worker for(int ep = 0; ep < modeDesc.partitionCount * 2; ep++)
1043*03ce13f7SAndroid Build Coastguard Worker {
1044*03ce13f7SAndroid Build Coastguard Worker e[ep].unquantize();
1045*03ce13f7SAndroid Build Coastguard Worker }
1046*03ce13f7SAndroid Build Coastguard Worker
1047*03ce13f7SAndroid Build Coastguard Worker // Get the indices, calculate final colors, and output
1048*03ce13f7SAndroid Build Coastguard Worker for(int y = 0; y < 4; y++)
1049*03ce13f7SAndroid Build Coastguard Worker {
1050*03ce13f7SAndroid Build Coastguard Worker for(int x = 0; x < 4; x++)
1051*03ce13f7SAndroid Build Coastguard Worker {
1052*03ce13f7SAndroid Build Coastguard Worker int pixelNum = x + y * 4;
1053*03ce13f7SAndroid Build Coastguard Worker IndexInfo idx;
1054*03ce13f7SAndroid Build Coastguard Worker bool isAnchor = false;
1055*03ce13f7SAndroid Build Coastguard Worker int firstEndpoint = 0;
1056*03ce13f7SAndroid Build Coastguard Worker // Bc6H can have either 1 or 2 petitions depending on the mode.
1057*03ce13f7SAndroid Build Coastguard Worker // The number of petitions affects the number of indices with implicit
1058*03ce13f7SAndroid Build Coastguard Worker // leading 0 bits and the number of bits per index.
1059*03ce13f7SAndroid Build Coastguard Worker if(modeDesc.partitionCount == 1)
1060*03ce13f7SAndroid Build Coastguard Worker {
1061*03ce13f7SAndroid Build Coastguard Worker idx.numBits = 4;
1062*03ce13f7SAndroid Build Coastguard Worker // There's an implicit leading 0 bit for the first idx
1063*03ce13f7SAndroid Build Coastguard Worker isAnchor = (pixelNum == 0);
1064*03ce13f7SAndroid Build Coastguard Worker }
1065*03ce13f7SAndroid Build Coastguard Worker else
1066*03ce13f7SAndroid Build Coastguard Worker {
1067*03ce13f7SAndroid Build Coastguard Worker idx.numBits = 3;
1068*03ce13f7SAndroid Build Coastguard Worker // There are 2 indices with implicit leading 0-bits.
1069*03ce13f7SAndroid Build Coastguard Worker isAnchor = ((pixelNum == 0) || (pixelNum == AnchorTable2[partition]));
1070*03ce13f7SAndroid Build Coastguard Worker firstEndpoint = PartitionTable2[partition][pixelNum] * 2;
1071*03ce13f7SAndroid Build Coastguard Worker }
1072*03ce13f7SAndroid Build Coastguard Worker
1073*03ce13f7SAndroid Build Coastguard Worker idx.value = data.consumeBits(idx.numBits - isAnchor - 1, 0);
1074*03ce13f7SAndroid Build Coastguard Worker
1075*03ce13f7SAndroid Build Coastguard Worker // Don't exit the loop early, we need to consume these index bits regardless if
1076*03ce13f7SAndroid Build Coastguard Worker // we actually output them or not.
1077*03ce13f7SAndroid Build Coastguard Worker if((y + dstY >= dstHeight) || (x + dstX >= dstWidth))
1078*03ce13f7SAndroid Build Coastguard Worker {
1079*03ce13f7SAndroid Build Coastguard Worker continue;
1080*03ce13f7SAndroid Build Coastguard Worker }
1081*03ce13f7SAndroid Build Coastguard Worker
1082*03ce13f7SAndroid Build Coastguard Worker Color color = interpolate(e[firstEndpoint], e[firstEndpoint + 1], idx, isSigned);
1083*03ce13f7SAndroid Build Coastguard Worker auto out = reinterpret_cast<Color *>(dst + dstBpp * x + dstPitch * y);
1084*03ce13f7SAndroid Build Coastguard Worker *out = color;
1085*03ce13f7SAndroid Build Coastguard Worker }
1086*03ce13f7SAndroid Build Coastguard Worker }
1087*03ce13f7SAndroid Build Coastguard Worker }
1088*03ce13f7SAndroid Build Coastguard Worker };
1089*03ce13f7SAndroid Build Coastguard Worker
1090*03ce13f7SAndroid Build Coastguard Worker } // namespace BC6H
1091*03ce13f7SAndroid Build Coastguard Worker
1092*03ce13f7SAndroid Build Coastguard Worker namespace BC7 {
1093*03ce13f7SAndroid Build Coastguard Worker // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt
1094*03ce13f7SAndroid Build Coastguard Worker // https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format
1095*03ce13f7SAndroid Build Coastguard Worker
1096*03ce13f7SAndroid Build Coastguard Worker struct Bitfield
1097*03ce13f7SAndroid Build Coastguard Worker {
1098*03ce13f7SAndroid Build Coastguard Worker int offset;
1099*03ce13f7SAndroid Build Coastguard Worker int count;
Then__anon204fc45b0111::BC7::Bitfield1100*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield Then(const int bits) { return { offset + count, bits }; }
operator ==__anon204fc45b0111::BC7::Bitfield1101*03ce13f7SAndroid Build Coastguard Worker constexpr bool operator==(const Bitfield &rhs) const
1102*03ce13f7SAndroid Build Coastguard Worker {
1103*03ce13f7SAndroid Build Coastguard Worker return offset == rhs.offset && count == rhs.count;
1104*03ce13f7SAndroid Build Coastguard Worker }
1105*03ce13f7SAndroid Build Coastguard Worker };
1106*03ce13f7SAndroid Build Coastguard Worker
1107*03ce13f7SAndroid Build Coastguard Worker struct Mode
1108*03ce13f7SAndroid Build Coastguard Worker {
1109*03ce13f7SAndroid Build Coastguard Worker const int IDX; // Mode index
1110*03ce13f7SAndroid Build Coastguard Worker const int NS; // Number of subsets in each partition
1111*03ce13f7SAndroid Build Coastguard Worker const int PB; // Partition bits
1112*03ce13f7SAndroid Build Coastguard Worker const int RB; // Rotation bits
1113*03ce13f7SAndroid Build Coastguard Worker const int ISB; // Index selection bits
1114*03ce13f7SAndroid Build Coastguard Worker const int CB; // Color bits
1115*03ce13f7SAndroid Build Coastguard Worker const int AB; // Alpha bits
1116*03ce13f7SAndroid Build Coastguard Worker const int EPB; // Endpoint P-bits
1117*03ce13f7SAndroid Build Coastguard Worker const int SPB; // Shared P-bits
1118*03ce13f7SAndroid Build Coastguard Worker const int IB; // Primary index bits per element
1119*03ce13f7SAndroid Build Coastguard Worker const int IBC; // Primary index bits total
1120*03ce13f7SAndroid Build Coastguard Worker const int IB2; // Secondary index bits per element
1121*03ce13f7SAndroid Build Coastguard Worker
NumColors__anon204fc45b0111::BC7::Mode1122*03ce13f7SAndroid Build Coastguard Worker constexpr int NumColors() const { return NS * 2; }
Partition__anon204fc45b0111::BC7::Mode1123*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield Partition() const { return { IDX + 1, PB }; }
Rotation__anon204fc45b0111::BC7::Mode1124*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield Rotation() const { return Partition().Then(RB); }
IndexSelection__anon204fc45b0111::BC7::Mode1125*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield IndexSelection() const { return Rotation().Then(ISB); }
Red__anon204fc45b0111::BC7::Mode1126*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield Red(int idx) const
1127*03ce13f7SAndroid Build Coastguard Worker {
1128*03ce13f7SAndroid Build Coastguard Worker return IndexSelection().Then(CB * idx).Then(CB);
1129*03ce13f7SAndroid Build Coastguard Worker }
Green__anon204fc45b0111::BC7::Mode1130*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield Green(int idx) const
1131*03ce13f7SAndroid Build Coastguard Worker {
1132*03ce13f7SAndroid Build Coastguard Worker return Red(NumColors() - 1).Then(CB * idx).Then(CB);
1133*03ce13f7SAndroid Build Coastguard Worker }
Blue__anon204fc45b0111::BC7::Mode1134*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield Blue(int idx) const
1135*03ce13f7SAndroid Build Coastguard Worker {
1136*03ce13f7SAndroid Build Coastguard Worker return Green(NumColors() - 1).Then(CB * idx).Then(CB);
1137*03ce13f7SAndroid Build Coastguard Worker }
Alpha__anon204fc45b0111::BC7::Mode1138*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield Alpha(int idx) const
1139*03ce13f7SAndroid Build Coastguard Worker {
1140*03ce13f7SAndroid Build Coastguard Worker return Blue(NumColors() - 1).Then(AB * idx).Then(AB);
1141*03ce13f7SAndroid Build Coastguard Worker }
EndpointPBit__anon204fc45b0111::BC7::Mode1142*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield EndpointPBit(int idx) const
1143*03ce13f7SAndroid Build Coastguard Worker {
1144*03ce13f7SAndroid Build Coastguard Worker return Alpha(NumColors() - 1).Then(EPB * idx).Then(EPB);
1145*03ce13f7SAndroid Build Coastguard Worker }
SharedPBit0__anon204fc45b0111::BC7::Mode1146*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield SharedPBit0() const
1147*03ce13f7SAndroid Build Coastguard Worker {
1148*03ce13f7SAndroid Build Coastguard Worker return EndpointPBit(NumColors() - 1).Then(SPB);
1149*03ce13f7SAndroid Build Coastguard Worker }
SharedPBit1__anon204fc45b0111::BC7::Mode1150*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield SharedPBit1() const
1151*03ce13f7SAndroid Build Coastguard Worker {
1152*03ce13f7SAndroid Build Coastguard Worker return SharedPBit0().Then(SPB);
1153*03ce13f7SAndroid Build Coastguard Worker }
PrimaryIndex__anon204fc45b0111::BC7::Mode1154*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield PrimaryIndex(int offset, int count) const
1155*03ce13f7SAndroid Build Coastguard Worker {
1156*03ce13f7SAndroid Build Coastguard Worker return SharedPBit1().Then(offset).Then(count);
1157*03ce13f7SAndroid Build Coastguard Worker }
SecondaryIndex__anon204fc45b0111::BC7::Mode1158*03ce13f7SAndroid Build Coastguard Worker constexpr Bitfield SecondaryIndex(int offset, int count) const
1159*03ce13f7SAndroid Build Coastguard Worker {
1160*03ce13f7SAndroid Build Coastguard Worker return SharedPBit1().Then(IBC + offset).Then(count);
1161*03ce13f7SAndroid Build Coastguard Worker }
1162*03ce13f7SAndroid Build Coastguard Worker };
1163*03ce13f7SAndroid Build Coastguard Worker
1164*03ce13f7SAndroid Build Coastguard Worker static constexpr Mode Modes[] = {
1165*03ce13f7SAndroid Build Coastguard Worker // IDX NS PB RB ISB CB AB EPB SPB IB IBC, IB2
1166*03ce13f7SAndroid Build Coastguard Worker /**/ { 0x0, 0x3, 0x4, 0x0, 0x0, 0x4, 0x0, 0x1, 0x0, 0x3, 0x2d, 0x0 },
1167*03ce13f7SAndroid Build Coastguard Worker /**/ { 0x1, 0x2, 0x6, 0x0, 0x0, 0x6, 0x0, 0x0, 0x1, 0x3, 0x2e, 0x0 },
1168*03ce13f7SAndroid Build Coastguard Worker /**/ { 0x2, 0x3, 0x6, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x2, 0x1d, 0x0 },
1169*03ce13f7SAndroid Build Coastguard Worker /**/ { 0x3, 0x2, 0x6, 0x0, 0x0, 0x7, 0x0, 0x1, 0x0, 0x2, 0x1e, 0x0 },
1170*03ce13f7SAndroid Build Coastguard Worker /**/ { 0x4, 0x1, 0x0, 0x2, 0x1, 0x5, 0x6, 0x0, 0x0, 0x2, 0x1f, 0x3 },
1171*03ce13f7SAndroid Build Coastguard Worker /**/ { 0x5, 0x1, 0x0, 0x2, 0x0, 0x7, 0x8, 0x0, 0x0, 0x2, 0x1f, 0x2 },
1172*03ce13f7SAndroid Build Coastguard Worker /**/ { 0x6, 0x1, 0x0, 0x0, 0x0, 0x7, 0x7, 0x1, 0x0, 0x4, 0x3f, 0x0 },
1173*03ce13f7SAndroid Build Coastguard Worker /**/ { 0x7, 0x2, 0x6, 0x0, 0x0, 0x5, 0x5, 0x1, 0x0, 0x2, 0x1e, 0x0 },
1174*03ce13f7SAndroid Build Coastguard Worker /**/ { -1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x00, 0x0 },
1175*03ce13f7SAndroid Build Coastguard Worker };
1176*03ce13f7SAndroid Build Coastguard Worker
1177*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].NumColors() == 6, "BC7 static assertion failed");
1178*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].Partition() == Bitfield{ 1, 4 }, "BC7 static assertion failed");
1179*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].Red(0) == Bitfield{ 5, 4 }, "BC7 static assertion failed");
1180*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].Red(5) == Bitfield{ 25, 4 }, "BC7 static assertion failed");
1181*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].Green(0) == Bitfield{ 29, 4 }, "BC7 static assertion failed");
1182*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].Green(5) == Bitfield{ 49, 4 }, "BC7 static assertion failed");
1183*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].Blue(0) == Bitfield{ 53, 4 }, "BC7 static assertion failed");
1184*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].Blue(5) == Bitfield{ 73, 4 }, "BC7 static assertion failed");
1185*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].EndpointPBit(0) == Bitfield{ 77, 1 }, "BC7 static assertion failed");
1186*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].EndpointPBit(5) == Bitfield{ 82, 1 }, "BC7 static assertion failed");
1187*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].PrimaryIndex(0, 2) == Bitfield{ 83, 2 }, "BC7 static asassertionsert failed");
1188*03ce13f7SAndroid Build Coastguard Worker static_assert(Modes[0].PrimaryIndex(43, 1) == Bitfield{ 126, 1 }, "BC7 static assertion failed");
1189*03ce13f7SAndroid Build Coastguard Worker
1190*03ce13f7SAndroid Build Coastguard Worker static constexpr int MaxPartitions = 64;
1191*03ce13f7SAndroid Build Coastguard Worker static constexpr int MaxSubsets = 3;
1192*03ce13f7SAndroid Build Coastguard Worker
1193*03ce13f7SAndroid Build Coastguard Worker static constexpr uint8_t PartitionTable2[MaxPartitions][16] = {
1194*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 },
1195*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 },
1196*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
1197*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 },
1198*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 },
1199*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
1200*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
1201*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1 },
1202*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1 },
1203*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
1204*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
1205*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 },
1206*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
1207*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
1208*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
1209*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 },
1210*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1 },
1211*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
1212*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 },
1213*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
1214*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
1215*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 },
1216*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 },
1217*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 },
1218*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
1219*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 },
1220*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0 },
1221*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0 },
1222*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 },
1223*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
1224*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0 },
1225*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 },
1226*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 },
1227*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 },
1228*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0 },
1229*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0 },
1230*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 },
1231*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 },
1232*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 },
1233*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 },
1234*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0 },
1235*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 },
1236*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 },
1237*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0 },
1238*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 },
1239*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 },
1240*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 },
1241*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
1242*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
1243*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 },
1244*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0 },
1245*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0 },
1246*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 },
1247*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1 },
1248*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0 },
1249*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0 },
1250*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 },
1251*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1 },
1252*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 },
1253*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1 },
1254*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 },
1255*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
1256*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0 },
1257*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1 },
1258*03ce13f7SAndroid Build Coastguard Worker };
1259*03ce13f7SAndroid Build Coastguard Worker
1260*03ce13f7SAndroid Build Coastguard Worker static constexpr uint8_t PartitionTable3[MaxPartitions][16] = {
1261*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 2 },
1262*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1 },
1263*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 2, 0, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1 },
1264*03ce13f7SAndroid Build Coastguard Worker { 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 1, 1 },
1265*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2 },
1266*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 2, 2 },
1267*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 },
1268*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1 },
1269*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2 },
1270*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2 },
1271*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2 },
1272*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2 },
1273*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2 },
1274*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2 },
1275*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2 },
1276*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0 },
1277*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2 },
1278*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0 },
1279*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2 },
1280*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1 },
1281*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2 },
1282*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 2, 1 },
1283*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2 },
1284*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 1, 0, 2, 2, 1, 0 },
1285*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0 },
1286*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 2, 0, 0, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2 },
1287*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1, 0, 1, 1, 0 },
1288*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1 },
1289*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 2, 2, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 2, 2 },
1290*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 0, 2, 2, 2, 2, 2 },
1291*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1 },
1292*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 2, 0, 0, 0, 2, 2, 1, 1, 2, 2, 2, 1 },
1293*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 2, 2, 2 },
1294*03ce13f7SAndroid Build Coastguard Worker { 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 2, 0, 0, 1, 1 },
1295*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 2, 2, 2 },
1296*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0 },
1297*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0 },
1298*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 },
1299*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 0, 1, 2, 0 },
1300*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1 },
1301*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1 },
1302*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2 },
1303*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1 },
1304*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 2, 2 },
1305*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1 },
1306*03ce13f7SAndroid Build Coastguard Worker { 0, 2, 2, 0, 1, 2, 2, 1, 0, 2, 2, 0, 1, 2, 2, 1 },
1307*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1 },
1308*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 },
1309*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2 },
1310*03ce13f7SAndroid Build Coastguard Worker { 0, 2, 2, 2, 0, 1, 1, 1, 0, 2, 2, 2, 0, 1, 1, 1 },
1311*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 2, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 2 },
1312*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2 },
1313*03ce13f7SAndroid Build Coastguard Worker { 0, 2, 2, 2, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2 },
1314*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2 },
1315*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2 },
1316*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2 },
1317*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2 },
1318*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2 },
1319*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2 },
1320*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2 },
1321*03ce13f7SAndroid Build Coastguard Worker { 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1 },
1322*03ce13f7SAndroid Build Coastguard Worker { 0, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2 },
1323*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
1324*03ce13f7SAndroid Build Coastguard Worker { 0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 2, 2, 2, 0 },
1325*03ce13f7SAndroid Build Coastguard Worker };
1326*03ce13f7SAndroid Build Coastguard Worker
1327*03ce13f7SAndroid Build Coastguard Worker static constexpr uint8_t AnchorTable2[MaxPartitions] = {
1328*03ce13f7SAndroid Build Coastguard Worker // clang-format off
1329*03ce13f7SAndroid Build Coastguard Worker 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
1330*03ce13f7SAndroid Build Coastguard Worker 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
1331*03ce13f7SAndroid Build Coastguard Worker 0xf, 0x2, 0x8, 0x2, 0x2, 0x8, 0x8, 0xf,
1332*03ce13f7SAndroid Build Coastguard Worker 0x2, 0x8, 0x2, 0x2, 0x8, 0x8, 0x2, 0x2,
1333*03ce13f7SAndroid Build Coastguard Worker 0xf, 0xf, 0x6, 0x8, 0x2, 0x8, 0xf, 0xf,
1334*03ce13f7SAndroid Build Coastguard Worker 0x2, 0x8, 0x2, 0x2, 0x2, 0xf, 0xf, 0x6,
1335*03ce13f7SAndroid Build Coastguard Worker 0x6, 0x2, 0x6, 0x8, 0xf, 0xf, 0x2, 0x2,
1336*03ce13f7SAndroid Build Coastguard Worker 0xf, 0xf, 0xf, 0xf, 0xf, 0x2, 0x2, 0xf,
1337*03ce13f7SAndroid Build Coastguard Worker // clang-format on
1338*03ce13f7SAndroid Build Coastguard Worker };
1339*03ce13f7SAndroid Build Coastguard Worker
1340*03ce13f7SAndroid Build Coastguard Worker static constexpr uint8_t AnchorTable3a[MaxPartitions] = {
1341*03ce13f7SAndroid Build Coastguard Worker // clang-format off
1342*03ce13f7SAndroid Build Coastguard Worker 0x3, 0x3, 0xf, 0xf, 0x8, 0x3, 0xf, 0xf,
1343*03ce13f7SAndroid Build Coastguard Worker 0x8, 0x8, 0x6, 0x6, 0x6, 0x5, 0x3, 0x3,
1344*03ce13f7SAndroid Build Coastguard Worker 0x3, 0x3, 0x8, 0xf, 0x3, 0x3, 0x6, 0xa,
1345*03ce13f7SAndroid Build Coastguard Worker 0x5, 0x8, 0x8, 0x6, 0x8, 0x5, 0xf, 0xf,
1346*03ce13f7SAndroid Build Coastguard Worker 0x8, 0xf, 0x3, 0x5, 0x6, 0xa, 0x8, 0xf,
1347*03ce13f7SAndroid Build Coastguard Worker 0xf, 0x3, 0xf, 0x5, 0xf, 0xf, 0xf, 0xf,
1348*03ce13f7SAndroid Build Coastguard Worker 0x3, 0xf, 0x5, 0x5, 0x5, 0x8, 0x5, 0xa,
1349*03ce13f7SAndroid Build Coastguard Worker 0x5, 0xa, 0x8, 0xd, 0xf, 0xc, 0x3, 0x3,
1350*03ce13f7SAndroid Build Coastguard Worker // clang-format on
1351*03ce13f7SAndroid Build Coastguard Worker };
1352*03ce13f7SAndroid Build Coastguard Worker
1353*03ce13f7SAndroid Build Coastguard Worker static constexpr uint8_t AnchorTable3b[MaxPartitions] = {
1354*03ce13f7SAndroid Build Coastguard Worker // clang-format off
1355*03ce13f7SAndroid Build Coastguard Worker 0xf, 0x8, 0x8, 0x3, 0xf, 0xf, 0x3, 0x8,
1356*03ce13f7SAndroid Build Coastguard Worker 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x8,
1357*03ce13f7SAndroid Build Coastguard Worker 0xf, 0x8, 0xf, 0x3, 0xf, 0x8, 0xf, 0x8,
1358*03ce13f7SAndroid Build Coastguard Worker 0x3, 0xf, 0x6, 0xa, 0xf, 0xf, 0xa, 0x8,
1359*03ce13f7SAndroid Build Coastguard Worker 0xf, 0x3, 0xf, 0xa, 0xa, 0x8, 0x9, 0xa,
1360*03ce13f7SAndroid Build Coastguard Worker 0x6, 0xf, 0x8, 0xf, 0x3, 0x6, 0x6, 0x8,
1361*03ce13f7SAndroid Build Coastguard Worker 0xf, 0x3, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
1362*03ce13f7SAndroid Build Coastguard Worker 0xf, 0xf, 0xf, 0xf, 0x3, 0xf, 0xf, 0x8,
1363*03ce13f7SAndroid Build Coastguard Worker // clang-format on
1364*03ce13f7SAndroid Build Coastguard Worker };
1365*03ce13f7SAndroid Build Coastguard Worker
1366*03ce13f7SAndroid Build Coastguard Worker struct Color
1367*03ce13f7SAndroid Build Coastguard Worker {
1368*03ce13f7SAndroid Build Coastguard Worker struct RGB
1369*03ce13f7SAndroid Build Coastguard Worker {
1370*03ce13f7SAndroid Build Coastguard Worker RGB() = default;
RGB__anon204fc45b0111::BC7::Color::RGB1371*03ce13f7SAndroid Build Coastguard Worker RGB(uint8_t r, uint8_t g, uint8_t b)
1372*03ce13f7SAndroid Build Coastguard Worker : b(b)
1373*03ce13f7SAndroid Build Coastguard Worker , g(g)
1374*03ce13f7SAndroid Build Coastguard Worker , r(r)
1375*03ce13f7SAndroid Build Coastguard Worker {}
RGB__anon204fc45b0111::BC7::Color::RGB1376*03ce13f7SAndroid Build Coastguard Worker RGB(int r, int g, int b)
1377*03ce13f7SAndroid Build Coastguard Worker : b(static_cast<uint8_t>(b))
1378*03ce13f7SAndroid Build Coastguard Worker , g(static_cast<uint8_t>(g))
1379*03ce13f7SAndroid Build Coastguard Worker , r(static_cast<uint8_t>(r))
1380*03ce13f7SAndroid Build Coastguard Worker {}
1381*03ce13f7SAndroid Build Coastguard Worker
operator <<__anon204fc45b0111::BC7::Color::RGB1382*03ce13f7SAndroid Build Coastguard Worker RGB operator<<(int shift) const { return { r << shift, g << shift, b << shift }; }
operator >>__anon204fc45b0111::BC7::Color::RGB1383*03ce13f7SAndroid Build Coastguard Worker RGB operator>>(int shift) const { return { r >> shift, g >> shift, b >> shift }; }
operator |__anon204fc45b0111::BC7::Color::RGB1384*03ce13f7SAndroid Build Coastguard Worker RGB operator|(int bits) const { return { r | bits, g | bits, b | bits }; }
operator |__anon204fc45b0111::BC7::Color::RGB1385*03ce13f7SAndroid Build Coastguard Worker RGB operator|(const RGB &rhs) const { return { r | rhs.r, g | rhs.g, b | rhs.b }; }
operator +__anon204fc45b0111::BC7::Color::RGB1386*03ce13f7SAndroid Build Coastguard Worker RGB operator+(const RGB &rhs) const { return { r + rhs.r, g + rhs.g, b + rhs.b }; }
1387*03ce13f7SAndroid Build Coastguard Worker
1388*03ce13f7SAndroid Build Coastguard Worker uint8_t b;
1389*03ce13f7SAndroid Build Coastguard Worker uint8_t g;
1390*03ce13f7SAndroid Build Coastguard Worker uint8_t r;
1391*03ce13f7SAndroid Build Coastguard Worker };
1392*03ce13f7SAndroid Build Coastguard Worker
1393*03ce13f7SAndroid Build Coastguard Worker RGB rgb;
1394*03ce13f7SAndroid Build Coastguard Worker uint8_t a;
1395*03ce13f7SAndroid Build Coastguard Worker };
1396*03ce13f7SAndroid Build Coastguard Worker
1397*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(Color) == 4, "Color size must be 4 bytes");
1398*03ce13f7SAndroid Build Coastguard Worker
1399*03ce13f7SAndroid Build Coastguard Worker struct Block
1400*03ce13f7SAndroid Build Coastguard Worker {
Get__anon204fc45b0111::BC7::Block1401*03ce13f7SAndroid Build Coastguard Worker constexpr uint64_t Get(const Bitfield &bf) const
1402*03ce13f7SAndroid Build Coastguard Worker {
1403*03ce13f7SAndroid Build Coastguard Worker uint64_t mask = (1ULL << bf.count) - 1;
1404*03ce13f7SAndroid Build Coastguard Worker if(bf.offset + bf.count <= 64)
1405*03ce13f7SAndroid Build Coastguard Worker {
1406*03ce13f7SAndroid Build Coastguard Worker return (low >> bf.offset) & mask;
1407*03ce13f7SAndroid Build Coastguard Worker }
1408*03ce13f7SAndroid Build Coastguard Worker if(bf.offset >= 64)
1409*03ce13f7SAndroid Build Coastguard Worker {
1410*03ce13f7SAndroid Build Coastguard Worker return (high >> (bf.offset - 64)) & mask;
1411*03ce13f7SAndroid Build Coastguard Worker }
1412*03ce13f7SAndroid Build Coastguard Worker return ((low >> bf.offset) | (high << (64 - bf.offset))) & mask;
1413*03ce13f7SAndroid Build Coastguard Worker }
1414*03ce13f7SAndroid Build Coastguard Worker
mode__anon204fc45b0111::BC7::Block1415*03ce13f7SAndroid Build Coastguard Worker const Mode &mode() const
1416*03ce13f7SAndroid Build Coastguard Worker {
1417*03ce13f7SAndroid Build Coastguard Worker if((low & 0b00000001) != 0) { return Modes[0]; }
1418*03ce13f7SAndroid Build Coastguard Worker if((low & 0b00000010) != 0) { return Modes[1]; }
1419*03ce13f7SAndroid Build Coastguard Worker if((low & 0b00000100) != 0) { return Modes[2]; }
1420*03ce13f7SAndroid Build Coastguard Worker if((low & 0b00001000) != 0) { return Modes[3]; }
1421*03ce13f7SAndroid Build Coastguard Worker if((low & 0b00010000) != 0) { return Modes[4]; }
1422*03ce13f7SAndroid Build Coastguard Worker if((low & 0b00100000) != 0) { return Modes[5]; }
1423*03ce13f7SAndroid Build Coastguard Worker if((low & 0b01000000) != 0) { return Modes[6]; }
1424*03ce13f7SAndroid Build Coastguard Worker if((low & 0b10000000) != 0) { return Modes[7]; }
1425*03ce13f7SAndroid Build Coastguard Worker return Modes[8]; // Invalid mode
1426*03ce13f7SAndroid Build Coastguard Worker }
1427*03ce13f7SAndroid Build Coastguard Worker
1428*03ce13f7SAndroid Build Coastguard Worker struct IndexInfo
1429*03ce13f7SAndroid Build Coastguard Worker {
1430*03ce13f7SAndroid Build Coastguard Worker uint64_t value;
1431*03ce13f7SAndroid Build Coastguard Worker int numBits;
1432*03ce13f7SAndroid Build Coastguard Worker };
1433*03ce13f7SAndroid Build Coastguard Worker
interpolate__anon204fc45b0111::BC7::Block1434*03ce13f7SAndroid Build Coastguard Worker uint8_t interpolate(uint8_t e0, uint8_t e1, const IndexInfo &index) const
1435*03ce13f7SAndroid Build Coastguard Worker {
1436*03ce13f7SAndroid Build Coastguard Worker static constexpr uint16_t weights2[] = { 0, 21, 43, 64 };
1437*03ce13f7SAndroid Build Coastguard Worker static constexpr uint16_t weights3[] = { 0, 9, 18, 27, 37, 46, 55, 64 };
1438*03ce13f7SAndroid Build Coastguard Worker static constexpr uint16_t weights4[] = { 0, 4, 9, 13, 17, 21, 26, 30,
1439*03ce13f7SAndroid Build Coastguard Worker 34, 38, 43, 47, 51, 55, 60, 64 };
1440*03ce13f7SAndroid Build Coastguard Worker static const uint16_t constexpr *weightsN[] = {
1441*03ce13f7SAndroid Build Coastguard Worker nullptr, nullptr, weights2, weights3, weights4
1442*03ce13f7SAndroid Build Coastguard Worker };
1443*03ce13f7SAndroid Build Coastguard Worker const uint16_t *weights = weightsN[index.numBits];
1444*03ce13f7SAndroid Build Coastguard Worker ASSERT_MSG(weights != nullptr, "Unexpected number of index bits: %d", (int)index.numBits);
1445*03ce13f7SAndroid Build Coastguard Worker return (uint8_t)(((64 - weights[index.value]) * uint16_t(e0) + weights[index.value] * uint16_t(e1) + 32) >> 6);
1446*03ce13f7SAndroid Build Coastguard Worker }
1447*03ce13f7SAndroid Build Coastguard Worker
decode__anon204fc45b0111::BC7::Block1448*03ce13f7SAndroid Build Coastguard Worker void decode(uint8_t *dst, int dstX, int dstY, int dstWidth, int dstHeight, size_t dstPitch) const
1449*03ce13f7SAndroid Build Coastguard Worker {
1450*03ce13f7SAndroid Build Coastguard Worker const auto &mode = this->mode();
1451*03ce13f7SAndroid Build Coastguard Worker
1452*03ce13f7SAndroid Build Coastguard Worker if(mode.IDX < 0) // Invalid mode:
1453*03ce13f7SAndroid Build Coastguard Worker {
1454*03ce13f7SAndroid Build Coastguard Worker for(int y = 0; y < 4 && y + dstY < dstHeight; y++)
1455*03ce13f7SAndroid Build Coastguard Worker {
1456*03ce13f7SAndroid Build Coastguard Worker for(int x = 0; x < 4 && x + dstX < dstWidth; x++)
1457*03ce13f7SAndroid Build Coastguard Worker {
1458*03ce13f7SAndroid Build Coastguard Worker auto out = reinterpret_cast<Color *>(dst + sizeof(Color) * x + dstPitch * y);
1459*03ce13f7SAndroid Build Coastguard Worker out->rgb = { 0, 0, 0 };
1460*03ce13f7SAndroid Build Coastguard Worker out->a = 0;
1461*03ce13f7SAndroid Build Coastguard Worker }
1462*03ce13f7SAndroid Build Coastguard Worker }
1463*03ce13f7SAndroid Build Coastguard Worker return;
1464*03ce13f7SAndroid Build Coastguard Worker }
1465*03ce13f7SAndroid Build Coastguard Worker
1466*03ce13f7SAndroid Build Coastguard Worker using Endpoint = std::array<Color, 2>;
1467*03ce13f7SAndroid Build Coastguard Worker std::array<Endpoint, MaxSubsets> subsets;
1468*03ce13f7SAndroid Build Coastguard Worker
1469*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < mode.NS; i++)
1470*03ce13f7SAndroid Build Coastguard Worker {
1471*03ce13f7SAndroid Build Coastguard Worker auto &subset = subsets[i];
1472*03ce13f7SAndroid Build Coastguard Worker subset[0].rgb.r = Get(mode.Red(i * 2 + 0));
1473*03ce13f7SAndroid Build Coastguard Worker subset[0].rgb.g = Get(mode.Green(i * 2 + 0));
1474*03ce13f7SAndroid Build Coastguard Worker subset[0].rgb.b = Get(mode.Blue(i * 2 + 0));
1475*03ce13f7SAndroid Build Coastguard Worker subset[0].a = (mode.AB > 0) ? Get(mode.Alpha(i * 2 + 0)) : 255;
1476*03ce13f7SAndroid Build Coastguard Worker
1477*03ce13f7SAndroid Build Coastguard Worker subset[1].rgb.r = Get(mode.Red(i * 2 + 1));
1478*03ce13f7SAndroid Build Coastguard Worker subset[1].rgb.g = Get(mode.Green(i * 2 + 1));
1479*03ce13f7SAndroid Build Coastguard Worker subset[1].rgb.b = Get(mode.Blue(i * 2 + 1));
1480*03ce13f7SAndroid Build Coastguard Worker subset[1].a = (mode.AB > 0) ? Get(mode.Alpha(i * 2 + 1)) : 255;
1481*03ce13f7SAndroid Build Coastguard Worker }
1482*03ce13f7SAndroid Build Coastguard Worker
1483*03ce13f7SAndroid Build Coastguard Worker if(mode.SPB > 0)
1484*03ce13f7SAndroid Build Coastguard Worker {
1485*03ce13f7SAndroid Build Coastguard Worker auto pbit0 = Get(mode.SharedPBit0());
1486*03ce13f7SAndroid Build Coastguard Worker auto pbit1 = Get(mode.SharedPBit1());
1487*03ce13f7SAndroid Build Coastguard Worker subsets[0][0].rgb = (subsets[0][0].rgb << 1) | pbit0;
1488*03ce13f7SAndroid Build Coastguard Worker subsets[0][1].rgb = (subsets[0][1].rgb << 1) | pbit0;
1489*03ce13f7SAndroid Build Coastguard Worker subsets[1][0].rgb = (subsets[1][0].rgb << 1) | pbit1;
1490*03ce13f7SAndroid Build Coastguard Worker subsets[1][1].rgb = (subsets[1][1].rgb << 1) | pbit1;
1491*03ce13f7SAndroid Build Coastguard Worker }
1492*03ce13f7SAndroid Build Coastguard Worker
1493*03ce13f7SAndroid Build Coastguard Worker if(mode.EPB > 0)
1494*03ce13f7SAndroid Build Coastguard Worker {
1495*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < mode.NS; i++)
1496*03ce13f7SAndroid Build Coastguard Worker {
1497*03ce13f7SAndroid Build Coastguard Worker auto &subset = subsets[i];
1498*03ce13f7SAndroid Build Coastguard Worker auto pbit0 = Get(mode.EndpointPBit(i * 2 + 0));
1499*03ce13f7SAndroid Build Coastguard Worker auto pbit1 = Get(mode.EndpointPBit(i * 2 + 1));
1500*03ce13f7SAndroid Build Coastguard Worker subset[0].rgb = (subset[0].rgb << 1) | pbit0;
1501*03ce13f7SAndroid Build Coastguard Worker subset[1].rgb = (subset[1].rgb << 1) | pbit1;
1502*03ce13f7SAndroid Build Coastguard Worker if(mode.AB > 0)
1503*03ce13f7SAndroid Build Coastguard Worker {
1504*03ce13f7SAndroid Build Coastguard Worker subset[0].a = (subset[0].a << 1) | pbit0;
1505*03ce13f7SAndroid Build Coastguard Worker subset[1].a = (subset[1].a << 1) | pbit1;
1506*03ce13f7SAndroid Build Coastguard Worker }
1507*03ce13f7SAndroid Build Coastguard Worker }
1508*03ce13f7SAndroid Build Coastguard Worker }
1509*03ce13f7SAndroid Build Coastguard Worker
1510*03ce13f7SAndroid Build Coastguard Worker const auto colorBits = mode.CB + mode.SPB + mode.EPB;
1511*03ce13f7SAndroid Build Coastguard Worker const auto alphaBits = mode.AB + mode.SPB + mode.EPB;
1512*03ce13f7SAndroid Build Coastguard Worker
1513*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < mode.NS; i++)
1514*03ce13f7SAndroid Build Coastguard Worker {
1515*03ce13f7SAndroid Build Coastguard Worker auto &subset = subsets[i];
1516*03ce13f7SAndroid Build Coastguard Worker subset[0].rgb = subset[0].rgb << (8 - colorBits);
1517*03ce13f7SAndroid Build Coastguard Worker subset[1].rgb = subset[1].rgb << (8 - colorBits);
1518*03ce13f7SAndroid Build Coastguard Worker subset[0].rgb = subset[0].rgb | (subset[0].rgb >> colorBits);
1519*03ce13f7SAndroid Build Coastguard Worker subset[1].rgb = subset[1].rgb | (subset[1].rgb >> colorBits);
1520*03ce13f7SAndroid Build Coastguard Worker
1521*03ce13f7SAndroid Build Coastguard Worker if(mode.AB > 0)
1522*03ce13f7SAndroid Build Coastguard Worker {
1523*03ce13f7SAndroid Build Coastguard Worker subset[0].a = subset[0].a << (8 - alphaBits);
1524*03ce13f7SAndroid Build Coastguard Worker subset[1].a = subset[1].a << (8 - alphaBits);
1525*03ce13f7SAndroid Build Coastguard Worker subset[0].a = subset[0].a | (subset[0].a >> alphaBits);
1526*03ce13f7SAndroid Build Coastguard Worker subset[1].a = subset[1].a | (subset[1].a >> alphaBits);
1527*03ce13f7SAndroid Build Coastguard Worker }
1528*03ce13f7SAndroid Build Coastguard Worker }
1529*03ce13f7SAndroid Build Coastguard Worker
1530*03ce13f7SAndroid Build Coastguard Worker int colorIndexBitOffset = 0;
1531*03ce13f7SAndroid Build Coastguard Worker int alphaIndexBitOffset = 0;
1532*03ce13f7SAndroid Build Coastguard Worker for(int y = 0; y < 4; y++)
1533*03ce13f7SAndroid Build Coastguard Worker {
1534*03ce13f7SAndroid Build Coastguard Worker for(int x = 0; x < 4; x++)
1535*03ce13f7SAndroid Build Coastguard Worker {
1536*03ce13f7SAndroid Build Coastguard Worker auto texelIdx = y * 4 + x;
1537*03ce13f7SAndroid Build Coastguard Worker auto partitionIdx = Get(mode.Partition());
1538*03ce13f7SAndroid Build Coastguard Worker ASSERT(partitionIdx < MaxPartitions);
1539*03ce13f7SAndroid Build Coastguard Worker auto subsetIdx = subsetIndex(mode, partitionIdx, texelIdx);
1540*03ce13f7SAndroid Build Coastguard Worker ASSERT(subsetIdx < MaxSubsets);
1541*03ce13f7SAndroid Build Coastguard Worker const auto &subset = subsets[subsetIdx];
1542*03ce13f7SAndroid Build Coastguard Worker
1543*03ce13f7SAndroid Build Coastguard Worker auto anchorIdx = anchorIndex(mode, partitionIdx, subsetIdx);
1544*03ce13f7SAndroid Build Coastguard Worker auto isAnchor = anchorIdx == texelIdx;
1545*03ce13f7SAndroid Build Coastguard Worker auto colorIdx = colorIndex(mode, isAnchor, colorIndexBitOffset);
1546*03ce13f7SAndroid Build Coastguard Worker auto alphaIdx = alphaIndex(mode, isAnchor, alphaIndexBitOffset);
1547*03ce13f7SAndroid Build Coastguard Worker
1548*03ce13f7SAndroid Build Coastguard Worker if(y + dstY >= dstHeight || x + dstX >= dstWidth)
1549*03ce13f7SAndroid Build Coastguard Worker {
1550*03ce13f7SAndroid Build Coastguard Worker // Don't be tempted to skip early at the loops:
1551*03ce13f7SAndroid Build Coastguard Worker // The calls to colorIndex() and alphaIndex() adjust bit
1552*03ce13f7SAndroid Build Coastguard Worker // offsets that need to be carefully tracked.
1553*03ce13f7SAndroid Build Coastguard Worker continue;
1554*03ce13f7SAndroid Build Coastguard Worker }
1555*03ce13f7SAndroid Build Coastguard Worker
1556*03ce13f7SAndroid Build Coastguard Worker Color output;
1557*03ce13f7SAndroid Build Coastguard Worker output.rgb.r = interpolate(subset[0].rgb.r, subset[1].rgb.r, colorIdx);
1558*03ce13f7SAndroid Build Coastguard Worker output.rgb.g = interpolate(subset[0].rgb.g, subset[1].rgb.g, colorIdx);
1559*03ce13f7SAndroid Build Coastguard Worker output.rgb.b = interpolate(subset[0].rgb.b, subset[1].rgb.b, colorIdx);
1560*03ce13f7SAndroid Build Coastguard Worker output.a = interpolate(subset[0].a, subset[1].a, alphaIdx);
1561*03ce13f7SAndroid Build Coastguard Worker
1562*03ce13f7SAndroid Build Coastguard Worker switch(Get(mode.Rotation()))
1563*03ce13f7SAndroid Build Coastguard Worker {
1564*03ce13f7SAndroid Build Coastguard Worker default:
1565*03ce13f7SAndroid Build Coastguard Worker break;
1566*03ce13f7SAndroid Build Coastguard Worker case 1:
1567*03ce13f7SAndroid Build Coastguard Worker std::swap(output.a, output.rgb.r);
1568*03ce13f7SAndroid Build Coastguard Worker break;
1569*03ce13f7SAndroid Build Coastguard Worker case 2:
1570*03ce13f7SAndroid Build Coastguard Worker std::swap(output.a, output.rgb.g);
1571*03ce13f7SAndroid Build Coastguard Worker break;
1572*03ce13f7SAndroid Build Coastguard Worker case 3:
1573*03ce13f7SAndroid Build Coastguard Worker std::swap(output.a, output.rgb.b);
1574*03ce13f7SAndroid Build Coastguard Worker break;
1575*03ce13f7SAndroid Build Coastguard Worker }
1576*03ce13f7SAndroid Build Coastguard Worker
1577*03ce13f7SAndroid Build Coastguard Worker auto out = reinterpret_cast<Color *>(dst + sizeof(Color) * x + dstPitch * y);
1578*03ce13f7SAndroid Build Coastguard Worker *out = output;
1579*03ce13f7SAndroid Build Coastguard Worker }
1580*03ce13f7SAndroid Build Coastguard Worker }
1581*03ce13f7SAndroid Build Coastguard Worker }
1582*03ce13f7SAndroid Build Coastguard Worker
subsetIndex__anon204fc45b0111::BC7::Block1583*03ce13f7SAndroid Build Coastguard Worker int subsetIndex(const Mode &mode, int partitionIdx, int texelIndex) const
1584*03ce13f7SAndroid Build Coastguard Worker {
1585*03ce13f7SAndroid Build Coastguard Worker switch(mode.NS)
1586*03ce13f7SAndroid Build Coastguard Worker {
1587*03ce13f7SAndroid Build Coastguard Worker default:
1588*03ce13f7SAndroid Build Coastguard Worker return 0;
1589*03ce13f7SAndroid Build Coastguard Worker case 2:
1590*03ce13f7SAndroid Build Coastguard Worker return PartitionTable2[partitionIdx][texelIndex];
1591*03ce13f7SAndroid Build Coastguard Worker case 3:
1592*03ce13f7SAndroid Build Coastguard Worker return PartitionTable3[partitionIdx][texelIndex];
1593*03ce13f7SAndroid Build Coastguard Worker }
1594*03ce13f7SAndroid Build Coastguard Worker }
1595*03ce13f7SAndroid Build Coastguard Worker
anchorIndex__anon204fc45b0111::BC7::Block1596*03ce13f7SAndroid Build Coastguard Worker int anchorIndex(const Mode &mode, int partitionIdx, int subsetIdx) const
1597*03ce13f7SAndroid Build Coastguard Worker {
1598*03ce13f7SAndroid Build Coastguard Worker // ARB_texture_compression_bptc states:
1599*03ce13f7SAndroid Build Coastguard Worker // "In partition zero, the anchor index is always index zero.
1600*03ce13f7SAndroid Build Coastguard Worker // In other partitions, the anchor index is specified by tables
1601*03ce13f7SAndroid Build Coastguard Worker // Table.A2 and Table.A3.""
1602*03ce13f7SAndroid Build Coastguard Worker // Note: This is really confusing - I believe they meant subset instead
1603*03ce13f7SAndroid Build Coastguard Worker // of partition here.
1604*03ce13f7SAndroid Build Coastguard Worker switch(subsetIdx)
1605*03ce13f7SAndroid Build Coastguard Worker {
1606*03ce13f7SAndroid Build Coastguard Worker default:
1607*03ce13f7SAndroid Build Coastguard Worker return 0;
1608*03ce13f7SAndroid Build Coastguard Worker case 1:
1609*03ce13f7SAndroid Build Coastguard Worker return mode.NS == 2 ? AnchorTable2[partitionIdx] : AnchorTable3a[partitionIdx];
1610*03ce13f7SAndroid Build Coastguard Worker case 2:
1611*03ce13f7SAndroid Build Coastguard Worker return AnchorTable3b[partitionIdx];
1612*03ce13f7SAndroid Build Coastguard Worker }
1613*03ce13f7SAndroid Build Coastguard Worker }
1614*03ce13f7SAndroid Build Coastguard Worker
colorIndex__anon204fc45b0111::BC7::Block1615*03ce13f7SAndroid Build Coastguard Worker IndexInfo colorIndex(const Mode &mode, bool isAnchor,
1616*03ce13f7SAndroid Build Coastguard Worker int &indexBitOffset) const
1617*03ce13f7SAndroid Build Coastguard Worker {
1618*03ce13f7SAndroid Build Coastguard Worker // ARB_texture_compression_bptc states:
1619*03ce13f7SAndroid Build Coastguard Worker // "The index value for interpolating color comes from the secondary
1620*03ce13f7SAndroid Build Coastguard Worker // index for the texel if the format has an index selection bit and its
1621*03ce13f7SAndroid Build Coastguard Worker // value is one and from the primary index otherwise.""
1622*03ce13f7SAndroid Build Coastguard Worker auto idx = Get(mode.IndexSelection());
1623*03ce13f7SAndroid Build Coastguard Worker ASSERT(idx <= 1);
1624*03ce13f7SAndroid Build Coastguard Worker bool secondary = idx == 1;
1625*03ce13f7SAndroid Build Coastguard Worker auto numBits = secondary ? mode.IB2 : mode.IB;
1626*03ce13f7SAndroid Build Coastguard Worker auto numReadBits = numBits - (isAnchor ? 1 : 0);
1627*03ce13f7SAndroid Build Coastguard Worker auto index =
1628*03ce13f7SAndroid Build Coastguard Worker Get(secondary ? mode.SecondaryIndex(indexBitOffset, numReadBits)
1629*03ce13f7SAndroid Build Coastguard Worker : mode.PrimaryIndex(indexBitOffset, numReadBits));
1630*03ce13f7SAndroid Build Coastguard Worker indexBitOffset += numReadBits;
1631*03ce13f7SAndroid Build Coastguard Worker return { index, numBits };
1632*03ce13f7SAndroid Build Coastguard Worker }
1633*03ce13f7SAndroid Build Coastguard Worker
alphaIndex__anon204fc45b0111::BC7::Block1634*03ce13f7SAndroid Build Coastguard Worker IndexInfo alphaIndex(const Mode &mode, bool isAnchor,
1635*03ce13f7SAndroid Build Coastguard Worker int &indexBitOffset) const
1636*03ce13f7SAndroid Build Coastguard Worker {
1637*03ce13f7SAndroid Build Coastguard Worker // ARB_texture_compression_bptc states:
1638*03ce13f7SAndroid Build Coastguard Worker // "The alpha index comes from the secondary index if the block has a
1639*03ce13f7SAndroid Build Coastguard Worker // secondary index and the block either doesn't have an index selection
1640*03ce13f7SAndroid Build Coastguard Worker // bit or that bit is zero and the primary index otherwise."
1641*03ce13f7SAndroid Build Coastguard Worker auto idx = Get(mode.IndexSelection());
1642*03ce13f7SAndroid Build Coastguard Worker ASSERT(idx <= 1);
1643*03ce13f7SAndroid Build Coastguard Worker bool secondary = (mode.IB2 != 0) && (idx == 0);
1644*03ce13f7SAndroid Build Coastguard Worker auto numBits = secondary ? mode.IB2 : mode.IB;
1645*03ce13f7SAndroid Build Coastguard Worker auto numReadBits = numBits - (isAnchor ? 1 : 0);
1646*03ce13f7SAndroid Build Coastguard Worker auto index =
1647*03ce13f7SAndroid Build Coastguard Worker Get(secondary ? mode.SecondaryIndex(indexBitOffset, numReadBits)
1648*03ce13f7SAndroid Build Coastguard Worker : mode.PrimaryIndex(indexBitOffset, numReadBits));
1649*03ce13f7SAndroid Build Coastguard Worker indexBitOffset += numReadBits;
1650*03ce13f7SAndroid Build Coastguard Worker return { index, numBits };
1651*03ce13f7SAndroid Build Coastguard Worker }
1652*03ce13f7SAndroid Build Coastguard Worker
1653*03ce13f7SAndroid Build Coastguard Worker // Assumes little-endian
1654*03ce13f7SAndroid Build Coastguard Worker uint64_t low;
1655*03ce13f7SAndroid Build Coastguard Worker uint64_t high;
1656*03ce13f7SAndroid Build Coastguard Worker };
1657*03ce13f7SAndroid Build Coastguard Worker
1658*03ce13f7SAndroid Build Coastguard Worker } // namespace BC7
1659*03ce13f7SAndroid Build Coastguard Worker } // anonymous namespace
1660*03ce13f7SAndroid Build Coastguard Worker
1661*03ce13f7SAndroid Build Coastguard Worker // Decodes 1 to 4 channel images to 8 bit output
Decode(const uint8_t * src,uint8_t * dst,int w,int h,int dstPitch,int dstBpp,int n,bool isNoAlphaU)1662*03ce13f7SAndroid Build Coastguard Worker bool BC_Decoder::Decode(const uint8_t *src, uint8_t *dst, int w, int h, int dstPitch, int dstBpp, int n, bool isNoAlphaU)
1663*03ce13f7SAndroid Build Coastguard Worker {
1664*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(BC_color) == 8, "BC_color must be 8 bytes");
1665*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(BC_channel) == 8, "BC_channel must be 8 bytes");
1666*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(BC_alpha) == 8, "BC_alpha must be 8 bytes");
1667*03ce13f7SAndroid Build Coastguard Worker
1668*03ce13f7SAndroid Build Coastguard Worker const int dx = BlockWidth * dstBpp;
1669*03ce13f7SAndroid Build Coastguard Worker const int dy = BlockHeight * dstPitch;
1670*03ce13f7SAndroid Build Coastguard Worker const bool isAlpha = (n == 1) && !isNoAlphaU;
1671*03ce13f7SAndroid Build Coastguard Worker const bool isSigned = ((n == 4) || (n == 5) || (n == 6)) && !isNoAlphaU;
1672*03ce13f7SAndroid Build Coastguard Worker
1673*03ce13f7SAndroid Build Coastguard Worker switch(n)
1674*03ce13f7SAndroid Build Coastguard Worker {
1675*03ce13f7SAndroid Build Coastguard Worker case 1: // BC1
1676*03ce13f7SAndroid Build Coastguard Worker {
1677*03ce13f7SAndroid Build Coastguard Worker const BC_color *color = reinterpret_cast<const BC_color *>(src);
1678*03ce13f7SAndroid Build Coastguard Worker for(int y = 0; y < h; y += BlockHeight, dst += dy)
1679*03ce13f7SAndroid Build Coastguard Worker {
1680*03ce13f7SAndroid Build Coastguard Worker uint8_t *dstRow = dst;
1681*03ce13f7SAndroid Build Coastguard Worker for(int x = 0; x < w; x += BlockWidth, ++color, dstRow += dx)
1682*03ce13f7SAndroid Build Coastguard Worker {
1683*03ce13f7SAndroid Build Coastguard Worker color->decode(dstRow, x, y, w, h, dstPitch, dstBpp, isAlpha, false);
1684*03ce13f7SAndroid Build Coastguard Worker }
1685*03ce13f7SAndroid Build Coastguard Worker }
1686*03ce13f7SAndroid Build Coastguard Worker }
1687*03ce13f7SAndroid Build Coastguard Worker break;
1688*03ce13f7SAndroid Build Coastguard Worker case 2: // BC2
1689*03ce13f7SAndroid Build Coastguard Worker {
1690*03ce13f7SAndroid Build Coastguard Worker const BC_alpha *alpha = reinterpret_cast<const BC_alpha *>(src);
1691*03ce13f7SAndroid Build Coastguard Worker const BC_color *color = reinterpret_cast<const BC_color *>(src + 8);
1692*03ce13f7SAndroid Build Coastguard Worker for(int y = 0; y < h; y += BlockHeight, dst += dy)
1693*03ce13f7SAndroid Build Coastguard Worker {
1694*03ce13f7SAndroid Build Coastguard Worker uint8_t *dstRow = dst;
1695*03ce13f7SAndroid Build Coastguard Worker for(int x = 0; x < w; x += BlockWidth, alpha += 2, color += 2, dstRow += dx)
1696*03ce13f7SAndroid Build Coastguard Worker {
1697*03ce13f7SAndroid Build Coastguard Worker color->decode(dstRow, x, y, w, h, dstPitch, dstBpp, isAlpha, true);
1698*03ce13f7SAndroid Build Coastguard Worker alpha->decode(dstRow, x, y, w, h, dstPitch, dstBpp);
1699*03ce13f7SAndroid Build Coastguard Worker }
1700*03ce13f7SAndroid Build Coastguard Worker }
1701*03ce13f7SAndroid Build Coastguard Worker }
1702*03ce13f7SAndroid Build Coastguard Worker break;
1703*03ce13f7SAndroid Build Coastguard Worker case 3: // BC3
1704*03ce13f7SAndroid Build Coastguard Worker {
1705*03ce13f7SAndroid Build Coastguard Worker const BC_channel *alpha = reinterpret_cast<const BC_channel *>(src);
1706*03ce13f7SAndroid Build Coastguard Worker const BC_color *color = reinterpret_cast<const BC_color *>(src + 8);
1707*03ce13f7SAndroid Build Coastguard Worker for(int y = 0; y < h; y += BlockHeight, dst += dy)
1708*03ce13f7SAndroid Build Coastguard Worker {
1709*03ce13f7SAndroid Build Coastguard Worker uint8_t *dstRow = dst;
1710*03ce13f7SAndroid Build Coastguard Worker for(int x = 0; x < w; x += BlockWidth, alpha += 2, color += 2, dstRow += dx)
1711*03ce13f7SAndroid Build Coastguard Worker {
1712*03ce13f7SAndroid Build Coastguard Worker color->decode(dstRow, x, y, w, h, dstPitch, dstBpp, isAlpha, true);
1713*03ce13f7SAndroid Build Coastguard Worker alpha->decode(dstRow, x, y, w, h, dstPitch, dstBpp, 3, isSigned);
1714*03ce13f7SAndroid Build Coastguard Worker }
1715*03ce13f7SAndroid Build Coastguard Worker }
1716*03ce13f7SAndroid Build Coastguard Worker }
1717*03ce13f7SAndroid Build Coastguard Worker break;
1718*03ce13f7SAndroid Build Coastguard Worker case 4: // BC4
1719*03ce13f7SAndroid Build Coastguard Worker {
1720*03ce13f7SAndroid Build Coastguard Worker const BC_channel *red = reinterpret_cast<const BC_channel *>(src);
1721*03ce13f7SAndroid Build Coastguard Worker for(int y = 0; y < h; y += BlockHeight, dst += dy)
1722*03ce13f7SAndroid Build Coastguard Worker {
1723*03ce13f7SAndroid Build Coastguard Worker uint8_t *dstRow = dst;
1724*03ce13f7SAndroid Build Coastguard Worker for(int x = 0; x < w; x += BlockWidth, ++red, dstRow += dx)
1725*03ce13f7SAndroid Build Coastguard Worker {
1726*03ce13f7SAndroid Build Coastguard Worker red->decode(dstRow, x, y, w, h, dstPitch, dstBpp, 0, isSigned);
1727*03ce13f7SAndroid Build Coastguard Worker }
1728*03ce13f7SAndroid Build Coastguard Worker }
1729*03ce13f7SAndroid Build Coastguard Worker }
1730*03ce13f7SAndroid Build Coastguard Worker break;
1731*03ce13f7SAndroid Build Coastguard Worker case 5: // BC5
1732*03ce13f7SAndroid Build Coastguard Worker {
1733*03ce13f7SAndroid Build Coastguard Worker const BC_channel *red = reinterpret_cast<const BC_channel *>(src);
1734*03ce13f7SAndroid Build Coastguard Worker const BC_channel *green = reinterpret_cast<const BC_channel *>(src + 8);
1735*03ce13f7SAndroid Build Coastguard Worker for(int y = 0; y < h; y += BlockHeight, dst += dy)
1736*03ce13f7SAndroid Build Coastguard Worker {
1737*03ce13f7SAndroid Build Coastguard Worker uint8_t *dstRow = dst;
1738*03ce13f7SAndroid Build Coastguard Worker for(int x = 0; x < w; x += BlockWidth, red += 2, green += 2, dstRow += dx)
1739*03ce13f7SAndroid Build Coastguard Worker {
1740*03ce13f7SAndroid Build Coastguard Worker red->decode(dstRow, x, y, w, h, dstPitch, dstBpp, 0, isSigned);
1741*03ce13f7SAndroid Build Coastguard Worker green->decode(dstRow, x, y, w, h, dstPitch, dstBpp, 1, isSigned);
1742*03ce13f7SAndroid Build Coastguard Worker }
1743*03ce13f7SAndroid Build Coastguard Worker }
1744*03ce13f7SAndroid Build Coastguard Worker }
1745*03ce13f7SAndroid Build Coastguard Worker break;
1746*03ce13f7SAndroid Build Coastguard Worker case 6: // BC6H
1747*03ce13f7SAndroid Build Coastguard Worker {
1748*03ce13f7SAndroid Build Coastguard Worker const BC6H::Block *block = reinterpret_cast<const BC6H::Block *>(src);
1749*03ce13f7SAndroid Build Coastguard Worker for(int y = 0; y < h; y += BlockHeight, dst += dy)
1750*03ce13f7SAndroid Build Coastguard Worker {
1751*03ce13f7SAndroid Build Coastguard Worker uint8_t *dstRow = dst;
1752*03ce13f7SAndroid Build Coastguard Worker for(int x = 0; x < w; x += BlockWidth, ++block, dstRow += dx)
1753*03ce13f7SAndroid Build Coastguard Worker {
1754*03ce13f7SAndroid Build Coastguard Worker block->decode(dstRow, x, y, w, h, dstPitch, dstBpp, isSigned);
1755*03ce13f7SAndroid Build Coastguard Worker }
1756*03ce13f7SAndroid Build Coastguard Worker }
1757*03ce13f7SAndroid Build Coastguard Worker }
1758*03ce13f7SAndroid Build Coastguard Worker break;
1759*03ce13f7SAndroid Build Coastguard Worker case 7: // BC7
1760*03ce13f7SAndroid Build Coastguard Worker {
1761*03ce13f7SAndroid Build Coastguard Worker const BC7::Block *block = reinterpret_cast<const BC7::Block *>(src);
1762*03ce13f7SAndroid Build Coastguard Worker for(int y = 0; y < h; y += BlockHeight, dst += dy)
1763*03ce13f7SAndroid Build Coastguard Worker {
1764*03ce13f7SAndroid Build Coastguard Worker uint8_t *dstRow = dst;
1765*03ce13f7SAndroid Build Coastguard Worker for(int x = 0; x < w; x += BlockWidth, ++block, dstRow += dx)
1766*03ce13f7SAndroid Build Coastguard Worker {
1767*03ce13f7SAndroid Build Coastguard Worker block->decode(dstRow, x, y, w, h, dstPitch);
1768*03ce13f7SAndroid Build Coastguard Worker }
1769*03ce13f7SAndroid Build Coastguard Worker }
1770*03ce13f7SAndroid Build Coastguard Worker }
1771*03ce13f7SAndroid Build Coastguard Worker break;
1772*03ce13f7SAndroid Build Coastguard Worker default:
1773*03ce13f7SAndroid Build Coastguard Worker return false;
1774*03ce13f7SAndroid Build Coastguard Worker }
1775*03ce13f7SAndroid Build Coastguard Worker
1776*03ce13f7SAndroid Build Coastguard Worker return true;
1777*03ce13f7SAndroid Build Coastguard Worker }
1778