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