• 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__anon659343cc0111::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__anon659343cc0111::BC_color::Color67 		Color()
68 		{
69 			c[0] = c[1] = c[2] = 0;
70 			c[3] = 0xFF000000;
71 		}
72 
extract565__anon659343cc0111::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__anon659343cc0111::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__anon659343cc0111::BC_color::Color85 		void clearAlpha()
86 		{
87 			c[3] = 0;
88 		}
89 
operator *__anon659343cc0111::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 /__anon659343cc0111::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 >>__anon659343cc0111::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 +__anon659343cc0111::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__anon659343cc0111::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__anon659343cc0111::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__anon659343cc0111::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__anon659343cc0111::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__anon659343cc0111::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 		const uint16_t a = halfFloat1;
318 
RGBA__anon659343cc0111::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 =__anon659343cc0111::BC6H::Color::RGBA326 		RGBA &operator=(const RGBA &other)
327 		{
328 			if(this != &other)
329 			{
330 				this->r = other.r;
331 				this->g = other.g;
332 				this->b = other.b;
333 			}
334 
335 			return *this;
336 		}
337 	};
338 
Color(uint16_t r,uint16_t g,uint16_t b)339 	Color(uint16_t r, uint16_t g, uint16_t b)
340 	    : rgba(r, g, b)
341 	{
342 	}
343 
Color(int r,int g,int b)344 	Color(int r, int g, int b)
345 	    : rgba((uint16_t)r, (uint16_t)g, (uint16_t)b)
346 	{
347 	}
348 
Color()349 	Color()
350 	{
351 	}
352 
operator =(const Color & other)353 	Color &operator=(const Color &other)
354 	{
355 		if(this != &other)
356 		{
357 			this->rgba = other.rgba;
358 		}
359 		return *this;
360 	}
361 
362 	RGBA rgba;
363 	uint16_t channel[4];
364 };
365 static_assert(sizeof(Color) == 8, "BC6h::Color must be 8 bytes long");
366 
extendSign(int32_t val,size_t size)367 inline int32_t extendSign(int32_t val, size_t size)
368 {
369 	// Suppose we have a 2-bit integer being stored in 4 bit variable:
370 	//    x = 0b00AB
371 	//
372 	// In order to sign extend x, we need to turn the 0s into A's:
373 	//    x_extend = 0bAAAB
374 	//
375 	// We can do that by flipping A in x then subtracting 0b0010 from x.
376 	// Suppose A is 1:
377 	//    x       = 0b001B
378 	//    x_flip  = 0b000B
379 	//    x_minus = 0b111B
380 	// Since A is flipped to 0, subtracting the mask sets it and all the bits above it to 1.
381 	// And if A is 0:
382 	//    x       = 0b000B
383 	//    x_flip  = 0b001B
384 	//    x_minus = 0b000B
385 	// We unset the bit we flipped, and touch no other bit
386 	uint16_t mask = 1u << (size - 1);
387 	return (val ^ mask) - mask;
388 }
389 
390 static int constexpr RGBfChannels = 3;
391 struct RGBf
392 {
393 	uint16_t channel[RGBfChannels];
394 	size_t size[RGBfChannels];
395 	bool isSigned;
396 
RGBf__anon659343cc0111::BC6H::RGBf397 	RGBf()
398 	{
399 		static_assert(RGBfChannels == 3, "RGBf must have exactly 3 channels");
400 		static_assert(sizeof(channel) / sizeof(channel[0]) == RGBfChannels, "RGBf must have exactly 3 channels");
401 		static_assert(sizeof(channel) / sizeof(channel[0]) == sizeof(size) / sizeof(size[0]), "RGBf requires equally sized arrays for channels and channel sizes");
402 
403 		for(int i = 0; i < RGBfChannels; i++)
404 		{
405 			channel[i] = 0;
406 			size[i] = 0;
407 		}
408 
409 		isSigned = false;
410 	}
411 
extendSign__anon659343cc0111::BC6H::RGBf412 	void extendSign()
413 	{
414 		for(int i = 0; i < RGBfChannels; i++)
415 		{
416 			channel[i] = BC6H::extendSign(channel[i], size[i]);
417 		}
418 	}
419 
420 	// Assuming this is the delta, take the base-endpoint and transform this into
421 	// a proper endpoint.
422 	//
423 	// The final computed endpoint is truncated to the base-endpoint's size;
resolveDelta__anon659343cc0111::BC6H::RGBf424 	void resolveDelta(RGBf base)
425 	{
426 		for(int i = 0; i < RGBfChannels; i++)
427 		{
428 			size[i] = base.size[i];
429 			channel[i] = (base.channel[i] + channel[i]) & ((1 << base.size[i]) - 1);
430 		}
431 
432 		// Per the spec:
433 		// "For signed formats, the results of the delta calculation must be sign
434 		// extended as well."
435 		if(isSigned)
436 		{
437 			extendSign();
438 		}
439 	}
440 
unquantize__anon659343cc0111::BC6H::RGBf441 	void unquantize()
442 	{
443 		if(isSigned)
444 		{
445 			unquantizeSigned();
446 		}
447 		else
448 		{
449 			unquantizeUnsigned();
450 		}
451 	}
452 
unquantizeUnsigned__anon659343cc0111::BC6H::RGBf453 	void unquantizeUnsigned()
454 	{
455 		for(int i = 0; i < RGBfChannels; i++)
456 		{
457 			if(size[i] >= 15 || channel[i] == 0)
458 			{
459 				continue;
460 			}
461 			else if(channel[i] == ((1u << size[i]) - 1))
462 			{
463 				channel[i] = 0xFFFFu;
464 			}
465 			else
466 			{
467 				// Need 32 bits to avoid overflow
468 				uint32_t tmp = channel[i];
469 				channel[i] = (uint16_t)(((tmp << 16) + 0x8000) >> size[i]);
470 			}
471 			size[i] = 16;
472 		}
473 	}
474 
unquantizeSigned__anon659343cc0111::BC6H::RGBf475 	void unquantizeSigned()
476 	{
477 		for(int i = 0; i < RGBfChannels; i++)
478 		{
479 			if(size[i] >= 16 || channel[i] == 0)
480 			{
481 				continue;
482 			}
483 
484 			int16_t value = sw::bit_cast<int16_t>(channel[i]);
485 			int32_t result = value;
486 			bool signBit = value < 0;
487 			if(signBit)
488 			{
489 				value = -value;
490 			}
491 
492 			if(value >= ((1 << (size[i] - 1)) - 1))
493 			{
494 				result = 0x7FFF;
495 			}
496 			else
497 			{
498 				// Need 32 bits to avoid overflow
499 				int32_t tmp = value;
500 				result = (((tmp << 15) + 0x4000) >> (size[i] - 1));
501 			}
502 
503 			if(signBit)
504 			{
505 				result = -result;
506 			}
507 
508 			channel[i] = (uint16_t)result;
509 			size[i] = 16;
510 		}
511 	}
512 };
513 
514 struct Data
515 {
516 	uint64_t low64;
517 	uint64_t high64;
518 
519 	Data() = default;
Data__anon659343cc0111::BC6H::Data520 	Data(uint64_t low64, uint64_t high64)
521 	    : low64(low64)
522 	    , high64(high64)
523 	{
524 	}
525 
526 	// Consumes the lowest N bits from from low64 and high64 where N is:
527 	//      abs(MSB - LSB)
528 	// MSB and LSB come from the block description of the BC6h spec and specify
529 	// the location of the bits in the returned bitstring.
530 	//
531 	// If MSB < LSB, then the bits are reversed. Otherwise, the bitstring is read and
532 	// shifted without further modification.
533 	//
consumeBits__anon659343cc0111::BC6H::Data534 	uint32_t consumeBits(uint32_t MSB, uint32_t LSB)
535 	{
536 		bool reversed = MSB < LSB;
537 		if(reversed)
538 		{
539 			std::swap(MSB, LSB);
540 		}
541 		ASSERT(MSB - LSB + 1 < sizeof(uint32_t) * 8);
542 
543 		uint32_t numBits = MSB - LSB + 1;
544 		uint32_t mask = (1 << numBits) - 1;
545 		// Read the low N bits
546 		uint32_t bits = (low64 & mask);
547 
548 		low64 >>= numBits;
549 		// Put the low N bits of high64 into the high 64-N bits of low64
550 		low64 |= (high64 & mask) << (sizeof(high64) * 8 - numBits);
551 		high64 >>= numBits;
552 
553 		if(reversed)
554 		{
555 			uint32_t tmp = 0;
556 			for(uint32_t numSwaps = 0; numSwaps < numBits; numSwaps++)
557 			{
558 				tmp <<= 1;
559 				tmp |= (bits & 1);
560 				bits >>= 1;
561 			}
562 
563 			bits = tmp;
564 		}
565 
566 		return bits << LSB;
567 	}
568 };
569 
570 struct IndexInfo
571 {
572 	uint64_t value;
573 	int numBits;
574 };
575 
576 // Interpolates between two endpoints, then does a final unquantization step
interpolate(RGBf e0,RGBf e1,const IndexInfo & index,bool isSigned)577 Color interpolate(RGBf e0, RGBf e1, const IndexInfo &index, bool isSigned)
578 {
579 	static constexpr uint32_t weights3[] = { 0, 9, 18, 27, 37, 46, 55, 64 };
580 	static constexpr uint32_t weights4[] = { 0, 4, 9, 13, 17, 21, 26, 30,
581 		                                     34, 38, 43, 47, 51, 55, 60, 64 };
582 	static constexpr uint32_t const *weightsN[] = {
583 		nullptr, nullptr, nullptr, weights3, weights4
584 	};
585 	auto weights = weightsN[index.numBits];
586 	ASSERT_MSG(weights != nullptr, "Unexpected number of index bits: %d", (int)index.numBits);
587 	Color color;
588 	uint32_t e0Weight = 64 - weights[index.value];
589 	uint32_t e1Weight = weights[index.value];
590 
591 	for(int i = 0; i < RGBfChannels; i++)
592 	{
593 		int32_t e0Channel = e0.channel[i];
594 		int32_t e1Channel = e1.channel[i];
595 
596 		if(isSigned)
597 		{
598 			e0Channel = extendSign(e0Channel, 16);
599 			e1Channel = extendSign(e1Channel, 16);
600 		}
601 
602 		int32_t e0Value = e0Channel * e0Weight;
603 		int32_t e1Value = e1Channel * e1Weight;
604 
605 		uint32_t tmp = ((e0Value + e1Value + 32) >> 6);
606 
607 		// Need to unquantize value to limit it to the legal range of half-precision
608 		// floats. We do this by scaling by 31/32 or 31/64 depending on if the value
609 		// is signed or unsigned.
610 		if(isSigned)
611 		{
612 			tmp = ((tmp & 0x80000000) != 0) ? (((~tmp + 1) * 31) >> 5) | 0x8000 : (tmp * 31) >> 5;
613 			// Don't return -0.0f, just normalize it to 0.0f.
614 			if(tmp == 0x8000)
615 				tmp = 0;
616 		}
617 		else
618 		{
619 			tmp = (tmp * 31) >> 6;
620 		}
621 
622 		color.channel[i] = (uint16_t)tmp;
623 	}
624 
625 	return color;
626 }
627 
628 enum DataType
629 {
630 	// Endpoints
631 	EP0 = 0,
632 	EP1 = 1,
633 	EP2 = 2,
634 	EP3 = 3,
635 	Mode,
636 	Partition,
637 };
638 
639 enum Channel
640 {
641 	R = 0,
642 	G = 1,
643 	B = 2,
644 	None,
645 };
646 
647 struct DeltaBits
648 {
649 	size_t channel[3];
650 
DeltaBits__anon659343cc0111::BC6H::DeltaBits651 	DeltaBits()
652 	{
653 		channel[R] = 0;
654 		channel[G] = 0;
655 		channel[B] = 0;
656 	}
657 
DeltaBits__anon659343cc0111::BC6H::DeltaBits658 	DeltaBits(int r, int g, int b)
659 	{
660 		channel[R] = r;
661 		channel[G] = g;
662 		channel[B] = b;
663 	}
664 };
665 
666 struct ModeDesc
667 {
668 	int number;
669 	bool hasDelta;
670 	int partitionCount;
671 	int endpointBits;
672 	int numEndpoints;
673 	DeltaBits deltaBits;
674 
ModeDesc__anon659343cc0111::BC6H::ModeDesc675 	ModeDesc()
676 	    : number(-1)
677 	    , hasDelta(false)
678 	    , partitionCount(0)
679 	    , endpointBits(0)
680 	    , numEndpoints(0)
681 	{
682 	}
683 
ModeDesc__anon659343cc0111::BC6H::ModeDesc684 	ModeDesc(int number, bool hasDelta, int partitionCount, int endpointBits, DeltaBits deltaBits)
685 	    : number(number)
686 	    , hasDelta(hasDelta)
687 	    , partitionCount(partitionCount)
688 	    , endpointBits(endpointBits)
689 	    , deltaBits(deltaBits)
690 	{
691 		numEndpoints = partitionCount * 2;
692 	}
693 };
694 
695 struct BlockDesc
696 {
697 	DataType type;
698 	Channel channel;
699 	int MSB;
700 	int LSB;
701 	ModeDesc modeDesc;
702 
703 	BlockDesc() = default;
704 
BlockDesc__anon659343cc0111::BC6H::BlockDesc705 	BlockDesc(DataType type, Channel channel, int MSB, int LSB, ModeDesc modeDesc)
706 	    : type(type)
707 	    , channel(channel)
708 	    , MSB(MSB)
709 	    , LSB(LSB)
710 	    , modeDesc(modeDesc)
711 	{
712 	}
713 
BlockDesc__anon659343cc0111::BC6H::BlockDesc714 	BlockDesc(DataType type, Channel channel, int MSB, int LSB)
715 	    : type(type)
716 	    , channel(channel)
717 	    , MSB(MSB)
718 	    , LSB(LSB)
719 	{
720 	}
721 };
722 
723 // Table describing the bitfields for each mode from the LSB to the MSB before
724 // the index data starts.
725 //
726 // The numbers come from the BC6h block description. The basic format is a list of bitfield
727 // descriptors of the form:
728 //   {Type, Channel, MSB, LSB}
729 //   * Type describes which endpoint this is, or if this is a mode or a partition number.
730 //   * Channel describes one of the 3 color channels within an endpoint
731 //   * MSB and LSB specificy:
732 //      * The size of the bitfield being read
733 //      * The position of the bitfield within the variable it is being read to
734 //      * And if the bitfield is stored in reverse bit order
735 //     If MSB < LSB then the bitfield is stored in reverse order. The size of the bitfield
736 //     is abs(MSB-LSB+1). And the position of the bitfield within the variable is
737 //     min(LSB, MSB).
738 //
739 // Invalid or reserved modes do not have any fields within them.
740 static const std::vector<BlockDesc> blockDescs[32] = {
741 	// clang-format off
742 	// Mode 0
743 	{ { Mode, None, 1, 0, { 0, true, 2, 10, { 5, 5, 5 } } },
744 	  { EP2, G, 4, 4 }, { EP2, B, 4, 4 }, { EP3, B, 4, 4 },
745 	  { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
746 	  { EP1, R, 4, 0 }, { EP3, G, 4, 4 }, { EP2, G, 3, 0 },
747 	  { EP1, G, 4, 0 }, { EP3, B, 0, 0 }, { EP3, G, 3, 0 },
748 	  { EP1, B, 4, 0 }, { EP3, B, 1, 1 }, { EP2, B, 3, 0 },
749 	  { EP2, R, 4, 0 }, { EP3, B, 2, 2 }, { EP3, R, 4, 0 },
750 	  { EP3, B, 3, 3 },
751 	  { Partition, None, 4, 0 } },
752 	// Mode 1
753 	{ { Mode, None, 1, 0, { 1, true, 2, 7, { 6, 6, 6 } } },
754 	  { EP2, G, 5, 5 }, { EP3, G, 5, 4 }, { EP0, R, 6, 0 },
755 	  { EP3, B, 1, 0 }, { EP2, B, 4, 4 }, { EP0, G, 6, 0 },
756 	  { EP2, B, 5, 5 }, { EP3, B, 2, 2 }, { EP2, G, 4, 4 },
757 	  { EP0, B, 6, 0 }, { EP3, B, 3, 3 }, { EP3, B, 5, 5 },
758       { EP3, B, 4, 4 }, { EP1, R, 5, 0 }, { EP2, G, 3, 0 },
759       { EP1, G, 5, 0 }, { EP3, G, 3, 0 }, { EP1, B, 5, 0 },
760       { EP2, B, 3, 0 }, { EP2, R, 5, 0 }, { EP3, R, 5, 0 },
761 	  { Partition, None, 4, 0 } },
762 	// Mode 2
763 	{ { Mode, None, 4, 0, { 2, true, 2, 11, { 5, 4, 4 } } },
764 	  { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
765 	  { EP1, R, 4, 0 }, { EP0, R, 10, 10 }, { EP2, G, 3, 0 },
766 	  { EP1, G, 3, 0 }, { EP0, G, 10, 10 }, { EP3, B, 0, 0 },
767 	  { EP3, G, 3, 0 }, { EP1, B, 3, 0 }, { EP0, B, 10, 10 },
768 	  { EP3, B, 1, 1 }, { EP2, B, 3, 0 }, { EP2, R, 4, 0 },
769 	  { EP3, B, 2, 2 }, { EP3, R, 4, 0 }, { EP3, B, 3, 3 },
770 	  { Partition, None, 4, 0 } },
771 	// Mode 3
772 	{
773 	    { Mode, None, 4, 0, { 3, false, 1, 10, { 0, 0, 0 } } },
774 	    { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
775 	    { EP1, R, 9, 0 }, { EP1, G, 9, 0 }, { EP1, B, 9, 0 },
776 	},
777 	// Mode 4: Illegal
778 	{},
779 	// Mode 5: Illegal
780 	{},
781 	// Mode 6
782 	{ { Mode, None, 4, 0, { 6, true, 2, 11, { 4, 5, 4 } } },
783 	  { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
784 	  { EP1, R, 3, 0 }, { EP0, R, 10, 10 }, { EP3, G, 4, 4 },
785 	  { EP2, G, 3, 0 }, { EP1, G, 4, 0 }, { EP0, G, 10, 10 },
786 	  { EP3, G, 3, 0 }, { EP1, B, 3, 0 }, { EP0, B, 10, 10 },
787 	  { EP3, B, 1, 1 }, { EP2, B, 3, 0 }, { EP2, R, 3, 0 },
788 	  { EP3, B, 0, 0 }, { EP3, B, 2, 2 }, { EP3, R, 3, 0 },
789 	  { EP2, G, 4, 4 }, { EP3, B, 3, 3 },
790 	  { Partition, None, 4, 0 } },
791 	// Mode 7
792 	{
793 	    { Mode, None, 4, 0, { 7, true, 1, 11, { 9, 9, 9 } } },
794 	    { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
795 	    { EP1, R, 8, 0 }, { EP0, R, 10, 10 }, { EP1, G, 8, 0 },
796 	    { EP0, G, 10, 10 }, { EP1, B, 8, 0 }, { EP0, B, 10, 10 },
797 	},
798 	// Mode 8: Illegal
799 	{},
800 	// Mode 9: Illegal
801 	{},
802 	// Mode 10
803 	{ { Mode, None, 4, 0, { 10, true, 2, 11, { 4, 4, 5 } } },
804 	  { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
805 	  { EP1, R, 3, 0 }, { EP0, R, 10, 10 }, { EP2, B, 4, 4 },
806 	  { EP2, G, 3, 0 }, { EP1, G, 3, 0 }, { EP0, G, 10, 10 },
807 	  { EP3, B, 0, 0 }, { EP3, G, 3, 0 }, { EP1, B, 4, 0 },
808 	  { EP0, B, 10, 10 }, { EP2, B, 3, 0 }, { EP2, R, 3, 0 },
809 	  { EP3, B, 1, 1 }, { EP3, B, 2, 2 }, { EP3, R, 3, 0 },
810       { EP3, B, 4, 4 }, { EP3, B, 3, 3 },
811 	  { Partition, None, 4, 0 } },
812 	// Mode 11
813 	{
814 	    { Mode, None, 4, 0, { 11, true, 1, 12, { 8, 8, 8 } } },
815 	    { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
816 	    { EP1, R, 7, 0 }, { EP0, R, 10, 11 }, { EP1, G, 7, 0 },
817 	    { EP0, G, 10, 11 }, { EP1, B, 7, 0 }, { EP0, B, 10, 11 },
818 	},
819 	// Mode 12: Illegal
820 	{},
821 	// Mode 13: Illegal
822 	{},
823 	// Mode 14
824 	{ { Mode, None, 4, 0, { 14, true, 2, 9, { 5, 5, 5 } } },
825 	  { EP0, R, 8, 0 }, { EP2, B, 4, 4 }, { EP0, G, 8, 0 },
826 	  { EP2, G, 4, 4 }, { EP0, B, 8, 0 }, { EP3, B, 4, 4 },
827 	  { EP1, R, 4, 0 }, { EP3, G, 4, 4 }, { EP2, G, 3, 0 },
828 	  { EP1, G, 4, 0 }, { EP3, B, 0, 0 }, { EP3, G, 3, 0 },
829 	  { EP1, B, 4, 0 }, { EP3, B, 1, 1 }, { EP2, B, 3, 0 },
830 	  { EP2, R, 4, 0 }, { EP3, B, 2, 2 }, { EP3, R, 4, 0 },
831 	  { EP3, B, 3, 3 },
832 	  { Partition, None, 4, 0 } },
833 	// Mode 15
834 	{
835 	    { Mode, None, 4, 0, { 15, true, 1, 16, { 4, 4, 4 } } },
836 	    { EP0, R, 9, 0 }, { EP0, G, 9, 0 }, { EP0, B, 9, 0 },
837 	    { EP1, R, 3, 0 }, { EP0, R, 10, 15 }, { EP1, G, 3, 0 },
838 	    { EP0, G, 10, 15 }, { EP1, B, 3, 0 }, { EP0, B, 10, 15 },
839 	},
840 	// Mode 16: Illegal
841 	{},
842 	// Mode 17: Illegal
843 	{},
844 	// Mode 18
845 	{ { Mode, None, 4, 0, { 18, true, 2, 8, { 6, 5, 5 } } },
846 	  { EP0, R, 7, 0 }, { EP3, G, 4, 4 }, { EP2, B, 4, 4 },
847 	  { EP0, G, 7, 0 }, { EP3, B, 2, 2 }, { EP2, G, 4, 4 },
848 	  { EP0, B, 7, 0 }, { EP3, B, 3, 3 }, { EP3, B, 4, 4 },
849       { EP1, R, 5, 0 }, { EP2, G, 3, 0 }, { EP1, G, 4, 0 },
850       { EP3, B, 0, 0 }, { EP3, G, 3, 0 }, { EP1, B, 4, 0 },
851       { EP3, B, 1, 1 }, { EP2, B, 3, 0 }, { EP2, R, 5, 0 },
852       { EP3, R, 5, 0 },
853 	  { Partition, None, 4, 0 } },
854 	// Mode 19: Reserved
855 	{},
856 	// Mode 20: Illegal
857 	{},
858 	// Mode 21: Illegal
859 	{},
860 	// Mode 22:
861 	{ { Mode, None, 4, 0, { 22, true, 2, 8, { 5, 6, 5 } } },
862 	  { EP0, R, 7, 0 }, { EP3, B, 0, 0 }, { EP2, B, 4, 4 },
863 	  { EP0, G, 7, 0 }, { EP2, G, 5, 5 }, { EP2, G, 4, 4 },
864       { EP0, B, 7, 0 }, { EP3, G, 5, 5 }, { EP3, B, 4, 4 },
865       { EP1, R, 4, 0 }, { EP3, G, 4, 4 }, { EP2, G, 3, 0 },
866       { EP1, G, 5, 0 }, { EP3, G, 3, 0 }, { EP1, B, 4, 0 },
867       { EP3, B, 1, 1 }, { EP2, B, 3, 0 }, { EP2, R, 4, 0 },
868       { EP3, B, 2, 2 }, { EP3, R, 4, 0 }, { EP3, B, 3, 3 },
869 	  { Partition, None, 4, 0 } },
870 	// Mode 23: Reserved
871 	{},
872 	// Mode 24: Illegal
873 	{},
874 	// Mode 25: Illegal
875 	{},
876 	// Mode 26
877 	{ { Mode, None, 4, 0, { 26, true, 2, 8, { 5, 5, 6 } } },
878 	  { EP0, R, 7, 0 }, { EP3, B, 1, 1 }, { EP2, B, 4, 4 },
879 	  { EP0, G, 7, 0 }, { EP2, B, 5, 5 }, { EP2, G, 4, 4 },
880 	  { EP0, B, 7, 0 }, { EP3, B, 5, 5 }, { EP3, B, 4, 4 },
881       { EP1, R, 4, 0 }, { EP3, G, 4, 4 }, { EP2, G, 3, 0 },
882       { EP1, G, 4, 0 }, { EP3, B, 0, 0 }, { EP3, G, 3, 0 },
883       { EP1, B, 5, 0 }, { EP2, B, 3, 0 }, { EP2, R, 4, 0 },
884       { EP3, B, 2, 2 }, { EP3, R, 4, 0 }, { EP3, B, 3, 3 },
885 	  { Partition, None, 4, 0 } },
886 	// Mode 27: Reserved
887 	{},
888 	// Mode 28: Illegal
889 	{},
890 	// Mode 29: Illegal
891 	{},
892 	// Mode 30
893 	{ { Mode, None, 4, 0, { 30, false, 2, 6, { 0, 0, 0 } } },
894 	  { EP0, R, 5, 0 }, { EP3, G, 4, 4 }, { EP3, B, 0, 0 },
895       { EP3, B, 1, 1 }, { EP2, B, 4, 4 }, { EP0, G, 5, 0 },
896       { EP2, G, 5, 5 }, { EP2, B, 5, 5 }, { EP3, B, 2, 2 },
897       { EP2, G, 4, 4 }, { EP0, B, 5, 0 }, { EP3, G, 5, 5 },
898       { EP3, B, 3, 3 }, { EP3, B, 5, 5 }, { EP3, B, 4, 4 },
899       { EP1, R, 5, 0 }, { EP2, G, 3, 0 }, { EP1, G, 5, 0 },
900       { EP3, G, 3, 0 }, { EP1, B, 5, 0 }, { EP2, B, 3, 0 },
901       { EP2, R, 5, 0 }, { EP3, R, 5, 0 },
902 	  { Partition, None, 4, 0 } },
903 	// Mode 31: Reserved
904 	{},
905 	// clang-format on
906 };
907 
908 struct Block
909 {
910 	uint64_t low64;
911 	uint64_t high64;
912 
decode__anon659343cc0111::BC6H::Block913 	void decode(uint8_t *dst, int dstX, int dstY, int dstWidth, int dstHeight, size_t dstPitch, size_t dstBpp, bool isSigned) const
914 	{
915 		uint8_t mode = 0;
916 		Data data(low64, high64);
917 		ASSERT(dstBpp == sizeof(Color));
918 
919 		if((data.low64 & 0x2) == 0)
920 		{
921 			mode = data.consumeBits(1, 0);
922 		}
923 		else
924 		{
925 			mode = data.consumeBits(4, 0);
926 		}
927 
928 		// Illegal or reserved mode
929 		if(blockDescs[mode].size() == 0)
930 		{
931 			for(int y = 0; y < 4 && y + dstY < dstHeight; y++)
932 			{
933 				for(int x = 0; x < 4 && x + dstX < dstWidth; x++)
934 				{
935 					auto out = reinterpret_cast<Color *>(dst + sizeof(Color) * x + dstPitch * y);
936 					out->rgba = { 0, 0, 0 };
937 				}
938 			}
939 			return;
940 		}
941 
942 		RGBf e[4];
943 		e[0].isSigned = e[1].isSigned = e[2].isSigned = e[3].isSigned = isSigned;
944 
945 		int partition = 0;
946 		ModeDesc modeDesc;
947 		// For assertion checks
948 		modeDesc.number = -1;
949 		for(auto desc : blockDescs[mode])
950 		{
951 			switch(desc.type)
952 			{
953 				case Mode:
954 					modeDesc = desc.modeDesc;
955 					ASSERT(modeDesc.number == mode);
956 
957 					e[0].size[0] = e[0].size[1] = e[0].size[2] = modeDesc.endpointBits;
958 					for(int i = 0; i < RGBfChannels; i++)
959 					{
960 						if(modeDesc.hasDelta)
961 						{
962 							e[1].size[i] = e[2].size[i] = e[3].size[i] = modeDesc.deltaBits.channel[i];
963 						}
964 						else
965 						{
966 							e[1].size[i] = e[2].size[i] = e[3].size[i] = modeDesc.endpointBits;
967 						}
968 					}
969 					break;
970 				case Partition:
971 					partition |= data.consumeBits(desc.MSB, desc.LSB);
972 					break;
973 				case EP0:
974 				case EP1:
975 				case EP2:
976 				case EP3:
977 					e[desc.type].channel[desc.channel] |= data.consumeBits(desc.MSB, desc.LSB);
978 					break;
979 				default:
980 					ASSERT_MSG(false, "Unexpected enum value: %d", (int)desc.type);
981 					return;
982 			}
983 		}
984 
985 		ASSERT_MSG(modeDesc.number != -1, "Failed to decode mode %d", mode);
986 
987 		// Sign extension
988 		if(isSigned)
989 		{
990 			for(int ep = 0; ep < modeDesc.numEndpoints; ep++)
991 			{
992 				e[ep].extendSign();
993 			}
994 		}
995 		else if(modeDesc.hasDelta)
996 		{
997 			// Don't sign-extend the base endpoint in an unsigned format.
998 			for(int ep = 1; ep < modeDesc.numEndpoints; ep++)
999 			{
1000 				e[ep].extendSign();
1001 			}
1002 		}
1003 
1004 		// Turn the deltas into endpoints
1005 		if(modeDesc.hasDelta)
1006 		{
1007 			for(int ep = 1; ep < modeDesc.numEndpoints; ep++)
1008 			{
1009 				e[ep].resolveDelta(e[0]);
1010 			}
1011 		}
1012 
1013 		for(int ep = 0; ep < modeDesc.numEndpoints; ep++)
1014 		{
1015 			e[ep].unquantize();
1016 		}
1017 
1018 		// Get the indices, calculate final colors, and output
1019 		for(int y = 0; y < 4; y++)
1020 		{
1021 			for(int x = 0; x < 4; x++)
1022 			{
1023 				int pixelNum = x + y * 4;
1024 				IndexInfo idx;
1025 				bool isAnchor = false;
1026 				int firstEndpoint = 0;
1027 				// Bc6H can have either 1 or 2 petitions depending on the mode.
1028 				// The number of petitions affects the number of indices with implicit
1029 				// leading 0 bits and the number of bits per index.
1030 				if(modeDesc.partitionCount == 1)
1031 				{
1032 					idx.numBits = 4;
1033 					// There's an implicit leading 0 bit for the first idx
1034 					isAnchor = (pixelNum == 0);
1035 				}
1036 				else
1037 				{
1038 					idx.numBits = 3;
1039 					// There are 2 indices with implicit leading 0-bits.
1040 					isAnchor = ((pixelNum == 0) || (pixelNum == AnchorTable2[partition]));
1041 					firstEndpoint = PartitionTable2[partition][pixelNum] * 2;
1042 				}
1043 
1044 				idx.value = data.consumeBits(idx.numBits - isAnchor - 1, 0);
1045 
1046 				// Don't exit the loop early, we need to consume these index bits regardless if
1047 				// we actually output them or not.
1048 				if((y + dstY >= dstHeight) || (x + dstX >= dstWidth))
1049 				{
1050 					continue;
1051 				}
1052 
1053 				Color color = interpolate(e[firstEndpoint], e[firstEndpoint + 1], idx, isSigned);
1054 				auto out = reinterpret_cast<Color *>(dst + dstBpp * x + dstPitch * y);
1055 				*out = color;
1056 			}
1057 		}
1058 	}
1059 };
1060 
1061 }  // namespace BC6H
1062 
1063 namespace BC7 {
1064 // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt
1065 // https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format
1066 
1067 struct Bitfield
1068 {
1069 	int offset;
1070 	int count;
Then__anon659343cc0111::BC7::Bitfield1071 	constexpr Bitfield Then(const int bits) { return { offset + count, bits }; }
operator ==__anon659343cc0111::BC7::Bitfield1072 	constexpr bool operator==(const Bitfield &rhs)
1073 	{
1074 		return offset == rhs.offset && count == rhs.count;
1075 	}
1076 };
1077 
1078 struct Mode
1079 {
1080 	const int IDX;  // Mode index
1081 	const int NS;   // Number of subsets in each partition
1082 	const int PB;   // Partition bits
1083 	const int RB;   // Rotation bits
1084 	const int ISB;  // Index selection bits
1085 	const int CB;   // Color bits
1086 	const int AB;   // Alpha bits
1087 	const int EPB;  // Endpoint P-bits
1088 	const int SPB;  // Shared P-bits
1089 	const int IB;   // Primary index bits per element
1090 	const int IBC;  // Primary index bits total
1091 	const int IB2;  // Secondary index bits per element
1092 
NumColors__anon659343cc0111::BC7::Mode1093 	constexpr int NumColors() const { return NS * 2; }
Partition__anon659343cc0111::BC7::Mode1094 	constexpr Bitfield Partition() const { return { IDX + 1, PB }; }
Rotation__anon659343cc0111::BC7::Mode1095 	constexpr Bitfield Rotation() const { return Partition().Then(RB); }
IndexSelection__anon659343cc0111::BC7::Mode1096 	constexpr Bitfield IndexSelection() const { return Rotation().Then(ISB); }
Red__anon659343cc0111::BC7::Mode1097 	constexpr Bitfield Red(int idx) const
1098 	{
1099 		return IndexSelection().Then(CB * idx).Then(CB);
1100 	}
Green__anon659343cc0111::BC7::Mode1101 	constexpr Bitfield Green(int idx) const
1102 	{
1103 		return Red(NumColors() - 1).Then(CB * idx).Then(CB);
1104 	}
Blue__anon659343cc0111::BC7::Mode1105 	constexpr Bitfield Blue(int idx) const
1106 	{
1107 		return Green(NumColors() - 1).Then(CB * idx).Then(CB);
1108 	}
Alpha__anon659343cc0111::BC7::Mode1109 	constexpr Bitfield Alpha(int idx) const
1110 	{
1111 		return Blue(NumColors() - 1).Then(AB * idx).Then(AB);
1112 	}
EndpointPBit__anon659343cc0111::BC7::Mode1113 	constexpr Bitfield EndpointPBit(int idx) const
1114 	{
1115 		return Alpha(NumColors() - 1).Then(EPB * idx).Then(EPB);
1116 	}
SharedPBit0__anon659343cc0111::BC7::Mode1117 	constexpr Bitfield SharedPBit0() const
1118 	{
1119 		return EndpointPBit(NumColors() - 1).Then(SPB);
1120 	}
SharedPBit1__anon659343cc0111::BC7::Mode1121 	constexpr Bitfield SharedPBit1() const
1122 	{
1123 		return SharedPBit0().Then(SPB);
1124 	}
PrimaryIndex__anon659343cc0111::BC7::Mode1125 	constexpr Bitfield PrimaryIndex(int offset, int count) const
1126 	{
1127 		return SharedPBit1().Then(offset).Then(count);
1128 	}
SecondaryIndex__anon659343cc0111::BC7::Mode1129 	constexpr Bitfield SecondaryIndex(int offset, int count) const
1130 	{
1131 		return SharedPBit1().Then(IBC + offset).Then(count);
1132 	}
1133 };
1134 
1135 static constexpr Mode Modes[] = {
1136 	//     IDX  NS   PB   RB   ISB  CB   AB   EPB  SPB  IB   IBC, IB2
1137 	/**/ { 0x0, 0x3, 0x4, 0x0, 0x0, 0x4, 0x0, 0x1, 0x0, 0x3, 0x2d, 0x0 },
1138 	/**/ { 0x1, 0x2, 0x6, 0x0, 0x0, 0x6, 0x0, 0x0, 0x1, 0x3, 0x2e, 0x0 },
1139 	/**/ { 0x2, 0x3, 0x6, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x2, 0x1d, 0x0 },
1140 	/**/ { 0x3, 0x2, 0x6, 0x0, 0x0, 0x7, 0x0, 0x1, 0x0, 0x2, 0x1e, 0x0 },
1141 	/**/ { 0x4, 0x1, 0x0, 0x2, 0x1, 0x5, 0x6, 0x0, 0x0, 0x2, 0x1f, 0x3 },
1142 	/**/ { 0x5, 0x1, 0x0, 0x2, 0x0, 0x7, 0x8, 0x0, 0x0, 0x2, 0x1f, 0x2 },
1143 	/**/ { 0x6, 0x1, 0x0, 0x0, 0x0, 0x7, 0x7, 0x1, 0x0, 0x4, 0x3f, 0x0 },
1144 	/**/ { 0x7, 0x2, 0x6, 0x0, 0x0, 0x5, 0x5, 0x1, 0x0, 0x2, 0x1e, 0x0 },
1145 	/**/ { -1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x00, 0x0 },
1146 };
1147 
1148 static_assert(Modes[0].NumColors() == 6, "BC7 static assertion failed");
1149 static_assert(Modes[0].Partition() == Bitfield{ 1, 4 }, "BC7 static assertion failed");
1150 static_assert(Modes[0].Red(0) == Bitfield{ 5, 4 }, "BC7 static assertion failed");
1151 static_assert(Modes[0].Red(5) == Bitfield{ 25, 4 }, "BC7 static assertion failed");
1152 static_assert(Modes[0].Green(0) == Bitfield{ 29, 4 }, "BC7 static assertion failed");
1153 static_assert(Modes[0].Green(5) == Bitfield{ 49, 4 }, "BC7 static assertion failed");
1154 static_assert(Modes[0].Blue(0) == Bitfield{ 53, 4 }, "BC7 static assertion failed");
1155 static_assert(Modes[0].Blue(5) == Bitfield{ 73, 4 }, "BC7 static assertion failed");
1156 static_assert(Modes[0].EndpointPBit(0) == Bitfield{ 77, 1 }, "BC7 static assertion failed");
1157 static_assert(Modes[0].EndpointPBit(5) == Bitfield{ 82, 1 }, "BC7 static assertion failed");
1158 static_assert(Modes[0].PrimaryIndex(0, 2) == Bitfield{ 83, 2 }, "BC7 static asassertionsert failed");
1159 static_assert(Modes[0].PrimaryIndex(43, 1) == Bitfield{ 126, 1 }, "BC7 static assertion failed");
1160 
1161 static constexpr int MaxPartitions = 64;
1162 static constexpr int MaxSubsets = 3;
1163 
1164 static constexpr uint8_t PartitionTable2[MaxPartitions][16] = {
1165 	{ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 },
1166 	{ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 },
1167 	{ 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
1168 	{ 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 },
1169 	{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 },
1170 	{ 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
1171 	{ 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
1172 	{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1 },
1173 	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1 },
1174 	{ 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
1175 	{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
1176 	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 },
1177 	{ 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
1178 	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
1179 	{ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
1180 	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 },
1181 	{ 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1 },
1182 	{ 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
1183 	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 },
1184 	{ 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
1185 	{ 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
1186 	{ 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 },
1187 	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 },
1188 	{ 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 },
1189 	{ 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
1190 	{ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 },
1191 	{ 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0 },
1192 	{ 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0 },
1193 	{ 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 },
1194 	{ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
1195 	{ 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0 },
1196 	{ 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 },
1197 	{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 },
1198 	{ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 },
1199 	{ 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0 },
1200 	{ 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0 },
1201 	{ 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 },
1202 	{ 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 },
1203 	{ 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 },
1204 	{ 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 },
1205 	{ 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0 },
1206 	{ 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 },
1207 	{ 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 },
1208 	{ 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0 },
1209 	{ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 },
1210 	{ 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 },
1211 	{ 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 },
1212 	{ 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
1213 	{ 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
1214 	{ 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 },
1215 	{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0 },
1216 	{ 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0 },
1217 	{ 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 },
1218 	{ 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1 },
1219 	{ 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0 },
1220 	{ 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0 },
1221 	{ 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 },
1222 	{ 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1 },
1223 	{ 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 },
1224 	{ 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1 },
1225 	{ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 },
1226 	{ 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
1227 	{ 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0 },
1228 	{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1 },
1229 };
1230 
1231 static constexpr uint8_t PartitionTable3[MaxPartitions][16] = {
1232 	{ 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 2 },
1233 	{ 0, 0, 0, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1 },
1234 	{ 0, 0, 0, 0, 2, 0, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1 },
1235 	{ 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 1, 1 },
1236 	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2 },
1237 	{ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 2, 2 },
1238 	{ 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 },
1239 	{ 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1 },
1240 	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2 },
1241 	{ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2 },
1242 	{ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2 },
1243 	{ 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2 },
1244 	{ 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2 },
1245 	{ 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2 },
1246 	{ 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2 },
1247 	{ 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0 },
1248 	{ 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2 },
1249 	{ 0, 1, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0 },
1250 	{ 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2 },
1251 	{ 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1 },
1252 	{ 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2 },
1253 	{ 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 2, 1 },
1254 	{ 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2 },
1255 	{ 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 1, 0, 2, 2, 1, 0 },
1256 	{ 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0 },
1257 	{ 0, 0, 1, 2, 0, 0, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2 },
1258 	{ 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1, 0, 1, 1, 0 },
1259 	{ 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1 },
1260 	{ 0, 0, 2, 2, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 2, 2 },
1261 	{ 0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 0, 2, 2, 2, 2, 2 },
1262 	{ 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1 },
1263 	{ 0, 0, 0, 0, 2, 0, 0, 0, 2, 2, 1, 1, 2, 2, 2, 1 },
1264 	{ 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 2, 2, 2 },
1265 	{ 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 2, 0, 0, 1, 1 },
1266 	{ 0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 2, 2, 2 },
1267 	{ 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0 },
1268 	{ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0 },
1269 	{ 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 },
1270 	{ 0, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 0, 1, 2, 0 },
1271 	{ 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1 },
1272 	{ 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1 },
1273 	{ 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2 },
1274 	{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1 },
1275 	{ 0, 0, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 2, 2 },
1276 	{ 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1 },
1277 	{ 0, 2, 2, 0, 1, 2, 2, 1, 0, 2, 2, 0, 1, 2, 2, 1 },
1278 	{ 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1 },
1279 	{ 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 },
1280 	{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2 },
1281 	{ 0, 2, 2, 2, 0, 1, 1, 1, 0, 2, 2, 2, 0, 1, 1, 1 },
1282 	{ 0, 0, 0, 2, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 2 },
1283 	{ 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2 },
1284 	{ 0, 2, 2, 2, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2 },
1285 	{ 0, 0, 0, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2 },
1286 	{ 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2 },
1287 	{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2 },
1288 	{ 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2 },
1289 	{ 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2 },
1290 	{ 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2 },
1291 	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2 },
1292 	{ 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1 },
1293 	{ 0, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2 },
1294 	{ 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
1295 	{ 0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 2, 2, 2, 0 },
1296 };
1297 
1298 static constexpr uint8_t AnchorTable2[MaxPartitions] = {
1299 	// clang-format off
1300 	0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
1301 	0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
1302 	0xf, 0x2, 0x8, 0x2, 0x2, 0x8, 0x8, 0xf,
1303 	0x2, 0x8, 0x2, 0x2, 0x8, 0x8, 0x2, 0x2,
1304 	0xf, 0xf, 0x6, 0x8, 0x2, 0x8, 0xf, 0xf,
1305 	0x2, 0x8, 0x2, 0x2, 0x2, 0xf, 0xf, 0x6,
1306 	0x6, 0x2, 0x6, 0x8, 0xf, 0xf, 0x2, 0x2,
1307 	0xf, 0xf, 0xf, 0xf, 0xf, 0x2, 0x2, 0xf,
1308 	// clang-format on
1309 };
1310 
1311 static constexpr uint8_t AnchorTable3a[MaxPartitions] = {
1312 	// clang-format off
1313 	0x3, 0x3, 0xf, 0xf, 0x8, 0x3, 0xf, 0xf,
1314 	0x8, 0x8, 0x6, 0x6, 0x6, 0x5, 0x3, 0x3,
1315 	0x3, 0x3, 0x8, 0xf, 0x3, 0x3, 0x6, 0xa,
1316 	0x5, 0x8, 0x8, 0x6, 0x8, 0x5, 0xf, 0xf,
1317 	0x8, 0xf, 0x3, 0x5, 0x6, 0xa, 0x8, 0xf,
1318 	0xf, 0x3, 0xf, 0x5, 0xf, 0xf, 0xf, 0xf,
1319 	0x3, 0xf, 0x5, 0x5, 0x5, 0x8, 0x5, 0xa,
1320 	0x5, 0xa, 0x8, 0xd, 0xf, 0xc, 0x3, 0x3,
1321 	// clang-format on
1322 };
1323 
1324 static constexpr uint8_t AnchorTable3b[MaxPartitions] = {
1325 	// clang-format off
1326 	0xf, 0x8, 0x8, 0x3, 0xf, 0xf, 0x3, 0x8,
1327 	0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x8,
1328 	0xf, 0x8, 0xf, 0x3, 0xf, 0x8, 0xf, 0x8,
1329 	0x3, 0xf, 0x6, 0xa, 0xf, 0xf, 0xa, 0x8,
1330 	0xf, 0x3, 0xf, 0xa, 0xa, 0x8, 0x9, 0xa,
1331 	0x6, 0xf, 0x8, 0xf, 0x3, 0x6, 0x6, 0x8,
1332 	0xf, 0x3, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
1333 	0xf, 0xf, 0xf, 0xf, 0x3, 0xf, 0xf, 0x8,
1334 	// clang-format on
1335 };
1336 
1337 struct Color
1338 {
1339 	struct RGB
1340 	{
1341 		RGB() = default;
RGB__anon659343cc0111::BC7::Color::RGB1342 		RGB(uint8_t r, uint8_t g, uint8_t b)
1343 		    : b(b)
1344 		    , g(g)
1345 		    , r(r)
1346 		{}
RGB__anon659343cc0111::BC7::Color::RGB1347 		RGB(int r, int g, int b)
1348 		    : b(static_cast<uint8_t>(b))
1349 		    , g(static_cast<uint8_t>(g))
1350 		    , r(static_cast<uint8_t>(r))
1351 		{}
1352 
operator <<__anon659343cc0111::BC7::Color::RGB1353 		RGB operator<<(int shift) const { return { r << shift, g << shift, b << shift }; }
operator >>__anon659343cc0111::BC7::Color::RGB1354 		RGB operator>>(int shift) const { return { r >> shift, g >> shift, b >> shift }; }
operator |__anon659343cc0111::BC7::Color::RGB1355 		RGB operator|(int bits) const { return { r | bits, g | bits, b | bits }; }
operator |__anon659343cc0111::BC7::Color::RGB1356 		RGB operator|(const RGB &rhs) const { return { r | rhs.r, g | rhs.g, b | rhs.b }; }
operator +__anon659343cc0111::BC7::Color::RGB1357 		RGB operator+(const RGB &rhs) const { return { r + rhs.r, g + rhs.g, b + rhs.b }; }
1358 
1359 		uint8_t b;
1360 		uint8_t g;
1361 		uint8_t r;
1362 	};
1363 
1364 	RGB rgb;
1365 	uint8_t a;
1366 };
1367 
1368 static_assert(sizeof(Color) == 4, "Color size must be 4 bytes");
1369 
1370 struct Block
1371 {
Get__anon659343cc0111::BC7::Block1372 	constexpr uint64_t Get(const Bitfield &bf) const
1373 	{
1374 		uint64_t mask = (1ULL << bf.count) - 1;
1375 		if(bf.offset + bf.count <= 64)
1376 		{
1377 			return (low >> bf.offset) & mask;
1378 		}
1379 		if(bf.offset >= 64)
1380 		{
1381 			return (high >> (bf.offset - 64)) & mask;
1382 		}
1383 		return ((low >> bf.offset) | (high << (64 - bf.offset))) & mask;
1384 	}
1385 
mode__anon659343cc0111::BC7::Block1386 	const Mode &mode() const
1387 	{
1388 		if((low & 0b00000001) != 0) { return Modes[0]; }
1389 		if((low & 0b00000010) != 0) { return Modes[1]; }
1390 		if((low & 0b00000100) != 0) { return Modes[2]; }
1391 		if((low & 0b00001000) != 0) { return Modes[3]; }
1392 		if((low & 0b00010000) != 0) { return Modes[4]; }
1393 		if((low & 0b00100000) != 0) { return Modes[5]; }
1394 		if((low & 0b01000000) != 0) { return Modes[6]; }
1395 		if((low & 0b10000000) != 0) { return Modes[7]; }
1396 		return Modes[8];  // Invalid mode
1397 	}
1398 
1399 	struct IndexInfo
1400 	{
1401 		uint64_t value;
1402 		int numBits;
1403 	};
1404 
interpolate__anon659343cc0111::BC7::Block1405 	uint8_t interpolate(uint8_t e0, uint8_t e1, const IndexInfo &index) const
1406 	{
1407 		static constexpr uint16_t weights2[] = { 0, 21, 43, 64 };
1408 		static constexpr uint16_t weights3[] = { 0, 9, 18, 27, 37, 46, 55, 64 };
1409 		static constexpr uint16_t weights4[] = { 0, 4, 9, 13, 17, 21, 26, 30,
1410 			                                     34, 38, 43, 47, 51, 55, 60, 64 };
1411 		static constexpr uint16_t const *weightsN[] = {
1412 			nullptr, nullptr, weights2, weights3, weights4
1413 		};
1414 		auto weights = weightsN[index.numBits];
1415 		ASSERT_MSG(weights != nullptr, "Unexpected number of index bits: %d", (int)index.numBits);
1416 		return (uint8_t)(((64 - weights[index.value]) * uint16_t(e0) + weights[index.value] * uint16_t(e1) + 32) >> 6);
1417 	}
1418 
decode__anon659343cc0111::BC7::Block1419 	void decode(uint8_t *dst, int dstX, int dstY, int dstWidth, int dstHeight, size_t dstPitch) const
1420 	{
1421 		auto const &mode = this->mode();
1422 
1423 		if(mode.IDX < 0)  // Invalid mode:
1424 		{
1425 			for(int y = 0; y < 4 && y + dstY < dstHeight; y++)
1426 			{
1427 				for(int x = 0; x < 4 && x + dstX < dstWidth; x++)
1428 				{
1429 					auto out = reinterpret_cast<Color *>(dst + sizeof(Color) * x + dstPitch * y);
1430 					out->rgb = { 0, 0, 0 };
1431 					out->a = 0;
1432 				}
1433 			}
1434 			return;
1435 		}
1436 
1437 		using Endpoint = std::array<Color, 2>;
1438 		std::array<Endpoint, MaxSubsets> subsets;
1439 
1440 		for(int i = 0; i < mode.NS; i++)
1441 		{
1442 			auto &subset = subsets[i];
1443 			subset[0].rgb.r = Get(mode.Red(i * 2 + 0));
1444 			subset[0].rgb.g = Get(mode.Green(i * 2 + 0));
1445 			subset[0].rgb.b = Get(mode.Blue(i * 2 + 0));
1446 			subset[0].a = (mode.AB > 0) ? Get(mode.Alpha(i * 2 + 0)) : 255;
1447 
1448 			subset[1].rgb.r = Get(mode.Red(i * 2 + 1));
1449 			subset[1].rgb.g = Get(mode.Green(i * 2 + 1));
1450 			subset[1].rgb.b = Get(mode.Blue(i * 2 + 1));
1451 			subset[1].a = (mode.AB > 0) ? Get(mode.Alpha(i * 2 + 1)) : 255;
1452 		}
1453 
1454 		if(mode.SPB > 0)
1455 		{
1456 			auto pbit0 = Get(mode.SharedPBit0());
1457 			auto pbit1 = Get(mode.SharedPBit1());
1458 			subsets[0][0].rgb = (subsets[0][0].rgb << 1) | pbit0;
1459 			subsets[0][1].rgb = (subsets[0][1].rgb << 1) | pbit0;
1460 			subsets[1][0].rgb = (subsets[1][0].rgb << 1) | pbit1;
1461 			subsets[1][1].rgb = (subsets[1][1].rgb << 1) | pbit1;
1462 		}
1463 
1464 		if(mode.EPB > 0)
1465 		{
1466 			for(int i = 0; i < mode.NS; i++)
1467 			{
1468 				auto &subset = subsets[i];
1469 				auto pbit0 = Get(mode.EndpointPBit(i * 2 + 0));
1470 				auto pbit1 = Get(mode.EndpointPBit(i * 2 + 1));
1471 				subset[0].rgb = (subset[0].rgb << 1) | pbit0;
1472 				subset[1].rgb = (subset[1].rgb << 1) | pbit1;
1473 				if(mode.AB > 0)
1474 				{
1475 					subset[0].a = (subset[0].a << 1) | pbit0;
1476 					subset[1].a = (subset[1].a << 1) | pbit1;
1477 				}
1478 			}
1479 		}
1480 
1481 		auto const colorBits = mode.CB + mode.SPB + mode.EPB;
1482 		auto const alphaBits = mode.AB + mode.SPB + mode.EPB;
1483 
1484 		for(int i = 0; i < mode.NS; i++)
1485 		{
1486 			auto &subset = subsets[i];
1487 			subset[0].rgb = subset[0].rgb << (8 - colorBits);
1488 			subset[1].rgb = subset[1].rgb << (8 - colorBits);
1489 			subset[0].rgb = subset[0].rgb | (subset[0].rgb >> colorBits);
1490 			subset[1].rgb = subset[1].rgb | (subset[1].rgb >> colorBits);
1491 
1492 			if(mode.AB > 0)
1493 			{
1494 				subset[0].a = subset[0].a << (8 - alphaBits);
1495 				subset[1].a = subset[1].a << (8 - alphaBits);
1496 				subset[0].a = subset[0].a | (subset[0].a >> alphaBits);
1497 				subset[1].a = subset[1].a | (subset[1].a >> alphaBits);
1498 			}
1499 		}
1500 
1501 		int colorIndexBitOffset = 0;
1502 		int alphaIndexBitOffset = 0;
1503 		for(int y = 0; y < 4; y++)
1504 		{
1505 			for(int x = 0; x < 4; x++)
1506 			{
1507 				auto texelIdx = y * 4 + x;
1508 				auto partitionIdx = Get(mode.Partition());
1509 				ASSERT(partitionIdx < MaxPartitions);
1510 				auto subsetIdx = subsetIndex(mode, partitionIdx, texelIdx);
1511 				ASSERT(subsetIdx < MaxSubsets);
1512 				auto const &subset = subsets[subsetIdx];
1513 
1514 				auto anchorIdx = anchorIndex(mode, partitionIdx, subsetIdx);
1515 				auto isAnchor = anchorIdx == texelIdx;
1516 				auto colorIdx = colorIndex(mode, isAnchor, colorIndexBitOffset);
1517 				auto alphaIdx = alphaIndex(mode, isAnchor, alphaIndexBitOffset);
1518 
1519 				if(y + dstY >= dstHeight || x + dstX >= dstWidth)
1520 				{
1521 					// Don't be tempted to skip early at the loops:
1522 					// The calls to colorIndex() and alphaIndex() adjust bit
1523 					// offsets that need to be carefully tracked.
1524 					continue;
1525 				}
1526 
1527 				Color output;
1528 				output.rgb.r = interpolate(subset[0].rgb.r, subset[1].rgb.r, colorIdx);
1529 				output.rgb.g = interpolate(subset[0].rgb.g, subset[1].rgb.g, colorIdx);
1530 				output.rgb.b = interpolate(subset[0].rgb.b, subset[1].rgb.b, colorIdx);
1531 				output.a = interpolate(subset[0].a, subset[1].a, alphaIdx);
1532 
1533 				switch(Get(mode.Rotation()))
1534 				{
1535 					default:
1536 						break;
1537 					case 1:
1538 						std::swap(output.a, output.rgb.r);
1539 						break;
1540 					case 2:
1541 						std::swap(output.a, output.rgb.g);
1542 						break;
1543 					case 3:
1544 						std::swap(output.a, output.rgb.b);
1545 						break;
1546 				}
1547 
1548 				auto out = reinterpret_cast<Color *>(dst + sizeof(Color) * x + dstPitch * y);
1549 				*out = output;
1550 			}
1551 		}
1552 	}
1553 
subsetIndex__anon659343cc0111::BC7::Block1554 	int subsetIndex(const Mode &mode, int partitionIdx, int texelIndex) const
1555 	{
1556 		switch(mode.NS)
1557 		{
1558 			default:
1559 				return 0;
1560 			case 2:
1561 				return PartitionTable2[partitionIdx][texelIndex];
1562 			case 3:
1563 				return PartitionTable3[partitionIdx][texelIndex];
1564 		}
1565 	}
1566 
anchorIndex__anon659343cc0111::BC7::Block1567 	int anchorIndex(const Mode &mode, int partitionIdx, int subsetIdx) const
1568 	{
1569 		// ARB_texture_compression_bptc states:
1570 		// "In partition zero, the anchor index is always index zero.
1571 		// In other partitions, the anchor index is specified by tables
1572 		// Table.A2 and Table.A3.""
1573 		// Note: This is really confusing - I believe they meant subset instead
1574 		// of partition here.
1575 		switch(subsetIdx)
1576 		{
1577 			default:
1578 				return 0;
1579 			case 1:
1580 				return mode.NS == 2 ? AnchorTable2[partitionIdx] : AnchorTable3a[partitionIdx];
1581 			case 2:
1582 				return AnchorTable3b[partitionIdx];
1583 		}
1584 	}
1585 
colorIndex__anon659343cc0111::BC7::Block1586 	IndexInfo colorIndex(const Mode &mode, bool isAnchor,
1587 	                     int &indexBitOffset) const
1588 	{
1589 		// ARB_texture_compression_bptc states:
1590 		// "The index value for interpolating color comes from the secondary
1591 		// index for the texel if the format has an index selection bit and its
1592 		// value is one and from the primary index otherwise.""
1593 		auto idx = Get(mode.IndexSelection());
1594 		ASSERT(idx <= 1);
1595 		bool secondary = idx == 1;
1596 		auto numBits = secondary ? mode.IB2 : mode.IB;
1597 		auto numReadBits = numBits - (isAnchor ? 1 : 0);
1598 		auto index =
1599 		    Get(secondary ? mode.SecondaryIndex(indexBitOffset, numReadBits)
1600 		                  : mode.PrimaryIndex(indexBitOffset, numReadBits));
1601 		indexBitOffset += numReadBits;
1602 		return { index, numBits };
1603 	}
1604 
alphaIndex__anon659343cc0111::BC7::Block1605 	IndexInfo alphaIndex(const Mode &mode, bool isAnchor,
1606 	                     int &indexBitOffset) const
1607 	{
1608 		// ARB_texture_compression_bptc states:
1609 		// "The alpha index comes from the secondary index if the block has a
1610 		// secondary index and the block either doesn't have an index selection
1611 		// bit or that bit is zero and the primary index otherwise."
1612 		auto idx = Get(mode.IndexSelection());
1613 		ASSERT(idx <= 1);
1614 		bool secondary = (mode.IB2 != 0) && (idx == 0);
1615 		auto numBits = secondary ? mode.IB2 : mode.IB;
1616 		auto numReadBits = numBits - (isAnchor ? 1 : 0);
1617 		auto index =
1618 		    Get(secondary ? mode.SecondaryIndex(indexBitOffset, numReadBits)
1619 		                  : mode.PrimaryIndex(indexBitOffset, numReadBits));
1620 		indexBitOffset += numReadBits;
1621 		return { index, numBits };
1622 	}
1623 
1624 	// Assumes little-endian
1625 	uint64_t low;
1626 	uint64_t high;
1627 };
1628 
1629 }  // namespace BC7
1630 }  // anonymous namespace
1631 
1632 // 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)1633 bool BC_Decoder::Decode(const uint8_t *src, uint8_t *dst, int w, int h, int dstPitch, int dstBpp, int n, bool isNoAlphaU)
1634 {
1635 	static_assert(sizeof(BC_color) == 8, "BC_color must be 8 bytes");
1636 	static_assert(sizeof(BC_channel) == 8, "BC_channel must be 8 bytes");
1637 	static_assert(sizeof(BC_alpha) == 8, "BC_alpha must be 8 bytes");
1638 
1639 	const int dx = BlockWidth * dstBpp;
1640 	const int dy = BlockHeight * dstPitch;
1641 	const bool isAlpha = (n == 1) && !isNoAlphaU;
1642 	const bool isSigned = ((n == 4) || (n == 5) || (n == 6)) && !isNoAlphaU;
1643 
1644 	switch(n)
1645 	{
1646 		case 1:  // BC1
1647 		{
1648 			const BC_color *color = reinterpret_cast<const BC_color *>(src);
1649 			for(int y = 0; y < h; y += BlockHeight, dst += dy)
1650 			{
1651 				uint8_t *dstRow = dst;
1652 				for(int x = 0; x < w; x += BlockWidth, ++color, dstRow += dx)
1653 				{
1654 					color->decode(dstRow, x, y, w, h, dstPitch, dstBpp, isAlpha, false);
1655 				}
1656 			}
1657 		}
1658 		break;
1659 		case 2:  // BC2
1660 		{
1661 			const BC_alpha *alpha = reinterpret_cast<const BC_alpha *>(src);
1662 			const BC_color *color = reinterpret_cast<const BC_color *>(src + 8);
1663 			for(int y = 0; y < h; y += BlockHeight, dst += dy)
1664 			{
1665 				uint8_t *dstRow = dst;
1666 				for(int x = 0; x < w; x += BlockWidth, alpha += 2, color += 2, dstRow += dx)
1667 				{
1668 					color->decode(dstRow, x, y, w, h, dstPitch, dstBpp, isAlpha, true);
1669 					alpha->decode(dstRow, x, y, w, h, dstPitch, dstBpp);
1670 				}
1671 			}
1672 		}
1673 		break;
1674 		case 3:  // BC3
1675 		{
1676 			const BC_channel *alpha = reinterpret_cast<const BC_channel *>(src);
1677 			const BC_color *color = reinterpret_cast<const BC_color *>(src + 8);
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, alpha += 2, color += 2, dstRow += dx)
1682 				{
1683 					color->decode(dstRow, x, y, w, h, dstPitch, dstBpp, isAlpha, true);
1684 					alpha->decode(dstRow, x, y, w, h, dstPitch, dstBpp, 3, isSigned);
1685 				}
1686 			}
1687 		}
1688 		break;
1689 		case 4:  // BC4
1690 		{
1691 			const BC_channel *red = reinterpret_cast<const BC_channel *>(src);
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, ++red, dstRow += dx)
1696 				{
1697 					red->decode(dstRow, x, y, w, h, dstPitch, dstBpp, 0, isSigned);
1698 				}
1699 			}
1700 		}
1701 		break;
1702 		case 5:  // BC5
1703 		{
1704 			const BC_channel *red = reinterpret_cast<const BC_channel *>(src);
1705 			const BC_channel *green = reinterpret_cast<const BC_channel *>(src + 8);
1706 			for(int y = 0; y < h; y += BlockHeight, dst += dy)
1707 			{
1708 				uint8_t *dstRow = dst;
1709 				for(int x = 0; x < w; x += BlockWidth, red += 2, green += 2, dstRow += dx)
1710 				{
1711 					red->decode(dstRow, x, y, w, h, dstPitch, dstBpp, 0, isSigned);
1712 					green->decode(dstRow, x, y, w, h, dstPitch, dstBpp, 1, isSigned);
1713 				}
1714 			}
1715 		}
1716 		break;
1717 		case 6:  // BC6H
1718 		{
1719 			const BC6H::Block *block = reinterpret_cast<const BC6H::Block *>(src);
1720 			for(int y = 0; y < h; y += BlockHeight, dst += dy)
1721 			{
1722 				uint8_t *dstRow = dst;
1723 				for(int x = 0; x < w; x += BlockWidth, ++block, dstRow += dx)
1724 				{
1725 					block->decode(dstRow, x, y, w, h, dstPitch, dstBpp, isSigned);
1726 				}
1727 			}
1728 		}
1729 		break;
1730 		case 7:  // BC7
1731 		{
1732 			const BC7::Block *block = reinterpret_cast<const BC7::Block *>(src);
1733 			for(int y = 0; y < h; y += BlockHeight, dst += dy)
1734 			{
1735 				uint8_t *dstRow = dst;
1736 				for(int x = 0; x < w; x += BlockWidth, ++block, dstRow += dx)
1737 				{
1738 					block->decode(dstRow, x, y, w, h, dstPitch);
1739 				}
1740 			}
1741 		}
1742 		break;
1743 		default:
1744 			return false;
1745 	}
1746 
1747 	return true;
1748 }
1749