CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/ext/basis_universal/basisu_transcoder.h
Views: 1401
1
// basisu_transcoder.h
2
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
3
// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
4
//
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy 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,
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
// See the License for the specific language governing permissions and
15
// limitations under the License.
16
#pragma once
17
18
// By default KTX2 support is enabled to simplify compilation. This implies the need for the Zstandard library (which we distribute as a single source file in the "zstd" directory) by default.
19
// Set BASISD_SUPPORT_KTX2 to 0 to completely disable KTX2 support as well as Zstd/miniz usage which is only required for UASTC supercompression in KTX2 files.
20
// Also see BASISD_SUPPORT_KTX2_ZSTD in basisu_transcoder.cpp, which individually disables Zstd usage.
21
#ifndef BASISD_SUPPORT_KTX2
22
#define BASISD_SUPPORT_KTX2 1
23
#endif
24
25
// Set BASISD_SUPPORT_KTX2_ZSTD to 0 to disable Zstd usage and KTX2 UASTC Zstd supercompression support
26
#ifndef BASISD_SUPPORT_KTX2_ZSTD
27
#define BASISD_SUPPORT_KTX2_ZSTD 1
28
#endif
29
30
// Set BASISU_FORCE_DEVEL_MESSAGES to 1 to enable debug printf()'s whenever an error occurs, for easier debugging during development.
31
#ifndef BASISU_FORCE_DEVEL_MESSAGES
32
#define BASISU_FORCE_DEVEL_MESSAGES 0
33
#endif
34
35
#include "basisu_transcoder_internal.h"
36
#include "basisu_transcoder_uastc.h"
37
#include "basisu_file_headers.h"
38
39
namespace basist
40
{
41
// High-level composite texture formats supported by the transcoder.
42
// Each of these texture formats directly correspond to OpenGL/D3D/Vulkan etc. texture formats.
43
// Notes:
44
// - If you specify a texture format that supports alpha, but the .basis file doesn't have alpha, the transcoder will automatically output a
45
// fully opaque (255) alpha channel.
46
// - The PVRTC1 texture formats only support power of 2 dimension .basis files, but this may be relaxed in a future version.
47
// - The PVRTC1 transcoders are real-time encoders, so don't expect the highest quality. We may add a slower encoder with improved quality.
48
// - These enums must be kept in sync with Javascript code that calls the transcoder.
49
enum class transcoder_texture_format
50
{
51
// Compressed formats
52
53
// ETC1-2
54
cTFETC1_RGB = 0, // Opaque only, returns RGB or alpha data if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
55
cTFETC2_RGBA = 1, // Opaque+alpha, ETC2_EAC_A8 block followed by a ETC1 block, alpha channel will be opaque for opaque .basis files
56
57
// BC1-5, BC7 (desktop, some mobile devices)
58
cTFBC1_RGB = 2, // Opaque only, no punchthrough alpha support yet, transcodes alpha slice if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
59
cTFBC3_RGBA = 3, // Opaque+alpha, BC4 followed by a BC1 block, alpha channel will be opaque for opaque .basis files
60
cTFBC4_R = 4, // Red only, alpha slice is transcoded to output if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
61
cTFBC5_RG = 5, // XY: Two BC4 blocks, X=R and Y=Alpha, .basis file should have alpha data (if not Y will be all 255's)
62
cTFBC7_RGBA = 6, // RGB or RGBA, mode 5 for ETC1S, modes (1,2,3,5,6,7) for UASTC
63
64
// PVRTC1 4bpp (mobile, PowerVR devices)
65
cTFPVRTC1_4_RGB = 8, // Opaque only, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified, nearly lowest quality of any texture format.
66
cTFPVRTC1_4_RGBA = 9, // Opaque+alpha, most useful for simple opacity maps. If .basis file doesn't have alpha cTFPVRTC1_4_RGB will be used instead. Lowest quality of any supported texture format.
67
68
// ASTC (mobile, Intel devices, hopefully all desktop GPU's one day)
69
cTFASTC_4x4_RGBA = 10, // Opaque+alpha, ASTC 4x4, alpha channel will be opaque for opaque .basis files. Transcoder uses RGB/RGBA/L/LA modes, void extent, and up to two ([0,47] and [0,255]) endpoint precisions.
70
71
// ATC (mobile, Adreno devices, this is a niche format)
72
cTFATC_RGB = 11, // Opaque, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified. ATI ATC (GL_ATC_RGB_AMD)
73
cTFATC_RGBA = 12, // Opaque+alpha, alpha channel will be opaque for opaque .basis files. ATI ATC (GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD)
74
75
// FXT1 (desktop, Intel devices, this is a super obscure format)
76
cTFFXT1_RGB = 17, // Opaque only, uses exclusively CC_MIXED blocks. Notable for having a 8x4 block size. GL_3DFX_texture_compression_FXT1 is supported on Intel integrated GPU's (such as HD 630).
77
// Punch-through alpha is relatively easy to support, but full alpha is harder. This format is only here for completeness so opaque-only is fine for now.
78
// See the BASISU_USE_ORIGINAL_3DFX_FXT1_ENCODING macro in basisu_transcoder_internal.h.
79
80
cTFPVRTC2_4_RGB = 18, // Opaque-only, almost BC1 quality, much faster to transcode and supports arbitrary texture dimensions (unlike PVRTC1 RGB).
81
cTFPVRTC2_4_RGBA = 19, // Opaque+alpha, slower to encode than cTFPVRTC2_4_RGB. Premultiplied alpha is highly recommended, otherwise the color channel can leak into the alpha channel on transparent blocks.
82
83
cTFETC2_EAC_R11 = 20, // R only (ETC2 EAC R11 unsigned)
84
cTFETC2_EAC_RG11 = 21, // RG only (ETC2 EAC RG11 unsigned), R=opaque.r, G=alpha - for tangent space normal maps
85
86
// Uncompressed (raw pixel) formats
87
cTFRGBA32 = 13, // 32bpp RGBA image stored in raster (not block) order in memory, R is first byte, A is last byte.
88
cTFRGB565 = 14, // 16bpp RGB image stored in raster (not block) order in memory, R at bit position 11
89
cTFBGR565 = 15, // 16bpp RGB image stored in raster (not block) order in memory, R at bit position 0
90
cTFRGBA4444 = 16, // 16bpp RGBA image stored in raster (not block) order in memory, R at bit position 12, A at bit position 0
91
92
cTFTotalTextureFormats = 22,
93
94
// Old enums for compatibility with code compiled against previous versions
95
cTFETC1 = cTFETC1_RGB,
96
cTFETC2 = cTFETC2_RGBA,
97
cTFBC1 = cTFBC1_RGB,
98
cTFBC3 = cTFBC3_RGBA,
99
cTFBC4 = cTFBC4_R,
100
cTFBC5 = cTFBC5_RG,
101
102
// Previously, the caller had some control over which BC7 mode the transcoder output. We've simplified this due to UASTC, which supports numerous modes.
103
cTFBC7_M6_RGB = cTFBC7_RGBA, // Opaque only, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified. Highest quality of all the non-ETC1 formats.
104
cTFBC7_M5_RGBA = cTFBC7_RGBA, // Opaque+alpha, alpha channel will be opaque for opaque .basis files
105
cTFBC7_M6_OPAQUE_ONLY = cTFBC7_RGBA,
106
cTFBC7_M5 = cTFBC7_RGBA,
107
cTFBC7_ALT = 7,
108
109
cTFASTC_4x4 = cTFASTC_4x4_RGBA,
110
111
cTFATC_RGBA_INTERPOLATED_ALPHA = cTFATC_RGBA,
112
};
113
114
// For compressed texture formats, this returns the # of bytes per block. For uncompressed, it returns the # of bytes per pixel.
115
// NOTE: Previously, this function was called basis_get_bytes_per_block(), and it always returned 16*bytes_per_pixel for uncompressed formats which was confusing.
116
uint32_t basis_get_bytes_per_block_or_pixel(transcoder_texture_format fmt);
117
118
// Returns format's name in ASCII
119
const char* basis_get_format_name(transcoder_texture_format fmt);
120
121
// Returns block format name in ASCII
122
const char* basis_get_block_format_name(block_format fmt);
123
124
// Returns true if the format supports an alpha channel.
125
bool basis_transcoder_format_has_alpha(transcoder_texture_format fmt);
126
127
// Returns the basisu::texture_format corresponding to the specified transcoder_texture_format.
128
basisu::texture_format basis_get_basisu_texture_format(transcoder_texture_format fmt);
129
130
// Returns the texture type's name in ASCII.
131
const char* basis_get_texture_type_name(basis_texture_type tex_type);
132
133
// Returns true if the transcoder texture type is an uncompressed (raw pixel) format.
134
bool basis_transcoder_format_is_uncompressed(transcoder_texture_format tex_type);
135
136
// Returns the # of bytes per pixel for uncompressed formats, or 0 for block texture formats.
137
uint32_t basis_get_uncompressed_bytes_per_pixel(transcoder_texture_format fmt);
138
139
// Returns the block width for the specified texture format, which is currently either 4 or 8 for FXT1.
140
uint32_t basis_get_block_width(transcoder_texture_format tex_type);
141
142
// Returns the block height for the specified texture format, which is currently always 4.
143
uint32_t basis_get_block_height(transcoder_texture_format tex_type);
144
145
// Returns true if the specified format was enabled at compile time.
146
bool basis_is_format_supported(transcoder_texture_format tex_type, basis_tex_format fmt = basis_tex_format::cETC1S);
147
148
// Validates that the output buffer is large enough to hold the entire transcoded texture.
149
// For uncompressed texture formats, most input parameters are in pixels, not blocks. Blocks are 4x4 pixels.
150
bool basis_validate_output_buffer_size(transcoder_texture_format target_format,
151
uint32_t output_blocks_buf_size_in_blocks_or_pixels,
152
uint32_t orig_width, uint32_t orig_height,
153
uint32_t output_row_pitch_in_blocks_or_pixels,
154
uint32_t output_rows_in_pixels,
155
uint32_t total_slice_blocks);
156
157
class basisu_transcoder;
158
159
// This struct holds all state used during transcoding. For video, it needs to persist between image transcodes (it holds the previous frame).
160
// For threading you can use one state per thread.
161
struct basisu_transcoder_state
162
{
163
struct block_preds
164
{
165
uint16_t m_endpoint_index;
166
uint8_t m_pred_bits;
167
};
168
169
basisu::vector<block_preds> m_block_endpoint_preds[2];
170
171
enum { cMaxPrevFrameLevels = 16 };
172
basisu::vector<uint32_t> m_prev_frame_indices[2][cMaxPrevFrameLevels]; // [alpha_flag][level_index]
173
174
void clear()
175
{
176
for (uint32_t i = 0; i < 2; i++)
177
{
178
m_block_endpoint_preds[i].clear();
179
180
for (uint32_t j = 0; j < cMaxPrevFrameLevels; j++)
181
m_prev_frame_indices[i][j].clear();
182
}
183
}
184
};
185
186
// Low-level helper class that does the actual transcoding.
187
class basisu_lowlevel_etc1s_transcoder
188
{
189
friend class basisu_transcoder;
190
191
public:
192
basisu_lowlevel_etc1s_transcoder();
193
194
void set_global_codebooks(const basisu_lowlevel_etc1s_transcoder* pGlobal_codebook) { m_pGlobal_codebook = pGlobal_codebook; }
195
const basisu_lowlevel_etc1s_transcoder* get_global_codebooks() const { return m_pGlobal_codebook; }
196
197
bool decode_palettes(
198
uint32_t num_endpoints, const uint8_t* pEndpoints_data, uint32_t endpoints_data_size,
199
uint32_t num_selectors, const uint8_t* pSelectors_data, uint32_t selectors_data_size);
200
201
bool decode_tables(const uint8_t* pTable_data, uint32_t table_data_size);
202
203
bool transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt,
204
uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const bool is_video, const bool is_alpha_slice, const uint32_t level_index, const uint32_t orig_width, const uint32_t orig_height, uint32_t output_row_pitch_in_blocks_or_pixels = 0,
205
basisu_transcoder_state* pState = nullptr, bool astc_transcode_alpha = false, void* pAlpha_blocks = nullptr, uint32_t output_rows_in_pixels = 0);
206
207
bool transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt,
208
uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const basis_file_header& header, const basis_slice_desc& slice_desc, uint32_t output_row_pitch_in_blocks_or_pixels = 0,
209
basisu_transcoder_state* pState = nullptr, bool astc_transcode_alpha = false, void* pAlpha_blocks = nullptr, uint32_t output_rows_in_pixels = 0)
210
{
211
return transcode_slice(pDst_blocks, num_blocks_x, num_blocks_y, pImage_data, image_data_size, fmt, output_block_or_pixel_stride_in_bytes, bc1_allow_threecolor_blocks,
212
header.m_tex_type == cBASISTexTypeVideoFrames, (slice_desc.m_flags & cSliceDescFlagsHasAlpha) != 0, slice_desc.m_level_index,
213
slice_desc.m_orig_width, slice_desc.m_orig_height, output_row_pitch_in_blocks_or_pixels, pState,
214
astc_transcode_alpha,
215
pAlpha_blocks,
216
output_rows_in_pixels);
217
}
218
219
// Container independent transcoding
220
bool transcode_image(
221
transcoder_texture_format target_format,
222
void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
223
const uint8_t* pCompressed_data, uint32_t compressed_data_length,
224
uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
225
uint32_t rgb_offset, uint32_t rgb_length, uint32_t alpha_offset, uint32_t alpha_length,
226
uint32_t decode_flags = 0,
227
bool basis_file_has_alpha_slices = false,
228
bool is_video = false,
229
uint32_t output_row_pitch_in_blocks_or_pixels = 0,
230
basisu_transcoder_state* pState = nullptr,
231
uint32_t output_rows_in_pixels = 0);
232
233
void clear()
234
{
235
m_local_endpoints.clear();
236
m_local_selectors.clear();
237
m_endpoint_pred_model.clear();
238
m_delta_endpoint_model.clear();
239
m_selector_model.clear();
240
m_selector_history_buf_rle_model.clear();
241
m_selector_history_buf_size = 0;
242
}
243
244
// Low-level methods
245
typedef basisu::vector<endpoint> endpoint_vec;
246
const endpoint_vec& get_endpoints() const { return m_local_endpoints; }
247
248
typedef basisu::vector<selector> selector_vec;
249
const selector_vec& get_selectors() const { return m_local_selectors; }
250
251
private:
252
const basisu_lowlevel_etc1s_transcoder* m_pGlobal_codebook;
253
254
endpoint_vec m_local_endpoints;
255
selector_vec m_local_selectors;
256
257
huffman_decoding_table m_endpoint_pred_model, m_delta_endpoint_model, m_selector_model, m_selector_history_buf_rle_model;
258
259
uint32_t m_selector_history_buf_size;
260
261
basisu_transcoder_state m_def_state;
262
};
263
264
enum basisu_decode_flags
265
{
266
// PVRTC1: decode non-pow2 ETC1S texture level to the next larger power of 2 (not implemented yet, but we're going to support it). Ignored if the slice's dimensions are already a power of 2.
267
cDecodeFlagsPVRTCDecodeToNextPow2 = 2,
268
269
// When decoding to an opaque texture format, if the basis file has alpha, decode the alpha slice instead of the color slice to the output texture format.
270
// This is primarily to allow decoding of textures with alpha to multiple ETC1 textures (one for color, another for alpha).
271
cDecodeFlagsTranscodeAlphaDataToOpaqueFormats = 4,
272
273
// Forbid usage of BC1 3 color blocks (we don't support BC1 punchthrough alpha yet).
274
// This flag is used internally when decoding to BC3.
275
cDecodeFlagsBC1ForbidThreeColorBlocks = 8,
276
277
// The output buffer contains alpha endpoint/selector indices.
278
// Used internally when decoding formats like ASTC that require both color and alpha data to be available when transcoding to the output format.
279
cDecodeFlagsOutputHasAlphaIndices = 16,
280
281
cDecodeFlagsHighQuality = 32
282
};
283
284
class basisu_lowlevel_uastc_transcoder
285
{
286
friend class basisu_transcoder;
287
288
public:
289
basisu_lowlevel_uastc_transcoder();
290
291
bool transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt,
292
uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, bool has_alpha, const uint32_t orig_width, const uint32_t orig_height, uint32_t output_row_pitch_in_blocks_or_pixels = 0,
293
basisu_transcoder_state* pState = nullptr, uint32_t output_rows_in_pixels = 0, int channel0 = -1, int channel1 = -1, uint32_t decode_flags = 0);
294
295
bool transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt,
296
uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const basis_file_header& header, const basis_slice_desc& slice_desc, uint32_t output_row_pitch_in_blocks_or_pixels = 0,
297
basisu_transcoder_state* pState = nullptr, uint32_t output_rows_in_pixels = 0, int channel0 = -1, int channel1 = -1, uint32_t decode_flags = 0)
298
{
299
return transcode_slice(pDst_blocks, num_blocks_x, num_blocks_y, pImage_data, image_data_size, fmt,
300
output_block_or_pixel_stride_in_bytes, bc1_allow_threecolor_blocks, (header.m_flags & cBASISHeaderFlagHasAlphaSlices) != 0, slice_desc.m_orig_width, slice_desc.m_orig_height, output_row_pitch_in_blocks_or_pixels,
301
pState, output_rows_in_pixels, channel0, channel1, decode_flags);
302
}
303
304
// Container independent transcoding
305
bool transcode_image(
306
transcoder_texture_format target_format,
307
void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
308
const uint8_t* pCompressed_data, uint32_t compressed_data_length,
309
uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
310
uint32_t slice_offset, uint32_t slice_length,
311
uint32_t decode_flags = 0,
312
bool has_alpha = false,
313
bool is_video = false,
314
uint32_t output_row_pitch_in_blocks_or_pixels = 0,
315
basisu_transcoder_state* pState = nullptr,
316
uint32_t output_rows_in_pixels = 0,
317
int channel0 = -1, int channel1 = -1);
318
};
319
320
struct basisu_slice_info
321
{
322
uint32_t m_orig_width;
323
uint32_t m_orig_height;
324
325
uint32_t m_width;
326
uint32_t m_height;
327
328
uint32_t m_num_blocks_x;
329
uint32_t m_num_blocks_y;
330
uint32_t m_total_blocks;
331
332
uint32_t m_compressed_size;
333
334
uint32_t m_slice_index; // the slice index in the .basis file
335
uint32_t m_image_index; // the source image index originally provided to the encoder
336
uint32_t m_level_index; // the mipmap level within this image
337
338
uint32_t m_unpacked_slice_crc16;
339
340
bool m_alpha_flag; // true if the slice has alpha data
341
bool m_iframe_flag; // true if the slice is an I-Frame
342
};
343
344
typedef basisu::vector<basisu_slice_info> basisu_slice_info_vec;
345
346
struct basisu_image_info
347
{
348
uint32_t m_image_index;
349
uint32_t m_total_levels;
350
351
uint32_t m_orig_width;
352
uint32_t m_orig_height;
353
354
uint32_t m_width;
355
uint32_t m_height;
356
357
uint32_t m_num_blocks_x;
358
uint32_t m_num_blocks_y;
359
uint32_t m_total_blocks;
360
361
uint32_t m_first_slice_index;
362
363
bool m_alpha_flag; // true if the image has alpha data
364
bool m_iframe_flag; // true if the image is an I-Frame
365
};
366
367
struct basisu_image_level_info
368
{
369
uint32_t m_image_index;
370
uint32_t m_level_index;
371
372
uint32_t m_orig_width;
373
uint32_t m_orig_height;
374
375
uint32_t m_width;
376
uint32_t m_height;
377
378
uint32_t m_num_blocks_x;
379
uint32_t m_num_blocks_y;
380
uint32_t m_total_blocks;
381
382
uint32_t m_first_slice_index;
383
384
uint32_t m_rgb_file_ofs;
385
uint32_t m_rgb_file_len;
386
uint32_t m_alpha_file_ofs;
387
uint32_t m_alpha_file_len;
388
389
bool m_alpha_flag; // true if the image has alpha data
390
bool m_iframe_flag; // true if the image is an I-Frame
391
};
392
393
struct basisu_file_info
394
{
395
uint32_t m_version;
396
uint32_t m_total_header_size;
397
398
uint32_t m_total_selectors;
399
// will be 0 for UASTC or if the file uses global codebooks
400
uint32_t m_selector_codebook_ofs;
401
uint32_t m_selector_codebook_size;
402
403
uint32_t m_total_endpoints;
404
// will be 0 for UASTC or if the file uses global codebooks
405
uint32_t m_endpoint_codebook_ofs;
406
uint32_t m_endpoint_codebook_size;
407
408
uint32_t m_tables_ofs;
409
uint32_t m_tables_size;
410
411
uint32_t m_slices_size;
412
413
basis_texture_type m_tex_type;
414
uint32_t m_us_per_frame;
415
416
// Low-level slice information (1 slice per image for color-only basis files, 2 for alpha basis files)
417
basisu_slice_info_vec m_slice_info;
418
419
uint32_t m_total_images; // total # of images
420
basisu::vector<uint32_t> m_image_mipmap_levels; // the # of mipmap levels for each image
421
422
uint32_t m_userdata0;
423
uint32_t m_userdata1;
424
425
basis_tex_format m_tex_format; // ETC1S, UASTC, etc.
426
427
bool m_y_flipped; // true if the image was Y flipped
428
bool m_etc1s; // true if the file is ETC1S
429
bool m_has_alpha_slices; // true if the texture has alpha slices (for ETC1S: even slices RGB, odd slices alpha)
430
};
431
432
// High-level transcoder class which accepts .basis file data and allows the caller to query information about the file and transcode image levels to various texture formats.
433
// If you're just starting out this is the class you care about.
434
class basisu_transcoder
435
{
436
basisu_transcoder(basisu_transcoder&);
437
basisu_transcoder& operator= (const basisu_transcoder&);
438
439
public:
440
basisu_transcoder();
441
442
// Validates the .basis file. This computes a crc16 over the entire file, so it's slow.
443
bool validate_file_checksums(const void* pData, uint32_t data_size, bool full_validation) const;
444
445
// Quick header validation - no crc16 checks.
446
bool validate_header(const void* pData, uint32_t data_size) const;
447
448
basis_texture_type get_texture_type(const void* pData, uint32_t data_size) const;
449
bool get_userdata(const void* pData, uint32_t data_size, uint32_t& userdata0, uint32_t& userdata1) const;
450
451
// Returns the total number of images in the basis file (always 1 or more).
452
// Note that the number of mipmap levels for each image may differ, and that images may have different resolutions.
453
uint32_t get_total_images(const void* pData, uint32_t data_size) const;
454
455
basis_tex_format get_tex_format(const void* pData, uint32_t data_size) const;
456
457
// Returns the number of mipmap levels in an image.
458
uint32_t get_total_image_levels(const void* pData, uint32_t data_size, uint32_t image_index) const;
459
460
// Returns basic information about an image. Note that orig_width/orig_height may not be a multiple of 4.
461
bool get_image_level_desc(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, uint32_t& orig_width, uint32_t& orig_height, uint32_t& total_blocks) const;
462
463
// Returns information about the specified image.
464
bool get_image_info(const void* pData, uint32_t data_size, basisu_image_info& image_info, uint32_t image_index) const;
465
466
// Returns information about the specified image's mipmap level.
467
bool get_image_level_info(const void* pData, uint32_t data_size, basisu_image_level_info& level_info, uint32_t image_index, uint32_t level_index) const;
468
469
// Get a description of the basis file and low-level information about each slice.
470
bool get_file_info(const void* pData, uint32_t data_size, basisu_file_info& file_info) const;
471
472
// start_transcoding() must be called before calling transcode_slice() or transcode_image_level().
473
// For ETC1S files, this call decompresses the selector/endpoint codebooks, so ideally you would only call this once per .basis file (not each image/mipmap level).
474
bool start_transcoding(const void* pData, uint32_t data_size);
475
476
bool stop_transcoding();
477
478
// Returns true if start_transcoding() has been called.
479
bool get_ready_to_transcode() const { return m_ready_to_transcode; }
480
481
// transcode_image_level() decodes a single mipmap level from the .basis file to any of the supported output texture formats.
482
// It'll first find the slice(s) to transcode, then call transcode_slice() one or two times to decode both the color and alpha texture data (or RG texture data from two slices for BC5).
483
// If the .basis file doesn't have alpha slices, the output alpha blocks will be set to fully opaque (all 255's).
484
// Currently, to decode to PVRTC1 the basis texture's dimensions in pixels must be a power of 2, due to PVRTC1 format requirements.
485
// output_blocks_buf_size_in_blocks_or_pixels should be at least the image level's total_blocks (num_blocks_x * num_blocks_y), or the total number of output pixels if fmt==cTFRGBA32.
486
// output_row_pitch_in_blocks_or_pixels: Number of blocks or pixels per row. If 0, the transcoder uses the slice's num_blocks_x or orig_width (NOT num_blocks_x * 4). Ignored for PVRTC1 (due to texture swizzling).
487
// output_rows_in_pixels: Ignored unless fmt is uncompressed (cRGBA32, etc.). The total number of output rows in the output buffer. If 0, the transcoder assumes the slice's orig_height (NOT num_blocks_y * 4).
488
// Notes:
489
// - basisu_transcoder_init() must have been called first to initialize the transcoder lookup tables before calling this function.
490
// - This method assumes the output texture buffer is readable. In some cases to handle alpha, the transcoder will write temporary data to the output texture in
491
// a first pass, which will be read in a second pass.
492
bool transcode_image_level(
493
const void* pData, uint32_t data_size,
494
uint32_t image_index, uint32_t level_index,
495
void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
496
transcoder_texture_format fmt,
497
uint32_t decode_flags = 0, uint32_t output_row_pitch_in_blocks_or_pixels = 0, basisu_transcoder_state* pState = nullptr, uint32_t output_rows_in_pixels = 0) const;
498
499
// Finds the basis slice corresponding to the specified image/level/alpha params, or -1 if the slice can't be found.
500
int find_slice(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, bool alpha_data) const;
501
502
// transcode_slice() decodes a single slice from the .basis file. It's a low-level API - most likely you want to use transcode_image_level().
503
// This is a low-level API, and will be needed to be called multiple times to decode some texture formats (like BC3, BC5, or ETC2).
504
// output_blocks_buf_size_in_blocks_or_pixels is just used for verification to make sure the output buffer is large enough.
505
// output_blocks_buf_size_in_blocks_or_pixels should be at least the image level's total_blocks (num_blocks_x * num_blocks_y), or the total number of output pixels if fmt==cTFRGBA32.
506
// output_block_stride_in_bytes: Number of bytes between each output block.
507
// output_row_pitch_in_blocks_or_pixels: Number of blocks or pixels per row. If 0, the transcoder uses the slice's num_blocks_x or orig_width (NOT num_blocks_x * 4). Ignored for PVRTC1 (due to texture swizzling).
508
// output_rows_in_pixels: Ignored unless fmt is cRGBA32. The total number of output rows in the output buffer. If 0, the transcoder assumes the slice's orig_height (NOT num_blocks_y * 4).
509
// Notes:
510
// - basisu_transcoder_init() must have been called first to initialize the transcoder lookup tables before calling this function.
511
bool transcode_slice(const void* pData, uint32_t data_size, uint32_t slice_index,
512
void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
513
block_format fmt, uint32_t output_block_stride_in_bytes, uint32_t decode_flags = 0, uint32_t output_row_pitch_in_blocks_or_pixels = 0, basisu_transcoder_state* pState = nullptr, void* pAlpha_blocks = nullptr,
514
uint32_t output_rows_in_pixels = 0, int channel0 = -1, int channel1 = -1) const;
515
516
static void write_opaque_alpha_blocks(
517
uint32_t num_blocks_x, uint32_t num_blocks_y,
518
void* pOutput_blocks, block_format fmt,
519
uint32_t block_stride_in_bytes, uint32_t output_row_pitch_in_blocks_or_pixels);
520
521
void set_global_codebooks(const basisu_lowlevel_etc1s_transcoder* pGlobal_codebook) { m_lowlevel_etc1s_decoder.set_global_codebooks(pGlobal_codebook); }
522
const basisu_lowlevel_etc1s_transcoder* get_global_codebooks() const { return m_lowlevel_etc1s_decoder.get_global_codebooks(); }
523
524
const basisu_lowlevel_etc1s_transcoder& get_lowlevel_etc1s_decoder() const { return m_lowlevel_etc1s_decoder; }
525
basisu_lowlevel_etc1s_transcoder& get_lowlevel_etc1s_decoder() { return m_lowlevel_etc1s_decoder; }
526
527
const basisu_lowlevel_uastc_transcoder& get_lowlevel_uastc_decoder() const { return m_lowlevel_uastc_decoder; }
528
basisu_lowlevel_uastc_transcoder& get_lowlevel_uastc_decoder() { return m_lowlevel_uastc_decoder; }
529
530
private:
531
mutable basisu_lowlevel_etc1s_transcoder m_lowlevel_etc1s_decoder;
532
mutable basisu_lowlevel_uastc_transcoder m_lowlevel_uastc_decoder;
533
534
bool m_ready_to_transcode;
535
536
int find_first_slice_index(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index) const;
537
538
bool validate_header_quick(const void* pData, uint32_t data_size) const;
539
};
540
541
// basisu_transcoder_init() MUST be called before a .basis file can be transcoded.
542
void basisu_transcoder_init();
543
544
enum debug_flags_t
545
{
546
cDebugFlagVisCRs = 1,
547
cDebugFlagVisBC1Sels = 2,
548
cDebugFlagVisBC1Endpoints = 4
549
};
550
uint32_t get_debug_flags();
551
void set_debug_flags(uint32_t f);
552
553
// ------------------------------------------------------------------------------------------------------
554
// Optional .KTX2 file format support
555
// KTX2 reading optionally requires miniz or Zstd decompressors for supercompressed UASTC files.
556
// ------------------------------------------------------------------------------------------------------
557
#if BASISD_SUPPORT_KTX2
558
#pragma pack(push)
559
#pragma pack(1)
560
struct ktx2_header
561
{
562
uint8_t m_identifier[12];
563
basisu::packed_uint<4> m_vk_format;
564
basisu::packed_uint<4> m_type_size;
565
basisu::packed_uint<4> m_pixel_width;
566
basisu::packed_uint<4> m_pixel_height;
567
basisu::packed_uint<4> m_pixel_depth;
568
basisu::packed_uint<4> m_layer_count;
569
basisu::packed_uint<4> m_face_count;
570
basisu::packed_uint<4> m_level_count;
571
basisu::packed_uint<4> m_supercompression_scheme;
572
basisu::packed_uint<4> m_dfd_byte_offset;
573
basisu::packed_uint<4> m_dfd_byte_length;
574
basisu::packed_uint<4> m_kvd_byte_offset;
575
basisu::packed_uint<4> m_kvd_byte_length;
576
basisu::packed_uint<8> m_sgd_byte_offset;
577
basisu::packed_uint<8> m_sgd_byte_length;
578
};
579
580
struct ktx2_level_index
581
{
582
basisu::packed_uint<8> m_byte_offset;
583
basisu::packed_uint<8> m_byte_length;
584
basisu::packed_uint<8> m_uncompressed_byte_length;
585
};
586
587
struct ktx2_etc1s_global_data_header
588
{
589
basisu::packed_uint<2> m_endpoint_count;
590
basisu::packed_uint<2> m_selector_count;
591
basisu::packed_uint<4> m_endpoints_byte_length;
592
basisu::packed_uint<4> m_selectors_byte_length;
593
basisu::packed_uint<4> m_tables_byte_length;
594
basisu::packed_uint<4> m_extended_byte_length;
595
};
596
597
struct ktx2_etc1s_image_desc
598
{
599
basisu::packed_uint<4> m_image_flags;
600
basisu::packed_uint<4> m_rgb_slice_byte_offset;
601
basisu::packed_uint<4> m_rgb_slice_byte_length;
602
basisu::packed_uint<4> m_alpha_slice_byte_offset;
603
basisu::packed_uint<4> m_alpha_slice_byte_length;
604
};
605
606
struct ktx2_animdata
607
{
608
basisu::packed_uint<4> m_duration;
609
basisu::packed_uint<4> m_timescale;
610
basisu::packed_uint<4> m_loopcount;
611
};
612
#pragma pack(pop)
613
614
const uint32_t KTX2_VK_FORMAT_UNDEFINED = 0;
615
const uint32_t KTX2_KDF_DF_MODEL_UASTC = 166;
616
const uint32_t KTX2_KDF_DF_MODEL_ETC1S = 163;
617
const uint32_t KTX2_IMAGE_IS_P_FRAME = 2;
618
const uint32_t KTX2_UASTC_BLOCK_SIZE = 16;
619
const uint32_t KTX2_MAX_SUPPORTED_LEVEL_COUNT = 16; // this is an implementation specific constraint and can be increased
620
621
// The KTX2 transfer functions supported by KTX2
622
const uint32_t KTX2_KHR_DF_TRANSFER_LINEAR = 1;
623
const uint32_t KTX2_KHR_DF_TRANSFER_SRGB = 2;
624
625
enum ktx2_supercompression
626
{
627
KTX2_SS_NONE = 0,
628
KTX2_SS_BASISLZ = 1,
629
KTX2_SS_ZSTANDARD = 2
630
};
631
632
extern const uint8_t g_ktx2_file_identifier[12];
633
634
enum ktx2_df_channel_id
635
{
636
KTX2_DF_CHANNEL_ETC1S_RGB = 0U,
637
KTX2_DF_CHANNEL_ETC1S_RRR = 3U,
638
KTX2_DF_CHANNEL_ETC1S_GGG = 4U,
639
KTX2_DF_CHANNEL_ETC1S_AAA = 15U,
640
641
KTX2_DF_CHANNEL_UASTC_DATA = 0U,
642
KTX2_DF_CHANNEL_UASTC_RGB = 0U,
643
KTX2_DF_CHANNEL_UASTC_RGBA = 3U,
644
KTX2_DF_CHANNEL_UASTC_RRR = 4U,
645
KTX2_DF_CHANNEL_UASTC_RRRG = 5U,
646
KTX2_DF_CHANNEL_UASTC_RG = 6U,
647
};
648
649
inline const char* ktx2_get_etc1s_df_channel_id_str(ktx2_df_channel_id id)
650
{
651
switch (id)
652
{
653
case KTX2_DF_CHANNEL_ETC1S_RGB: return "RGB";
654
case KTX2_DF_CHANNEL_ETC1S_RRR: return "RRR";
655
case KTX2_DF_CHANNEL_ETC1S_GGG: return "GGG";
656
case KTX2_DF_CHANNEL_ETC1S_AAA: return "AAA";
657
default: break;
658
}
659
return "?";
660
}
661
662
inline const char* ktx2_get_uastc_df_channel_id_str(ktx2_df_channel_id id)
663
{
664
switch (id)
665
{
666
case KTX2_DF_CHANNEL_UASTC_RGB: return "RGB";
667
case KTX2_DF_CHANNEL_UASTC_RGBA: return "RGBA";
668
case KTX2_DF_CHANNEL_UASTC_RRR: return "RRR";
669
case KTX2_DF_CHANNEL_UASTC_RRRG: return "RRRG";
670
case KTX2_DF_CHANNEL_UASTC_RG: return "RG";
671
default: break;
672
}
673
return "?";
674
}
675
676
enum ktx2_df_color_primaries
677
{
678
KTX2_DF_PRIMARIES_UNSPECIFIED = 0,
679
KTX2_DF_PRIMARIES_BT709 = 1,
680
KTX2_DF_PRIMARIES_SRGB = 1,
681
KTX2_DF_PRIMARIES_BT601_EBU = 2,
682
KTX2_DF_PRIMARIES_BT601_SMPTE = 3,
683
KTX2_DF_PRIMARIES_BT2020 = 4,
684
KTX2_DF_PRIMARIES_CIEXYZ = 5,
685
KTX2_DF_PRIMARIES_ACES = 6,
686
KTX2_DF_PRIMARIES_ACESCC = 7,
687
KTX2_DF_PRIMARIES_NTSC1953 = 8,
688
KTX2_DF_PRIMARIES_PAL525 = 9,
689
KTX2_DF_PRIMARIES_DISPLAYP3 = 10,
690
KTX2_DF_PRIMARIES_ADOBERGB = 11
691
};
692
693
inline const char* ktx2_get_df_color_primaries_str(ktx2_df_color_primaries p)
694
{
695
switch (p)
696
{
697
case KTX2_DF_PRIMARIES_UNSPECIFIED: return "UNSPECIFIED";
698
case KTX2_DF_PRIMARIES_BT709: return "BT709";
699
case KTX2_DF_PRIMARIES_BT601_EBU: return "EBU";
700
case KTX2_DF_PRIMARIES_BT601_SMPTE: return "SMPTE";
701
case KTX2_DF_PRIMARIES_BT2020: return "BT2020";
702
case KTX2_DF_PRIMARIES_CIEXYZ: return "CIEXYZ";
703
case KTX2_DF_PRIMARIES_ACES: return "ACES";
704
case KTX2_DF_PRIMARIES_ACESCC: return "ACESCC";
705
case KTX2_DF_PRIMARIES_NTSC1953: return "NTSC1953";
706
case KTX2_DF_PRIMARIES_PAL525: return "PAL525";
707
case KTX2_DF_PRIMARIES_DISPLAYP3: return "DISPLAYP3";
708
case KTX2_DF_PRIMARIES_ADOBERGB: return "ADOBERGB";
709
default: break;
710
}
711
return "?";
712
}
713
714
// Information about a single 2D texture "image" in a KTX2 file.
715
struct ktx2_image_level_info
716
{
717
// The mipmap level index (0=largest), texture array layer index, and cubemap face index of the image.
718
uint32_t m_level_index;
719
uint32_t m_layer_index;
720
uint32_t m_face_index;
721
722
// The image's actual (or the original source image's) width/height in pixels, which may not be divisible by 4 pixels.
723
uint32_t m_orig_width;
724
uint32_t m_orig_height;
725
726
// The image's physical width/height, which will always be divisible by 4 pixels.
727
uint32_t m_width;
728
uint32_t m_height;
729
730
// The texture's dimensions in 4x4 texel blocks.
731
uint32_t m_num_blocks_x;
732
uint32_t m_num_blocks_y;
733
734
// The total number of blocks
735
uint32_t m_total_blocks;
736
737
// true if the image has alpha data
738
bool m_alpha_flag;
739
740
// true if the image is an I-Frame. Currently, for ETC1S textures, the first frame will always be an I-Frame, and subsequent frames will always be P-Frames.
741
bool m_iframe_flag;
742
};
743
744
// Thread-specific ETC1S/supercompressed UASTC transcoder state. (If you're not doing multithreading transcoding you can ignore this.)
745
struct ktx2_transcoder_state
746
{
747
basist::basisu_transcoder_state m_transcoder_state;
748
basisu::uint8_vec m_level_uncomp_data;
749
int m_uncomp_data_level_index;
750
751
void clear()
752
{
753
m_transcoder_state.clear();
754
m_level_uncomp_data.clear();
755
m_uncomp_data_level_index = -1;
756
}
757
};
758
759
// This class is quite similar to basisu_transcoder. It treats KTX2 files as a simple container for ETC1S/UASTC texture data.
760
// It does not support 1D or 3D textures.
761
// It only supports 2D and cubemap textures, with or without mipmaps, texture arrays of 2D/cubemap textures, and texture video files.
762
// It only supports raw non-supercompressed UASTC, ETC1S, UASTC+Zstd, or UASTC+zlib compressed files.
763
// DFD (Data Format Descriptor) parsing is purposely as simple as possible.
764
// If you need to know how to interpret the texture channels you'll need to parse the DFD yourself after calling get_dfd().
765
class ktx2_transcoder
766
{
767
public:
768
ktx2_transcoder();
769
770
// Frees all allocations, resets object.
771
void clear();
772
773
// init() parses the KTX2 header, level index array, DFD, and key values, but nothing else.
774
// Importantly, it does not parse or decompress the ETC1S global supercompressed data, so some things (like which frames are I/P-Frames) won't be available until start_transcoding() is called.
775
// This method holds a pointer to the file data until clear() is called.
776
bool init(const void* pData, uint32_t data_size);
777
778
// Returns the data/size passed to init().
779
const uint8_t* get_data() const { return m_pData; }
780
uint32_t get_data_size() const { return m_data_size; }
781
782
// Returns the KTX2 header. Valid after init().
783
const ktx2_header& get_header() const { return m_header; }
784
785
// Returns the KTX2 level index array. There will be one entry for each mipmap level. Valid after init().
786
const basisu::vector<ktx2_level_index>& get_level_index() const { return m_levels; }
787
788
// Returns the texture's width in texels. Always non-zero, might not be divisible by 4. Valid after init().
789
uint32_t get_width() const { return m_header.m_pixel_width; }
790
791
// Returns the texture's height in texels. Always non-zero, might not be divisible by 4. Valid after init().
792
uint32_t get_height() const { return m_header.m_pixel_height; }
793
794
// Returns the texture's number of mipmap levels. Always returns 1 or higher. Valid after init().
795
uint32_t get_levels() const { return m_header.m_level_count; }
796
797
// Returns the number of faces. Returns 1 for 2D textures and or 6 for cubemaps. Valid after init().
798
uint32_t get_faces() const { return m_header.m_face_count; }
799
800
// Returns 0 or the number of layers in the texture array or texture video. Valid after init().
801
uint32_t get_layers() const { return m_header.m_layer_count; }
802
803
// Returns cETC1S or cUASTC4x4. Valid after init().
804
basist::basis_tex_format get_format() const { return m_format; }
805
806
bool is_etc1s() const { return get_format() == basist::basis_tex_format::cETC1S; }
807
808
bool is_uastc() const { return get_format() == basist::basis_tex_format::cUASTC4x4; }
809
810
// Returns true if the ETC1S file has two planes (typically RGBA, or RRRG), or true if the UASTC file has alpha data. Valid after init().
811
uint32_t get_has_alpha() const { return m_has_alpha; }
812
813
// Returns the entire Data Format Descriptor (DFD) from the KTX2 file. Valid after init().
814
// See https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#_the_khronos_data_format_descriptor_overview
815
const basisu::uint8_vec& get_dfd() const { return m_dfd; }
816
817
// Some basic DFD accessors. Valid after init().
818
uint32_t get_dfd_color_model() const { return m_dfd_color_model; }
819
820
// Returns the DFD color primary.
821
// We do not validate the color primaries, so the returned value may not be in the ktx2_df_color_primaries enum.
822
ktx2_df_color_primaries get_dfd_color_primaries() const { return m_dfd_color_prims; }
823
824
// Returns KTX2_KHR_DF_TRANSFER_LINEAR or KTX2_KHR_DF_TRANSFER_SRGB.
825
uint32_t get_dfd_transfer_func() const { return m_dfd_transfer_func; }
826
827
uint32_t get_dfd_flags() const { return m_dfd_flags; }
828
829
// Returns 1 (ETC1S/UASTC) or 2 (ETC1S with an internal alpha channel).
830
uint32_t get_dfd_total_samples() const { return m_dfd_samples; }
831
832
// Returns the channel mapping for each DFD "sample". UASTC always has 1 sample, ETC1S can have one or two.
833
// Note the returned value SHOULD be one of the ktx2_df_channel_id enums, but we don't validate that.
834
// It's up to the caller to decide what to do if the value isn't in the enum.
835
ktx2_df_channel_id get_dfd_channel_id0() const { return m_dfd_chan0; }
836
ktx2_df_channel_id get_dfd_channel_id1() const { return m_dfd_chan1; }
837
838
// Key value field data.
839
struct key_value
840
{
841
// The key field is UTF8 and always zero terminated.
842
basisu::uint8_vec m_key;
843
844
// The value may be empty. It consists of raw bytes which may or may not be zero terminated.
845
basisu::uint8_vec m_value;
846
847
bool operator< (const key_value& rhs) const { return strcmp((const char*)m_key.data(), (const char *)rhs.m_key.data()) < 0; }
848
};
849
typedef basisu::vector<key_value> key_value_vec;
850
851
// Returns the array of key-value entries. This may be empty. Valid after init().
852
// The order of key values fields in this array exactly matches the order they were stored in the file. The keys are supposed to be sorted by their Unicode code points.
853
const key_value_vec& get_key_values() const { return m_key_values; }
854
855
const basisu::uint8_vec *find_key(const std::string& key_name) const;
856
857
// Low-level ETC1S specific accessors
858
859
// Returns the ETC1S global supercompression data header, which is only valid after start_transcoding() is called.
860
const ktx2_etc1s_global_data_header& get_etc1s_header() const { return m_etc1s_header; }
861
862
// Returns the array of ETC1S image descriptors, which is only valid after get_etc1s_image_descs() is called.
863
const basisu::vector<ktx2_etc1s_image_desc>& get_etc1s_image_descs() const { return m_etc1s_image_descs; }
864
865
// Must have called startTranscoding() first
866
uint32_t get_etc1s_image_descs_image_flags(uint32_t level_index, uint32_t layer_index, uint32_t face_index) const;
867
868
// is_video() is only valid after start_transcoding() is called.
869
// For ETC1S data, if this returns true you must currently transcode the file from first to last frame, in order, without skipping any frames.
870
bool is_video() const { return m_is_video; }
871
872
// start_transcoding() MUST be called before calling transcode_image().
873
// This method decompresses the ETC1S global endpoint/selector codebooks, which is not free, so try to avoid calling it excessively.
874
bool start_transcoding();
875
876
// get_image_level_info() be called after init(), but the m_iframe_flag's won't be valid until start_transcoding() is called.
877
// You can call this method before calling transcode_image_level() to retrieve basic information about the mipmap level's dimensions, etc.
878
bool get_image_level_info(ktx2_image_level_info& level_info, uint32_t level_index, uint32_t layer_index, uint32_t face_index) const;
879
880
// transcode_image_level() transcodes a single 2D texture or cubemap face from the KTX2 file.
881
// Internally it uses the same low-level transcode API's as basisu_transcoder::transcode_image_level().
882
// If the file is UASTC and is supercompressed with Zstandard, and the file is a texture array or cubemap, it's highly recommended that each mipmap level is
883
// completely transcoded before switching to another level. Every time the mipmap level is changed all supercompressed level data must be decompressed using Zstandard as a single unit.
884
// Currently ETC1S videos must always be transcoded from first to last frame (or KTX2 "layer"), in order, with no skipping of frames.
885
// By default this method is not thread safe unless you specify a pointer to a user allocated thread-specific transcoder_state struct.
886
bool transcode_image_level(
887
uint32_t level_index, uint32_t layer_index, uint32_t face_index,
888
void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
889
basist::transcoder_texture_format fmt,
890
uint32_t decode_flags = 0, uint32_t output_row_pitch_in_blocks_or_pixels = 0, uint32_t output_rows_in_pixels = 0, int channel0 = -1, int channel1 = -1,
891
ktx2_transcoder_state *pState = nullptr);
892
893
private:
894
const uint8_t* m_pData;
895
uint32_t m_data_size;
896
897
ktx2_header m_header;
898
basisu::vector<ktx2_level_index> m_levels;
899
basisu::uint8_vec m_dfd;
900
key_value_vec m_key_values;
901
902
ktx2_etc1s_global_data_header m_etc1s_header;
903
basisu::vector<ktx2_etc1s_image_desc> m_etc1s_image_descs;
904
905
basist::basis_tex_format m_format;
906
907
uint32_t m_dfd_color_model;
908
ktx2_df_color_primaries m_dfd_color_prims;
909
uint32_t m_dfd_transfer_func;
910
uint32_t m_dfd_flags;
911
uint32_t m_dfd_samples;
912
ktx2_df_channel_id m_dfd_chan0, m_dfd_chan1;
913
914
basist::basisu_lowlevel_etc1s_transcoder m_etc1s_transcoder;
915
basist::basisu_lowlevel_uastc_transcoder m_uastc_transcoder;
916
917
ktx2_transcoder_state m_def_transcoder_state;
918
919
bool m_has_alpha;
920
bool m_is_video;
921
922
bool decompress_level_data(uint32_t level_index, basisu::uint8_vec& uncomp_data);
923
bool decompress_etc1s_global_data();
924
bool read_key_values();
925
};
926
927
#endif // BASISD_SUPPORT_KTX2
928
929
// Returns true if the transcoder was compiled with KTX2 support.
930
bool basisu_transcoder_supports_ktx2();
931
932
// Returns true if the transcoder was compiled with Zstandard support.
933
bool basisu_transcoder_supports_ktx2_zstd();
934
935
} // namespace basisu
936
937
938