1 // SPDX-License-Identifier: Apache-2.0
2 // ----------------------------------------------------------------------------
3 // Copyright 2011-2021 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 #if !defined(ASTCENC_DECOMPRESS_ONLY)
19 
20 /**
21  * @brief Functions for color quantization.
22  *
23  * The design of the color quantization functionality requires the caller to use higher level error
24  * analysis to determine the base encoding that should be used. This earlier analysis will select
25  * the basic type of the endpoint that should be used:
26  *
27  *     * Mode: LDR or HDR
28  *     * Quantization level
29  *     * Channel count: L, LA, RGB, or RGBA
30  *     * Endpoint 2 type: Direct color endcode, or scaled from endpoint 1.
31  *
32  * However, this leaves a number of decisions about exactly how to pack the endpoints open. In
33  * particular we need to determine if blue contraction can be used, or/and if delta encoding can be
34  * used. If they can be applied these will allow us to maintain higher precision in the endpoints
35  * without needing additional storage.
36  */
37 
38 #include <stdio.h>
39 #include <assert.h>
40 
41 #include "astcenc_internal.h"
42 
43 /**
44  * @brief Determine the quantized value given a quantization level.
45  *
46  * @param quant_level   The quantization level to use.
47  * @param value         The value to convert. This may be outside of the 0-255 range and will be
48  *                      clamped before the value is looked up.
49  *
50  * @return The encoded quantized value. These are not necessarily in order; the compressor
51  *         scrambles the values slightly to make hardware implementation easier.
52  */
quant_color_clamp(quant_method quant_level,int value)53 static inline int quant_color_clamp(
54 	quant_method quant_level,
55 	int value
56 ) {
57 	value = astc::clamp(value, 0, 255);
58 	return color_quant_tables[quant_level - QUANT_6][value];
59 }
60 
61 /**
62  * @brief Determine the quantized value given a quantization level.
63  *
64  * @param quant_level   The quantization level to use.
65  * @param value         The value to convert. This may be outside of the 0-255 range and will be
66  *                      clamped before the value is looked up.
67  *
68  * @return The encoded quantized value. These are not necessarily in order; the compressor
69  *         scrambles the values slightly to make hardware implementation easier.
70  */
quant_color(quant_method quant_level,int value)71 static inline uint8_t quant_color(
72 	quant_method quant_level,
73 	int value
74 ) {
75 	return color_quant_tables[quant_level - QUANT_6][value];
76 }
77 
78 /**
79  * @brief Determine the unquantized value given a quantization level.
80  *
81  * @param quant_level   The quantization level to use.
82  * @param value         The value to convert.
83  *
84  * @return The encoded quantized value. These are not necessarily in order; the compressor
85  *         scrambles the values slightly to make hardware implementation easier.
86  */
unquant_color(quant_method quant_level,int value)87 static inline uint8_t unquant_color(
88 	quant_method quant_level,
89 	int value
90 ) {
91 	return color_unquant_tables[quant_level - QUANT_6][value];
92 }
93 
94 /**
95  * @brief Quantize an LDR RGB color.
96  *
97  * Since this is a fall-back encoding, we cannot actually fail but must produce a sensible result.
98  * For this encoding @c color0 cannot be larger than @c color1. If @c color0 is actually larger
99  * than @c color1, @c color0 is reduced and @c color1 is increased until the constraint is met.
100  *
101  * @param      color0        The input unquantized color0 endpoint.
102  * @param      color1        The input unquantized color1 endpoint.
103  * @param[out] output        The output endpoints, returned as (r0, r1, g0, g1, b0, b1).
104  * @param      quant_level   The quantization level to use.
105  */
quantize_rgb(vfloat4 color0,vfloat4 color1,uint8_t output[6],quant_method quant_level)106 static void quantize_rgb(
107 	vfloat4 color0,
108 	vfloat4 color1,
109 	uint8_t output[6],
110 	quant_method quant_level
111 ) {
112 	float scale = 1.0f / 257.0f;
113 
114 	float r0 = astc::clamp255f(color0.lane<0>() * scale);
115 	float g0 = astc::clamp255f(color0.lane<1>() * scale);
116 	float b0 = astc::clamp255f(color0.lane<2>() * scale);
117 
118 	float r1 = astc::clamp255f(color1.lane<0>() * scale);
119 	float g1 = astc::clamp255f(color1.lane<1>() * scale);
120 	float b1 = astc::clamp255f(color1.lane<2>() * scale);
121 
122 	int ri0, gi0, bi0, ri1, gi1, bi1;
123 	int ri0b, gi0b, bi0b, ri1b, gi1b, bi1b;
124 	float rgb0_addon = 0.5f;
125 	float rgb1_addon = 0.5f;
126 	do
127 	{
128 		ri0 = quant_color_clamp(quant_level, astc::flt2int_rd(r0 + rgb0_addon));
129 		gi0 = quant_color_clamp(quant_level, astc::flt2int_rd(g0 + rgb0_addon));
130 		bi0 = quant_color_clamp(quant_level, astc::flt2int_rd(b0 + rgb0_addon));
131 		ri1 = quant_color_clamp(quant_level, astc::flt2int_rd(r1 + rgb1_addon));
132 		gi1 = quant_color_clamp(quant_level, astc::flt2int_rd(g1 + rgb1_addon));
133 		bi1 = quant_color_clamp(quant_level, astc::flt2int_rd(b1 + rgb1_addon));
134 
135 		ri0b = unquant_color(quant_level, ri0);
136 		gi0b = unquant_color(quant_level, gi0);
137 		bi0b = unquant_color(quant_level, bi0);
138 		ri1b = unquant_color(quant_level, ri1);
139 		gi1b = unquant_color(quant_level, gi1);
140 		bi1b = unquant_color(quant_level, bi1);
141 
142 		rgb0_addon -= 0.2f;
143 		rgb1_addon += 0.2f;
144 	} while (ri0b + gi0b + bi0b > ri1b + gi1b + bi1b);
145 
146 	output[0] = static_cast<uint8_t>(ri0);
147 	output[1] = static_cast<uint8_t>(ri1);
148 	output[2] = static_cast<uint8_t>(gi0);
149 	output[3] = static_cast<uint8_t>(gi1);
150 	output[4] = static_cast<uint8_t>(bi0);
151 	output[5] = static_cast<uint8_t>(bi1);
152 }
153 
154 /**
155  * @brief Quantize an LDR RGBA color.
156  *
157  * Since this is a fall-back encoding, we cannot actually fail but must produce a sensible result.
158  * For this encoding @c color0.rgb cannot be larger than @c color1.rgb (this indicates blue
159  * contraction). If @c color0.rgb is actually larger than @c color1.rgb, @c color0.rgb is reduced
160  * and @c color1.rgb is increased until the constraint is met.
161  *
162  * @param      color0        The input unquantized color0 endpoint.
163  * @param      color1        The input unquantized color1 endpoint.
164  * @param[out] output        The output endpoints, returned as (r0, r1, g0, g1, b0, b1, a0, a1).
165  * @param      quant_level   The quantization level to use.
166  */
quantize_rgba(vfloat4 color0,vfloat4 color1,uint8_t output[8],quant_method quant_level)167 static void quantize_rgba(
168 	vfloat4 color0,
169 	vfloat4 color1,
170 	uint8_t output[8],
171 	quant_method quant_level
172 ) {
173 	float scale = 1.0f / 257.0f;
174 
175 	float a0 = astc::clamp255f(color0.lane<3>() * scale);
176 	float a1 = astc::clamp255f(color1.lane<3>() * scale);
177 
178 	output[6] = quant_color(quant_level, astc::flt2int_rtn(a0));
179 	output[7] = quant_color(quant_level, astc::flt2int_rtn(a1));
180 
181 	quantize_rgb(color0, color1, output, quant_level);
182 }
183 
184 /**
185  * @brief Try to quantize an LDR RGB color using blue-contraction.
186  *
187  * Blue-contraction is only usable if encoded color 1 is larger than color 0.
188  *
189  * @param      color0        The input unquantized color0 endpoint.
190  * @param      color1        The input unquantized color1 endpoint.
191  * @param[out] output        The output endpoints, returned as (r1, r0, g1, g0, b1, b0).
192  * @param      quant_level   The quantization level to use.
193  *
194  * @return Returns @c false on failure, @c true on success.
195  */
try_quantize_rgb_blue_contract(vfloat4 color0,vfloat4 color1,uint8_t output[6],quant_method quant_level)196 static bool try_quantize_rgb_blue_contract(
197 	vfloat4 color0,
198 	vfloat4 color1,
199 	uint8_t output[6],
200 	quant_method quant_level
201 ) {
202 	float scale = 1.0f / 257.0f;
203 
204 	float r0 = color0.lane<0>() * scale;
205 	float g0 = color0.lane<1>() * scale;
206 	float b0 = color0.lane<2>() * scale;
207 
208 	float r1 = color1.lane<0>() * scale;
209 	float g1 = color1.lane<1>() * scale;
210 	float b1 = color1.lane<2>() * scale;
211 
212 	// Apply inverse blue-contraction. This can produce an overflow; which means BC cannot be used.
213 	r0 += (r0 - b0);
214 	g0 += (g0 - b0);
215 	r1 += (r1 - b1);
216 	g1 += (g1 - b1);
217 
218 	if (r0 < 0.0f || r0 > 255.0f || g0 < 0.0f || g0 > 255.0f || b0 < 0.0f || b0 > 255.0f ||
219 		r1 < 0.0f || r1 > 255.0f || g1 < 0.0f || g1 > 255.0f || b1 < 0.0f || b1 > 255.0f)
220 	{
221 		return false;
222 	}
223 
224 	// Quantize the inverse-blue-contracted color
225 	int ri0 = quant_color(quant_level, astc::flt2int_rtn(r0));
226 	int gi0 = quant_color(quant_level, astc::flt2int_rtn(g0));
227 	int bi0 = quant_color(quant_level, astc::flt2int_rtn(b0));
228 
229 	int ri1 = quant_color(quant_level, astc::flt2int_rtn(r1));
230 	int gi1 = quant_color(quant_level, astc::flt2int_rtn(g1));
231 	int bi1 = quant_color(quant_level, astc::flt2int_rtn(b1));
232 
233 	// Then unquantize again
234 	int ru0 = unquant_color(quant_level, ri0);
235 	int gu0 = unquant_color(quant_level, gi0);
236 	int bu0 = unquant_color(quant_level, bi0);
237 
238 	int ru1 = unquant_color(quant_level, ri1);
239 	int gu1 = unquant_color(quant_level, gi1);
240 	int bu1 = unquant_color(quant_level, bi1);
241 
242 	// If color #1 is not larger than color #0 then blue-contraction cannot be used. Note that
243 	// blue-contraction and quantization change this order, which is why we must test aftwards.
244 	if (ru1 + gu1 + bu1 <= ru0 + gu0 + bu0)
245 	{
246 		return false;
247 	}
248 
249 	output[0] = static_cast<uint8_t>(ri1);
250 	output[1] = static_cast<uint8_t>(ri0);
251 	output[2] = static_cast<uint8_t>(gi1);
252 	output[3] = static_cast<uint8_t>(gi0);
253 	output[4] = static_cast<uint8_t>(bi1);
254 	output[5] = static_cast<uint8_t>(bi0);
255 
256 	return true;
257 }
258 
259 /**
260  * @brief Try to quantize an LDR RGBA color using blue-contraction.
261  *
262  * Blue-contraction is only usable if encoded color 1 RGB is larger than color 0 RGB.
263  *
264  * @param      color0        The input unquantized color0 endpoint.
265  * @param      color1        The input unquantized color1 endpoint.
266  * @param[out] output        The output endpoints, returned as (r1, r0, g1, g0, b1, b0, a1, a0).
267  * @param      quant_level   The quantization level to use.
268  *
269  * @return Returns @c false on failure, @c true on success.
270  */
try_quantize_rgba_blue_contract(vfloat4 color0,vfloat4 color1,uint8_t output[8],quant_method quant_level)271 static int try_quantize_rgba_blue_contract(
272 	vfloat4 color0,
273 	vfloat4 color1,
274 	uint8_t output[8],
275 	quant_method quant_level
276 ) {
277 	float scale = 1.0f / 257.0f;
278 
279 	float a0 = astc::clamp255f(color0.lane<3>() * scale);
280 	float a1 = astc::clamp255f(color1.lane<3>() * scale);
281 
282 	output[6] = quant_color(quant_level, astc::flt2int_rtn(a1));
283 	output[7] = quant_color(quant_level, astc::flt2int_rtn(a0));
284 
285 	return try_quantize_rgb_blue_contract(color0, color1, output, quant_level);
286 }
287 
288 /**
289  * @brief Try to quantize an LDR RGB color using delta encoding.
290  *
291  * At decode time we move one bit from the offset to the base and seize another bit as a sign bit;
292  * we then unquantize both values as if they contain one extra bit. If the sum of the offsets is
293  * non-negative, then we encode a regular delta.
294  *
295  * @param      color0        The input unquantized color0 endpoint.
296  * @param      color1        The input unquantized color1 endpoint.
297  * @param[out] output        The output endpoints, returned as (r0, r1, g0, g1, b0, b1).
298  * @param      quant_level   The quantization level to use.
299  *
300  * @return Returns @c false on failure, @c true on success.
301  */
try_quantize_rgb_delta(vfloat4 color0,vfloat4 color1,uint8_t output[6],quant_method quant_level)302 static bool try_quantize_rgb_delta(
303 	vfloat4 color0,
304 	vfloat4 color1,
305 	uint8_t output[6],
306 	quant_method quant_level
307 ) {
308 	float scale = 1.0f / 257.0f;
309 
310 	float r0 = astc::clamp255f(color0.lane<0>() * scale);
311 	float g0 = astc::clamp255f(color0.lane<1>() * scale);
312 	float b0 = astc::clamp255f(color0.lane<2>() * scale);
313 
314 	float r1 = astc::clamp255f(color1.lane<0>() * scale);
315 	float g1 = astc::clamp255f(color1.lane<1>() * scale);
316 	float b1 = astc::clamp255f(color1.lane<2>() * scale);
317 
318 	// Transform r0 to unorm9
319 	int r0a = astc::flt2int_rtn(r0);
320 	int g0a = astc::flt2int_rtn(g0);
321 	int b0a = astc::flt2int_rtn(b0);
322 
323 	r0a <<= 1;
324 	g0a <<= 1;
325 	b0a <<= 1;
326 
327 	// Mask off the top bit
328 	int r0b = r0a & 0xFF;
329 	int g0b = g0a & 0xFF;
330 	int b0b = b0a & 0xFF;
331 
332 	// Quantize then unquantize in order to get a value that we take differences against
333 	int r0be = quant_color(quant_level, r0b);
334 	int g0be = quant_color(quant_level, g0b);
335 	int b0be = quant_color(quant_level, b0b);
336 
337 	int r0bu = unquant_color(quant_level, r0be);
338 	int g0bu = unquant_color(quant_level, g0be);
339 	int b0bu = unquant_color(quant_level, b0be);
340 
341 	r0b = r0bu | (r0a & 0x100);
342 	g0b = g0bu | (g0a & 0x100);
343 	b0b = b0bu | (b0a & 0x100);
344 
345 	// Get hold of the second value
346 	int r1d = astc::flt2int_rtn(r1);
347 	int g1d = astc::flt2int_rtn(g1);
348 	int b1d = astc::flt2int_rtn(b1);
349 
350 	r1d <<= 1;
351 	g1d <<= 1;
352 	b1d <<= 1;
353 
354 	// ... and take differences
355 	r1d -= r0b;
356 	g1d -= g0b;
357 	b1d -= b0b;
358 
359 	// Check if the difference is too large to be encodable
360 	if (r1d > 63 || g1d > 63 || b1d > 63 || r1d < -64 || g1d < -64 || b1d < -64)
361 	{
362 		return false;
363 	}
364 
365 	// Insert top bit of the base into the offset
366 	r1d &= 0x7F;
367 	g1d &= 0x7F;
368 	b1d &= 0x7F;
369 
370 	r1d |= (r0b & 0x100) >> 1;
371 	g1d |= (g0b & 0x100) >> 1;
372 	b1d |= (b0b & 0x100) >> 1;
373 
374 	// Then quantize and unquantize; if this causes either top two bits to flip, then encoding fails
375 	// since we have then corrupted either the top bit of the base or the sign bit of the offset
376 	int r1de = quant_color(quant_level, r1d);
377 	int g1de = quant_color(quant_level, g1d);
378 	int b1de = quant_color(quant_level, b1d);
379 
380 	int r1du = unquant_color(quant_level, r1de);
381 	int g1du = unquant_color(quant_level, g1de);
382 	int b1du = unquant_color(quant_level, b1de);
383 
384 	if (((r1d ^ r1du) | (g1d ^ g1du) | (b1d ^ b1du)) & 0xC0)
385 	{
386 		return false;
387 	}
388 
389 	// If the sum of offsets triggers blue-contraction then encoding fails
390 	vint4 ep0(r0bu, g0bu, b0bu, 0);
391 	vint4 ep1(r1du, g1du, b1du, 0);
392 	bit_transfer_signed(ep1, ep0);
393 	if (hadd_rgb_s(ep1) < 0)
394 	{
395 		return false;
396 	}
397 
398 	// Check that the offsets produce legitimate sums as well
399 	ep0 = ep0 + ep1;
400 	if (any((ep0 < vint4(0)) | (ep0 > vint4(0xFF))))
401 	{
402 		return false;
403 	}
404 
405 	output[0] = static_cast<uint8_t>(r0be);
406 	output[1] = static_cast<uint8_t>(r1de);
407 	output[2] = static_cast<uint8_t>(g0be);
408 	output[3] = static_cast<uint8_t>(g1de);
409 	output[4] = static_cast<uint8_t>(b0be);
410 	output[5] = static_cast<uint8_t>(b1de);
411 
412 	return true;
413 }
414 
try_quantize_rgb_delta_blue_contract(vfloat4 color0,vfloat4 color1,uint8_t output[6],quant_method quant_level)415 static bool try_quantize_rgb_delta_blue_contract(
416 	vfloat4 color0,
417 	vfloat4 color1,
418 	uint8_t output[6],
419 	quant_method quant_level
420 ) {
421 	// Note: Switch around endpoint colors already at start
422 	float scale = 1.0f / 257.0f;
423 
424 	float r1 = color0.lane<0>() * scale;
425 	float g1 = color0.lane<1>() * scale;
426 	float b1 = color0.lane<2>() * scale;
427 
428 	float r0 = color1.lane<0>() * scale;
429 	float g0 = color1.lane<1>() * scale;
430 	float b0 = color1.lane<2>() * scale;
431 
432 	// Apply inverse blue-contraction. This can produce an overflow; which means BC cannot be used.
433 	r0 += (r0 - b0);
434 	g0 += (g0 - b0);
435 	r1 += (r1 - b1);
436 	g1 += (g1 - b1);
437 
438 	if (r0 < 0.0f || r0 > 255.0f || g0 < 0.0f || g0 > 255.0f || b0 < 0.0f || b0 > 255.0f ||
439 	    r1 < 0.0f || r1 > 255.0f || g1 < 0.0f || g1 > 255.0f || b1 < 0.0f || b1 > 255.0f)
440 	{
441 		return false;
442 	}
443 
444 	// Transform r0 to unorm9
445 	int r0a = astc::flt2int_rtn(r0);
446 	int g0a = astc::flt2int_rtn(g0);
447 	int b0a = astc::flt2int_rtn(b0);
448 	r0a <<= 1;
449 	g0a <<= 1;
450 	b0a <<= 1;
451 
452 	// Mask off the top bit
453 	int r0b = r0a & 0xFF;
454 	int g0b = g0a & 0xFF;
455 	int b0b = b0a & 0xFF;
456 
457 	// Quantize, then unquantize in order to get a value that we take differences against.
458 	int r0be = quant_color(quant_level, r0b);
459 	int g0be = quant_color(quant_level, g0b);
460 	int b0be = quant_color(quant_level, b0b);
461 
462 	int r0bu = unquant_color(quant_level, r0be);
463 	int g0bu = unquant_color(quant_level, g0be);
464 	int b0bu = unquant_color(quant_level, b0be);
465 
466 	r0b = r0bu | (r0a & 0x100);
467 	g0b = g0bu | (g0a & 0x100);
468 	b0b = b0bu | (b0a & 0x100);
469 
470 	// Get hold of the second value
471 	int r1d = astc::flt2int_rtn(r1);
472 	int g1d = astc::flt2int_rtn(g1);
473 	int b1d = astc::flt2int_rtn(b1);
474 
475 	r1d <<= 1;
476 	g1d <<= 1;
477 	b1d <<= 1;
478 
479 	// .. and take differences!
480 	r1d -= r0b;
481 	g1d -= g0b;
482 	b1d -= b0b;
483 
484 	// Check if the difference is too large to be encodable
485 	if (r1d > 63 || g1d > 63 || b1d > 63 || r1d < -64 || g1d < -64 || b1d < -64)
486 	{
487 		return false;
488 	}
489 
490 	// Insert top bit of the base into the offset
491 	r1d &= 0x7F;
492 	g1d &= 0x7F;
493 	b1d &= 0x7F;
494 
495 	r1d |= (r0b & 0x100) >> 1;
496 	g1d |= (g0b & 0x100) >> 1;
497 	b1d |= (b0b & 0x100) >> 1;
498 
499 	// Then quantize and  unquantize; if this causes any of the top two bits to flip,
500 	// then encoding fails, since we have then corrupted either the top bit of the base
501 	// or the sign bit of the offset.
502 	int r1de = quant_color(quant_level, r1d);
503 	int g1de = quant_color(quant_level, g1d);
504 	int b1de = quant_color(quant_level, b1d);
505 
506 	int r1du = unquant_color(quant_level, r1de);
507 	int g1du = unquant_color(quant_level, g1de);
508 	int b1du = unquant_color(quant_level, b1de);
509 
510 	if (((r1d ^ r1du) | (g1d ^ g1du) | (b1d ^ b1du)) & 0xC0)
511 	{
512 		return false;
513 	}
514 
515 	// If the sum of offsets does not trigger blue-contraction then encoding fails
516 	vint4 ep0(r0bu, g0bu, b0bu, 0);
517 	vint4 ep1(r1du, g1du, b1du, 0);
518 	bit_transfer_signed(ep1, ep0);
519 	if (hadd_rgb_s(ep1) >= 0)
520 	{
521 		return false;
522 	}
523 
524 	// Check that the offsets produce legitimate sums as well
525 	ep0 = ep0 + ep1;
526 	if (any((ep0 < vint4(0)) | (ep0 > vint4(0xFF))))
527 	{
528 		return false;
529 	}
530 
531 	output[0] = static_cast<uint8_t>(r0be);
532 	output[1] = static_cast<uint8_t>(r1de);
533 	output[2] = static_cast<uint8_t>(g0be);
534 	output[3] = static_cast<uint8_t>(g1de);
535 	output[4] = static_cast<uint8_t>(b0be);
536 	output[5] = static_cast<uint8_t>(b1de);
537 
538 	return true;
539 }
540 
541 /**
542  * @brief Try to quantize an LDR A color using delta encoding.
543  *
544  * At decode time we move one bit from the offset to the base and seize another bit as a sign bit;
545  * we then unquantize both values as if they contain one extra bit. If the sum of the offsets is
546  * non-negative, then we encode a regular delta.
547  *
548  * This function only compressed the alpha - the other elements in the output array are not touched.
549  *
550  * @param      color0        The input unquantized color0 endpoint.
551  * @param      color1        The input unquantized color1 endpoint.
552  * @param[out] output        The output endpoints, returned as (x, x, x, x, x, x, a0, a1).
553  * @param      quant_level   The quantization level to use.
554  *
555  * @return Returns @c false on failure, @c true on success.
556  */
try_quantize_alpha_delta(vfloat4 color0,vfloat4 color1,uint8_t output[8],quant_method quant_level)557 static bool try_quantize_alpha_delta(
558 	vfloat4 color0,
559 	vfloat4 color1,
560 	uint8_t output[8],
561 	quant_method quant_level
562 ) {
563 	float scale = 1.0f / 257.0f;
564 
565 	float a0 = astc::clamp255f(color0.lane<3>() * scale);
566 	float a1 = astc::clamp255f(color1.lane<3>() * scale);
567 
568 	int a0a = astc::flt2int_rtn(a0);
569 	a0a <<= 1;
570 	int a0b = a0a & 0xFF;
571 	int a0be = quant_color(quant_level, a0b);
572 	a0b = unquant_color(quant_level, a0be);
573 	a0b |= a0a & 0x100;
574 	int a1d = astc::flt2int_rtn(a1);
575 	a1d <<= 1;
576 	a1d -= a0b;
577 
578 	if (a1d > 63 || a1d < -64)
579 	{
580 		return false;
581 	}
582 
583 	a1d &= 0x7F;
584 	a1d |= (a0b & 0x100) >> 1;
585 
586 	int a1de = quant_color(quant_level, a1d);
587 	int a1du = unquant_color(quant_level, a1de);
588 	if ((a1d ^ a1du) & 0xC0)
589 	{
590 		return false;
591 	}
592 
593 	a1du &= 0x7F;
594 	if (a1du & 0x40)
595 	{
596 		a1du -= 0x80;
597 	}
598 
599 	a1du += a0b;
600 	if (a1du < 0 || a1du > 0x1FF)
601 	{
602 		return false;
603 	}
604 
605 	output[6] = static_cast<uint8_t>(a0be);
606 	output[7] = static_cast<uint8_t>(a1de);
607 
608 	return true;
609 }
610 
611 /**
612  * @brief Try to quantize an LDR LA color using delta encoding.
613  *
614  * At decode time we move one bit from the offset to the base and seize another bit as a sign bit;
615  * we then unquantize both values as if they contain one extra bit. If the sum of the offsets is
616  * non-negative, then we encode a regular delta.
617  *
618  * This function only compressed the alpha - the other elements in the output array are not touched.
619  *
620  * @param      color0        The input unquantized color0 endpoint.
621  * @param      color1        The input unquantized color1 endpoint.
622  * @param[out] output        The output endpoints, returned as (l0, l1, a0, a1).
623  * @param      quant_level   The quantization level to use.
624  *
625  * @return Returns @c false on failure, @c true on success.
626  */
try_quantize_luminance_alpha_delta(vfloat4 color0,vfloat4 color1,uint8_t output[4],quant_method quant_level)627 static bool try_quantize_luminance_alpha_delta(
628 	vfloat4 color0,
629 	vfloat4 color1,
630 	uint8_t output[4],
631 	quant_method quant_level
632 ) {
633 	float scale = 1.0f / 257.0f;
634 
635 	float l0 = astc::clamp255f(hadd_rgb_s(color0) * ((1.0f / 3.0f) * scale));
636 	float l1 = astc::clamp255f(hadd_rgb_s(color1) * ((1.0f / 3.0f) * scale));
637 
638 	float a0 = astc::clamp255f(color0.lane<3>() * scale);
639 	float a1 = astc::clamp255f(color1.lane<3>() * scale);
640 
641 	int l0a = astc::flt2int_rtn(l0);
642 	int a0a = astc::flt2int_rtn(a0);
643 	l0a <<= 1;
644 	a0a <<= 1;
645 
646 	int l0b = l0a & 0xFF;
647 	int a0b = a0a & 0xFF;
648 	int l0be = quant_color(quant_level, l0b);
649 	int a0be = quant_color(quant_level, a0b);
650 	l0b = unquant_color(quant_level, l0be);
651 	a0b = unquant_color(quant_level, a0be);
652 	l0b |= l0a & 0x100;
653 	a0b |= a0a & 0x100;
654 
655 	int l1d = astc::flt2int_rtn(l1);
656 	int a1d = astc::flt2int_rtn(a1);
657 	l1d <<= 1;
658 	a1d <<= 1;
659 	l1d -= l0b;
660 	a1d -= a0b;
661 
662 	if (l1d > 63 || l1d < -64)
663 	{
664 		return false;
665 	}
666 
667 	if (a1d > 63 || a1d < -64)
668 	{
669 		return false;
670 	}
671 
672 	l1d &= 0x7F;
673 	a1d &= 0x7F;
674 	l1d |= (l0b & 0x100) >> 1;
675 	a1d |= (a0b & 0x100) >> 1;
676 
677 	int l1de = quant_color(quant_level, l1d);
678 	int a1de = quant_color(quant_level, a1d);
679 	int l1du = unquant_color(quant_level, l1de);
680 	int a1du = unquant_color(quant_level, a1de);
681 
682 	if ((l1d ^ l1du) & 0xC0)
683 	{
684 		return false;
685 	}
686 
687 	if ((a1d ^ a1du) & 0xC0)
688 	{
689 		return false;
690 	}
691 
692 	l1du &= 0x7F;
693 	a1du &= 0x7F;
694 
695 	if (l1du & 0x40)
696 	{
697 		l1du -= 0x80;
698 	}
699 
700 	if (a1du & 0x40)
701 	{
702 		a1du -= 0x80;
703 	}
704 
705 	l1du += l0b;
706 	a1du += a0b;
707 
708 	if (l1du < 0 || l1du > 0x1FF)
709 	{
710 		return false;
711 	}
712 
713 	if (a1du < 0 || a1du > 0x1FF)
714 	{
715 		return false;
716 	}
717 
718 	output[0] = static_cast<uint8_t>(l0be);
719 	output[1] = static_cast<uint8_t>(l1de);
720 	output[2] = static_cast<uint8_t>(a0be);
721 	output[3] = static_cast<uint8_t>(a1de);
722 
723 	return true;
724 }
725 
726 /**
727  * @brief Try to quantize an LDR RGBA color using delta encoding.
728  *
729  * At decode time we move one bit from the offset to the base and seize another bit as a sign bit;
730  * we then unquantize both values as if they contain one extra bit. If the sum of the offsets is
731  * non-negative, then we encode a regular delta.
732  *
733  * This function only compressed the alpha - the other elements in the output array are not touched.
734  *
735  * @param      color0        The input unquantized color0 endpoint.
736  * @param      color1        The input unquantized color1 endpoint.
737  * @param[out] output        The output endpoints, returned as (r0, r1, b0, b1, g0, g1, a0, a1).
738  * @param      quant_level   The quantization level to use.
739  *
740  * @return Returns @c false on failure, @c true on success.
741  */
try_quantize_rgba_delta(vfloat4 color0,vfloat4 color1,uint8_t output[8],quant_method quant_level)742 static bool try_quantize_rgba_delta(
743 	vfloat4 color0,
744 	vfloat4 color1,
745 	uint8_t output[8],
746 	quant_method quant_level
747 ) {
748 	return try_quantize_rgb_delta(color0, color1, output, quant_level) &&
749 	       try_quantize_alpha_delta(color0, color1, output, quant_level);
750 }
751 
752 
753 /**
754  * @brief Try to quantize an LDR RGBA color using delta and blue contract encoding.
755  *
756  * At decode time we move one bit from the offset to the base and seize another bit as a sign bit;
757  * we then unquantize both values as if they contain one extra bit. If the sum of the offsets is
758  * non-negative, then we encode a regular delta.
759  *
760  * This function only compressed the alpha - the other elements in the output array are not touched.
761  *
762  * @param      color0       The input unquantized color0 endpoint.
763  * @param      color1       The input unquantized color1 endpoint.
764  * @param[out] output       The output endpoints, returned as (r0, r1, b0, b1, g0, g1, a0, a1).
765  * @param      quant_level  The quantization level to use.
766  *
767  * @return Returns @c false on failure, @c true on success.
768  */
try_quantize_rgba_delta_blue_contract(vfloat4 color0,vfloat4 color1,uint8_t output[8],quant_method quant_level)769 static bool try_quantize_rgba_delta_blue_contract(
770 	vfloat4 color0,
771 	vfloat4 color1,
772 	uint8_t output[8],
773 	quant_method quant_level
774 ) {
775 	// Note that we swap the color0 and color1 ordering for alpha to match RGB blue-contract
776 	return try_quantize_rgb_delta_blue_contract(color0, color1, output, quant_level) &&
777 	       try_quantize_alpha_delta(color1, color0, output, quant_level);
778 }
779 
780 /**
781  * @brief Quantize an LDR RGB color using scale encoding.
782  *
783  * @param      color         The input unquantized color endpoint and scale factor.
784  * @param[out] output        The output endpoints, returned as (r0, g0, b0, s).
785  * @param      quant_level   The quantization level to use.
786  */
quantize_rgbs(vfloat4 color,uint8_t output[4],quant_method quant_level)787 static void quantize_rgbs(
788 	vfloat4 color,
789 	uint8_t output[4],
790 	quant_method quant_level
791 ) {
792 	float scale = 1.0f / 257.0f;
793 
794 	float r = astc::clamp255f(color.lane<0>() * scale);
795 	float g = astc::clamp255f(color.lane<1>() * scale);
796 	float b = astc::clamp255f(color.lane<2>() * scale);
797 
798 	int ri = quant_color(quant_level, astc::flt2int_rtn(r));
799 	int gi = quant_color(quant_level, astc::flt2int_rtn(g));
800 	int bi = quant_color(quant_level, astc::flt2int_rtn(b));
801 
802 	int ru = unquant_color(quant_level, ri);
803 	int gu = unquant_color(quant_level, gi);
804 	int bu = unquant_color(quant_level, bi);
805 
806 	float oldcolorsum = hadd_rgb_s(color) * scale;
807 	float newcolorsum = static_cast<float>(ru + gu + bu);
808 
809 	float scalea = astc::clamp1f(color.lane<3>() * (oldcolorsum + 1e-10f) / (newcolorsum + 1e-10f));
810 	int scale_idx = astc::flt2int_rtn(scalea * 256.0f);
811 	scale_idx = astc::clamp(scale_idx, 0, 255);
812 
813 	output[0] = static_cast<uint8_t>(ri);
814 	output[1] = static_cast<uint8_t>(gi);
815 	output[2] = static_cast<uint8_t>(bi);
816 	output[3] = quant_color(quant_level, scale_idx);
817 }
818 
819 /**
820  * @brief Quantize an LDR RGBA color using scale encoding.
821  *
822  * @param      color        The input unquantized color endpoint and scale factor.
823  * @param[out] output       The output endpoints, returned as (r0, g0, b0, s, a0, a1).
824  * @param      quant_level  The quantization level to use.
825  */
quantize_rgbs_alpha(vfloat4 color0,vfloat4 color1,vfloat4 color,uint8_t output[6],quant_method quant_level)826 static void quantize_rgbs_alpha(
827 	vfloat4 color0,
828 	vfloat4 color1,
829 	vfloat4 color,
830 	uint8_t output[6],
831 	quant_method quant_level
832 ) {
833 	float scale = 1.0f / 257.0f;
834 
835 	float a0 = astc::clamp255f(color0.lane<3>() * scale);
836 	float a1 = astc::clamp255f(color1.lane<3>() * scale);
837 
838 	output[4] = quant_color(quant_level, astc::flt2int_rtn(a0));
839 	output[5] = quant_color(quant_level, astc::flt2int_rtn(a1));
840 
841 	quantize_rgbs(color, output, quant_level);
842 }
843 
844 /**
845  * @brief Quantize a LDR L color.
846  *
847  * @param      color0        The input unquantized color0 endpoint.
848  * @param      color1        The input unquantized color1 endpoint.
849  * @param[out] output        The output endpoints, returned as (l0, l1).
850  * @param      quant_level   The quantization level to use.
851  */
quantize_luminance(vfloat4 color0,vfloat4 color1,uint8_t output[2],quant_method quant_level)852 static void quantize_luminance(
853 	vfloat4 color0,
854 	vfloat4 color1,
855 	uint8_t output[2],
856 	quant_method quant_level
857 ) {
858 	float scale = 1.0f / 257.0f;
859 
860 	color0 = color0 * scale;
861 	color1 = color1 * scale;
862 
863 	float lum0 = astc::clamp255f(hadd_rgb_s(color0) * (1.0f / 3.0f));
864 	float lum1 = astc::clamp255f(hadd_rgb_s(color1) * (1.0f / 3.0f));
865 
866 	if (lum0 > lum1)
867 	{
868 		float avg = (lum0 + lum1) * 0.5f;
869 		lum0 = avg;
870 		lum1 = avg;
871 	}
872 
873 	output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0));
874 	output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1));
875 }
876 
877 /**
878  * @brief Quantize a LDR LA color.
879  *
880  * @param      color0        The input unquantized color0 endpoint.
881  * @param      color1        The input unquantized color1 endpoint.
882  * @param[out] output        The output endpoints, returned as (l0, l1, a0, a1).
883  * @param      quant_level   The quantization level to use.
884  */
quantize_luminance_alpha(vfloat4 color0,vfloat4 color1,uint8_t output[4],quant_method quant_level)885 static void quantize_luminance_alpha(
886 	vfloat4 color0,
887 	vfloat4 color1,
888 	uint8_t output[4],
889 	quant_method quant_level
890 ) {
891 	float scale = 1.0f / 257.0f;
892 
893 	color0 = color0 * scale;
894 	color1 = color1 * scale;
895 
896 	float lum0 = astc::clamp255f(hadd_rgb_s(color0) * (1.0f / 3.0f));
897 	float lum1 = astc::clamp255f(hadd_rgb_s(color1) * (1.0f / 3.0f));
898 
899 	float a0 = astc::clamp255f(color0.lane<3>());
900 	float a1 = astc::clamp255f(color1.lane<3>());
901 
902 	// If endpoints are close then pull apart slightly; this gives > 8 bit normal map precision.
903 	if (quant_level > 18)
904 	{
905 		if (fabsf(lum0 - lum1) < 3.0f)
906 		{
907 			if (lum0 < lum1)
908 			{
909 				lum0 -= 0.5f;
910 				lum1 += 0.5f;
911 			}
912 			else
913 			{
914 				lum0 += 0.5f;
915 				lum1 -= 0.5f;
916 			}
917 
918 			lum0 = astc::clamp255f(lum0);
919 			lum1 = astc::clamp255f(lum1);
920 		}
921 
922 		if (fabsf(a0 - a1) < 3.0f)
923 		{
924 			if (a0 < a1)
925 			{
926 				a0 -= 0.5f;
927 				a1 += 0.5f;
928 			}
929 			else
930 			{
931 				a0 += 0.5f;
932 				a1 -= 0.5f;
933 			}
934 
935 			a0 = astc::clamp255f(a0);
936 			a1 = astc::clamp255f(a1);
937 		}
938 	}
939 
940 	output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0));
941 	output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1));
942 	output[2] = quant_color(quant_level, astc::flt2int_rtn(a0));
943 	output[3] = quant_color(quant_level, astc::flt2int_rtn(a1));
944 }
945 
946 /**
947  * @brief Quantize and unquantize a value ensuring top two bits are the same.
948  *
949  * @param      quant_level     The quantization level to use.
950  * @param      value           The input unquantized value.
951  * @param[out] quant_value     The quantized value.
952  * @param[out] unquant_value   The unquantized value after quantization.
953  */
quantize_and_unquantize_retain_top_two_bits(quant_method quant_level,uint8_t value,uint8_t & quant_value,uint8_t & unquant_value)954 static inline void quantize_and_unquantize_retain_top_two_bits(
955 	quant_method quant_level,
956 	uint8_t value,
957 	uint8_t& quant_value,
958 	uint8_t& unquant_value
959 ) {
960 	int perform_loop;
961 	uint8_t quantval;
962 	uint8_t uquantval;
963 
964 	do
965 	{
966 		quantval = quant_color(quant_level, value);
967 		uquantval = unquant_color(quant_level, quantval);
968 
969 		// Perform looping if the top two bits were modified by quant/unquant
970 		perform_loop = (value & 0xC0) != (uquantval & 0xC0);
971 
972 		if ((uquantval & 0xC0) > (value & 0xC0))
973 		{
974 			// Quant/unquant rounded UP so that the top two bits changed;
975 			// decrement the input in hopes that this will avoid rounding up.
976 			value--;
977 		}
978 		else if ((uquantval & 0xC0) < (value & 0xC0))
979 		{
980 			// Quant/unquant rounded DOWN so that the top two bits changed;
981 			// decrement the input in hopes that this will avoid rounding down.
982 			value--;
983 		}
984 	} while (perform_loop);
985 
986 	quant_value = quantval;
987 	unquant_value = uquantval;
988 }
989 
990 /**
991  * @brief Quantize and unquantize a value ensuring top four bits are the same.
992  *
993  * @param      quant_level     The quantization level to use.
994  * @param      value           The input unquantized value.
995  * @param[out] quant_value     The quantized value.
996  * @param[out] unquant_value   The unquantized value after quantization.
997  */
quantize_and_unquantize_retain_top_four_bits(quant_method quant_level,uint8_t value,uint8_t & quant_value,uint8_t & unquant_value)998 static inline void quantize_and_unquantize_retain_top_four_bits(
999 	quant_method quant_level,
1000 	uint8_t value,
1001 	uint8_t& quant_value,
1002 	uint8_t& unquant_value
1003 ) {
1004 	uint8_t perform_loop;
1005 	uint8_t quantval;
1006 	uint8_t uquantval;
1007 
1008 	do
1009 	{
1010 		quantval = quant_color(quant_level, value);
1011 		uquantval = unquant_color(quant_level, quantval);
1012 
1013 		// Perform looping if the top four bits were modified by quant/unquant
1014 		perform_loop = (value & 0xF0) != (uquantval & 0xF0);
1015 
1016 		if ((uquantval & 0xF0) > (value & 0xF0))
1017 		{
1018 			// Quant/unquant rounded UP so that the top four bits changed;
1019 			// decrement the input value in hopes that this will avoid rounding up.
1020 			value--;
1021 		}
1022 		else if ((uquantval & 0xF0) < (value & 0xF0))
1023 		{
1024 			// Quant/unquant rounded DOWN so that the top four bits changed;
1025 			// decrement the input value in hopes that this will avoid rounding down.
1026 			value--;
1027 		}
1028 	} while (perform_loop);
1029 
1030 	quant_value = quantval;
1031 	unquant_value = uquantval;
1032 }
1033 
1034 /**
1035  * @brief Quantize a HDR RGB color using RGB + offset.
1036  *
1037  * @param      color         The input unquantized color endpoint and offset.
1038  * @param[out] output        The output endpoints, returned as packed RGBS with some mode bits.
1039  * @param      quant_level   The quantization level to use.
1040  */
quantize_hdr_rgbo(vfloat4 color,uint8_t output[4],quant_method quant_level)1041 static void quantize_hdr_rgbo(
1042 	vfloat4 color,
1043 	uint8_t output[4],
1044 	quant_method quant_level
1045 ) {
1046 	color.set_lane<0>(color.lane<0>() + color.lane<3>());
1047 	color.set_lane<1>(color.lane<1>() + color.lane<3>());
1048 	color.set_lane<2>(color.lane<2>() + color.lane<3>());
1049 
1050 	color = clamp(0.0f, 65535.0f, color);
1051 
1052 	vfloat4 color_bak = color;
1053 
1054 	int majcomp;
1055 	if (color.lane<0>() > color.lane<1>() && color.lane<0>() > color.lane<2>())
1056 	{
1057 		majcomp = 0;			// red is largest component
1058 	}
1059 	else if (color.lane<1>() > color.lane<2>())
1060 	{
1061 		majcomp = 1;			// green is largest component
1062 	}
1063 	else
1064 	{
1065 		majcomp = 2;			// blue is largest component
1066 	}
1067 
1068 	// swap around the red component and the largest component.
1069 	switch (majcomp)
1070 	{
1071 	case 1:
1072 		color = color.swz<1, 0, 2, 3>();
1073 		break;
1074 	case 2:
1075 		color = color.swz<2, 1, 0, 3>();
1076 		break;
1077 	default:
1078 		break;
1079 	}
1080 
1081 	static const int mode_bits[5][3] {
1082 		{11, 5, 7},
1083 		{11, 6, 5},
1084 		{10, 5, 8},
1085 		{9, 6, 7},
1086 		{8, 7, 6}
1087 	};
1088 
1089 	static const float mode_cutoffs[5][2] {
1090 		{1024, 4096},
1091 		{2048, 1024},
1092 		{2048, 16384},
1093 		{8192, 16384},
1094 		{32768, 16384}
1095 	};
1096 
1097 	static const float mode_rscales[5] {
1098 		32.0f,
1099 		32.0f,
1100 		64.0f,
1101 		128.0f,
1102 		256.0f,
1103 	};
1104 
1105 	static const float mode_scales[5] {
1106 		1.0f / 32.0f,
1107 		1.0f / 32.0f,
1108 		1.0f / 64.0f,
1109 		1.0f / 128.0f,
1110 		1.0f / 256.0f,
1111 	};
1112 
1113 	float r_base = color.lane<0>();
1114 	float g_base = color.lane<0>() - color.lane<1>() ;
1115 	float b_base = color.lane<0>() - color.lane<2>() ;
1116 	float s_base = color.lane<3>() ;
1117 
1118 	for (int mode = 0; mode < 5; mode++)
1119 	{
1120 		if (g_base > mode_cutoffs[mode][0] || b_base > mode_cutoffs[mode][0] || s_base > mode_cutoffs[mode][1])
1121 		{
1122 			continue;
1123 		}
1124 
1125 		// Encode the mode into a 4-bit vector
1126 		int mode_enc = mode < 4 ? (mode | (majcomp << 2)) : (majcomp | 0xC);
1127 
1128 		float mode_scale = mode_scales[mode];
1129 		float mode_rscale = mode_rscales[mode];
1130 
1131 		int gb_intcutoff = 1 << mode_bits[mode][1];
1132 		int s_intcutoff = 1 << mode_bits[mode][2];
1133 
1134 		// Quantize and unquantize R
1135 		int r_intval = astc::flt2int_rtn(r_base * mode_scale);
1136 
1137 		int r_lowbits = r_intval & 0x3f;
1138 
1139 		r_lowbits |= (mode_enc & 3) << 6;
1140 
1141 		uint8_t r_quantval;
1142 		uint8_t r_uquantval;
1143 		quantize_and_unquantize_retain_top_two_bits(
1144 		    quant_level, static_cast<uint8_t>(r_lowbits), r_quantval, r_uquantval);
1145 
1146 		r_intval = (r_intval & ~0x3f) | (r_uquantval & 0x3f);
1147 		float r_fval = static_cast<float>(r_intval) * mode_rscale;
1148 
1149 		// Recompute G and B, then quantize and unquantize them
1150 		float g_fval = r_fval - color.lane<1>() ;
1151 		float b_fval = r_fval - color.lane<2>() ;
1152 
1153 		g_fval = astc::clamp(g_fval, 0.0f, 65535.0f);
1154 		b_fval = astc::clamp(b_fval, 0.0f, 65535.0f);
1155 
1156 		int g_intval = astc::flt2int_rtn(g_fval * mode_scale);
1157 		int b_intval = astc::flt2int_rtn(b_fval * mode_scale);
1158 
1159 		if (g_intval >= gb_intcutoff || b_intval >= gb_intcutoff)
1160 		{
1161 			continue;
1162 		}
1163 
1164 		int g_lowbits = g_intval & 0x1f;
1165 		int b_lowbits = b_intval & 0x1f;
1166 
1167 		int bit0 = 0;
1168 		int bit1 = 0;
1169 		int bit2 = 0;
1170 		int bit3 = 0;
1171 
1172 		switch (mode)
1173 		{
1174 		case 0:
1175 		case 2:
1176 			bit0 = (r_intval >> 9) & 1;
1177 			break;
1178 		case 1:
1179 		case 3:
1180 			bit0 = (r_intval >> 8) & 1;
1181 			break;
1182 		case 4:
1183 		case 5:
1184 			bit0 = (g_intval >> 6) & 1;
1185 			break;
1186 		}
1187 
1188 		switch (mode)
1189 		{
1190 		case 0:
1191 		case 1:
1192 		case 2:
1193 		case 3:
1194 			bit2 = (r_intval >> 7) & 1;
1195 			break;
1196 		case 4:
1197 		case 5:
1198 			bit2 = (b_intval >> 6) & 1;
1199 			break;
1200 		}
1201 
1202 		switch (mode)
1203 		{
1204 		case 0:
1205 		case 2:
1206 			bit1 = (r_intval >> 8) & 1;
1207 			break;
1208 		case 1:
1209 		case 3:
1210 		case 4:
1211 		case 5:
1212 			bit1 = (g_intval >> 5) & 1;
1213 			break;
1214 		}
1215 
1216 		switch (mode)
1217 		{
1218 		case 0:
1219 			bit3 = (r_intval >> 10) & 1;
1220 			break;
1221 		case 2:
1222 			bit3 = (r_intval >> 6) & 1;
1223 			break;
1224 		case 1:
1225 		case 3:
1226 		case 4:
1227 		case 5:
1228 			bit3 = (b_intval >> 5) & 1;
1229 			break;
1230 		}
1231 
1232 		g_lowbits |= (mode_enc & 0x4) << 5;
1233 		b_lowbits |= (mode_enc & 0x8) << 4;
1234 
1235 		g_lowbits |= bit0 << 6;
1236 		g_lowbits |= bit1 << 5;
1237 		b_lowbits |= bit2 << 6;
1238 		b_lowbits |= bit3 << 5;
1239 
1240 		uint8_t g_quantval;
1241 		uint8_t b_quantval;
1242 		uint8_t g_uquantval;
1243 		uint8_t b_uquantval;
1244 
1245 		quantize_and_unquantize_retain_top_four_bits(
1246 		    quant_level, static_cast<uint8_t>(g_lowbits), g_quantval, g_uquantval);
1247 		quantize_and_unquantize_retain_top_four_bits(
1248 		    quant_level, static_cast<uint8_t>(b_lowbits), b_quantval, b_uquantval);
1249 
1250 		g_intval = (g_intval & ~0x1f) | (g_uquantval & 0x1f);
1251 		b_intval = (b_intval & ~0x1f) | (b_uquantval & 0x1f);
1252 
1253 		g_fval = static_cast<float>(g_intval) * mode_rscale;
1254 		b_fval = static_cast<float>(b_intval) * mode_rscale;
1255 
1256 		// Recompute the scale value, based on the errors introduced to red, green and blue
1257 
1258 		// If the error is positive, then the R,G,B errors combined have raised the color
1259 		// value overall; as such, the scale value needs to be increased.
1260 		float rgb_errorsum = (r_fval - color.lane<0>() ) + (r_fval - g_fval - color.lane<1>() ) + (r_fval - b_fval - color.lane<2>() );
1261 
1262 		float s_fval = s_base + rgb_errorsum * (1.0f / 3.0f);
1263 		s_fval = astc::clamp(s_fval, 0.0f, 1e9f);
1264 
1265 		int s_intval = astc::flt2int_rtn(s_fval * mode_scale);
1266 
1267 		if (s_intval >= s_intcutoff)
1268 		{
1269 			continue;
1270 		}
1271 
1272 		int s_lowbits = s_intval & 0x1f;
1273 
1274 		int bit4;
1275 		int bit5;
1276 		int bit6;
1277 		switch (mode)
1278 		{
1279 		case 1:
1280 			bit6 = (r_intval >> 9) & 1;
1281 			break;
1282 		default:
1283 			bit6 = (s_intval >> 5) & 1;
1284 			break;
1285 		}
1286 
1287 		switch (mode)
1288 		{
1289 		case 4:
1290 			bit5 = (r_intval >> 7) & 1;
1291 			break;
1292 		case 1:
1293 			bit5 = (r_intval >> 10) & 1;
1294 			break;
1295 		default:
1296 			bit5 = (s_intval >> 6) & 1;
1297 			break;
1298 		}
1299 
1300 		switch (mode)
1301 		{
1302 		case 2:
1303 			bit4 = (s_intval >> 7) & 1;
1304 			break;
1305 		default:
1306 			bit4 = (r_intval >> 6) & 1;
1307 			break;
1308 		}
1309 
1310 		s_lowbits |= bit6 << 5;
1311 		s_lowbits |= bit5 << 6;
1312 		s_lowbits |= bit4 << 7;
1313 
1314 		uint8_t s_quantval;
1315 		uint8_t s_uquantval;
1316 
1317 		quantize_and_unquantize_retain_top_four_bits(
1318 		    quant_level, static_cast<uint8_t>(s_lowbits), s_quantval, s_uquantval);
1319 
1320 		output[0] = r_quantval;
1321 		output[1] = g_quantval;
1322 		output[2] = b_quantval;
1323 		output[3] = s_quantval;
1324 		return;
1325 	}
1326 
1327 	// Failed to encode any of the modes above? In that case encode using mode #5
1328 	float vals[4];
1329 	vals[0] = color_bak.lane<0>();
1330 	vals[1] = color_bak.lane<1>();
1331 	vals[2] = color_bak.lane<2>();
1332 	vals[3] = color_bak.lane<3>();
1333 
1334 	int ivals[4];
1335 	float cvals[3];
1336 
1337 	for (int i = 0; i < 3; i++)
1338 	{
1339 		vals[i] = astc::clamp(vals[i], 0.0f, 65020.0f);
1340 		ivals[i] = astc::flt2int_rtn(vals[i] * (1.0f / 512.0f));
1341 		cvals[i] = static_cast<float>(ivals[i]) * 512.0f;
1342 	}
1343 
1344 	float rgb_errorsum = (cvals[0] - vals[0]) + (cvals[1] - vals[1]) + (cvals[2] - vals[2]);
1345 	vals[3] += rgb_errorsum * (1.0f / 3.0f);
1346 
1347 	vals[3] = astc::clamp(vals[3], 0.0f, 65020.0f);
1348 	ivals[3] = astc::flt2int_rtn(vals[3] * (1.0f / 512.0f));
1349 
1350 	int encvals[4];
1351 	encvals[0] = (ivals[0] & 0x3f) | 0xC0;
1352 	encvals[1] = (ivals[1] & 0x7f) | 0x80;
1353 	encvals[2] = (ivals[2] & 0x7f) | 0x80;
1354 	encvals[3] = (ivals[3] & 0x7f) | ((ivals[0] & 0x40) << 1);
1355 
1356 	for (uint8_t i = 0; i < 4; i++)
1357 	{
1358 		uint8_t dummy;
1359 		quantize_and_unquantize_retain_top_four_bits(
1360 		    quant_level, static_cast<uint8_t>(encvals[i]), output[i], dummy);
1361 	}
1362 
1363 	return;
1364 }
1365 
1366 /**
1367  * @brief Quantize a HDR RGB color using direct RGB encoding.
1368  *
1369  * @param      color0        The input unquantized color0 endpoint.
1370  * @param      color1        The input unquantized color1 endpoint.
1371  * @param[out] output        The output endpoints, returned as packed RGB+RGB pairs with mode bits.
1372  * @param      quant_level   The quantization level to use.
1373  */
quantize_hdr_rgb(vfloat4 color0,vfloat4 color1,uint8_t output[6],quant_method quant_level)1374 static void quantize_hdr_rgb(
1375 	vfloat4 color0,
1376 	vfloat4 color1,
1377 	uint8_t output[6],
1378 	quant_method quant_level
1379 ) {
1380 	// Note: color*.lane<3> is not used so we can ignore it
1381 	color0 = clamp(0.0f, 65535.0f, color0);
1382 	color1 = clamp(0.0f, 65535.0f, color1);
1383 
1384 	vfloat4 color0_bak = color0;
1385 	vfloat4 color1_bak = color1;
1386 
1387 	int majcomp;
1388 	if (color1.lane<0>() > color1.lane<1>() && color1.lane<0>() > color1.lane<2>())
1389 	{
1390 		majcomp = 0;
1391 	}
1392 	else if (color1.lane<1>() > color1.lane<2>())
1393 	{
1394 		majcomp = 1;
1395 	}
1396 	else
1397 	{
1398 		majcomp = 2;
1399 	}
1400 
1401 	// Swizzle the components
1402 	switch (majcomp)
1403 	{
1404 	case 1:  // red-green swap
1405 		color0 = color0.swz<1, 0, 2, 3>();
1406 		color1 = color1.swz<1, 0, 2, 3>();
1407 		break;
1408 	case 2:  // red-blue swap
1409 		color0 = color0.swz<2, 1, 0, 3>();
1410 		color1 = color1.swz<2, 1, 0, 3>();
1411 		break;
1412 	default:
1413 		break;
1414 	}
1415 
1416 	float a_base = color1.lane<0>();
1417 	a_base = astc::clamp(a_base, 0.0f, 65535.0f);
1418 
1419 	float b0_base = a_base - color1.lane<1>();
1420 	float b1_base = a_base - color1.lane<2>();
1421 	float c_base = a_base - color0.lane<0>();
1422 	float d0_base = a_base - b0_base - c_base - color0.lane<1>();
1423 	float d1_base = a_base - b1_base - c_base - color0.lane<2>();
1424 
1425 	// Number of bits in the various fields in the various modes
1426 	static const int mode_bits[8][4] {
1427 		{9, 7, 6, 7},
1428 		{9, 8, 6, 6},
1429 		{10, 6, 7, 7},
1430 		{10, 7, 7, 6},
1431 		{11, 8, 6, 5},
1432 		{11, 6, 8, 6},
1433 		{12, 7, 7, 5},
1434 		{12, 6, 7, 6}
1435 	};
1436 
1437 	// Cutoffs to use for the computed values of a,b,c,d, assuming the
1438 	// range 0..65535 are LNS values corresponding to fp16.
1439 	static const float mode_cutoffs[8][4] {
1440 		{16384, 8192, 8192, 8},	// mode 0: 9,7,6,7
1441 		{32768, 8192, 4096, 8},	// mode 1: 9,8,6,6
1442 		{4096, 8192, 4096, 4},	// mode 2: 10,6,7,7
1443 		{8192, 8192, 2048, 4},	// mode 3: 10,7,7,6
1444 		{8192, 2048, 512, 2},	// mode 4: 11,8,6,5
1445 		{2048, 8192, 1024, 2},	// mode 5: 11,6,8,6
1446 		{2048, 2048, 256, 1},	// mode 6: 12,7,7,5
1447 		{1024, 2048, 512, 1},	// mode 7: 12,6,7,6
1448 	};
1449 
1450 	static const float mode_scales[8] {
1451 		1.0f / 128.0f,
1452 		1.0f / 128.0f,
1453 		1.0f / 64.0f,
1454 		1.0f / 64.0f,
1455 		1.0f / 32.0f,
1456 		1.0f / 32.0f,
1457 		1.0f / 16.0f,
1458 		1.0f / 16.0f,
1459 	};
1460 
1461 	// Scaling factors when going from what was encoded in the mode to 16 bits.
1462 	static const float mode_rscales[8] {
1463 		128.0f,
1464 		128.0f,
1465 		64.0f,
1466 		64.0f,
1467 		32.0f,
1468 		32.0f,
1469 		16.0f,
1470 		16.0f
1471 	};
1472 
1473 	// Try modes one by one, with the highest-precision mode first.
1474 	for (int mode = 7; mode >= 0; mode--)
1475 	{
1476 		// For each mode, test if we can in fact accommodate the computed b, c, and d values.
1477 		// If we clearly can't, then we skip to the next mode.
1478 
1479 		float b_cutoff = mode_cutoffs[mode][0];
1480 		float c_cutoff = mode_cutoffs[mode][1];
1481 		float d_cutoff = mode_cutoffs[mode][2];
1482 
1483 		if (b0_base > b_cutoff || b1_base > b_cutoff || c_base > c_cutoff || fabsf(d0_base) > d_cutoff || fabsf(d1_base) > d_cutoff)
1484 		{
1485 			continue;
1486 		}
1487 
1488 		float mode_scale = mode_scales[mode];
1489 		float mode_rscale = mode_rscales[mode];
1490 
1491 		int b_intcutoff = 1 << mode_bits[mode][1];
1492 		int c_intcutoff = 1 << mode_bits[mode][2];
1493 		int d_intcutoff = 1 << (mode_bits[mode][3] - 1);
1494 
1495 		// Quantize and unquantize A, with the assumption that its high bits can be handled safely.
1496 		int a_intval = astc::flt2int_rtn(a_base * mode_scale);
1497 		int a_lowbits = a_intval & 0xFF;
1498 
1499 		int a_quantval = quant_color(quant_level, a_lowbits);
1500 		int a_uquantval = unquant_color(quant_level, a_quantval);
1501 		a_intval = (a_intval & ~0xFF) | a_uquantval;
1502 		float a_fval = static_cast<float>(a_intval) * mode_rscale;
1503 
1504 		// Recompute C, then quantize and unquantize it
1505 		float c_fval = a_fval - color0.lane<0>();
1506 		c_fval = astc::clamp(c_fval, 0.0f, 65535.0f);
1507 
1508 		int c_intval = astc::flt2int_rtn(c_fval * mode_scale);
1509 
1510 		if (c_intval >= c_intcutoff)
1511 		{
1512 			continue;
1513 		}
1514 
1515 		int c_lowbits = c_intval & 0x3f;
1516 
1517 		c_lowbits |= (mode & 1) << 7;
1518 		c_lowbits |= (a_intval & 0x100) >> 2;
1519 
1520 		uint8_t c_quantval;
1521 		uint8_t c_uquantval;
1522 
1523 		quantize_and_unquantize_retain_top_two_bits(
1524 		    quant_level, static_cast<uint8_t>(c_lowbits), c_quantval, c_uquantval);
1525 
1526 		c_intval = (c_intval & ~0x3F) | (c_uquantval & 0x3F);
1527 		c_fval = static_cast<float>(c_intval) * mode_rscale;
1528 
1529 		// Recompute B0 and B1, then quantize and unquantize them
1530 		float b0_fval = a_fval - color1.lane<1>();
1531 		float b1_fval = a_fval - color1.lane<2>();
1532 
1533 		b0_fval = astc::clamp(b0_fval, 0.0f, 65535.0f);
1534 		b1_fval = astc::clamp(b1_fval, 0.0f, 65535.0f);
1535 		int b0_intval = astc::flt2int_rtn(b0_fval * mode_scale);
1536 		int b1_intval = astc::flt2int_rtn(b1_fval * mode_scale);
1537 
1538 		if (b0_intval >= b_intcutoff || b1_intval >= b_intcutoff)
1539 		{
1540 			continue;
1541 		}
1542 
1543 		int b0_lowbits = b0_intval & 0x3f;
1544 		int b1_lowbits = b1_intval & 0x3f;
1545 
1546 		int bit0 = 0;
1547 		int bit1 = 0;
1548 		switch (mode)
1549 		{
1550 		case 0:
1551 		case 1:
1552 		case 3:
1553 		case 4:
1554 		case 6:
1555 			bit0 = (b0_intval >> 6) & 1;
1556 			break;
1557 		case 2:
1558 		case 5:
1559 		case 7:
1560 			bit0 = (a_intval >> 9) & 1;
1561 			break;
1562 		}
1563 
1564 		switch (mode)
1565 		{
1566 		case 0:
1567 		case 1:
1568 		case 3:
1569 		case 4:
1570 		case 6:
1571 			bit1 = (b1_intval >> 6) & 1;
1572 			break;
1573 		case 2:
1574 			bit1 = (c_intval >> 6) & 1;
1575 			break;
1576 		case 5:
1577 		case 7:
1578 			bit1 = (a_intval >> 10) & 1;
1579 			break;
1580 		}
1581 
1582 		b0_lowbits |= bit0 << 6;
1583 		b1_lowbits |= bit1 << 6;
1584 
1585 		b0_lowbits |= ((mode >> 1) & 1) << 7;
1586 		b1_lowbits |= ((mode >> 2) & 1) << 7;
1587 
1588 		uint8_t b0_quantval;
1589 		uint8_t b1_quantval;
1590 		uint8_t b0_uquantval;
1591 		uint8_t b1_uquantval;
1592 
1593 		quantize_and_unquantize_retain_top_two_bits(
1594 		    quant_level, static_cast<uint8_t>(b0_lowbits), b0_quantval, b0_uquantval);
1595 		quantize_and_unquantize_retain_top_two_bits(
1596 		    quant_level, static_cast<uint8_t>(b1_lowbits), b1_quantval, b1_uquantval);
1597 
1598 		b0_intval = (b0_intval & ~0x3f) | (b0_uquantval & 0x3f);
1599 		b1_intval = (b1_intval & ~0x3f) | (b1_uquantval & 0x3f);
1600 		b0_fval = static_cast<float>(b0_intval) * mode_rscale;
1601 		b1_fval = static_cast<float>(b1_intval) * mode_rscale;
1602 
1603 		// Recompute D0 and D1, then quantize and unquantize them
1604 		float d0_fval = a_fval - b0_fval - c_fval - color0.lane<1>();
1605 		float d1_fval = a_fval - b1_fval - c_fval - color0.lane<2>();
1606 
1607 		d0_fval = astc::clamp(d0_fval, -65535.0f, 65535.0f);
1608 		d1_fval = astc::clamp(d1_fval, -65535.0f, 65535.0f);
1609 
1610 		int d0_intval = astc::flt2int_rtn(d0_fval * mode_scale);
1611 		int d1_intval = astc::flt2int_rtn(d1_fval * mode_scale);
1612 
1613 		if (abs(d0_intval) >= d_intcutoff || abs(d1_intval) >= d_intcutoff)
1614 		{
1615 			continue;
1616 		}
1617 
1618 		int d0_lowbits = d0_intval & 0x1f;
1619 		int d1_lowbits = d1_intval & 0x1f;
1620 
1621 		int bit2 = 0;
1622 		int bit3 = 0;
1623 		int bit4;
1624 		int bit5;
1625 		switch (mode)
1626 		{
1627 		case 0:
1628 		case 2:
1629 			bit2 = (d0_intval >> 6) & 1;
1630 			break;
1631 		case 1:
1632 		case 4:
1633 			bit2 = (b0_intval >> 7) & 1;
1634 			break;
1635 		case 3:
1636 			bit2 = (a_intval >> 9) & 1;
1637 			break;
1638 		case 5:
1639 			bit2 = (c_intval >> 7) & 1;
1640 			break;
1641 		case 6:
1642 		case 7:
1643 			bit2 = (a_intval >> 11) & 1;
1644 			break;
1645 		}
1646 		switch (mode)
1647 		{
1648 		case 0:
1649 		case 2:
1650 			bit3 = (d1_intval >> 6) & 1;
1651 			break;
1652 		case 1:
1653 		case 4:
1654 			bit3 = (b1_intval >> 7) & 1;
1655 			break;
1656 		case 3:
1657 		case 5:
1658 		case 6:
1659 		case 7:
1660 			bit3 = (c_intval >> 6) & 1;
1661 			break;
1662 		}
1663 
1664 		switch (mode)
1665 		{
1666 		case 4:
1667 		case 6:
1668 			bit4 = (a_intval >> 9) & 1;
1669 			bit5 = (a_intval >> 10) & 1;
1670 			break;
1671 		default:
1672 			bit4 = (d0_intval >> 5) & 1;
1673 			bit5 = (d1_intval >> 5) & 1;
1674 			break;
1675 		}
1676 
1677 		d0_lowbits |= bit2 << 6;
1678 		d1_lowbits |= bit3 << 6;
1679 		d0_lowbits |= bit4 << 5;
1680 		d1_lowbits |= bit5 << 5;
1681 
1682 		d0_lowbits |= (majcomp & 1) << 7;
1683 		d1_lowbits |= ((majcomp >> 1) & 1) << 7;
1684 
1685 		uint8_t d0_quantval;
1686 		uint8_t d1_quantval;
1687 		uint8_t d0_uquantval;
1688 		uint8_t d1_uquantval;
1689 
1690 		quantize_and_unquantize_retain_top_four_bits(
1691 		    quant_level, static_cast<uint8_t>(d0_lowbits), d0_quantval, d0_uquantval);
1692 		quantize_and_unquantize_retain_top_four_bits(
1693 		    quant_level, static_cast<uint8_t>(d1_lowbits), d1_quantval, d1_uquantval);
1694 
1695 		output[0] = static_cast<uint8_t>(a_quantval);
1696 		output[1] = c_quantval;
1697 		output[2] = b0_quantval;
1698 		output[3] = b1_quantval;
1699 		output[4] = d0_quantval;
1700 		output[5] = d1_quantval;
1701 		return;
1702 	}
1703 
1704 	// If neither of the modes fit we will use a flat representation for storing data, using 8 bits
1705 	// for red and green, and 7 bits for blue. This gives color accuracy roughly similar to LDR
1706 	// 4:4:3 which is not at all great but usable. This representation is used if the light color is
1707 	// more than 4x the color value of the dark color.
1708 	float vals[6];
1709 	vals[0] = color0_bak.lane<0>();
1710 	vals[1] = color1_bak.lane<0>();
1711 	vals[2] = color0_bak.lane<1>();
1712 	vals[3] = color1_bak.lane<1>();
1713 	vals[4] = color0_bak.lane<2>();
1714 	vals[5] = color1_bak.lane<2>();
1715 
1716 	for (int i = 0; i < 6; i++)
1717 	{
1718 		vals[i] = astc::clamp(vals[i], 0.0f, 65020.0f);
1719 	}
1720 
1721 	for (int i = 0; i < 4; i++)
1722 	{
1723 		int idx = astc::flt2int_rtn(vals[i] * 1.0f / 256.0f);
1724 		output[i] = quant_color(quant_level, idx);
1725 	}
1726 
1727 	for (int i = 4; i < 6; i++)
1728 	{
1729 		uint8_t dummy;
1730 		int idx = astc::flt2int_rtn(vals[i] * 1.0f / 512.0f) + 128;
1731 		quantize_and_unquantize_retain_top_two_bits(
1732 		    quant_level, static_cast<uint8_t>(idx), output[i], dummy);
1733 	}
1734 
1735 	return;
1736 }
1737 
1738 /**
1739  * @brief Quantize a HDR RGB + LDR A color using direct RGBA encoding.
1740  *
1741  * @param      color0        The input unquantized color0 endpoint.
1742  * @param      color1        The input unquantized color1 endpoint.
1743  * @param[out] output        The output endpoints, returned as packed RGBA+RGBA pairs with mode bits.
1744  * @param      quant_level   The quantization level to use.
1745  */
quantize_hdr_rgb_ldr_alpha(vfloat4 color0,vfloat4 color1,uint8_t output[8],quant_method quant_level)1746 static void quantize_hdr_rgb_ldr_alpha(
1747 	vfloat4 color0,
1748 	vfloat4 color1,
1749 	uint8_t output[8],
1750 	quant_method quant_level
1751 ) {
1752 	float scale = 1.0f / 257.0f;
1753 
1754 	float a0 = astc::clamp255f(color0.lane<3>() * scale);
1755 	float a1 = astc::clamp255f(color1.lane<3>() * scale);
1756 
1757 	output[6] = quant_color(quant_level, astc::flt2int_rtn(a0));
1758 	output[7] = quant_color(quant_level, astc::flt2int_rtn(a1));
1759 
1760 	quantize_hdr_rgb(color0, color1, output, quant_level);
1761 }
1762 
1763 /**
1764  * @brief Quantize a HDR L color using the large range encoding.
1765  *
1766  * @param      color0        The input unquantized color0 endpoint.
1767  * @param      color1        The input unquantized color1 endpoint.
1768  * @param[out] output        The output endpoints, returned as packed (l0, l1).
1769  * @param      quant_level   The quantization level to use.
1770  */
quantize_hdr_luminance_large_range(vfloat4 color0,vfloat4 color1,uint8_t output[2],quant_method quant_level)1771 static void quantize_hdr_luminance_large_range(
1772 	vfloat4 color0,
1773 	vfloat4 color1,
1774 	uint8_t output[2],
1775 	quant_method quant_level
1776 ) {
1777 	float lum0 = hadd_rgb_s(color0) * (1.0f / 3.0f);
1778 	float lum1 = hadd_rgb_s(color1) * (1.0f / 3.0f);
1779 
1780 	if (lum1 < lum0)
1781 	{
1782 		float avg = (lum0 + lum1) * 0.5f;
1783 		lum0 = avg;
1784 		lum1 = avg;
1785 	}
1786 
1787 	int ilum1 = astc::flt2int_rtn(lum1);
1788 	int ilum0 = astc::flt2int_rtn(lum0);
1789 
1790 	// Find the closest encodable point in the upper half of the code-point space
1791 	int upper_v0 = (ilum0 + 128) >> 8;
1792 	int upper_v1 = (ilum1 + 128) >> 8;
1793 
1794 	upper_v0 = astc::clamp(upper_v0, 0, 255);
1795 	upper_v1 = astc::clamp(upper_v1, 0, 255);
1796 
1797 	// Find the closest encodable point in the lower half of the code-point space
1798 	int lower_v0 = (ilum1 + 256) >> 8;
1799 	int lower_v1 = ilum0 >> 8;
1800 
1801 	lower_v0 = astc::clamp(lower_v0, 0, 255);
1802 	lower_v1 = astc::clamp(lower_v1, 0, 255);
1803 
1804 	// Determine the distance between the point in code-point space and the input value
1805 	int upper0_dec = upper_v0 << 8;
1806 	int upper1_dec = upper_v1 << 8;
1807 	int lower0_dec = (lower_v1 << 8) + 128;
1808 	int lower1_dec = (lower_v0 << 8) - 128;
1809 
1810 	int upper0_diff = upper0_dec - ilum0;
1811 	int upper1_diff = upper1_dec - ilum1;
1812 	int lower0_diff = lower0_dec - ilum0;
1813 	int lower1_diff = lower1_dec - ilum1;
1814 
1815 	int upper_error = (upper0_diff * upper0_diff) + (upper1_diff * upper1_diff);
1816 	int lower_error = (lower0_diff * lower0_diff) + (lower1_diff * lower1_diff);
1817 
1818 	int v0, v1;
1819 	if (upper_error < lower_error)
1820 	{
1821 		v0 = upper_v0;
1822 		v1 = upper_v1;
1823 	}
1824 	else
1825 	{
1826 		v0 = lower_v0;
1827 		v1 = lower_v1;
1828 	}
1829 
1830 	// OK; encode
1831 	output[0] = quant_color(quant_level, v0);
1832 	output[1] = quant_color(quant_level, v1);
1833 }
1834 
1835 /**
1836  * @brief Quantize a HDR L color using the small range encoding.
1837  *
1838  * @param      color0        The input unquantized color0 endpoint.
1839  * @param      color1        The input unquantized color1 endpoint.
1840  * @param[out] output        The output endpoints, returned as packed (l0, l1) with mode bits.
1841  * @param      quant_level   The quantization level to use.
1842  *
1843  * @return Returns @c false on failure, @c true on success.
1844  */
try_quantize_hdr_luminance_small_range(vfloat4 color0,vfloat4 color1,uint8_t output[2],quant_method quant_level)1845 static bool try_quantize_hdr_luminance_small_range(
1846 	vfloat4 color0,
1847 	vfloat4 color1,
1848 	uint8_t output[2],
1849 	quant_method quant_level
1850 ) {
1851 	float lum0 = hadd_rgb_s(color0) * (1.0f / 3.0f);
1852 	float lum1 = hadd_rgb_s(color1) * (1.0f / 3.0f);
1853 
1854 	if (lum1 < lum0)
1855 	{
1856 		float avg = (lum0 + lum1) * 0.5f;
1857 		lum0 = avg;
1858 		lum1 = avg;
1859 	}
1860 
1861 	int ilum1 = astc::flt2int_rtn(lum1);
1862 	int ilum0 = astc::flt2int_rtn(lum0);
1863 
1864 	// Difference of more than a factor-of-2 results in immediate failure
1865 	if (ilum1 - ilum0 > 2048)
1866 	{
1867 		return false;
1868 	}
1869 
1870 	int lowval, highval, diffval;
1871 	int v0, v1;
1872 	int v0e, v1e;
1873 	int v0d, v1d;
1874 
1875 	// Try to encode the high-precision submode
1876 	lowval = (ilum0 + 16) >> 5;
1877 	highval = (ilum1 + 16) >> 5;
1878 
1879 	lowval = astc::clamp(lowval, 0, 2047);
1880 	highval = astc::clamp(highval, 0, 2047);
1881 
1882 	v0 = lowval & 0x7F;
1883 	v0e = quant_color(quant_level, v0);
1884 	v0d = unquant_color(quant_level, v0e);
1885 
1886 	if (v0d < 0x80)
1887 	{
1888 		lowval = (lowval & ~0x7F) | v0d;
1889 		diffval = highval - lowval;
1890 		if (diffval >= 0 && diffval <= 15)
1891 		{
1892 			v1 = ((lowval >> 3) & 0xF0) | diffval;
1893 			v1e = quant_color(quant_level, v1);
1894 			v1d = unquant_color(quant_level, v1e);
1895 			if ((v1d & 0xF0) == (v1 & 0xF0))
1896 			{
1897 				output[0] = static_cast<uint8_t>(v0e);
1898 				output[1] = static_cast<uint8_t>(v1e);
1899 				return true;
1900 			}
1901 		}
1902 	}
1903 
1904 	// Try to encode the low-precision submode
1905 	lowval = (ilum0 + 32) >> 6;
1906 	highval = (ilum1 + 32) >> 6;
1907 
1908 	lowval = astc::clamp(lowval, 0, 1023);
1909 	highval = astc::clamp(highval, 0, 1023);
1910 
1911 	v0 = (lowval & 0x7F) | 0x80;
1912 	v0e = quant_color(quant_level, v0);
1913 	v0d = unquant_color(quant_level, v0e);
1914 	if ((v0d & 0x80) == 0)
1915 	{
1916 		return false;
1917 	}
1918 
1919 	lowval = (lowval & ~0x7F) | (v0d & 0x7F);
1920 	diffval = highval - lowval;
1921 	if (diffval < 0 || diffval > 31)
1922 	{
1923 		return false;
1924 	}
1925 
1926 	v1 = ((lowval >> 2) & 0xE0) | diffval;
1927 	v1e = quant_color(quant_level, v1);
1928 	v1d = unquant_color(quant_level, v1e);
1929 	if ((v1d & 0xE0) != (v1 & 0xE0))
1930 	{
1931 		return false;
1932 	}
1933 
1934 	output[0] = static_cast<uint8_t>(v0e);
1935 	output[1] = static_cast<uint8_t>(v1e);
1936 	return true;
1937 }
1938 
1939 /**
1940  * @brief Quantize a HDR A color using either delta or direct RGBA encoding.
1941  *
1942  * @param      alpha0        The input unquantized color0 endpoint.
1943  * @param      alpha1        The input unquantized color1 endpoint.
1944  * @param[out] output        The output endpoints, returned as packed RGBA+RGBA pairs with mode bits.
1945  * @param      quant_level   The quantization level to use.
1946  */
quantize_hdr_alpha(float alpha0,float alpha1,uint8_t output[2],quant_method quant_level)1947 static void quantize_hdr_alpha(
1948 	float alpha0,
1949 	float alpha1,
1950 	uint8_t output[2],
1951 	quant_method quant_level
1952 ) {
1953 	alpha0 = astc::clamp(alpha0, 0.0f, 65280.0f);
1954 	alpha1 = astc::clamp(alpha1, 0.0f, 65280.0f);
1955 
1956 	int ialpha0 = astc::flt2int_rtn(alpha0);
1957 	int ialpha1 = astc::flt2int_rtn(alpha1);
1958 
1959 	int val0, val1, diffval;
1960 	int v6, v7;
1961 	int v6e, v7e;
1962 	int v6d, v7d;
1963 
1964 	// Try to encode one of the delta submodes, in decreasing-precision order
1965 	for (int i = 2; i >= 0; i--)
1966 	{
1967 		val0 = (ialpha0 + (128 >> i)) >> (8 - i);
1968 		val1 = (ialpha1 + (128 >> i)) >> (8 - i);
1969 
1970 		v6 = (val0 & 0x7F) | ((i & 1) << 7);
1971 		v6e = quant_color(quant_level, v6);
1972 		v6d = unquant_color(quant_level, v6e);
1973 
1974 		if ((v6 ^ v6d) & 0x80)
1975 		{
1976 			continue;
1977 		}
1978 
1979 		val0 = (val0 & ~0x7f) | (v6d & 0x7f);
1980 		diffval = val1 - val0;
1981 		int cutoff = 32 >> i;
1982 		int mask = 2 * cutoff - 1;
1983 
1984 		if (diffval < -cutoff || diffval >= cutoff)
1985 		{
1986 			continue;
1987 		}
1988 
1989 		v7 = ((i & 2) << 6) | ((val0 >> 7) << (6 - i)) | (diffval & mask);
1990 		v7e = quant_color(quant_level, v7);
1991 		v7d = unquant_color(quant_level, v7e);
1992 
1993 		static const int testbits[3] { 0xE0, 0xF0, 0xF8 };
1994 
1995 		if ((v7 ^ v7d) & testbits[i])
1996 		{
1997 			continue;
1998 		}
1999 
2000 		output[0] = static_cast<uint8_t>(v6e);
2001 		output[1] = static_cast<uint8_t>(v7e);
2002 		return;
2003 	}
2004 
2005 	// Could not encode any of the delta modes; instead encode a flat value
2006 	val0 = (ialpha0 + 256) >> 9;
2007 	val1 = (ialpha1 + 256) >> 9;
2008 	v6 = val0 | 0x80;
2009 	v7 = val1 | 0x80;
2010 
2011 	output[0] = quant_color(quant_level, v6);
2012 	output[1] = quant_color(quant_level, v7);
2013 
2014 	return;
2015 }
2016 
2017 /**
2018  * @brief Quantize a HDR RGBA color using either delta or direct RGBA encoding.
2019  *
2020  * @param      color0        The input unquantized color0 endpoint.
2021  * @param      color1        The input unquantized color1 endpoint.
2022  * @param[out] output        The output endpoints, returned as packed RGBA+RGBA pairs with mode bits.
2023  * @param      quant_level   The quantization level to use.
2024  */
quantize_hdr_rgb_alpha(vfloat4 color0,vfloat4 color1,uint8_t output[8],quant_method quant_level)2025 static void quantize_hdr_rgb_alpha(
2026 	vfloat4 color0,
2027 	vfloat4 color1,
2028 	uint8_t output[8],
2029 	quant_method quant_level
2030 ) {
2031 	quantize_hdr_rgb(color0, color1, output, quant_level);
2032 	quantize_hdr_alpha(color0.lane<3>(), color1.lane<3>(), output + 6, quant_level);
2033 }
2034 
2035 /* See header for documentation. */
pack_color_endpoints(vfloat4 color0,vfloat4 color1,vfloat4 rgbs_color,vfloat4 rgbo_color,int format,uint8_t * output,quant_method quant_level)2036 uint8_t pack_color_endpoints(
2037 	vfloat4 color0,
2038 	vfloat4 color1,
2039 	vfloat4 rgbs_color,
2040 	vfloat4 rgbo_color,
2041 	int format,
2042 	uint8_t* output,
2043 	quant_method quant_level
2044 ) {
2045 	assert(QUANT_6 <= quant_level && quant_level <= QUANT_256);
2046 
2047 	// We do not support negative colors
2048 	color0 = max(color0, 0.0f);
2049 	color1 = max(color1, 0.0f);
2050 
2051 	uint8_t retval = 0;
2052 
2053 	switch (format)
2054 	{
2055 	case FMT_RGB:
2056 		if (quant_level <= 18)
2057 		{
2058 			if (try_quantize_rgb_delta_blue_contract(color0, color1, output, quant_level))
2059 			{
2060 				retval = FMT_RGB_DELTA;
2061 				break;
2062 			}
2063 			if (try_quantize_rgb_delta(color0, color1, output, quant_level))
2064 			{
2065 				retval = FMT_RGB_DELTA;
2066 				break;
2067 			}
2068 		}
2069 		if (try_quantize_rgb_blue_contract(color0, color1, output, quant_level))
2070 		{
2071 			retval = FMT_RGB;
2072 			break;
2073 		}
2074 		quantize_rgb(color0, color1, output, quant_level);
2075 		retval = FMT_RGB;
2076 		break;
2077 
2078 	case FMT_RGBA:
2079 		if (quant_level <= 18)
2080 		{
2081 			if (try_quantize_rgba_delta_blue_contract(color0, color1, output, quant_level))
2082 			{
2083 				retval = FMT_RGBA_DELTA;
2084 				break;
2085 			}
2086 			if (try_quantize_rgba_delta(color0, color1, output, quant_level))
2087 			{
2088 				retval = FMT_RGBA_DELTA;
2089 				break;
2090 			}
2091 		}
2092 		if (try_quantize_rgba_blue_contract(color0, color1, output, quant_level))
2093 		{
2094 			retval = FMT_RGBA;
2095 			break;
2096 		}
2097 		quantize_rgba(color0, color1, output, quant_level);
2098 		retval = FMT_RGBA;
2099 		break;
2100 
2101 	case FMT_RGB_SCALE:
2102 		quantize_rgbs(rgbs_color, output, quant_level);
2103 		retval = FMT_RGB_SCALE;
2104 		break;
2105 
2106 	case FMT_HDR_RGB_SCALE:
2107 		quantize_hdr_rgbo(rgbo_color, output, quant_level);
2108 		retval = FMT_HDR_RGB_SCALE;
2109 		break;
2110 
2111 	case FMT_HDR_RGB:
2112 		quantize_hdr_rgb(color0, color1, output, quant_level);
2113 		retval = FMT_HDR_RGB;
2114 		break;
2115 
2116 	case FMT_RGB_SCALE_ALPHA:
2117 		quantize_rgbs_alpha(color0, color1, rgbs_color, output, quant_level);
2118 		retval = FMT_RGB_SCALE_ALPHA;
2119 		break;
2120 
2121 	case FMT_HDR_LUMINANCE_SMALL_RANGE:
2122 	case FMT_HDR_LUMINANCE_LARGE_RANGE:
2123 		if (try_quantize_hdr_luminance_small_range(color0, color1, output, quant_level))
2124 		{
2125 			retval = FMT_HDR_LUMINANCE_SMALL_RANGE;
2126 			break;
2127 		}
2128 		quantize_hdr_luminance_large_range(color0, color1, output, quant_level);
2129 		retval = FMT_HDR_LUMINANCE_LARGE_RANGE;
2130 		break;
2131 
2132 	case FMT_LUMINANCE:
2133 		quantize_luminance(color0, color1, output, quant_level);
2134 		retval = FMT_LUMINANCE;
2135 		break;
2136 
2137 	case FMT_LUMINANCE_ALPHA:
2138 		if (quant_level <= 18)
2139 		{
2140 			if (try_quantize_luminance_alpha_delta(color0, color1, output, quant_level))
2141 			{
2142 				retval = FMT_LUMINANCE_ALPHA_DELTA;
2143 				break;
2144 			}
2145 		}
2146 		quantize_luminance_alpha(color0, color1, output, quant_level);
2147 		retval = FMT_LUMINANCE_ALPHA;
2148 		break;
2149 
2150 	case FMT_HDR_RGB_LDR_ALPHA:
2151 		quantize_hdr_rgb_ldr_alpha(color0, color1, output, quant_level);
2152 		retval = FMT_HDR_RGB_LDR_ALPHA;
2153 		break;
2154 
2155 	case FMT_HDR_RGBA:
2156 		quantize_hdr_rgb_alpha(color0, color1, output, quant_level);
2157 		retval = FMT_HDR_RGBA;
2158 		break;
2159 	}
2160 
2161 	return retval;
2162 }
2163 
2164 #endif
2165