xref: /aosp_15_r20/external/mesa3d/src/util/texcompress_astc_luts.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /* Copyright (c) 2017-2022 Hans-Kristian Arntzen
2*61046927SAndroid Build Coastguard Worker  *
3*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining
4*61046927SAndroid Build Coastguard Worker  * a copy of this software and associated documentation files (the
5*61046927SAndroid Build Coastguard Worker  * "Software"), to deal in the Software without restriction, including
6*61046927SAndroid Build Coastguard Worker  * without limitation the rights to use, copy, modify, merge, publish,
7*61046927SAndroid Build Coastguard Worker  * distribute, sublicense, and/or sell copies of the Software, and to
8*61046927SAndroid Build Coastguard Worker  * permit persons to whom the Software is furnished to do so, subject to
9*61046927SAndroid Build Coastguard Worker  * the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be
12*61046927SAndroid Build Coastguard Worker  * included in all copies or substantial portions of the Software.
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15*61046927SAndroid Build Coastguard Worker  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16*61046927SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17*61046927SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18*61046927SAndroid Build Coastguard Worker  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19*61046927SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20*61046927SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21*61046927SAndroid Build Coastguard Worker  */
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker #include <assert.h>
24*61046927SAndroid Build Coastguard Worker #include <cstdint>
25*61046927SAndroid Build Coastguard Worker #include <cstring>
26*61046927SAndroid Build Coastguard Worker #include <mutex>
27*61046927SAndroid Build Coastguard Worker #include <unordered_map>
28*61046927SAndroid Build Coastguard Worker #include <vector>
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #include "texcompress_astc_luts.h"
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker namespace Granite
33*61046927SAndroid Build Coastguard Worker {
build_astc_unquant_weight_lut(uint8_t * lut,size_t range,const ASTCQuantizationMode & mode)34*61046927SAndroid Build Coastguard Worker static void build_astc_unquant_weight_lut(uint8_t *lut, size_t range, const ASTCQuantizationMode &mode)
35*61046927SAndroid Build Coastguard Worker {
36*61046927SAndroid Build Coastguard Worker 	for (size_t i = 0; i < range; i++)
37*61046927SAndroid Build Coastguard Worker 	{
38*61046927SAndroid Build Coastguard Worker 		auto &v = lut[i];
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker 		if (!mode.quints && !mode.trits)
41*61046927SAndroid Build Coastguard Worker 		{
42*61046927SAndroid Build Coastguard Worker 			switch (mode.bits)
43*61046927SAndroid Build Coastguard Worker 			{
44*61046927SAndroid Build Coastguard Worker 			case 1:
45*61046927SAndroid Build Coastguard Worker 				v = i * 63;
46*61046927SAndroid Build Coastguard Worker 				break;
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker 			case 2:
49*61046927SAndroid Build Coastguard Worker 				v = i * 0x15;
50*61046927SAndroid Build Coastguard Worker 				break;
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker 			case 3:
53*61046927SAndroid Build Coastguard Worker 				v = i * 9;
54*61046927SAndroid Build Coastguard Worker 				break;
55*61046927SAndroid Build Coastguard Worker 
56*61046927SAndroid Build Coastguard Worker 			case 4:
57*61046927SAndroid Build Coastguard Worker 				v = (i << 2) | (i >> 2);
58*61046927SAndroid Build Coastguard Worker 				break;
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker 			case 5:
61*61046927SAndroid Build Coastguard Worker 				v = (i << 1) | (i >> 4);
62*61046927SAndroid Build Coastguard Worker 				break;
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker 			default:
65*61046927SAndroid Build Coastguard Worker 				v = 0;
66*61046927SAndroid Build Coastguard Worker 				break;
67*61046927SAndroid Build Coastguard Worker 			}
68*61046927SAndroid Build Coastguard Worker 		}
69*61046927SAndroid Build Coastguard Worker 		else if (mode.bits == 0)
70*61046927SAndroid Build Coastguard Worker 		{
71*61046927SAndroid Build Coastguard Worker 			if (mode.trits)
72*61046927SAndroid Build Coastguard Worker 				v = 32 * i;
73*61046927SAndroid Build Coastguard Worker 			else
74*61046927SAndroid Build Coastguard Worker 				v = 16 * i;
75*61046927SAndroid Build Coastguard Worker 		}
76*61046927SAndroid Build Coastguard Worker 		else
77*61046927SAndroid Build Coastguard Worker 		{
78*61046927SAndroid Build Coastguard Worker 			unsigned b = (i >> 1) & 1;
79*61046927SAndroid Build Coastguard Worker 			unsigned c = (i >> 2) & 1;
80*61046927SAndroid Build Coastguard Worker 			unsigned A, B, C, D;
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker 			A = 0x7f * (i & 1);
83*61046927SAndroid Build Coastguard Worker 			D = i >> mode.bits;
84*61046927SAndroid Build Coastguard Worker 			B = 0;
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker 			if (mode.trits)
87*61046927SAndroid Build Coastguard Worker 			{
88*61046927SAndroid Build Coastguard Worker 				static const unsigned Cs[3] = { 50, 23, 11 };
89*61046927SAndroid Build Coastguard Worker 				C = Cs[mode.bits - 1];
90*61046927SAndroid Build Coastguard Worker 				if (mode.bits == 2)
91*61046927SAndroid Build Coastguard Worker 					B = 0x45 * b;
92*61046927SAndroid Build Coastguard Worker 				else if (mode.bits == 3)
93*61046927SAndroid Build Coastguard Worker 					B = 0x21 * b + 0x42 * c;
94*61046927SAndroid Build Coastguard Worker 			}
95*61046927SAndroid Build Coastguard Worker 			else
96*61046927SAndroid Build Coastguard Worker 			{
97*61046927SAndroid Build Coastguard Worker 				static const unsigned Cs[2] = { 28, 13 };
98*61046927SAndroid Build Coastguard Worker 				C = Cs[mode.bits - 1];
99*61046927SAndroid Build Coastguard Worker 				if (mode.bits == 2)
100*61046927SAndroid Build Coastguard Worker 					B = 0x42 * b;
101*61046927SAndroid Build Coastguard Worker 			}
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker 			unsigned unq = D * C + B;
104*61046927SAndroid Build Coastguard Worker 			unq ^= A;
105*61046927SAndroid Build Coastguard Worker 			unq = (A & 0x20) | (unq >> 2);
106*61046927SAndroid Build Coastguard Worker 			v = unq;
107*61046927SAndroid Build Coastguard Worker 		}
108*61046927SAndroid Build Coastguard Worker 
109*61046927SAndroid Build Coastguard Worker 		// Expand [0, 63] to [0, 64].
110*61046927SAndroid Build Coastguard Worker 		if (mode.bits != 0 && v > 32)
111*61046927SAndroid Build Coastguard Worker 			v++;
112*61046927SAndroid Build Coastguard Worker 	}
113*61046927SAndroid Build Coastguard Worker }
114*61046927SAndroid Build Coastguard Worker 
build_astc_unquant_endpoint_lut(uint8_t * lut,size_t range,const ASTCQuantizationMode & mode)115*61046927SAndroid Build Coastguard Worker static void build_astc_unquant_endpoint_lut(uint8_t *lut, size_t range, const ASTCQuantizationMode &mode)
116*61046927SAndroid Build Coastguard Worker {
117*61046927SAndroid Build Coastguard Worker 	for (size_t i = 0; i < range; i++)
118*61046927SAndroid Build Coastguard Worker 	{
119*61046927SAndroid Build Coastguard Worker 		auto &v = lut[i];
120*61046927SAndroid Build Coastguard Worker 
121*61046927SAndroid Build Coastguard Worker 		if (!mode.quints && !mode.trits)
122*61046927SAndroid Build Coastguard Worker 		{
123*61046927SAndroid Build Coastguard Worker 			// Bit-replication.
124*61046927SAndroid Build Coastguard Worker 			switch (mode.bits)
125*61046927SAndroid Build Coastguard Worker 			{
126*61046927SAndroid Build Coastguard Worker 			case 1:
127*61046927SAndroid Build Coastguard Worker 				v = i * 0xff;
128*61046927SAndroid Build Coastguard Worker 				break;
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker 			case 2:
131*61046927SAndroid Build Coastguard Worker 				v = i * 0x55;
132*61046927SAndroid Build Coastguard Worker 				break;
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker 			case 3:
135*61046927SAndroid Build Coastguard Worker 				v = (i << 5) | (i << 2) | (i >> 1);
136*61046927SAndroid Build Coastguard Worker 				break;
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker 			case 4:
139*61046927SAndroid Build Coastguard Worker 				v = i * 0x11;
140*61046927SAndroid Build Coastguard Worker 				break;
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker 			case 5:
143*61046927SAndroid Build Coastguard Worker 				v = (i << 3) | (i >> 2);
144*61046927SAndroid Build Coastguard Worker 				break;
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker 			case 6:
147*61046927SAndroid Build Coastguard Worker 				v = (i << 2) | (i >> 4);
148*61046927SAndroid Build Coastguard Worker 				break;
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker 			case 7:
151*61046927SAndroid Build Coastguard Worker 				v = (i << 1) | (i >> 6);
152*61046927SAndroid Build Coastguard Worker 				break;
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker 			default:
155*61046927SAndroid Build Coastguard Worker 				v = i;
156*61046927SAndroid Build Coastguard Worker 				break;
157*61046927SAndroid Build Coastguard Worker 			}
158*61046927SAndroid Build Coastguard Worker 		}
159*61046927SAndroid Build Coastguard Worker 		else
160*61046927SAndroid Build Coastguard Worker 		{
161*61046927SAndroid Build Coastguard Worker 			unsigned A, B, C, D;
162*61046927SAndroid Build Coastguard Worker 			unsigned b = (i >> 1) & 1;
163*61046927SAndroid Build Coastguard Worker 			unsigned c = (i >> 2) & 1;
164*61046927SAndroid Build Coastguard Worker 			unsigned d = (i >> 3) & 1;
165*61046927SAndroid Build Coastguard Worker 			unsigned e = (i >> 4) & 1;
166*61046927SAndroid Build Coastguard Worker 			unsigned f = (i >> 5) & 1;
167*61046927SAndroid Build Coastguard Worker 
168*61046927SAndroid Build Coastguard Worker 			B = 0;
169*61046927SAndroid Build Coastguard Worker 			D = i >> mode.bits;
170*61046927SAndroid Build Coastguard Worker 			A = (i & 1) * 0x1ff;
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker 			if (mode.trits)
173*61046927SAndroid Build Coastguard Worker 			{
174*61046927SAndroid Build Coastguard Worker 				static const unsigned Cs[6] = { 204, 93, 44, 22, 11, 5 };
175*61046927SAndroid Build Coastguard Worker 				C = Cs[mode.bits - 1];
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker 				switch (mode.bits)
178*61046927SAndroid Build Coastguard Worker 				{
179*61046927SAndroid Build Coastguard Worker 				case 2:
180*61046927SAndroid Build Coastguard Worker 					B = b * 0x116;
181*61046927SAndroid Build Coastguard Worker 					break;
182*61046927SAndroid Build Coastguard Worker 
183*61046927SAndroid Build Coastguard Worker 				case 3:
184*61046927SAndroid Build Coastguard Worker 					B = b * 0x85 + c * 0x10a;
185*61046927SAndroid Build Coastguard Worker 					break;
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker 				case 4:
188*61046927SAndroid Build Coastguard Worker 					B = b * 0x41 + c * 0x82 + d * 0x104;
189*61046927SAndroid Build Coastguard Worker 					break;
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker 				case 5:
192*61046927SAndroid Build Coastguard Worker 					B = b * 0x20 + c * 0x40 + d * 0x81 + e * 0x102;
193*61046927SAndroid Build Coastguard Worker 					break;
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker 				case 6:
196*61046927SAndroid Build Coastguard Worker 					B = b * 0x10 + c * 0x20 + d * 0x40 + e * 0x80 + f * 0x101;
197*61046927SAndroid Build Coastguard Worker 					break;
198*61046927SAndroid Build Coastguard Worker 				}
199*61046927SAndroid Build Coastguard Worker 			}
200*61046927SAndroid Build Coastguard Worker 			else
201*61046927SAndroid Build Coastguard Worker 			{
202*61046927SAndroid Build Coastguard Worker 				static const unsigned Cs[5] = { 113, 54, 26, 13, 6 };
203*61046927SAndroid Build Coastguard Worker 				C = Cs[mode.bits - 1];
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker 				switch (mode.bits)
206*61046927SAndroid Build Coastguard Worker 				{
207*61046927SAndroid Build Coastguard Worker 				case 2:
208*61046927SAndroid Build Coastguard Worker 					B = b * 0x10c;
209*61046927SAndroid Build Coastguard Worker 					break;
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker 				case 3:
212*61046927SAndroid Build Coastguard Worker 					B = b * 0x82 + c * 0x105;
213*61046927SAndroid Build Coastguard Worker 					break;
214*61046927SAndroid Build Coastguard Worker 
215*61046927SAndroid Build Coastguard Worker 				case 4:
216*61046927SAndroid Build Coastguard Worker 					B = b * 0x40 + c * 0x81 + d * 0x102;
217*61046927SAndroid Build Coastguard Worker 					break;
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker 				case 5:
220*61046927SAndroid Build Coastguard Worker 					B = b * 0x20 + c * 0x40 + d * 0x80 + e * 0x101;
221*61046927SAndroid Build Coastguard Worker 					break;
222*61046927SAndroid Build Coastguard Worker 				}
223*61046927SAndroid Build Coastguard Worker 			}
224*61046927SAndroid Build Coastguard Worker 
225*61046927SAndroid Build Coastguard Worker 			unsigned unq = D * C + B;
226*61046927SAndroid Build Coastguard Worker 			unq ^= A;
227*61046927SAndroid Build Coastguard Worker 			unq = (A & 0x80) | (unq >> 2);
228*61046927SAndroid Build Coastguard Worker 			v = uint8_t(unq);
229*61046927SAndroid Build Coastguard Worker 		}
230*61046927SAndroid Build Coastguard Worker 	}
231*61046927SAndroid Build Coastguard Worker }
232*61046927SAndroid Build Coastguard Worker 
astc_value_range(const ASTCQuantizationMode & mode)233*61046927SAndroid Build Coastguard Worker static unsigned astc_value_range(const ASTCQuantizationMode &mode)
234*61046927SAndroid Build Coastguard Worker {
235*61046927SAndroid Build Coastguard Worker 	unsigned value_range = 1u << mode.bits;
236*61046927SAndroid Build Coastguard Worker 	if (mode.trits)
237*61046927SAndroid Build Coastguard Worker 		value_range *= 3;
238*61046927SAndroid Build Coastguard Worker 	if (mode.quints)
239*61046927SAndroid Build Coastguard Worker 		value_range *= 5;
240*61046927SAndroid Build Coastguard Worker 
241*61046927SAndroid Build Coastguard Worker 	if (value_range == 1)
242*61046927SAndroid Build Coastguard Worker 		value_range = 0;
243*61046927SAndroid Build Coastguard Worker 	return value_range;
244*61046927SAndroid Build Coastguard Worker }
245*61046927SAndroid Build Coastguard Worker 
astc_hash52(uint32_t p)246*61046927SAndroid Build Coastguard Worker static uint32_t astc_hash52(uint32_t p)
247*61046927SAndroid Build Coastguard Worker {
248*61046927SAndroid Build Coastguard Worker 	p ^= p >> 15; p -= p << 17; p += p << 7; p += p << 4;
249*61046927SAndroid Build Coastguard Worker 	p ^= p >>  5; p += p << 16; p ^= p >> 7; p ^= p >> 3;
250*61046927SAndroid Build Coastguard Worker 	p ^= p <<  6; p ^= p >> 17;
251*61046927SAndroid Build Coastguard Worker 	return p;
252*61046927SAndroid Build Coastguard Worker }
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker // Copy-paste from spec.
astc_select_partition(int seed,int x,int y,int z,int partitioncount,bool small_block)255*61046927SAndroid Build Coastguard Worker static int astc_select_partition(int seed, int x, int y, int z, int partitioncount, bool small_block)
256*61046927SAndroid Build Coastguard Worker {
257*61046927SAndroid Build Coastguard Worker 	if (small_block)
258*61046927SAndroid Build Coastguard Worker 	{
259*61046927SAndroid Build Coastguard Worker 		x <<= 1;
260*61046927SAndroid Build Coastguard Worker 		y <<= 1;
261*61046927SAndroid Build Coastguard Worker 		z <<= 1;
262*61046927SAndroid Build Coastguard Worker 	}
263*61046927SAndroid Build Coastguard Worker 
264*61046927SAndroid Build Coastguard Worker 	seed += (partitioncount - 1) * 1024;
265*61046927SAndroid Build Coastguard Worker 	uint32_t rnum = astc_hash52(seed);
266*61046927SAndroid Build Coastguard Worker 	uint8_t seed1 = rnum & 0xF;
267*61046927SAndroid Build Coastguard Worker 	uint8_t seed2 = (rnum >> 4) & 0xF;
268*61046927SAndroid Build Coastguard Worker 	uint8_t seed3 = (rnum >> 8) & 0xF;
269*61046927SAndroid Build Coastguard Worker 	uint8_t seed4 = (rnum >> 12) & 0xF;
270*61046927SAndroid Build Coastguard Worker 	uint8_t seed5 = (rnum >> 16) & 0xF;
271*61046927SAndroid Build Coastguard Worker 	uint8_t seed6 = (rnum >> 20) & 0xF;
272*61046927SAndroid Build Coastguard Worker 	uint8_t seed7 = (rnum >> 24) & 0xF;
273*61046927SAndroid Build Coastguard Worker 	uint8_t seed8 = (rnum >> 28) & 0xF;
274*61046927SAndroid Build Coastguard Worker 	uint8_t seed9 = (rnum >> 18) & 0xF;
275*61046927SAndroid Build Coastguard Worker 	uint8_t seed10 = (rnum >> 22) & 0xF;
276*61046927SAndroid Build Coastguard Worker 	uint8_t seed11 = (rnum >> 26) & 0xF;
277*61046927SAndroid Build Coastguard Worker 	uint8_t seed12 = ((rnum >> 30) | (rnum << 2)) & 0xF;
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker 	seed1 *= seed1; seed2 *= seed2; seed3 *= seed3; seed4 *= seed4;
280*61046927SAndroid Build Coastguard Worker 	seed5 *= seed5; seed6 *= seed6; seed7 *= seed7; seed8 *= seed8;
281*61046927SAndroid Build Coastguard Worker 	seed9 *= seed9; seed10 *= seed10; seed11 *= seed11; seed12 *= seed12;
282*61046927SAndroid Build Coastguard Worker 
283*61046927SAndroid Build Coastguard Worker 	int sh1, sh2, sh3;
284*61046927SAndroid Build Coastguard Worker 	if (seed & 1)
285*61046927SAndroid Build Coastguard Worker 	{
286*61046927SAndroid Build Coastguard Worker 		sh1 = seed & 2 ? 4 : 5;
287*61046927SAndroid Build Coastguard Worker 		sh2 = partitioncount == 3 ? 6 : 5;
288*61046927SAndroid Build Coastguard Worker 	}
289*61046927SAndroid Build Coastguard Worker 	else
290*61046927SAndroid Build Coastguard Worker 	{
291*61046927SAndroid Build Coastguard Worker 		sh1 = partitioncount == 3 ? 6 : 5;
292*61046927SAndroid Build Coastguard Worker 		sh2 = seed & 2 ? 4 : 5;
293*61046927SAndroid Build Coastguard Worker 	}
294*61046927SAndroid Build Coastguard Worker 	sh3 = (seed & 0x10) ? sh1 : sh2;
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker 	seed1 >>= sh1; seed2 >>= sh2; seed3 >>= sh1; seed4 >>= sh2;
297*61046927SAndroid Build Coastguard Worker 	seed5 >>= sh1; seed6 >>= sh2; seed7 >>= sh1; seed8 >>= sh2;
298*61046927SAndroid Build Coastguard Worker 	seed9 >>= sh3; seed10 >>= sh3; seed11 >>= sh3; seed12 >>= sh3;
299*61046927SAndroid Build Coastguard Worker 
300*61046927SAndroid Build Coastguard Worker 	int a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14);
301*61046927SAndroid Build Coastguard Worker 	int b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10);
302*61046927SAndroid Build Coastguard Worker 	int c = seed5 * x + seed6 * y + seed9 * z + (rnum >> 6);
303*61046927SAndroid Build Coastguard Worker 	int d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 2);
304*61046927SAndroid Build Coastguard Worker 
305*61046927SAndroid Build Coastguard Worker 	a &= 0x3f; b &= 0x3f; c &= 0x3f; d &= 0x3f;
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker 	if (partitioncount < 4)
308*61046927SAndroid Build Coastguard Worker 		d = 0;
309*61046927SAndroid Build Coastguard Worker 	if (partitioncount < 3)
310*61046927SAndroid Build Coastguard Worker 		c = 0;
311*61046927SAndroid Build Coastguard Worker 
312*61046927SAndroid Build Coastguard Worker 	if (a >= b && a >= c && a >= d)
313*61046927SAndroid Build Coastguard Worker 		return 0;
314*61046927SAndroid Build Coastguard Worker 	else if (b >= c && b >= d)
315*61046927SAndroid Build Coastguard Worker 		return 1;
316*61046927SAndroid Build Coastguard Worker 	else if (c >= d)
317*61046927SAndroid Build Coastguard Worker 		return 2;
318*61046927SAndroid Build Coastguard Worker 	else
319*61046927SAndroid Build Coastguard Worker 		return 3;
320*61046927SAndroid Build Coastguard Worker }
321*61046927SAndroid Build Coastguard Worker 
PartitionTable(unsigned block_width,unsigned block_height)322*61046927SAndroid Build Coastguard Worker ASTCLutHolder::PartitionTable::PartitionTable(unsigned block_width, unsigned block_height)
323*61046927SAndroid Build Coastguard Worker {
324*61046927SAndroid Build Coastguard Worker 	bool small_block = (block_width * block_height) < 31;
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker 	lut_width = block_width * 32;
327*61046927SAndroid Build Coastguard Worker 	lut_height = block_height * 32;
328*61046927SAndroid Build Coastguard Worker 	lut_buffer.resize(lut_width * lut_height);
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker 	for (unsigned seed_y = 0; seed_y < 32; seed_y++)
331*61046927SAndroid Build Coastguard Worker 	{
332*61046927SAndroid Build Coastguard Worker 		for (unsigned seed_x = 0; seed_x < 32; seed_x++)
333*61046927SAndroid Build Coastguard Worker 		{
334*61046927SAndroid Build Coastguard Worker 			unsigned seed = seed_y * 32 + seed_x;
335*61046927SAndroid Build Coastguard Worker 			for (unsigned block_y = 0; block_y < block_height; block_y++)
336*61046927SAndroid Build Coastguard Worker 			{
337*61046927SAndroid Build Coastguard Worker 				for (unsigned block_x = 0; block_x < block_width; block_x++)
338*61046927SAndroid Build Coastguard Worker 				{
339*61046927SAndroid Build Coastguard Worker 					int part2 = astc_select_partition(seed, block_x, block_y, 0, 2, small_block);
340*61046927SAndroid Build Coastguard Worker 					int part3 = astc_select_partition(seed, block_x, block_y, 0, 3, small_block);
341*61046927SAndroid Build Coastguard Worker 					int part4 = astc_select_partition(seed, block_x, block_y, 0, 4, small_block);
342*61046927SAndroid Build Coastguard Worker 					lut_buffer[(seed_y * block_height + block_y) * lut_width + (seed_x * block_width + block_x)] =
343*61046927SAndroid Build Coastguard Worker 							(part2 << 0) | (part3 << 2) | (part4 << 4);
344*61046927SAndroid Build Coastguard Worker 				}
345*61046927SAndroid Build Coastguard Worker 			}
346*61046927SAndroid Build Coastguard Worker 		}
347*61046927SAndroid Build Coastguard Worker 	}
348*61046927SAndroid Build Coastguard Worker }
349*61046927SAndroid Build Coastguard Worker 
get_partition_table(unsigned width,unsigned height)350*61046927SAndroid Build Coastguard Worker ASTCLutHolder::PartitionTable &ASTCLutHolder::get_partition_table(unsigned width, unsigned height)
351*61046927SAndroid Build Coastguard Worker {
352*61046927SAndroid Build Coastguard Worker 	std::lock_guard<std::mutex> holder{table_lock};
353*61046927SAndroid Build Coastguard Worker 	auto itr = tables.find(width * 16 + height);
354*61046927SAndroid Build Coastguard Worker 	if (itr != tables.end())
355*61046927SAndroid Build Coastguard Worker 	{
356*61046927SAndroid Build Coastguard Worker 		return itr->second;
357*61046927SAndroid Build Coastguard Worker 	}
358*61046927SAndroid Build Coastguard Worker 	else
359*61046927SAndroid Build Coastguard Worker 	{
360*61046927SAndroid Build Coastguard Worker 		auto &t = tables[width * 16 + height];
361*61046927SAndroid Build Coastguard Worker 		t = { width, height };
362*61046927SAndroid Build Coastguard Worker 		return t;
363*61046927SAndroid Build Coastguard Worker 	}
364*61046927SAndroid Build Coastguard Worker }
365*61046927SAndroid Build Coastguard Worker 
get_astc_luts()366*61046927SAndroid Build Coastguard Worker ASTCLutHolder &get_astc_luts()
367*61046927SAndroid Build Coastguard Worker {
368*61046927SAndroid Build Coastguard Worker 	static ASTCLutHolder holder;
369*61046927SAndroid Build Coastguard Worker 	return holder;
370*61046927SAndroid Build Coastguard Worker }
371*61046927SAndroid Build Coastguard Worker 
ASTCLutHolder()372*61046927SAndroid Build Coastguard Worker ASTCLutHolder::ASTCLutHolder()
373*61046927SAndroid Build Coastguard Worker {
374*61046927SAndroid Build Coastguard Worker 	init_color_endpoint();
375*61046927SAndroid Build Coastguard Worker 	init_weight_luts();
376*61046927SAndroid Build Coastguard Worker 	init_trits_quints();
377*61046927SAndroid Build Coastguard Worker }
378*61046927SAndroid Build Coastguard Worker 
init_color_endpoint()379*61046927SAndroid Build Coastguard Worker void ASTCLutHolder::init_color_endpoint()
380*61046927SAndroid Build Coastguard Worker {
381*61046927SAndroid Build Coastguard Worker 	auto &unquant_lut = color_endpoint.unquant_lut;
382*61046927SAndroid Build Coastguard Worker 
383*61046927SAndroid Build Coastguard Worker 	for (size_t i = 0; i < astc_num_quantization_modes; i++)
384*61046927SAndroid Build Coastguard Worker 	{
385*61046927SAndroid Build Coastguard Worker 		auto value_range = astc_value_range(astc_quantization_modes[i]);
386*61046927SAndroid Build Coastguard Worker 		color_endpoint.unquant_lut_offsets[i] = color_endpoint.unquant_offset;
387*61046927SAndroid Build Coastguard Worker 		build_astc_unquant_endpoint_lut(unquant_lut + color_endpoint.unquant_offset, value_range, astc_quantization_modes[i]);
388*61046927SAndroid Build Coastguard Worker 		color_endpoint.unquant_offset += value_range;
389*61046927SAndroid Build Coastguard Worker 	}
390*61046927SAndroid Build Coastguard Worker 
391*61046927SAndroid Build Coastguard Worker 	auto &lut = color_endpoint.lut;
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker 	// We can have a maximum of 9 endpoint pairs, i.e. 18 endpoint values in total.
394*61046927SAndroid Build Coastguard Worker 	for (unsigned pairs_minus_1 = 0; pairs_minus_1 < 9; pairs_minus_1++)
395*61046927SAndroid Build Coastguard Worker 	{
396*61046927SAndroid Build Coastguard Worker 		for (unsigned remaining = 0; remaining < 128; remaining++)
397*61046927SAndroid Build Coastguard Worker 		{
398*61046927SAndroid Build Coastguard Worker 			bool found_mode = false;
399*61046927SAndroid Build Coastguard Worker 			for (auto &mode : astc_quantization_modes)
400*61046927SAndroid Build Coastguard Worker 			{
401*61046927SAndroid Build Coastguard Worker 				unsigned num_values = (pairs_minus_1 + 1) * 2;
402*61046927SAndroid Build Coastguard Worker 				unsigned total_bits = mode.bits * num_values +
403*61046927SAndroid Build Coastguard Worker 				                      (mode.quints * 7 * num_values + 2) / 3 +
404*61046927SAndroid Build Coastguard Worker 				                      (mode.trits * 8 * num_values + 4) / 5;
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker 				if (total_bits <= remaining)
407*61046927SAndroid Build Coastguard Worker 				{
408*61046927SAndroid Build Coastguard Worker 					found_mode = true;
409*61046927SAndroid Build Coastguard Worker 					lut[pairs_minus_1][remaining][0] = mode.bits;
410*61046927SAndroid Build Coastguard Worker 					lut[pairs_minus_1][remaining][1] = mode.trits;
411*61046927SAndroid Build Coastguard Worker 					lut[pairs_minus_1][remaining][2] = mode.quints;
412*61046927SAndroid Build Coastguard Worker 					lut[pairs_minus_1][remaining][3] = color_endpoint.unquant_lut_offsets[&mode - astc_quantization_modes];
413*61046927SAndroid Build Coastguard Worker 					break;
414*61046927SAndroid Build Coastguard Worker 				}
415*61046927SAndroid Build Coastguard Worker 			}
416*61046927SAndroid Build Coastguard Worker 
417*61046927SAndroid Build Coastguard Worker 			if (!found_mode)
418*61046927SAndroid Build Coastguard Worker 				memset(lut[pairs_minus_1][remaining], 0, sizeof(lut[pairs_minus_1][remaining]));
419*61046927SAndroid Build Coastguard Worker 		}
420*61046927SAndroid Build Coastguard Worker 	}
421*61046927SAndroid Build Coastguard Worker }
422*61046927SAndroid Build Coastguard Worker 
init_weight_luts()423*61046927SAndroid Build Coastguard Worker void ASTCLutHolder::init_weight_luts()
424*61046927SAndroid Build Coastguard Worker {
425*61046927SAndroid Build Coastguard Worker 	auto &lut = weights.lut;
426*61046927SAndroid Build Coastguard Worker 	auto &unquant_lut = weights.unquant_lut;
427*61046927SAndroid Build Coastguard Worker 	auto &unquant_offset = weights.unquant_offset;
428*61046927SAndroid Build Coastguard Worker 
429*61046927SAndroid Build Coastguard Worker 	for (size_t i = 0; i < astc_num_weight_modes; i++)
430*61046927SAndroid Build Coastguard Worker 	{
431*61046927SAndroid Build Coastguard Worker 		auto value_range = astc_value_range(astc_weight_modes[i]);
432*61046927SAndroid Build Coastguard Worker 		lut[i][0] = astc_weight_modes[i].bits;
433*61046927SAndroid Build Coastguard Worker 		lut[i][1] = astc_weight_modes[i].trits;
434*61046927SAndroid Build Coastguard Worker 		lut[i][2] = astc_weight_modes[i].quints;
435*61046927SAndroid Build Coastguard Worker 		lut[i][3] = unquant_offset;
436*61046927SAndroid Build Coastguard Worker 		build_astc_unquant_weight_lut(unquant_lut + unquant_offset, value_range, astc_weight_modes[i]);
437*61046927SAndroid Build Coastguard Worker 		unquant_offset += value_range;
438*61046927SAndroid Build Coastguard Worker 	}
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker 	assert(unquant_offset <= 256);
441*61046927SAndroid Build Coastguard Worker }
442*61046927SAndroid Build Coastguard Worker 
init_trits_quints()443*61046927SAndroid Build Coastguard Worker void ASTCLutHolder::init_trits_quints()
444*61046927SAndroid Build Coastguard Worker {
445*61046927SAndroid Build Coastguard Worker 	// From specification.
446*61046927SAndroid Build Coastguard Worker 	auto &trits_quints = integer.trits_quints;
447*61046927SAndroid Build Coastguard Worker 
448*61046927SAndroid Build Coastguard Worker 	for (unsigned T = 0; T < 256; T++)
449*61046927SAndroid Build Coastguard Worker 	{
450*61046927SAndroid Build Coastguard Worker 		unsigned C;
451*61046927SAndroid Build Coastguard Worker 		uint8_t t0, t1, t2, t3, t4;
452*61046927SAndroid Build Coastguard Worker 
453*61046927SAndroid Build Coastguard Worker 		if (((T >> 2) & 7) == 7)
454*61046927SAndroid Build Coastguard Worker 		{
455*61046927SAndroid Build Coastguard Worker 			C = (((T >> 5) & 7) << 2) | (T & 3);
456*61046927SAndroid Build Coastguard Worker 			t4 = t3 = 2;
457*61046927SAndroid Build Coastguard Worker 		}
458*61046927SAndroid Build Coastguard Worker 		else
459*61046927SAndroid Build Coastguard Worker 		{
460*61046927SAndroid Build Coastguard Worker 			C = T & 0x1f;
461*61046927SAndroid Build Coastguard Worker 			if (((T >> 5) & 3) == 3)
462*61046927SAndroid Build Coastguard Worker 			{
463*61046927SAndroid Build Coastguard Worker 				t4 = 2;
464*61046927SAndroid Build Coastguard Worker 				t3 = (T >> 7) & 1;
465*61046927SAndroid Build Coastguard Worker 			}
466*61046927SAndroid Build Coastguard Worker 			else
467*61046927SAndroid Build Coastguard Worker 			{
468*61046927SAndroid Build Coastguard Worker 				t4 = (T >> 7) & 1;
469*61046927SAndroid Build Coastguard Worker 				t3 = (T >> 5) & 3;
470*61046927SAndroid Build Coastguard Worker 			}
471*61046927SAndroid Build Coastguard Worker 		}
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker 		if ((C & 3) == 3)
474*61046927SAndroid Build Coastguard Worker 		{
475*61046927SAndroid Build Coastguard Worker 			t2 = 2;
476*61046927SAndroid Build Coastguard Worker 			t1 = (C >> 4) & 1;
477*61046927SAndroid Build Coastguard Worker 			t0 = (((C >> 3) & 1) << 1) | (((C >> 2) & 1) & ~(((C >> 3) & 1)));
478*61046927SAndroid Build Coastguard Worker 		}
479*61046927SAndroid Build Coastguard Worker 		else if (((C >> 2) & 3) == 3)
480*61046927SAndroid Build Coastguard Worker 		{
481*61046927SAndroid Build Coastguard Worker 			t2 = 2;
482*61046927SAndroid Build Coastguard Worker 			t1 = 2;
483*61046927SAndroid Build Coastguard Worker 			t0 = C & 3;
484*61046927SAndroid Build Coastguard Worker 		}
485*61046927SAndroid Build Coastguard Worker 		else
486*61046927SAndroid Build Coastguard Worker 		{
487*61046927SAndroid Build Coastguard Worker 			t2 = (C >> 4) & 1;
488*61046927SAndroid Build Coastguard Worker 			t1 = (C >> 2) & 3;
489*61046927SAndroid Build Coastguard Worker 			t0 = (((C >> 1) & 1) << 1) | ((C & 1) & ~(((C >> 1) & 1)));
490*61046927SAndroid Build Coastguard Worker 		}
491*61046927SAndroid Build Coastguard Worker 
492*61046927SAndroid Build Coastguard Worker 		trits_quints[T] = t0 | (t1 << 3) | (t2 << 6) | (t3 << 9) | (t4 << 12);
493*61046927SAndroid Build Coastguard Worker 	}
494*61046927SAndroid Build Coastguard Worker 
495*61046927SAndroid Build Coastguard Worker 	for (unsigned Q = 0; Q < 128; Q++)
496*61046927SAndroid Build Coastguard Worker 	{
497*61046927SAndroid Build Coastguard Worker 		unsigned C;
498*61046927SAndroid Build Coastguard Worker 		uint8_t q0, q1, q2;
499*61046927SAndroid Build Coastguard Worker 		if (((Q >> 1) & 3) == 3 && ((Q >> 5) & 3) == 0)
500*61046927SAndroid Build Coastguard Worker 		{
501*61046927SAndroid Build Coastguard Worker 			q2 = ((Q & 1) << 2) | ((((Q >> 4) & 1) & ~(Q & 1)) << 1) | (((Q >> 3) & 1) & ~(Q & 1));
502*61046927SAndroid Build Coastguard Worker 			q1 = q0 = 4;
503*61046927SAndroid Build Coastguard Worker 		}
504*61046927SAndroid Build Coastguard Worker 		else
505*61046927SAndroid Build Coastguard Worker 		{
506*61046927SAndroid Build Coastguard Worker 			if (((Q >> 1) & 3) == 3)
507*61046927SAndroid Build Coastguard Worker 			{
508*61046927SAndroid Build Coastguard Worker 				q2 = 4;
509*61046927SAndroid Build Coastguard Worker 				C = (((Q >> 3) & 3) << 3) | ((~(Q >> 5) & 3) << 1) | (Q & 1);
510*61046927SAndroid Build Coastguard Worker 			}
511*61046927SAndroid Build Coastguard Worker 			else
512*61046927SAndroid Build Coastguard Worker 			{
513*61046927SAndroid Build Coastguard Worker 				q2 = (Q >> 5) & 3;
514*61046927SAndroid Build Coastguard Worker 				C = Q & 0x1f;
515*61046927SAndroid Build Coastguard Worker 			}
516*61046927SAndroid Build Coastguard Worker 
517*61046927SAndroid Build Coastguard Worker 			if ((C & 7) == 5)
518*61046927SAndroid Build Coastguard Worker 			{
519*61046927SAndroid Build Coastguard Worker 				q1 = 4;
520*61046927SAndroid Build Coastguard Worker 				q0 = (C >> 3) & 3;
521*61046927SAndroid Build Coastguard Worker 			}
522*61046927SAndroid Build Coastguard Worker 			else
523*61046927SAndroid Build Coastguard Worker 			{
524*61046927SAndroid Build Coastguard Worker 				q1 = (C >> 3) & 3;
525*61046927SAndroid Build Coastguard Worker 				q0 = C & 7;
526*61046927SAndroid Build Coastguard Worker 			}
527*61046927SAndroid Build Coastguard Worker 		}
528*61046927SAndroid Build Coastguard Worker 
529*61046927SAndroid Build Coastguard Worker 		trits_quints[256 + Q] = q0 | (q1 << 3) | (q2 << 6);
530*61046927SAndroid Build Coastguard Worker 	}
531*61046927SAndroid Build Coastguard Worker }
532*61046927SAndroid Build Coastguard Worker }
533