Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/dds_ktx/include/dds_ktx.h
2 views
1
//
2
// Copyright 2018 Sepehr Taghdisian (septag@github). All rights reserved.
3
// License: https://github.com/septag/dds-ktx#license-bsd-2-clause
4
//
5
// Many parts of this code is taken from bimg library:
6
// https://github.com/bkaradzic/bimg
7
//
8
// Copyright 2011-2019 Branimir Karadzic. All rights reserved.
9
// License: https://github.com/bkaradzic/bimg#license-bsd-2-clause
10
//
11
// dds-ktx.h - v1.1.0 - Reader/Writer for DDS/KTX formats
12
// Parses DDS and KTX files from a memory blob, written in C99
13
//
14
// Supported formats:
15
// For supported formats, see ddsktx_format enum.
16
// Both KTX/DDS parser supports all formats defined in ddsktx_format
17
//
18
// Overriable macros:
19
// DDSKTX_API Define any function specifier for public functions (default: extern)
20
// ddsktx_memcpy default: memcpy(dst, src, size)
21
// ddsktx_memset default: memset(dst, v, size)
22
// ddsktx_assert default: assert(a)
23
// ddsktx_strcpy default: strcpy(dst, src)
24
// ddsktx_memcmp default: memcmp(ptr1, ptr2, size)
25
//
26
// API:
27
// bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err);
28
// Parses texture file and fills the ddsktx_texture_info struct
29
// Returns true if successfully parsed, false if failed with an error message inside ddsktx_error parameter (optional)
30
// After format is parsed, you can read the contents of ddsktx_format and create your GPU texture
31
// To get pointer to mips and slices see ddsktx_get_sub function
32
//
33
// void ddsktx_get_sub(const ddsktx_texture_info* tex, ddsktx_sub_data* buff,
34
// const void* file_data, int size,
35
// int array_idx, int slice_face_idx, int mip_idx);
36
// Gets sub-image data, form a parsed texture file
37
// user must provided the container object and the original file data which was passed to ddsktx_parse
38
// array_idx: array index (0..num_layers)
39
// slice_face_idx: depth-slice or cube-face index.
40
// if 'flags' have DDSKTX_TEXTURE_FLAG_CUBEMAP bit, then this value represents cube-face-index (0..DDSKTX_CUBE_FACE_COUNT)
41
// else it represents depth slice index (0..depth)
42
// mip_idx: mip index (0..num_mips-1 in ddsktx_texture_info)
43
//
44
// const char* ddsktx_format_str(ddsktx_format format);
45
// Converts a format enumeration to string
46
//
47
// bool ddsktx_format_compressed(ddsktx_format format);
48
// Returns true if format is compressed
49
//
50
// Example (for 2D textures only):
51
// int size;
52
// void* dds_data = load_file("test.dds", &size);
53
// assert(dds_data);
54
// ddsktx_texture_info tc = {0};
55
// if (ddsktx_parse(&tc, dds_data, size, NULL)) {
56
// assert(tc.depth == 1);
57
// assert(!(tc.flags & DDSKTX_TEXTURE_FLAG_CUBEMAP));
58
// assert(tc.num_layers == 1);
59
// // Create GPU texture from tc data
60
// for (int mip = 0; mip < tc.num_mips; mip++) {
61
// ddsktx_sub_data sub_data;
62
// ddsktx_get_sub(&tc, &sub_data, dds_data, size, 0, 0, mip);
63
// // Fill/Set texture sub resource data (mips in this case)
64
// }
65
// }
66
// free(dds_data); // memory must be valid during stc_ calls
67
//
68
// Version history:
69
// 0.9.0 Initial release, ktx is incomplete
70
// 1.0.0 Api change: ddsktx_sub_data
71
// Added KTX support
72
// 1.0.1 Fixed major bugs in KTX parsing
73
// 1.1.0 Fixed bugs in get_sub routine, refactored some parts, image-viewer example
74
//
75
// TODO
76
// Write KTX/DDS
77
// Read KTX metadata. currently it just stores the offset/size to the metadata block
78
//
79
80
#pragma once
81
82
#include <stddef.h>
83
#include <stdint.h>
84
#include <stdbool.h>
85
86
#ifndef DDSKTX_API
87
# ifdef __cplusplus
88
# define DDSKTX_API extern "C"
89
# else
90
# define DDSKTX_API
91
# endif
92
#endif
93
94
typedef struct ddsktx_sub_data
95
{
96
const void* buff;
97
int width;
98
int height;
99
int size_bytes;
100
int row_pitch_bytes;
101
} ddsktx_sub_data;
102
103
typedef enum ddsktx_format
104
{
105
DDSKTX_FORMAT_BC1, // DXT1
106
DDSKTX_FORMAT_BC2, // DXT3
107
DDSKTX_FORMAT_BC3, // DXT5
108
DDSKTX_FORMAT_BC4, // ATI1
109
DDSKTX_FORMAT_BC5, // ATI2
110
DDSKTX_FORMAT_BC6H, // BC6H
111
DDSKTX_FORMAT_BC7, // BC7
112
DDSKTX_FORMAT_ETC1, // ETC1 RGB8
113
DDSKTX_FORMAT_ETC2, // ETC2 RGB8
114
DDSKTX_FORMAT_ETC2A, // ETC2 RGBA8
115
DDSKTX_FORMAT_ETC2A1, // ETC2 RGB8A1
116
DDSKTX_FORMAT_PTC12, // PVRTC1 RGB 2bpp
117
DDSKTX_FORMAT_PTC14, // PVRTC1 RGB 4bpp
118
DDSKTX_FORMAT_PTC12A, // PVRTC1 RGBA 2bpp
119
DDSKTX_FORMAT_PTC14A, // PVRTC1 RGBA 4bpp
120
DDSKTX_FORMAT_PTC22, // PVRTC2 RGBA 2bpp
121
DDSKTX_FORMAT_PTC24, // PVRTC2 RGBA 4bpp
122
DDSKTX_FORMAT_ATC, // ATC RGB 4BPP
123
DDSKTX_FORMAT_ATCE, // ATCE RGBA 8 BPP explicit alpha
124
DDSKTX_FORMAT_ATCI, // ATCI RGBA 8 BPP interpolated alpha
125
DDSKTX_FORMAT_ASTC4x4, // ASTC 4x4 8.0 BPP
126
DDSKTX_FORMAT_ASTC5x5, // ASTC 5x5 5.12 BPP
127
DDSKTX_FORMAT_ASTC6x6, // ASTC 6x6 3.56 BPP
128
DDSKTX_FORMAT_ASTC8x5, // ASTC 8x5 3.20 BPP
129
DDSKTX_FORMAT_ASTC8x6, // ASTC 8x6 2.67 BPP
130
DDSKTX_FORMAT_ASTC10x5, // ASTC 10x5 2.56 BPP
131
_DDSKTX_FORMAT_COMPRESSED,
132
DDSKTX_FORMAT_A8,
133
DDSKTX_FORMAT_R8,
134
DDSKTX_FORMAT_RGBA8,
135
DDSKTX_FORMAT_RGBA8S,
136
DDSKTX_FORMAT_RG16,
137
DDSKTX_FORMAT_RGB8,
138
DDSKTX_FORMAT_R16,
139
DDSKTX_FORMAT_R32F,
140
DDSKTX_FORMAT_R16F,
141
DDSKTX_FORMAT_RG16F,
142
DDSKTX_FORMAT_RG16S,
143
DDSKTX_FORMAT_RGBA16F,
144
DDSKTX_FORMAT_RGBA16,
145
DDSKTX_FORMAT_BGRA8,
146
DDSKTX_FORMAT_RGB10A2,
147
DDSKTX_FORMAT_RG11B10F,
148
DDSKTX_FORMAT_RG8,
149
DDSKTX_FORMAT_RG8S,
150
_DDSKTX_FORMAT_COUNT
151
} ddsktx_format;
152
153
typedef enum ddsktx_texture_flags
154
{
155
DDSKTX_TEXTURE_FLAG_CUBEMAP = 0x01,
156
DDSKTX_TEXTURE_FLAG_SRGB = 0x02,
157
DDSKTX_TEXTURE_FLAG_ALPHA = 0x04, // Has alpha channel
158
DDSKTX_TEXTURE_FLAG_DDS = 0x08, // container was DDS file
159
DDSKTX_TEXTURE_FLAG_KTX = 0x10, // container was KTX file
160
DDSKTX_TEXTURE_FLAG_VOLUME = 0x20, // 3D volume
161
} ddsktx_texture_flags;
162
163
typedef struct ddsktx_texture_info
164
{
165
int data_offset; // start offset of pixel data
166
int size_bytes;
167
ddsktx_format format;
168
unsigned int flags; // ddsktx_texture_flags
169
int width;
170
int height;
171
int depth;
172
int num_layers;
173
int num_mips;
174
int bpp;
175
int metadata_offset; // ktx only
176
int metadata_size; // ktx only
177
} ddsktx_texture_info;
178
179
typedef enum ddsktx_cube_face
180
{
181
DDSKTX_CUBE_FACE_X_POSITIVE = 0,
182
DDSKTX_CUBE_FACE_X_NEGATIVE,
183
DDSKTX_CUBE_FACE_Y_POSITIVE,
184
DDSKTX_CUBE_FACE_Y_NEGATIVE,
185
DDSKTX_CUBE_FACE_Z_POSITIVE,
186
DDSKTX_CUBE_FACE_Z_NEGATIVE,
187
DDSKTX_CUBE_FACE_COUNT
188
} ddsktx_cube_face;
189
190
typedef struct ddsktx_error
191
{
192
char msg[256];
193
} ddsktx_error;
194
195
#ifdef __cplusplus
196
# define ddsktx_default(_v) =_v
197
#else
198
# define ddsktx_default(_v)
199
#endif
200
201
DDSKTX_API bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err ddsktx_default(NULL));
202
DDSKTX_API void ddsktx_get_sub(const ddsktx_texture_info* tex, ddsktx_sub_data* buff,
203
const void* file_data, int size,
204
int array_idx, int slice_face_idx, int mip_idx);
205
DDSKTX_API const char* ddsktx_format_str(ddsktx_format format);
206
DDSKTX_API bool ddsktx_format_compressed(ddsktx_format format);
207
208
////////////////////////////////////////////////////////////////////////////////////////////////////
209
// Implementation
210
#ifdef DDSKTX_IMPLEMENT
211
212
#define stc__makefourcc(_a, _b, _c, _d) ( ( (uint32_t)(_a) | ( (uint32_t)(_b) << 8) | \
213
( (uint32_t)(_c) << 16) | ( (uint32_t)(_d) << 24) ) )
214
215
// DDS: https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dx-graphics-dds-pguide
216
#define DDSKTX__DDS_HEADER_SIZE 124
217
#define DDSKTX__DDS_MAGIC stc__makefourcc('D', 'D', 'S', ' ')
218
#define DDSKTX__DDS_DXT1 stc__makefourcc('D', 'X', 'T', '1')
219
#define DDSKTX__DDS_DXT2 stc__makefourcc('D', 'X', 'T', '2')
220
#define DDSKTX__DDS_DXT3 stc__makefourcc('D', 'X', 'T', '3')
221
#define DDSKTX__DDS_DXT4 stc__makefourcc('D', 'X', 'T', '4')
222
#define DDSKTX__DDS_DXT5 stc__makefourcc('D', 'X', 'T', '5')
223
#define DDSKTX__DDS_ATI1 stc__makefourcc('A', 'T', 'I', '1')
224
#define DDSKTX__DDS_BC4U stc__makefourcc('B', 'C', '4', 'U')
225
#define DDSKTX__DDS_ATI2 stc__makefourcc('A', 'T', 'I', '2')
226
#define DDSKTX__DDS_BC5U stc__makefourcc('B', 'C', '5', 'U')
227
#define DDSKTX__DDS_DX10 stc__makefourcc('D', 'X', '1', '0')
228
229
#define DDSKTX__DDS_ETC1 stc__makefourcc('E', 'T', 'C', '1')
230
#define DDSKTX__DDS_ETC2 stc__makefourcc('E', 'T', 'C', '2')
231
#define DDSKTX__DDS_ET2A stc__makefourcc('E', 'T', '2', 'A')
232
#define DDSKTX__DDS_PTC2 stc__makefourcc('P', 'T', 'C', '2')
233
#define DDSKTX__DDS_PTC4 stc__makefourcc('P', 'T', 'C', '4')
234
#define DDSKTX__DDS_ATC stc__makefourcc('A', 'T', 'C', ' ')
235
#define DDSKTX__DDS_ATCE stc__makefourcc('A', 'T', 'C', 'E')
236
#define DDSKTX__DDS_ATCI stc__makefourcc('A', 'T', 'C', 'I')
237
#define DDSKTX__DDS_ASTC4x4 stc__makefourcc('A', 'S', '4', '4')
238
#define DDSKTX__DDS_ASTC5x5 stc__makefourcc('A', 'S', '5', '5')
239
#define DDSKTX__DDS_ASTC6x6 stc__makefourcc('A', 'S', '6', '6')
240
#define DDSKTX__DDS_ASTC8x5 stc__makefourcc('A', 'S', '8', '5')
241
#define DDSKTX__DDS_ASTC8x6 stc__makefourcc('A', 'S', '8', '6')
242
#define DDSKTX__DDS_ASTC10x5 stc__makefourcc('A', 'S', ':', '5')
243
244
#define DDSKTX__DDS_R8G8B8 20
245
#define DDSKTX__DDS_A8R8G8B8 21
246
#define DDSKTX__DDS_R5G6B5 23
247
#define DDSKTX__DDS_A1R5G5B5 25
248
#define DDSKTX__DDS_A4R4G4B4 26
249
#define DDSKTX__DDS_A2B10G10R10 31
250
#define DDSKTX__DDS_G16R16 34
251
#define DDSKTX__DDS_A2R10G10B10 35
252
#define DDSKTX__DDS_A16B16G16R16 36
253
#define DDSKTX__DDS_A8L8 51
254
#define DDSKTX__DDS_R16F 111
255
#define DDSKTX__DDS_G16R16F 112
256
#define DDSKTX__DDS_A16B16G16R16F 113
257
#define DDSKTX__DDS_R32F 114
258
#define DDSKTX__DDS_G32R32F 115
259
#define DDSKTX__DDS_A32B32G32R32F 116
260
261
#define DDSKTX__DDS_FORMAT_R32G32B32A32_FLOAT 2
262
#define DDSKTX__DDS_FORMAT_R32G32B32A32_UINT 3
263
#define DDSKTX__DDS_FORMAT_R16G16B16A16_FLOAT 10
264
#define DDSKTX__DDS_FORMAT_R16G16B16A16_UNORM 11
265
#define DDSKTX__DDS_FORMAT_R16G16B16A16_UINT 12
266
#define DDSKTX__DDS_FORMAT_R32G32_FLOAT 16
267
#define DDSKTX__DDS_FORMAT_R32G32_UINT 17
268
#define DDSKTX__DDS_FORMAT_R10G10B10A2_UNORM 24
269
#define DDSKTX__DDS_FORMAT_R11G11B10_FLOAT 26
270
#define DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM 28
271
#define DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM_SRGB 29
272
#define DDSKTX__DDS_FORMAT_R16G16_FLOAT 34
273
#define DDSKTX__DDS_FORMAT_R16G16_UNORM 35
274
#define DDSKTX__DDS_FORMAT_R32_FLOAT 41
275
#define DDSKTX__DDS_FORMAT_R32_UINT 42
276
#define DDSKTX__DDS_FORMAT_R8G8_UNORM 49
277
#define DDSKTX__DDS_FORMAT_R16_FLOAT 54
278
#define DDSKTX__DDS_FORMAT_R16_UNORM 56
279
#define DDSKTX__DDS_FORMAT_R8_UNORM 61
280
#define DDSKTX__DDS_FORMAT_R1_UNORM 66
281
#define DDSKTX__DDS_FORMAT_BC1_UNORM 71
282
#define DDSKTX__DDS_FORMAT_BC1_UNORM_SRGB 72
283
#define DDSKTX__DDS_FORMAT_BC2_UNORM 74
284
#define DDSKTX__DDS_FORMAT_BC2_UNORM_SRGB 75
285
#define DDSKTX__DDS_FORMAT_BC3_UNORM 77
286
#define DDSKTX__DDS_FORMAT_BC3_UNORM_SRGB 78
287
#define DDSKTX__DDS_FORMAT_BC4_UNORM 80
288
#define DDSKTX__DDS_FORMAT_BC5_UNORM 83
289
#define DDSKTX__DDS_FORMAT_B5G6R5_UNORM 85
290
#define DDSKTX__DDS_FORMAT_B5G5R5A1_UNORM 86
291
#define DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM 87
292
#define DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM_SRGB 91
293
#define DDSKTX__DDS_FORMAT_BC6H_SF16 96
294
#define DDSKTX__DDS_FORMAT_BC7_UNORM 98
295
#define DDSKTX__DDS_FORMAT_BC7_UNORM_SRGB 99
296
#define DDSKTX__DDS_FORMAT_B4G4R4A4_UNORM 115
297
298
#define DDSKTX__DDS_DX10_DIMENSION_TEXTURE2D 3
299
#define DDSKTX__DDS_DX10_DIMENSION_TEXTURE3D 4
300
#define DDSKTX__DDS_DX10_MISC_TEXTURECUBE 4
301
302
#define DDSKTX__DDSD_CAPS 0x00000001
303
#define DDSKTX__DDSD_HEIGHT 0x00000002
304
#define DDSKTX__DDSD_WIDTH 0x00000004
305
#define DDSKTX__DDSD_PITCH 0x00000008
306
#define DDSKTX__DDSD_PIXELFORMAT 0x00001000
307
#define DDSKTX__DDSD_MIPMAPCOUNT 0x00020000
308
#define DDSKTX__DDSD_LINEARSIZE 0x00080000
309
#define DDSKTX__DDSD_DEPTH 0x00800000
310
311
#define DDSKTX__DDPF_ALPHAPIXELS 0x00000001
312
#define DDSKTX__DDPF_ALPHA 0x00000002
313
#define DDSKTX__DDPF_FOURCC 0x00000004
314
#define DDSKTX__DDPF_INDEXED 0x00000020
315
#define DDSKTX__DDPF_RGB 0x00000040
316
#define DDSKTX__DDPF_YUV 0x00000200
317
#define DDSKTX__DDPF_LUMINANCE 0x00020000
318
#define DDSKTX__DDPF_BUMPDUDV 0x00080000
319
320
#define DDSKTX__DDSCAPS_COMPLEX 0x00000008
321
#define DDSKTX__DDSCAPS_TEXTURE 0x00001000
322
#define DDSKTX__DDSCAPS_MIPMAP 0x00400000
323
324
#define DDSKTX__DDSCAPS2_VOLUME 0x00200000
325
#define DDSKTX__DDSCAPS2_CUBEMAP 0x00000200
326
#define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
327
#define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
328
#define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
329
#define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
330
#define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
331
#define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
332
333
#define DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES (0 \
334
| DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEX \
335
| DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEX \
336
| DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEY \
337
| DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEY \
338
| DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEZ \
339
| DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEZ )
340
341
#pragma pack(push, 1)
342
typedef struct ddsktx__dds_pixel_format
343
{
344
uint32_t size;
345
uint32_t flags;
346
uint32_t fourcc;
347
uint32_t rgb_bit_count;
348
uint32_t bit_mask[4];
349
} ddsktx__dds_pixel_format;
350
351
// https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dds-header
352
typedef struct ddsktx__dds_header
353
{
354
uint32_t size;
355
uint32_t flags;
356
uint32_t height;
357
uint32_t width;
358
uint32_t pitch_lin_size;
359
uint32_t depth;
360
uint32_t mip_count;
361
uint32_t reserved1[11];
362
ddsktx__dds_pixel_format pixel_format;
363
uint32_t caps1;
364
uint32_t caps2;
365
uint32_t caps3;
366
uint32_t caps4;
367
uint32_t reserved2;
368
} ddsktx__dds_header;
369
370
// https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dds-header-dxt10
371
typedef struct ddsktx__dds_header_dxgi
372
{
373
uint32_t dxgi_format;
374
uint32_t dimension;
375
uint32_t misc_flags;
376
uint32_t array_size;
377
uint32_t misc_flags2;
378
} ddsktx__dds_header_dxgi;
379
380
typedef struct ddsktx__ktx_header
381
{
382
uint8_t id[8];
383
uint32_t endianess;
384
uint32_t type;
385
uint32_t type_size;
386
uint32_t format;
387
uint32_t internal_format;
388
uint32_t base_internal_format;
389
uint32_t width;
390
uint32_t height;
391
uint32_t depth;
392
uint32_t array_count;
393
uint32_t face_count;
394
uint32_t mip_count;
395
uint32_t metadata_size;
396
} ddsktx__ktx_header;
397
#pragma pack(pop)
398
399
typedef struct ddsktx__dds_translate_fourcc_format
400
{
401
uint32_t dds_format;
402
ddsktx_format format;
403
bool srgb;
404
} ddsktx__dds_translate_fourcc_format;
405
406
typedef struct ddsktx__dds_translate_pixel_format
407
{
408
uint32_t bit_count;
409
uint32_t flags;
410
uint32_t bit_mask[4];
411
ddsktx_format format;
412
} ddsktx__dds_translate_pixel_format;
413
414
typedef struct ddsktx__mem_reader
415
{
416
const uint8_t* buff;
417
int total;
418
int offset;
419
} ddsktx__mem_reader;
420
421
typedef struct ddsktx__block_info
422
{
423
uint8_t bpp;
424
uint8_t block_width;
425
uint8_t block_height;
426
uint8_t block_size;
427
uint8_t min_block_x;
428
uint8_t min_block_y;
429
uint8_t depth_bits;
430
uint8_t stencil_bits;
431
uint8_t r_bits;
432
uint8_t g_bits;
433
uint8_t b_bits;
434
uint8_t a_bits;
435
uint8_t encoding;
436
} ddsktx__block_info;
437
438
#ifndef ddsktx_memcpy
439
# include <string.h>
440
# define ddsktx_memcpy(_dst, _src, _size) memcpy((_dst), (_src), (_size))
441
#endif
442
443
#ifndef ddsktx_memset
444
# include <string.h>
445
# define ddsktx_memset(_dst, _v, _size) memset((_dst), (_v), (_size))
446
#endif
447
448
#ifndef ddsktx_assert
449
# include <assert.h>
450
# define ddsktx_assert(_a) assert(_a)
451
#endif
452
453
#ifndef ddsktx_strcpy
454
# include <string.h>
455
# ifdef _MSC_VER
456
# define ddsktx_strcpy(_dst, _src) strcpy_s((_dst), sizeof(_dst), (_src))
457
# else
458
# define ddsktx_strcpy(_dst, _src) strcpy((_dst), (_src))
459
# endif
460
#endif
461
462
#ifndef ddsktx_memcmp
463
# include <string.h>
464
# define ddsktx_memcmp(_ptr1, _ptr2, _num) memcmp((_ptr1), (_ptr2), (_num))
465
#endif
466
467
#define ddsktx__max(a, b) ((a) > (b) ? (a) : (b))
468
#define ddsktx__min(a, b) ((a) < (b) ? (a) : (b))
469
#define ddsktx__align_mask(_value, _mask) (((_value)+(_mask)) & ((~0)&(~(_mask))))
470
#define ddsktx__err(_err, _msg) if (_err) ddsktx_strcpy(_err->msg, _msg); return false
471
472
static const ddsktx__dds_translate_fourcc_format k__translate_dds_fourcc[] = {
473
{ DDSKTX__DDS_DXT1, DDSKTX_FORMAT_BC1, false },
474
{ DDSKTX__DDS_DXT2, DDSKTX_FORMAT_BC2, false },
475
{ DDSKTX__DDS_DXT3, DDSKTX_FORMAT_BC2, false },
476
{ DDSKTX__DDS_DXT4, DDSKTX_FORMAT_BC3, false },
477
{ DDSKTX__DDS_DXT5, DDSKTX_FORMAT_BC3, false },
478
{ DDSKTX__DDS_ATI1, DDSKTX_FORMAT_BC4, false },
479
{ DDSKTX__DDS_BC4U, DDSKTX_FORMAT_BC4, false },
480
{ DDSKTX__DDS_ATI2, DDSKTX_FORMAT_BC5, false },
481
{ DDSKTX__DDS_BC5U, DDSKTX_FORMAT_BC5, false },
482
{ DDSKTX__DDS_ETC1, DDSKTX_FORMAT_ETC1, false },
483
{ DDSKTX__DDS_ETC2, DDSKTX_FORMAT_ETC2, false },
484
{ DDSKTX__DDS_ET2A, DDSKTX_FORMAT_ETC2A, false },
485
{ DDSKTX__DDS_PTC2, DDSKTX_FORMAT_PTC12A, false },
486
{ DDSKTX__DDS_PTC4, DDSKTX_FORMAT_PTC14A, false },
487
{ DDSKTX__DDS_ATC , DDSKTX_FORMAT_ATC, false },
488
{ DDSKTX__DDS_ATCE, DDSKTX_FORMAT_ATCE, false },
489
{ DDSKTX__DDS_ATCI, DDSKTX_FORMAT_ATCI, false },
490
{ DDSKTX__DDS_ASTC4x4, DDSKTX_FORMAT_ASTC4x4, false },
491
{ DDSKTX__DDS_ASTC5x5, DDSKTX_FORMAT_ASTC5x5, false },
492
{ DDSKTX__DDS_ASTC6x6, DDSKTX_FORMAT_ASTC6x6, false },
493
{ DDSKTX__DDS_ASTC8x5, DDSKTX_FORMAT_ASTC8x5, false },
494
{ DDSKTX__DDS_ASTC8x6, DDSKTX_FORMAT_ASTC8x6, false },
495
{ DDSKTX__DDS_ASTC10x5, DDSKTX_FORMAT_ASTC10x5, false },
496
{ DDSKTX__DDS_A16B16G16R16, DDSKTX_FORMAT_RGBA16, false },
497
{ DDSKTX__DDS_A16B16G16R16F, DDSKTX_FORMAT_RGBA16F, false },
498
{ DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, DDSKTX_FORMAT_BGRA8, false },
499
{ DDSKTX__DDPF_INDEXED, DDSKTX_FORMAT_R8, false },
500
{ DDSKTX__DDPF_LUMINANCE, DDSKTX_FORMAT_R8, false },
501
{ DDSKTX__DDPF_ALPHA, DDSKTX_FORMAT_R8, false },
502
{ DDSKTX__DDS_R16F, DDSKTX_FORMAT_R16F, false },
503
{ DDSKTX__DDS_R32F, DDSKTX_FORMAT_R32F, false },
504
{ DDSKTX__DDS_A8L8, DDSKTX_FORMAT_RG8, false },
505
{ DDSKTX__DDS_G16R16, DDSKTX_FORMAT_RG16, false },
506
{ DDSKTX__DDS_G16R16F, DDSKTX_FORMAT_RG16F, false },
507
{ DDSKTX__DDS_R8G8B8, DDSKTX_FORMAT_RGB8, false },
508
{ DDSKTX__DDS_A8R8G8B8, DDSKTX_FORMAT_BGRA8, false },
509
{ DDSKTX__DDS_A16B16G16R16, DDSKTX_FORMAT_RGBA16, false },
510
{ DDSKTX__DDS_A16B16G16R16F, DDSKTX_FORMAT_RGBA16F, false },
511
{ DDSKTX__DDS_A2B10G10R10, DDSKTX_FORMAT_RGB10A2, false },
512
};
513
514
static const ddsktx__dds_translate_fourcc_format k__translate_dxgi[] = {
515
{ DDSKTX__DDS_FORMAT_BC1_UNORM, DDSKTX_FORMAT_BC1, false },
516
{ DDSKTX__DDS_FORMAT_BC1_UNORM_SRGB, DDSKTX_FORMAT_BC1, true },
517
{ DDSKTX__DDS_FORMAT_BC2_UNORM, DDSKTX_FORMAT_BC2, false },
518
{ DDSKTX__DDS_FORMAT_BC2_UNORM_SRGB, DDSKTX_FORMAT_BC2, true },
519
{ DDSKTX__DDS_FORMAT_BC3_UNORM, DDSKTX_FORMAT_BC3, false },
520
{ DDSKTX__DDS_FORMAT_BC3_UNORM_SRGB, DDSKTX_FORMAT_BC3, true },
521
{ DDSKTX__DDS_FORMAT_BC4_UNORM, DDSKTX_FORMAT_BC4, false },
522
{ DDSKTX__DDS_FORMAT_BC5_UNORM, DDSKTX_FORMAT_BC5, false },
523
{ DDSKTX__DDS_FORMAT_BC6H_SF16, DDSKTX_FORMAT_BC6H, false },
524
{ DDSKTX__DDS_FORMAT_BC7_UNORM, DDSKTX_FORMAT_BC7, false },
525
{ DDSKTX__DDS_FORMAT_BC7_UNORM_SRGB, DDSKTX_FORMAT_BC7, true },
526
527
{ DDSKTX__DDS_FORMAT_R8_UNORM, DDSKTX_FORMAT_R8, false },
528
{ DDSKTX__DDS_FORMAT_R16_UNORM, DDSKTX_FORMAT_R16, false },
529
{ DDSKTX__DDS_FORMAT_R16_FLOAT, DDSKTX_FORMAT_R16F, false },
530
{ DDSKTX__DDS_FORMAT_R32_FLOAT, DDSKTX_FORMAT_R32F, false },
531
{ DDSKTX__DDS_FORMAT_R8G8_UNORM, DDSKTX_FORMAT_RG8, false },
532
{ DDSKTX__DDS_FORMAT_R16G16_UNORM, DDSKTX_FORMAT_RG16, false },
533
{ DDSKTX__DDS_FORMAT_R16G16_FLOAT, DDSKTX_FORMAT_RG16F, false },
534
{ DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM, DDSKTX_FORMAT_BGRA8, false },
535
{ DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM_SRGB, DDSKTX_FORMAT_BGRA8, true },
536
{ DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM, DDSKTX_FORMAT_RGBA8, false },
537
{ DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM_SRGB, DDSKTX_FORMAT_RGBA8, true },
538
{ DDSKTX__DDS_FORMAT_R16G16B16A16_UNORM, DDSKTX_FORMAT_RGBA16, false },
539
{ DDSKTX__DDS_FORMAT_R16G16B16A16_FLOAT, DDSKTX_FORMAT_RGBA16F, false },
540
{ DDSKTX__DDS_FORMAT_R10G10B10A2_UNORM, DDSKTX_FORMAT_RGB10A2, false },
541
{ DDSKTX__DDS_FORMAT_R11G11B10_FLOAT, DDSKTX_FORMAT_RG11B10F, false },
542
};
543
544
static const ddsktx__dds_translate_pixel_format k__translate_dds_pixel[] = {
545
{ 8, DDSKTX__DDPF_LUMINANCE, { 0x000000ff, 0x00000000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_R8 },
546
{ 16, DDSKTX__DDPF_BUMPDUDV, { 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG8S },
547
{ 24, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_RGB8 },
548
{ 24, DDSKTX__DDPF_RGB, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }, DDSKTX_FORMAT_RGB8 },
549
{ 32, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_BGRA8 },
550
{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, DDSKTX_FORMAT_RGBA8 },
551
{ 32, DDSKTX__DDPF_BUMPDUDV, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, DDSKTX_FORMAT_RGBA8S },
552
{ 32, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSKTX_FORMAT_BGRA8 },
553
{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSKTX_FORMAT_BGRA8 }, // D3DFMT_A8R8G8B8
554
{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_BGRA8 }, // D3DFMT_X8R8G8B8
555
{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 }, DDSKTX_FORMAT_RGB10A2 },
556
{ 32, DDSKTX__DDPF_RGB, { 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG16 },
557
{ 32, DDSKTX__DDPF_BUMPDUDV, { 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG16S }
558
};
559
560
typedef enum ddsktx__encode_type
561
{
562
DDSKTX__ENCODE_UNORM,
563
DDSKTX__ENCODE_SNORM,
564
DDSKTX__ENCODE_FLOAT,
565
DDSKTX__ENCODE_INT,
566
DDSKTX__ENCODE_UINT,
567
DDSKTX__ENCODE_COUNT
568
} ddsktx__encode_type;
569
570
static const ddsktx__block_info k__block_info[] =
571
{
572
// +-------------------------------------------- bits per pixel
573
// | +----------------------------------------- block width
574
// | | +-------------------------------------- block height
575
// | | | +---------------------------------- block size
576
// | | | | +------------------------------- min blocks x
577
// | | | | | +---------------------------- min blocks y
578
// | | | | | | +------------------------ depth bits
579
// | | | | | | | +--------------------- stencil bits
580
// | | | | | | | | +---+---+---+----- r, g, b, a bits
581
// | | | | | | | | r g b a +-- encoding type
582
// | | | | | | | | | | | | |
583
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC1
584
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC2
585
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC3
586
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC4
587
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC5
588
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // BC6H
589
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC7
590
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC1
591
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2
592
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2A
593
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2A1
594
{ 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC12
595
{ 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC14
596
{ 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC12A
597
{ 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC14A
598
{ 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC22
599
{ 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC24
600
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATC
601
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATCE
602
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATCI
603
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC4x4
604
{ 6, 5, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC5x5
605
{ 4, 6, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC6x6
606
{ 4, 8, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC8x5
607
{ 3, 8, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC8x6
608
{ 3, 10, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC10x5
609
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_COUNT) }, // Unknown
610
{ 8, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // A8
611
{ 8, 1, 1, 1, 1, 1, 0, 0, 8, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // R8
612
{ 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGBA8
613
{ 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_SNORM) }, // RGBA8S
614
{ 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG16
615
{ 24, 1, 1, 3, 1, 1, 0, 0, 8, 8, 8, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGB8
616
{ 16, 1, 1, 2, 1, 1, 0, 0, 16, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // R16
617
{ 32, 1, 1, 4, 1, 1, 0, 0, 32, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // R32F
618
{ 16, 1, 1, 2, 1, 1, 0, 0, 16, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // R16F
619
{ 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // RG16F
620
{ 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_SNORM) }, // RG16S
621
{ 64, 1, 1, 8, 1, 1, 0, 0, 16, 16, 16, 16, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // RGBA16F
622
{ 64, 1, 1, 8, 1, 1, 0, 0, 16, 16, 16, 16, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGBA16
623
{ 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BGRA8
624
{ 32, 1, 1, 4, 1, 1, 0, 0, 10, 10, 10, 2, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGB10A2
625
{ 32, 1, 1, 4, 1, 1, 0, 0, 11, 11, 10, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG11B10F
626
{ 16, 1, 1, 2, 1, 1, 0, 0, 8, 8, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG8
627
{ 16, 1, 1, 2, 1, 1, 0, 0, 8, 8, 0, 0, (uint8_t)(DDSKTX__ENCODE_SNORM) } // RG8S
628
};
629
630
// KTX: https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
631
#define DDSKTX__KTX_MAGIC stc__makefourcc(0xAB, 'K', 'T', 'X')
632
#define DDSKTX__KTX_HEADER_SIZE 60 // actual header size is 64, but we read 4 bytes for the 'magic'
633
634
#define DDSKTX__KTX_ETC1_RGB8_OES 0x8D64
635
#define DDSKTX__KTX_COMPRESSED_R11_EAC 0x9270
636
#define DDSKTX__KTX_COMPRESSED_SIGNED_R11_EAC 0x9271
637
#define DDSKTX__KTX_COMPRESSED_RG11_EAC 0x9272
638
#define DDSKTX__KTX_COMPRESSED_SIGNED_RG11_EAC 0x9273
639
#define DDSKTX__KTX_COMPRESSED_RGB8_ETC2 0x9274
640
#define DDSKTX__KTX_COMPRESSED_SRGB8_ETC2 0x9275
641
#define DDSKTX__KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
642
#define DDSKTX__KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
643
#define DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC 0x9278
644
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
645
#define DDSKTX__KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
646
#define DDSKTX__KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
647
#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
648
#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
649
#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137
650
#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
651
#define DDSKTX__KTX_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
652
#define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
653
#define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
654
#define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
655
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
656
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
657
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
658
#define DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
659
#define DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
660
#define DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
661
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
662
#define DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
663
#define DDSKTX__KTX_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
664
#define DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
665
#define DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55
666
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56
667
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57
668
#define DDSKTX__KTX_ATC_RGB_AMD 0x8C92
669
#define DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
670
#define DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
671
#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_4x4_KHR 0x93B0
672
#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_5x5_KHR 0x93B2
673
#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_6x6_KHR 0x93B4
674
#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x5_KHR 0x93B5
675
#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x6_KHR 0x93B6
676
#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_10x5_KHR 0x93B8
677
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_4x4_KHR 0x93D0
678
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_5x5_KHR 0x93D2
679
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_6x6_KHR 0x93D4
680
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_8x5_KHR 0x93D5
681
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_8x6_KHR 0x93D6
682
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_10x5_KHR 0x93D8
683
684
#define DDSKTX__KTX_A8 0x803C
685
#define DDSKTX__KTX_R8 0x8229
686
#define DDSKTX__KTX_R16 0x822A
687
#define DDSKTX__KTX_RG8 0x822B
688
#define DDSKTX__KTX_RG16 0x822C
689
#define DDSKTX__KTX_R16F 0x822D
690
#define DDSKTX__KTX_R32F 0x822E
691
#define DDSKTX__KTX_RG16F 0x822F
692
#define DDSKTX__KTX_RG32F 0x8230
693
#define DDSKTX__KTX_RGBA8 0x8058
694
#define DDSKTX__KTX_RGBA16 0x805B
695
#define DDSKTX__KTX_RGBA16F 0x881A
696
#define DDSKTX__KTX_R32UI 0x8236
697
#define DDSKTX__KTX_RG32UI 0x823C
698
#define DDSKTX__KTX_RGBA32UI 0x8D70
699
#define DDSKTX__KTX_RGBA32F 0x8814
700
#define DDSKTX__KTX_RGB565 0x8D62
701
#define DDSKTX__KTX_RGBA4 0x8056
702
#define DDSKTX__KTX_RGB5_A1 0x8057
703
#define DDSKTX__KTX_RGB10_A2 0x8059
704
#define DDSKTX__KTX_R8I 0x8231
705
#define DDSKTX__KTX_R8UI 0x8232
706
#define DDSKTX__KTX_R16I 0x8233
707
#define DDSKTX__KTX_R16UI 0x8234
708
#define DDSKTX__KTX_R32I 0x8235
709
#define DDSKTX__KTX_R32UI 0x8236
710
#define DDSKTX__KTX_RG8I 0x8237
711
#define DDSKTX__KTX_RG8UI 0x8238
712
#define DDSKTX__KTX_RG16I 0x8239
713
#define DDSKTX__KTX_RG16UI 0x823A
714
#define DDSKTX__KTX_RG32I 0x823B
715
#define DDSKTX__KTX_RG32UI 0x823C
716
#define DDSKTX__KTX_R8_SNORM 0x8F94
717
#define DDSKTX__KTX_RG8_SNORM 0x8F95
718
#define DDSKTX__KTX_RGB8_SNORM 0x8F96
719
#define DDSKTX__KTX_RGBA8_SNORM 0x8F97
720
#define DDSKTX__KTX_R16_SNORM 0x8F98
721
#define DDSKTX__KTX_RG16_SNORM 0x8F99
722
#define DDSKTX__KTX_RGB16_SNORM 0x8F9A
723
#define DDSKTX__KTX_RGBA16_SNORM 0x8F9B
724
#define DDSKTX__KTX_SRGB8 0x8C41
725
#define DDSKTX__KTX_SRGB8_ALPHA8 0x8C43
726
#define DDSKTX__KTX_RGBA32UI 0x8D70
727
#define DDSKTX__KTX_RGB32UI 0x8D71
728
#define DDSKTX__KTX_RGBA16UI 0x8D76
729
#define DDSKTX__KTX_RGB16UI 0x8D77
730
#define DDSKTX__KTX_RGBA8UI 0x8D7C
731
#define DDSKTX__KTX_RGB8UI 0x8D7D
732
#define DDSKTX__KTX_RGBA32I 0x8D82
733
#define DDSKTX__KTX_RGB32I 0x8D83
734
#define DDSKTX__KTX_RGBA16I 0x8D88
735
#define DDSKTX__KTX_RGB16I 0x8D89
736
#define DDSKTX__KTX_RGBA8I 0x8D8E
737
#define DDSKTX__KTX_RGB8 0x8051
738
#define DDSKTX__KTX_RGB8I 0x8D8F
739
#define DDSKTX__KTX_RGB9_E5 0x8C3D
740
#define DDSKTX__KTX_R11F_G11F_B10F 0x8C3A
741
742
#define DDSKTX__KTX_ZERO 0
743
#define DDSKTX__KTX_RED 0x1903
744
#define DDSKTX__KTX_ALPHA 0x1906
745
#define DDSKTX__KTX_RGB 0x1907
746
#define DDSKTX__KTX_RGBA 0x1908
747
#define DDSKTX__KTX_BGRA 0x80E1
748
#define DDSKTX__KTX_RG 0x8227
749
750
#define DDSKTX__KTX_BYTE 0x1400
751
#define DDSKTX__KTX_UNSIGNED_BYTE 0x1401
752
#define DDSKTX__KTX_SHORT 0x1402
753
#define DDSKTX__KTX_UNSIGNED_SHORT 0x1403
754
#define DDSKTX__KTX_INT 0x1404
755
#define DDSKTX__KTX_UNSIGNED_INT 0x1405
756
#define DDSKTX__KTX_FLOAT 0x1406
757
#define DDSKTX__KTX_HALF_FLOAT 0x140B
758
#define DDSKTX__KTX_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
759
#define DDSKTX__KTX_UNSIGNED_SHORT_5_6_5 0x8363
760
#define DDSKTX__KTX_UNSIGNED_SHORT_4_4_4_4 0x8033
761
#define DDSKTX__KTX_UNSIGNED_SHORT_5_5_5_1 0x8034
762
#define DDSKTX__KTX_UNSIGNED_INT_2_10_10_10_REV 0x8368
763
#define DDSKTX__KTX_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
764
765
typedef struct ddsktx__ktx_format_info
766
{
767
uint32_t internal_fmt;
768
uint32_t internal_fmt_srgb;
769
uint32_t fmt;
770
uint32_t type;
771
} ddsktx__ktx_format_info;
772
773
typedef struct ddsktx__ktx_format_info2
774
{
775
uint32_t internal_fmt;
776
ddsktx_format format;
777
} ddsktx__ktx_format_info2;
778
779
static const ddsktx__ktx_format_info k__translate_ktx_fmt[] = {
780
{ DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT, DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT, DDSKTX__KTX_ZERO, }, // BC1
781
{ DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT, DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT, DDSKTX__KTX_ZERO, }, // BC2
782
{ DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT, DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT, DDSKTX__KTX_ZERO, }, // BC3
783
{ DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT, DDSKTX__KTX_ZERO, }, // BC4
784
{ DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, DDSKTX__KTX_ZERO, }, // BC5
785
{ DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, DDSKTX__KTX_ZERO, }, // BC6H
786
{ DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB, DDSKTX__KTX_ZERO, }, // BC7
787
{ DDSKTX__KTX_ETC1_RGB8_OES, DDSKTX__KTX_ZERO, DDSKTX__KTX_ETC1_RGB8_OES, DDSKTX__KTX_ZERO, }, // ETC1
788
{ DDSKTX__KTX_COMPRESSED_RGB8_ETC2, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGB8_ETC2, DDSKTX__KTX_ZERO, }, // ETC2
789
{ DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC, DDSKTX__KTX_COMPRESSED_SRGB8_ETC2, DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC, DDSKTX__KTX_ZERO, }, // ETC2A
790
{ DDSKTX__KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DDSKTX__KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DDSKTX__KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DDSKTX__KTX_ZERO, }, // ETC2A1
791
{ DDSKTX__KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT, DDSKTX__KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, DDSKTX__KTX_ZERO, }, // PTC12
792
{ DDSKTX__KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT, DDSKTX__KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, DDSKTX__KTX_ZERO, }, // PTC14
793
{ DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, DDSKTX__KTX_ZERO, }, // PTC12A
794
{ DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, DDSKTX__KTX_ZERO, }, // PTC14A
795
{ DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, DDSKTX__KTX_ZERO, }, // PTC22
796
{ DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, DDSKTX__KTX_ZERO, }, // PTC24
797
{ DDSKTX__KTX_ATC_RGB_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGB_AMD, DDSKTX__KTX_ZERO, }, // ATC
798
{ DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, DDSKTX__KTX_ZERO, }, // ATCE
799
{ DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, DDSKTX__KTX_ZERO, }, // ATCI
800
{ DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_4x4_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_4x4_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_4x4_KHR, DDSKTX__KTX_ZERO, }, // ASTC4x4
801
{ DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_5x5_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_5x5_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_5x5_KHR, DDSKTX__KTX_ZERO, }, // ASTC5x5
802
{ DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_6x6_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_6x6_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_6x6_KHR, DDSKTX__KTX_ZERO, }, // ASTC6x6
803
{ DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x5_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_8x5_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x5_KHR, DDSKTX__KTX_ZERO, }, // ASTC8x5
804
{ DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x6_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_8x6_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x6_KHR, DDSKTX__KTX_ZERO, }, // ASTC8x6
805
{ DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_10x5_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_10x5_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_10x5_KHR, DDSKTX__KTX_ZERO, }, // ASTC10x5
806
{ DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, }, // Unknown
807
{ DDSKTX__KTX_ALPHA, DDSKTX__KTX_ZERO, DDSKTX__KTX_ALPHA, DDSKTX__KTX_UNSIGNED_BYTE, }, // A8
808
{ DDSKTX__KTX_R8, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_BYTE, }, // R8
809
{ DDSKTX__KTX_RGBA8, DDSKTX__KTX_SRGB8_ALPHA8, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_BYTE, }, // RGBA8
810
{ DDSKTX__KTX_RGBA8_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_BYTE, }, // RGBA8S
811
{ DDSKTX__KTX_RG16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_UNSIGNED_SHORT, }, // RG16
812
{ DDSKTX__KTX_RGB8, DDSKTX__KTX_SRGB8, DDSKTX__KTX_RGB, DDSKTX__KTX_UNSIGNED_BYTE, }, // RGB8
813
{ DDSKTX__KTX_R16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16
814
{ DDSKTX__KTX_R32F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_FLOAT, }, // R32F
815
{ DDSKTX__KTX_R16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_HALF_FLOAT, }, // R16F
816
{ DDSKTX__KTX_RG16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_FLOAT, }, // RG16F
817
{ DDSKTX__KTX_RG16_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_SHORT, }, // RG16S
818
{ DDSKTX__KTX_RGBA16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_HALF_FLOAT, }, // RGBA16F
819
{ DDSKTX__KTX_RGBA16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_SHORT, }, // RGBA16
820
{ DDSKTX__KTX_BGRA, DDSKTX__KTX_SRGB8_ALPHA8, DDSKTX__KTX_BGRA, DDSKTX__KTX_UNSIGNED_BYTE, }, // BGRA8
821
{ DDSKTX__KTX_RGB10_A2, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_INT_2_10_10_10_REV, }, // RGB10A2
822
{ DDSKTX__KTX_R11F_G11F_B10F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGB, DDSKTX__KTX_UNSIGNED_INT_10F_11F_11F_REV, }, // RG11B10F
823
{ DDSKTX__KTX_RG8, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_UNSIGNED_BYTE, }, // RG8
824
{ DDSKTX__KTX_RG8_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_BYTE, }, // RG8S
825
{ DDSKTX__KTX_R16I, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16I
826
{ DDSKTX__KTX_R16UI, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16UI
827
};
828
829
static const ddsktx__ktx_format_info2 k__translate_ktx_fmt2[] =
830
{
831
{ DDSKTX__KTX_A8, DDSKTX_FORMAT_A8 },
832
{ DDSKTX__KTX_RED, DDSKTX_FORMAT_R8 },
833
{ DDSKTX__KTX_RGB, DDSKTX_FORMAT_RGB8 },
834
{ DDSKTX__KTX_RGBA, DDSKTX_FORMAT_RGBA8 },
835
{ DDSKTX__KTX_COMPRESSED_RGB_S3TC_DXT1_EXT, DDSKTX_FORMAT_BC1 },
836
};
837
838
typedef struct ddsktx__format_info
839
{
840
const char* name;
841
bool has_alpha;
842
} ddsktx__format_info;
843
844
static const ddsktx__format_info k__formats_info[] = {
845
{"BC1", false},
846
{"BC2", true},
847
{"BC3", true},
848
{"BC4", false},
849
{"BC5", false},
850
{"BC6H", false},
851
{"BC7", true},
852
{"ETC1", false},
853
{"ETC2", false},
854
{"ETC2A", true},
855
{"ETC2A1", true},
856
{"PTC12", false},
857
{"PTC14", false},
858
{"PTC12A", true},
859
{"PTC14A", true},
860
{"PTC22", true},
861
{"PTC24", true},
862
{"ATC", false},
863
{"ATCE", false},
864
{"ATCI", false},
865
{"ASTC4x4", true},
866
{"ASTC5x5", true},
867
{"ASTC6x6", false},
868
{"ASTC8x5", true},
869
{"ASTC8x6", false},
870
{"ASTC10x5", false},
871
{"<unknown>", false},
872
{"A8", true},
873
{"R8", false},
874
{"RGBA8", true},
875
{"RGBA8S", true},
876
{"RG16", false},
877
{"RGB8", false},
878
{"R16", false},
879
{"R32F", false},
880
{"R16F", false},
881
{"RG16F", false},
882
{"RG16S", false},
883
{"RGBA16F", true},
884
{"RGBA16",true},
885
{"BGRA8", true},
886
{"RGB10A2", true},
887
{"RG11B10F", false},
888
{"RG8", false},
889
{"RG8S", false}
890
};
891
892
893
static inline int ddsktx__read(ddsktx__mem_reader* reader, void* buff, int size)
894
{
895
int read_bytes = (reader->offset + size) <= reader->total ? size : (reader->total - reader->offset);
896
ddsktx_memcpy(buff, reader->buff + reader->offset, read_bytes);
897
reader->offset += read_bytes;
898
return read_bytes;
899
}
900
901
static bool ddsktx__parse_ktx(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err)
902
{
903
static const uint8_t ktx__id[] = { 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
904
905
ddsktx_memset(tc, 0x0, sizeof(ddsktx_texture_info));
906
907
ddsktx__mem_reader r = {(const uint8_t*)file_data, size, sizeof(uint32_t)};
908
ddsktx__ktx_header header;
909
if (ddsktx__read(&r, &header, sizeof(header)) != DDSKTX__KTX_HEADER_SIZE) {
910
ddsktx__err(err, "ktx; header size does not match");
911
}
912
913
if (ddsktx_memcmp(header.id, ktx__id, sizeof(header.id)) != 0) {
914
ddsktx__err(err, "ktx: invalid file header");
915
}
916
917
// TODO: support big endian
918
if (header.endianess != 0x04030201) {
919
ddsktx__err(err, "ktx: big-endian format is not supported");
920
}
921
922
tc->metadata_offset = r.offset;
923
tc->metadata_size = (int)header.metadata_size;
924
r.offset += (int)header.metadata_size;
925
926
ddsktx_format format = _DDSKTX_FORMAT_COUNT;
927
928
int count = sizeof(k__translate_ktx_fmt)/sizeof(ddsktx__ktx_format_info);
929
for (int i = 0; i < count; i++) {
930
if (k__translate_ktx_fmt[i].internal_fmt == header.internal_format) {
931
format = (ddsktx_format)i;
932
break;
933
}
934
}
935
936
if (format == _DDSKTX_FORMAT_COUNT) {
937
count = sizeof(k__translate_ktx_fmt2)/sizeof(ddsktx__ktx_format_info2);
938
for (int i = 0; i < count; i++) {
939
if (k__translate_ktx_fmt2[i].internal_fmt == header.internal_format) {
940
format = (ddsktx_format)k__translate_ktx_fmt2[i].format;
941
break;
942
}
943
}
944
}
945
946
if (format == _DDSKTX_FORMAT_COUNT) {
947
ddsktx__err(err, "ktx: unsupported format");
948
}
949
950
if (header.face_count > 1 && header.face_count != DDSKTX_CUBE_FACE_COUNT) {
951
ddsktx__err(err, "ktx: incomplete cubemap");
952
}
953
954
tc->data_offset = r.offset;
955
tc->size_bytes = r.total - r.offset;
956
tc->format = format;
957
tc->width = (int)header.width;
958
tc->height = (int)header.height;
959
tc->depth = ddsktx__max((int)header.depth, 1);
960
tc->num_layers = ddsktx__max((int)header.array_count, 1);
961
tc->num_mips = ddsktx__max((int)header.mip_count, 1);
962
tc->bpp = k__block_info[format].bpp;
963
964
if (header.face_count == 6)
965
tc->flags |= DDSKTX_TEXTURE_FLAG_CUBEMAP;
966
tc->flags |= k__formats_info[format].has_alpha ? DDSKTX_TEXTURE_FLAG_ALPHA : 0;
967
tc->flags |= DDSKTX_TEXTURE_FLAG_KTX;
968
969
return true;
970
}
971
972
static bool ddsktx__parse_dds(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err)
973
{
974
ddsktx__mem_reader r = {(const uint8_t*)file_data, size, sizeof(uint32_t)};
975
ddsktx__dds_header header;
976
if (ddsktx__read(&r, &header, sizeof(header)) < DDSKTX__DDS_HEADER_SIZE ||
977
header.size != DDSKTX__DDS_HEADER_SIZE)
978
{
979
ddsktx__err(err, "dds: header size does not match");
980
}
981
982
uint32_t required_flags = (DDSKTX__DDSD_HEIGHT|DDSKTX__DDSD_WIDTH);
983
if ((header.flags & required_flags) != required_flags) {
984
ddsktx__err(err, "dds: have invalid flags");
985
}
986
987
if (header.pixel_format.size != sizeof(ddsktx__dds_pixel_format)) {
988
ddsktx__err(err, "dds: pixel format header is invalid");
989
}
990
991
uint32_t dxgi_format = 0;
992
uint32_t array_size = 1;
993
if (DDSKTX__DDPF_FOURCC == (header.flags & DDSKTX__DDPF_FOURCC) &&
994
header.pixel_format.fourcc == DDSKTX__DDS_DX10)
995
{
996
ddsktx__dds_header_dxgi dxgi_header;
997
ddsktx__read(&r, &dxgi_header, sizeof(dxgi_header));
998
dxgi_format = dxgi_header.dxgi_format;
999
array_size = dxgi_header.array_size;
1000
}
1001
1002
if ((header.caps1 & DDSKTX__DDSCAPS_TEXTURE) == 0) {
1003
ddsktx__err(err, "dds: unsupported caps");
1004
}
1005
1006
bool cubemap = (header.caps2 & DDSKTX__DDSCAPS2_CUBEMAP) != 0;
1007
if (cubemap && (header.caps2 & DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES) != DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES) {
1008
ddsktx__err(err, "dds: incomplete cubemap");
1009
}
1010
bool volume = (header.caps2 & DDSKTX__DDSCAPS2_VOLUME) != 0;
1011
1012
ddsktx_format format = _DDSKTX_FORMAT_COUNT;
1013
bool has_alpha = (header.pixel_format.flags & DDSKTX__DDPF_ALPHA) != 0;
1014
bool srgb = false;
1015
1016
if (dxgi_format == 0) {
1017
if ((header.pixel_format.flags & DDSKTX__DDPF_FOURCC) == DDSKTX__DDPF_FOURCC) {
1018
int count = sizeof(k__translate_dds_fourcc)/sizeof(ddsktx__dds_translate_fourcc_format);
1019
for (int i = 0; i < count; i++) {
1020
if (k__translate_dds_fourcc[i].dds_format == header.pixel_format.fourcc) {
1021
format = k__translate_dds_fourcc[i].format;
1022
break;
1023
}
1024
}
1025
} else {
1026
int count = sizeof(k__translate_dds_pixel)/sizeof(ddsktx__dds_translate_pixel_format);
1027
for (int i = 0; i < count; i++) {
1028
const ddsktx__dds_translate_pixel_format* f = &k__translate_dds_pixel[i];
1029
if (f->bit_count == header.pixel_format.rgb_bit_count &&
1030
f->flags == header.pixel_format.flags &&
1031
f->bit_mask[0] == header.pixel_format.bit_mask[0] &&
1032
f->bit_mask[1] == header.pixel_format.bit_mask[1] &&
1033
f->bit_mask[2] == header.pixel_format.bit_mask[2] &&
1034
f->bit_mask[3] == header.pixel_format.bit_mask[3])
1035
{
1036
format = f->format;
1037
break;
1038
}
1039
}
1040
}
1041
} else {
1042
int count = sizeof(k__translate_dxgi)/sizeof(ddsktx__dds_translate_fourcc_format);
1043
for (int i = 0; i < count; i++) {
1044
if (k__translate_dxgi[i].dds_format == dxgi_format) {
1045
format = k__translate_dxgi[i].format;
1046
srgb = k__translate_dxgi[i].srgb;
1047
break;
1048
}
1049
}
1050
}
1051
1052
if (format == _DDSKTX_FORMAT_COUNT) {
1053
ddsktx__err(err, "dds: unknown format");
1054
}
1055
1056
ddsktx_memset(tc, 0x0, sizeof(ddsktx_texture_info));
1057
tc->data_offset = r.offset;
1058
tc->size_bytes = r.total - r.offset;
1059
tc->format = format;
1060
tc->width = (int)header.width;
1061
tc->height = (int)header.height;
1062
tc->depth = ddsktx__max(1, (int)header.depth);
1063
tc->num_layers = ddsktx__max(1, (int)array_size);
1064
tc->num_mips = (header.caps1 & DDSKTX__DDSCAPS_MIPMAP) ? (int)header.mip_count : 1;
1065
tc->bpp = k__block_info[format].bpp;
1066
if (has_alpha || k__formats_info[format].has_alpha)
1067
tc->flags |= DDSKTX_TEXTURE_FLAG_ALPHA;
1068
if (cubemap)
1069
tc->flags |= DDSKTX_TEXTURE_FLAG_CUBEMAP;
1070
if (volume)
1071
tc->flags |= DDSKTX_TEXTURE_FLAG_VOLUME;
1072
if (srgb)
1073
tc->flags |= DDSKTX_TEXTURE_FLAG_SRGB;
1074
tc->flags |= DDSKTX_TEXTURE_FLAG_DDS;
1075
1076
return true;
1077
}
1078
1079
void ddsktx_get_sub(const ddsktx_texture_info* tc, ddsktx_sub_data* sub_data,
1080
const void* file_data, int size,
1081
int array_idx, int slice_face_idx, int mip_idx)
1082
{
1083
ddsktx_assert(tc);
1084
ddsktx_assert(sub_data);
1085
ddsktx_assert(file_data);
1086
ddsktx_assert(size > 0);
1087
ddsktx_assert(array_idx < tc->num_layers);
1088
ddsktx_assert(!((tc->flags&DDSKTX_TEXTURE_FLAG_CUBEMAP) && (slice_face_idx >= DDSKTX_CUBE_FACE_COUNT)) && "invalid cube-face index");
1089
ddsktx_assert(!(!(tc->flags&DDSKTX_TEXTURE_FLAG_CUBEMAP) && (slice_face_idx >= tc->depth)) && "invalid depth-slice index");
1090
ddsktx_assert(mip_idx < tc->num_mips);
1091
1092
ddsktx__mem_reader r = { (uint8_t*)file_data, size, tc->data_offset };
1093
ddsktx_format format = tc->format;
1094
1095
ddsktx_assert(format < _DDSKTX_FORMAT_COUNT && format != _DDSKTX_FORMAT_COMPRESSED);
1096
const ddsktx__block_info* binfo = &k__block_info[format];
1097
const int bpp = binfo->bpp;
1098
const int block_size = binfo->block_size;
1099
const int min_block_x = binfo->min_block_x;
1100
const int min_block_y = binfo->min_block_y;
1101
1102
int num_faces;
1103
1104
ddsktx_assert(!((tc->flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) && tc->depth > 1) && "textures must be either Cube or 3D");
1105
int slice_idx, face_idx, num_slices;
1106
if (tc->flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) {
1107
slice_idx = 0;
1108
face_idx = slice_face_idx;
1109
num_faces = DDSKTX_CUBE_FACE_COUNT;
1110
num_slices = 1;
1111
} else {
1112
slice_idx = slice_face_idx;
1113
face_idx = 0;
1114
num_faces = 1;
1115
num_slices = tc->depth;
1116
}
1117
1118
if (tc->flags & DDSKTX_TEXTURE_FLAG_DDS) {
1119
for (int layer = 0, num_layers = tc->num_layers; layer < num_layers; layer++) {
1120
for (int face = 0; face < num_faces; face++) {
1121
int width = tc->width;
1122
int height = tc->height;
1123
1124
for (int mip = 0, mip_count = tc->num_mips; mip < mip_count; mip++) {
1125
int row_bytes, mip_size;
1126
1127
if (format < _DDSKTX_FORMAT_COMPRESSED) {
1128
int num_blocks_wide = width > 0 ? ddsktx__max(1, (width + 3)/4) : 0;
1129
num_blocks_wide = ddsktx__max(min_block_x, num_blocks_wide);
1130
1131
int num_blocks_high = height > 0 ? ddsktx__max(1, (height + 3)/4) : 0;
1132
num_blocks_high = ddsktx__max(min_block_y, num_blocks_high);
1133
1134
row_bytes = num_blocks_wide * block_size;
1135
mip_size = row_bytes * num_blocks_high;
1136
} else {
1137
row_bytes = (width*bpp + 7)/8; // round to nearest byte
1138
mip_size = row_bytes * height;
1139
}
1140
1141
for (int slice = 0; slice < num_slices; slice++) {
1142
if (layer == array_idx && mip == mip_idx &&
1143
slice == slice_idx && face_idx == face)
1144
{
1145
sub_data->buff = r.buff + r.offset;
1146
sub_data->width = width;
1147
sub_data->height = height;
1148
sub_data->size_bytes = mip_size;
1149
sub_data->row_pitch_bytes = row_bytes;
1150
return;
1151
}
1152
1153
r.offset += mip_size;
1154
ddsktx_assert(r.offset <= r.total && "texture buffer overflow");
1155
} // foreach slice
1156
1157
width >>= 1;
1158
height >>= 1;
1159
1160
if (width == 0) {
1161
width = 1;
1162
}
1163
if (height == 0) {
1164
height = 1;
1165
}
1166
} // foreach mip
1167
} // foreach face
1168
} // foreach array-item
1169
} else if (tc->flags & DDSKTX_TEXTURE_FLAG_KTX) {
1170
int width = tc->width;
1171
int height = tc->height;
1172
1173
for (int mip = 0, c = tc->num_mips; mip < c; mip++) {
1174
int row_bytes, mip_size;
1175
1176
if (format < _DDSKTX_FORMAT_COMPRESSED) {
1177
int num_blocks_wide = width > 0 ? ddsktx__max(1, (width + 3)/4) : 0;
1178
num_blocks_wide = ddsktx__max(min_block_x, num_blocks_wide);
1179
1180
int num_blocks_high = height > 0 ? ddsktx__max(1, (height + 3)/4) : 0;
1181
num_blocks_high = ddsktx__max(min_block_y, num_blocks_high);
1182
1183
row_bytes = num_blocks_wide * block_size;
1184
mip_size = row_bytes * num_blocks_high;
1185
}
1186
else {
1187
row_bytes = (width*bpp + 7)/8; // round to nearest byte
1188
mip_size = row_bytes * height;
1189
}
1190
1191
int image_size;
1192
ddsktx__read(&r, &image_size, sizeof(image_size));
1193
ddsktx_assert(image_size == (mip_size*num_faces*num_slices) && "image size mismatch");
1194
1195
for (int layer = 0, num_layers = tc->num_layers; layer < num_layers; layer++) {
1196
for (int face = 0; face < num_faces; face++) {
1197
for (int slice = 0; slice < num_slices; slice++) {
1198
if (layer == array_idx && mip == mip_idx &&
1199
slice == slice_idx && face_idx == face)
1200
{
1201
sub_data->buff = r.buff + r.offset;
1202
sub_data->width = width;
1203
sub_data->height = height;
1204
sub_data->size_bytes = mip_size;
1205
sub_data->row_pitch_bytes = row_bytes;
1206
return;
1207
}
1208
1209
r.offset += mip_size;
1210
ddsktx_assert(r.offset <= r.total && "texture buffer overflow");
1211
} // foreach slice
1212
1213
1214
r.offset = ddsktx__align_mask(r.offset, 3); // cube-padding
1215
} // foreach face
1216
} // foreach array-item
1217
1218
width >>= 1;
1219
height >>= 1;
1220
1221
if (width == 0) {
1222
width = 1;
1223
}
1224
if (height == 0) {
1225
height = 1;
1226
}
1227
1228
r.offset = ddsktx__align_mask(r.offset, 3); // mip-padding
1229
} // foreach mip
1230
} else {
1231
ddsktx_assert(0 && "invalid file format");
1232
}
1233
}
1234
1235
bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err)
1236
{
1237
ddsktx_assert(tc);
1238
ddsktx_assert(file_data);
1239
ddsktx_assert(size > 0);
1240
1241
ddsktx__mem_reader r = {(const uint8_t*)file_data, size, 0};
1242
1243
// Read file flag and determine the file type
1244
uint32_t file_flag = 0;
1245
if (ddsktx__read(&r, &file_flag, sizeof(file_flag)) != sizeof(file_flag)) {
1246
ddsktx__err(err, "invalid texture file");
1247
}
1248
1249
switch (file_flag) {
1250
case DDSKTX__DDS_MAGIC:
1251
return ddsktx__parse_dds(tc, file_data, size, err);
1252
case DDSKTX__KTX_MAGIC:
1253
return ddsktx__parse_ktx(tc, file_data, size, err);
1254
default:
1255
ddsktx__err(err, "unknown texture format");
1256
}
1257
}
1258
1259
const char* ddsktx_format_str(ddsktx_format format)
1260
{
1261
return k__formats_info[format].name;
1262
}
1263
1264
bool ddsktx_format_compressed(ddsktx_format format)
1265
{
1266
ddsktx_assert(format != _DDSKTX_FORMAT_COMPRESSED && format != _DDSKTX_FORMAT_COUNT);
1267
return format < _DDSKTX_FORMAT_COMPRESSED;
1268
}
1269
1270
#endif // DDSKTX_IMPLEMENT
1271
1272