• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: Apache-2.0
2 // ----------------------------------------------------------------------------
3 // Copyright 2011-2020 Arm Limited
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 // use this file except in compliance with the License. You may obtain a copy
7 // of the License at:
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 // License for the specific language governing permissions and limitations
15 // under the License.
16 // ----------------------------------------------------------------------------
17 
18 /**
19  * @brief Functions to generate block size descriptor and decimation tables.
20  */
21 
22 #include "astc_codec_internals.h"
23 #include <memory>
24 
25 struct TexelWeight
26 {
27 	int weightcount_of_texel[MAX_TEXELS_PER_BLOCK];
28 	int grid_weights_of_texel[MAX_TEXELS_PER_BLOCK][4];
29 	int weights_of_texel[MAX_TEXELS_PER_BLOCK][4];
30 
31 	int texelcount_of_weight[MAX_WEIGHTS_PER_BLOCK];
32 	int texels_of_weight[MAX_WEIGHTS_PER_BLOCK][MAX_TEXELS_PER_BLOCK];
33 	int texelweights_of_weight[MAX_WEIGHTS_PER_BLOCK][MAX_TEXELS_PER_BLOCK];
34 };
35 
36 // return 0 on invalid mode, 1 on valid mode.
decode_block_mode_2d(int blockmode,int * Nval,int * Mval,int * dual_weight_plane,int * quant_mode)37 static int decode_block_mode_2d(
38 	int blockmode,
39 	int* Nval,
40 	int* Mval,
41 	int* dual_weight_plane,
42 	int* quant_mode
43 ) {
44 	int base_quant_mode = (blockmode >> 4) & 1;
45 	int H = (blockmode >> 9) & 1;
46 	int D = (blockmode >> 10) & 1;
47 
48 	int A = (blockmode >> 5) & 0x3;
49 
50 	int N = 0, M = 0;
51 
52 	if ((blockmode & 3) != 0)
53 	{
54 		base_quant_mode |= (blockmode & 3) << 1;
55 		int B = (blockmode >> 7) & 3;
56 		switch ((blockmode >> 2) & 3)
57 		{
58 		case 0:
59 			N = B + 4;
60 			M = A + 2;
61 			break;
62 		case 1:
63 			N = B + 8;
64 			M = A + 2;
65 			break;
66 		case 2:
67 			N = A + 2;
68 			M = B + 8;
69 			break;
70 		case 3:
71 			B &= 1;
72 			if (blockmode & 0x100)
73 			{
74 				N = B + 2;
75 				M = A + 2;
76 			}
77 			else
78 			{
79 				N = A + 2;
80 				M = B + 6;
81 			}
82 			break;
83 		}
84 	}
85 	else
86 	{
87 		base_quant_mode |= ((blockmode >> 2) & 3) << 1;
88 		if (((blockmode >> 2) & 3) == 0)
89 			return 0;
90 		int B = (blockmode >> 9) & 3;
91 		switch ((blockmode >> 7) & 3)
92 		{
93 		case 0:
94 			N = 12;
95 			M = A + 2;
96 			break;
97 		case 1:
98 			N = A + 2;
99 			M = 12;
100 			break;
101 		case 2:
102 			N = A + 6;
103 			M = B + 6;
104 			D = 0;
105 			H = 0;
106 			break;
107 		case 3:
108 			switch ((blockmode >> 5) & 3)
109 			{
110 			case 0:
111 				N = 6;
112 				M = 10;
113 				break;
114 			case 1:
115 				N = 10;
116 				M = 6;
117 				break;
118 			case 2:
119 			case 3:
120 				return 0;
121 			}
122 			break;
123 		}
124 	}
125 
126 	int weight_count = N * M * (D + 1);
127 	int qmode = (base_quant_mode - 2) + 6 * H;
128 
129 	int weightbits = compute_ise_bitcount(weight_count, (quantization_method) qmode);
130 	if (weight_count > MAX_WEIGHTS_PER_BLOCK || weightbits < MIN_WEIGHT_BITS_PER_BLOCK || weightbits > MAX_WEIGHT_BITS_PER_BLOCK)
131 		return 0;
132 
133 	*Nval = N;
134 	*Mval = M;
135 	*dual_weight_plane = D;
136 	*quant_mode = qmode;
137 	return 1;
138 }
139 
decode_block_mode_3d(int blockmode,int * Nval,int * Mval,int * Qval,int * dual_weight_plane,int * quant_mode)140 static int decode_block_mode_3d(
141 	int blockmode,
142 	int* Nval,
143 	int* Mval,
144 	int* Qval,
145 	int* dual_weight_plane,
146 	int* quant_mode
147 ) {
148 	int base_quant_mode = (blockmode >> 4) & 1;
149 	int H = (blockmode >> 9) & 1;
150 	int D = (blockmode >> 10) & 1;
151 
152 	int A = (blockmode >> 5) & 0x3;
153 
154 	int N = 0, M = 0, Q = 0;
155 
156 	if ((blockmode & 3) != 0)
157 	{
158 		base_quant_mode |= (blockmode & 3) << 1;
159 		int B = (blockmode >> 7) & 3;
160 		int C = (blockmode >> 2) & 0x3;
161 		N = A + 2;
162 		M = B + 2;
163 		Q = C + 2;
164 	}
165 	else
166 	{
167 		base_quant_mode |= ((blockmode >> 2) & 3) << 1;
168 		if (((blockmode >> 2) & 3) == 0)
169 			return 0;
170 		int B = (blockmode >> 9) & 3;
171 		if (((blockmode >> 7) & 3) != 3)
172 		{
173 			D = 0;
174 			H = 0;
175 		}
176 		switch ((blockmode >> 7) & 3)
177 		{
178 		case 0:
179 			N = 6;
180 			M = B + 2;
181 			Q = A + 2;
182 			break;
183 		case 1:
184 			N = A + 2;
185 			M = 6;
186 			Q = B + 2;
187 			break;
188 		case 2:
189 			N = A + 2;
190 			M = B + 2;
191 			Q = 6;
192 			break;
193 		case 3:
194 			N = 2;
195 			M = 2;
196 			Q = 2;
197 			switch ((blockmode >> 5) & 3)
198 			{
199 			case 0:
200 				N = 6;
201 				break;
202 			case 1:
203 				M = 6;
204 				break;
205 			case 2:
206 				Q = 6;
207 				break;
208 			case 3:
209 				return 0;
210 			}
211 			break;
212 		}
213 	}
214 
215 	int weight_count = N * M * Q * (D + 1);
216 	int qmode = (base_quant_mode - 2) + 6 * H;
217 
218 	int weightbits = compute_ise_bitcount(weight_count, (quantization_method) qmode);
219 	if (weight_count > MAX_WEIGHTS_PER_BLOCK ||
220 	    weightbits < MIN_WEIGHT_BITS_PER_BLOCK ||
221 	    weightbits > MAX_WEIGHT_BITS_PER_BLOCK)
222 		return 0;
223 
224 	*Nval = N;
225 	*Mval = M;
226 	*Qval = Q;
227 	*dual_weight_plane = D;
228 	*quant_mode = qmode;
229 	return 1;
230 }
231 
initialize_decimation_table_2d(int xdim,int ydim,int x_weights,int y_weights,decimation_table * dt)232 static void initialize_decimation_table_2d(
233 	int xdim,
234 	int ydim,
235 	int x_weights,
236 	int y_weights,
237 	decimation_table* dt
238 ) {
239 	int i, j;
240 	int x, y;
241 
242 	int texels_per_block = xdim * ydim;
243 	int weights_per_block = x_weights * y_weights;
244 
245 	std::unique_ptr<TexelWeight> tw(new TexelWeight);
246 
247 	for (i = 0; i < weights_per_block; i++)
248 		tw->texelcount_of_weight[i] = 0;
249 	for (i = 0; i < texels_per_block; i++)
250 		tw->weightcount_of_texel[i] = 0;
251 
252 	for (y = 0; y < ydim; y++)
253 		for (x = 0; x < xdim; x++)
254 		{
255 			int texel = y * xdim + x;
256 
257 			int x_weight = (((1024 + xdim / 2) / (xdim - 1)) * x * (x_weights - 1) + 32) >> 6;
258 			int y_weight = (((1024 + ydim / 2) / (ydim - 1)) * y * (y_weights - 1) + 32) >> 6;
259 
260 			int x_weight_frac = x_weight & 0xF;
261 			int y_weight_frac = y_weight & 0xF;
262 			int x_weight_int = x_weight >> 4;
263 			int y_weight_int = y_weight >> 4;
264 			int qweight[4];
265 			int weight[4];
266 			qweight[0] = x_weight_int + y_weight_int * x_weights;
267 			qweight[1] = qweight[0] + 1;
268 			qweight[2] = qweight[0] + x_weights;
269 			qweight[3] = qweight[2] + 1;
270 
271 			// truncated-precision bilinear interpolation.
272 			int prod = x_weight_frac * y_weight_frac;
273 
274 			weight[3] = (prod + 8) >> 4;
275 			weight[1] = x_weight_frac - weight[3];
276 			weight[2] = y_weight_frac - weight[3];
277 			weight[0] = 16 - x_weight_frac - y_weight_frac + weight[3];
278 
279 			for (i = 0; i < 4; i++)
280 				if (weight[i] != 0)
281 				{
282 					tw->grid_weights_of_texel[texel][tw->weightcount_of_texel[texel]] = qweight[i];
283 					tw->weights_of_texel[texel][tw->weightcount_of_texel[texel]] = weight[i];
284 					tw->weightcount_of_texel[texel]++;
285 					tw->texels_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = texel;
286 					tw->texelweights_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = weight[i];
287 					tw->texelcount_of_weight[qweight[i]]++;
288 				}
289 		}
290 
291 	for (i = 0; i < texels_per_block; i++)
292 	{
293 		dt->texel_num_weights[i] = tw->weightcount_of_texel[i];
294 
295 		// ensure that all 4 entries are actually initialized.
296 		// This allows a branch-free implementation of compute_value_of_texel_flt()
297 		for (j = 0; j < 4; j++)
298 		{
299 			dt->texel_weights_int[i][j] = 0;
300 			dt->texel_weights_float[i][j] = 0.0f;
301 			dt->texel_weights[i][j] = 0;
302 		}
303 
304 		for (j = 0; j < tw->weightcount_of_texel[i]; j++)
305 		{
306 			dt->texel_weights_int[i][j] = (uint8_t)(tw->weights_of_texel[i][j]);
307 			dt->texel_weights_float[i][j] = ((float)(tw->weights_of_texel[i][j])) * (1.0f / TEXEL_WEIGHT_SUM);
308 			dt->texel_weights[i][j] = (uint8_t)(tw->grid_weights_of_texel[i][j]);
309 		}
310 	}
311 
312 	for (i = 0; i < weights_per_block; i++)
313 	{
314 		dt->weight_num_texels[i] = tw->texelcount_of_weight[i];
315 
316 		for (j = 0; j < tw->texelcount_of_weight[i]; j++)
317 		{
318 			int texel = tw->texels_of_weight[i][j];
319 			dt->weight_texel[i][j] = (uint8_t)texel;
320 			dt->weights_int[i][j] = (uint8_t)(tw->texelweights_of_weight[i][j]);
321 			dt->weights_flt[i][j] = (float)(tw->texelweights_of_weight[i][j]);
322 
323 			// perform a layer of array unrolling. An aspect of this unrolling is that
324 			// one of the texel-weight indexes is an identity-mapped index; we will use this
325 			// fact to reorder the indexes so that the first one is the identity index.
326 			int swap_idx = -1;
327 			for (int k = 0; k < 4; k++)
328 			{
329 				int dttw = dt->texel_weights[texel][k];
330 				float dttwf = dt->texel_weights_float[texel][k];
331 				if (dttw == i && dttwf != 0.0f)
332 					swap_idx = k;
333 				dt->texel_weights_texel[i][j][k] = (uint8_t)dttw;
334 				dt->texel_weights_float_texel[i][j][k] = dttwf;
335 			}
336 
337 			if (swap_idx != 0)
338 			{
339 				int vi = dt->texel_weights_texel[i][j][0];
340 				float vf = dt->texel_weights_float_texel[i][j][0];
341 				dt->texel_weights_texel[i][j][0] = dt->texel_weights_texel[i][j][swap_idx];
342 				dt->texel_weights_float_texel[i][j][0] = dt->texel_weights_float_texel[i][j][swap_idx];
343 				dt->texel_weights_texel[i][j][swap_idx] = (uint8_t)vi;
344 				dt->texel_weights_float_texel[i][j][swap_idx] = vf;
345 			}
346 		}
347 	}
348 
349 	dt->num_texels = texels_per_block;
350 	dt->num_weights = weights_per_block;
351 }
352 
initialize_decimation_table_3d(int xdim,int ydim,int zdim,int x_weights,int y_weights,int z_weights,decimation_table * dt)353 static void initialize_decimation_table_3d(
354 	int xdim,
355 	int ydim,
356 	int zdim,
357 	int x_weights,
358 	int y_weights,
359 	int z_weights,
360 	decimation_table* dt
361 ) {
362 	int i, j;
363 	int x, y, z;
364 
365 	int texels_per_block = xdim * ydim * zdim;
366 	int weights_per_block = x_weights * y_weights * z_weights;
367 
368 	std::unique_ptr<TexelWeight> tw(new TexelWeight);
369 
370 	for (i = 0; i < weights_per_block; i++)
371 		tw->texelcount_of_weight[i] = 0;
372 	for (i = 0; i < texels_per_block; i++)
373 		tw->weightcount_of_texel[i] = 0;
374 
375 	for (z = 0; z < zdim; z++)
376 	{
377 		for (y = 0; y < ydim; y++)
378 		{
379 			for (x = 0; x < xdim; x++)
380 			{
381 				int texel = (z * ydim + y) * xdim + x;
382 
383 				int x_weight = (((1024 + xdim / 2) / (xdim - 1)) * x * (x_weights - 1) + 32) >> 6;
384 				int y_weight = (((1024 + ydim / 2) / (ydim - 1)) * y * (y_weights - 1) + 32) >> 6;
385 				int z_weight = (((1024 + zdim / 2) / (zdim - 1)) * z * (z_weights - 1) + 32) >> 6;
386 
387 				int x_weight_frac = x_weight & 0xF;
388 				int y_weight_frac = y_weight & 0xF;
389 				int z_weight_frac = z_weight & 0xF;
390 				int x_weight_int = x_weight >> 4;
391 				int y_weight_int = y_weight >> 4;
392 				int z_weight_int = z_weight >> 4;
393 				int qweight[4];
394 				int weight[4];
395 				qweight[0] = (z_weight_int * y_weights + y_weight_int) * x_weights + x_weight_int;
396 				qweight[3] = ((z_weight_int + 1) * y_weights + (y_weight_int + 1)) * x_weights + (x_weight_int + 1);
397 
398 				// simplex interpolation
399 				int fs = x_weight_frac;
400 				int ft = y_weight_frac;
401 				int fp = z_weight_frac;
402 
403 				int cas = ((fs > ft) << 2) + ((ft > fp) << 1) + ((fs > fp));
404 				int N = x_weights;
405 				int NM = x_weights * y_weights;
406 
407 				int s1, s2, w0, w1, w2, w3;
408 				switch (cas)
409 				{
410 				case 7:
411 					s1 = 1;
412 					s2 = N;
413 					w0 = 16 - fs;
414 					w1 = fs - ft;
415 					w2 = ft - fp;
416 					w3 = fp;
417 					break;
418 				case 3:
419 					s1 = N;
420 					s2 = 1;
421 					w0 = 16 - ft;
422 					w1 = ft - fs;
423 					w2 = fs - fp;
424 					w3 = fp;
425 					break;
426 				case 5:
427 					s1 = 1;
428 					s2 = NM;
429 					w0 = 16 - fs;
430 					w1 = fs - fp;
431 					w2 = fp - ft;
432 					w3 = ft;
433 					break;
434 				case 4:
435 					s1 = NM;
436 					s2 = 1;
437 					w0 = 16 - fp;
438 					w1 = fp - fs;
439 					w2 = fs - ft;
440 					w3 = ft;
441 					break;
442 				case 2:
443 					s1 = N;
444 					s2 = NM;
445 					w0 = 16 - ft;
446 					w1 = ft - fp;
447 					w2 = fp - fs;
448 					w3 = fs;
449 					break;
450 				case 0:
451 					s1 = NM;
452 					s2 = N;
453 					w0 = 16 - fp;
454 					w1 = fp - ft;
455 					w2 = ft - fs;
456 					w3 = fs;
457 					break;
458 
459 				default:
460 					s1 = NM;
461 					s2 = N;
462 					w0 = 16 - fp;
463 					w1 = fp - ft;
464 					w2 = ft - fs;
465 					w3 = fs;
466 					break;
467 				}
468 
469 				qweight[1] = qweight[0] + s1;
470 				qweight[2] = qweight[1] + s2;
471 				weight[0] = w0;
472 				weight[1] = w1;
473 				weight[2] = w2;
474 				weight[3] = w3;
475 
476 				for (i = 0; i < 4; i++)
477 				{
478 					if (weight[i] != 0)
479 					{
480 						tw->grid_weights_of_texel[texel][tw->weightcount_of_texel[texel]] = qweight[i];
481 						tw->weights_of_texel[texel][tw->weightcount_of_texel[texel]] = weight[i];
482 						tw->weightcount_of_texel[texel]++;
483 						tw->texels_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = texel;
484 						tw->texelweights_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = weight[i];
485 						tw->texelcount_of_weight[qweight[i]]++;
486 					}
487 				}
488 			}
489 		}
490 	}
491 
492 	for (i = 0; i < texels_per_block; i++)
493 	{
494 		dt->texel_num_weights[i] = tw->weightcount_of_texel[i];
495 
496 		// ensure that all 4 entries are actually initialized.
497 		// This allows a branch-free implementation of compute_value_of_texel_flt()
498 		for (j = 0; j < 4; j++)
499 		{
500 			dt->texel_weights_int[i][j] = 0;
501 			dt->texel_weights_float[i][j] = 0.0f;
502 			dt->texel_weights[i][j] = 0;
503 		}
504 
505 		for (j = 0; j < tw->weightcount_of_texel[i]; j++)
506 		{
507 			dt->texel_weights_int[i][j] = (uint8_t)(tw->weights_of_texel[i][j]);
508 			dt->texel_weights_float[i][j] = ((float)(tw->weights_of_texel[i][j])) * (1.0f / TEXEL_WEIGHT_SUM);
509 			dt->texel_weights[i][j] = (uint8_t)(tw->grid_weights_of_texel[i][j]);
510 		}
511 	}
512 
513 	for (i = 0; i < weights_per_block; i++)
514 	{
515 		dt->weight_num_texels[i] = tw->texelcount_of_weight[i];
516 		for (j = 0; j < tw->texelcount_of_weight[i]; j++)
517 		{
518 			int texel = tw->texels_of_weight[i][j];
519 			dt->weight_texel[i][j] = (uint8_t)texel;
520 			dt->weights_int[i][j] = (uint8_t)(tw->texelweights_of_weight[i][j]);
521 			dt->weights_flt[i][j] = (float)(tw->texelweights_of_weight[i][j]);
522 
523 			// perform a layer of array unrolling. An aspect of this unrolling is that
524 			// one of the texel-weight indexes is an identity-mapped index; we will use this
525 			// fact to reorder the indexes so that the first one is the identity index.
526 			int swap_idx = -1;
527 			for (int k = 0; k < 4; k++)
528 			{
529 				int dttw = dt->texel_weights[texel][k];
530 				float dttwf = dt->texel_weights_float[texel][k];
531 				if (dttw == i && dttwf != 0.0f)
532 					swap_idx = k;
533 				dt->texel_weights_texel[i][j][k] = (uint8_t)dttw;
534 				dt->texel_weights_float_texel[i][j][k] = dttwf;
535 			}
536 
537 			if (swap_idx != 0)
538 			{
539 				int vi = dt->texel_weights_texel[i][j][0];
540 				float vf = dt->texel_weights_float_texel[i][j][0];
541 				dt->texel_weights_texel[i][j][0] = dt->texel_weights_texel[i][j][swap_idx];
542 				dt->texel_weights_float_texel[i][j][0] = dt->texel_weights_float_texel[i][j][swap_idx];
543 				dt->texel_weights_texel[i][j][swap_idx] = (uint8_t)vi;
544 				dt->texel_weights_float_texel[i][j][swap_idx] = vf;
545 			}
546 		}
547 	}
548 
549 	dt->num_texels = texels_per_block;
550 	dt->num_weights = weights_per_block;
551 }
552 
construct_block_size_descriptor_2d(int xdim,int ydim,block_size_descriptor * bsd)553 static void construct_block_size_descriptor_2d(
554 	int xdim,
555 	int ydim,
556 	block_size_descriptor* bsd
557 ) {
558 	int decimation_mode_index[256];	// for each of the 256 entries in the decim_table_array, its index
559 	int decimation_mode_count = 0;
560 
561 	bsd->xdim = xdim;
562 	bsd->ydim = ydim;
563 	bsd->zdim = 1;
564 	bsd->texel_count = xdim * ydim;
565 
566 	for (int i = 0; i < 256; i++)
567 	{
568 		decimation_mode_index[i] = -1;
569 	}
570 
571 	// gather all the infill-modes that can be used with the current block size
572 	for (int x_weights = 2; x_weights <= 12; x_weights++)
573 	{
574 		for (int y_weights = 2; y_weights <= 12; y_weights++)
575 		{
576 			if (x_weights * y_weights > MAX_WEIGHTS_PER_BLOCK)
577 			{
578 				continue;
579 			}
580 
581 			decimation_table *dt = new decimation_table;
582 			decimation_mode_index[y_weights * 16 + x_weights] = decimation_mode_count;
583 			initialize_decimation_table_2d(xdim, ydim, x_weights, y_weights, dt);
584 
585 			int weight_count = x_weights * y_weights;
586 
587 			int maxprec_1plane = -1;
588 			int maxprec_2planes = -1;
589 			for (int i = 0; i < 12; i++)
590 			{
591 				int bits_1plane = compute_ise_bitcount(weight_count, (quantization_method) i);
592 				int bits_2planes = compute_ise_bitcount(2 * weight_count, (quantization_method) i);
593 				if (bits_1plane >= MIN_WEIGHT_BITS_PER_BLOCK && bits_1plane <= MAX_WEIGHT_BITS_PER_BLOCK)
594 					maxprec_1plane = i;
595 				if (bits_2planes >= MIN_WEIGHT_BITS_PER_BLOCK && bits_2planes <= MAX_WEIGHT_BITS_PER_BLOCK)
596 					maxprec_2planes = i;
597 			}
598 
599 			if (2 * x_weights * y_weights > MAX_WEIGHTS_PER_BLOCK)
600 			{
601 				maxprec_2planes = -1;
602 			}
603 
604 			bsd->permit_encode[decimation_mode_count] = (x_weights <= xdim && y_weights <= ydim);
605 
606 			bsd->decimation_mode_samples[decimation_mode_count] = weight_count;
607 			bsd->decimation_mode_maxprec_1plane[decimation_mode_count] = maxprec_1plane;
608 			bsd->decimation_mode_maxprec_2planes[decimation_mode_count] = maxprec_2planes;
609 			bsd->decimation_tables[decimation_mode_count] = dt;
610 
611 			decimation_mode_count++;
612 		}
613 	}
614 
615 	for (int i = 0; i < MAX_DECIMATION_MODES; i++)
616 	{
617 		bsd->decimation_mode_percentile[i] = 1.0f;
618 	}
619 
620 	for (int i = decimation_mode_count; i < MAX_DECIMATION_MODES; i++)
621 	{
622 		bsd->permit_encode[i] = 0;
623 		bsd->decimation_mode_samples[i] = 0;
624 		bsd->decimation_mode_maxprec_1plane[i] = -1;
625 		bsd->decimation_mode_maxprec_2planes[i] = -1;
626 	}
627 
628 	bsd->decimation_mode_count = decimation_mode_count;
629 
630 	const float *percentiles = get_2d_percentile_table(xdim, ydim);
631 
632 	// then construct the list of block formats
633 	for (int i = 0; i < 2048; i++)
634 	{
635 		int x_weights, y_weights;
636 		int is_dual_plane;
637 		int quantization_mode;
638 		int fail = 0;
639 		int permit_encode = 1;
640 
641 		if (decode_block_mode_2d(i, &x_weights, &y_weights, &is_dual_plane, &quantization_mode))
642 		{
643 			if (x_weights > xdim || y_weights > ydim)
644 				permit_encode = 0;
645 		}
646 		else
647 		{
648 			fail = 1;
649 			permit_encode = 0;
650 		}
651 
652 		if (fail)
653 		{
654 			bsd->block_modes[i].decimation_mode = -1;
655 			bsd->block_modes[i].quantization_mode = -1;
656 			bsd->block_modes[i].is_dual_plane = -1;
657 			bsd->block_modes[i].permit_encode = 0;
658 			bsd->block_modes[i].permit_decode = 0;
659 			bsd->block_modes[i].percentile = 1.0f;
660 		}
661 		else
662 		{
663 			int decimation_mode = decimation_mode_index[y_weights * 16 + x_weights];
664 			bsd->block_modes[i].decimation_mode = decimation_mode;
665 			bsd->block_modes[i].quantization_mode = quantization_mode;
666 			bsd->block_modes[i].is_dual_plane = is_dual_plane;
667 			bsd->block_modes[i].permit_encode = permit_encode;
668 			bsd->block_modes[i].permit_decode = permit_encode;	// disallow decode of grid size larger than block size.
669 			bsd->block_modes[i].percentile = percentiles[i];
670 
671 			if (bsd->decimation_mode_percentile[decimation_mode] > percentiles[i])
672 				bsd->decimation_mode_percentile[decimation_mode] = percentiles[i];
673 		}
674 	}
675 
676 	delete[] percentiles;
677 
678 	if (xdim * ydim <= 64)
679 	{
680 		bsd->texelcount_for_bitmap_partitioning = xdim * ydim;
681 		for (int i = 0; i < xdim * ydim; i++)
682 		{
683 			bsd->texels_for_bitmap_partitioning[i] = i;
684 		}
685 	}
686 	else
687 	{
688 		uint64_t rng_state[2];
689 		astc::rand_init(rng_state);
690 
691 		// pick 64 random texels for use with bitmap partitioning.
692 		int arr[MAX_TEXELS_PER_BLOCK];
693 		for (int i = 0; i < xdim * ydim; i++)
694 		{
695 			arr[i] = 0;
696 		}
697 
698 		int arr_elements_set = 0;
699 		while (arr_elements_set < 64)
700 		{
701 			unsigned int idx = (unsigned int)astc::rand(rng_state);
702 			idx %= xdim * ydim;
703 			if (arr[idx] == 0)
704 			{
705 				arr_elements_set++;
706 				arr[idx] = 1;
707 			}
708 		}
709 
710 		int texel_weights_written = 0;
711 		int idx = 0;
712 		while (texel_weights_written < 64)
713 		{
714 			if (arr[idx])
715 			{
716 				bsd->texels_for_bitmap_partitioning[texel_weights_written++] = idx;
717 			}
718 			idx++;
719 		}
720 
721 		bsd->texelcount_for_bitmap_partitioning = 64;
722 	}
723 }
724 
construct_block_size_descriptor_3d(int xdim,int ydim,int zdim,block_size_descriptor * bsd)725 static void construct_block_size_descriptor_3d(
726 	int xdim,
727 	int ydim,
728 	int zdim,
729 	block_size_descriptor * bsd
730 ) {
731 	int decimation_mode_index[512];	// for each of the 512 entries in the decim_table_array, its index
732 	int decimation_mode_count = 0;
733 
734 	bsd->xdim = xdim;
735 	bsd->ydim = ydim;
736 	bsd->zdim = zdim;
737 	bsd->texel_count = xdim * ydim * zdim;
738 
739 	for (int i = 0; i < 512; i++)
740 	{
741 		decimation_mode_index[i] = -1;
742 	}
743 
744 	// gather all the infill-modes that can be used with the current block size
745 	for (int x_weights = 2; x_weights <= 6; x_weights++)
746 	{
747 		for (int y_weights = 2; y_weights <= 6; y_weights++)
748 		{
749 			for (int z_weights = 2; z_weights <= 6; z_weights++)
750 			{
751 				if ((x_weights * y_weights * z_weights) > MAX_WEIGHTS_PER_BLOCK)
752 					continue;
753 				decimation_table *dt = new decimation_table;
754 				decimation_mode_index[z_weights * 64 + y_weights * 8 + x_weights] = decimation_mode_count;
755 				initialize_decimation_table_3d(xdim, ydim, zdim, x_weights, y_weights, z_weights, dt);
756 
757 				int weight_count = x_weights * y_weights * z_weights;
758 
759 				int maxprec_1plane = -1;
760 				int maxprec_2planes = -1;
761 				for (int i = 0; i < 12; i++)
762 				{
763 					int bits_1plane = compute_ise_bitcount(weight_count, (quantization_method) i);
764 					int bits_2planes = compute_ise_bitcount(2 * weight_count, (quantization_method) i);
765 					if (bits_1plane >= MIN_WEIGHT_BITS_PER_BLOCK && bits_1plane <= MAX_WEIGHT_BITS_PER_BLOCK)
766 						maxprec_1plane = i;
767 					if (bits_2planes >= MIN_WEIGHT_BITS_PER_BLOCK && bits_2planes <= MAX_WEIGHT_BITS_PER_BLOCK)
768 						maxprec_2planes = i;
769 				}
770 
771 				if ((2 * x_weights * y_weights * z_weights) > MAX_WEIGHTS_PER_BLOCK)
772 					maxprec_2planes = -1;
773 
774 				bsd->permit_encode[decimation_mode_count] = (x_weights <= xdim && y_weights <= ydim && z_weights <= zdim);
775 
776 				bsd->decimation_mode_samples[decimation_mode_count] = weight_count;
777 				bsd->decimation_mode_maxprec_1plane[decimation_mode_count] = maxprec_1plane;
778 				bsd->decimation_mode_maxprec_2planes[decimation_mode_count] = maxprec_2planes;
779 				bsd->decimation_tables[decimation_mode_count] = dt;
780 
781 				decimation_mode_count++;
782 			}
783 		}
784 	}
785 
786 	for (int i = 0; i < MAX_DECIMATION_MODES; i++)
787 	{
788 		bsd->decimation_mode_percentile[i] = 1.0f;
789 	}
790 
791 	for (int i = decimation_mode_count; i < MAX_DECIMATION_MODES; i++)
792 	{
793 		bsd->permit_encode[i] = 0;
794 		bsd->decimation_mode_samples[i] = 0;
795 		bsd->decimation_mode_maxprec_1plane[i] = -1;
796 		bsd->decimation_mode_maxprec_2planes[i] = -1;
797 	}
798 
799 	bsd->decimation_mode_count = decimation_mode_count;
800 
801 	// then construct the list of block formats
802 	for (int i = 0; i < 2048; i++)
803 	{
804 		int x_weights, y_weights, z_weights;
805 		int is_dual_plane;
806 		int quantization_mode;
807 		int fail = 0;
808 		int permit_encode = 1;
809 
810 		if (decode_block_mode_3d(i, &x_weights, &y_weights, &z_weights, &is_dual_plane, &quantization_mode))
811 		{
812 			if (x_weights > xdim || y_weights > ydim || z_weights > zdim)
813 				permit_encode = 0;
814 		}
815 		else
816 		{
817 			fail = 1;
818 			permit_encode = 0;
819 		}
820 		if (fail)
821 		{
822 			bsd->block_modes[i].decimation_mode = -1;
823 			bsd->block_modes[i].quantization_mode = -1;
824 			bsd->block_modes[i].is_dual_plane = -1;
825 			bsd->block_modes[i].permit_encode = 0;
826 			bsd->block_modes[i].permit_decode = 0;
827 			bsd->block_modes[i].percentile = 1.0f;
828 		}
829 		else
830 		{
831 			int decimation_mode = decimation_mode_index[z_weights * 64 + y_weights * 8 + x_weights];
832 			bsd->block_modes[i].decimation_mode = decimation_mode;
833 			bsd->block_modes[i].quantization_mode = quantization_mode;
834 			bsd->block_modes[i].is_dual_plane = is_dual_plane;
835 			bsd->block_modes[i].permit_encode = permit_encode;
836 			bsd->block_modes[i].permit_decode = permit_encode;
837 
838 			bsd->block_modes[i].percentile = 0.0f; // No percentile table
839 			if (bsd->decimation_mode_percentile[decimation_mode] > 0.0f)
840 				bsd->decimation_mode_percentile[decimation_mode] = 0.0f;
841 		}
842 	}
843 
844 	if (xdim * ydim * zdim <= 64)
845 	{
846 		bsd->texelcount_for_bitmap_partitioning = xdim * ydim * zdim;
847 		for (int i = 0; i < xdim * ydim * zdim; i++)
848 		{
849 			bsd->texels_for_bitmap_partitioning[i] = i;
850 		}
851 	}
852 	else
853 	{
854 		uint64_t rng_state[2];
855 		astc::rand_init(rng_state);
856 
857 		// pick 64 random texels for use with bitmap partitioning.
858 		int arr[MAX_TEXELS_PER_BLOCK];
859 		for (int i = 0; i < xdim * ydim * zdim; i++)
860 		{
861 			arr[i] = 0;
862 		}
863 
864 		int arr_elements_set = 0;
865 		while (arr_elements_set < 64)
866 		{
867 			unsigned int idx = (unsigned int)astc::rand(rng_state);
868 			idx %= xdim * ydim * zdim;
869 			if (arr[idx] == 0)
870 			{
871 				arr_elements_set++;
872 				arr[idx] = 1;
873 			}
874 		}
875 
876 		int texel_weights_written = 0;
877 		int idx = 0;
878 		while (texel_weights_written < 64)
879 		{
880 			if (arr[idx])
881 				bsd->texels_for_bitmap_partitioning[texel_weights_written++] = idx;
882 			idx++;
883 		}
884 		bsd->texelcount_for_bitmap_partitioning = 64;
885 	}
886 }
887 
888 /* Public function, see header file for detailed documentation */
init_block_size_descriptor(int xdim,int ydim,int zdim,block_size_descriptor * bsd)889 void init_block_size_descriptor(
890 	int xdim,
891 	int ydim,
892 	int zdim,
893 	block_size_descriptor* bsd
894 ) {
895 	if (zdim > 1)
896 		construct_block_size_descriptor_3d(xdim, ydim, zdim, bsd);
897 	else
898 		construct_block_size_descriptor_2d(xdim, ydim, bsd);
899 
900 	init_partition_tables(bsd);
901 }
902 
term_block_size_descriptor(block_size_descriptor * bsd)903 void term_block_size_descriptor(
904 	block_size_descriptor* bsd)
905 {
906 	for(int i = 0; i < bsd->decimation_mode_count; i++)
907 	{
908 		delete bsd->decimation_tables[i];
909 	}
910 }
911