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