Path: blob/a-new-beginning/SharedDependencies/Sources/dds_ktx/include/dds_ktx.h
2 views
//1// Copyright 2018 Sepehr Taghdisian (septag@github). All rights reserved.2// License: https://github.com/septag/dds-ktx#license-bsd-2-clause3//4// Many parts of this code is taken from bimg library:5// https://github.com/bkaradzic/bimg6//7// Copyright 2011-2019 Branimir Karadzic. All rights reserved.8// License: https://github.com/bkaradzic/bimg#license-bsd-2-clause9//10// dds-ktx.h - v1.1.0 - Reader/Writer for DDS/KTX formats11// Parses DDS and KTX files from a memory blob, written in C9912//13// Supported formats:14// For supported formats, see ddsktx_format enum.15// Both KTX/DDS parser supports all formats defined in ddsktx_format16//17// Overriable macros:18// DDSKTX_API Define any function specifier for public functions (default: extern)19// ddsktx_memcpy default: memcpy(dst, src, size)20// ddsktx_memset default: memset(dst, v, size)21// ddsktx_assert default: assert(a)22// ddsktx_strcpy default: strcpy(dst, src)23// ddsktx_memcmp default: memcmp(ptr1, ptr2, size)24//25// API:26// bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err);27// Parses texture file and fills the ddsktx_texture_info struct28// Returns true if successfully parsed, false if failed with an error message inside ddsktx_error parameter (optional)29// After format is parsed, you can read the contents of ddsktx_format and create your GPU texture30// To get pointer to mips and slices see ddsktx_get_sub function31//32// void ddsktx_get_sub(const ddsktx_texture_info* tex, ddsktx_sub_data* buff,33// const void* file_data, int size,34// int array_idx, int slice_face_idx, int mip_idx);35// Gets sub-image data, form a parsed texture file36// user must provided the container object and the original file data which was passed to ddsktx_parse37// array_idx: array index (0..num_layers)38// slice_face_idx: depth-slice or cube-face index.39// if 'flags' have DDSKTX_TEXTURE_FLAG_CUBEMAP bit, then this value represents cube-face-index (0..DDSKTX_CUBE_FACE_COUNT)40// else it represents depth slice index (0..depth)41// mip_idx: mip index (0..num_mips-1 in ddsktx_texture_info)42//43// const char* ddsktx_format_str(ddsktx_format format);44// Converts a format enumeration to string45//46// bool ddsktx_format_compressed(ddsktx_format format);47// Returns true if format is compressed48//49// Example (for 2D textures only):50// int size;51// void* dds_data = load_file("test.dds", &size);52// assert(dds_data);53// ddsktx_texture_info tc = {0};54// if (ddsktx_parse(&tc, dds_data, size, NULL)) {55// assert(tc.depth == 1);56// assert(!(tc.flags & DDSKTX_TEXTURE_FLAG_CUBEMAP));57// assert(tc.num_layers == 1);58// // Create GPU texture from tc data59// for (int mip = 0; mip < tc.num_mips; mip++) {60// ddsktx_sub_data sub_data;61// ddsktx_get_sub(&tc, &sub_data, dds_data, size, 0, 0, mip);62// // Fill/Set texture sub resource data (mips in this case)63// }64// }65// free(dds_data); // memory must be valid during stc_ calls66//67// Version history:68// 0.9.0 Initial release, ktx is incomplete69// 1.0.0 Api change: ddsktx_sub_data70// Added KTX support71// 1.0.1 Fixed major bugs in KTX parsing72// 1.1.0 Fixed bugs in get_sub routine, refactored some parts, image-viewer example73//74// TODO75// Write KTX/DDS76// Read KTX metadata. currently it just stores the offset/size to the metadata block77//7879#pragma once8081#include <stddef.h>82#include <stdint.h>83#include <stdbool.h>8485#ifndef DDSKTX_API86# ifdef __cplusplus87# define DDSKTX_API extern "C"88# else89# define DDSKTX_API90# endif91#endif9293typedef struct ddsktx_sub_data94{95const void* buff;96int width;97int height;98int size_bytes;99int row_pitch_bytes;100} ddsktx_sub_data;101102typedef enum ddsktx_format103{104DDSKTX_FORMAT_BC1, // DXT1105DDSKTX_FORMAT_BC2, // DXT3106DDSKTX_FORMAT_BC3, // DXT5107DDSKTX_FORMAT_BC4, // ATI1108DDSKTX_FORMAT_BC5, // ATI2109DDSKTX_FORMAT_BC6H, // BC6H110DDSKTX_FORMAT_BC7, // BC7111DDSKTX_FORMAT_ETC1, // ETC1 RGB8112DDSKTX_FORMAT_ETC2, // ETC2 RGB8113DDSKTX_FORMAT_ETC2A, // ETC2 RGBA8114DDSKTX_FORMAT_ETC2A1, // ETC2 RGB8A1115DDSKTX_FORMAT_PTC12, // PVRTC1 RGB 2bpp116DDSKTX_FORMAT_PTC14, // PVRTC1 RGB 4bpp117DDSKTX_FORMAT_PTC12A, // PVRTC1 RGBA 2bpp118DDSKTX_FORMAT_PTC14A, // PVRTC1 RGBA 4bpp119DDSKTX_FORMAT_PTC22, // PVRTC2 RGBA 2bpp120DDSKTX_FORMAT_PTC24, // PVRTC2 RGBA 4bpp121DDSKTX_FORMAT_ATC, // ATC RGB 4BPP122DDSKTX_FORMAT_ATCE, // ATCE RGBA 8 BPP explicit alpha123DDSKTX_FORMAT_ATCI, // ATCI RGBA 8 BPP interpolated alpha124DDSKTX_FORMAT_ASTC4x4, // ASTC 4x4 8.0 BPP125DDSKTX_FORMAT_ASTC5x5, // ASTC 5x5 5.12 BPP126DDSKTX_FORMAT_ASTC6x6, // ASTC 6x6 3.56 BPP127DDSKTX_FORMAT_ASTC8x5, // ASTC 8x5 3.20 BPP128DDSKTX_FORMAT_ASTC8x6, // ASTC 8x6 2.67 BPP129DDSKTX_FORMAT_ASTC10x5, // ASTC 10x5 2.56 BPP130_DDSKTX_FORMAT_COMPRESSED,131DDSKTX_FORMAT_A8,132DDSKTX_FORMAT_R8,133DDSKTX_FORMAT_RGBA8,134DDSKTX_FORMAT_RGBA8S,135DDSKTX_FORMAT_RG16,136DDSKTX_FORMAT_RGB8,137DDSKTX_FORMAT_R16,138DDSKTX_FORMAT_R32F,139DDSKTX_FORMAT_R16F,140DDSKTX_FORMAT_RG16F,141DDSKTX_FORMAT_RG16S,142DDSKTX_FORMAT_RGBA16F,143DDSKTX_FORMAT_RGBA16,144DDSKTX_FORMAT_BGRA8,145DDSKTX_FORMAT_RGB10A2,146DDSKTX_FORMAT_RG11B10F,147DDSKTX_FORMAT_RG8,148DDSKTX_FORMAT_RG8S,149_DDSKTX_FORMAT_COUNT150} ddsktx_format;151152typedef enum ddsktx_texture_flags153{154DDSKTX_TEXTURE_FLAG_CUBEMAP = 0x01,155DDSKTX_TEXTURE_FLAG_SRGB = 0x02,156DDSKTX_TEXTURE_FLAG_ALPHA = 0x04, // Has alpha channel157DDSKTX_TEXTURE_FLAG_DDS = 0x08, // container was DDS file158DDSKTX_TEXTURE_FLAG_KTX = 0x10, // container was KTX file159DDSKTX_TEXTURE_FLAG_VOLUME = 0x20, // 3D volume160} ddsktx_texture_flags;161162typedef struct ddsktx_texture_info163{164int data_offset; // start offset of pixel data165int size_bytes;166ddsktx_format format;167unsigned int flags; // ddsktx_texture_flags168int width;169int height;170int depth;171int num_layers;172int num_mips;173int bpp;174int metadata_offset; // ktx only175int metadata_size; // ktx only176} ddsktx_texture_info;177178typedef enum ddsktx_cube_face179{180DDSKTX_CUBE_FACE_X_POSITIVE = 0,181DDSKTX_CUBE_FACE_X_NEGATIVE,182DDSKTX_CUBE_FACE_Y_POSITIVE,183DDSKTX_CUBE_FACE_Y_NEGATIVE,184DDSKTX_CUBE_FACE_Z_POSITIVE,185DDSKTX_CUBE_FACE_Z_NEGATIVE,186DDSKTX_CUBE_FACE_COUNT187} ddsktx_cube_face;188189typedef struct ddsktx_error190{191char msg[256];192} ddsktx_error;193194#ifdef __cplusplus195# define ddsktx_default(_v) =_v196#else197# define ddsktx_default(_v)198#endif199200DDSKTX_API bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err ddsktx_default(NULL));201DDSKTX_API void ddsktx_get_sub(const ddsktx_texture_info* tex, ddsktx_sub_data* buff,202const void* file_data, int size,203int array_idx, int slice_face_idx, int mip_idx);204DDSKTX_API const char* ddsktx_format_str(ddsktx_format format);205DDSKTX_API bool ddsktx_format_compressed(ddsktx_format format);206207////////////////////////////////////////////////////////////////////////////////////////////////////208// Implementation209#ifdef DDSKTX_IMPLEMENT210211#define stc__makefourcc(_a, _b, _c, _d) ( ( (uint32_t)(_a) | ( (uint32_t)(_b) << 8) | \212( (uint32_t)(_c) << 16) | ( (uint32_t)(_d) << 24) ) )213214// DDS: https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dx-graphics-dds-pguide215#define DDSKTX__DDS_HEADER_SIZE 124216#define DDSKTX__DDS_MAGIC stc__makefourcc('D', 'D', 'S', ' ')217#define DDSKTX__DDS_DXT1 stc__makefourcc('D', 'X', 'T', '1')218#define DDSKTX__DDS_DXT2 stc__makefourcc('D', 'X', 'T', '2')219#define DDSKTX__DDS_DXT3 stc__makefourcc('D', 'X', 'T', '3')220#define DDSKTX__DDS_DXT4 stc__makefourcc('D', 'X', 'T', '4')221#define DDSKTX__DDS_DXT5 stc__makefourcc('D', 'X', 'T', '5')222#define DDSKTX__DDS_ATI1 stc__makefourcc('A', 'T', 'I', '1')223#define DDSKTX__DDS_BC4U stc__makefourcc('B', 'C', '4', 'U')224#define DDSKTX__DDS_ATI2 stc__makefourcc('A', 'T', 'I', '2')225#define DDSKTX__DDS_BC5U stc__makefourcc('B', 'C', '5', 'U')226#define DDSKTX__DDS_DX10 stc__makefourcc('D', 'X', '1', '0')227228#define DDSKTX__DDS_ETC1 stc__makefourcc('E', 'T', 'C', '1')229#define DDSKTX__DDS_ETC2 stc__makefourcc('E', 'T', 'C', '2')230#define DDSKTX__DDS_ET2A stc__makefourcc('E', 'T', '2', 'A')231#define DDSKTX__DDS_PTC2 stc__makefourcc('P', 'T', 'C', '2')232#define DDSKTX__DDS_PTC4 stc__makefourcc('P', 'T', 'C', '4')233#define DDSKTX__DDS_ATC stc__makefourcc('A', 'T', 'C', ' ')234#define DDSKTX__DDS_ATCE stc__makefourcc('A', 'T', 'C', 'E')235#define DDSKTX__DDS_ATCI stc__makefourcc('A', 'T', 'C', 'I')236#define DDSKTX__DDS_ASTC4x4 stc__makefourcc('A', 'S', '4', '4')237#define DDSKTX__DDS_ASTC5x5 stc__makefourcc('A', 'S', '5', '5')238#define DDSKTX__DDS_ASTC6x6 stc__makefourcc('A', 'S', '6', '6')239#define DDSKTX__DDS_ASTC8x5 stc__makefourcc('A', 'S', '8', '5')240#define DDSKTX__DDS_ASTC8x6 stc__makefourcc('A', 'S', '8', '6')241#define DDSKTX__DDS_ASTC10x5 stc__makefourcc('A', 'S', ':', '5')242243#define DDSKTX__DDS_R8G8B8 20244#define DDSKTX__DDS_A8R8G8B8 21245#define DDSKTX__DDS_R5G6B5 23246#define DDSKTX__DDS_A1R5G5B5 25247#define DDSKTX__DDS_A4R4G4B4 26248#define DDSKTX__DDS_A2B10G10R10 31249#define DDSKTX__DDS_G16R16 34250#define DDSKTX__DDS_A2R10G10B10 35251#define DDSKTX__DDS_A16B16G16R16 36252#define DDSKTX__DDS_A8L8 51253#define DDSKTX__DDS_R16F 111254#define DDSKTX__DDS_G16R16F 112255#define DDSKTX__DDS_A16B16G16R16F 113256#define DDSKTX__DDS_R32F 114257#define DDSKTX__DDS_G32R32F 115258#define DDSKTX__DDS_A32B32G32R32F 116259260#define DDSKTX__DDS_FORMAT_R32G32B32A32_FLOAT 2261#define DDSKTX__DDS_FORMAT_R32G32B32A32_UINT 3262#define DDSKTX__DDS_FORMAT_R16G16B16A16_FLOAT 10263#define DDSKTX__DDS_FORMAT_R16G16B16A16_UNORM 11264#define DDSKTX__DDS_FORMAT_R16G16B16A16_UINT 12265#define DDSKTX__DDS_FORMAT_R32G32_FLOAT 16266#define DDSKTX__DDS_FORMAT_R32G32_UINT 17267#define DDSKTX__DDS_FORMAT_R10G10B10A2_UNORM 24268#define DDSKTX__DDS_FORMAT_R11G11B10_FLOAT 26269#define DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM 28270#define DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM_SRGB 29271#define DDSKTX__DDS_FORMAT_R16G16_FLOAT 34272#define DDSKTX__DDS_FORMAT_R16G16_UNORM 35273#define DDSKTX__DDS_FORMAT_R32_FLOAT 41274#define DDSKTX__DDS_FORMAT_R32_UINT 42275#define DDSKTX__DDS_FORMAT_R8G8_UNORM 49276#define DDSKTX__DDS_FORMAT_R16_FLOAT 54277#define DDSKTX__DDS_FORMAT_R16_UNORM 56278#define DDSKTX__DDS_FORMAT_R8_UNORM 61279#define DDSKTX__DDS_FORMAT_R1_UNORM 66280#define DDSKTX__DDS_FORMAT_BC1_UNORM 71281#define DDSKTX__DDS_FORMAT_BC1_UNORM_SRGB 72282#define DDSKTX__DDS_FORMAT_BC2_UNORM 74283#define DDSKTX__DDS_FORMAT_BC2_UNORM_SRGB 75284#define DDSKTX__DDS_FORMAT_BC3_UNORM 77285#define DDSKTX__DDS_FORMAT_BC3_UNORM_SRGB 78286#define DDSKTX__DDS_FORMAT_BC4_UNORM 80287#define DDSKTX__DDS_FORMAT_BC5_UNORM 83288#define DDSKTX__DDS_FORMAT_B5G6R5_UNORM 85289#define DDSKTX__DDS_FORMAT_B5G5R5A1_UNORM 86290#define DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM 87291#define DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM_SRGB 91292#define DDSKTX__DDS_FORMAT_BC6H_SF16 96293#define DDSKTX__DDS_FORMAT_BC7_UNORM 98294#define DDSKTX__DDS_FORMAT_BC7_UNORM_SRGB 99295#define DDSKTX__DDS_FORMAT_B4G4R4A4_UNORM 115296297#define DDSKTX__DDS_DX10_DIMENSION_TEXTURE2D 3298#define DDSKTX__DDS_DX10_DIMENSION_TEXTURE3D 4299#define DDSKTX__DDS_DX10_MISC_TEXTURECUBE 4300301#define DDSKTX__DDSD_CAPS 0x00000001302#define DDSKTX__DDSD_HEIGHT 0x00000002303#define DDSKTX__DDSD_WIDTH 0x00000004304#define DDSKTX__DDSD_PITCH 0x00000008305#define DDSKTX__DDSD_PIXELFORMAT 0x00001000306#define DDSKTX__DDSD_MIPMAPCOUNT 0x00020000307#define DDSKTX__DDSD_LINEARSIZE 0x00080000308#define DDSKTX__DDSD_DEPTH 0x00800000309310#define DDSKTX__DDPF_ALPHAPIXELS 0x00000001311#define DDSKTX__DDPF_ALPHA 0x00000002312#define DDSKTX__DDPF_FOURCC 0x00000004313#define DDSKTX__DDPF_INDEXED 0x00000020314#define DDSKTX__DDPF_RGB 0x00000040315#define DDSKTX__DDPF_YUV 0x00000200316#define DDSKTX__DDPF_LUMINANCE 0x00020000317#define DDSKTX__DDPF_BUMPDUDV 0x00080000318319#define DDSKTX__DDSCAPS_COMPLEX 0x00000008320#define DDSKTX__DDSCAPS_TEXTURE 0x00001000321#define DDSKTX__DDSCAPS_MIPMAP 0x00400000322323#define DDSKTX__DDSCAPS2_VOLUME 0x00200000324#define DDSKTX__DDSCAPS2_CUBEMAP 0x00000200325#define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400326#define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800327#define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000328#define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000329#define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000330#define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000331332#define DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES (0 \333| DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEX \334| DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEX \335| DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEY \336| DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEY \337| DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEZ \338| DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEZ )339340#pragma pack(push, 1)341typedef struct ddsktx__dds_pixel_format342{343uint32_t size;344uint32_t flags;345uint32_t fourcc;346uint32_t rgb_bit_count;347uint32_t bit_mask[4];348} ddsktx__dds_pixel_format;349350// https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dds-header351typedef struct ddsktx__dds_header352{353uint32_t size;354uint32_t flags;355uint32_t height;356uint32_t width;357uint32_t pitch_lin_size;358uint32_t depth;359uint32_t mip_count;360uint32_t reserved1[11];361ddsktx__dds_pixel_format pixel_format;362uint32_t caps1;363uint32_t caps2;364uint32_t caps3;365uint32_t caps4;366uint32_t reserved2;367} ddsktx__dds_header;368369// https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dds-header-dxt10370typedef struct ddsktx__dds_header_dxgi371{372uint32_t dxgi_format;373uint32_t dimension;374uint32_t misc_flags;375uint32_t array_size;376uint32_t misc_flags2;377} ddsktx__dds_header_dxgi;378379typedef struct ddsktx__ktx_header380{381uint8_t id[8];382uint32_t endianess;383uint32_t type;384uint32_t type_size;385uint32_t format;386uint32_t internal_format;387uint32_t base_internal_format;388uint32_t width;389uint32_t height;390uint32_t depth;391uint32_t array_count;392uint32_t face_count;393uint32_t mip_count;394uint32_t metadata_size;395} ddsktx__ktx_header;396#pragma pack(pop)397398typedef struct ddsktx__dds_translate_fourcc_format399{400uint32_t dds_format;401ddsktx_format format;402bool srgb;403} ddsktx__dds_translate_fourcc_format;404405typedef struct ddsktx__dds_translate_pixel_format406{407uint32_t bit_count;408uint32_t flags;409uint32_t bit_mask[4];410ddsktx_format format;411} ddsktx__dds_translate_pixel_format;412413typedef struct ddsktx__mem_reader414{415const uint8_t* buff;416int total;417int offset;418} ddsktx__mem_reader;419420typedef struct ddsktx__block_info421{422uint8_t bpp;423uint8_t block_width;424uint8_t block_height;425uint8_t block_size;426uint8_t min_block_x;427uint8_t min_block_y;428uint8_t depth_bits;429uint8_t stencil_bits;430uint8_t r_bits;431uint8_t g_bits;432uint8_t b_bits;433uint8_t a_bits;434uint8_t encoding;435} ddsktx__block_info;436437#ifndef ddsktx_memcpy438# include <string.h>439# define ddsktx_memcpy(_dst, _src, _size) memcpy((_dst), (_src), (_size))440#endif441442#ifndef ddsktx_memset443# include <string.h>444# define ddsktx_memset(_dst, _v, _size) memset((_dst), (_v), (_size))445#endif446447#ifndef ddsktx_assert448# include <assert.h>449# define ddsktx_assert(_a) assert(_a)450#endif451452#ifndef ddsktx_strcpy453# include <string.h>454# ifdef _MSC_VER455# define ddsktx_strcpy(_dst, _src) strcpy_s((_dst), sizeof(_dst), (_src))456# else457# define ddsktx_strcpy(_dst, _src) strcpy((_dst), (_src))458# endif459#endif460461#ifndef ddsktx_memcmp462# include <string.h>463# define ddsktx_memcmp(_ptr1, _ptr2, _num) memcmp((_ptr1), (_ptr2), (_num))464#endif465466#define ddsktx__max(a, b) ((a) > (b) ? (a) : (b))467#define ddsktx__min(a, b) ((a) < (b) ? (a) : (b))468#define ddsktx__align_mask(_value, _mask) (((_value)+(_mask)) & ((~0)&(~(_mask))))469#define ddsktx__err(_err, _msg) if (_err) ddsktx_strcpy(_err->msg, _msg); return false470471static const ddsktx__dds_translate_fourcc_format k__translate_dds_fourcc[] = {472{ DDSKTX__DDS_DXT1, DDSKTX_FORMAT_BC1, false },473{ DDSKTX__DDS_DXT2, DDSKTX_FORMAT_BC2, false },474{ DDSKTX__DDS_DXT3, DDSKTX_FORMAT_BC2, false },475{ DDSKTX__DDS_DXT4, DDSKTX_FORMAT_BC3, false },476{ DDSKTX__DDS_DXT5, DDSKTX_FORMAT_BC3, false },477{ DDSKTX__DDS_ATI1, DDSKTX_FORMAT_BC4, false },478{ DDSKTX__DDS_BC4U, DDSKTX_FORMAT_BC4, false },479{ DDSKTX__DDS_ATI2, DDSKTX_FORMAT_BC5, false },480{ DDSKTX__DDS_BC5U, DDSKTX_FORMAT_BC5, false },481{ DDSKTX__DDS_ETC1, DDSKTX_FORMAT_ETC1, false },482{ DDSKTX__DDS_ETC2, DDSKTX_FORMAT_ETC2, false },483{ DDSKTX__DDS_ET2A, DDSKTX_FORMAT_ETC2A, false },484{ DDSKTX__DDS_PTC2, DDSKTX_FORMAT_PTC12A, false },485{ DDSKTX__DDS_PTC4, DDSKTX_FORMAT_PTC14A, false },486{ DDSKTX__DDS_ATC , DDSKTX_FORMAT_ATC, false },487{ DDSKTX__DDS_ATCE, DDSKTX_FORMAT_ATCE, false },488{ DDSKTX__DDS_ATCI, DDSKTX_FORMAT_ATCI, false },489{ DDSKTX__DDS_ASTC4x4, DDSKTX_FORMAT_ASTC4x4, false },490{ DDSKTX__DDS_ASTC5x5, DDSKTX_FORMAT_ASTC5x5, false },491{ DDSKTX__DDS_ASTC6x6, DDSKTX_FORMAT_ASTC6x6, false },492{ DDSKTX__DDS_ASTC8x5, DDSKTX_FORMAT_ASTC8x5, false },493{ DDSKTX__DDS_ASTC8x6, DDSKTX_FORMAT_ASTC8x6, false },494{ DDSKTX__DDS_ASTC10x5, DDSKTX_FORMAT_ASTC10x5, false },495{ DDSKTX__DDS_A16B16G16R16, DDSKTX_FORMAT_RGBA16, false },496{ DDSKTX__DDS_A16B16G16R16F, DDSKTX_FORMAT_RGBA16F, false },497{ DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, DDSKTX_FORMAT_BGRA8, false },498{ DDSKTX__DDPF_INDEXED, DDSKTX_FORMAT_R8, false },499{ DDSKTX__DDPF_LUMINANCE, DDSKTX_FORMAT_R8, false },500{ DDSKTX__DDPF_ALPHA, DDSKTX_FORMAT_R8, false },501{ DDSKTX__DDS_R16F, DDSKTX_FORMAT_R16F, false },502{ DDSKTX__DDS_R32F, DDSKTX_FORMAT_R32F, false },503{ DDSKTX__DDS_A8L8, DDSKTX_FORMAT_RG8, false },504{ DDSKTX__DDS_G16R16, DDSKTX_FORMAT_RG16, false },505{ DDSKTX__DDS_G16R16F, DDSKTX_FORMAT_RG16F, false },506{ DDSKTX__DDS_R8G8B8, DDSKTX_FORMAT_RGB8, false },507{ DDSKTX__DDS_A8R8G8B8, DDSKTX_FORMAT_BGRA8, false },508{ DDSKTX__DDS_A16B16G16R16, DDSKTX_FORMAT_RGBA16, false },509{ DDSKTX__DDS_A16B16G16R16F, DDSKTX_FORMAT_RGBA16F, false },510{ DDSKTX__DDS_A2B10G10R10, DDSKTX_FORMAT_RGB10A2, false },511};512513static const ddsktx__dds_translate_fourcc_format k__translate_dxgi[] = {514{ DDSKTX__DDS_FORMAT_BC1_UNORM, DDSKTX_FORMAT_BC1, false },515{ DDSKTX__DDS_FORMAT_BC1_UNORM_SRGB, DDSKTX_FORMAT_BC1, true },516{ DDSKTX__DDS_FORMAT_BC2_UNORM, DDSKTX_FORMAT_BC2, false },517{ DDSKTX__DDS_FORMAT_BC2_UNORM_SRGB, DDSKTX_FORMAT_BC2, true },518{ DDSKTX__DDS_FORMAT_BC3_UNORM, DDSKTX_FORMAT_BC3, false },519{ DDSKTX__DDS_FORMAT_BC3_UNORM_SRGB, DDSKTX_FORMAT_BC3, true },520{ DDSKTX__DDS_FORMAT_BC4_UNORM, DDSKTX_FORMAT_BC4, false },521{ DDSKTX__DDS_FORMAT_BC5_UNORM, DDSKTX_FORMAT_BC5, false },522{ DDSKTX__DDS_FORMAT_BC6H_SF16, DDSKTX_FORMAT_BC6H, false },523{ DDSKTX__DDS_FORMAT_BC7_UNORM, DDSKTX_FORMAT_BC7, false },524{ DDSKTX__DDS_FORMAT_BC7_UNORM_SRGB, DDSKTX_FORMAT_BC7, true },525526{ DDSKTX__DDS_FORMAT_R8_UNORM, DDSKTX_FORMAT_R8, false },527{ DDSKTX__DDS_FORMAT_R16_UNORM, DDSKTX_FORMAT_R16, false },528{ DDSKTX__DDS_FORMAT_R16_FLOAT, DDSKTX_FORMAT_R16F, false },529{ DDSKTX__DDS_FORMAT_R32_FLOAT, DDSKTX_FORMAT_R32F, false },530{ DDSKTX__DDS_FORMAT_R8G8_UNORM, DDSKTX_FORMAT_RG8, false },531{ DDSKTX__DDS_FORMAT_R16G16_UNORM, DDSKTX_FORMAT_RG16, false },532{ DDSKTX__DDS_FORMAT_R16G16_FLOAT, DDSKTX_FORMAT_RG16F, false },533{ DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM, DDSKTX_FORMAT_BGRA8, false },534{ DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM_SRGB, DDSKTX_FORMAT_BGRA8, true },535{ DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM, DDSKTX_FORMAT_RGBA8, false },536{ DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM_SRGB, DDSKTX_FORMAT_RGBA8, true },537{ DDSKTX__DDS_FORMAT_R16G16B16A16_UNORM, DDSKTX_FORMAT_RGBA16, false },538{ DDSKTX__DDS_FORMAT_R16G16B16A16_FLOAT, DDSKTX_FORMAT_RGBA16F, false },539{ DDSKTX__DDS_FORMAT_R10G10B10A2_UNORM, DDSKTX_FORMAT_RGB10A2, false },540{ DDSKTX__DDS_FORMAT_R11G11B10_FLOAT, DDSKTX_FORMAT_RG11B10F, false },541};542543static const ddsktx__dds_translate_pixel_format k__translate_dds_pixel[] = {544{ 8, DDSKTX__DDPF_LUMINANCE, { 0x000000ff, 0x00000000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_R8 },545{ 16, DDSKTX__DDPF_BUMPDUDV, { 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG8S },546{ 24, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_RGB8 },547{ 24, DDSKTX__DDPF_RGB, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }, DDSKTX_FORMAT_RGB8 },548{ 32, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_BGRA8 },549{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, DDSKTX_FORMAT_RGBA8 },550{ 32, DDSKTX__DDPF_BUMPDUDV, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, DDSKTX_FORMAT_RGBA8S },551{ 32, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSKTX_FORMAT_BGRA8 },552{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSKTX_FORMAT_BGRA8 }, // D3DFMT_A8R8G8B8553{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_BGRA8 }, // D3DFMT_X8R8G8B8554{ 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 }, DDSKTX_FORMAT_RGB10A2 },555{ 32, DDSKTX__DDPF_RGB, { 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG16 },556{ 32, DDSKTX__DDPF_BUMPDUDV, { 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG16S }557};558559typedef enum ddsktx__encode_type560{561DDSKTX__ENCODE_UNORM,562DDSKTX__ENCODE_SNORM,563DDSKTX__ENCODE_FLOAT,564DDSKTX__ENCODE_INT,565DDSKTX__ENCODE_UINT,566DDSKTX__ENCODE_COUNT567} ddsktx__encode_type;568569static const ddsktx__block_info k__block_info[] =570{571// +-------------------------------------------- bits per pixel572// | +----------------------------------------- block width573// | | +-------------------------------------- block height574// | | | +---------------------------------- block size575// | | | | +------------------------------- min blocks x576// | | | | | +---------------------------- min blocks y577// | | | | | | +------------------------ depth bits578// | | | | | | | +--------------------- stencil bits579// | | | | | | | | +---+---+---+----- r, g, b, a bits580// | | | | | | | | r g b a +-- encoding type581// | | | | | | | | | | | | |582{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC1583{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC2584{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC3585{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC4586{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC5587{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // BC6H588{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC7589{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC1590{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2591{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2A592{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2A1593{ 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC12594{ 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC14595{ 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC12A596{ 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC14A597{ 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC22598{ 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC24599{ 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATC600{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATCE601{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATCI602{ 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC4x4603{ 6, 5, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC5x5604{ 4, 6, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC6x6605{ 4, 8, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC8x5606{ 3, 8, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC8x6607{ 3, 10, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC10x5608{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_COUNT) }, // Unknown609{ 8, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // A8610{ 8, 1, 1, 1, 1, 1, 0, 0, 8, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // R8611{ 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGBA8612{ 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_SNORM) }, // RGBA8S613{ 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG16614{ 24, 1, 1, 3, 1, 1, 0, 0, 8, 8, 8, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGB8615{ 16, 1, 1, 2, 1, 1, 0, 0, 16, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // R16616{ 32, 1, 1, 4, 1, 1, 0, 0, 32, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // R32F617{ 16, 1, 1, 2, 1, 1, 0, 0, 16, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // R16F618{ 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // RG16F619{ 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_SNORM) }, // RG16S620{ 64, 1, 1, 8, 1, 1, 0, 0, 16, 16, 16, 16, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // RGBA16F621{ 64, 1, 1, 8, 1, 1, 0, 0, 16, 16, 16, 16, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGBA16622{ 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BGRA8623{ 32, 1, 1, 4, 1, 1, 0, 0, 10, 10, 10, 2, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGB10A2624{ 32, 1, 1, 4, 1, 1, 0, 0, 11, 11, 10, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG11B10F625{ 16, 1, 1, 2, 1, 1, 0, 0, 8, 8, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG8626{ 16, 1, 1, 2, 1, 1, 0, 0, 8, 8, 0, 0, (uint8_t)(DDSKTX__ENCODE_SNORM) } // RG8S627};628629// KTX: https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/630#define DDSKTX__KTX_MAGIC stc__makefourcc(0xAB, 'K', 'T', 'X')631#define DDSKTX__KTX_HEADER_SIZE 60 // actual header size is 64, but we read 4 bytes for the 'magic'632633#define DDSKTX__KTX_ETC1_RGB8_OES 0x8D64634#define DDSKTX__KTX_COMPRESSED_R11_EAC 0x9270635#define DDSKTX__KTX_COMPRESSED_SIGNED_R11_EAC 0x9271636#define DDSKTX__KTX_COMPRESSED_RG11_EAC 0x9272637#define DDSKTX__KTX_COMPRESSED_SIGNED_RG11_EAC 0x9273638#define DDSKTX__KTX_COMPRESSED_RGB8_ETC2 0x9274639#define DDSKTX__KTX_COMPRESSED_SRGB8_ETC2 0x9275640#define DDSKTX__KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276641#define DDSKTX__KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277642#define DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC 0x9278643#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279644#define DDSKTX__KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00645#define DDSKTX__KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01646#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02647#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03648#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137649#define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138650#define DDSKTX__KTX_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0651#define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1652#define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2653#define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3654#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D655#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E656#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F657#define DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70658#define DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72659#define DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C660#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D661#define DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E662#define DDSKTX__KTX_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F663#define DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54664#define DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55665#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56666#define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57667#define DDSKTX__KTX_ATC_RGB_AMD 0x8C92668#define DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93669#define DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE670#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_4x4_KHR 0x93B0671#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_5x5_KHR 0x93B2672#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_6x6_KHR 0x93B4673#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x5_KHR 0x93B5674#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x6_KHR 0x93B6675#define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_10x5_KHR 0x93B8676#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_4x4_KHR 0x93D0677#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_5x5_KHR 0x93D2678#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_6x6_KHR 0x93D4679#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_8x5_KHR 0x93D5680#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_8x6_KHR 0x93D6681#define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_10x5_KHR 0x93D8682683#define DDSKTX__KTX_A8 0x803C684#define DDSKTX__KTX_R8 0x8229685#define DDSKTX__KTX_R16 0x822A686#define DDSKTX__KTX_RG8 0x822B687#define DDSKTX__KTX_RG16 0x822C688#define DDSKTX__KTX_R16F 0x822D689#define DDSKTX__KTX_R32F 0x822E690#define DDSKTX__KTX_RG16F 0x822F691#define DDSKTX__KTX_RG32F 0x8230692#define DDSKTX__KTX_RGBA8 0x8058693#define DDSKTX__KTX_RGBA16 0x805B694#define DDSKTX__KTX_RGBA16F 0x881A695#define DDSKTX__KTX_R32UI 0x8236696#define DDSKTX__KTX_RG32UI 0x823C697#define DDSKTX__KTX_RGBA32UI 0x8D70698#define DDSKTX__KTX_RGBA32F 0x8814699#define DDSKTX__KTX_RGB565 0x8D62700#define DDSKTX__KTX_RGBA4 0x8056701#define DDSKTX__KTX_RGB5_A1 0x8057702#define DDSKTX__KTX_RGB10_A2 0x8059703#define DDSKTX__KTX_R8I 0x8231704#define DDSKTX__KTX_R8UI 0x8232705#define DDSKTX__KTX_R16I 0x8233706#define DDSKTX__KTX_R16UI 0x8234707#define DDSKTX__KTX_R32I 0x8235708#define DDSKTX__KTX_R32UI 0x8236709#define DDSKTX__KTX_RG8I 0x8237710#define DDSKTX__KTX_RG8UI 0x8238711#define DDSKTX__KTX_RG16I 0x8239712#define DDSKTX__KTX_RG16UI 0x823A713#define DDSKTX__KTX_RG32I 0x823B714#define DDSKTX__KTX_RG32UI 0x823C715#define DDSKTX__KTX_R8_SNORM 0x8F94716#define DDSKTX__KTX_RG8_SNORM 0x8F95717#define DDSKTX__KTX_RGB8_SNORM 0x8F96718#define DDSKTX__KTX_RGBA8_SNORM 0x8F97719#define DDSKTX__KTX_R16_SNORM 0x8F98720#define DDSKTX__KTX_RG16_SNORM 0x8F99721#define DDSKTX__KTX_RGB16_SNORM 0x8F9A722#define DDSKTX__KTX_RGBA16_SNORM 0x8F9B723#define DDSKTX__KTX_SRGB8 0x8C41724#define DDSKTX__KTX_SRGB8_ALPHA8 0x8C43725#define DDSKTX__KTX_RGBA32UI 0x8D70726#define DDSKTX__KTX_RGB32UI 0x8D71727#define DDSKTX__KTX_RGBA16UI 0x8D76728#define DDSKTX__KTX_RGB16UI 0x8D77729#define DDSKTX__KTX_RGBA8UI 0x8D7C730#define DDSKTX__KTX_RGB8UI 0x8D7D731#define DDSKTX__KTX_RGBA32I 0x8D82732#define DDSKTX__KTX_RGB32I 0x8D83733#define DDSKTX__KTX_RGBA16I 0x8D88734#define DDSKTX__KTX_RGB16I 0x8D89735#define DDSKTX__KTX_RGBA8I 0x8D8E736#define DDSKTX__KTX_RGB8 0x8051737#define DDSKTX__KTX_RGB8I 0x8D8F738#define DDSKTX__KTX_RGB9_E5 0x8C3D739#define DDSKTX__KTX_R11F_G11F_B10F 0x8C3A740741#define DDSKTX__KTX_ZERO 0742#define DDSKTX__KTX_RED 0x1903743#define DDSKTX__KTX_ALPHA 0x1906744#define DDSKTX__KTX_RGB 0x1907745#define DDSKTX__KTX_RGBA 0x1908746#define DDSKTX__KTX_BGRA 0x80E1747#define DDSKTX__KTX_RG 0x8227748749#define DDSKTX__KTX_BYTE 0x1400750#define DDSKTX__KTX_UNSIGNED_BYTE 0x1401751#define DDSKTX__KTX_SHORT 0x1402752#define DDSKTX__KTX_UNSIGNED_SHORT 0x1403753#define DDSKTX__KTX_INT 0x1404754#define DDSKTX__KTX_UNSIGNED_INT 0x1405755#define DDSKTX__KTX_FLOAT 0x1406756#define DDSKTX__KTX_HALF_FLOAT 0x140B757#define DDSKTX__KTX_UNSIGNED_INT_5_9_9_9_REV 0x8C3E758#define DDSKTX__KTX_UNSIGNED_SHORT_5_6_5 0x8363759#define DDSKTX__KTX_UNSIGNED_SHORT_4_4_4_4 0x8033760#define DDSKTX__KTX_UNSIGNED_SHORT_5_5_5_1 0x8034761#define DDSKTX__KTX_UNSIGNED_INT_2_10_10_10_REV 0x8368762#define DDSKTX__KTX_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B763764typedef struct ddsktx__ktx_format_info765{766uint32_t internal_fmt;767uint32_t internal_fmt_srgb;768uint32_t fmt;769uint32_t type;770} ddsktx__ktx_format_info;771772typedef struct ddsktx__ktx_format_info2773{774uint32_t internal_fmt;775ddsktx_format format;776} ddsktx__ktx_format_info2;777778static const ddsktx__ktx_format_info k__translate_ktx_fmt[] = {779{ 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, }, // BC1780{ 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, }, // BC2781{ 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, }, // BC3782{ DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT, DDSKTX__KTX_ZERO, }, // BC4783{ DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, DDSKTX__KTX_ZERO, }, // BC5784{ DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, DDSKTX__KTX_ZERO, }, // BC6H785{ DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB, DDSKTX__KTX_ZERO, }, // BC7786{ DDSKTX__KTX_ETC1_RGB8_OES, DDSKTX__KTX_ZERO, DDSKTX__KTX_ETC1_RGB8_OES, DDSKTX__KTX_ZERO, }, // ETC1787{ DDSKTX__KTX_COMPRESSED_RGB8_ETC2, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGB8_ETC2, DDSKTX__KTX_ZERO, }, // ETC2788{ DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC, DDSKTX__KTX_COMPRESSED_SRGB8_ETC2, DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC, DDSKTX__KTX_ZERO, }, // ETC2A789{ DDSKTX__KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DDSKTX__KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DDSKTX__KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DDSKTX__KTX_ZERO, }, // ETC2A1790{ DDSKTX__KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT, DDSKTX__KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, DDSKTX__KTX_ZERO, }, // PTC12791{ DDSKTX__KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT, DDSKTX__KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, DDSKTX__KTX_ZERO, }, // PTC14792{ 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, }, // PTC12A793{ 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, }, // PTC14A794{ DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, DDSKTX__KTX_ZERO, }, // PTC22795{ DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, DDSKTX__KTX_ZERO, }, // PTC24796{ DDSKTX__KTX_ATC_RGB_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGB_AMD, DDSKTX__KTX_ZERO, }, // ATC797{ DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, DDSKTX__KTX_ZERO, }, // ATCE798{ DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, DDSKTX__KTX_ZERO, }, // ATCI799{ 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, }, // ASTC4x4800{ 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, }, // ASTC5x5801{ 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, }, // ASTC6x6802{ 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, }, // ASTC8x5803{ 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, }, // ASTC8x6804{ 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, }, // ASTC10x5805{ DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, }, // Unknown806{ DDSKTX__KTX_ALPHA, DDSKTX__KTX_ZERO, DDSKTX__KTX_ALPHA, DDSKTX__KTX_UNSIGNED_BYTE, }, // A8807{ DDSKTX__KTX_R8, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_BYTE, }, // R8808{ DDSKTX__KTX_RGBA8, DDSKTX__KTX_SRGB8_ALPHA8, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_BYTE, }, // RGBA8809{ DDSKTX__KTX_RGBA8_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_BYTE, }, // RGBA8S810{ DDSKTX__KTX_RG16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_UNSIGNED_SHORT, }, // RG16811{ DDSKTX__KTX_RGB8, DDSKTX__KTX_SRGB8, DDSKTX__KTX_RGB, DDSKTX__KTX_UNSIGNED_BYTE, }, // RGB8812{ DDSKTX__KTX_R16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16813{ DDSKTX__KTX_R32F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_FLOAT, }, // R32F814{ DDSKTX__KTX_R16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_HALF_FLOAT, }, // R16F815{ DDSKTX__KTX_RG16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_FLOAT, }, // RG16F816{ DDSKTX__KTX_RG16_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_SHORT, }, // RG16S817{ DDSKTX__KTX_RGBA16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_HALF_FLOAT, }, // RGBA16F818{ DDSKTX__KTX_RGBA16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_SHORT, }, // RGBA16819{ DDSKTX__KTX_BGRA, DDSKTX__KTX_SRGB8_ALPHA8, DDSKTX__KTX_BGRA, DDSKTX__KTX_UNSIGNED_BYTE, }, // BGRA8820{ DDSKTX__KTX_RGB10_A2, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_INT_2_10_10_10_REV, }, // RGB10A2821{ DDSKTX__KTX_R11F_G11F_B10F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGB, DDSKTX__KTX_UNSIGNED_INT_10F_11F_11F_REV, }, // RG11B10F822{ DDSKTX__KTX_RG8, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_UNSIGNED_BYTE, }, // RG8823{ DDSKTX__KTX_RG8_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_BYTE, }, // RG8S824{ DDSKTX__KTX_R16I, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16I825{ DDSKTX__KTX_R16UI, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16UI826};827828static const ddsktx__ktx_format_info2 k__translate_ktx_fmt2[] =829{830{ DDSKTX__KTX_A8, DDSKTX_FORMAT_A8 },831{ DDSKTX__KTX_RED, DDSKTX_FORMAT_R8 },832{ DDSKTX__KTX_RGB, DDSKTX_FORMAT_RGB8 },833{ DDSKTX__KTX_RGBA, DDSKTX_FORMAT_RGBA8 },834{ DDSKTX__KTX_COMPRESSED_RGB_S3TC_DXT1_EXT, DDSKTX_FORMAT_BC1 },835};836837typedef struct ddsktx__format_info838{839const char* name;840bool has_alpha;841} ddsktx__format_info;842843static const ddsktx__format_info k__formats_info[] = {844{"BC1", false},845{"BC2", true},846{"BC3", true},847{"BC4", false},848{"BC5", false},849{"BC6H", false},850{"BC7", true},851{"ETC1", false},852{"ETC2", false},853{"ETC2A", true},854{"ETC2A1", true},855{"PTC12", false},856{"PTC14", false},857{"PTC12A", true},858{"PTC14A", true},859{"PTC22", true},860{"PTC24", true},861{"ATC", false},862{"ATCE", false},863{"ATCI", false},864{"ASTC4x4", true},865{"ASTC5x5", true},866{"ASTC6x6", false},867{"ASTC8x5", true},868{"ASTC8x6", false},869{"ASTC10x5", false},870{"<unknown>", false},871{"A8", true},872{"R8", false},873{"RGBA8", true},874{"RGBA8S", true},875{"RG16", false},876{"RGB8", false},877{"R16", false},878{"R32F", false},879{"R16F", false},880{"RG16F", false},881{"RG16S", false},882{"RGBA16F", true},883{"RGBA16",true},884{"BGRA8", true},885{"RGB10A2", true},886{"RG11B10F", false},887{"RG8", false},888{"RG8S", false}889};890891892static inline int ddsktx__read(ddsktx__mem_reader* reader, void* buff, int size)893{894int read_bytes = (reader->offset + size) <= reader->total ? size : (reader->total - reader->offset);895ddsktx_memcpy(buff, reader->buff + reader->offset, read_bytes);896reader->offset += read_bytes;897return read_bytes;898}899900static bool ddsktx__parse_ktx(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err)901{902static const uint8_t ktx__id[] = { 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };903904ddsktx_memset(tc, 0x0, sizeof(ddsktx_texture_info));905906ddsktx__mem_reader r = {(const uint8_t*)file_data, size, sizeof(uint32_t)};907ddsktx__ktx_header header;908if (ddsktx__read(&r, &header, sizeof(header)) != DDSKTX__KTX_HEADER_SIZE) {909ddsktx__err(err, "ktx; header size does not match");910}911912if (ddsktx_memcmp(header.id, ktx__id, sizeof(header.id)) != 0) {913ddsktx__err(err, "ktx: invalid file header");914}915916// TODO: support big endian917if (header.endianess != 0x04030201) {918ddsktx__err(err, "ktx: big-endian format is not supported");919}920921tc->metadata_offset = r.offset;922tc->metadata_size = (int)header.metadata_size;923r.offset += (int)header.metadata_size;924925ddsktx_format format = _DDSKTX_FORMAT_COUNT;926927int count = sizeof(k__translate_ktx_fmt)/sizeof(ddsktx__ktx_format_info);928for (int i = 0; i < count; i++) {929if (k__translate_ktx_fmt[i].internal_fmt == header.internal_format) {930format = (ddsktx_format)i;931break;932}933}934935if (format == _DDSKTX_FORMAT_COUNT) {936count = sizeof(k__translate_ktx_fmt2)/sizeof(ddsktx__ktx_format_info2);937for (int i = 0; i < count; i++) {938if (k__translate_ktx_fmt2[i].internal_fmt == header.internal_format) {939format = (ddsktx_format)k__translate_ktx_fmt2[i].format;940break;941}942}943}944945if (format == _DDSKTX_FORMAT_COUNT) {946ddsktx__err(err, "ktx: unsupported format");947}948949if (header.face_count > 1 && header.face_count != DDSKTX_CUBE_FACE_COUNT) {950ddsktx__err(err, "ktx: incomplete cubemap");951}952953tc->data_offset = r.offset;954tc->size_bytes = r.total - r.offset;955tc->format = format;956tc->width = (int)header.width;957tc->height = (int)header.height;958tc->depth = ddsktx__max((int)header.depth, 1);959tc->num_layers = ddsktx__max((int)header.array_count, 1);960tc->num_mips = ddsktx__max((int)header.mip_count, 1);961tc->bpp = k__block_info[format].bpp;962963if (header.face_count == 6)964tc->flags |= DDSKTX_TEXTURE_FLAG_CUBEMAP;965tc->flags |= k__formats_info[format].has_alpha ? DDSKTX_TEXTURE_FLAG_ALPHA : 0;966tc->flags |= DDSKTX_TEXTURE_FLAG_KTX;967968return true;969}970971static bool ddsktx__parse_dds(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err)972{973ddsktx__mem_reader r = {(const uint8_t*)file_data, size, sizeof(uint32_t)};974ddsktx__dds_header header;975if (ddsktx__read(&r, &header, sizeof(header)) < DDSKTX__DDS_HEADER_SIZE ||976header.size != DDSKTX__DDS_HEADER_SIZE)977{978ddsktx__err(err, "dds: header size does not match");979}980981uint32_t required_flags = (DDSKTX__DDSD_HEIGHT|DDSKTX__DDSD_WIDTH);982if ((header.flags & required_flags) != required_flags) {983ddsktx__err(err, "dds: have invalid flags");984}985986if (header.pixel_format.size != sizeof(ddsktx__dds_pixel_format)) {987ddsktx__err(err, "dds: pixel format header is invalid");988}989990uint32_t dxgi_format = 0;991uint32_t array_size = 1;992if (DDSKTX__DDPF_FOURCC == (header.flags & DDSKTX__DDPF_FOURCC) &&993header.pixel_format.fourcc == DDSKTX__DDS_DX10)994{995ddsktx__dds_header_dxgi dxgi_header;996ddsktx__read(&r, &dxgi_header, sizeof(dxgi_header));997dxgi_format = dxgi_header.dxgi_format;998array_size = dxgi_header.array_size;999}10001001if ((header.caps1 & DDSKTX__DDSCAPS_TEXTURE) == 0) {1002ddsktx__err(err, "dds: unsupported caps");1003}10041005bool cubemap = (header.caps2 & DDSKTX__DDSCAPS2_CUBEMAP) != 0;1006if (cubemap && (header.caps2 & DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES) != DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES) {1007ddsktx__err(err, "dds: incomplete cubemap");1008}1009bool volume = (header.caps2 & DDSKTX__DDSCAPS2_VOLUME) != 0;10101011ddsktx_format format = _DDSKTX_FORMAT_COUNT;1012bool has_alpha = (header.pixel_format.flags & DDSKTX__DDPF_ALPHA) != 0;1013bool srgb = false;10141015if (dxgi_format == 0) {1016if ((header.pixel_format.flags & DDSKTX__DDPF_FOURCC) == DDSKTX__DDPF_FOURCC) {1017int count = sizeof(k__translate_dds_fourcc)/sizeof(ddsktx__dds_translate_fourcc_format);1018for (int i = 0; i < count; i++) {1019if (k__translate_dds_fourcc[i].dds_format == header.pixel_format.fourcc) {1020format = k__translate_dds_fourcc[i].format;1021break;1022}1023}1024} else {1025int count = sizeof(k__translate_dds_pixel)/sizeof(ddsktx__dds_translate_pixel_format);1026for (int i = 0; i < count; i++) {1027const ddsktx__dds_translate_pixel_format* f = &k__translate_dds_pixel[i];1028if (f->bit_count == header.pixel_format.rgb_bit_count &&1029f->flags == header.pixel_format.flags &&1030f->bit_mask[0] == header.pixel_format.bit_mask[0] &&1031f->bit_mask[1] == header.pixel_format.bit_mask[1] &&1032f->bit_mask[2] == header.pixel_format.bit_mask[2] &&1033f->bit_mask[3] == header.pixel_format.bit_mask[3])1034{1035format = f->format;1036break;1037}1038}1039}1040} else {1041int count = sizeof(k__translate_dxgi)/sizeof(ddsktx__dds_translate_fourcc_format);1042for (int i = 0; i < count; i++) {1043if (k__translate_dxgi[i].dds_format == dxgi_format) {1044format = k__translate_dxgi[i].format;1045srgb = k__translate_dxgi[i].srgb;1046break;1047}1048}1049}10501051if (format == _DDSKTX_FORMAT_COUNT) {1052ddsktx__err(err, "dds: unknown format");1053}10541055ddsktx_memset(tc, 0x0, sizeof(ddsktx_texture_info));1056tc->data_offset = r.offset;1057tc->size_bytes = r.total - r.offset;1058tc->format = format;1059tc->width = (int)header.width;1060tc->height = (int)header.height;1061tc->depth = ddsktx__max(1, (int)header.depth);1062tc->num_layers = ddsktx__max(1, (int)array_size);1063tc->num_mips = (header.caps1 & DDSKTX__DDSCAPS_MIPMAP) ? (int)header.mip_count : 1;1064tc->bpp = k__block_info[format].bpp;1065if (has_alpha || k__formats_info[format].has_alpha)1066tc->flags |= DDSKTX_TEXTURE_FLAG_ALPHA;1067if (cubemap)1068tc->flags |= DDSKTX_TEXTURE_FLAG_CUBEMAP;1069if (volume)1070tc->flags |= DDSKTX_TEXTURE_FLAG_VOLUME;1071if (srgb)1072tc->flags |= DDSKTX_TEXTURE_FLAG_SRGB;1073tc->flags |= DDSKTX_TEXTURE_FLAG_DDS;10741075return true;1076}10771078void ddsktx_get_sub(const ddsktx_texture_info* tc, ddsktx_sub_data* sub_data,1079const void* file_data, int size,1080int array_idx, int slice_face_idx, int mip_idx)1081{1082ddsktx_assert(tc);1083ddsktx_assert(sub_data);1084ddsktx_assert(file_data);1085ddsktx_assert(size > 0);1086ddsktx_assert(array_idx < tc->num_layers);1087ddsktx_assert(!((tc->flags&DDSKTX_TEXTURE_FLAG_CUBEMAP) && (slice_face_idx >= DDSKTX_CUBE_FACE_COUNT)) && "invalid cube-face index");1088ddsktx_assert(!(!(tc->flags&DDSKTX_TEXTURE_FLAG_CUBEMAP) && (slice_face_idx >= tc->depth)) && "invalid depth-slice index");1089ddsktx_assert(mip_idx < tc->num_mips);10901091ddsktx__mem_reader r = { (uint8_t*)file_data, size, tc->data_offset };1092ddsktx_format format = tc->format;10931094ddsktx_assert(format < _DDSKTX_FORMAT_COUNT && format != _DDSKTX_FORMAT_COMPRESSED);1095const ddsktx__block_info* binfo = &k__block_info[format];1096const int bpp = binfo->bpp;1097const int block_size = binfo->block_size;1098const int min_block_x = binfo->min_block_x;1099const int min_block_y = binfo->min_block_y;11001101int num_faces;11021103ddsktx_assert(!((tc->flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) && tc->depth > 1) && "textures must be either Cube or 3D");1104int slice_idx, face_idx, num_slices;1105if (tc->flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) {1106slice_idx = 0;1107face_idx = slice_face_idx;1108num_faces = DDSKTX_CUBE_FACE_COUNT;1109num_slices = 1;1110} else {1111slice_idx = slice_face_idx;1112face_idx = 0;1113num_faces = 1;1114num_slices = tc->depth;1115}11161117if (tc->flags & DDSKTX_TEXTURE_FLAG_DDS) {1118for (int layer = 0, num_layers = tc->num_layers; layer < num_layers; layer++) {1119for (int face = 0; face < num_faces; face++) {1120int width = tc->width;1121int height = tc->height;11221123for (int mip = 0, mip_count = tc->num_mips; mip < mip_count; mip++) {1124int row_bytes, mip_size;11251126if (format < _DDSKTX_FORMAT_COMPRESSED) {1127int num_blocks_wide = width > 0 ? ddsktx__max(1, (width + 3)/4) : 0;1128num_blocks_wide = ddsktx__max(min_block_x, num_blocks_wide);11291130int num_blocks_high = height > 0 ? ddsktx__max(1, (height + 3)/4) : 0;1131num_blocks_high = ddsktx__max(min_block_y, num_blocks_high);11321133row_bytes = num_blocks_wide * block_size;1134mip_size = row_bytes * num_blocks_high;1135} else {1136row_bytes = (width*bpp + 7)/8; // round to nearest byte1137mip_size = row_bytes * height;1138}11391140for (int slice = 0; slice < num_slices; slice++) {1141if (layer == array_idx && mip == mip_idx &&1142slice == slice_idx && face_idx == face)1143{1144sub_data->buff = r.buff + r.offset;1145sub_data->width = width;1146sub_data->height = height;1147sub_data->size_bytes = mip_size;1148sub_data->row_pitch_bytes = row_bytes;1149return;1150}11511152r.offset += mip_size;1153ddsktx_assert(r.offset <= r.total && "texture buffer overflow");1154} // foreach slice11551156width >>= 1;1157height >>= 1;11581159if (width == 0) {1160width = 1;1161}1162if (height == 0) {1163height = 1;1164}1165} // foreach mip1166} // foreach face1167} // foreach array-item1168} else if (tc->flags & DDSKTX_TEXTURE_FLAG_KTX) {1169int width = tc->width;1170int height = tc->height;11711172for (int mip = 0, c = tc->num_mips; mip < c; mip++) {1173int row_bytes, mip_size;11741175if (format < _DDSKTX_FORMAT_COMPRESSED) {1176int num_blocks_wide = width > 0 ? ddsktx__max(1, (width + 3)/4) : 0;1177num_blocks_wide = ddsktx__max(min_block_x, num_blocks_wide);11781179int num_blocks_high = height > 0 ? ddsktx__max(1, (height + 3)/4) : 0;1180num_blocks_high = ddsktx__max(min_block_y, num_blocks_high);11811182row_bytes = num_blocks_wide * block_size;1183mip_size = row_bytes * num_blocks_high;1184}1185else {1186row_bytes = (width*bpp + 7)/8; // round to nearest byte1187mip_size = row_bytes * height;1188}11891190int image_size;1191ddsktx__read(&r, &image_size, sizeof(image_size));1192ddsktx_assert(image_size == (mip_size*num_faces*num_slices) && "image size mismatch");11931194for (int layer = 0, num_layers = tc->num_layers; layer < num_layers; layer++) {1195for (int face = 0; face < num_faces; face++) {1196for (int slice = 0; slice < num_slices; slice++) {1197if (layer == array_idx && mip == mip_idx &&1198slice == slice_idx && face_idx == face)1199{1200sub_data->buff = r.buff + r.offset;1201sub_data->width = width;1202sub_data->height = height;1203sub_data->size_bytes = mip_size;1204sub_data->row_pitch_bytes = row_bytes;1205return;1206}12071208r.offset += mip_size;1209ddsktx_assert(r.offset <= r.total && "texture buffer overflow");1210} // foreach slice121112121213r.offset = ddsktx__align_mask(r.offset, 3); // cube-padding1214} // foreach face1215} // foreach array-item12161217width >>= 1;1218height >>= 1;12191220if (width == 0) {1221width = 1;1222}1223if (height == 0) {1224height = 1;1225}12261227r.offset = ddsktx__align_mask(r.offset, 3); // mip-padding1228} // foreach mip1229} else {1230ddsktx_assert(0 && "invalid file format");1231}1232}12331234bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err)1235{1236ddsktx_assert(tc);1237ddsktx_assert(file_data);1238ddsktx_assert(size > 0);12391240ddsktx__mem_reader r = {(const uint8_t*)file_data, size, 0};12411242// Read file flag and determine the file type1243uint32_t file_flag = 0;1244if (ddsktx__read(&r, &file_flag, sizeof(file_flag)) != sizeof(file_flag)) {1245ddsktx__err(err, "invalid texture file");1246}12471248switch (file_flag) {1249case DDSKTX__DDS_MAGIC:1250return ddsktx__parse_dds(tc, file_data, size, err);1251case DDSKTX__KTX_MAGIC:1252return ddsktx__parse_ktx(tc, file_data, size, err);1253default:1254ddsktx__err(err, "unknown texture format");1255}1256}12571258const char* ddsktx_format_str(ddsktx_format format)1259{1260return k__formats_info[format].name;1261}12621263bool ddsktx_format_compressed(ddsktx_format format)1264{1265ddsktx_assert(format != _DDSKTX_FORMAT_COMPRESSED && format != _DDSKTX_FORMAT_COUNT);1266return format < _DDSKTX_FORMAT_COMPRESSED;1267}12681269#endif // DDSKTX_IMPLEMENT127012711272