• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: Apache-2.0
2 // ----------------------------------------------------------------------------
3 // Copyright 2020-2024 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 The core astcenc codec library interface.
20  *
21  * This interface is the entry point to the core astcenc codec. It aims to be easy to use for
22  * non-experts, but also to allow experts to have fine control over the compressor heuristics if
23  * needed. The core codec only handles compression and decompression, transferring all inputs and
24  * outputs via memory buffers. To catch obvious input/output buffer sizing issues, which can cause
25  * security and stability problems, all transfer buffers are explicitly sized.
26  *
27  * While the aim is that we keep this interface mostly stable, it should be viewed as a mutable
28  * interface tied to a specific source version. We are not trying to maintain backwards
29  * compatibility across codec versions.
30  *
31  * The API state management is based around an explicit context object, which is the context for all
32  * allocated memory resources needed to compress and decompress a single image. A context can be
33  * used to sequentially compress multiple images using the same configuration, allowing setup
34  * overheads to be amortized over multiple images, which is particularly important when images are
35  * small.
36  *
37  * Multi-threading can be used two ways.
38  *
39  *     * An application wishing to process multiple images in parallel can allocate multiple
40  *       contexts and assign each context to a thread.
41  *     * An application wishing to process a single image in using multiple threads can configure
42  *       contexts for multi-threaded use, and invoke astcenc_compress/decompress() once per thread
43  *       for faster processing. The caller is responsible for creating the worker threads, and
44  *       synchronizing between images.
45  *
46  * Extended instruction set support
47  * ================================
48  *
49  * This library supports use of extended instruction sets, such as SSE4.1 and AVX2. These are
50  * enabled at compile time when building the library. There is no runtime checking in the core
51  * library that the instruction sets used are actually available. Checking compatibility is the
52  * responsibility of the calling code.
53  *
54  * Threading
55  * =========
56  *
57  * In pseudo-code, the usage for manual user threading looks like this:
58  *
59  *     // Configure the compressor run
60  *     astcenc_config my_config;
61  *     astcenc_config_init(..., &my_config);
62  *
63  *     // Power users can tweak <my_config> settings here ...
64  *
65  *     // Allocate working state given config and thread_count
66  *     astcenc_context* my_context;
67  *     astcenc_context_alloc(&my_config, thread_count, &my_context);
68  *
69  *     // Compress each image using these config settings
70  *     foreach image:
71  *         // For each thread in the thread pool
72  *         for i in range(0, thread_count):
73  *             astcenc_compress_image(my_context, &my_input, my_output, i);
74  *
75  *         astcenc_compress_reset(my_context);
76  *
77  *     // Clean up
78  *     astcenc_context_free(my_context);
79  *
80  * Images
81  * ======
82  *
83  * The codec supports compressing single images, which can be either 2D images or volumetric 3D
84  * images. Calling code is responsible for any handling of aggregate types, such as mipmap chains,
85  * texture arrays, or sliced 3D textures.
86  *
87  * Images are passed in as an astcenc_image structure. Inputs can be either 8-bit unorm, 16-bit
88  * half-float, or 32-bit float, as indicated by the data_type field.
89  *
90  * Images can be any dimension; there is no requirement to be a multiple of the ASTC block size.
91  *
92  * Data is always passed in as 4 color components, and accessed as an array of 2D image slices. Data
93  * within an image slice is always tightly packed without padding. Addressing looks like this:
94  *
95  *     data[z_coord][y_coord * x_dim * 4 + x_coord * 4    ]   // Red
96  *     data[z_coord][y_coord * x_dim * 4 + x_coord * 4 + 1]   // Green
97  *     data[z_coord][y_coord * x_dim * 4 + x_coord * 4 + 2]   // Blue
98  *     data[z_coord][y_coord * x_dim * 4 + x_coord * 4 + 3]   // Alpha
99  *
100  * Common compressor usage
101  * =======================
102  *
103  * One of the most important things for coding image quality is to align the input data component
104  * count with the ASTC color endpoint mode. This avoids wasting bits encoding components you don't
105  * actually need in the endpoint colors.
106  *
107  *         | Input data   | Encoding swizzle | Sampling swizzle |
108  *         | ------------ | ---------------- | ---------------- |
109  *         | 1 component  | RRR1             | .[rgb]           |
110  *         | 2 components | RRRG             | .[rgb]a          |
111  *         | 3 components | RGB1             | .rgb             |
112  *         | 4 components | RGBA             | .rgba            |
113  *
114  * The 1 and 2 component modes recommend sampling from "g" to recover the luminance value as this
115  * provide best compatibility with other texture formats where the green component may be stored at
116  * higher precision than the others, such as RGB565. For ASTC any of the RGB components can be used;
117  * the luminance endpoint component will be returned for all three.
118  *
119  * When using the normal map compression mode ASTC will store normals as a two component X+Y map.
120  * Input images must contain unit-length normalized and should be passed in using a two component
121  * swizzle. The astcenc command line tool defaults to an RRRG swizzle, but some developers prefer
122  * to use GGGR for compatability with BC5n which will work just as well. The Z component can be
123  * recovered programmatically in shader code, using knowledge that the vector is unit length and
124  * that Z must be positive for a tangent-space normal map.
125  *
126  * Decompress-only usage
127  * =====================
128  *
129  * For some use cases it is useful to have a cut-down context and/or library which supports
130  * decompression but not compression.
131  *
132  * A context can be made decompress-only using the ASTCENC_FLG_DECOMPRESS_ONLY flag when the context
133  * is allocated. These contexts have lower dynamic memory footprint than a full context.
134  *
135  * The entire library can be made decompress-only by building the files with the define
136  * ASTCENC_DECOMPRESS_ONLY set. In this build the context will be smaller, and the library will
137  * exclude the functionality which is only needed for compression. This reduces the binary size by
138  * ~180KB. For these builds contexts must be created with the ASTCENC_FLG_DECOMPRESS_ONLY flag.
139  *
140  * Note that context structures returned by a library built as decompress-only are incompatible with
141  * a library built with compression included, and visa versa, as they have different sizes and
142  * memory layout.
143  *
144  * Self-decompress-only usage
145  * ==========================
146  *
147  * ASTC is a complex format with a large search space. The parts of this search space that are
148  * searched is determined by heuristics that are, in part, tied to the quality level used when
149  * creating the context.
150  *
151  * A normal context is capable of decompressing any ASTC texture, including those generated by other
152  * compressors with unknown heuristics. This is the most flexible implementation, but forces the
153  * data tables used by the codec to include entries that are not needed during compression. This
154  * can slow down context creation by a significant amount, especially for the faster compression
155  * modes where few data table entries are actually used. To optimize this use case the context can
156  * be created with the ASTCENC_FLG_SELF_DECOMPRESS_ONLY flag. This tells the compressor that it will
157  * only be asked to decompress images that it compressed itself, allowing the data tables to
158  * exclude entries that are not needed by the current compression configuration. This reduces the
159  * size of the context data tables in memory and improves context creation performance. Note that,
160  * as of the 3.6 release, this flag no longer affects compression performance.
161  *
162  * Using this flag while attempting to decompress an valid image which was created by another
163  * compressor, or even another astcenc compressor version or configuration, may result in blocks
164  * returning as solid magenta or NaN value error blocks.
165  */
166 
167 #ifndef ASTCENC_INCLUDED
168 #define ASTCENC_INCLUDED
169 
170 #include <cstddef>
171 #include <cstdint>
172 #if defined(__aarch64__)
173 	#define ASTCENC_NEON 1
174 #else
175 	#define ASTCENC_NEON 0
176 #endif
177 
178 enum QualityProfile {
179 	HIGH_QUALITY_PROFILE = 0, // default profile
180 	HIGH_SPEED_PROFILE,
181 	CUSTOMIZED_PROFILE,
182 	HIGH_SPEED_PROFILE_HIGHBITS
183 };
184 
185 static const int HIGH_SPEED_PROFILE_BLOCK_MODE = 67; // keep openSource type, example
186 static const int BYTE_MASK = 0xFF;
187 
188 #define QUALITY_CONTROL (1)
189 #if QUALITY_CONTROL
190 enum ComponentRGBA {
191 	R_COM = 0,
192 	G_COM,
193 	B_COM,
194 	A_COM,
195 	RGBA_COM
196 };
197 #endif
198 
199 #if defined(ASTCENC_DYNAMIC_LIBRARY)
200 	#if defined(_MSC_VER)
201 		#define ASTCENC_PUBLIC extern "C" __declspec(dllexport)
202 	#else
203 		#define ASTCENC_PUBLIC extern "C" __attribute__ ((visibility ("default")))
204 	#endif
205 #else
206 	#define ASTCENC_PUBLIC
207 #endif
208 
209 /* ============================================================================
210     Data declarations
211 ============================================================================ */
212 
213 /**
214  * @brief An opaque structure; see astcenc_internal.h for definition.
215  */
216 struct astcenc_context;
217 
218 /**
219  * @brief A codec API error code.
220  */
221 enum astcenc_error {
222 	/** @brief The call was successful. */
223 	ASTCENC_SUCCESS = 0,
224 	/** @brief The call failed due to low memory, or undersized I/O buffers. */
225 	ASTCENC_ERR_OUT_OF_MEM,
226 	/** @brief The call failed due to the build using fast math. */
227 	ASTCENC_ERR_BAD_CPU_FLOAT,
228 	/** @brief The call failed due to an out-of-spec parameter. */
229 	ASTCENC_ERR_BAD_PARAM,
230 	/** @brief The call failed due to an out-of-spec block size. */
231 	ASTCENC_ERR_BAD_BLOCK_SIZE,
232 	/** @brief The call failed due to an out-of-spec color profile. */
233 	ASTCENC_ERR_BAD_PROFILE,
234 	/** @brief The call failed due to an out-of-spec quality value. */
235 	ASTCENC_ERR_BAD_QUALITY,
236 	/** @brief The call failed due to an out-of-spec component swizzle. */
237 	ASTCENC_ERR_BAD_SWIZZLE,
238 	/** @brief The call failed due to an out-of-spec flag set. */
239 	ASTCENC_ERR_BAD_FLAGS,
240 	/** @brief The call failed due to the context not supporting the operation. */
241 	ASTCENC_ERR_BAD_CONTEXT,
242 	/** @brief The call failed due to unimplemented functionality. */
243 	ASTCENC_ERR_NOT_IMPLEMENTED,
244 	/** @brief The call failed due to an out-of-spec decode mode flag set. */
245 	ASTCENC_ERR_BAD_DECODE_MODE,
246 #if defined(ASTCENC_DIAGNOSTICS)
247 	/** @brief The call failed due to an issue with diagnostic tracing. */
248 	ASTCENC_ERR_DTRACE_FAILURE,
249 #endif
250 #if QUALITY_CONTROL
251 	ASTCENC_ERR_BAD_QUALITY_CHECK,
252 #endif
253 #ifdef ASTC_CUSTOMIZED_ENABLE
254 	ASTCENC_ERR_DLOPEN_FAILED
255 #endif
256 };
257 
258 /**
259  * @brief A codec color profile.
260  */
261 enum astcenc_profile {
262 	/** @brief The LDR sRGB color profile. */
263 	ASTCENC_PRF_LDR_SRGB = 0,
264 	/** @brief The LDR linear color profile. */
265 	ASTCENC_PRF_LDR,
266 	/** @brief The HDR RGB with LDR alpha color profile. */
267 	ASTCENC_PRF_HDR_RGB_LDR_A,
268 	/** @brief The HDR RGBA color profile. */
269 	ASTCENC_PRF_HDR
270 };
271 
272 /** @brief The fastest, lowest quality, search preset. */
273 static const float ASTCENC_PRE_FASTEST = 0.0f;
274 
275 /** @brief The fast search preset. */
276 static const float ASTCENC_PRE_FAST = 10.0f;
277 
278 /** @brief The medium quality search preset. */
279 static const float ASTCENC_PRE_MEDIUM = 60.0f;
280 
281 /** @brief The thorough quality search preset. */
282 static const float ASTCENC_PRE_THOROUGH = 98.0f;
283 
284 /** @brief The thorough quality search preset. */
285 static const float ASTCENC_PRE_VERYTHOROUGH = 99.0f;
286 
287 /** @brief The exhaustive, highest quality, search preset. */
288 static const float ASTCENC_PRE_EXHAUSTIVE = 100.0f;
289 
290 /**
291  * @brief A codec component swizzle selector.
292  */
293 enum astcenc_swz
294 {
295 	/** @brief Select the red component. */
296 	ASTCENC_SWZ_R = 0,
297 	/** @brief Select the green component. */
298 	ASTCENC_SWZ_G = 1,
299 	/** @brief Select the blue component. */
300 	ASTCENC_SWZ_B = 2,
301 	/** @brief Select the alpha component. */
302 	ASTCENC_SWZ_A = 3,
303 	/** @brief Use a constant zero component. */
304 	ASTCENC_SWZ_0 = 4,
305 	/** @brief Use a constant one component. */
306 	ASTCENC_SWZ_1 = 5,
307 	/** @brief Use a reconstructed normal vector Z component. */
308 	ASTCENC_SWZ_Z = 6
309 };
310 
311 /**
312  * @brief A texel component swizzle.
313  */
314 struct astcenc_swizzle
315 {
316 	/** @brief The red component selector. */
317 	astcenc_swz r;
318 	/** @brief The green component selector. */
319 	astcenc_swz g;
320 	/** @brief The blue component selector. */
321 	astcenc_swz b;
322 	/** @brief The alpha component selector. */
323 	astcenc_swz a;
324 };
325 
326 /**
327  * @brief A texel component data format.
328  */
329 enum astcenc_type
330 {
331 	/** @brief Unorm 8-bit data per component. */
332 	ASTCENC_TYPE_U8 = 0,
333 	/** @brief 16-bit float per component. */
334 	ASTCENC_TYPE_F16 = 1,
335 	/** @brief 32-bit float per component. */
336 	ASTCENC_TYPE_F32 = 2,
337 	/** @brief 32-bit RGBA 1010102 data. */
338 	ASTCENC_TYPE_RGBA1010102 = 3
339 };
340 
341 /**
342  * @brief Function pointer type for compression progress reporting callback.
343  */
344 extern "C" typedef void (*astcenc_progress_callback)(float);
345 
346 /**
347  * @brief Enable normal map compression.
348  *
349  * Input data will be treated a two component normal map, storing X and Y, and the codec will
350  * optimize for angular error rather than simple linear PSNR. In this mode the input swizzle should
351  * be e.g. rrrg (the default ordering for ASTC normals on the command line) or gggr (the ordering
352  * used by BC5n).
353  */
354 static const unsigned int ASTCENC_FLG_MAP_NORMAL          = 1 << 0;
355 
356 /**
357  * @brief Enable compression heuristics that assume use of decode_unorm8 decode mode.
358  *
359  * The decode_unorm8 decode mode rounds differently to the decode_fp16 decode mode, so enabling this
360  * flag during compression will allow the compressor to use the correct rounding when selecting
361  * encodings. This will improve the compressed image quality if your application is using the
362  * decode_unorm8 decode mode, but will reduce image quality if using decode_fp16.
363  *
364  * Note that LDR_SRGB images will always use decode_unorm8 for the RGB channels, irrespective of
365  * this setting.
366  */
367 static const unsigned int ASTCENC_FLG_USE_DECODE_UNORM8        = 1 << 1;
368 
369 /**
370  * @brief Enable alpha weighting.
371  *
372  * The input alpha value is used for transparency, so errors in the RGB components are weighted by
373  * the transparency level. This allows the codec to more accurately encode the alpha value in areas
374  * where the color value is less significant.
375  */
376 static const unsigned int ASTCENC_FLG_USE_ALPHA_WEIGHT     = 1 << 2;
377 
378 /**
379  * @brief Enable perceptual error metrics.
380  *
381  * This mode enables perceptual compression mode, which will optimize for perceptual error rather
382  * than best PSNR. Only some input modes support perceptual error metrics.
383  */
384 static const unsigned int ASTCENC_FLG_USE_PERCEPTUAL       = 1 << 3;
385 
386 /**
387  * @brief Create a decompression-only context.
388  *
389  * This mode disables support for compression. This enables context allocation to skip some
390  * transient buffer allocation, resulting in lower memory usage.
391  */
392 static const unsigned int ASTCENC_FLG_DECOMPRESS_ONLY      = 1 << 4;
393 
394 /**
395  * @brief Create a self-decompression context.
396  *
397  * This mode configures the compressor so that it is only guaranteed to be able to decompress images
398  * that were actually created using the current context. This is the common case for compression use
399  * cases, and setting this flag enables additional optimizations, but does mean that the context
400  * cannot reliably decompress arbitrary ASTC images.
401  */
402 static const unsigned int ASTCENC_FLG_SELF_DECOMPRESS_ONLY = 1 << 5;
403 
404 /**
405  * @brief Enable RGBM map compression.
406  *
407  * Input data will be treated as HDR data that has been stored in an LDR RGBM-encoded wrapper
408  * format. Data must be preprocessed by the user to be in LDR RGBM format before calling the
409  * compression function, this flag is only used to control the use of RGBM-specific heuristics and
410  * error metrics.
411  *
412  * IMPORTANT: The ASTC format is prone to bad failure modes with unconstrained RGBM data; very small
413  * M values can round to zero due to quantization and result in black or white pixels. It is highly
414  * recommended that the minimum value of M used in the encoding is kept above a lower threshold (try
415  * 16 or 32). Applying this threshold reduces the number of very dark colors that can be
416  * represented, but is still higher precision than 8-bit LDR.
417  *
418  * When this flag is set the value of @c rgbm_m_scale in the context must be set to the RGBM scale
419  * factor used during reconstruction. This defaults to 5 when in RGBM mode.
420  *
421  * It is recommended that the value of @c cw_a_weight is set to twice the value of the multiplier
422  * scale, ensuring that the M value is accurately encoded. This defaults to 10 when in RGBM mode,
423  * matching the default scale factor.
424  */
425 static const unsigned int ASTCENC_FLG_MAP_RGBM             = 1 << 6;
426 
427 /**
428  * @brief The bit mask of all valid flags.
429  */
430 static const unsigned int ASTCENC_ALL_FLAGS =
431                               ASTCENC_FLG_MAP_NORMAL |
432                               ASTCENC_FLG_MAP_RGBM |
433                               ASTCENC_FLG_USE_ALPHA_WEIGHT |
434                               ASTCENC_FLG_USE_PERCEPTUAL |
435                               ASTCENC_FLG_USE_DECODE_UNORM8 |
436                               ASTCENC_FLG_DECOMPRESS_ONLY |
437                               ASTCENC_FLG_SELF_DECOMPRESS_ONLY;
438 
439 /**
440  * @brief The config structure.
441  *
442  * This structure will initially be populated by a call to astcenc_config_init, but power users may
443  * modify it before calling astcenc_context_alloc. See astcenccli_toplevel_help.cpp for full user
444  * documentation of the power-user settings.
445  *
446  * Note for any settings which are associated with a specific color component, the value in the
447  * config applies to the component that exists after any compression data swizzle is applied.
448  */
449 struct astcenc_config
450 {
451 	/** @brief The color profile. */
452 	astcenc_profile profile;
453 
454 	/** @brief The set of set flags. */
455 	unsigned int flags;
456 
457 	/** @brief The ASTC block size X dimension. */
458 	unsigned int block_x;
459 
460 	/** @brief The ASTC block size Y dimension. */
461 	unsigned int block_y;
462 
463 	/** @brief The ASTC block size Z dimension. */
464 	unsigned int block_z;
465 
466 	/** @brief The red component weight scale for error weighting (-cw). */
467 	float cw_r_weight;
468 
469 	/** @brief The green component weight scale for error weighting (-cw). */
470 	float cw_g_weight;
471 
472 	/** @brief The blue component weight scale for error weighting (-cw). */
473 	float cw_b_weight;
474 
475 	/** @brief The alpha component weight scale for error weighting (-cw). */
476 	float cw_a_weight;
477 
478 	/**
479 	 * @brief The radius for any alpha-weight scaling (-a).
480 	 *
481 	 * It is recommended that this is set to 1 when using FLG_USE_ALPHA_WEIGHT on a texture that
482 	 * will be sampled using linear texture filtering to minimize color bleed out of transparent
483 	 * texels that are adjacent to non-transparent texels.
484 	 */
485 	unsigned int a_scale_radius;
486 
487 	/** @brief The RGBM scale factor for the shared multiplier (-rgbm). */
488 	float rgbm_m_scale;
489 
490 	/**
491 	 * @brief The maximum number of partitions searched (-partitioncountlimit).
492 	 *
493 	 * Valid values are between 1 and 4.
494 	 */
495 	unsigned int tune_partition_count_limit;
496 
497 	/**
498 	 * @brief The maximum number of partitions searched (-2partitionindexlimit).
499 	 *
500 	 * Valid values are between 1 and 1024.
501 	 */
502 	unsigned int tune_2partition_index_limit;
503 
504 	/**
505 	 * @brief The maximum number of partitions searched (-3partitionindexlimit).
506 	 *
507 	 * Valid values are between 1 and 1024.
508 	 */
509 	unsigned int tune_3partition_index_limit;
510 
511 	/**
512 	 * @brief The maximum number of partitions searched (-4partitionindexlimit).
513 	 *
514 	 * Valid values are between 1 and 1024.
515 	 */
516 	unsigned int tune_4partition_index_limit;
517 
518 	/**
519 	 * @brief The maximum centile for block modes searched (-blockmodelimit).
520 	 *
521 	 * Valid values are between 1 and 100.
522 	 */
523 	unsigned int tune_block_mode_limit;
524 
525 	/**
526 	 * @brief The maximum iterative refinements applied (-refinementlimit).
527 	 *
528 	 * Valid values are between 1 and N; there is no technical upper limit
529 	 * but little benefit is expected after N=4.
530 	 */
531 	unsigned int tune_refinement_limit;
532 
533 	/**
534 	 * @brief The number of trial candidates per mode search (-candidatelimit).
535 	 *
536 	 * Valid values are between 1 and TUNE_MAX_TRIAL_CANDIDATES.
537 	 */
538 	unsigned int tune_candidate_limit;
539 
540 	/**
541 	 * @brief The number of trial partitionings per search (-2partitioncandidatelimit).
542 	 *
543 	 * Valid values are between 1 and TUNE_MAX_PARTITIONING_CANDIDATES.
544 	 */
545 	unsigned int tune_2partitioning_candidate_limit;
546 
547 	/**
548 	 * @brief The number of trial partitionings per search (-3partitioncandidatelimit).
549 	 *
550 	 * Valid values are between 1 and TUNE_MAX_PARTITIONING_CANDIDATES.
551 	 */
552 	unsigned int tune_3partitioning_candidate_limit;
553 
554 	/**
555 	 * @brief The number of trial partitionings per search (-4partitioncandidatelimit).
556 	 *
557 	 * Valid values are between 1 and TUNE_MAX_PARTITIONING_CANDIDATES.
558 	 */
559 	unsigned int tune_4partitioning_candidate_limit;
560 
561 	/**
562 	 * @brief The dB threshold for stopping block search (-dblimit).
563 	 *
564 	 * This option is ineffective for HDR textures.
565 	 */
566 	float tune_db_limit;
567 
568 	/**
569 	 * @brief The amount of MSE overshoot needed to early-out trials.
570 	 *
571 	 * The first early-out is for 1 partition, 1 plane trials, where we try a minimal encode using
572 	 * the high probability block modes. This can short-cut compression for simple blocks.
573 	 *
574 	 * The second early-out is for refinement trials, where we can exit refinement once quality is
575 	 * reached.
576 	 */
577 	float tune_mse_overshoot;
578 
579 	/**
580 	 * @brief The threshold for skipping 3.1/4.1 trials (-2partitionlimitfactor).
581 	 *
582 	 * This option is further scaled for normal maps, so it skips less often.
583 	 */
584 	float tune_2partition_early_out_limit_factor;
585 
586 	/**
587 	 * @brief The threshold for skipping 4.1 trials (-3partitionlimitfactor).
588 	 *
589 	 * This option is further scaled for normal maps, so it skips less often.
590 	 */
591 	float tune_3partition_early_out_limit_factor;
592 
593 	/**
594 	 * @brief The threshold for skipping two weight planes (-2planelimitcorrelation).
595 	 *
596 	 * This option is ineffective for normal maps.
597 	 */
598 	float tune_2plane_early_out_limit_correlation;
599 
600 	/**
601 	 * @brief The config enable for the mode0 fast-path search.
602 	 *
603 	 * If this is set to TUNE_MIN_TEXELS_MODE0 or higher then the early-out fast mode0
604 	 * search is enabled. This option is ineffective for 3D block sizes.
605 	 */
606 	float tune_search_mode0_enable;
607 
608 	/**
609 	 * @brief The progress callback, can be @c nullptr.
610 	 *
611 	 * If this is specified the codec will peridocially report progress for
612 	 * compression as a percentage between 0 and 100. The callback is called from one
613 	 * of the compressor threads, so doing significant work in the callback will
614 	 * reduce compression performance.
615 	 */
616 	astcenc_progress_callback progress_callback;
617 
618 #if defined(ASTCENC_DIAGNOSTICS)
619 	/**
620 	 * @brief The path to save the diagnostic trace data to.
621 	 *
622 	 * This option is not part of the public API, and requires special builds
623 	 * of the library.
624 	 */
625 	const char* trace_file_path;
626 #endif
627 	QualityProfile privateProfile;
628 };
629 
630 /**
631  * @brief An uncompressed 2D or 3D image.
632  *
633  * 3D image are passed in as an array of 2D slices. Each slice has identical
634  * size and color format.
635  */
636 struct astcenc_image
637 {
638 	/** @brief The stride dimension of the image, in texels. */
639 	unsigned int dim_stride;
640 
641 	/** @brief The X dimension of the image, in texels. */
642 	unsigned int dim_x;
643 
644 	/** @brief The Y dimension of the image, in texels. */
645 	unsigned int dim_y;
646 
647 	/** @brief The Z dimension of the image, in texels. */
648 	unsigned int dim_z;
649 
650 	/** @brief The data type per component. */
651 	astcenc_type data_type;
652 
653 	/** @brief The array of 2D slices, of length @c dim_z. */
654 	void** data;
655 };
656 
657 /**
658  * @brief A block encoding metadata query result.
659  *
660  * If the block is an error block or a constant color block or an error block all fields other than
661  * the profile, block dimensions, and error/constant indicator will be zero.
662  */
663 struct astcenc_block_info
664 {
665 	/** @brief The block encoding color profile. */
666 	astcenc_profile profile;
667 
668 	/** @brief The number of texels in the X dimension. */
669 	unsigned int block_x;
670 
671 	/** @brief The number of texels in the Y dimension. */
672 	unsigned int block_y;
673 
674 	/** @brief The number of texel in the Z dimension. */
675 	unsigned int block_z;
676 
677 	/** @brief The number of texels in the block. */
678 	unsigned int texel_count;
679 
680 	/** @brief True if this block is an error block. */
681 	bool is_error_block;
682 
683 	/** @brief True if this block is a constant color block. */
684 	bool is_constant_block;
685 
686 	/** @brief True if this block is an HDR block. */
687 	bool is_hdr_block;
688 
689 	/** @brief True if this block uses two weight planes. */
690 	bool is_dual_plane_block;
691 
692 	/** @brief The number of partitions if not constant color. */
693 	unsigned int partition_count;
694 
695 	/** @brief The partition index if 2 - 4 partitions used. */
696 	unsigned int partition_index;
697 
698 	/** @brief The component index of the second plane if dual plane. */
699 	unsigned int dual_plane_component;
700 
701 	/** @brief The color endpoint encoding mode for each partition. */
702 	unsigned int color_endpoint_modes[4];
703 
704 	/** @brief The number of color endpoint quantization levels. */
705 	unsigned int color_level_count;
706 
707 	/** @brief The number of weight quantization levels. */
708 	unsigned int weight_level_count;
709 
710 	/** @brief The number of weights in the X dimension. */
711 	unsigned int weight_x;
712 
713 	/** @brief The number of weights in the Y dimension. */
714 	unsigned int weight_y;
715 
716 	/** @brief The number of weights in the Z dimension. */
717 	unsigned int weight_z;
718 
719 	/** @brief The unpacked color endpoints for each partition. */
720 	float color_endpoints[4][2][4];
721 
722 	/** @brief The per-texel interpolation weights for the block. */
723 	float weight_values_plane1[216];
724 
725 	/** @brief The per-texel interpolation weights for the block. */
726 	float weight_values_plane2[216];
727 
728 	/** @brief The per-texel partition assignments for the block. */
729 	uint8_t partition_assignment[216];
730 };
731 
732 /**
733  * Populate a codec config based on default settings.
734  *
735  * Power users can edit the returned config struct to fine tune before allocating the context.
736  *
737  * @param      profile   Color profile.
738  * @param      block_x   ASTC block size X dimension.
739  * @param      block_y   ASTC block size Y dimension.
740  * @param      block_z   ASTC block size Z dimension.
741  * @param      quality   Search quality preset / effort level. Either an
742  *                       @c ASTCENC_PRE_* value, or a effort level between 0
743  *                       and 100. Performance is not linear between 0 and 100.
744 
745  * @param      flags     A valid set of @c ASTCENC_FLG_* flag bits.
746  * @param[out] config    Output config struct to populate.
747  *
748  * @return @c ASTCENC_SUCCESS on success, or an error if the inputs are invalid
749  * either individually, or in combination.
750  */
751 ASTCENC_PUBLIC astcenc_error astcenc_config_init(
752 	astcenc_profile profile,
753 	unsigned int block_x,
754 	unsigned int block_y,
755 	unsigned int block_z,
756 	float quality,
757 	unsigned int flags,
758 	astcenc_config* config);
759 
760 /**
761  * @brief Allocate a new codec context based on a config.
762  *
763  * This function allocates all of the memory resources and threads needed by the codec. This can be
764  * slow, so it is recommended that contexts are reused to serially compress or decompress multiple
765  * images to amortize setup cost.
766  *
767  * Contexts can be allocated to support only decompression using the @c ASTCENC_FLG_DECOMPRESS_ONLY
768  * flag when creating the configuration. The compression functions will fail if invoked. For a
769  * decompress-only library build the @c ASTCENC_FLG_DECOMPRESS_ONLY flag must be set when creating
770  * any context.
771  *
772  * @param[in]  config         Codec config.
773  * @param      thread_count   Thread count to configure for.
774  * @param[out] context        Location to store an opaque context pointer.
775  *
776  * @return @c ASTCENC_SUCCESS on success, or an error if context creation failed.
777  */
778 ASTCENC_PUBLIC astcenc_error astcenc_context_alloc(
779 	const astcenc_config* config,
780 	unsigned int thread_count,
781 	astcenc_context** context);
782 
783 /**
784  * @brief Compress an image.
785  *
786  * A single context can only compress or decompress a single image at a time.
787  *
788  * For a context configured for multi-threading, any set of the N threads can call this function.
789  * Work will be dynamically scheduled across the threads available. Each thread must have a unique
790  * @c thread_index.
791  *
792  * @param         context        Codec context.
793  * @param[in,out] image          An input image, in 2D slices.
794  * @param         swizzle        Compression data swizzle, applied before compression.
795  * @param[out]    data_out       Pointer to output data array.
796  * @param         data_len       Length of the output data array.
797  * @param         thread_index   Thread index [0..N-1] of calling thread.
798  *
799  * @return @c ASTCENC_SUCCESS on success, or an error if compression failed.
800  */
801 ASTCENC_PUBLIC astcenc_error astcenc_compress_image(
802 	astcenc_context* context,
803 	astcenc_image* image,
804 	const astcenc_swizzle* swizzle,
805 	uint8_t* data_out,
806 	size_t data_len,
807 #if QUALITY_CONTROL
808 	bool calQualityEnable,
809 	int32_t *mse[RGBA_COM],
810 #endif
811 	unsigned int thread_index);
812 
813 /**
814  * @brief Reset the codec state for a new compression.
815  *
816  * The caller is responsible for synchronizing threads in the worker thread pool. This function must
817  * only be called when all threads have exited the @c astcenc_compress_image() function for image N,
818  * but before any thread enters it for image N + 1.
819  *
820  * Calling this is not required (but won't hurt), if the context is created for single threaded use.
821  *
822  * @param context   Codec context.
823  *
824  * @return @c ASTCENC_SUCCESS on success, or an error if reset failed.
825  */
826 ASTCENC_PUBLIC astcenc_error astcenc_compress_reset(
827 	astcenc_context* context);
828 
829 /**
830  * @brief Decompress an image.
831  *
832  * @param         context        Codec context.
833  * @param[in]     data           Pointer to compressed data.
834  * @param         data_len       Length of the compressed data, in bytes.
835  * @param[in,out] image_out      Output image.
836  * @param         swizzle        Decompression data swizzle, applied after decompression.
837  * @param         thread_index   Thread index [0..N-1] of calling thread.
838  *
839  * @return @c ASTCENC_SUCCESS on success, or an error if decompression failed.
840  */
841 ASTCENC_PUBLIC astcenc_error astcenc_decompress_image(
842 	astcenc_context* context,
843 	const uint8_t* data,
844 	size_t data_len,
845 	astcenc_image* image_out,
846 	const astcenc_swizzle* swizzle,
847 	unsigned int thread_index);
848 
849 /**
850  * @brief Reset the codec state for a new decompression.
851  *
852  * The caller is responsible for synchronizing threads in the worker thread pool. This function must
853  * only be called when all threads have exited the @c astcenc_decompress_image() function for image
854  * N, but before any thread enters it for image N + 1.
855  *
856  * Calling this is not required (but won't hurt), if the context is created for single threaded use.
857  *
858  * @param context   Codec context.
859  *
860  * @return @c ASTCENC_SUCCESS on success, or an error if reset failed.
861  */
862 ASTCENC_PUBLIC astcenc_error astcenc_decompress_reset(
863 	astcenc_context* context);
864 
865 /**
866  * Free the compressor context.
867  *
868  * @param context   The codec context.
869  */
870 ASTCENC_PUBLIC void astcenc_context_free(
871 	astcenc_context* context);
872 
873 /**
874  * @brief Provide a high level summary of a block's encoding.
875  *
876  * This feature is primarily useful for codec developers but may be useful for developers building
877  * advanced content packaging pipelines.
878  *
879  * @param context   Codec context.
880  * @param data      One block of compressed ASTC data.
881  * @param info      The output info structure to populate.
882  *
883  * @return @c ASTCENC_SUCCESS if the block was decoded, or an error otherwise. Note that this
884  *         function will return success even if the block itself was an error block encoding, as the
885  *         decode was correctly handled.
886  */
887 ASTCENC_PUBLIC astcenc_error astcenc_get_block_info(
888 	astcenc_context* context,
889 	const uint8_t data[16],
890 	astcenc_block_info* info);
891 
892 /**
893  * @brief Get a printable string for specific status code.
894  *
895  * @param status   The status value.
896  *
897  * @return A human readable nul-terminated string.
898  */
899 ASTCENC_PUBLIC const char* astcenc_get_error_string(
900 	astcenc_error status);
901 
902 #endif
903