1338 lines
70 KiB
C
1338 lines
70 KiB
C
//
|
|
// Copyright 2018 Sepehr Taghdisian (septag@github). All rights reserved.
|
|
// License: https://github.com/septag/dds-ktx#license-bsd-2-clause
|
|
//
|
|
// Many parts of this code is taken from bimg library:
|
|
// https://github.com/bkaradzic/bimg
|
|
//
|
|
// Copyright 2011-2019 Branimir Karadzic. All rights reserved.
|
|
// License: https://github.com/bkaradzic/bimg#license-bsd-2-clause
|
|
//
|
|
// dds-ktx.h - v1.1.0 - Reader/Writer for DDS/KTX formats
|
|
// Parses DDS and KTX files from a memory blob, written in C99
|
|
//
|
|
// Supported formats:
|
|
// For supported formats, see ddsktx_format enum.
|
|
// Both KTX/DDS parser supports all formats defined in ddsktx_format
|
|
//
|
|
// Overriable macros:
|
|
// DDSKTX_API Define any function specifier for public functions (default: extern)
|
|
// ddsktx_memcpy default: memcpy(dst, src, size)
|
|
// ddsktx_memset default: memset(dst, v, size)
|
|
// ddsktx_assert default: assert(a)
|
|
// ddsktx_strcpy default: strcpy(dst, src)
|
|
// ddsktx_memcmp default: memcmp(ptr1, ptr2, size)
|
|
//
|
|
// API:
|
|
// bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err);
|
|
// Parses texture file and fills the ddsktx_texture_info struct
|
|
// Returns true if successfully parsed, false if failed with an error message inside ddsktx_error parameter (optional)
|
|
// After format is parsed, you can read the contents of ddsktx_format and create your GPU texture
|
|
// To get pointer to mips and slices see ddsktx_get_sub function
|
|
//
|
|
// void ddsktx_get_sub(const ddsktx_texture_info* tex, ddsktx_sub_data* buff,
|
|
// const void* file_data, int size,
|
|
// int array_idx, int slice_face_idx, int mip_idx);
|
|
// Gets sub-image data, form a parsed texture file
|
|
// user must provided the container object and the original file data which was passed to ddsktx_parse
|
|
// array_idx: array index (0..num_layers)
|
|
// slice_face_idx: depth-slice or cube-face index.
|
|
// if 'flags' have DDSKTX_TEXTURE_FLAG_CUBEMAP bit, then this value represents cube-face-index (0..DDSKTX_CUBE_FACE_COUNT)
|
|
// else it represents depth slice index (0..depth)
|
|
// mip_idx: mip index (0..num_mips-1 in ddsktx_texture_info)
|
|
//
|
|
// const char* ddsktx_format_str(ddsktx_format format);
|
|
// Converts a format enumeration to string
|
|
//
|
|
// bool ddsktx_format_compressed(ddsktx_format format);
|
|
// Returns true if format is compressed
|
|
//
|
|
// Example (for 2D textures only):
|
|
// int size;
|
|
// void* dds_data = load_file("test.dds", &size);
|
|
// assert(dds_data);
|
|
// ddsktx_texture_info tc = {0};
|
|
// if (ddsktx_parse(&tc, dds_data, size, NULL)) {
|
|
// assert(tc.depth == 1);
|
|
// assert(!(tc.flags & DDSKTX_TEXTURE_FLAG_CUBEMAP));
|
|
// assert(tc.num_layers == 1);
|
|
// // Create GPU texture from tc data
|
|
// for (int mip = 0; mip < tc.num_mips; mip++) {
|
|
// ddsktx_sub_data sub_data;
|
|
// ddsktx_get_sub(&tc, &sub_data, dds_data, size, 0, 0, mip);
|
|
// // Fill/Set texture sub resource data (mips in this case)
|
|
// }
|
|
// }
|
|
// free(dds_data); // memory must be valid during stc_ calls
|
|
//
|
|
// Version history:
|
|
// 0.9.0 Initial release, ktx is incomplete
|
|
// 1.0.0 Api change: ddsktx_sub_data
|
|
// Added KTX support
|
|
// 1.0.1 Fixed major bugs in KTX parsing
|
|
// 1.1.0 Fixed bugs in get_sub routine, refactored some parts, image-viewer example
|
|
//
|
|
// TODO
|
|
// Write KTX/DDS
|
|
// Read KTX metadata. currently it just stores the offset/size to the metadata block
|
|
//
|
|
|
|
#pragma once
|
|
// #define DDSKTX_IMPLEMENT
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#ifndef DDSKTX_API
|
|
# ifdef __cplusplus
|
|
# define DDSKTX_API extern "C"
|
|
# else
|
|
# define DDSKTX_API
|
|
# endif
|
|
#endif
|
|
|
|
typedef struct ddsktx_sub_data
|
|
{
|
|
const void* buff;
|
|
int width;
|
|
int height;
|
|
int size_bytes;
|
|
int row_pitch_bytes;
|
|
} ddsktx_sub_data;
|
|
|
|
typedef enum ddsktx_format
|
|
{
|
|
DDSKTX_FORMAT_BC1, // DXT1
|
|
DDSKTX_FORMAT_BC2, // DXT3
|
|
DDSKTX_FORMAT_BC3, // DXT5
|
|
DDSKTX_FORMAT_BC4, // ATI1
|
|
DDSKTX_FORMAT_BC5, // ATI2
|
|
DDSKTX_FORMAT_BC6H, // BC6H
|
|
DDSKTX_FORMAT_BC7, // BC7
|
|
DDSKTX_FORMAT_ETC1, // ETC1 RGB8
|
|
DDSKTX_FORMAT_ETC2, // ETC2 RGB8
|
|
DDSKTX_FORMAT_ETC2A, // ETC2 RGBA8
|
|
DDSKTX_FORMAT_ETC2A1, // ETC2 RGB8A1
|
|
DDSKTX_FORMAT_PTC12, // PVRTC1 RGB 2bpp
|
|
DDSKTX_FORMAT_PTC14, // PVRTC1 RGB 4bpp
|
|
DDSKTX_FORMAT_PTC12A, // PVRTC1 RGBA 2bpp
|
|
DDSKTX_FORMAT_PTC14A, // PVRTC1 RGBA 4bpp
|
|
DDSKTX_FORMAT_PTC22, // PVRTC2 RGBA 2bpp
|
|
DDSKTX_FORMAT_PTC24, // PVRTC2 RGBA 4bpp
|
|
DDSKTX_FORMAT_ATC, // ATC RGB 4BPP
|
|
DDSKTX_FORMAT_ATCE, // ATCE RGBA 8 BPP explicit alpha
|
|
DDSKTX_FORMAT_ATCI, // ATCI RGBA 8 BPP interpolated alpha
|
|
DDSKTX_FORMAT_ASTC4x4, // ASTC 4x4 8.00 BPP
|
|
DDSKTX_FORMAT_ASTC5x4, // ASTC 5x4 6.40 BPP
|
|
DDSKTX_FORMAT_ASTC5x5, // ASTC 5x5 5.12 BPP
|
|
DDSKTX_FORMAT_ASTC6x5, // ASTC 6x5 4.27 BPP
|
|
DDSKTX_FORMAT_ASTC6x6, // ASTC 6x6 3.56 BPP
|
|
DDSKTX_FORMAT_ASTC8x5, // ASTC 8x5 3.20 BPP
|
|
DDSKTX_FORMAT_ASTC8x6, // ASTC 8x6 2.67 BPP
|
|
DDSKTX_FORMAT_ASTC10x5, // ASTC 10x5 2.56 BPP
|
|
DDSKTX_FORMAT_ASTC10x6, // ASTC 10x6 2.13 BPP
|
|
DDSKTX_FORMAT_ASTC8x8, // ASTC 8x8 2.00 BPP
|
|
DDSKTX_FORMAT_ASTC10x8, // ASTC 10x8 1.60 BPP
|
|
DDSKTX_FORMAT_ASTC10x10,// ASTC 10x10 1.28 BPP
|
|
DDSKTX_FORMAT_ASTC12x10,// ASTC 12x10 1.07 BPP
|
|
DDSKTX_FORMAT_ASTC12x12,// ASTC 12x12 0.89 BPP
|
|
_DDSKTX_FORMAT_COMPRESSED,
|
|
DDSKTX_FORMAT_A8,
|
|
DDSKTX_FORMAT_R8,
|
|
DDSKTX_FORMAT_RGBA8,
|
|
DDSKTX_FORMAT_RGBA8S,
|
|
DDSKTX_FORMAT_RG16,
|
|
DDSKTX_FORMAT_RGB8,
|
|
DDSKTX_FORMAT_R16,
|
|
DDSKTX_FORMAT_R32F,
|
|
DDSKTX_FORMAT_R16F,
|
|
DDSKTX_FORMAT_RG16F,
|
|
DDSKTX_FORMAT_RG16S,
|
|
DDSKTX_FORMAT_RGBA16F,
|
|
DDSKTX_FORMAT_RGBA16,
|
|
DDSKTX_FORMAT_BGRA8,
|
|
DDSKTX_FORMAT_RGB10A2,
|
|
DDSKTX_FORMAT_RG11B10F,
|
|
DDSKTX_FORMAT_RG8,
|
|
DDSKTX_FORMAT_RG8S,
|
|
_DDSKTX_FORMAT_COUNT
|
|
} ddsktx_format;
|
|
|
|
typedef enum ddsktx_texture_flags
|
|
{
|
|
DDSKTX_TEXTURE_FLAG_CUBEMAP = 0x01,
|
|
DDSKTX_TEXTURE_FLAG_SRGB = 0x02,
|
|
DDSKTX_TEXTURE_FLAG_ALPHA = 0x04, // Has alpha channel
|
|
DDSKTX_TEXTURE_FLAG_DDS = 0x08, // container was DDS file
|
|
DDSKTX_TEXTURE_FLAG_KTX = 0x10, // container was KTX file
|
|
DDSKTX_TEXTURE_FLAG_VOLUME = 0x20, // 3D volume
|
|
} ddsktx_texture_flags;
|
|
|
|
typedef struct ddsktx_texture_info
|
|
{
|
|
int data_offset; // start offset of pixel data
|
|
int size_bytes;
|
|
ddsktx_format format;
|
|
unsigned int flags; // ddsktx_texture_flags
|
|
int width;
|
|
int height;
|
|
int depth;
|
|
int num_layers;
|
|
int num_mips;
|
|
int bpp;
|
|
int metadata_offset; // ktx only
|
|
int metadata_size; // ktx only
|
|
} ddsktx_texture_info;
|
|
|
|
typedef enum ddsktx_cube_face
|
|
{
|
|
DDSKTX_CUBE_FACE_X_POSITIVE = 0,
|
|
DDSKTX_CUBE_FACE_X_NEGATIVE,
|
|
DDSKTX_CUBE_FACE_Y_POSITIVE,
|
|
DDSKTX_CUBE_FACE_Y_NEGATIVE,
|
|
DDSKTX_CUBE_FACE_Z_POSITIVE,
|
|
DDSKTX_CUBE_FACE_Z_NEGATIVE,
|
|
DDSKTX_CUBE_FACE_COUNT
|
|
} ddsktx_cube_face;
|
|
|
|
typedef struct ddsktx_error
|
|
{
|
|
char msg[256];
|
|
} ddsktx_error;
|
|
|
|
#ifdef __cplusplus
|
|
# define ddsktx_default(_v) =_v
|
|
#else
|
|
# define ddsktx_default(_v)
|
|
#endif
|
|
|
|
DDSKTX_API bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err ddsktx_default(NULL));
|
|
DDSKTX_API void ddsktx_get_sub(const ddsktx_texture_info* tex, ddsktx_sub_data* buff,
|
|
const void* file_data, int size,
|
|
int array_idx, int slice_face_idx, int mip_idx);
|
|
DDSKTX_API const char* ddsktx_format_str(ddsktx_format format);
|
|
DDSKTX_API bool ddsktx_format_compressed(ddsktx_format format);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Implementation
|
|
#ifdef DDSKTX_IMPLEMENT
|
|
|
|
#define stc__makefourcc(_a, _b, _c, _d) ( ( (uint32_t)(_a) | ( (uint32_t)(_b) << 8) | \
|
|
( (uint32_t)(_c) << 16) | ( (uint32_t)(_d) << 24) ) )
|
|
|
|
// DDS: https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dx-graphics-dds-pguide
|
|
#define DDSKTX__DDS_HEADER_SIZE 124
|
|
#define DDSKTX__DDS_MAGIC stc__makefourcc('D', 'D', 'S', ' ')
|
|
#define DDSKTX__DDS_DXT1 stc__makefourcc('D', 'X', 'T', '1')
|
|
#define DDSKTX__DDS_DXT2 stc__makefourcc('D', 'X', 'T', '2')
|
|
#define DDSKTX__DDS_DXT3 stc__makefourcc('D', 'X', 'T', '3')
|
|
#define DDSKTX__DDS_DXT4 stc__makefourcc('D', 'X', 'T', '4')
|
|
#define DDSKTX__DDS_DXT5 stc__makefourcc('D', 'X', 'T', '5')
|
|
#define DDSKTX__DDS_ATI1 stc__makefourcc('A', 'T', 'I', '1')
|
|
#define DDSKTX__DDS_BC4U stc__makefourcc('B', 'C', '4', 'U')
|
|
#define DDSKTX__DDS_ATI2 stc__makefourcc('A', 'T', 'I', '2')
|
|
#define DDSKTX__DDS_BC5U stc__makefourcc('B', 'C', '5', 'U')
|
|
#define DDSKTX__DDS_DX10 stc__makefourcc('D', 'X', '1', '0')
|
|
|
|
#define DDSKTX__DDS_ETC1 stc__makefourcc('E', 'T', 'C', '1')
|
|
#define DDSKTX__DDS_ETC2 stc__makefourcc('E', 'T', 'C', '2')
|
|
#define DDSKTX__DDS_ET2A stc__makefourcc('E', 'T', '2', 'A')
|
|
#define DDSKTX__DDS_PTC2 stc__makefourcc('P', 'T', 'C', '2')
|
|
#define DDSKTX__DDS_PTC4 stc__makefourcc('P', 'T', 'C', '4')
|
|
#define DDSKTX__DDS_ATC stc__makefourcc('A', 'T', 'C', ' ')
|
|
#define DDSKTX__DDS_ATCE stc__makefourcc('A', 'T', 'C', 'E')
|
|
#define DDSKTX__DDS_ATCI stc__makefourcc('A', 'T', 'C', 'I')
|
|
#define DDSKTX__DDS_ASTC4x4 stc__makefourcc('A', 'S', '4', '4')
|
|
#define DDSKTX__DDS_ASTC5x4 stc__makefourcc('A', 'S', '5', '4')
|
|
#define DDSKTX__DDS_ASTC5x5 stc__makefourcc('A', 'S', '5', '5')
|
|
#define DDSKTX__DDS_ASTC6x5 stc__makefourcc('A', 'S', '6', '5')
|
|
#define DDSKTX__DDS_ASTC6x6 stc__makefourcc('A', 'S', '6', '6')
|
|
#define DDSKTX__DDS_ASTC8x5 stc__makefourcc('A', 'S', '8', '5')
|
|
#define DDSKTX__DDS_ASTC8x6 stc__makefourcc('A', 'S', '8', '6')
|
|
#define DDSKTX__DDS_ASTC10x5 stc__makefourcc('A', 'S', ':', '5')
|
|
#define DDSKTX__DDS_ASTC10x6 stc__makefourcc('A', 'S', ':', '6')
|
|
#define DDSKTX__DDS_ASTC8x8 stc__makefourcc('A', 'S', '8', '8')
|
|
#define DDSKTX__DDS_ASTC10x8 stc__makefourcc('A', 'S', ':', '8')
|
|
#define DDSKTX__DDS_ASTC10x10 stc__makefourcc('A', 'S', ':', ':')
|
|
#define DDSKTX__DDS_ASTC12x10 stc__makefourcc('A', 'S', '<', ':')
|
|
#define DDSKTX__DDS_ASTC12x12 stc__makefourcc('A', 'S', '<', '<')
|
|
|
|
#define DDSKTX__DDS_R8G8B8 20
|
|
#define DDSKTX__DDS_A8R8G8B8 21
|
|
#define DDSKTX__DDS_R5G6B5 23
|
|
#define DDSKTX__DDS_A1R5G5B5 25
|
|
#define DDSKTX__DDS_A4R4G4B4 26
|
|
#define DDSKTX__DDS_A2B10G10R10 31
|
|
#define DDSKTX__DDS_G16R16 34
|
|
#define DDSKTX__DDS_A2R10G10B10 35
|
|
#define DDSKTX__DDS_A16B16G16R16 36
|
|
#define DDSKTX__DDS_A8L8 51
|
|
#define DDSKTX__DDS_R16F 111
|
|
#define DDSKTX__DDS_G16R16F 112
|
|
#define DDSKTX__DDS_A16B16G16R16F 113
|
|
#define DDSKTX__DDS_R32F 114
|
|
#define DDSKTX__DDS_G32R32F 115
|
|
#define DDSKTX__DDS_A32B32G32R32F 116
|
|
|
|
#define DDSKTX__DDS_FORMAT_R32G32B32A32_FLOAT 2
|
|
#define DDSKTX__DDS_FORMAT_R32G32B32A32_UINT 3
|
|
#define DDSKTX__DDS_FORMAT_R16G16B16A16_FLOAT 10
|
|
#define DDSKTX__DDS_FORMAT_R16G16B16A16_UNORM 11
|
|
#define DDSKTX__DDS_FORMAT_R16G16B16A16_UINT 12
|
|
#define DDSKTX__DDS_FORMAT_R32G32_FLOAT 16
|
|
#define DDSKTX__DDS_FORMAT_R32G32_UINT 17
|
|
#define DDSKTX__DDS_FORMAT_R10G10B10A2_UNORM 24
|
|
#define DDSKTX__DDS_FORMAT_R11G11B10_FLOAT 26
|
|
#define DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM 28
|
|
#define DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM_SRGB 29
|
|
#define DDSKTX__DDS_FORMAT_R16G16_FLOAT 34
|
|
#define DDSKTX__DDS_FORMAT_R16G16_UNORM 35
|
|
#define DDSKTX__DDS_FORMAT_R32_FLOAT 41
|
|
#define DDSKTX__DDS_FORMAT_R32_UINT 42
|
|
#define DDSKTX__DDS_FORMAT_R8G8_UNORM 49
|
|
#define DDSKTX__DDS_FORMAT_R16_FLOAT 54
|
|
#define DDSKTX__DDS_FORMAT_R16_UNORM 56
|
|
#define DDSKTX__DDS_FORMAT_R8_UNORM 61
|
|
#define DDSKTX__DDS_FORMAT_R1_UNORM 66
|
|
#define DDSKTX__DDS_FORMAT_BC1_UNORM 71
|
|
#define DDSKTX__DDS_FORMAT_BC1_UNORM_SRGB 72
|
|
#define DDSKTX__DDS_FORMAT_BC2_UNORM 74
|
|
#define DDSKTX__DDS_FORMAT_BC2_UNORM_SRGB 75
|
|
#define DDSKTX__DDS_FORMAT_BC3_UNORM 77
|
|
#define DDSKTX__DDS_FORMAT_BC3_UNORM_SRGB 78
|
|
#define DDSKTX__DDS_FORMAT_BC4_UNORM 80
|
|
#define DDSKTX__DDS_FORMAT_BC5_UNORM 83
|
|
#define DDSKTX__DDS_FORMAT_B5G6R5_UNORM 85
|
|
#define DDSKTX__DDS_FORMAT_B5G5R5A1_UNORM 86
|
|
#define DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM 87
|
|
#define DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM_SRGB 91
|
|
#define DDSKTX__DDS_FORMAT_BC6H_SF16 96
|
|
#define DDSKTX__DDS_FORMAT_BC7_UNORM 98
|
|
#define DDSKTX__DDS_FORMAT_BC7_UNORM_SRGB 99
|
|
#define DDSKTX__DDS_FORMAT_B4G4R4A4_UNORM 115
|
|
|
|
#define DDSKTX__DDS_DX10_DIMENSION_TEXTURE2D 3
|
|
#define DDSKTX__DDS_DX10_DIMENSION_TEXTURE3D 4
|
|
#define DDSKTX__DDS_DX10_MISC_TEXTURECUBE 4
|
|
|
|
#define DDSKTX__DDSD_CAPS 0x00000001
|
|
#define DDSKTX__DDSD_HEIGHT 0x00000002
|
|
#define DDSKTX__DDSD_WIDTH 0x00000004
|
|
#define DDSKTX__DDSD_PITCH 0x00000008
|
|
#define DDSKTX__DDSD_PIXELFORMAT 0x00001000
|
|
#define DDSKTX__DDSD_MIPMAPCOUNT 0x00020000
|
|
#define DDSKTX__DDSD_LINEARSIZE 0x00080000
|
|
#define DDSKTX__DDSD_DEPTH 0x00800000
|
|
|
|
#define DDSKTX__DDPF_ALPHAPIXELS 0x00000001
|
|
#define DDSKTX__DDPF_ALPHA 0x00000002
|
|
#define DDSKTX__DDPF_FOURCC 0x00000004
|
|
#define DDSKTX__DDPF_INDEXED 0x00000020
|
|
#define DDSKTX__DDPF_RGB 0x00000040
|
|
#define DDSKTX__DDPF_YUV 0x00000200
|
|
#define DDSKTX__DDPF_LUMINANCE 0x00020000
|
|
#define DDSKTX__DDPF_BUMPDUDV 0x00080000
|
|
|
|
#define DDSKTX__DDSCAPS_COMPLEX 0x00000008
|
|
#define DDSKTX__DDSCAPS_TEXTURE 0x00001000
|
|
#define DDSKTX__DDSCAPS_MIPMAP 0x00400000
|
|
|
|
#define DDSKTX__DDSCAPS2_VOLUME 0x00200000
|
|
#define DDSKTX__DDSCAPS2_CUBEMAP 0x00000200
|
|
#define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
|
|
#define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
|
|
#define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
|
|
#define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
|
|
#define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
|
|
#define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
|
|
|
|
#define DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES (0 \
|
|
| DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEX \
|
|
| DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEX \
|
|
| DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEY \
|
|
| DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEY \
|
|
| DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEZ \
|
|
| DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEZ )
|
|
|
|
#pragma pack(push, 1)
|
|
typedef struct ddsktx__dds_pixel_format
|
|
{
|
|
uint32_t size;
|
|
uint32_t flags;
|
|
uint32_t fourcc;
|
|
uint32_t rgb_bit_count;
|
|
uint32_t bit_mask[4];
|
|
} ddsktx__dds_pixel_format;
|
|
|
|
// https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dds-header
|
|
typedef struct ddsktx__dds_header
|
|
{
|
|
uint32_t size;
|
|
uint32_t flags;
|
|
uint32_t height;
|
|
uint32_t width;
|
|
uint32_t pitch_lin_size;
|
|
uint32_t depth;
|
|
uint32_t mip_count;
|
|
uint32_t reserved1[11];
|
|
ddsktx__dds_pixel_format pixel_format;
|
|
uint32_t caps1;
|
|
uint32_t caps2;
|
|
uint32_t caps3;
|
|
uint32_t caps4;
|
|
uint32_t reserved2;
|
|
} ddsktx__dds_header;
|
|
|
|
// https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dds-header-dxt10
|
|
typedef struct ddsktx__dds_header_dxgi
|
|
{
|
|
uint32_t dxgi_format;
|
|
uint32_t dimension;
|
|
uint32_t misc_flags;
|
|
uint32_t array_size;
|
|
uint32_t misc_flags2;
|
|
} ddsktx__dds_header_dxgi;
|
|
|
|
typedef struct ddsktx__ktx_header
|
|
{
|
|
uint8_t id[8];
|
|
uint32_t endianess;
|
|
uint32_t type;
|
|
uint32_t type_size;
|
|
uint32_t format;
|
|
uint32_t internal_format;
|
|
uint32_t base_internal_format;
|
|
uint32_t width;
|
|
uint32_t height;
|
|
uint32_t depth;
|
|
uint32_t array_count;
|
|
uint32_t face_count;
|
|
uint32_t mip_count;
|
|
uint32_t metadata_size;
|
|
} ddsktx__ktx_header;
|
|
#pragma pack(pop)
|
|
|
|
typedef struct ddsktx__dds_translate_fourcc_format
|
|
{
|
|
uint32_t dds_format;
|
|
ddsktx_format format;
|
|
bool srgb;
|
|
} ddsktx__dds_translate_fourcc_format;
|
|
|
|
typedef struct ddsktx__dds_translate_pixel_format
|
|
{
|
|
uint32_t bit_count;
|
|
uint32_t flags;
|
|
uint32_t bit_mask[4];
|
|
ddsktx_format format;
|
|
} ddsktx__dds_translate_pixel_format;
|
|
|
|
typedef struct ddsktx__mem_reader
|
|
{
|
|
const uint8_t* buff;
|
|
int total;
|
|
int offset;
|
|
} ddsktx__mem_reader;
|
|
|
|
typedef struct ddsktx__block_info
|
|
{
|
|
uint8_t bpp;
|
|
uint8_t block_width;
|
|
uint8_t block_height;
|
|
uint8_t block_size;
|
|
uint8_t min_block_x;
|
|
uint8_t min_block_y;
|
|
uint8_t depth_bits;
|
|
uint8_t stencil_bits;
|
|
uint8_t r_bits;
|
|
uint8_t g_bits;
|
|
uint8_t b_bits;
|
|
uint8_t a_bits;
|
|
uint8_t encoding;
|
|
} ddsktx__block_info;
|
|
|
|
#ifndef ddsktx_memcpy
|
|
# include <string.h>
|
|
# define ddsktx_memcpy(_dst, _src, _size) memcpy((_dst), (_src), (_size))
|
|
#endif
|
|
|
|
#ifndef ddsktx_memset
|
|
# include <string.h>
|
|
# define ddsktx_memset(_dst, _v, _size) memset((_dst), (_v), (_size))
|
|
#endif
|
|
|
|
#ifndef ddsktx_assert
|
|
# include <assert.h>
|
|
# define ddsktx_assert(_a) assert(_a)
|
|
#endif
|
|
|
|
#ifndef ddsktx_strcpy
|
|
# include <string.h>
|
|
# ifdef _MSC_VER
|
|
# define ddsktx_strcpy(_dst, _src) strcpy_s((_dst), sizeof(_dst), (_src))
|
|
# else
|
|
# define ddsktx_strcpy(_dst, _src) strcpy((_dst), (_src))
|
|
# endif
|
|
#endif
|
|
|
|
#ifndef ddsktx_memcmp
|
|
# include <string.h>
|
|
# define ddsktx_memcmp(_ptr1, _ptr2, _num) memcmp((_ptr1), (_ptr2), (_num))
|
|
#endif
|
|
|
|
#define ddsktx__max(a, b) ((a) > (b) ? (a) : (b))
|
|
#define ddsktx__min(a, b) ((a) < (b) ? (a) : (b))
|
|
#define ddsktx__align_mask(_value, _mask) (((_value)+(_mask)) & ((~0)&(~(_mask))))
|
|
#define ddsktx__err(_err, _msg) if (_err) ddsktx_strcpy(_err->msg, _msg); return false
|
|
|
|
static const ddsktx__dds_translate_fourcc_format k__translate_dds_fourcc[] = {
|
|
{ DDSKTX__DDS_DXT1, DDSKTX_FORMAT_BC1, false },
|
|
{ DDSKTX__DDS_DXT2, DDSKTX_FORMAT_BC2, false },
|
|
{ DDSKTX__DDS_DXT3, DDSKTX_FORMAT_BC2, false },
|
|
{ DDSKTX__DDS_DXT4, DDSKTX_FORMAT_BC3, false },
|
|
{ DDSKTX__DDS_DXT5, DDSKTX_FORMAT_BC3, false },
|
|
{ DDSKTX__DDS_ATI1, DDSKTX_FORMAT_BC4, false },
|
|
{ DDSKTX__DDS_BC4U, DDSKTX_FORMAT_BC4, false },
|
|
{ DDSKTX__DDS_ATI2, DDSKTX_FORMAT_BC5, false },
|
|
{ DDSKTX__DDS_BC5U, DDSKTX_FORMAT_BC5, false },
|
|
{ DDSKTX__DDS_ETC1, DDSKTX_FORMAT_ETC1, false },
|
|
{ DDSKTX__DDS_ETC2, DDSKTX_FORMAT_ETC2, false },
|
|
{ DDSKTX__DDS_ET2A, DDSKTX_FORMAT_ETC2A, false },
|
|
{ DDSKTX__DDS_PTC2, DDSKTX_FORMAT_PTC12A, false },
|
|
{ DDSKTX__DDS_PTC4, DDSKTX_FORMAT_PTC14A, false },
|
|
{ DDSKTX__DDS_ATC , DDSKTX_FORMAT_ATC, false },
|
|
{ DDSKTX__DDS_ATCE, DDSKTX_FORMAT_ATCE, false },
|
|
{ DDSKTX__DDS_ATCI, DDSKTX_FORMAT_ATCI, false },
|
|
{ DDSKTX__DDS_ASTC4x4, DDSKTX_FORMAT_ASTC4x4, false },
|
|
{ DDSKTX__DDS_ASTC5x4, DDSKTX_FORMAT_ASTC5x4, false },
|
|
{ DDSKTX__DDS_ASTC5x5, DDSKTX_FORMAT_ASTC5x5, false },
|
|
{ DDSKTX__DDS_ASTC6x5, DDSKTX_FORMAT_ASTC6x5, false },
|
|
{ DDSKTX__DDS_ASTC6x6, DDSKTX_FORMAT_ASTC6x6, false },
|
|
{ DDSKTX__DDS_ASTC8x5, DDSKTX_FORMAT_ASTC8x5, false },
|
|
{ DDSKTX__DDS_ASTC8x6, DDSKTX_FORMAT_ASTC8x6, false },
|
|
{ DDSKTX__DDS_ASTC10x5, DDSKTX_FORMAT_ASTC10x5, false },
|
|
{ DDSKTX__DDS_ASTC10x6, DDSKTX_FORMAT_ASTC10x6, false },
|
|
{ DDSKTX__DDS_ASTC8x8, DDSKTX_FORMAT_ASTC8x8, false },
|
|
{ DDSKTX__DDS_ASTC10x8, DDSKTX_FORMAT_ASTC10x8, false },
|
|
{ DDSKTX__DDS_ASTC10x10, DDSKTX_FORMAT_ASTC10x10, false },
|
|
{ DDSKTX__DDS_ASTC12x10, DDSKTX_FORMAT_ASTC12x10, false },
|
|
{ DDSKTX__DDS_ASTC12x12, DDSKTX_FORMAT_ASTC12x12, false },
|
|
{ DDSKTX__DDS_A16B16G16R16, DDSKTX_FORMAT_RGBA16, false },
|
|
{ DDSKTX__DDS_A16B16G16R16F, DDSKTX_FORMAT_RGBA16F, false },
|
|
{ DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, DDSKTX_FORMAT_BGRA8, false },
|
|
{ DDSKTX__DDPF_INDEXED, DDSKTX_FORMAT_R8, false },
|
|
{ DDSKTX__DDPF_LUMINANCE, DDSKTX_FORMAT_R8, false },
|
|
{ DDSKTX__DDPF_ALPHA, DDSKTX_FORMAT_R8, false },
|
|
{ DDSKTX__DDS_R16F, DDSKTX_FORMAT_R16F, false },
|
|
{ DDSKTX__DDS_R32F, DDSKTX_FORMAT_R32F, false },
|
|
{ DDSKTX__DDS_A8L8, DDSKTX_FORMAT_RG8, false },
|
|
{ DDSKTX__DDS_G16R16, DDSKTX_FORMAT_RG16, false },
|
|
{ DDSKTX__DDS_G16R16F, DDSKTX_FORMAT_RG16F, false },
|
|
{ DDSKTX__DDS_R8G8B8, DDSKTX_FORMAT_RGB8, false },
|
|
{ DDSKTX__DDS_A8R8G8B8, DDSKTX_FORMAT_BGRA8, false },
|
|
{ DDSKTX__DDS_A16B16G16R16, DDSKTX_FORMAT_RGBA16, false },
|
|
{ DDSKTX__DDS_A16B16G16R16F, DDSKTX_FORMAT_RGBA16F, false },
|
|
{ DDSKTX__DDS_A2B10G10R10, DDSKTX_FORMAT_RGB10A2, false },
|
|
};
|
|
|
|
static const ddsktx__dds_translate_fourcc_format k__translate_dxgi[] = {
|
|
{ DDSKTX__DDS_FORMAT_BC1_UNORM, DDSKTX_FORMAT_BC1, false },
|
|
{ DDSKTX__DDS_FORMAT_BC1_UNORM_SRGB, DDSKTX_FORMAT_BC1, true },
|
|
{ DDSKTX__DDS_FORMAT_BC2_UNORM, DDSKTX_FORMAT_BC2, false },
|
|
{ DDSKTX__DDS_FORMAT_BC2_UNORM_SRGB, DDSKTX_FORMAT_BC2, true },
|
|
{ DDSKTX__DDS_FORMAT_BC3_UNORM, DDSKTX_FORMAT_BC3, false },
|
|
{ DDSKTX__DDS_FORMAT_BC3_UNORM_SRGB, DDSKTX_FORMAT_BC3, true },
|
|
{ DDSKTX__DDS_FORMAT_BC4_UNORM, DDSKTX_FORMAT_BC4, false },
|
|
{ DDSKTX__DDS_FORMAT_BC5_UNORM, DDSKTX_FORMAT_BC5, false },
|
|
{ DDSKTX__DDS_FORMAT_BC6H_SF16, DDSKTX_FORMAT_BC6H, false },
|
|
{ DDSKTX__DDS_FORMAT_BC7_UNORM, DDSKTX_FORMAT_BC7, false },
|
|
{ DDSKTX__DDS_FORMAT_BC7_UNORM_SRGB, DDSKTX_FORMAT_BC7, true },
|
|
|
|
{ DDSKTX__DDS_FORMAT_R8_UNORM, DDSKTX_FORMAT_R8, false },
|
|
{ DDSKTX__DDS_FORMAT_R16_UNORM, DDSKTX_FORMAT_R16, false },
|
|
{ DDSKTX__DDS_FORMAT_R16_FLOAT, DDSKTX_FORMAT_R16F, false },
|
|
{ DDSKTX__DDS_FORMAT_R32_FLOAT, DDSKTX_FORMAT_R32F, false },
|
|
{ DDSKTX__DDS_FORMAT_R8G8_UNORM, DDSKTX_FORMAT_RG8, false },
|
|
{ DDSKTX__DDS_FORMAT_R16G16_UNORM, DDSKTX_FORMAT_RG16, false },
|
|
{ DDSKTX__DDS_FORMAT_R16G16_FLOAT, DDSKTX_FORMAT_RG16F, false },
|
|
{ DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM, DDSKTX_FORMAT_BGRA8, false },
|
|
{ DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM_SRGB, DDSKTX_FORMAT_BGRA8, true },
|
|
{ DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM, DDSKTX_FORMAT_RGBA8, false },
|
|
{ DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM_SRGB, DDSKTX_FORMAT_RGBA8, true },
|
|
{ DDSKTX__DDS_FORMAT_R16G16B16A16_UNORM, DDSKTX_FORMAT_RGBA16, false },
|
|
{ DDSKTX__DDS_FORMAT_R16G16B16A16_FLOAT, DDSKTX_FORMAT_RGBA16F, false },
|
|
{ DDSKTX__DDS_FORMAT_R10G10B10A2_UNORM, DDSKTX_FORMAT_RGB10A2, false },
|
|
{ DDSKTX__DDS_FORMAT_R11G11B10_FLOAT, DDSKTX_FORMAT_RG11B10F, false },
|
|
};
|
|
|
|
static const ddsktx__dds_translate_pixel_format k__translate_dds_pixel[] = {
|
|
{ 8, DDSKTX__DDPF_LUMINANCE, { 0x000000ff, 0x00000000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_R8 },
|
|
{ 16, DDSKTX__DDPF_BUMPDUDV, { 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG8S },
|
|
{ 24, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_RGB8 },
|
|
{ 24, DDSKTX__DDPF_RGB, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }, DDSKTX_FORMAT_RGB8 },
|
|
{ 32, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_BGRA8 },
|
|
{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, DDSKTX_FORMAT_RGBA8 },
|
|
{ 32, DDSKTX__DDPF_BUMPDUDV, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, DDSKTX_FORMAT_RGBA8S },
|
|
{ 32, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSKTX_FORMAT_BGRA8 },
|
|
{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSKTX_FORMAT_BGRA8 }, // D3DFMT_A8R8G8B8
|
|
{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_BGRA8 }, // D3DFMT_X8R8G8B8
|
|
{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 }, DDSKTX_FORMAT_RGB10A2 },
|
|
{ 32, DDSKTX__DDPF_RGB, { 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG16 },
|
|
{ 32, DDSKTX__DDPF_BUMPDUDV, { 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG16S }
|
|
};
|
|
|
|
typedef enum ddsktx__encode_type
|
|
{
|
|
DDSKTX__ENCODE_UNORM,
|
|
DDSKTX__ENCODE_SNORM,
|
|
DDSKTX__ENCODE_FLOAT,
|
|
DDSKTX__ENCODE_INT,
|
|
DDSKTX__ENCODE_UINT,
|
|
DDSKTX__ENCODE_COUNT
|
|
} ddsktx__encode_type;
|
|
|
|
static const ddsktx__block_info k__block_info[] =
|
|
{
|
|
// +-------------------------------------------- bits per pixel
|
|
// | +----------------------------------------- block width
|
|
// | | +-------------------------------------- block height
|
|
// | | | +---------------------------------- block size
|
|
// | | | | +------------------------------- min blocks x
|
|
// | | | | | +---------------------------- min blocks y
|
|
// | | | | | | +------------------------ depth bits
|
|
// | | | | | | | +--------------------- stencil bits
|
|
// | | | | | | | | +---+---+---+----- r, g, b, a bits
|
|
// | | | | | | | | r g b a +-- encoding type
|
|
// | | | | | | | | | | | | |
|
|
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC1
|
|
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC2
|
|
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC3
|
|
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC4
|
|
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC5
|
|
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // BC6H
|
|
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC7
|
|
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC1
|
|
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2
|
|
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2A
|
|
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2A1
|
|
{ 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC12
|
|
{ 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC14
|
|
{ 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC12A
|
|
{ 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC14A
|
|
{ 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC22
|
|
{ 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC24
|
|
{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATC
|
|
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATCE
|
|
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATCI
|
|
{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC4x4
|
|
{ 6, 5, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC5x4
|
|
{ 5, 5, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC5x5
|
|
{ 4, 6, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC6x5
|
|
{ 4, 6, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC6x6
|
|
{ 3, 8, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC8x5
|
|
{ 3, 8, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC8x6
|
|
{ 3, 10,5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC10x5
|
|
{ 2, 10,6, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC10x6
|
|
{ 2, 8, 8, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC8x8
|
|
{ 2, 10,8, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC10x8
|
|
{ 1, 10,10,16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC10x10
|
|
{ 1, 12,10,16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC12x10
|
|
{ 1, 12,12,16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC12x12
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_COUNT) }, // Unknown
|
|
{ 8, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // A8
|
|
{ 8, 1, 1, 1, 1, 1, 0, 0, 8, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // R8
|
|
{ 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGBA8
|
|
{ 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_SNORM) }, // RGBA8S
|
|
{ 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG16
|
|
{ 24, 1, 1, 3, 1, 1, 0, 0, 8, 8, 8, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGB8
|
|
{ 16, 1, 1, 2, 1, 1, 0, 0, 16, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // R16
|
|
{ 32, 1, 1, 4, 1, 1, 0, 0, 32, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // R32F
|
|
{ 16, 1, 1, 2, 1, 1, 0, 0, 16, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // R16F
|
|
{ 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // RG16F
|
|
{ 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_SNORM) }, // RG16S
|
|
{ 64, 1, 1, 8, 1, 1, 0, 0, 16, 16, 16, 16, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // RGBA16F
|
|
{ 64, 1, 1, 8, 1, 1, 0, 0, 16, 16, 16, 16, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGBA16
|
|
{ 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BGRA8
|
|
{ 32, 1, 1, 4, 1, 1, 0, 0, 10, 10, 10, 2, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGB10A2
|
|
{ 32, 1, 1, 4, 1, 1, 0, 0, 11, 11, 10, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG11B10F
|
|
{ 16, 1, 1, 2, 1, 1, 0, 0, 8, 8, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG8
|
|
{ 16, 1, 1, 2, 1, 1, 0, 0, 8, 8, 0, 0, (uint8_t)(DDSKTX__ENCODE_SNORM) } // RG8S
|
|
};
|
|
|
|
// KTX: https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
|
|
#define DDSKTX__KTX_MAGIC stc__makefourcc(0xAB, 'K', 'T', 'X')
|
|
#define DDSKTX__KTX_HEADER_SIZE 60 // actual header size is 64, but we read 4 bytes for the 'magic'
|
|
|
|
#define DDSKTX__KTX_ETC1_RGB8_OES 0x8D64
|
|
#define DDSKTX__KTX_COMPRESSED_R11_EAC 0x9270
|
|
#define DDSKTX__KTX_COMPRESSED_SIGNED_R11_EAC 0x9271
|
|
#define DDSKTX__KTX_COMPRESSED_RG11_EAC 0x9272
|
|
#define DDSKTX__KTX_COMPRESSED_SIGNED_RG11_EAC 0x9273
|
|
#define DDSKTX__KTX_COMPRESSED_RGB8_ETC2 0x9274
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ETC2 0x9275
|
|
#define DDSKTX__KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC 0x9278
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
|
|
#define DDSKTX__KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
|
|
#define DDSKTX__KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
|
|
#define DDSKTX__KTX_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
|
|
#define DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
|
|
#define DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
|
|
#define DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
|
|
#define DDSKTX__KTX_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57
|
|
#define DDSKTX__KTX_ATC_RGB_AMD 0x8C92
|
|
#define DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
|
|
#define DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
|
|
#define DDSKTX__KTX_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
|
|
#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
|
|
|
|
#define DDSKTX__KTX_A8 0x803C
|
|
#define DDSKTX__KTX_R8 0x8229
|
|
#define DDSKTX__KTX_R16 0x822A
|
|
#define DDSKTX__KTX_RG8 0x822B
|
|
#define DDSKTX__KTX_RG16 0x822C
|
|
#define DDSKTX__KTX_R16F 0x822D
|
|
#define DDSKTX__KTX_R32F 0x822E
|
|
#define DDSKTX__KTX_RG16F 0x822F
|
|
#define DDSKTX__KTX_RG32F 0x8230
|
|
#define DDSKTX__KTX_RGBA8 0x8058
|
|
#define DDSKTX__KTX_RGBA16 0x805B
|
|
#define DDSKTX__KTX_RGBA16F 0x881A
|
|
#define DDSKTX__KTX_R32UI 0x8236
|
|
#define DDSKTX__KTX_RG32UI 0x823C
|
|
#define DDSKTX__KTX_RGBA32UI 0x8D70
|
|
#define DDSKTX__KTX_RGBA32F 0x8814
|
|
#define DDSKTX__KTX_RGB565 0x8D62
|
|
#define DDSKTX__KTX_RGBA4 0x8056
|
|
#define DDSKTX__KTX_RGB5_A1 0x8057
|
|
#define DDSKTX__KTX_RGB10_A2 0x8059
|
|
#define DDSKTX__KTX_R8I 0x8231
|
|
#define DDSKTX__KTX_R8UI 0x8232
|
|
#define DDSKTX__KTX_R16I 0x8233
|
|
#define DDSKTX__KTX_R16UI 0x8234
|
|
#define DDSKTX__KTX_R32I 0x8235
|
|
#define DDSKTX__KTX_R32UI 0x8236
|
|
#define DDSKTX__KTX_RG8I 0x8237
|
|
#define DDSKTX__KTX_RG8UI 0x8238
|
|
#define DDSKTX__KTX_RG16I 0x8239
|
|
#define DDSKTX__KTX_RG16UI 0x823A
|
|
#define DDSKTX__KTX_RG32I 0x823B
|
|
#define DDSKTX__KTX_RG32UI 0x823C
|
|
#define DDSKTX__KTX_R8_SNORM 0x8F94
|
|
#define DDSKTX__KTX_RG8_SNORM 0x8F95
|
|
#define DDSKTX__KTX_RGB8_SNORM 0x8F96
|
|
#define DDSKTX__KTX_RGBA8_SNORM 0x8F97
|
|
#define DDSKTX__KTX_R16_SNORM 0x8F98
|
|
#define DDSKTX__KTX_RG16_SNORM 0x8F99
|
|
#define DDSKTX__KTX_RGB16_SNORM 0x8F9A
|
|
#define DDSKTX__KTX_RGBA16_SNORM 0x8F9B
|
|
#define DDSKTX__KTX_SRGB8 0x8C41
|
|
#define DDSKTX__KTX_SRGB8_ALPHA8 0x8C43
|
|
#define DDSKTX__KTX_RGBA32UI 0x8D70
|
|
#define DDSKTX__KTX_RGB32UI 0x8D71
|
|
#define DDSKTX__KTX_RGBA16UI 0x8D76
|
|
#define DDSKTX__KTX_RGB16UI 0x8D77
|
|
#define DDSKTX__KTX_RGBA8UI 0x8D7C
|
|
#define DDSKTX__KTX_RGB8UI 0x8D7D
|
|
#define DDSKTX__KTX_RGBA32I 0x8D82
|
|
#define DDSKTX__KTX_RGB32I 0x8D83
|
|
#define DDSKTX__KTX_RGBA16I 0x8D88
|
|
#define DDSKTX__KTX_RGB16I 0x8D89
|
|
#define DDSKTX__KTX_RGBA8I 0x8D8E
|
|
#define DDSKTX__KTX_RGB8 0x8051
|
|
#define DDSKTX__KTX_RGB8I 0x8D8F
|
|
#define DDSKTX__KTX_RGB9_E5 0x8C3D
|
|
#define DDSKTX__KTX_R11F_G11F_B10F 0x8C3A
|
|
|
|
#define DDSKTX__KTX_ZERO 0
|
|
#define DDSKTX__KTX_RED 0x1903
|
|
#define DDSKTX__KTX_ALPHA 0x1906
|
|
#define DDSKTX__KTX_RGB 0x1907
|
|
#define DDSKTX__KTX_RGBA 0x1908
|
|
#define DDSKTX__KTX_BGRA 0x80E1
|
|
#define DDSKTX__KTX_RG 0x8227
|
|
|
|
#define DDSKTX__KTX_BYTE 0x1400
|
|
#define DDSKTX__KTX_UNSIGNED_BYTE 0x1401
|
|
#define DDSKTX__KTX_SHORT 0x1402
|
|
#define DDSKTX__KTX_UNSIGNED_SHORT 0x1403
|
|
#define DDSKTX__KTX_INT 0x1404
|
|
#define DDSKTX__KTX_UNSIGNED_INT 0x1405
|
|
#define DDSKTX__KTX_FLOAT 0x1406
|
|
#define DDSKTX__KTX_HALF_FLOAT 0x140B
|
|
#define DDSKTX__KTX_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
|
|
#define DDSKTX__KTX_UNSIGNED_SHORT_5_6_5 0x8363
|
|
#define DDSKTX__KTX_UNSIGNED_SHORT_4_4_4_4 0x8033
|
|
#define DDSKTX__KTX_UNSIGNED_SHORT_5_5_5_1 0x8034
|
|
#define DDSKTX__KTX_UNSIGNED_INT_2_10_10_10_REV 0x8368
|
|
#define DDSKTX__KTX_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
|
|
|
|
typedef struct ddsktx__ktx_format_info
|
|
{
|
|
uint32_t internal_fmt;
|
|
uint32_t internal_fmt_srgb;
|
|
uint32_t fmt;
|
|
uint32_t type;
|
|
} ddsktx__ktx_format_info;
|
|
|
|
typedef struct ddsktx__ktx_format_info2
|
|
{
|
|
uint32_t internal_fmt;
|
|
ddsktx_format format;
|
|
} ddsktx__ktx_format_info2;
|
|
|
|
static const ddsktx__ktx_format_info k__translate_ktx_fmt[] = {
|
|
{ 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
|
|
{ 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
|
|
{ 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
|
|
{ DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT, DDSKTX__KTX_ZERO, }, // BC4
|
|
{ DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, DDSKTX__KTX_ZERO, }, // BC5
|
|
{ DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, DDSKTX__KTX_ZERO, }, // BC6H
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB, DDSKTX__KTX_ZERO, }, // BC7
|
|
{ DDSKTX__KTX_ETC1_RGB8_OES, DDSKTX__KTX_ZERO, DDSKTX__KTX_ETC1_RGB8_OES, DDSKTX__KTX_ZERO, }, // ETC1
|
|
{ DDSKTX__KTX_COMPRESSED_RGB8_ETC2, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGB8_ETC2, DDSKTX__KTX_ZERO, }, // ETC2
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC, DDSKTX__KTX_COMPRESSED_SRGB8_ETC2, DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC, DDSKTX__KTX_ZERO, }, // ETC2A
|
|
{ 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
|
|
{ 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
|
|
{ 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
|
|
{ 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
|
|
{ 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
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, DDSKTX__KTX_ZERO, }, // PTC22
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, DDSKTX__KTX_ZERO, }, // PTC24
|
|
{ DDSKTX__KTX_ATC_RGB_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGB_AMD, DDSKTX__KTX_ZERO, }, // ATC
|
|
{ DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, DDSKTX__KTX_ZERO, }, // ATCE
|
|
{ DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, DDSKTX__KTX_ZERO, }, // ATCI
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_4x4_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_4x4_KHR, DDSKTX__KTX_ZERO, }, // ASTC4x4
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_5x4_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_5x4_KHR, DDSKTX__KTX_ZERO, }, // ASTC5x4
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_5x5_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_5x5_KHR, DDSKTX__KTX_ZERO, }, // ASTC5x5
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_6x5_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_6x5_KHR, DDSKTX__KTX_ZERO, }, // ASTC6x5
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_6x6_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_6x6_KHR, DDSKTX__KTX_ZERO, }, // ASTC6x6
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_8x5_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_8x5_KHR, DDSKTX__KTX_ZERO, }, // ASTC8x5
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_8x6_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_8x6_KHR, DDSKTX__KTX_ZERO, }, // ASTC8x6
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x5_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x5_KHR, DDSKTX__KTX_ZERO, }, // ASTC10x5
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x6_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x6_KHR, DDSKTX__KTX_ZERO, }, // ASTC10x6
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_8x8_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_8x8_KHR, DDSKTX__KTX_ZERO, }, // ASTC8x8
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x8_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x8_KHR, DDSKTX__KTX_ZERO, }, // ASTC10x8
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x10_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_10x10_KHR, DDSKTX__KTX_ZERO, }, // ASTC10x10
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_12x10_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_12x10_KHR, DDSKTX__KTX_ZERO, }, // ASTC12x10
|
|
{ DDSKTX__KTX_COMPRESSED_RGBA_ASTC_12x12_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ASTC_12x12_KHR, DDSKTX__KTX_ZERO, }, // ASTC12x12
|
|
{ DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, }, // Unknown
|
|
{ DDSKTX__KTX_ALPHA, DDSKTX__KTX_ZERO, DDSKTX__KTX_ALPHA, DDSKTX__KTX_UNSIGNED_BYTE, }, // A8
|
|
{ DDSKTX__KTX_R8, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_BYTE, }, // R8
|
|
{ DDSKTX__KTX_RGBA8, DDSKTX__KTX_SRGB8_ALPHA8, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_BYTE, }, // RGBA8
|
|
{ DDSKTX__KTX_RGBA8_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_BYTE, }, // RGBA8S
|
|
{ DDSKTX__KTX_RG16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_UNSIGNED_SHORT, }, // RG16
|
|
{ DDSKTX__KTX_RGB8, DDSKTX__KTX_SRGB8, DDSKTX__KTX_RGB, DDSKTX__KTX_UNSIGNED_BYTE, }, // RGB8
|
|
{ DDSKTX__KTX_R16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16
|
|
{ DDSKTX__KTX_R32F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_FLOAT, }, // R32F
|
|
{ DDSKTX__KTX_R16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_HALF_FLOAT, }, // R16F
|
|
{ DDSKTX__KTX_RG16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_FLOAT, }, // RG16F
|
|
{ DDSKTX__KTX_RG16_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_SHORT, }, // RG16S
|
|
{ DDSKTX__KTX_RGBA16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_HALF_FLOAT, }, // RGBA16F
|
|
{ DDSKTX__KTX_RGBA16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_SHORT, }, // RGBA16
|
|
{ DDSKTX__KTX_BGRA, DDSKTX__KTX_SRGB8_ALPHA8, DDSKTX__KTX_BGRA, DDSKTX__KTX_UNSIGNED_BYTE, }, // BGRA8
|
|
{ DDSKTX__KTX_RGB10_A2, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_INT_2_10_10_10_REV, }, // RGB10A2
|
|
{ DDSKTX__KTX_R11F_G11F_B10F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGB, DDSKTX__KTX_UNSIGNED_INT_10F_11F_11F_REV, }, // RG11B10F
|
|
{ DDSKTX__KTX_RG8, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_UNSIGNED_BYTE, }, // RG8
|
|
{ DDSKTX__KTX_RG8_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_BYTE, }, // RG8S
|
|
{ DDSKTX__KTX_R16I, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16I
|
|
{ DDSKTX__KTX_R16UI, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16UI
|
|
};
|
|
|
|
static const ddsktx__ktx_format_info2 k__translate_ktx_fmt2[] =
|
|
{
|
|
{ DDSKTX__KTX_A8, DDSKTX_FORMAT_A8 },
|
|
{ DDSKTX__KTX_RED, DDSKTX_FORMAT_R8 },
|
|
{ DDSKTX__KTX_RGB, DDSKTX_FORMAT_RGB8 },
|
|
{ DDSKTX__KTX_RGBA, DDSKTX_FORMAT_RGBA8 },
|
|
{ DDSKTX__KTX_COMPRESSED_RGB_S3TC_DXT1_EXT, DDSKTX_FORMAT_BC1 },
|
|
};
|
|
|
|
typedef struct ddsktx__format_info
|
|
{
|
|
const char* name;
|
|
bool has_alpha;
|
|
} ddsktx__format_info;
|
|
|
|
static const ddsktx__format_info k__formats_info[] = {
|
|
{"BC1", false},
|
|
{"BC2", true},
|
|
{"BC3", true},
|
|
{"BC4", false},
|
|
{"BC5", false},
|
|
{"BC6H", false},
|
|
{"BC7", true},
|
|
{"ETC1", false},
|
|
{"ETC2", false},
|
|
{"ETC2A", true},
|
|
{"ETC2A1", true},
|
|
{"PTC12", false},
|
|
{"PTC14", false},
|
|
{"PTC12A", true},
|
|
{"PTC14A", true},
|
|
{"PTC22", true},
|
|
{"PTC24", true},
|
|
{"ATC", false},
|
|
{"ATCE", false},
|
|
{"ATCI", false},
|
|
{"ASTC4x4", true},
|
|
{"ASTC5x4", true},
|
|
{"ASTC5x5", true},
|
|
{"ASTC6x5", true},
|
|
{"ASTC6x6", true},
|
|
{"ASTC8x5", true},
|
|
{"ASTC8x6", true},
|
|
{"ASTC10x5", true},
|
|
{"ASTC10x6", true},
|
|
{"ASTC8x8", true},
|
|
{"ASTC10x8", true},
|
|
{"ASTC10x10", true},
|
|
{"ASTC12x10", true},
|
|
{"ASTC12x12", true},
|
|
{"<unknown>", false},
|
|
{"A8", true},
|
|
{"R8", false},
|
|
{"RGBA8", true},
|
|
{"RGBA8S", true},
|
|
{"RG16", false},
|
|
{"RGB8", false},
|
|
{"R16", false},
|
|
{"R32F", false},
|
|
{"R16F", false},
|
|
{"RG16F", false},
|
|
{"RG16S", false},
|
|
{"RGBA16F", true},
|
|
{"RGBA16",true},
|
|
{"BGRA8", true},
|
|
{"RGB10A2", true},
|
|
{"RG11B10F", false},
|
|
{"RG8", false},
|
|
{"RG8S", false}
|
|
};
|
|
|
|
|
|
static inline int ddsktx__read(ddsktx__mem_reader* reader, void* buff, int size)
|
|
{
|
|
int read_bytes = (reader->offset + size) <= reader->total ? size : (reader->total - reader->offset);
|
|
ddsktx_memcpy(buff, reader->buff + reader->offset, read_bytes);
|
|
reader->offset += read_bytes;
|
|
return read_bytes;
|
|
}
|
|
|
|
static bool ddsktx__parse_ktx(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err)
|
|
{
|
|
static const uint8_t ktx__id[] = { 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
|
|
|
|
ddsktx_memset(tc, 0x0, sizeof(ddsktx_texture_info));
|
|
|
|
ddsktx__mem_reader r = {(const uint8_t*)file_data, size, sizeof(uint32_t)};
|
|
ddsktx__ktx_header header;
|
|
if (ddsktx__read(&r, &header, sizeof(header)) != DDSKTX__KTX_HEADER_SIZE) {
|
|
ddsktx__err(err, "ktx; header size does not match");
|
|
}
|
|
|
|
if (ddsktx_memcmp(header.id, ktx__id, sizeof(header.id)) != 0) {
|
|
ddsktx__err(err, "ktx: invalid file header");
|
|
}
|
|
|
|
// TODO: support big endian
|
|
if (header.endianess != 0x04030201) {
|
|
ddsktx__err(err, "ktx: big-endian format is not supported");
|
|
}
|
|
|
|
tc->metadata_offset = r.offset;
|
|
tc->metadata_size = (int)header.metadata_size;
|
|
r.offset += (int)header.metadata_size;
|
|
|
|
ddsktx_format format = _DDSKTX_FORMAT_COUNT;
|
|
|
|
int count = sizeof(k__translate_ktx_fmt)/sizeof(ddsktx__ktx_format_info);
|
|
for (int i = 0; i < count; i++) {
|
|
if (k__translate_ktx_fmt[i].internal_fmt == header.internal_format) {
|
|
format = (ddsktx_format)i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (format == _DDSKTX_FORMAT_COUNT) {
|
|
count = sizeof(k__translate_ktx_fmt2)/sizeof(ddsktx__ktx_format_info2);
|
|
for (int i = 0; i < count; i++) {
|
|
if (k__translate_ktx_fmt2[i].internal_fmt == header.internal_format) {
|
|
format = (ddsktx_format)k__translate_ktx_fmt2[i].format;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (format == _DDSKTX_FORMAT_COUNT) {
|
|
ddsktx__err(err, "ktx: unsupported format");
|
|
}
|
|
|
|
if (header.face_count > 1 && header.face_count != DDSKTX_CUBE_FACE_COUNT) {
|
|
ddsktx__err(err, "ktx: incomplete cubemap");
|
|
}
|
|
|
|
tc->data_offset = r.offset;
|
|
tc->size_bytes = r.total - r.offset;
|
|
tc->format = format;
|
|
tc->width = (int)header.width;
|
|
tc->height = (int)header.height;
|
|
tc->depth = ddsktx__max((int)header.depth, 1);
|
|
tc->num_layers = ddsktx__max((int)header.array_count, 1);
|
|
tc->num_mips = ddsktx__max((int)header.mip_count, 1);
|
|
tc->bpp = k__block_info[format].bpp;
|
|
|
|
if (header.face_count == 6)
|
|
tc->flags |= DDSKTX_TEXTURE_FLAG_CUBEMAP;
|
|
tc->flags |= k__formats_info[format].has_alpha ? DDSKTX_TEXTURE_FLAG_ALPHA : 0;
|
|
tc->flags |= DDSKTX_TEXTURE_FLAG_KTX;
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool ddsktx__parse_dds(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err)
|
|
{
|
|
ddsktx__mem_reader r = {(const uint8_t*)file_data, size, sizeof(uint32_t)};
|
|
ddsktx__dds_header header;
|
|
if (ddsktx__read(&r, &header, sizeof(header)) < DDSKTX__DDS_HEADER_SIZE ||
|
|
header.size != DDSKTX__DDS_HEADER_SIZE)
|
|
{
|
|
ddsktx__err(err, "dds: header size does not match");
|
|
}
|
|
|
|
uint32_t required_flags = (DDSKTX__DDSD_HEIGHT|DDSKTX__DDSD_WIDTH);
|
|
if ((header.flags & required_flags) != required_flags) {
|
|
ddsktx__err(err, "dds: have invalid flags");
|
|
}
|
|
|
|
if (header.pixel_format.size != sizeof(ddsktx__dds_pixel_format)) {
|
|
ddsktx__err(err, "dds: pixel format header is invalid");
|
|
}
|
|
|
|
uint32_t dxgi_format = 0;
|
|
uint32_t array_size = 1;
|
|
if (DDSKTX__DDPF_FOURCC == (header.flags & DDSKTX__DDPF_FOURCC) &&
|
|
header.pixel_format.fourcc == DDSKTX__DDS_DX10)
|
|
{
|
|
ddsktx__dds_header_dxgi dxgi_header;
|
|
ddsktx__read(&r, &dxgi_header, sizeof(dxgi_header));
|
|
dxgi_format = dxgi_header.dxgi_format;
|
|
array_size = dxgi_header.array_size;
|
|
}
|
|
|
|
if ((header.caps1 & DDSKTX__DDSCAPS_TEXTURE) == 0) {
|
|
ddsktx__err(err, "dds: unsupported caps");
|
|
}
|
|
|
|
bool cubemap = (header.caps2 & DDSKTX__DDSCAPS2_CUBEMAP) != 0;
|
|
if (cubemap && (header.caps2 & DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES) != DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES) {
|
|
ddsktx__err(err, "dds: incomplete cubemap");
|
|
}
|
|
bool volume = (header.caps2 & DDSKTX__DDSCAPS2_VOLUME) != 0;
|
|
|
|
ddsktx_format format = _DDSKTX_FORMAT_COUNT;
|
|
bool has_alpha = (header.pixel_format.flags & DDSKTX__DDPF_ALPHA) != 0;
|
|
bool srgb = false;
|
|
|
|
if (dxgi_format == 0) {
|
|
if ((header.pixel_format.flags & DDSKTX__DDPF_FOURCC) == DDSKTX__DDPF_FOURCC) {
|
|
int count = sizeof(k__translate_dds_fourcc)/sizeof(ddsktx__dds_translate_fourcc_format);
|
|
for (int i = 0; i < count; i++) {
|
|
if (k__translate_dds_fourcc[i].dds_format == header.pixel_format.fourcc) {
|
|
format = k__translate_dds_fourcc[i].format;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
int count = sizeof(k__translate_dds_pixel)/sizeof(ddsktx__dds_translate_pixel_format);
|
|
for (int i = 0; i < count; i++) {
|
|
const ddsktx__dds_translate_pixel_format* f = &k__translate_dds_pixel[i];
|
|
if (f->bit_count == header.pixel_format.rgb_bit_count &&
|
|
f->flags == header.pixel_format.flags &&
|
|
f->bit_mask[0] == header.pixel_format.bit_mask[0] &&
|
|
f->bit_mask[1] == header.pixel_format.bit_mask[1] &&
|
|
f->bit_mask[2] == header.pixel_format.bit_mask[2] &&
|
|
f->bit_mask[3] == header.pixel_format.bit_mask[3])
|
|
{
|
|
format = f->format;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
int count = sizeof(k__translate_dxgi)/sizeof(ddsktx__dds_translate_fourcc_format);
|
|
for (int i = 0; i < count; i++) {
|
|
if (k__translate_dxgi[i].dds_format == dxgi_format) {
|
|
format = k__translate_dxgi[i].format;
|
|
srgb = k__translate_dxgi[i].srgb;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (format == _DDSKTX_FORMAT_COUNT) {
|
|
ddsktx__err(err, "dds: unknown format");
|
|
}
|
|
|
|
ddsktx_memset(tc, 0x0, sizeof(ddsktx_texture_info));
|
|
tc->data_offset = r.offset;
|
|
tc->size_bytes = r.total - r.offset;
|
|
tc->format = format;
|
|
tc->width = (int)header.width;
|
|
tc->height = (int)header.height;
|
|
tc->depth = ddsktx__max(1, (int)header.depth);
|
|
tc->num_layers = ddsktx__max(1, (int)array_size);
|
|
tc->num_mips = (header.caps1 & DDSKTX__DDSCAPS_MIPMAP) ? (int)header.mip_count : 1;
|
|
tc->bpp = k__block_info[format].bpp;
|
|
if (has_alpha || k__formats_info[format].has_alpha)
|
|
tc->flags |= DDSKTX_TEXTURE_FLAG_ALPHA;
|
|
if (cubemap)
|
|
tc->flags |= DDSKTX_TEXTURE_FLAG_CUBEMAP;
|
|
if (volume)
|
|
tc->flags |= DDSKTX_TEXTURE_FLAG_VOLUME;
|
|
if (srgb)
|
|
tc->flags |= DDSKTX_TEXTURE_FLAG_SRGB;
|
|
tc->flags |= DDSKTX_TEXTURE_FLAG_DDS;
|
|
|
|
return true;
|
|
}
|
|
|
|
void ddsktx_get_sub(const ddsktx_texture_info* tc, ddsktx_sub_data* sub_data,
|
|
const void* file_data, int size,
|
|
int array_idx, int slice_face_idx, int mip_idx)
|
|
{
|
|
ddsktx_assert(tc);
|
|
ddsktx_assert(sub_data);
|
|
ddsktx_assert(file_data);
|
|
ddsktx_assert(size > 0);
|
|
ddsktx_assert(array_idx < tc->num_layers);
|
|
ddsktx_assert(!((tc->flags&DDSKTX_TEXTURE_FLAG_CUBEMAP) && (slice_face_idx >= DDSKTX_CUBE_FACE_COUNT)) && "invalid cube-face index");
|
|
ddsktx_assert(!(!(tc->flags&DDSKTX_TEXTURE_FLAG_CUBEMAP) && (slice_face_idx >= tc->depth)) && "invalid depth-slice index");
|
|
ddsktx_assert(mip_idx < tc->num_mips);
|
|
|
|
ddsktx__mem_reader r = { (uint8_t*)file_data, size, tc->data_offset };
|
|
ddsktx_format format = tc->format;
|
|
|
|
ddsktx_assert(format < _DDSKTX_FORMAT_COUNT && format != _DDSKTX_FORMAT_COMPRESSED);
|
|
const ddsktx__block_info* binfo = &k__block_info[format];
|
|
const int bpp = binfo->bpp;
|
|
const int block_width = binfo->block_width;
|
|
const int block_height = binfo->block_height;
|
|
const int block_size = binfo->block_size;
|
|
const int min_block_x = binfo->min_block_x;
|
|
const int min_block_y = binfo->min_block_y;
|
|
|
|
int num_faces;
|
|
|
|
ddsktx_assert(!((tc->flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) && tc->depth > 1) && "textures must be either Cube or 3D");
|
|
int slice_idx, face_idx, num_slices;
|
|
if (tc->flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) {
|
|
slice_idx = 0;
|
|
face_idx = slice_face_idx;
|
|
num_faces = DDSKTX_CUBE_FACE_COUNT;
|
|
num_slices = 1;
|
|
} else {
|
|
slice_idx = slice_face_idx;
|
|
face_idx = 0;
|
|
num_faces = 1;
|
|
num_slices = tc->depth;
|
|
}
|
|
|
|
if (tc->flags & DDSKTX_TEXTURE_FLAG_DDS) {
|
|
for (int layer = 0, num_layers = tc->num_layers; layer < num_layers; layer++) {
|
|
for (int face = 0; face < num_faces; face++) {
|
|
int width = tc->width;
|
|
int height = tc->height;
|
|
|
|
for (int mip = 0, mip_count = tc->num_mips; mip < mip_count; mip++) {
|
|
int row_bytes, mip_size;
|
|
|
|
if (format < _DDSKTX_FORMAT_COMPRESSED) {
|
|
int num_blocks_wide = width > 0 ? ddsktx__max(1, (width + (block_width-1)) / block_width) : 0;
|
|
num_blocks_wide = ddsktx__max(min_block_x, num_blocks_wide);
|
|
|
|
int num_blocks_high = height > 0 ? ddsktx__max(1, (height + (block_height-1)) / block_height) : 0;
|
|
num_blocks_high = ddsktx__max(min_block_y, num_blocks_high);
|
|
|
|
row_bytes = num_blocks_wide * block_size;
|
|
mip_size = row_bytes * num_blocks_high;
|
|
} else {
|
|
row_bytes = (width*bpp + 7)/8; // round to nearest byte
|
|
mip_size = row_bytes * height;
|
|
}
|
|
|
|
for (int slice = 0; slice < num_slices; slice++) {
|
|
if (layer == array_idx && mip == mip_idx &&
|
|
slice == slice_idx && face_idx == face)
|
|
{
|
|
sub_data->buff = r.buff + r.offset;
|
|
sub_data->width = width;
|
|
sub_data->height = height;
|
|
sub_data->size_bytes = mip_size;
|
|
sub_data->row_pitch_bytes = row_bytes;
|
|
return;
|
|
}
|
|
|
|
r.offset += mip_size;
|
|
ddsktx_assert(r.offset <= r.total && "texture buffer overflow");
|
|
} // foreach slice
|
|
|
|
width >>= 1;
|
|
height >>= 1;
|
|
|
|
if (width == 0) {
|
|
width = 1;
|
|
}
|
|
if (height == 0) {
|
|
height = 1;
|
|
}
|
|
} // foreach mip
|
|
} // foreach face
|
|
} // foreach array-item
|
|
} else if (tc->flags & DDSKTX_TEXTURE_FLAG_KTX) {
|
|
int width = tc->width;
|
|
int height = tc->height;
|
|
|
|
for (int mip = 0, c = tc->num_mips; mip < c; mip++) {
|
|
int row_bytes, mip_size;
|
|
|
|
if (format < _DDSKTX_FORMAT_COMPRESSED) {
|
|
int num_blocks_wide = width > 0 ? ddsktx__max(1, (width + (block_width-1)) / block_width) : 0;
|
|
num_blocks_wide = ddsktx__max(min_block_x, num_blocks_wide);
|
|
|
|
int num_blocks_high = height > 0 ? ddsktx__max(1, (height + (block_height-1)) / block_height) : 0;
|
|
num_blocks_high = ddsktx__max(min_block_y, num_blocks_high);
|
|
|
|
row_bytes = num_blocks_wide * block_size;
|
|
mip_size = row_bytes * num_blocks_high;
|
|
}
|
|
else {
|
|
row_bytes = (width*bpp + 7)/8; // round to nearest byte
|
|
mip_size = row_bytes * height;
|
|
}
|
|
|
|
int image_size;
|
|
ddsktx__read(&r, &image_size, sizeof(image_size));
|
|
ddsktx_assert(image_size == (mip_size*num_faces*num_slices) && "image size mismatch");
|
|
|
|
for (int layer = 0, num_layers = tc->num_layers; layer < num_layers; layer++) {
|
|
for (int face = 0; face < num_faces; face++) {
|
|
for (int slice = 0; slice < num_slices; slice++) {
|
|
if (layer == array_idx && mip == mip_idx &&
|
|
slice == slice_idx && face_idx == face)
|
|
{
|
|
sub_data->buff = r.buff + r.offset;
|
|
sub_data->width = width;
|
|
sub_data->height = height;
|
|
sub_data->size_bytes = mip_size;
|
|
sub_data->row_pitch_bytes = row_bytes;
|
|
return;
|
|
}
|
|
|
|
r.offset += mip_size;
|
|
ddsktx_assert(r.offset <= r.total && "texture buffer overflow");
|
|
} // foreach slice
|
|
|
|
|
|
r.offset = ddsktx__align_mask(r.offset, 3); // cube-padding
|
|
} // foreach face
|
|
} // foreach array-item
|
|
|
|
width >>= 1;
|
|
height >>= 1;
|
|
|
|
if (width == 0) {
|
|
width = 1;
|
|
}
|
|
if (height == 0) {
|
|
height = 1;
|
|
}
|
|
|
|
r.offset = ddsktx__align_mask(r.offset, 3); // mip-padding
|
|
} // foreach mip
|
|
} else {
|
|
ddsktx_assert(0 && "invalid file format");
|
|
}
|
|
}
|
|
|
|
bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err)
|
|
{
|
|
ddsktx_assert(tc);
|
|
ddsktx_assert(file_data);
|
|
ddsktx_assert(size > 0);
|
|
|
|
ddsktx__mem_reader r = {(const uint8_t*)file_data, size, 0};
|
|
|
|
// Read file flag and determine the file type
|
|
uint32_t file_flag = 0;
|
|
if (ddsktx__read(&r, &file_flag, sizeof(file_flag)) != sizeof(file_flag)) {
|
|
ddsktx__err(err, "invalid texture file");
|
|
}
|
|
|
|
switch (file_flag) {
|
|
case DDSKTX__DDS_MAGIC:
|
|
return ddsktx__parse_dds(tc, file_data, size, err);
|
|
case DDSKTX__KTX_MAGIC:
|
|
return ddsktx__parse_ktx(tc, file_data, size, err);
|
|
default:
|
|
ddsktx__err(err, "unknown texture format");
|
|
}
|
|
}
|
|
|
|
const char* ddsktx_format_str(ddsktx_format format)
|
|
{
|
|
return k__formats_info[format].name;
|
|
}
|
|
|
|
bool ddsktx_format_compressed(ddsktx_format format)
|
|
{
|
|
ddsktx_assert(format != _DDSKTX_FORMAT_COMPRESSED && format != _DDSKTX_FORMAT_COUNT);
|
|
return format < _DDSKTX_FORMAT_COMPRESSED;
|
|
}
|
|
|
|
#endif // DDSKTX_IMPLEMENT
|
|
|