├── .editorconfig ├── .gitignore ├── .idea ├── .gitignore ├── misc.xml ├── modules.xml ├── tiny_ktx.iml └── vcs.xml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── include └── tiny_ktx │ ├── tinyktx.h │ └── tinyktx2.h ├── src └── tinyktx.c └── tests ├── runner.cpp ├── test_tinyktx.cpp └── test_tinyktx_tinyimageformat.cpp /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*.{c,cpp,h,hpp}] 5 | indent_style = tab 6 | indent_size = 2 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | 54 | # Project exclude paths 55 | /cmake-build-debug/ -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/tiny_ktx.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12.4) 2 | get_directory_property(hasParent PARENT_DIRECTORY) 3 | if(NOT hasParent) 4 | option(unittests "unittests" OFF) 5 | get_filename_component(_PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) 6 | set_property(GLOBAL PROPERTY GLOBAL_FETCHDEPS_BASE ${_PARENT_DIR}/al2o3 ) 7 | include(FetchContent) 8 | FetchContent_Declare( al2o3 GIT_REPOSITORY https://github.com/DeanoC/al2o3 GIT_TAG master ) 9 | FetchContent_GetProperties(al2o3) 10 | if(NOT al2o3_POPULATED) 11 | FetchContent_Populate(al2o3) 12 | add_subdirectory(${al2o3_SOURCE_DIR} ${al2o3_BINARY_DIR}) 13 | endif() 14 | INIT_AL2O3(${CMAKE_CURRENT_SOURCE_DIR}) 15 | endif () 16 | 17 | SET_MIN_VERSIONS() 18 | set(LibName tiny_ktx) 19 | project(${LibName}) 20 | 21 | set(Interface 22 | tinyktx.h 23 | ) 24 | 25 | set(Src 26 | tinyktx.c 27 | ) 28 | 29 | set(Deps 30 | tiny_imageformat 31 | ) 32 | ADD_LIB(${LibName} "${Interface}" "${Src}" "${Deps}") 33 | 34 | set( Tests 35 | runner.cpp 36 | test_tinyktx.cpp 37 | test_tinyktx_tinyimageformat.cpp 38 | ) 39 | set( TestDeps 40 | al2o3_catch2 41 | al2o3_vfile 42 | al2o3_stb 43 | tiny_imageformat 44 | utils_simple_logmanager) 45 | ADD_LIB_TESTS(${LibName} "${Interface}" "${Tests}" "${TestDeps}") 46 | 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 DeanoC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tiny_ktx 2 | Small C based KTX texture loader (inspired by syoyo tiny libraries) 3 | 4 | KTX textures can handle 5 | * Almost any format of texture data 6 | * 1D, 2D, 3D and cubemaps textures 7 | * Texture arrays 8 | * Mipmaps 9 | * Key value pairs for custom data extensions 10 | 11 | Its an efficient open format for almost every realtime texture data you could want. 12 | 13 | ## What it does? 14 | * Loads Khronos KTX textures 15 | * Saves Khronos KTX textures 16 | * Optionally provide format in either native GL/KTX style or Vulkan/Dx12/Metal style 17 | * Optionally provides GL defines requires to read KTX files without GL 18 | 19 | tiny_ktx is a very low level API as such it only handles these parts, it doesn't process the data in any way 20 | 21 | ## Requirements 22 | None except a C compiler (TODO test which version 89 or 99) 23 | 24 | By default uses 4 std lib headers 25 | * stdint.h -for uint32_t and int64_t 26 | * stdbool.h - for bool 27 | * stddef.h - for size_t 28 | * string.h - for memcpy 29 | 30 | However if the types/functions are provided you can opt out 31 | of these being included via *TINYKTX_HAVE_UINTXX_T* etc. 32 | 33 | ## How to build 34 | * include tinyktx.h from include/tiny_ktx in your project 35 | * in 1 file in your project define *TINYKTX_IMPLEMENTATION* before tinyktx.h 36 | 37 | if using cmake and want a library version just add this using add_subdirectory 38 | and add tiny_ktx as a dependency 39 | 40 | ## Handling KTX format 41 | KTX file are based on OpenGL which has evolved a fairly complex pixel format system 42 | 43 | Whilst this may be useful if you are importing into a GL application for other its quite hard to convert. 44 | 45 | An optional part of TinyKtx (default is on) will convert these into a more Vulkan/Dx12/Metal format. 46 | 47 | Rather than the multiple uint32_t types KTX stores format in, TinyKtx provides a single large enum. 48 | 49 | *TinyKtx_GetFormatGL* will give you the format directly as stored in the KTX file 50 | 51 | *TinyKtx_GetFormat* will provide a single value converted from the KTX GL provided type. 52 | 53 | if TinyKtx_GetFormat can't convert it will return *TKTX_UNDEFINED* 54 | 55 | ## How to load a KTX 56 | Create a contex using *TinyKtx_CreateContext* passing in callbacks for 57 | * optional error report 58 | * alloc 59 | * free 60 | * read 61 | * seek 62 | * tell 63 | 64 | All are provides a void* user data argument for file handle etc. 65 | 66 | ``` 67 | Read the header (TinyKtx_ReadHeader). 68 | A tell/read should be at the start of the KTX data 69 | 70 | Query the dimension, format etc. (TinyKtx_Width etc.) 71 | 72 | For each mipmap level in the file (TinyKtx_NumberOfMipmaps) 73 | get the mipmap size (TinyKtx_ImageSize) 74 | get the mipmap data (TinyKtx_ImageRawData) 75 | ``` 76 | Load snippet 77 | ```c 78 | static void tinyktxCallbackError(void *user, char const *msg) { 79 | LOGERROR("Tiny_Ktx ERROR: %s", msg); 80 | } 81 | static void *tinyktxCallbackAlloc(void *user, size_t size) { 82 | return MEMORY_MALLOC(size); 83 | } 84 | static void tinyktxCallbackFree(void *user, void *data) { 85 | MEMORY_FREE(data); 86 | } 87 | static size_t tinyktxCallbackRead(void *user, void* data, size_t size) { 88 | auto handle = (VFile_Handle) user; 89 | return VFile_Read(handle, data, size); 90 | } 91 | static bool tinyktxCallbackSeek(void *user, int64_t offset) { 92 | auto handle = (VFile_Handle) user; 93 | return VFile_Seek(handle, offset, VFile_SD_Begin); 94 | 95 | } 96 | static int64_t tinyktxCallbackTell(void *user) { 97 | auto handle = (VFile_Handle) user; 98 | return VFile_Tell(handle); 99 | } 100 | 101 | AL2O3_EXTERN_C Image_ImageHeader const *Image_LoadKTX(VFile_Handle handle) { 102 | TinyKtx_Callbacks callbacks { 103 | &tinyktxCallbackError, 104 | &tinyktxCallbackAlloc, 105 | &tinyktxCallbackFree, 106 | tinyktxCallbackRead, 107 | &tinyktxCallbackSeek, 108 | &tinyktxCallbackTell 109 | }; 110 | 111 | auto ctx = TinyKtx_CreateContext( &callbacks, handle); 112 | TinyKtx_ReadHeader(ctx); 113 | uint32_t w = TinyKtx_Width(ctx); 114 | uint32_t h = TinyKtx_Height(ctx); 115 | uint32_t d = TinyKtx_Depth(ctx); 116 | uint32_t s = TinyKtx_ArraySlices(ctx); 117 | ImageFormat fmt = ImageFormatToTinyKtxFormat(TinyKtx_GetFormat(ctx)); 118 | if(fmt == ImageFormat_UNDEFINED) { 119 | TinyKtx_DestroyContext(ctx); 120 | return nullptr; 121 | } 122 | 123 | Image_ImageHeader const* topImage = nullptr; 124 | Image_ImageHeader const* prevImage = nullptr; 125 | for(auto i = 0u; i < TinyKtx_NumberOfMipmaps(ctx);++i) { 126 | auto image = Image_CreateNoClear(w, h, d, s, fmt); 127 | if(i == 0) topImage = image; 128 | 129 | if(Image_ByteCountOf(image) != TinyKtx_ImageSize(ctx, i)) { 130 | LOGERROR("KTX file %s mipmap %i size error", VFile_GetName(handle), i); 131 | Image_Destroy(topImage); 132 | TinyKtx_DestroyContext(ctx); 133 | return nullptr; 134 | } 135 | memcpy(Image_RawDataPtr(image), TinyKtx_ImageRawData(ctx, i), Image_ByteCountOf(image)); 136 | if(prevImage) { 137 | auto p = (Image_ImageHeader *)prevImage; 138 | p->nextType = Image_NextType::Image_IT_MipMaps; 139 | p->nextImage = image; 140 | } 141 | if(w > 1) w = w / 2; 142 | if(h > 1) h = h / 2; 143 | if(d > 1) d = d / 2; 144 | prevImage = image; 145 | } 146 | 147 | TinyKtx_DestroyContext(ctx); 148 | return topImage; 149 | } 150 | ``` 151 | 152 | 153 | ## How to save a KTX 154 | Saving doesn't need a context just a *TinyKtx_WriteCallbacks* with 155 | * error reporting 156 | * alloc (not currently used) 157 | * free (not currently used) 158 | * write 159 | 160 | ``` 161 | A TinyKtx_WriteImage or TinyKtx_WriteImageGL are the only API entry point for saving a KTX file. 162 | 163 | Provide it with the format (in either style), dimensions and whether its a cube map or not 164 | 165 | Pass the number of mipmaps and arrays filled with the size of each mipmap image and a pointer to the data 166 | ``` 167 | Save snippet 168 | ```c 169 | static void tinyktxCallbackError(void *user, char const *msg) { 170 | LOGERROR("Tiny_Ktx ERROR: %s", msg); 171 | } 172 | 173 | static void *tinyktxCallbackAlloc(void *user, size_t size) { 174 | return MEMORY_MALLOC(size); 175 | } 176 | 177 | static void tinyktxCallbackFree(void *user, void *data) { 178 | MEMORY_FREE(data); 179 | } 180 | 181 | static void tinyktxCallbackWrite(void *user, void const *data, size_t size) { 182 | auto handle = (VFile_Handle) user; 183 | VFile_Write(handle, data, size); 184 | } 185 | AL2O3_EXTERN_C bool Image_SaveKTX(Image_ImageHeader *image, VFile_Handle handle) { 186 | using namespace Image; 187 | TinyKtx_WriteCallbacks callback{ 188 | &tinyktxCallbackError, 189 | &tinyktxCallbackAlloc, 190 | &tinyktxCallbackFree, 191 | &tinyktxCallbackWrite, 192 | }; 193 | 194 | TinyKtx_Format fmt = ImageFormatToTinyKtxFormat(image->format); 195 | if(fmt == TKTX_UNDEFINED) return false; 196 | 197 | uint32_t numMipmaps = (image->nextType == Image_NextType::Image_IT_None) ? 1 : (uint32_t)Image_LinkedImageCountOf(image); 198 | 199 | uint32_t mipmapsizes[TINYKTX_MAX_MIPMAPLEVELS]; 200 | void const* mipmaps[TINYKTX_MAX_MIPMAPLEVELS]; 201 | memset(mipmapsizes, 0, sizeof(uint32_t)*TINYKTX_MAX_MIPMAPLEVELS); 202 | memset(mipmaps, 0, sizeof(void const*)*TINYKTX_MAX_MIPMAPLEVELS); 203 | 204 | for(size_t i = 0; i < numMipmaps; ++i) { 205 | mipmapsizes[i] = (uint32_t) Image_LinkedImageOf(image, i)->dataSize; 206 | mipmaps[i] = Image_RawDataPtr(Image_LinkedImageOf(image, i)); 207 | } 208 | 209 | return TinyKtx_WriteImage(&callback, 210 | handle, 211 | image->width, 212 | image->height, 213 | image->depth, 214 | image->slices, 215 | numMipmaps, 216 | fmt, 217 | Image_IsCubemap(image), 218 | mipmapsizes, 219 | mipmaps ); 220 | } 221 | ``` 222 | 223 | ## Tests 224 | Testing is done using my Taylor scriptable content processor. 225 | 226 | [taylor_imagetest - script and data](https://github.com/DeanoC/taylor_imagetests) 227 | 228 | [taylor - app that runs the test script) ](https://github.com/DeanoC/taylor) 229 | 230 | ## TODO 231 | Lots of validation/tests 232 | 233 | Save key data pairs (currently will load them but doesn't write any) 234 | 235 | Handle endianness? 236 | 237 | ## Higher level 238 | tiny_ktx is the lowel level part of my gfx_imageio and gfx_image libraries. 239 | 240 | They handle conversion or data, reading and writing and load/save other format ast well 241 | 242 | taylor is a lua scripted content command line program that uses the above library for processing. 243 | 244 | If you want higher level of tiny_ktx or how tiny_ktx is used see the links below 245 | 246 | The snippets above are from gfx_imageio 247 | 248 | [gfx_imageio - higher level import/export image using tiny_ktx (and other formats)](https://github.com/DeanoC/gfx_imageio) 249 | 250 | [taylor - lua scripted image processer using gfx_imageio](https://github.com/DeanoC/taylor) 251 | -------------------------------------------------------------------------------- /include/tiny_ktx/tinyktx.h: -------------------------------------------------------------------------------- 1 | // MIT license see full LICENSE text at end of file 2 | #pragma once 3 | #ifndef TINY_KTX_TINYKTX_H 4 | #define TINY_KTX_TINYKTX_H 5 | 6 | #ifndef TINYKTX_HAVE_UINTXX_T 7 | #include // for uint32_t and int64_t 8 | #endif 9 | #ifndef TINYKTX_HAVE_BOOL 10 | #include // for bool 11 | #endif 12 | #ifndef TINYKTX_HAVE_SIZE_T 13 | #include // for size_t 14 | #endif 15 | #ifndef TINYKTX_HAVE_MEMCPY 16 | #include // for memcpy 17 | #endif 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define TINYKTX_MAX_MIPMAPLEVELS 16 24 | 25 | typedef struct TinyKtx_Context *TinyKtx_ContextHandle; 26 | 27 | typedef void *(*TinyKtx_AllocFunc)(void *user, size_t size); 28 | typedef void (*TinyKtx_FreeFunc)(void *user, void *memory); 29 | typedef size_t (*TinyKtx_ReadFunc)(void *user, void *buffer, size_t byteCount); 30 | typedef bool (*TinyKtx_SeekFunc)(void *user, int64_t offset); 31 | typedef int64_t (*TinyKtx_TellFunc)(void *user); 32 | typedef void (*TinyKtx_ErrorFunc)(void *user, char const *msg); 33 | 34 | typedef struct TinyKtx_Callbacks { 35 | TinyKtx_ErrorFunc errorFn; 36 | TinyKtx_AllocFunc allocFn; 37 | TinyKtx_FreeFunc freeFn; 38 | TinyKtx_ReadFunc readFn; 39 | TinyKtx_SeekFunc seekFn; 40 | TinyKtx_TellFunc tellFn; 41 | } TinyKtx_Callbacks; 42 | 43 | TinyKtx_ContextHandle TinyKtx_CreateContext(TinyKtx_Callbacks const *callbacks, void *user); 44 | void TinyKtx_DestroyContext(TinyKtx_ContextHandle handle); 45 | 46 | // reset lets you reuse the context for another file (saves an alloc/free cycle) 47 | void TinyKtx_Reset(TinyKtx_ContextHandle handle); 48 | 49 | // call this to read the header file should already be at the start of the KTX data 50 | bool TinyKtx_ReadHeader(TinyKtx_ContextHandle handle); 51 | 52 | // this is slow linear search. TODO add iterator style reading of key value pairs 53 | bool TinyKtx_GetValue(TinyKtx_ContextHandle handle, char const *key, void const **value); 54 | 55 | bool TinyKtx_Is1D(TinyKtx_ContextHandle handle); 56 | bool TinyKtx_Is2D(TinyKtx_ContextHandle handle); 57 | bool TinyKtx_Is3D(TinyKtx_ContextHandle handle); 58 | bool TinyKtx_IsCubemap(TinyKtx_ContextHandle handle); 59 | bool TinyKtx_IsArray(TinyKtx_ContextHandle handle); 60 | 61 | bool TinyKtx_Dimensions(TinyKtx_ContextHandle handle, uint32_t* width, uint32_t* height, uint32_t* depth, uint32_t* slices); 62 | uint32_t TinyKtx_Width(TinyKtx_ContextHandle handle); 63 | uint32_t TinyKtx_Height(TinyKtx_ContextHandle handle); 64 | uint32_t TinyKtx_Depth(TinyKtx_ContextHandle handle); 65 | uint32_t TinyKtx_ArraySlices(TinyKtx_ContextHandle handle); 66 | 67 | bool TinyKtx_GetFormatGL(TinyKtx_ContextHandle handle, uint32_t *glformat, uint32_t *gltype, uint32_t *glinternalformat, uint32_t* typesize, uint32_t* glbaseinternalformat); 68 | 69 | bool TinyKtx_NeedsGenerationOfMipmaps(TinyKtx_ContextHandle handle); 70 | bool TinyKtx_NeedsEndianCorrecting(TinyKtx_ContextHandle handle); 71 | 72 | uint32_t TinyKtx_NumberOfMipmaps(TinyKtx_ContextHandle handle); 73 | uint32_t TinyKtx_ImageSize(TinyKtx_ContextHandle handle, uint32_t mipmaplevel); 74 | 75 | bool TinyKtx_IsMipMapLevelUnpacked(TinyKtx_ContextHandle handle, uint32_t mipmaplevel); 76 | // this is required to read Unpacked data correctly 77 | uint32_t TinyKtx_UnpackedRowStride(TinyKtx_ContextHandle handle, uint32_t mipmaplevel); 78 | 79 | // data return by ImageRawData is owned by the context. Don't free it! 80 | void const *TinyKtx_ImageRawData(TinyKtx_ContextHandle handle, uint32_t mipmaplevel); 81 | 82 | typedef void (*TinyKtx_WriteFunc)(void *user, void const *buffer, size_t byteCount); 83 | 84 | typedef struct TinyKtx_WriteCallbacks { 85 | TinyKtx_ErrorFunc errorFn; 86 | TinyKtx_AllocFunc allocFn; 87 | TinyKtx_FreeFunc freeFn; 88 | TinyKtx_WriteFunc writeFn; 89 | } TinyKtx_WriteCallbacks; 90 | 91 | 92 | bool TinyKtx_WriteImageGL(TinyKtx_WriteCallbacks const *callbacks, 93 | void *user, 94 | uint32_t width, 95 | uint32_t height, 96 | uint32_t depth, 97 | uint32_t slices, 98 | uint32_t mipmaplevels, 99 | uint32_t format, 100 | uint32_t internalFormat, 101 | uint32_t baseFormat, 102 | uint32_t type, 103 | uint32_t typeSize, 104 | bool cubemap, 105 | uint32_t const *mipmapsizes, 106 | void const **mipmaps); 107 | 108 | // ktx v1 is based on GL (slightly confusing imho) texture format system 109 | // there is format, internal format, type etc. 110 | 111 | // we try and expose a more dx12/vulkan/metal style of format 112 | // but obviously still need to GL data so bare with me. 113 | // a TinyKTX_Format is the equivilent to GL/KTX Format and Type 114 | // the API doesn't expose the actual values (which come from GL itself) 115 | // but provide an API call to crack them back into the actual GL values). 116 | 117 | // Ktx v2 is based on VkFormat and also DFD, so we now base the 118 | // enumeration values of TinyKtx_Format on the Vkformat values where possible 119 | 120 | #ifndef TINYIMAGEFORMAT_VKFORMAT 121 | #define TINYIMAGEFORMAT_VKFORMAT 122 | typedef enum TinyImageFormat_VkFormat { 123 | TIF_VK_FORMAT_UNDEFINED = 0, 124 | TIF_VK_FORMAT_R4G4_UNORM_PACK8 = 1, 125 | TIF_VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2, 126 | TIF_VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3, 127 | TIF_VK_FORMAT_R5G6B5_UNORM_PACK16 = 4, 128 | TIF_VK_FORMAT_B5G6R5_UNORM_PACK16 = 5, 129 | TIF_VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6, 130 | TIF_VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7, 131 | TIF_VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8, 132 | TIF_VK_FORMAT_R8_UNORM = 9, 133 | TIF_VK_FORMAT_R8_SNORM = 10, 134 | TIF_VK_FORMAT_R8_USCALED = 11, 135 | TIF_VK_FORMAT_R8_SSCALED = 12, 136 | TIF_VK_FORMAT_R8_UINT = 13, 137 | TIF_VK_FORMAT_R8_SINT = 14, 138 | TIF_VK_FORMAT_R8_SRGB = 15, 139 | TIF_VK_FORMAT_R8G8_UNORM = 16, 140 | TIF_VK_FORMAT_R8G8_SNORM = 17, 141 | TIF_VK_FORMAT_R8G8_USCALED = 18, 142 | TIF_VK_FORMAT_R8G8_SSCALED = 19, 143 | TIF_VK_FORMAT_R8G8_UINT = 20, 144 | TIF_VK_FORMAT_R8G8_SINT = 21, 145 | TIF_VK_FORMAT_R8G8_SRGB = 22, 146 | TIF_VK_FORMAT_R8G8B8_UNORM = 23, 147 | TIF_VK_FORMAT_R8G8B8_SNORM = 24, 148 | TIF_VK_FORMAT_R8G8B8_USCALED = 25, 149 | TIF_VK_FORMAT_R8G8B8_SSCALED = 26, 150 | TIF_VK_FORMAT_R8G8B8_UINT = 27, 151 | TIF_VK_FORMAT_R8G8B8_SINT = 28, 152 | TIF_VK_FORMAT_R8G8B8_SRGB = 29, 153 | TIF_VK_FORMAT_B8G8R8_UNORM = 30, 154 | TIF_VK_FORMAT_B8G8R8_SNORM = 31, 155 | TIF_VK_FORMAT_B8G8R8_USCALED = 32, 156 | TIF_VK_FORMAT_B8G8R8_SSCALED = 33, 157 | TIF_VK_FORMAT_B8G8R8_UINT = 34, 158 | TIF_VK_FORMAT_B8G8R8_SINT = 35, 159 | TIF_VK_FORMAT_B8G8R8_SRGB = 36, 160 | TIF_VK_FORMAT_R8G8B8A8_UNORM = 37, 161 | TIF_VK_FORMAT_R8G8B8A8_SNORM = 38, 162 | TIF_VK_FORMAT_R8G8B8A8_USCALED = 39, 163 | TIF_VK_FORMAT_R8G8B8A8_SSCALED = 40, 164 | TIF_VK_FORMAT_R8G8B8A8_UINT = 41, 165 | TIF_VK_FORMAT_R8G8B8A8_SINT = 42, 166 | TIF_VK_FORMAT_R8G8B8A8_SRGB = 43, 167 | TIF_VK_FORMAT_B8G8R8A8_UNORM = 44, 168 | TIF_VK_FORMAT_B8G8R8A8_SNORM = 45, 169 | TIF_VK_FORMAT_B8G8R8A8_USCALED = 46, 170 | TIF_VK_FORMAT_B8G8R8A8_SSCALED = 47, 171 | TIF_VK_FORMAT_B8G8R8A8_UINT = 48, 172 | TIF_VK_FORMAT_B8G8R8A8_SINT = 49, 173 | TIF_VK_FORMAT_B8G8R8A8_SRGB = 50, 174 | TIF_VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51, 175 | TIF_VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52, 176 | TIF_VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53, 177 | TIF_VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54, 178 | TIF_VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55, 179 | TIF_VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56, 180 | TIF_VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57, 181 | TIF_VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58, 182 | TIF_VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59, 183 | TIF_VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60, 184 | TIF_VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61, 185 | TIF_VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62, 186 | TIF_VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63, 187 | TIF_VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64, 188 | TIF_VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65, 189 | TIF_VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66, 190 | TIF_VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67, 191 | TIF_VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68, 192 | TIF_VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69, 193 | TIF_VK_FORMAT_R16_UNORM = 70, 194 | TIF_VK_FORMAT_R16_SNORM = 71, 195 | TIF_VK_FORMAT_R16_USCALED = 72, 196 | TIF_VK_FORMAT_R16_SSCALED = 73, 197 | TIF_VK_FORMAT_R16_UINT = 74, 198 | TIF_VK_FORMAT_R16_SINT = 75, 199 | TIF_VK_FORMAT_R16_SFLOAT = 76, 200 | TIF_VK_FORMAT_R16G16_UNORM = 77, 201 | TIF_VK_FORMAT_R16G16_SNORM = 78, 202 | TIF_VK_FORMAT_R16G16_USCALED = 79, 203 | TIF_VK_FORMAT_R16G16_SSCALED = 80, 204 | TIF_VK_FORMAT_R16G16_UINT = 81, 205 | TIF_VK_FORMAT_R16G16_SINT = 82, 206 | TIF_VK_FORMAT_R16G16_SFLOAT = 83, 207 | TIF_VK_FORMAT_R16G16B16_UNORM = 84, 208 | TIF_VK_FORMAT_R16G16B16_SNORM = 85, 209 | TIF_VK_FORMAT_R16G16B16_USCALED = 86, 210 | TIF_VK_FORMAT_R16G16B16_SSCALED = 87, 211 | TIF_VK_FORMAT_R16G16B16_UINT = 88, 212 | TIF_VK_FORMAT_R16G16B16_SINT = 89, 213 | TIF_VK_FORMAT_R16G16B16_SFLOAT = 90, 214 | TIF_VK_FORMAT_R16G16B16A16_UNORM = 91, 215 | TIF_VK_FORMAT_R16G16B16A16_SNORM = 92, 216 | TIF_VK_FORMAT_R16G16B16A16_USCALED = 93, 217 | TIF_VK_FORMAT_R16G16B16A16_SSCALED = 94, 218 | TIF_VK_FORMAT_R16G16B16A16_UINT = 95, 219 | TIF_VK_FORMAT_R16G16B16A16_SINT = 96, 220 | TIF_VK_FORMAT_R16G16B16A16_SFLOAT = 97, 221 | TIF_VK_FORMAT_R32_UINT = 98, 222 | TIF_VK_FORMAT_R32_SINT = 99, 223 | TIF_VK_FORMAT_R32_SFLOAT = 100, 224 | TIF_VK_FORMAT_R32G32_UINT = 101, 225 | TIF_VK_FORMAT_R32G32_SINT = 102, 226 | TIF_VK_FORMAT_R32G32_SFLOAT = 103, 227 | TIF_VK_FORMAT_R32G32B32_UINT = 104, 228 | TIF_VK_FORMAT_R32G32B32_SINT = 105, 229 | TIF_VK_FORMAT_R32G32B32_SFLOAT = 106, 230 | TIF_VK_FORMAT_R32G32B32A32_UINT = 107, 231 | TIF_VK_FORMAT_R32G32B32A32_SINT = 108, 232 | TIF_VK_FORMAT_R32G32B32A32_SFLOAT = 109, 233 | TIF_VK_FORMAT_R64_UINT = 110, 234 | TIF_VK_FORMAT_R64_SINT = 111, 235 | TIF_VK_FORMAT_R64_SFLOAT = 112, 236 | TIF_VK_FORMAT_R64G64_UINT = 113, 237 | TIF_VK_FORMAT_R64G64_SINT = 114, 238 | TIF_VK_FORMAT_R64G64_SFLOAT = 115, 239 | TIF_VK_FORMAT_R64G64B64_UINT = 116, 240 | TIF_VK_FORMAT_R64G64B64_SINT = 117, 241 | TIF_VK_FORMAT_R64G64B64_SFLOAT = 118, 242 | TIF_VK_FORMAT_R64G64B64A64_UINT = 119, 243 | TIF_VK_FORMAT_R64G64B64A64_SINT = 120, 244 | TIF_VK_FORMAT_R64G64B64A64_SFLOAT = 121, 245 | TIF_VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122, 246 | TIF_VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123, 247 | TIF_VK_FORMAT_D16_UNORM = 124, 248 | TIF_VK_FORMAT_X8_D24_UNORM_PACK32 = 125, 249 | TIF_VK_FORMAT_D32_SFLOAT = 126, 250 | TIF_VK_FORMAT_S8_UINT = 127, 251 | TIF_VK_FORMAT_D16_UNORM_S8_UINT = 128, 252 | TIF_VK_FORMAT_D24_UNORM_S8_UINT = 129, 253 | TIF_VK_FORMAT_D32_SFLOAT_S8_UINT = 130, 254 | TIF_VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131, 255 | TIF_VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132, 256 | TIF_VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133, 257 | TIF_VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134, 258 | TIF_VK_FORMAT_BC2_UNORM_BLOCK = 135, 259 | TIF_VK_FORMAT_BC2_SRGB_BLOCK = 136, 260 | TIF_VK_FORMAT_BC3_UNORM_BLOCK = 137, 261 | TIF_VK_FORMAT_BC3_SRGB_BLOCK = 138, 262 | TIF_VK_FORMAT_BC4_UNORM_BLOCK = 139, 263 | TIF_VK_FORMAT_BC4_SNORM_BLOCK = 140, 264 | TIF_VK_FORMAT_BC5_UNORM_BLOCK = 141, 265 | TIF_VK_FORMAT_BC5_SNORM_BLOCK = 142, 266 | TIF_VK_FORMAT_BC6H_UFLOAT_BLOCK = 143, 267 | TIF_VK_FORMAT_BC6H_SFLOAT_BLOCK = 144, 268 | TIF_VK_FORMAT_BC7_UNORM_BLOCK = 145, 269 | TIF_VK_FORMAT_BC7_SRGB_BLOCK = 146, 270 | TIF_VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147, 271 | TIF_VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148, 272 | TIF_VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149, 273 | TIF_VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150, 274 | TIF_VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151, 275 | TIF_VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152, 276 | TIF_VK_FORMAT_EAC_R11_UNORM_BLOCK = 153, 277 | TIF_VK_FORMAT_EAC_R11_SNORM_BLOCK = 154, 278 | TIF_VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155, 279 | TIF_VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156, 280 | TIF_VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157, 281 | TIF_VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158, 282 | TIF_VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159, 283 | TIF_VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160, 284 | TIF_VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161, 285 | TIF_VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162, 286 | TIF_VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163, 287 | TIF_VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164, 288 | TIF_VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165, 289 | TIF_VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166, 290 | TIF_VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167, 291 | TIF_VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168, 292 | TIF_VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169, 293 | TIF_VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170, 294 | TIF_VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171, 295 | TIF_VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172, 296 | TIF_VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173, 297 | TIF_VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174, 298 | TIF_VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175, 299 | TIF_VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176, 300 | TIF_VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177, 301 | TIF_VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178, 302 | TIF_VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179, 303 | TIF_VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180, 304 | TIF_VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181, 305 | TIF_VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182, 306 | TIF_VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183, 307 | TIF_VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184, 308 | 309 | TIF_VK_FORMAT_G8B8G8R8_422_UNORM = 1000156000, 310 | TIF_VK_FORMAT_B8G8R8G8_422_UNORM = 1000156001, 311 | TIF_VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM = 1000156002, 312 | TIF_VK_FORMAT_G8_B8R8_2PLANE_420_UNORM = 1000156003, 313 | TIF_VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM = 1000156004, 314 | TIF_VK_FORMAT_G8_B8R8_2PLANE_422_UNORM = 1000156005, 315 | TIF_VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM = 1000156006, 316 | TIF_VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007, 317 | TIF_VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008, 318 | TIF_VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009, 319 | TIF_VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010, 320 | TIF_VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011, 321 | TIF_VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 = 1000156012, 322 | TIF_VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 = 1000156013, 323 | TIF_VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 = 1000156014, 324 | TIF_VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 = 1000156015, 325 | TIF_VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 = 1000156016, 326 | TIF_VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017, 327 | TIF_VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018, 328 | TIF_VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019, 329 | TIF_VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020, 330 | TIF_VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021, 331 | TIF_VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 = 1000156022, 332 | TIF_VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 = 1000156023, 333 | TIF_VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 = 1000156024, 334 | TIF_VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 = 1000156025, 335 | TIF_VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 = 1000156026, 336 | TIF_VK_FORMAT_G16B16G16R16_422_UNORM = 1000156027, 337 | TIF_VK_FORMAT_B16G16R16G16_422_UNORM = 1000156028, 338 | TIF_VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM = 1000156029, 339 | TIF_VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030, 340 | TIF_VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031, 341 | TIF_VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032, 342 | TIF_VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033, 343 | TIF_VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000, 344 | TIF_VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001, 345 | TIF_VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002, 346 | TIF_VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003, 347 | TIF_VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004, 348 | TIF_VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005, 349 | TIF_VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006, 350 | TIF_VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007, 351 | } TinyImageFormat_VkFormat; 352 | #endif // TINYIMAGEFORMAT_VKFORMAT 353 | 354 | #define TINYKTX_MEV(x) TKTX_##x = TIF_VK_FORMAT_##x 355 | typedef enum TinyKtx_Format { 356 | TINYKTX_MEV(UNDEFINED), 357 | TINYKTX_MEV(R4G4_UNORM_PACK8), 358 | TINYKTX_MEV(R4G4B4A4_UNORM_PACK16), 359 | TINYKTX_MEV(B4G4R4A4_UNORM_PACK16), 360 | TINYKTX_MEV(R5G6B5_UNORM_PACK16), 361 | TINYKTX_MEV(B5G6R5_UNORM_PACK16), 362 | TINYKTX_MEV(R5G5B5A1_UNORM_PACK16), 363 | TINYKTX_MEV(B5G5R5A1_UNORM_PACK16), 364 | TINYKTX_MEV(A1R5G5B5_UNORM_PACK16), 365 | 366 | TINYKTX_MEV(R8_UNORM), 367 | TINYKTX_MEV(R8_SNORM), 368 | TINYKTX_MEV(R8_UINT), 369 | TINYKTX_MEV(R8_SINT), 370 | TINYKTX_MEV(R8_SRGB), 371 | 372 | TINYKTX_MEV(R8G8_UNORM), 373 | TINYKTX_MEV(R8G8_SNORM), 374 | TINYKTX_MEV(R8G8_UINT), 375 | TINYKTX_MEV(R8G8_SINT), 376 | TINYKTX_MEV(R8G8_SRGB), 377 | 378 | TINYKTX_MEV(R8G8B8_UNORM), 379 | TINYKTX_MEV(R8G8B8_SNORM), 380 | TINYKTX_MEV(R8G8B8_UINT), 381 | TINYKTX_MEV(R8G8B8_SINT), 382 | TINYKTX_MEV(R8G8B8_SRGB), 383 | TINYKTX_MEV(B8G8R8_UNORM), 384 | TINYKTX_MEV(B8G8R8_SNORM), 385 | TINYKTX_MEV(B8G8R8_UINT), 386 | TINYKTX_MEV(B8G8R8_SINT), 387 | TINYKTX_MEV(B8G8R8_SRGB), 388 | 389 | TINYKTX_MEV(R8G8B8A8_UNORM), 390 | TINYKTX_MEV(R8G8B8A8_SNORM), 391 | TINYKTX_MEV(R8G8B8A8_UINT), 392 | TINYKTX_MEV(R8G8B8A8_SINT), 393 | TINYKTX_MEV(R8G8B8A8_SRGB), 394 | TINYKTX_MEV(B8G8R8A8_UNORM), 395 | TINYKTX_MEV(B8G8R8A8_SNORM), 396 | TINYKTX_MEV(B8G8R8A8_UINT), 397 | TINYKTX_MEV(B8G8R8A8_SINT), 398 | TINYKTX_MEV(B8G8R8A8_SRGB), 399 | 400 | TINYKTX_MEV(A8B8G8R8_UNORM_PACK32), 401 | TINYKTX_MEV(A8B8G8R8_SNORM_PACK32), 402 | TINYKTX_MEV(A8B8G8R8_UINT_PACK32), 403 | TINYKTX_MEV(A8B8G8R8_SINT_PACK32), 404 | TINYKTX_MEV(A8B8G8R8_SRGB_PACK32), 405 | 406 | TINYKTX_MEV(E5B9G9R9_UFLOAT_PACK32), 407 | TINYKTX_MEV(A2R10G10B10_UNORM_PACK32), 408 | TINYKTX_MEV(A2R10G10B10_UINT_PACK32), 409 | TINYKTX_MEV(A2B10G10R10_UNORM_PACK32), 410 | TINYKTX_MEV(A2B10G10R10_UINT_PACK32), 411 | TINYKTX_MEV(B10G11R11_UFLOAT_PACK32), 412 | 413 | TINYKTX_MEV(R16_UNORM), 414 | TINYKTX_MEV(R16_SNORM), 415 | TINYKTX_MEV(R16_UINT), 416 | TINYKTX_MEV(R16_SINT), 417 | TINYKTX_MEV(R16_SFLOAT), 418 | TINYKTX_MEV(R16G16_UNORM), 419 | TINYKTX_MEV(R16G16_SNORM), 420 | TINYKTX_MEV(R16G16_UINT), 421 | TINYKTX_MEV(R16G16_SINT), 422 | TINYKTX_MEV(R16G16_SFLOAT), 423 | TINYKTX_MEV(R16G16B16_UNORM), 424 | TINYKTX_MEV(R16G16B16_SNORM), 425 | TINYKTX_MEV(R16G16B16_UINT), 426 | TINYKTX_MEV(R16G16B16_SINT), 427 | TINYKTX_MEV(R16G16B16_SFLOAT), 428 | TINYKTX_MEV(R16G16B16A16_UNORM), 429 | TINYKTX_MEV(R16G16B16A16_SNORM), 430 | TINYKTX_MEV(R16G16B16A16_UINT), 431 | TINYKTX_MEV(R16G16B16A16_SINT), 432 | TINYKTX_MEV(R16G16B16A16_SFLOAT), 433 | TINYKTX_MEV(R32_UINT), 434 | TINYKTX_MEV(R32_SINT), 435 | TINYKTX_MEV(R32_SFLOAT), 436 | TINYKTX_MEV(R32G32_UINT), 437 | TINYKTX_MEV(R32G32_SINT), 438 | TINYKTX_MEV(R32G32_SFLOAT), 439 | TINYKTX_MEV(R32G32B32_UINT), 440 | TINYKTX_MEV(R32G32B32_SINT), 441 | TINYKTX_MEV(R32G32B32_SFLOAT), 442 | TINYKTX_MEV(R32G32B32A32_UINT), 443 | TINYKTX_MEV(R32G32B32A32_SINT), 444 | TINYKTX_MEV(R32G32B32A32_SFLOAT), 445 | 446 | TINYKTX_MEV(BC1_RGB_UNORM_BLOCK), 447 | TINYKTX_MEV(BC1_RGB_SRGB_BLOCK), 448 | TINYKTX_MEV(BC1_RGBA_UNORM_BLOCK), 449 | TINYKTX_MEV(BC1_RGBA_SRGB_BLOCK), 450 | TINYKTX_MEV(BC2_UNORM_BLOCK), 451 | TINYKTX_MEV(BC2_SRGB_BLOCK), 452 | TINYKTX_MEV(BC3_UNORM_BLOCK), 453 | TINYKTX_MEV(BC3_SRGB_BLOCK), 454 | TINYKTX_MEV(BC4_UNORM_BLOCK), 455 | TINYKTX_MEV(BC4_SNORM_BLOCK), 456 | TINYKTX_MEV(BC5_UNORM_BLOCK), 457 | TINYKTX_MEV(BC5_SNORM_BLOCK), 458 | TINYKTX_MEV(BC6H_UFLOAT_BLOCK), 459 | TINYKTX_MEV(BC6H_SFLOAT_BLOCK), 460 | TINYKTX_MEV(BC7_UNORM_BLOCK), 461 | TINYKTX_MEV(BC7_SRGB_BLOCK), 462 | 463 | TINYKTX_MEV(ETC2_R8G8B8_UNORM_BLOCK), 464 | TINYKTX_MEV(ETC2_R8G8B8A1_UNORM_BLOCK), 465 | TINYKTX_MEV(ETC2_R8G8B8A8_UNORM_BLOCK), 466 | TINYKTX_MEV(ETC2_R8G8B8_SRGB_BLOCK), 467 | TINYKTX_MEV(ETC2_R8G8B8A1_SRGB_BLOCK), 468 | TINYKTX_MEV(ETC2_R8G8B8A8_SRGB_BLOCK), 469 | TINYKTX_MEV(EAC_R11_UNORM_BLOCK), 470 | TINYKTX_MEV(EAC_R11G11_UNORM_BLOCK), 471 | TINYKTX_MEV(EAC_R11_SNORM_BLOCK), 472 | TINYKTX_MEV(EAC_R11G11_SNORM_BLOCK), 473 | 474 | TKTX_PVR_2BPP_UNORM_BLOCK = TIF_VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, 475 | TKTX_PVR_2BPPA_UNORM_BLOCK = TIF_VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG, 476 | TKTX_PVR_4BPP_UNORM_BLOCK = TIF_VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, 477 | TKTX_PVR_4BPPA_UNORM_BLOCK = TIF_VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG, 478 | TKTX_PVR_2BPP_SRGB_BLOCK = TIF_VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, 479 | TKTX_PVR_2BPPA_SRGB_BLOCK = TIF_VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG, 480 | TKTX_PVR_4BPP_SRGB_BLOCK = TIF_VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG, 481 | TKTX_PVR_4BPPA_SRGB_BLOCK = TIF_VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG, 482 | 483 | TINYKTX_MEV(ASTC_4x4_UNORM_BLOCK), 484 | TINYKTX_MEV(ASTC_4x4_SRGB_BLOCK), 485 | TINYKTX_MEV(ASTC_5x4_UNORM_BLOCK), 486 | TINYKTX_MEV(ASTC_5x4_SRGB_BLOCK), 487 | TINYKTX_MEV(ASTC_5x5_UNORM_BLOCK), 488 | TINYKTX_MEV(ASTC_5x5_SRGB_BLOCK), 489 | TINYKTX_MEV(ASTC_6x5_UNORM_BLOCK), 490 | TINYKTX_MEV(ASTC_6x5_SRGB_BLOCK), 491 | TINYKTX_MEV(ASTC_6x6_UNORM_BLOCK), 492 | TINYKTX_MEV(ASTC_6x6_SRGB_BLOCK), 493 | TINYKTX_MEV(ASTC_8x5_UNORM_BLOCK), 494 | TINYKTX_MEV(ASTC_8x5_SRGB_BLOCK), 495 | TINYKTX_MEV(ASTC_8x6_UNORM_BLOCK), 496 | TINYKTX_MEV(ASTC_8x6_SRGB_BLOCK), 497 | TINYKTX_MEV(ASTC_8x8_UNORM_BLOCK), 498 | TINYKTX_MEV(ASTC_8x8_SRGB_BLOCK), 499 | TINYKTX_MEV(ASTC_10x5_UNORM_BLOCK), 500 | TINYKTX_MEV(ASTC_10x5_SRGB_BLOCK), 501 | TINYKTX_MEV(ASTC_10x6_UNORM_BLOCK), 502 | TINYKTX_MEV(ASTC_10x6_SRGB_BLOCK), 503 | TINYKTX_MEV(ASTC_10x8_UNORM_BLOCK), 504 | TINYKTX_MEV(ASTC_10x8_SRGB_BLOCK), 505 | TINYKTX_MEV(ASTC_10x10_UNORM_BLOCK), 506 | TINYKTX_MEV(ASTC_10x10_SRGB_BLOCK), 507 | TINYKTX_MEV(ASTC_12x10_UNORM_BLOCK), 508 | TINYKTX_MEV(ASTC_12x10_SRGB_BLOCK), 509 | TINYKTX_MEV(ASTC_12x12_UNORM_BLOCK), 510 | TINYKTX_MEV(ASTC_12x12_SRGB_BLOCK), 511 | 512 | } TinyKtx_Format; 513 | #undef TINYKTX_MEV 514 | 515 | // tiny_imageformat/format needs included before tinyktx.h for this functionality 516 | #ifdef TINYIMAGEFORMAT_BASE_H_ 517 | TinyImageFormat TinyImageFormat_FromTinyKtxFormat(TinyKtx_Format format); 518 | TinyKtx_Format TinyImageFormat_ToTinyKtxFormat(TinyImageFormat format); 519 | #endif 520 | 521 | TinyKtx_Format TinyKtx_GetFormat(TinyKtx_ContextHandle handle); 522 | bool TinyKtx_CrackFormatToGL(TinyKtx_Format format, uint32_t *glformat, uint32_t *gltype, uint32_t *glinternalformat, uint32_t* typesize); 523 | bool TinyKtx_WriteImage(TinyKtx_WriteCallbacks const *callbacks, 524 | void *user, 525 | uint32_t width, 526 | uint32_t height, 527 | uint32_t depth, 528 | uint32_t slices, 529 | uint32_t mipmaplevels, 530 | TinyKtx_Format format, 531 | bool cubemap, 532 | uint32_t const *mipmapsizes, 533 | void const **mipmaps); 534 | // GL types 535 | #define TINYKTX_GL_TYPE_COMPRESSED 0x0 536 | #define TINYKTX_GL_TYPE_BYTE 0x1400 537 | #define TINYKTX_GL_TYPE_UNSIGNED_BYTE 0x1401 538 | #define TINYKTX_GL_TYPE_SHORT 0x1402 539 | #define TINYKTX_GL_TYPE_UNSIGNED_SHORT 0x1403 540 | #define TINYKTX_GL_TYPE_INT 0x1404 541 | #define TINYKTX_GL_TYPE_UNSIGNED_INT 0x1405 542 | #define TINYKTX_GL_TYPE_FLOAT 0x1406 543 | #define TINYKTX_GL_TYPE_DOUBLE 0x140A 544 | #define TINYKTX_GL_TYPE_HALF_FLOAT 0x140B 545 | #define TINYKTX_GL_TYPE_UNSIGNED_BYTE_3_3_2 0x8032 546 | #define TINYKTX_GL_TYPE_UNSIGNED_SHORT_4_4_4_4 0x8033 547 | #define TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_5_5_1 0x8034 548 | #define TINYKTX_GL_TYPE_UNSIGNED_INT_8_8_8_8 0x8035 549 | #define TINYKTX_GL_TYPE_UNSIGNED_INT_10_10_10_2 0x8036 550 | #define TINYKTX_GL_TYPE_UNSIGNED_BYTE_2_3_3_REV 0x8362 551 | #define TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_6_5 0x8363 552 | #define TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_6_5_REV 0x8364 553 | #define TINYKTX_GL_TYPE_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 554 | #define TINYKTX_GL_TYPE_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 555 | #define TINYKTX_GL_TYPE_UNSIGNED_INT_8_8_8_8_REV 0x8367 556 | #define TINYKTX_GL_TYPE_UNSIGNED_INT_2_10_10_10_REV 0x8368 557 | #define TINYKTX_GL_TYPE_UNSIGNED_INT_24_8 0x84FA 558 | #define TINYKTX_GL_TYPE_UNSIGNED_INT_5_9_9_9_REV 0x8C3E 559 | #define TINYKTX_GL_TYPE_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B 560 | #define TINYKTX_GL_TYPE_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD 561 | 562 | // formats 563 | #define TINYKTX_GL_FORMAT_RED 0x1903 564 | #define TINYKTX_GL_FORMAT_GREEN 0x1904 565 | #define TINYKTX_GL_FORMAT_BLUE 0x1905 566 | #define TINYKTX_GL_FORMAT_ALPHA 0x1906 567 | #define TINYKTX_GL_FORMAT_RGB 0x1907 568 | #define TINYKTX_GL_FORMAT_RGBA 0x1908 569 | #define TINYKTX_GL_FORMAT_LUMINANCE 0x1909 570 | #define TINYKTX_GL_FORMAT_LUMINANCE_ALPHA 0x190A 571 | #define TINYKTX_GL_FORMAT_ABGR 0x8000 572 | #define TINYKTX_GL_FORMAT_INTENSITY 0x8049 573 | #define TINYKTX_GL_FORMAT_BGR 0x80E0 574 | #define TINYKTX_GL_FORMAT_BGRA 0x80E1 575 | #define TINYKTX_GL_FORMAT_RG 0x8227 576 | #define TINYKTX_GL_FORMAT_RG_INTEGER 0x8228 577 | #define TINYKTX_GL_FORMAT_SRGB 0x8C40 578 | #define TINYKTX_GL_FORMAT_SRGB_ALPHA 0x8C42 579 | #define TINYKTX_GL_FORMAT_SLUMINANCE_ALPHA 0x8C44 580 | #define TINYKTX_GL_FORMAT_SLUMINANCE 0x8C46 581 | #define TINYKTX_GL_FORMAT_RED_INTEGER 0x8D94 582 | #define TINYKTX_GL_FORMAT_GREEN_INTEGER 0x8D95 583 | #define TINYKTX_GL_FORMAT_BLUE_INTEGER 0x8D96 584 | #define TINYKTX_GL_FORMAT_ALPHA_INTEGER 0x8D97 585 | #define TINYKTX_GL_FORMAT_RGB_INTEGER 0x8D98 586 | #define TINYKTX_GL_FORMAT_RGBA_INTEGER 0x8D99 587 | #define TINYKTX_GL_FORMAT_BGR_INTEGER 0x8D9A 588 | #define TINYKTX_GL_FORMAT_BGRA_INTEGER 0x8D9B 589 | #define TINYKTX_GL_FORMAT_RED_SNORM 0x8F90 590 | #define TINYKTX_GL_FORMAT_RG_SNORM 0x8F91 591 | #define TINYKTX_GL_FORMAT_RGB_SNORM 0x8F92 592 | #define TINYKTX_GL_FORMAT_RGBA_SNORM 0x8F93 593 | 594 | #define TINYKTX_GL_INTFORMAT_ALPHA4 0x803B 595 | #define TINYKTX_GL_INTFORMAT_ALPHA8 0x803C 596 | #define TINYKTX_GL_INTFORMAT_ALPHA12 0x803D 597 | #define TINYKTX_GL_INTFORMAT_ALPHA16 0x803E 598 | #define TINYKTX_GL_INTFORMAT_LUMINANCE4 0x803F 599 | #define TINYKTX_GL_INTFORMAT_LUMINANCE8 0x8040 600 | #define TINYKTX_GL_INTFORMAT_LUMINANCE12 0x8041 601 | #define TINYKTX_GL_INTFORMAT_LUMINANCE16 0x8042 602 | #define TINYKTX_GL_INTFORMAT_LUMINANCE4_ALPHA4 0x8043 603 | #define TINYKTX_GL_INTFORMAT_LUMINANCE6_ALPHA2 0x8044 604 | #define TINYKTX_GL_INTFORMAT_LUMINANCE8_ALPHA8 0x8045 605 | #define TINYKTX_GL_INTFORMAT_LUMINANCE12_ALPHA4 0x8046 606 | #define TINYKTX_GL_INTFORMAT_LUMINANCE12_ALPHA12 0x8047 607 | #define TINYKTX_GL_INTFORMAT_LUMINANCE16_ALPHA16 0x8048 608 | #define TINYKTX_GL_INTFORMAT_INTENSITY4 0x804A 609 | #define TINYKTX_GL_INTFORMAT_INTENSITY8 0x804B 610 | #define TINYKTX_GL_INTFORMAT_INTENSITY12 0x804C 611 | #define TINYKTX_GL_INTFORMAT_INTENSITY16 0x804D 612 | #define TINYKTX_GL_INTFORMAT_RGB2 0x804E 613 | #define TINYKTX_GL_INTFORMAT_RGB4 0x804F 614 | #define TINYKTX_GL_INTFORMAT_RGB5 0x8050 615 | #define TINYKTX_GL_INTFORMAT_RGB8 0x8051 616 | #define TINYKTX_GL_INTFORMAT_RGB10 0x8052 617 | #define TINYKTX_GL_INTFORMAT_RGB12 0x8053 618 | #define TINYKTX_GL_INTFORMAT_RGB16 0x8054 619 | #define TINYKTX_GL_INTFORMAT_RGBA2 0x8055 620 | #define TINYKTX_GL_INTFORMAT_RGBA4 0x8056 621 | #define TINYKTX_GL_INTFORMAT_RGB5_A1 0x8057 622 | #define TINYKTX_GL_INTFORMAT_RGBA8 0x8058 623 | #define TINYKTX_GL_INTFORMAT_RGB10_A2 0x8059 624 | #define TINYKTX_GL_INTFORMAT_RGBA12 0x805A 625 | #define TINYKTX_GL_INTFORMAT_RGBA16 0x805B 626 | #define TINYKTX_GL_INTFORMAT_R8 0x8229 627 | #define TINYKTX_GL_INTFORMAT_R16 0x822A 628 | #define TINYKTX_GL_INTFORMAT_RG8 0x822B 629 | #define TINYKTX_GL_INTFORMAT_RG16 0x822C 630 | #define TINYKTX_GL_INTFORMAT_R16F 0x822D 631 | #define TINYKTX_GL_INTFORMAT_R32F 0x822E 632 | #define TINYKTX_GL_INTFORMAT_RG16F 0x822F 633 | #define TINYKTX_GL_INTFORMAT_RG32F 0x8230 634 | #define TINYKTX_GL_INTFORMAT_R8I 0x8231 635 | #define TINYKTX_GL_INTFORMAT_R8UI 0x8232 636 | #define TINYKTX_GL_INTFORMAT_R16I 0x8233 637 | #define TINYKTX_GL_INTFORMAT_R16UI 0x8234 638 | #define TINYKTX_GL_INTFORMAT_R32I 0x8235 639 | #define TINYKTX_GL_INTFORMAT_R32UI 0x8236 640 | #define TINYKTX_GL_INTFORMAT_RG8I 0x8237 641 | #define TINYKTX_GL_INTFORMAT_RG8UI 0x8238 642 | #define TINYKTX_GL_INTFORMAT_RG16I 0x8239 643 | #define TINYKTX_GL_INTFORMAT_RG16UI 0x823A 644 | #define TINYKTX_GL_INTFORMAT_RG32I 0x823B 645 | #define TINYKTX_GL_INTFORMAT_RG32UI 0x823C 646 | #define TINYKTX_GL_INTFORMAT_RGBA32F 0x8814 647 | #define TINYKTX_GL_INTFORMAT_RGB32F 0x8815 648 | #define TINYKTX_GL_INTFORMAT_RGBA16F 0x881A 649 | #define TINYKTX_GL_INTFORMAT_RGB16F 0x881B 650 | #define TINYKTX_GL_INTFORMAT_R11F_G11F_B10F 0x8C3A 651 | #define TINYKTX_GL_INTFORMAT_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B 652 | #define TINYKTX_GL_INTFORMAT_RGB9_E5 0x8C3D 653 | #define TINYKTX_GL_INTFORMAT_SRGB8 0x8C41 654 | #define TINYKTX_GL_INTFORMAT_SRGB8_ALPHA8 0x8C43 655 | #define TINYKTX_GL_INTFORMAT_SLUMINANCE8_ALPHA8 0x8C45 656 | #define TINYKTX_GL_INTFORMAT_SLUMINANCE8 0x8C47 657 | #define TINYKTX_GL_INTFORMAT_RGB565 0x8D62 658 | #define TINYKTX_GL_INTFORMAT_RGBA32UI 0x8D70 659 | #define TINYKTX_GL_INTFORMAT_RGB32UI 0x8D71 660 | #define TINYKTX_GL_INTFORMAT_RGBA16UI 0x8D76 661 | #define TINYKTX_GL_INTFORMAT_RGB16UI 0x8D77 662 | #define TINYKTX_GL_INTFORMAT_RGBA8UI 0x8D7C 663 | #define TINYKTX_GL_INTFORMAT_RGB8UI 0x8D7D 664 | #define TINYKTX_GL_INTFORMAT_RGBA32I 0x8D82 665 | #define TINYKTX_GL_INTFORMAT_RGB32I 0x8D83 666 | #define TINYKTX_GL_INTFORMAT_RGBA16I 0x8D88 667 | #define TINYKTX_GL_INTFORMAT_RGB16I 0x8D89 668 | #define TINYKTX_GL_INTFORMAT_RGBA8I 0x8D8E 669 | #define TINYKTX_GL_INTFORMAT_RGB8I 0x8D8F 670 | #define TINYKTX_GL_INTFORMAT_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD 671 | #define TINYKTX_GL_INTFORMAT_R8_SNORM 0x8F94 672 | #define TINYKTX_GL_INTFORMAT_RG8_SNORM 0x8F95 673 | #define TINYKTX_GL_INTFORMAT_RGB8_SNORM 0x8F96 674 | #define TINYKTX_GL_INTFORMAT_RGBA8_SNORM 0x8F97 675 | #define TINYKTX_GL_INTFORMAT_R16_SNORM 0x8F98 676 | #define TINYKTX_GL_INTFORMAT_RG16_SNORM 0x8F99 677 | #define TINYKTX_GL_INTFORMAT_RGB16_SNORM 0x8F9A 678 | #define TINYKTX_GL_INTFORMAT_RGBA16_SNORM 0x8F9B 679 | #define TINYKTX_GL_INTFORMAT_ALPHA8_SNORM 0x9014 680 | #define TINYKTX_GL_INTFORMAT_LUMINANCE8_SNORM 0x9015 681 | #define TINYKTX_GL_INTFORMAT_LUMINANCE8_ALPHA8_SNORM 0x9016 682 | #define TINYKTX_GL_INTFORMAT_INTENSITY8_SNORM 0x9017 683 | #define TINYKTX_GL_INTFORMAT_ALPHA16_SNORM 0x9018 684 | #define TINYKTX_GL_INTFORMAT_LUMINANCE16_SNORM 0x9019 685 | #define TINYKTX_GL_INTFORMAT_LUMINANCE16_ALPHA16_SNORM 0x901A 686 | #define TINYKTX_GL_INTFORMAT_INTENSITY16_SNORM 0x901B 687 | 688 | #define TINYKTX_GL_PALETTE4_RGB8_OES 0x8B90 689 | #define TINYKTX_GL_PALETTE4_RGBA8_OES 0x8B91 690 | #define TINYKTX_GL_PALETTE4_R5_G6_B5_OES 0x8B92 691 | #define TINYKTX_GL_PALETTE4_RGBA4_OES 0x8B93 692 | #define TINYKTX_GL_PALETTE4_RGB5_A1_OES 0x8B94 693 | #define TINYKTX_GL_PALETTE8_RGB8_OES 0x8B95 694 | #define TINYKTX_GL_PALETTE8_RGBA8_OES 0x8B96 695 | #define TINYKTX_GL_PALETTE8_R5_G6_B5_OES 0x8B97 696 | #define TINYKTX_GL_PALETTE8_RGBA4_OES 0x8B98 697 | #define TINYKTX_GL_PALETTE8_RGB5_A1_OES 0x8B99 698 | 699 | // compressed formats 700 | 701 | #define TINYKTX_GL_COMPRESSED_RGB_S3TC_DXT1 0x83F0 702 | #define TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT1 0x83F1 703 | #define TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT3 0x83F2 704 | #define TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT5 0x83F3 705 | #define TINYKTX_GL_COMPRESSED_3DC_X_AMD 0x87F9 706 | #define TINYKTX_GL_COMPRESSED_3DC_XY_AMD 0x87FA 707 | #define TINYKTX_GL_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA 0x87EE 708 | #define TINYKTX_GL_COMPRESSED_SRGB_PVRTC_2BPPV1 0x8A54 709 | #define TINYKTX_GL_COMPRESSED_SRGB_PVRTC_4BPPV1 0x8A55 710 | #define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1 0x8A56 711 | #define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1 0x8A57 712 | #define TINYKTX_GL_COMPRESSED_RGB_PVRTC_4BPPV1 0x8C00 713 | #define TINYKTX_GL_COMPRESSED_RGB_PVRTC_2BPPV1 0x8C01 714 | #define TINYKTX_GL_COMPRESSED_RGBA_PVRTC_4BPPV1 0x8C02 715 | #define TINYKTX_GL_COMPRESSED_RGBA_PVRTC_2BPPV1 0x8C03 716 | #define TINYKTX_GL_COMPRESSED_SRGB_S3TC_DXT1 0x8C4C 717 | #define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1 0x8C4D 718 | #define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3 0x8C4E 719 | #define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5 0x8C4F 720 | #define TINYKTX_GL_COMPRESSED_LUMINANCE_LATC1 0x8C70 721 | #define TINYKTX_GL_COMPRESSED_SIGNED_LUMINANCE_LATC1 0x8C71 722 | #define TINYKTX_GL_COMPRESSED_LUMINANCE_ALPHA_LATC2 0x8C72 723 | #define TINYKTX_GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2 0x8C73 724 | #define TINYKTX_GL_COMPRESSED_ATC_RGB 0x8C92 725 | #define TINYKTX_GL_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA 0x8C93 726 | #define TINYKTX_GL_COMPRESSED_RED_RGTC1 0x8DBB 727 | #define TINYKTX_GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC 728 | #define TINYKTX_GL_COMPRESSED_RED_GREEN_RGTC2 0x8DBD 729 | #define TINYKTX_GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2 0x8DBE 730 | #define TINYKTX_GL_COMPRESSED_ETC1_RGB8_OES 0x8D64 731 | #define TINYKTX_GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C 732 | #define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D 733 | #define TINYKTX_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E 734 | #define TINYKTX_GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F 735 | #define TINYKTX_GL_COMPRESSED_R11_EAC 0x9270 736 | #define TINYKTX_GL_COMPRESSED_SIGNED_R11_EAC 0x9271 737 | #define TINYKTX_GL_COMPRESSED_RG11_EAC 0x9272 738 | #define TINYKTX_GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 739 | #define TINYKTX_GL_COMPRESSED_RGB8_ETC2 0x9274 740 | #define TINYKTX_GL_COMPRESSED_SRGB8_ETC2 0x9275 741 | #define TINYKTX_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 742 | #define TINYKTX_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 743 | #define TINYKTX_GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 744 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 745 | #define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2 0x93F0 746 | #define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2 0x93F1 747 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_4x4 0x93B0 748 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_5x4 0x93B1 749 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_5x5 0x93B2 750 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_6x5 0x93B3 751 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_6x6 0x93B4 752 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x5 0x93B5 753 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x6 0x93B6 754 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x8 0x93B7 755 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x5 0x93B8 756 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x6 0x93B9 757 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x8 0x93BA 758 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x10 0x93BB 759 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_12x10 0x93BC 760 | #define TINYKTX_GL_COMPRESSED_RGBA_ASTC_12x12 0x93BD 761 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4 0x93D0 762 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4 0x93D1 763 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5 0x93D2 764 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5 0x93D3 765 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6 0x93D4 766 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5 0x93D5 767 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6 0x93D6 768 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8 0x93D7 769 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5 0x93D8 770 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6 0x93D9 771 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8 0x93DA 772 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10 0x93DB 773 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10 0x93DC 774 | #define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12 0x93DD 775 | 776 | #ifdef TINYKTX_IMPLEMENTATION 777 | 778 | typedef struct TinyKtx_Header { 779 | uint8_t identifier[12]; 780 | uint32_t endianness; 781 | uint32_t glType; 782 | uint32_t glTypeSize; 783 | uint32_t glFormat; 784 | uint32_t glInternalFormat; 785 | uint32_t glBaseInternalFormat; 786 | uint32_t pixelWidth; 787 | uint32_t pixelHeight; 788 | uint32_t pixelDepth; 789 | uint32_t numberOfArrayElements; 790 | uint32_t numberOfFaces; 791 | uint32_t numberOfMipmapLevels; 792 | uint32_t bytesOfKeyValueData; 793 | 794 | } TinyKtx_Header; 795 | 796 | typedef struct TinyKtx_KeyValuePair { 797 | uint32_t size; 798 | } TinyKtx_KeyValuePair; // followed by at least size bytes (aligned to 4) 799 | 800 | 801 | typedef struct TinyKtx_Context { 802 | TinyKtx_Callbacks callbacks; 803 | void *user; 804 | uint64_t headerPos; 805 | uint64_t firstImagePos; 806 | 807 | TinyKtx_Header header; 808 | 809 | TinyKtx_KeyValuePair const *keyData; 810 | bool headerValid; 811 | bool sameEndian; 812 | 813 | uint32_t mipMapSizes[TINYKTX_MAX_MIPMAPLEVELS]; 814 | uint8_t const *mipmaps[TINYKTX_MAX_MIPMAPLEVELS]; 815 | 816 | } TinyKtx_Context; 817 | 818 | static uint8_t TinyKtx_fileIdentifier[12] = { 819 | 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A 820 | }; 821 | 822 | static void TinyKtx_NullErrorFunc(void *user, char const *msg) {} 823 | 824 | TinyKtx_ContextHandle TinyKtx_CreateContext(TinyKtx_Callbacks const *callbacks, void *user) { 825 | TinyKtx_Context *ctx = (TinyKtx_Context *) callbacks->allocFn(user, sizeof(TinyKtx_Context)); 826 | if (ctx == NULL) 827 | return NULL; 828 | 829 | memset(ctx, 0, sizeof(TinyKtx_Context)); 830 | memcpy(&ctx->callbacks, callbacks, sizeof(TinyKtx_Callbacks)); 831 | ctx->user = user; 832 | if (ctx->callbacks.errorFn == NULL) { 833 | ctx->callbacks.errorFn = &TinyKtx_NullErrorFunc; 834 | } 835 | 836 | if (ctx->callbacks.readFn == NULL) { 837 | ctx->callbacks.errorFn(user, "TinyKtx must have read callback"); 838 | return NULL; 839 | } 840 | if (ctx->callbacks.allocFn == NULL) { 841 | ctx->callbacks.errorFn(user, "TinyKtx must have alloc callback"); 842 | return NULL; 843 | } 844 | if (ctx->callbacks.freeFn == NULL) { 845 | ctx->callbacks.errorFn(user, "TinyKtx must have free callback"); 846 | return NULL; 847 | } 848 | if (ctx->callbacks.seekFn == NULL) { 849 | ctx->callbacks.errorFn(user, "TinyKtx must have seek callback"); 850 | return NULL; 851 | } 852 | if (ctx->callbacks.tellFn == NULL) { 853 | ctx->callbacks.errorFn(user, "TinyKtx must have tell callback"); 854 | return NULL; 855 | } 856 | 857 | TinyKtx_Reset(ctx); 858 | 859 | return ctx; 860 | } 861 | 862 | void TinyKtx_DestroyContext(TinyKtx_ContextHandle handle) { 863 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 864 | if (ctx == NULL) 865 | return; 866 | TinyKtx_Reset(handle); 867 | 868 | ctx->callbacks.freeFn(ctx->user, ctx); 869 | } 870 | 871 | void TinyKtx_Reset(TinyKtx_ContextHandle handle) { 872 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 873 | if (ctx == NULL) 874 | return; 875 | 876 | // backup user provided callbacks and data 877 | TinyKtx_Callbacks callbacks; 878 | memcpy(&callbacks, &ctx->callbacks, sizeof(TinyKtx_Callbacks)); 879 | void *user = ctx->user; 880 | 881 | // free memory of sub data 882 | if (ctx->keyData != NULL) { 883 | callbacks.freeFn(user, (void *) ctx->keyData); 884 | } 885 | 886 | for (int i = 0; i < TINYKTX_MAX_MIPMAPLEVELS; ++i) { 887 | if (ctx->mipmaps[i] != NULL) { 888 | callbacks.freeFn(user, (void *) ctx->mipmaps[i]); 889 | } 890 | } 891 | 892 | // reset to default state 893 | memset(ctx, 0, sizeof(TinyKtx_Context)); 894 | memcpy(&ctx->callbacks, &callbacks, sizeof(TinyKtx_Callbacks)); 895 | ctx->user = user; 896 | 897 | } 898 | 899 | 900 | bool TinyKtx_ReadHeader(TinyKtx_ContextHandle handle) { 901 | 902 | static uint32_t const sameEndianDecider = 0x04030201; 903 | static uint32_t const differentEndianDecider = 0x01020304; 904 | 905 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 906 | if (ctx == NULL) 907 | return false; 908 | 909 | ctx->headerPos = ctx->callbacks.tellFn(ctx->user); 910 | ctx->callbacks.readFn(ctx->user, &ctx->header, sizeof(TinyKtx_Header)); 911 | 912 | if (memcmp(&ctx->header.identifier, TinyKtx_fileIdentifier, 12) != 0) { 913 | ctx->callbacks.errorFn(ctx->user, "Not a KTX file or corrupted as identified isn't valid"); 914 | return false; 915 | } 916 | 917 | if (ctx->header.endianness == sameEndianDecider) { 918 | ctx->sameEndian = true; 919 | } else if (ctx->header.endianness == differentEndianDecider) { 920 | ctx->sameEndian = false; 921 | } else { 922 | // corrupt or mid endian? 923 | ctx->callbacks.errorFn(ctx->user, "Endian Error"); 924 | return false; 925 | } 926 | 927 | if (ctx->header.numberOfFaces != 1 && ctx->header.numberOfFaces != 6) { 928 | ctx->callbacks.errorFn(ctx->user, "no. of Faces must be 1 or 6"); 929 | return false; 930 | } 931 | 932 | ctx->keyData = (TinyKtx_KeyValuePair const *) ctx->callbacks.allocFn(ctx->user, ctx->header.bytesOfKeyValueData); 933 | ctx->callbacks.readFn(ctx->user, (void *) ctx->keyData, ctx->header.bytesOfKeyValueData); 934 | 935 | ctx->firstImagePos = ctx->callbacks.tellFn(ctx->user); 936 | 937 | ctx->headerValid = true; 938 | return true; 939 | } 940 | 941 | bool TinyKtx_GetValue(TinyKtx_ContextHandle handle, char const *key, void const **value) { 942 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 943 | if (ctx == NULL) 944 | return false; 945 | if (ctx->headerValid == false) { 946 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 947 | return false; 948 | } 949 | 950 | if (ctx->keyData == NULL) { 951 | ctx->callbacks.errorFn(ctx->user, "No key value data in this KTX"); 952 | return false; 953 | } 954 | 955 | TinyKtx_KeyValuePair const *curKey = ctx->keyData; 956 | while (((uint8_t *) curKey - (uint8_t *) ctx->keyData) < ctx->header.bytesOfKeyValueData) { 957 | char const *kvp = (char const *) curKey; 958 | 959 | if (strcmp(kvp, key) == 0) { 960 | size_t sl = strlen(kvp); 961 | *value = (void const *) (kvp + sl); 962 | return true; 963 | } 964 | curKey = curKey + ((curKey->size + 3u) & ~3u); 965 | } 966 | return false; 967 | } 968 | 969 | bool TinyKtx_Is1D(TinyKtx_ContextHandle handle) { 970 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 971 | if (ctx == NULL) 972 | return false; 973 | if (ctx->headerValid == false) { 974 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 975 | return false; 976 | } 977 | return (ctx->header.pixelHeight <= 1) && (ctx->header.pixelDepth <= 1 ); 978 | } 979 | bool TinyKtx_Is2D(TinyKtx_ContextHandle handle) { 980 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 981 | if (ctx == NULL) 982 | return false; 983 | if (ctx->headerValid == false) { 984 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 985 | return false; 986 | } 987 | 988 | return (ctx->header.pixelHeight > 1 && ctx->header.pixelDepth <= 1); 989 | } 990 | bool TinyKtx_Is3D(TinyKtx_ContextHandle handle) { 991 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 992 | if (ctx == NULL) 993 | return false; 994 | if (ctx->headerValid == false) { 995 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 996 | return false; 997 | } 998 | 999 | return (ctx->header.pixelHeight > 1 && ctx->header.pixelDepth > 1); 1000 | } 1001 | 1002 | bool TinyKtx_IsCubemap(TinyKtx_ContextHandle handle) { 1003 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1004 | if (ctx == NULL) 1005 | return false; 1006 | if (ctx->headerValid == false) { 1007 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1008 | return false; 1009 | } 1010 | 1011 | return (ctx->header.numberOfFaces == 6); 1012 | } 1013 | bool TinyKtx_IsArray(TinyKtx_ContextHandle handle) { 1014 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1015 | if (ctx == NULL) 1016 | return false; 1017 | if (ctx->headerValid == false) { 1018 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1019 | return false; 1020 | } 1021 | 1022 | return (ctx->header.numberOfArrayElements > 1); 1023 | } 1024 | 1025 | bool TinyKtx_Dimensions(TinyKtx_ContextHandle handle, 1026 | uint32_t *width, 1027 | uint32_t *height, 1028 | uint32_t *depth, 1029 | uint32_t *slices) { 1030 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1031 | if (ctx == NULL) 1032 | return false; 1033 | if (ctx->headerValid == false) { 1034 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1035 | return false; 1036 | } 1037 | 1038 | if (width) 1039 | *width = ctx->header.pixelWidth; 1040 | if (height) 1041 | *height = ctx->header.pixelWidth; 1042 | if (depth) 1043 | *depth = ctx->header.pixelDepth; 1044 | if (slices) 1045 | *slices = ctx->header.numberOfArrayElements; 1046 | return true; 1047 | } 1048 | 1049 | uint32_t TinyKtx_Width(TinyKtx_ContextHandle handle) { 1050 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1051 | if (ctx == NULL) 1052 | return 0; 1053 | if (ctx->headerValid == false) { 1054 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1055 | return 0; 1056 | } 1057 | return ctx->header.pixelWidth; 1058 | 1059 | } 1060 | 1061 | uint32_t TinyKtx_Height(TinyKtx_ContextHandle handle) { 1062 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1063 | if (ctx == NULL) 1064 | return 0; 1065 | if (ctx->headerValid == false) { 1066 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1067 | return 0; 1068 | } 1069 | 1070 | return ctx->header.pixelHeight; 1071 | } 1072 | 1073 | uint32_t TinyKtx_Depth(TinyKtx_ContextHandle handle) { 1074 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1075 | if (ctx == NULL) 1076 | return 0; 1077 | if (ctx->headerValid == false) { 1078 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1079 | return 0; 1080 | } 1081 | return ctx->header.pixelDepth; 1082 | } 1083 | 1084 | uint32_t TinyKtx_ArraySlices(TinyKtx_ContextHandle handle) { 1085 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1086 | if (ctx == NULL) 1087 | return 0; 1088 | if (ctx->headerValid == false) { 1089 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1090 | return 0; 1091 | } 1092 | 1093 | return ctx->header.numberOfArrayElements; 1094 | } 1095 | 1096 | uint32_t TinyKtx_NumberOfMipmaps(TinyKtx_ContextHandle handle) { 1097 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1098 | if (ctx == NULL) 1099 | return 0; 1100 | if (ctx->headerValid == false) { 1101 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1102 | return 0; 1103 | } 1104 | 1105 | return ctx->header.numberOfMipmapLevels ? ctx->header.numberOfMipmapLevels : 1; 1106 | } 1107 | 1108 | bool TinyKtx_NeedsGenerationOfMipmaps(TinyKtx_ContextHandle handle) { 1109 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1110 | if (ctx == NULL) 1111 | return false; 1112 | if (ctx->headerValid == false) { 1113 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1114 | return false; 1115 | } 1116 | 1117 | return ctx->header.numberOfMipmapLevels == 0; 1118 | } 1119 | 1120 | bool TinyKtx_NeedsEndianCorrecting(TinyKtx_ContextHandle handle) { 1121 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1122 | if (ctx == NULL) 1123 | return false; 1124 | if (ctx->headerValid == false) { 1125 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1126 | return false; 1127 | } 1128 | 1129 | return ctx->sameEndian == false; 1130 | } 1131 | 1132 | bool TinyKtx_GetFormatGL(TinyKtx_ContextHandle handle, uint32_t *glformat, uint32_t *gltype, uint32_t *glinternalformat, uint32_t* typesize, uint32_t* glbaseinternalformat) { 1133 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1134 | if (ctx == NULL) 1135 | return false; 1136 | if (ctx->headerValid == false) { 1137 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1138 | return false; 1139 | } 1140 | 1141 | *glformat = ctx->header.glFormat; 1142 | *gltype = ctx->header.glType; 1143 | *glinternalformat = ctx->header.glInternalFormat; 1144 | *glbaseinternalformat = ctx->header.glBaseInternalFormat; 1145 | *typesize = ctx->header.glBaseInternalFormat; 1146 | 1147 | return true; 1148 | } 1149 | 1150 | static uint32_t TinyKtx_imageSize(TinyKtx_ContextHandle handle, uint32_t mipmaplevel, bool seekLast) { 1151 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1152 | 1153 | if (mipmaplevel >= ctx->header.numberOfMipmapLevels) { 1154 | ctx->callbacks.errorFn(ctx->user, "Invalid mipmap level"); 1155 | return 0; 1156 | } 1157 | if (mipmaplevel >= TINYKTX_MAX_MIPMAPLEVELS) { 1158 | ctx->callbacks.errorFn(ctx->user, "Invalid mipmap level"); 1159 | return 0; 1160 | } 1161 | if (!seekLast && ctx->mipMapSizes[mipmaplevel] != 0) 1162 | return ctx->mipMapSizes[mipmaplevel]; 1163 | 1164 | uint64_t currentOffset = ctx->firstImagePos; 1165 | for (uint32_t i = 0; i <= mipmaplevel; ++i) { 1166 | uint32_t size; 1167 | // if we have already read this mipmaps size use it 1168 | if (ctx->mipMapSizes[i] != 0) { 1169 | size = ctx->mipMapSizes[i]; 1170 | if (seekLast && i == mipmaplevel) { 1171 | ctx->callbacks.seekFn(ctx->user, currentOffset + sizeof(uint32_t)); 1172 | } 1173 | } else { 1174 | // otherwise seek and read it 1175 | ctx->callbacks.seekFn(ctx->user, currentOffset); 1176 | size_t readchk = ctx->callbacks.readFn(ctx->user, &size, sizeof(uint32_t)); 1177 | if(readchk != 4) { 1178 | ctx->callbacks.errorFn(ctx->user, "Reading image size error"); 1179 | return 0; 1180 | } 1181 | // so in the really small print KTX v1 states GL_UNPACK_ALIGNMENT = 4 1182 | // which PVR Texture Tool and I missed. It means pad to 1, 2, 4, 8 1183 | // note 3 or 6 bytes are rounded up. 1184 | // we rely on the loader setting this right, we should handle file with 1185 | // it not to standard but its really the level up that has to do this 1186 | 1187 | if (ctx->header.numberOfFaces == 6 && ctx->header.numberOfArrayElements == 0) { 1188 | size = ((size + 3u) & ~3u) * 6; // face padding and 6 faces 1189 | } 1190 | 1191 | ctx->mipMapSizes[i] = size; 1192 | } 1193 | currentOffset += (size + sizeof(uint32_t) + 3u) & ~3u; // size + mip padding 1194 | } 1195 | 1196 | return ctx->mipMapSizes[mipmaplevel]; 1197 | } 1198 | 1199 | uint32_t TinyKtx_ImageSize(TinyKtx_ContextHandle handle, uint32_t mipmaplevel) { 1200 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1201 | if (ctx == NULL) return 0; 1202 | 1203 | if (ctx->headerValid == false) { 1204 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1205 | return 0; 1206 | } 1207 | return TinyKtx_imageSize(handle, mipmaplevel, false); 1208 | } 1209 | 1210 | void const *TinyKtx_ImageRawData(TinyKtx_ContextHandle handle, uint32_t mipmaplevel) { 1211 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1212 | if (ctx == NULL) 1213 | return NULL; 1214 | 1215 | if (ctx->headerValid == false) { 1216 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1217 | return NULL; 1218 | } 1219 | 1220 | if (mipmaplevel >= ctx->header.numberOfMipmapLevels) { 1221 | ctx->callbacks.errorFn(ctx->user, "Invalid mipmap level"); 1222 | return NULL; 1223 | } 1224 | 1225 | if (mipmaplevel >= TINYKTX_MAX_MIPMAPLEVELS) { 1226 | ctx->callbacks.errorFn(ctx->user, "Invalid mipmap level"); 1227 | return NULL; 1228 | } 1229 | 1230 | if (ctx->mipmaps[mipmaplevel] != NULL) 1231 | return ctx->mipmaps[mipmaplevel]; 1232 | 1233 | uint32_t size = TinyKtx_imageSize(handle, mipmaplevel, true); 1234 | if (size == 0) 1235 | return NULL; 1236 | 1237 | ctx->mipmaps[mipmaplevel] = (uint8_t const*) ctx->callbacks.allocFn(ctx->user, size); 1238 | if (ctx->mipmaps[mipmaplevel]) { 1239 | ctx->callbacks.readFn(ctx->user, (void *) ctx->mipmaps[mipmaplevel], size); 1240 | } 1241 | 1242 | return ctx->mipmaps[mipmaplevel]; 1243 | } 1244 | 1245 | #define FT(fmt, type, intfmt, size) *glformat = TINYKTX_GL_FORMAT_##fmt; \ 1246 | *gltype = TINYKTX_GL_TYPE_##type; \ 1247 | *glinternalformat = TINYKTX_GL_INTFORMAT_##intfmt; \ 1248 | *typesize = size; \ 1249 | return true; 1250 | #define FTC(fmt, intfmt) *glformat = TINYKTX_GL_FORMAT_##fmt; \ 1251 | *gltype = TINYKTX_GL_TYPE_COMPRESSED; \ 1252 | *glinternalformat = TINYKTX_GL_COMPRESSED_##intfmt; \ 1253 | *typesize = 1; \ 1254 | return true; 1255 | 1256 | bool TinyKtx_CrackFormatToGL(TinyKtx_Format format, 1257 | uint32_t *glformat, 1258 | uint32_t *gltype, 1259 | uint32_t *glinternalformat, 1260 | uint32_t *typesize) { 1261 | switch (format) { 1262 | case TKTX_R4G4_UNORM_PACK8: FT(RG, UNSIGNED_SHORT_4_4_4_4, RGB4, 1) 1263 | case TKTX_R4G4B4A4_UNORM_PACK16: FT(RGBA, UNSIGNED_SHORT_4_4_4_4, RGBA4, 2) 1264 | 1265 | case TKTX_B4G4R4A4_UNORM_PACK16: FT(BGRA, UNSIGNED_SHORT_4_4_4_4_REV, RGBA4, 2) 1266 | 1267 | case TKTX_R5G6B5_UNORM_PACK16: FT(RGB, UNSIGNED_SHORT_5_6_5_REV, RGB565, 2) 1268 | case TKTX_B5G6R5_UNORM_PACK16: FT(BGR, UNSIGNED_SHORT_5_6_5, RGB565, 2) 1269 | 1270 | case TKTX_R5G5B5A1_UNORM_PACK16: FT(RGBA, UNSIGNED_SHORT_5_5_5_1, RGB5_A1, 2) 1271 | case TKTX_A1R5G5B5_UNORM_PACK16: FT(RGBA, UNSIGNED_SHORT_1_5_5_5_REV, RGB5_A1, 2) 1272 | case TKTX_B5G5R5A1_UNORM_PACK16: FT(BGRA, UNSIGNED_SHORT_5_5_5_1, RGB5_A1, 2) 1273 | 1274 | case TKTX_A2R10G10B10_UNORM_PACK32: FT(BGRA, UNSIGNED_INT_2_10_10_10_REV, RGB10_A2, 4) 1275 | case TKTX_A2R10G10B10_UINT_PACK32: FT(BGRA_INTEGER, UNSIGNED_INT_2_10_10_10_REV, RGB10_A2, 4) 1276 | case TKTX_A2B10G10R10_UNORM_PACK32: FT(RGBA, UNSIGNED_INT_2_10_10_10_REV, RGB10_A2, 4) 1277 | case TKTX_A2B10G10R10_UINT_PACK32: FT(RGBA_INTEGER, UNSIGNED_INT_2_10_10_10_REV, RGB10_A2, 4) 1278 | 1279 | case TKTX_R8_UNORM: FT(RED, UNSIGNED_BYTE, R8, 1) 1280 | case TKTX_R8_SNORM: FT(RED, BYTE, R8_SNORM, 1) 1281 | case TKTX_R8_UINT: FT(RED_INTEGER, UNSIGNED_BYTE, R8UI, 1) 1282 | case TKTX_R8_SINT: FT(RED_INTEGER, BYTE, R8I, 1) 1283 | case TKTX_R8_SRGB: FT(SLUMINANCE, UNSIGNED_BYTE, SRGB8, 1) 1284 | 1285 | case TKTX_R8G8_UNORM: FT(RG, UNSIGNED_BYTE, RG8, 1) 1286 | case TKTX_R8G8_SNORM: FT(RG, BYTE, RG8_SNORM, 1) 1287 | case TKTX_R8G8_UINT: FT(RG_INTEGER, UNSIGNED_BYTE, RG8UI, 1) 1288 | case TKTX_R8G8_SINT: FT(RG_INTEGER, BYTE, RG8I, 1) 1289 | case TKTX_R8G8_SRGB: FT(SLUMINANCE_ALPHA, UNSIGNED_BYTE, SRGB8, 1) 1290 | 1291 | case TKTX_R8G8B8_UNORM: FT(RGB, UNSIGNED_BYTE, RGB8, 1) 1292 | case TKTX_R8G8B8_SNORM: FT(RGB, BYTE, RGB8_SNORM, 1) 1293 | case TKTX_R8G8B8_UINT: FT(RGB_INTEGER, UNSIGNED_BYTE, RGB8UI, 1) 1294 | case TKTX_R8G8B8_SINT: FT(RGB_INTEGER, BYTE, RGB8I, 1) 1295 | case TKTX_R8G8B8_SRGB: FT(SRGB, UNSIGNED_BYTE, SRGB8, 1) 1296 | 1297 | case TKTX_B8G8R8_UNORM: FT(BGR, UNSIGNED_BYTE, RGB8, 1) 1298 | case TKTX_B8G8R8_SNORM: FT(BGR, BYTE, RGB8_SNORM, 1) 1299 | case TKTX_B8G8R8_UINT: FT(BGR_INTEGER, UNSIGNED_BYTE, RGB8UI, 1) 1300 | case TKTX_B8G8R8_SINT: FT(BGR_INTEGER, BYTE, RGB8I, 1) 1301 | case TKTX_B8G8R8_SRGB: FT(BGR, UNSIGNED_BYTE, SRGB8, 1) 1302 | 1303 | case TKTX_R8G8B8A8_UNORM:FT(RGBA, UNSIGNED_BYTE, RGBA8, 1) 1304 | case TKTX_R8G8B8A8_SNORM:FT(RGBA, BYTE, RGBA8_SNORM, 1) 1305 | case TKTX_R8G8B8A8_UINT: FT(RGBA_INTEGER, UNSIGNED_BYTE, RGBA8UI, 1) 1306 | case TKTX_R8G8B8A8_SINT: FT(RGBA_INTEGER, BYTE, RGBA8I, 1) 1307 | case TKTX_R8G8B8A8_SRGB: FT(SRGB_ALPHA, UNSIGNED_BYTE, SRGB8, 1) 1308 | 1309 | case TKTX_B8G8R8A8_UNORM: FT(BGRA, UNSIGNED_BYTE, RGBA8, 1) 1310 | case TKTX_B8G8R8A8_SNORM: FT(BGRA, BYTE, RGBA8_SNORM, 1) 1311 | case TKTX_B8G8R8A8_UINT: FT(BGRA_INTEGER, UNSIGNED_BYTE, RGBA8UI, 1) 1312 | case TKTX_B8G8R8A8_SINT: FT(BGRA_INTEGER, BYTE, RGBA8I, 1) 1313 | case TKTX_B8G8R8A8_SRGB: FT(BGRA, UNSIGNED_BYTE, SRGB8, 1) 1314 | 1315 | case TKTX_E5B9G9R9_UFLOAT_PACK32: FT(BGR, UNSIGNED_INT_5_9_9_9_REV, RGB9_E5, 4); 1316 | case TKTX_A8B8G8R8_UNORM_PACK32: FT(ABGR, UNSIGNED_BYTE, RGBA8, 1) 1317 | case TKTX_A8B8G8R8_SNORM_PACK32: FT(ABGR, BYTE, RGBA8, 1) 1318 | case TKTX_A8B8G8R8_UINT_PACK32: FT(ABGR, UNSIGNED_BYTE, RGBA8UI, 1) 1319 | case TKTX_A8B8G8R8_SINT_PACK32: FT(ABGR, BYTE, RGBA8I, 1) 1320 | case TKTX_A8B8G8R8_SRGB_PACK32: FT(ABGR, UNSIGNED_BYTE, SRGB8, 1) 1321 | case TKTX_B10G11R11_UFLOAT_PACK32: FT(BGR, UNSIGNED_INT_10F_11F_11F_REV, R11F_G11F_B10F, 4) 1322 | 1323 | case TKTX_R16_UNORM: FT(RED, UNSIGNED_SHORT, R16, 2) 1324 | case TKTX_R16_SNORM: FT(RED, SHORT, R16_SNORM, 2) 1325 | case TKTX_R16_UINT: FT(RED_INTEGER, UNSIGNED_SHORT, R16UI, 2) 1326 | case TKTX_R16_SINT: FT(RED_INTEGER, SHORT, R16I, 2) 1327 | case TKTX_R16_SFLOAT:FT(RED, HALF_FLOAT, R16F, 2) 1328 | 1329 | case TKTX_R16G16_UNORM: FT(RG, UNSIGNED_SHORT, RG16, 2) 1330 | case TKTX_R16G16_SNORM: FT(RG, SHORT, RG16_SNORM, 2) 1331 | case TKTX_R16G16_UINT: FT(RG_INTEGER, UNSIGNED_SHORT, RG16UI, 2) 1332 | case TKTX_R16G16_SINT: FT(RG_INTEGER, SHORT, RG16I, 2) 1333 | case TKTX_R16G16_SFLOAT:FT(RG, HALF_FLOAT, RG16F, 2) 1334 | 1335 | case TKTX_R16G16B16_UNORM: FT(RGB, UNSIGNED_SHORT, RGB16, 2) 1336 | case TKTX_R16G16B16_SNORM: FT(RGB, SHORT, RGB16_SNORM, 2) 1337 | case TKTX_R16G16B16_UINT: FT(RGB_INTEGER, UNSIGNED_SHORT, RGB16UI, 2) 1338 | case TKTX_R16G16B16_SINT: FT(RGB_INTEGER, SHORT, RGB16I, 2) 1339 | case TKTX_R16G16B16_SFLOAT: FT(RGB, HALF_FLOAT, RGB16F, 2) 1340 | 1341 | case TKTX_R16G16B16A16_UNORM: FT(RGBA, UNSIGNED_SHORT, RGBA16, 2) 1342 | case TKTX_R16G16B16A16_SNORM: FT(RGBA, SHORT, RGBA16_SNORM, 2) 1343 | case TKTX_R16G16B16A16_UINT: FT(RGBA_INTEGER, UNSIGNED_SHORT, RGBA16UI, 2) 1344 | case TKTX_R16G16B16A16_SINT: FT(RGBA_INTEGER, SHORT, RGBA16I, 2) 1345 | case TKTX_R16G16B16A16_SFLOAT:FT(RGBA, HALF_FLOAT, RGBA16F, 2) 1346 | 1347 | case TKTX_R32_UINT: FT(RED_INTEGER, UNSIGNED_INT, R32UI, 4) 1348 | case TKTX_R32_SINT: FT(RED_INTEGER, INT, R32I, 4) 1349 | case TKTX_R32_SFLOAT: FT(RED, FLOAT, R32F, 4) 1350 | 1351 | case TKTX_R32G32_UINT: FT(RG_INTEGER, UNSIGNED_INT, RG32UI, 4) 1352 | case TKTX_R32G32_SINT: FT(RG_INTEGER, INT, RG32I, 4) 1353 | case TKTX_R32G32_SFLOAT: FT(RG, FLOAT, RG32F, 4) 1354 | 1355 | case TKTX_R32G32B32_UINT: FT(RGB_INTEGER, UNSIGNED_INT, RGB32UI, 4) 1356 | case TKTX_R32G32B32_SINT: FT(RGB_INTEGER, INT, RGB32I, 4) 1357 | case TKTX_R32G32B32_SFLOAT: FT(RGB_INTEGER, FLOAT, RGB32F, 4) 1358 | 1359 | case TKTX_R32G32B32A32_UINT: FT(RGBA_INTEGER, UNSIGNED_INT, RGBA32UI, 4) 1360 | case TKTX_R32G32B32A32_SINT: FT(RGBA_INTEGER, INT, RGBA32I, 4) 1361 | case TKTX_R32G32B32A32_SFLOAT:FT(RGBA, FLOAT, RGBA32F, 4) 1362 | 1363 | case TKTX_BC1_RGB_UNORM_BLOCK: FTC(RGB, RGB_S3TC_DXT1) 1364 | case TKTX_BC1_RGB_SRGB_BLOCK: FTC(RGB, SRGB_S3TC_DXT1) 1365 | case TKTX_BC1_RGBA_UNORM_BLOCK: FTC(RGBA, RGBA_S3TC_DXT1) 1366 | case TKTX_BC1_RGBA_SRGB_BLOCK: FTC(RGBA, SRGB_ALPHA_S3TC_DXT1) 1367 | case TKTX_BC2_UNORM_BLOCK: FTC(RGBA, RGBA_S3TC_DXT3) 1368 | case TKTX_BC2_SRGB_BLOCK: FTC(RGBA, SRGB_ALPHA_S3TC_DXT3) 1369 | case TKTX_BC3_UNORM_BLOCK: FTC(RGBA, RGBA_S3TC_DXT5) 1370 | case TKTX_BC3_SRGB_BLOCK: FTC(RGBA, SRGB_ALPHA_S3TC_DXT5) 1371 | case TKTX_BC4_UNORM_BLOCK: FTC(RED, RED_RGTC1) 1372 | case TKTX_BC4_SNORM_BLOCK: FTC(RED, SIGNED_RED_RGTC1) 1373 | case TKTX_BC5_UNORM_BLOCK: FTC(RG, RED_GREEN_RGTC2) 1374 | case TKTX_BC5_SNORM_BLOCK: FTC(RG, SIGNED_RED_GREEN_RGTC2) 1375 | case TKTX_BC6H_UFLOAT_BLOCK: FTC(RGB, RGB_BPTC_UNSIGNED_FLOAT) 1376 | case TKTX_BC6H_SFLOAT_BLOCK: FTC(RGB, RGB_BPTC_SIGNED_FLOAT) 1377 | case TKTX_BC7_UNORM_BLOCK: FTC(RGBA, RGBA_BPTC_UNORM) 1378 | case TKTX_BC7_SRGB_BLOCK: FTC(RGBA, SRGB_ALPHA_BPTC_UNORM) 1379 | 1380 | case TKTX_ETC2_R8G8B8_UNORM_BLOCK: FTC(RGB, RGB8_ETC2) 1381 | case TKTX_ETC2_R8G8B8A1_UNORM_BLOCK: FTC(RGBA, RGB8_PUNCHTHROUGH_ALPHA1_ETC2) 1382 | case TKTX_ETC2_R8G8B8A8_UNORM_BLOCK: FTC(RGBA, RGBA8_ETC2_EAC) 1383 | case TKTX_ETC2_R8G8B8_SRGB_BLOCK: FTC(SRGB, SRGB8_ETC2) 1384 | case TKTX_ETC2_R8G8B8A1_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) 1385 | case TKTX_ETC2_R8G8B8A8_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ETC2_EAC) 1386 | case TKTX_EAC_R11_UNORM_BLOCK: FTC(RED, R11_EAC) 1387 | case TKTX_EAC_R11G11_UNORM_BLOCK: FTC(RG, RG11_EAC) 1388 | case TKTX_EAC_R11_SNORM_BLOCK: FTC(RED, SIGNED_R11_EAC) 1389 | case TKTX_EAC_R11G11_SNORM_BLOCK: FTC(RG, SIGNED_RG11_EAC) 1390 | 1391 | case TKTX_PVR_2BPP_UNORM_BLOCK: FTC(RGB, RGB_PVRTC_2BPPV1) 1392 | case TKTX_PVR_2BPPA_UNORM_BLOCK: FTC(RGBA, RGBA_PVRTC_2BPPV1); 1393 | case TKTX_PVR_4BPP_UNORM_BLOCK: FTC(RGB, RGB_PVRTC_4BPPV1) 1394 | case TKTX_PVR_4BPPA_UNORM_BLOCK: FTC(RGB, RGB_PVRTC_4BPPV1) 1395 | case TKTX_PVR_2BPP_SRGB_BLOCK: FTC(SRGB, SRGB_PVRTC_2BPPV1) 1396 | case TKTX_PVR_2BPPA_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB_ALPHA_PVRTC_2BPPV1); 1397 | case TKTX_PVR_4BPP_SRGB_BLOCK: FTC(SRGB, SRGB_PVRTC_2BPPV1) 1398 | case TKTX_PVR_4BPPA_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB_ALPHA_PVRTC_2BPPV1); 1399 | 1400 | case TKTX_ASTC_4x4_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_4x4) 1401 | case TKTX_ASTC_4x4_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_4x4) 1402 | case TKTX_ASTC_5x4_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_5x4) 1403 | case TKTX_ASTC_5x4_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_5x4) 1404 | case TKTX_ASTC_5x5_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_5x5) 1405 | case TKTX_ASTC_5x5_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_5x5) 1406 | case TKTX_ASTC_6x5_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_6x5) 1407 | case TKTX_ASTC_6x5_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_6x5) 1408 | case TKTX_ASTC_6x6_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_6x6) 1409 | case TKTX_ASTC_6x6_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_6x6) 1410 | case TKTX_ASTC_8x5_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_8x5) 1411 | case TKTX_ASTC_8x5_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_8x5) 1412 | case TKTX_ASTC_8x6_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_8x6) 1413 | case TKTX_ASTC_8x6_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_8x6) 1414 | case TKTX_ASTC_8x8_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_8x8) 1415 | case TKTX_ASTC_8x8_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_8x8) 1416 | case TKTX_ASTC_10x5_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_10x5) 1417 | case TKTX_ASTC_10x5_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_10x5) 1418 | case TKTX_ASTC_10x6_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_10x6) 1419 | case TKTX_ASTC_10x6_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_10x6) 1420 | case TKTX_ASTC_10x8_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_10x8); 1421 | case TKTX_ASTC_10x8_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_10x8) 1422 | case TKTX_ASTC_10x10_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_10x10) 1423 | case TKTX_ASTC_10x10_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_10x10) 1424 | case TKTX_ASTC_12x10_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_12x10) 1425 | case TKTX_ASTC_12x10_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_12x10) 1426 | case TKTX_ASTC_12x12_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_12x12) 1427 | case TKTX_ASTC_12x12_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_12x12) 1428 | 1429 | default:break; 1430 | } 1431 | return false; 1432 | } 1433 | #undef FT 1434 | #undef FTC 1435 | 1436 | TinyKtx_Format TinyKtx_CrackFormatFromGL(uint32_t const glformat, 1437 | uint32_t const gltype, 1438 | uint32_t const glinternalformat, 1439 | uint32_t const typesize) { 1440 | switch (glinternalformat) { 1441 | case TINYKTX_GL_COMPRESSED_RGB_S3TC_DXT1: return TKTX_BC1_RGB_UNORM_BLOCK; 1442 | case TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT1: return TKTX_BC1_RGBA_UNORM_BLOCK; 1443 | case TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT3: return TKTX_BC2_UNORM_BLOCK; 1444 | case TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT5: return TKTX_BC3_UNORM_BLOCK; 1445 | case TINYKTX_GL_COMPRESSED_3DC_X_AMD: return TKTX_BC4_UNORM_BLOCK; 1446 | case TINYKTX_GL_COMPRESSED_3DC_XY_AMD: return TKTX_BC5_UNORM_BLOCK; 1447 | case TINYKTX_GL_COMPRESSED_SRGB_PVRTC_2BPPV1: return TKTX_PVR_2BPP_SRGB_BLOCK; 1448 | case TINYKTX_GL_COMPRESSED_SRGB_PVRTC_4BPPV1: return TKTX_PVR_2BPPA_SRGB_BLOCK; 1449 | case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1: return TKTX_PVR_2BPPA_SRGB_BLOCK; 1450 | case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1: return TKTX_PVR_4BPPA_SRGB_BLOCK; 1451 | case TINYKTX_GL_COMPRESSED_RGB_PVRTC_4BPPV1: return TKTX_PVR_4BPP_UNORM_BLOCK; 1452 | case TINYKTX_GL_COMPRESSED_RGB_PVRTC_2BPPV1: return TKTX_PVR_2BPP_UNORM_BLOCK; 1453 | case TINYKTX_GL_COMPRESSED_RGBA_PVRTC_4BPPV1: return TKTX_PVR_4BPPA_UNORM_BLOCK; 1454 | case TINYKTX_GL_COMPRESSED_RGBA_PVRTC_2BPPV1: return TKTX_PVR_2BPPA_UNORM_BLOCK; 1455 | case TINYKTX_GL_COMPRESSED_SRGB_S3TC_DXT1: return TKTX_BC1_RGB_SRGB_BLOCK; 1456 | case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1: return TKTX_BC1_RGBA_SRGB_BLOCK; 1457 | case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3: return TKTX_BC2_SRGB_BLOCK; 1458 | case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5: return TKTX_BC3_SRGB_BLOCK; 1459 | case TINYKTX_GL_COMPRESSED_LUMINANCE_LATC1: return TKTX_BC4_UNORM_BLOCK; 1460 | case TINYKTX_GL_COMPRESSED_SIGNED_LUMINANCE_LATC1: return TKTX_BC4_SNORM_BLOCK; 1461 | case TINYKTX_GL_COMPRESSED_LUMINANCE_ALPHA_LATC2: return TKTX_BC5_UNORM_BLOCK; 1462 | case TINYKTX_GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2: return TKTX_BC5_SNORM_BLOCK; 1463 | case TINYKTX_GL_COMPRESSED_RED_RGTC1: return TKTX_BC4_UNORM_BLOCK; 1464 | case TINYKTX_GL_COMPRESSED_SIGNED_RED_RGTC1: return TKTX_BC4_SNORM_BLOCK; 1465 | case TINYKTX_GL_COMPRESSED_RED_GREEN_RGTC2: return TKTX_BC5_UNORM_BLOCK; 1466 | case TINYKTX_GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2: return TKTX_BC5_SNORM_BLOCK; 1467 | case TINYKTX_GL_COMPRESSED_ETC1_RGB8_OES: return TKTX_ETC2_R8G8B8_UNORM_BLOCK; 1468 | case TINYKTX_GL_COMPRESSED_RGBA_BPTC_UNORM: return TKTX_BC7_UNORM_BLOCK; 1469 | case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: return TKTX_BC7_SRGB_BLOCK; 1470 | case TINYKTX_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: return TKTX_BC6H_SFLOAT_BLOCK; 1471 | case TINYKTX_GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: return TKTX_BC6H_UFLOAT_BLOCK; 1472 | case TINYKTX_GL_COMPRESSED_R11_EAC: return TKTX_EAC_R11_UNORM_BLOCK; 1473 | case TINYKTX_GL_COMPRESSED_SIGNED_R11_EAC: return TKTX_EAC_R11_SNORM_BLOCK; 1474 | case TINYKTX_GL_COMPRESSED_RG11_EAC: return TKTX_EAC_R11G11_UNORM_BLOCK; 1475 | case TINYKTX_GL_COMPRESSED_SIGNED_RG11_EAC: return TKTX_EAC_R11G11_UNORM_BLOCK; 1476 | case TINYKTX_GL_COMPRESSED_RGB8_ETC2: return TKTX_ETC2_R8G8B8_UNORM_BLOCK; 1477 | case TINYKTX_GL_COMPRESSED_SRGB8_ETC2: return TKTX_ETC2_R8G8B8_SRGB_BLOCK; 1478 | case TINYKTX_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: return TKTX_ETC2_R8G8B8A1_UNORM_BLOCK; 1479 | case TINYKTX_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: return TKTX_ETC2_R8G8B8A1_SRGB_BLOCK; 1480 | case TINYKTX_GL_COMPRESSED_RGBA8_ETC2_EAC: return TKTX_ETC2_R8G8B8A8_UNORM_BLOCK; 1481 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: return TKTX_ETC2_R8G8B8A8_SRGB_BLOCK; 1482 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_4x4: return TKTX_ASTC_4x4_UNORM_BLOCK; 1483 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_5x4: return TKTX_ASTC_5x4_UNORM_BLOCK; 1484 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_5x5: return TKTX_ASTC_5x5_UNORM_BLOCK; 1485 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_6x5: return TKTX_ASTC_6x5_UNORM_BLOCK; 1486 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_6x6: return TKTX_ASTC_6x6_UNORM_BLOCK; 1487 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x5: return TKTX_ASTC_8x5_UNORM_BLOCK; 1488 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x6: return TKTX_ASTC_8x6_UNORM_BLOCK; 1489 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x8: return TKTX_ASTC_8x8_UNORM_BLOCK; 1490 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x5: return TKTX_ASTC_10x5_UNORM_BLOCK; 1491 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x6: return TKTX_ASTC_10x6_UNORM_BLOCK; 1492 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x8: return TKTX_ASTC_10x8_UNORM_BLOCK; 1493 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x10: return TKTX_ASTC_10x10_UNORM_BLOCK; 1494 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_12x10: return TKTX_ASTC_12x10_UNORM_BLOCK; 1495 | case TINYKTX_GL_COMPRESSED_RGBA_ASTC_12x12: return TKTX_ASTC_12x12_UNORM_BLOCK; 1496 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4: return TKTX_ASTC_4x4_SRGB_BLOCK; 1497 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4: return TKTX_ASTC_5x4_SRGB_BLOCK; 1498 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5: return TKTX_ASTC_5x5_SRGB_BLOCK; 1499 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5: return TKTX_ASTC_6x5_SRGB_BLOCK; 1500 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6: return TKTX_ASTC_6x6_SRGB_BLOCK; 1501 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5: return TKTX_ASTC_8x5_SRGB_BLOCK; 1502 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6: return TKTX_ASTC_8x6_SRGB_BLOCK; 1503 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8: return TKTX_ASTC_8x8_SRGB_BLOCK; 1504 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5: return TKTX_ASTC_10x5_SRGB_BLOCK; 1505 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6: return TKTX_ASTC_10x6_SRGB_BLOCK; 1506 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8: return TKTX_ASTC_10x8_SRGB_BLOCK; 1507 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10: return TKTX_ASTC_10x10_SRGB_BLOCK; 1508 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10: return TKTX_ASTC_12x10_SRGB_BLOCK; 1509 | case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12: return TKTX_ASTC_12x12_SRGB_BLOCK; 1510 | 1511 | // non compressed 1512 | case TINYKTX_GL_INTFORMAT_RGB4: 1513 | if(glformat == TINYKTX_GL_FORMAT_RG) { 1514 | return TKTX_R4G4_UNORM_PACK8; 1515 | } 1516 | break; 1517 | 1518 | case TINYKTX_GL_INTFORMAT_RGBA4: 1519 | if(glformat == TINYKTX_GL_FORMAT_RGBA) { 1520 | return TKTX_R4G4B4A4_UNORM_PACK16; 1521 | } else if(glformat == TINYKTX_GL_FORMAT_BGRA) { 1522 | return TKTX_B4G4R4A4_UNORM_PACK16; 1523 | } 1524 | break; 1525 | case TINYKTX_GL_INTFORMAT_RGB565: 1526 | if(gltype == TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_6_5 || glformat == TINYKTX_GL_FORMAT_BGR) { 1527 | return TKTX_B5G6R5_UNORM_PACK16; 1528 | } else { 1529 | return TKTX_R5G6B5_UNORM_PACK16; 1530 | } 1531 | break; 1532 | 1533 | case TINYKTX_GL_INTFORMAT_RGB5_A1: 1534 | if (gltype == TINYKTX_GL_TYPE_UNSIGNED_SHORT_1_5_5_5_REV) { 1535 | return TKTX_A1R5G5B5_UNORM_PACK16; 1536 | } else if (gltype == TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_5_5_1) { 1537 | if(glformat == TINYKTX_GL_FORMAT_BGRA) { 1538 | return TKTX_B5G5R5A1_UNORM_PACK16; 1539 | } else { 1540 | return TKTX_R5G5B5A1_UNORM_PACK16; 1541 | } 1542 | } 1543 | break; 1544 | case TINYKTX_GL_INTFORMAT_R8_SNORM: 1545 | case TINYKTX_GL_INTFORMAT_R8: 1546 | if(gltype == TINYKTX_GL_TYPE_BYTE || glinternalformat == TINYKTX_GL_INTFORMAT_R8_SNORM) { 1547 | return TKTX_R8_SNORM; 1548 | } else { 1549 | return TKTX_R8_UNORM; 1550 | } 1551 | break; 1552 | case TINYKTX_GL_INTFORMAT_RG8_SNORM: 1553 | case TINYKTX_GL_INTFORMAT_RG8: 1554 | if(gltype == TINYKTX_GL_TYPE_BYTE || 1555 | glinternalformat == TINYKTX_GL_INTFORMAT_RG8_SNORM) { 1556 | return TKTX_R8G8_SNORM; 1557 | } else { 1558 | return TKTX_R8G8_UNORM; 1559 | } 1560 | break; 1561 | case TINYKTX_GL_INTFORMAT_RGB8_SNORM: 1562 | case TINYKTX_GL_INTFORMAT_RGB8: 1563 | if(glformat == TINYKTX_GL_FORMAT_BGR) { 1564 | if(gltype == TINYKTX_GL_TYPE_BYTE || 1565 | glinternalformat == TINYKTX_GL_INTFORMAT_RGB8_SNORM) { 1566 | return TKTX_B8G8R8_SNORM; 1567 | } else { 1568 | return TKTX_B8G8R8_UNORM; 1569 | } 1570 | } else { 1571 | if(gltype == TINYKTX_GL_TYPE_BYTE || 1572 | glinternalformat == TINYKTX_GL_INTFORMAT_RGB8_SNORM) { 1573 | return TKTX_R8G8B8_SNORM; 1574 | } else { 1575 | return TKTX_R8G8B8_UNORM; 1576 | } 1577 | } 1578 | break; 1579 | case TINYKTX_GL_INTFORMAT_RGBA8_SNORM: 1580 | case TINYKTX_GL_INTFORMAT_RGBA8: 1581 | if(glformat == TINYKTX_GL_FORMAT_RGBA) { 1582 | if(gltype == TINYKTX_GL_TYPE_BYTE || 1583 | glinternalformat == TINYKTX_GL_INTFORMAT_RGBA8_SNORM) { 1584 | return TKTX_R8G8B8A8_SNORM; 1585 | } else if(gltype == TINYKTX_GL_TYPE_UNSIGNED_BYTE) { 1586 | return TKTX_R8G8B8A8_UNORM; 1587 | } 1588 | } else if(glformat == TINYKTX_GL_FORMAT_BGRA) { 1589 | if(gltype == TINYKTX_GL_TYPE_BYTE || 1590 | glinternalformat == TINYKTX_GL_INTFORMAT_RGBA8_SNORM) { 1591 | return TKTX_B8G8R8A8_SNORM; 1592 | } else if(gltype == TINYKTX_GL_TYPE_UNSIGNED_BYTE) { 1593 | return TKTX_B8G8R8A8_UNORM; 1594 | } 1595 | } else if(glformat == TINYKTX_GL_FORMAT_ABGR) { 1596 | if(gltype == TINYKTX_GL_TYPE_BYTE || 1597 | glinternalformat == TINYKTX_GL_INTFORMAT_RGBA8_SNORM) { 1598 | return TKTX_A8B8G8R8_SNORM_PACK32; 1599 | } else if(gltype == TINYKTX_GL_TYPE_UNSIGNED_BYTE) { 1600 | return TKTX_A8B8G8R8_UNORM_PACK32; 1601 | } 1602 | } 1603 | break; 1604 | 1605 | case TINYKTX_GL_INTFORMAT_R16: return TKTX_R16_UNORM; 1606 | case TINYKTX_GL_INTFORMAT_RG16: return TKTX_R16G16_UNORM; 1607 | case TINYKTX_GL_INTFORMAT_RGB16: return TKTX_R16G16B16_UNORM; 1608 | case TINYKTX_GL_INTFORMAT_RGBA16: return TKTX_R16G16B16A16_UNORM; 1609 | 1610 | case TINYKTX_GL_INTFORMAT_R16_SNORM:return TKTX_R16_SNORM; 1611 | case TINYKTX_GL_INTFORMAT_RG16_SNORM: return TKTX_R16G16_SNORM; 1612 | case TINYKTX_GL_INTFORMAT_RGB16_SNORM: return TKTX_R16G16B16_SNORM; 1613 | case TINYKTX_GL_INTFORMAT_RGBA16_SNORM: return TKTX_R16G16B16A16_SNORM; 1614 | 1615 | case TINYKTX_GL_INTFORMAT_R8I: return TKTX_R8_SINT; 1616 | case TINYKTX_GL_INTFORMAT_RG8I: return TKTX_R8G8_SINT; 1617 | case TINYKTX_GL_INTFORMAT_RGB8I: 1618 | if(glformat == TINYKTX_GL_FORMAT_RGB || glformat == TINYKTX_GL_FORMAT_RGB_INTEGER) { 1619 | return TKTX_R8G8B8_SINT; 1620 | } else if(glformat == TINYKTX_GL_FORMAT_BGR || glformat == TINYKTX_GL_FORMAT_BGR_INTEGER) { 1621 | return TKTX_B8G8R8_SINT; 1622 | } 1623 | break; 1624 | 1625 | case TINYKTX_GL_INTFORMAT_RGBA8I: 1626 | if(glformat == TINYKTX_GL_FORMAT_RGBA || glformat == TINYKTX_GL_FORMAT_RGBA_INTEGER) { 1627 | return TKTX_R8G8B8A8_SINT; 1628 | } else if(glformat == TINYKTX_GL_FORMAT_BGRA || glformat == TINYKTX_GL_FORMAT_BGRA_INTEGER) { 1629 | return TKTX_B8G8R8A8_SINT; 1630 | } else if(glformat == TINYKTX_GL_FORMAT_ABGR) { 1631 | return TKTX_A8B8G8R8_SINT_PACK32; 1632 | } 1633 | break; 1634 | 1635 | case TINYKTX_GL_INTFORMAT_R16I: return TKTX_R16_SINT; 1636 | case TINYKTX_GL_INTFORMAT_RG16I: return TKTX_R16G16_SINT; 1637 | case TINYKTX_GL_INTFORMAT_RGB16I:return TKTX_R16G16B16_SINT; 1638 | case TINYKTX_GL_INTFORMAT_RGBA16I:return TKTX_R16G16B16A16_SINT; 1639 | 1640 | case TINYKTX_GL_INTFORMAT_R32I: return TKTX_R32_SINT; 1641 | case TINYKTX_GL_INTFORMAT_RG32I: return TKTX_R32G32_SINT; 1642 | case TINYKTX_GL_INTFORMAT_RGB32I: 1643 | if(glformat == TINYKTX_GL_FORMAT_RGB || glformat == TINYKTX_GL_FORMAT_RGB_INTEGER) { 1644 | return TKTX_R32G32B32_SINT; 1645 | } 1646 | break; 1647 | case TINYKTX_GL_INTFORMAT_RGBA32I:return TKTX_R32G32B32A32_SINT; 1648 | 1649 | case TINYKTX_GL_INTFORMAT_R8UI: return TKTX_R8_UINT; 1650 | case TINYKTX_GL_INTFORMAT_RG8UI: return TKTX_R8G8_UINT; 1651 | case TINYKTX_GL_INTFORMAT_RGB8UI: 1652 | if(glformat == TINYKTX_GL_FORMAT_RGB || glformat == TINYKTX_GL_FORMAT_RGB_INTEGER) { 1653 | return TKTX_R8G8B8_UINT; 1654 | } else if(glformat == TINYKTX_GL_FORMAT_BGR || glformat == TINYKTX_GL_FORMAT_BGR_INTEGER) { 1655 | return TKTX_B8G8R8_UINT; 1656 | } 1657 | break; 1658 | case TINYKTX_GL_INTFORMAT_RGBA8UI: 1659 | if(glformat == TINYKTX_GL_FORMAT_RGBA || glformat == TINYKTX_GL_FORMAT_RGBA_INTEGER) { 1660 | return TKTX_R8G8B8A8_UINT; 1661 | } else if(glformat == TINYKTX_GL_FORMAT_BGRA || glformat == TINYKTX_GL_FORMAT_BGRA_INTEGER) { 1662 | return TKTX_B8G8R8A8_UINT; 1663 | } else if(glformat == TINYKTX_GL_FORMAT_ABGR) { 1664 | return TKTX_A8B8G8R8_UINT_PACK32; 1665 | } 1666 | break; 1667 | 1668 | case TINYKTX_GL_INTFORMAT_R16UI: return TKTX_R16_UINT; 1669 | case TINYKTX_GL_INTFORMAT_RG16UI: return TKTX_R16G16_UINT; 1670 | case TINYKTX_GL_INTFORMAT_RGB16UI:return TKTX_R16G16B16_UINT; 1671 | case TINYKTX_GL_INTFORMAT_RGBA16UI: return TKTX_R16G16B16A16_UINT; 1672 | 1673 | case TINYKTX_GL_INTFORMAT_R32UI: return TKTX_R32_UINT; 1674 | case TINYKTX_GL_INTFORMAT_RG32UI: return TKTX_R32G32_UINT; 1675 | case TINYKTX_GL_INTFORMAT_RGB32UI: return TKTX_R32G32B32_UINT; 1676 | case TINYKTX_GL_INTFORMAT_RGBA32UI: return TKTX_R32G32B32A32_UINT; 1677 | 1678 | case TINYKTX_GL_INTFORMAT_R16F: return TKTX_R16_SFLOAT; 1679 | case TINYKTX_GL_INTFORMAT_RG16F: return TKTX_R16G16_SFLOAT; 1680 | case TINYKTX_GL_INTFORMAT_RGB16F: return TKTX_R16G16B16_SFLOAT; 1681 | case TINYKTX_GL_INTFORMAT_RGBA16F: return TKTX_R16G16B16A16_SFLOAT; 1682 | 1683 | case TINYKTX_GL_INTFORMAT_R32F: return TKTX_R32_SFLOAT; 1684 | case TINYKTX_GL_INTFORMAT_RG32F: return TKTX_R32G32_SFLOAT; 1685 | case TINYKTX_GL_INTFORMAT_RGB32F: return TKTX_R32G32B32_SFLOAT; 1686 | case TINYKTX_GL_INTFORMAT_RGBA32F: return TKTX_R32G32B32A32_SFLOAT; 1687 | 1688 | case TINYKTX_GL_INTFORMAT_R11F_G11F_B10F: return TKTX_B10G11R11_UFLOAT_PACK32; //?? 1689 | case TINYKTX_GL_INTFORMAT_UNSIGNED_INT_10F_11F_11F_REV: return TKTX_B10G11R11_UFLOAT_PACK32; //? 1690 | case TINYKTX_GL_INTFORMAT_RGB9_E5: return TKTX_E5B9G9R9_UFLOAT_PACK32; 1691 | case TINYKTX_GL_INTFORMAT_SLUMINANCE8_ALPHA8: return TKTX_R8G8_SRGB; 1692 | case TINYKTX_GL_INTFORMAT_SLUMINANCE8: return TKTX_R8_SRGB; 1693 | 1694 | case TINYKTX_GL_INTFORMAT_ALPHA8: return TKTX_R8_UNORM; 1695 | case TINYKTX_GL_INTFORMAT_ALPHA16: return TKTX_R16_UNORM; 1696 | case TINYKTX_GL_INTFORMAT_LUMINANCE8: return TKTX_R8_UNORM; 1697 | case TINYKTX_GL_INTFORMAT_LUMINANCE16: return TKTX_R16_UNORM; 1698 | case TINYKTX_GL_INTFORMAT_LUMINANCE8_ALPHA8: return TKTX_R8G8_UNORM; 1699 | case TINYKTX_GL_INTFORMAT_LUMINANCE16_ALPHA16: return TKTX_R16G16_UNORM; 1700 | case TINYKTX_GL_INTFORMAT_INTENSITY8: return TKTX_R8_UNORM; 1701 | case TINYKTX_GL_INTFORMAT_INTENSITY16: return TKTX_R16_UNORM; 1702 | 1703 | case TINYKTX_GL_INTFORMAT_ALPHA8_SNORM: return TKTX_R8_SNORM; 1704 | case TINYKTX_GL_INTFORMAT_LUMINANCE8_SNORM: return TKTX_R8_SNORM; 1705 | case TINYKTX_GL_INTFORMAT_LUMINANCE8_ALPHA8_SNORM: return TKTX_R8G8_SNORM; 1706 | case TINYKTX_GL_INTFORMAT_INTENSITY8_SNORM: return TKTX_R8_SNORM; 1707 | case TINYKTX_GL_INTFORMAT_ALPHA16_SNORM: return TKTX_R16_SNORM; 1708 | case TINYKTX_GL_INTFORMAT_LUMINANCE16_SNORM: return TKTX_R16_SNORM; 1709 | case TINYKTX_GL_INTFORMAT_LUMINANCE16_ALPHA16_SNORM: return TKTX_R16G16_SNORM; 1710 | case TINYKTX_GL_INTFORMAT_INTENSITY16_SNORM: return TKTX_R16_SNORM; 1711 | 1712 | case TINYKTX_GL_INTFORMAT_SRGB8: 1713 | case TINYKTX_GL_INTFORMAT_SRGB8_ALPHA8: 1714 | if (glformat == TINYKTX_GL_FORMAT_SLUMINANCE) { 1715 | return TKTX_R8_SRGB; 1716 | } else if (glformat == TINYKTX_GL_FORMAT_SLUMINANCE_ALPHA) { 1717 | return TKTX_R8G8_SRGB; 1718 | } else if (glformat == TINYKTX_GL_FORMAT_SRGB) { 1719 | return TKTX_R8G8B8_SRGB; 1720 | } else if (glformat == TINYKTX_GL_FORMAT_SRGB_ALPHA) { 1721 | return TKTX_R8G8B8A8_SRGB; 1722 | } else if (glformat == TINYKTX_GL_FORMAT_BGR) { 1723 | return TKTX_B8G8R8_SRGB; 1724 | } else if (glformat == TINYKTX_GL_FORMAT_BGRA) { 1725 | return TKTX_B8G8R8A8_SRGB; 1726 | } else if (glformat == TINYKTX_GL_FORMAT_ABGR) { 1727 | return TKTX_A8B8G8R8_SRGB_PACK32; 1728 | } 1729 | break; 1730 | case TINYKTX_GL_INTFORMAT_RGB10_A2: 1731 | if(glformat == TINYKTX_GL_FORMAT_BGRA) { 1732 | return TKTX_A2R10G10B10_UNORM_PACK32; 1733 | } else if(glformat == TINYKTX_GL_FORMAT_RGBA) { 1734 | return TKTX_A2B10G10R10_UNORM_PACK32; 1735 | } else if(glformat == TINYKTX_GL_FORMAT_BGRA_INTEGER) { 1736 | return TKTX_A2R10G10B10_UINT_PACK32; 1737 | } else if(glformat == TINYKTX_GL_FORMAT_RGBA_INTEGER) { 1738 | return TKTX_A2B10G10R10_UINT_PACK32; 1739 | } 1740 | break; 1741 | 1742 | // apparently we get FORMAT formats in the internal format slot sometimes 1743 | case TINYKTX_GL_FORMAT_RED: 1744 | switch(gltype) { 1745 | case TINYKTX_GL_TYPE_BYTE: return TKTX_R8_SNORM; 1746 | case TINYKTX_GL_TYPE_UNSIGNED_BYTE: return TKTX_R8_UNORM; 1747 | case TINYKTX_GL_TYPE_SHORT: return TKTX_R16_SNORM; 1748 | case TINYKTX_GL_TYPE_UNSIGNED_SHORT:return TKTX_R16_UNORM; 1749 | case TINYKTX_GL_TYPE_INT: return TKTX_R32_SINT; 1750 | case TINYKTX_GL_TYPE_UNSIGNED_INT: return TKTX_R32_UINT; 1751 | case TINYKTX_GL_TYPE_FLOAT: return TKTX_R32_SFLOAT; 1752 | // case TINYKTX_GL_TYPE_DOUBLE: return TKTX_R64G64B64A64_SFLOAT; 1753 | case TINYKTX_GL_TYPE_HALF_FLOAT: return TKTX_R16_SFLOAT; 1754 | default: return TKTX_UNDEFINED; 1755 | } 1756 | case TINYKTX_GL_FORMAT_RG: 1757 | switch(gltype) { 1758 | case TINYKTX_GL_TYPE_BYTE: return TKTX_R8G8_SNORM; 1759 | case TINYKTX_GL_TYPE_UNSIGNED_BYTE: return TKTX_R8G8_UNORM; 1760 | case TINYKTX_GL_TYPE_SHORT: return TKTX_R16G16_SNORM; 1761 | case TINYKTX_GL_TYPE_UNSIGNED_SHORT:return TKTX_R16G16_UNORM; 1762 | case TINYKTX_GL_TYPE_INT: return TKTX_R32G32_SINT; 1763 | case TINYKTX_GL_TYPE_UNSIGNED_INT: return TKTX_R32G32_UINT; 1764 | case TINYKTX_GL_TYPE_FLOAT: return TKTX_R32G32_SFLOAT; 1765 | // case TINYKTX_GL_TYPE_DOUBLE: return TKTX_R64G64_SFLOAT; 1766 | case TINYKTX_GL_TYPE_HALF_FLOAT: return TKTX_R16G16_SFLOAT; 1767 | default: return TKTX_UNDEFINED; 1768 | } 1769 | 1770 | case TINYKTX_GL_FORMAT_RGB: 1771 | switch(gltype) { 1772 | case TINYKTX_GL_TYPE_BYTE: return TKTX_R8G8B8_SNORM; 1773 | case TINYKTX_GL_TYPE_UNSIGNED_BYTE: return TKTX_R8G8B8_UNORM; 1774 | case TINYKTX_GL_TYPE_SHORT: return TKTX_R16G16B16_SNORM; 1775 | case TINYKTX_GL_TYPE_UNSIGNED_SHORT:return TKTX_R16G16B16_UNORM; 1776 | case TINYKTX_GL_TYPE_INT: return TKTX_R32G32B32_SINT; 1777 | case TINYKTX_GL_TYPE_UNSIGNED_INT: return TKTX_R32G32B32_UINT; 1778 | case TINYKTX_GL_TYPE_FLOAT: return TKTX_R32G32B32_SFLOAT; 1779 | // case TINYKTX_GL_TYPE_DOUBLE: return TKTX_R64G64B64_SFLOAT; 1780 | case TINYKTX_GL_TYPE_HALF_FLOAT: return TKTX_R16G16B16_SFLOAT; 1781 | default: return TKTX_UNDEFINED; 1782 | } 1783 | case TINYKTX_GL_FORMAT_RGBA: 1784 | switch(gltype) { 1785 | case TINYKTX_GL_TYPE_BYTE: return TKTX_R8G8B8A8_SNORM; 1786 | case TINYKTX_GL_TYPE_UNSIGNED_BYTE: return TKTX_R8G8B8A8_UNORM; 1787 | case TINYKTX_GL_TYPE_SHORT: return TKTX_R16G16B16A16_SNORM; 1788 | case TINYKTX_GL_TYPE_UNSIGNED_SHORT:return TKTX_R16G16B16A16_UNORM; 1789 | case TINYKTX_GL_TYPE_INT: return TKTX_R32G32B32A32_SINT; 1790 | case TINYKTX_GL_TYPE_UNSIGNED_INT: return TKTX_R32G32B32A32_UINT; 1791 | case TINYKTX_GL_TYPE_FLOAT: return TKTX_R32G32B32A32_SFLOAT; 1792 | // case TINYKTX_GL_TYPE_DOUBLE: return TKTX_R64G64B64A64_SFLOAT; 1793 | case TINYKTX_GL_TYPE_HALF_FLOAT: return TKTX_R16G16B16A16_SFLOAT; 1794 | default: return TKTX_UNDEFINED; 1795 | } 1796 | 1797 | // can't handle yet 1798 | case TINYKTX_GL_INTFORMAT_ALPHA4: 1799 | case TINYKTX_GL_INTFORMAT_ALPHA12: 1800 | case TINYKTX_GL_INTFORMAT_LUMINANCE4: 1801 | case TINYKTX_GL_INTFORMAT_LUMINANCE12: 1802 | case TINYKTX_GL_INTFORMAT_LUMINANCE4_ALPHA4: 1803 | case TINYKTX_GL_INTFORMAT_LUMINANCE6_ALPHA2: 1804 | case TINYKTX_GL_INTFORMAT_LUMINANCE12_ALPHA4: 1805 | case TINYKTX_GL_INTFORMAT_LUMINANCE12_ALPHA12: 1806 | case TINYKTX_GL_INTFORMAT_INTENSITY4: 1807 | case TINYKTX_GL_INTFORMAT_INTENSITY12: 1808 | case TINYKTX_GL_INTFORMAT_RGB2: 1809 | case TINYKTX_GL_INTFORMAT_RGB5: 1810 | case TINYKTX_GL_INTFORMAT_RGB10: 1811 | case TINYKTX_GL_INTFORMAT_RGB12: 1812 | case TINYKTX_GL_INTFORMAT_RGBA2: 1813 | case TINYKTX_GL_INTFORMAT_RGBA12: 1814 | case TINYKTX_GL_INTFORMAT_FLOAT_32_UNSIGNED_INT_24_8_REV: 1815 | case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2: 1816 | case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2: 1817 | case TINYKTX_GL_COMPRESSED_ATC_RGB: 1818 | case TINYKTX_GL_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA: 1819 | case TINYKTX_GL_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA: 1820 | default: break; 1821 | } 1822 | return TKTX_UNDEFINED; 1823 | } 1824 | 1825 | uint32_t TinyKtx_ElementCountFromGLFormat(uint32_t fmt){ 1826 | switch(fmt) { 1827 | case TINYKTX_GL_FORMAT_RED: 1828 | case TINYKTX_GL_FORMAT_GREEN: 1829 | case TINYKTX_GL_FORMAT_BLUE: 1830 | case TINYKTX_GL_FORMAT_ALPHA: 1831 | case TINYKTX_GL_FORMAT_LUMINANCE: 1832 | case TINYKTX_GL_FORMAT_INTENSITY: 1833 | case TINYKTX_GL_FORMAT_RED_INTEGER: 1834 | case TINYKTX_GL_FORMAT_GREEN_INTEGER: 1835 | case TINYKTX_GL_FORMAT_BLUE_INTEGER: 1836 | case TINYKTX_GL_FORMAT_ALPHA_INTEGER: 1837 | case TINYKTX_GL_FORMAT_SLUMINANCE: 1838 | case TINYKTX_GL_FORMAT_RED_SNORM: 1839 | return 1; 1840 | 1841 | case TINYKTX_GL_FORMAT_RG_INTEGER: 1842 | case TINYKTX_GL_FORMAT_RG: 1843 | case TINYKTX_GL_FORMAT_LUMINANCE_ALPHA: 1844 | case TINYKTX_GL_FORMAT_SLUMINANCE_ALPHA: 1845 | case TINYKTX_GL_FORMAT_RG_SNORM: 1846 | return 2; 1847 | 1848 | case TINYKTX_GL_FORMAT_BGR: 1849 | case TINYKTX_GL_FORMAT_RGB: 1850 | case TINYKTX_GL_FORMAT_SRGB: 1851 | case TINYKTX_GL_FORMAT_RGB_INTEGER: 1852 | case TINYKTX_GL_FORMAT_BGR_INTEGER: 1853 | case TINYKTX_GL_FORMAT_RGB_SNORM: 1854 | return 3; 1855 | 1856 | case TINYKTX_GL_FORMAT_BGRA: 1857 | case TINYKTX_GL_FORMAT_RGBA: 1858 | case TINYKTX_GL_FORMAT_ABGR: 1859 | case TINYKTX_GL_FORMAT_SRGB_ALPHA: 1860 | case TINYKTX_GL_FORMAT_RGBA_INTEGER: 1861 | case TINYKTX_GL_FORMAT_BGRA_INTEGER: 1862 | case TINYKTX_GL_FORMAT_RGBA_SNORM: 1863 | return 4; 1864 | } 1865 | 1866 | return 0; 1867 | } 1868 | bool TinyKtx_ByteDividableFromGLType(uint32_t type){ 1869 | switch(type) { 1870 | case TINYKTX_GL_TYPE_COMPRESSED: 1871 | case TINYKTX_GL_TYPE_UNSIGNED_BYTE_3_3_2: 1872 | case TINYKTX_GL_TYPE_UNSIGNED_SHORT_4_4_4_4: 1873 | case TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_5_5_1: 1874 | case TINYKTX_GL_TYPE_UNSIGNED_INT_8_8_8_8: 1875 | case TINYKTX_GL_TYPE_UNSIGNED_INT_10_10_10_2: 1876 | case TINYKTX_GL_TYPE_UNSIGNED_BYTE_2_3_3_REV: 1877 | case TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_6_5: 1878 | case TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_6_5_REV: 1879 | case TINYKTX_GL_TYPE_UNSIGNED_SHORT_4_4_4_4_REV: 1880 | case TINYKTX_GL_TYPE_UNSIGNED_SHORT_1_5_5_5_REV: 1881 | case TINYKTX_GL_TYPE_UNSIGNED_INT_8_8_8_8_REV: 1882 | case TINYKTX_GL_TYPE_UNSIGNED_INT_2_10_10_10_REV: 1883 | case TINYKTX_GL_TYPE_UNSIGNED_INT_24_8: 1884 | case TINYKTX_GL_TYPE_UNSIGNED_INT_5_9_9_9_REV: 1885 | case TINYKTX_GL_TYPE_UNSIGNED_INT_10F_11F_11F_REV: 1886 | case TINYKTX_GL_TYPE_FLOAT_32_UNSIGNED_INT_24_8_REV: 1887 | return false; 1888 | case TINYKTX_GL_TYPE_BYTE: 1889 | case TINYKTX_GL_TYPE_UNSIGNED_BYTE: 1890 | case TINYKTX_GL_TYPE_SHORT: 1891 | case TINYKTX_GL_TYPE_UNSIGNED_SHORT: 1892 | case TINYKTX_GL_TYPE_INT: 1893 | case TINYKTX_GL_TYPE_UNSIGNED_INT: 1894 | case TINYKTX_GL_TYPE_FLOAT: 1895 | case TINYKTX_GL_TYPE_DOUBLE: 1896 | case TINYKTX_GL_TYPE_HALF_FLOAT: 1897 | return true; 1898 | } 1899 | return false; 1900 | } 1901 | TinyKtx_Format TinyKtx_GetFormat(TinyKtx_ContextHandle handle) { 1902 | uint32_t glformat; 1903 | uint32_t gltype; 1904 | uint32_t glinternalformat; 1905 | uint32_t typesize; 1906 | uint32_t glbaseinternalformat; 1907 | 1908 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1909 | if (ctx == NULL) 1910 | return TKTX_UNDEFINED; 1911 | 1912 | if (ctx->headerValid == false) { 1913 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1914 | return TKTX_UNDEFINED; 1915 | } 1916 | 1917 | if(TinyKtx_GetFormatGL(handle, &glformat, &gltype, &glinternalformat, &typesize, &glbaseinternalformat) == false) 1918 | return TKTX_UNDEFINED; 1919 | 1920 | return TinyKtx_CrackFormatFromGL(glformat, gltype, glinternalformat, typesize); 1921 | } 1922 | static uint32_t TinyKtx_MipMapReduce(uint32_t value, uint32_t mipmaplevel) { 1923 | 1924 | // handle 0 being passed in 1925 | if(value <= 1) return 1; 1926 | 1927 | // there are better ways of doing this (log2 etc.) but this doesn't require any 1928 | // dependecies and isn't used enough to matter imho 1929 | for (uint32_t i = 0u; i < mipmaplevel;++i) { 1930 | if(value <= 1) return 1; 1931 | value = value / 2; 1932 | } 1933 | return value; 1934 | } 1935 | 1936 | // KTX specifys GL_UNPACK_ALIGNMENT = 4 which means some files have unexpected padding 1937 | // that probably means you can't just memcpy the data out if you aren't using a GL 1938 | // texture with GL_UNPACK_ALIGNMENT of 4 1939 | // this will be true if this mipmap level is 'unpacked' so has padding on each row 1940 | // you will need to handle. 1941 | bool TinyKtx_IsMipMapLevelUnpacked(TinyKtx_ContextHandle handle, uint32_t mipmaplevel) { 1942 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1943 | if (ctx == NULL) 1944 | return false; 1945 | if (ctx->headerValid == false) { 1946 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1947 | return false; 1948 | } 1949 | 1950 | if (ctx->header.glTypeSize < 4 && 1951 | TinyKtx_ByteDividableFromGLType(ctx->header.glType)) { 1952 | 1953 | uint32_t const s = ctx->header.glTypeSize; 1954 | uint32_t const n = TinyKtx_ElementCountFromGLFormat(ctx->header.glFormat); 1955 | if (n == 0) { 1956 | ctx->callbacks.errorFn(ctx->user, "TinyKtx_ElementCountFromGLFormat error"); 1957 | return false; 1958 | } 1959 | 1960 | uint32_t const w = TinyKtx_MipMapReduce(ctx->header.pixelWidth, mipmaplevel); 1961 | uint32_t const snl = s * n * w; 1962 | uint32_t const k = ((snl + 3u) & ~3u); 1963 | 1964 | if(k != snl) { 1965 | return true; 1966 | } 1967 | } 1968 | return false; 1969 | } 1970 | uint32_t TinyKtx_UnpackedRowStride(TinyKtx_ContextHandle handle, uint32_t mipmaplevel) { 1971 | TinyKtx_Context *ctx = (TinyKtx_Context *) handle; 1972 | if (ctx == NULL) 1973 | return 0; 1974 | if (ctx->headerValid == false) { 1975 | ctx->callbacks.errorFn(ctx->user, "Header data hasn't been read yet or its invalid"); 1976 | return 0; 1977 | } 1978 | 1979 | if (ctx->header.glTypeSize < 4 && 1980 | TinyKtx_ByteDividableFromGLType(ctx->header.glType)) { 1981 | 1982 | uint32_t const s = ctx->header.glTypeSize; 1983 | uint32_t const n = TinyKtx_ElementCountFromGLFormat(ctx->header.glFormat); 1984 | if (n == 0) { 1985 | ctx->callbacks.errorFn(ctx->user, "TinyKtx_ElementCountFromGLFormat error"); 1986 | return 0; 1987 | } 1988 | 1989 | uint32_t const w = TinyKtx_MipMapReduce(ctx->header.pixelWidth, mipmaplevel); 1990 | uint32_t const snl = s * n * w; 1991 | uint32_t const k = ((snl + 3u) & ~3u); 1992 | return k; 1993 | } 1994 | return 0; 1995 | } 1996 | 1997 | 1998 | bool TinyKtx_WriteImageGL(TinyKtx_WriteCallbacks const *callbacks, 1999 | void *user, 2000 | uint32_t width, 2001 | uint32_t height, 2002 | uint32_t depth, 2003 | uint32_t slices, 2004 | uint32_t mipmaplevels, 2005 | uint32_t format, 2006 | uint32_t internalFormat, 2007 | uint32_t baseFormat, 2008 | uint32_t type, 2009 | uint32_t typeSize, 2010 | bool cubemap, 2011 | uint32_t const *mipmapsizes, 2012 | void const **mipmaps) { 2013 | 2014 | TinyKtx_Header header; 2015 | memcpy(header.identifier, TinyKtx_fileIdentifier, 12); 2016 | header.endianness = 0x04030201; 2017 | header.glFormat = format; 2018 | header.glInternalFormat = internalFormat; 2019 | header.glBaseInternalFormat = baseFormat; 2020 | header.glType = type; 2021 | header.glTypeSize = typeSize; 2022 | header.pixelWidth = width; 2023 | header.pixelHeight = (height == 1) ? 0 : height; 2024 | header.pixelDepth = (depth == 1) ? 0 : depth; 2025 | header.numberOfArrayElements = (slices == 1) ? 0 : slices; 2026 | header.numberOfFaces = cubemap ? 6 : 1; 2027 | header.numberOfMipmapLevels = mipmaplevels; 2028 | // TODO keyvalue pair data 2029 | header.bytesOfKeyValueData = 0; 2030 | callbacks->writeFn(user, &header, sizeof(TinyKtx_Header)); 2031 | 2032 | uint32_t w = (width == 0) ? 1 : width; 2033 | uint32_t h = (height == 0) ? 1 : height; 2034 | uint32_t d = (depth == 0) ? 1 : depth; 2035 | uint32_t sl = (slices == 0) ? 1 : slices; 2036 | static uint8_t const padding[4] = {0, 0, 0, 0}; 2037 | 2038 | for (uint32_t i = 0u; i < mipmaplevels; ++i) { 2039 | 2040 | bool writeRaw = true; 2041 | 2042 | if( typeSize < 4 && 2043 | TinyKtx_ByteDividableFromGLType(type)) { 2044 | 2045 | uint32_t const s = typeSize; 2046 | uint32_t const n = TinyKtx_ElementCountFromGLFormat(format); 2047 | if (n == 0) { 2048 | callbacks->errorFn(user, "TinyKtx_ElementCountFromGLFormat error"); 2049 | return false; 2050 | } 2051 | uint32_t const snl = s * n * w; 2052 | uint32_t const k = ((snl + 3u) & ~3u); 2053 | 2054 | uint32_t const size = (k * h * d * snl); 2055 | if (size < mipmapsizes[i]) { 2056 | callbacks->errorFn(user, "Internal size error, padding should only ever expand"); 2057 | return false; 2058 | } 2059 | 2060 | // if we need to expand for padding take the slow per row write route 2061 | if (size > mipmapsizes[i]) { 2062 | callbacks->writeFn(user, &size, sizeof(uint32_t)); 2063 | 2064 | uint8_t const *src = (uint8_t const*) mipmaps[i]; 2065 | for (uint32_t ww = 0u; ww < sl; ++ww) { 2066 | for (uint32_t zz = 0; zz < d; ++zz) { 2067 | for (uint32_t yy = 0; yy < h; ++yy) { 2068 | callbacks->writeFn(user, src, snl); 2069 | callbacks->writeFn(user, padding, k - snl); 2070 | src += snl; 2071 | } 2072 | } 2073 | } 2074 | uint32_t paddCount = ((size + 3u) & ~3u) - size; 2075 | if(paddCount > 3) { 2076 | callbacks->errorFn(user, "Internal error: padding bytes > 3"); 2077 | return false; 2078 | } 2079 | 2080 | callbacks->writeFn(user, padding, paddCount); 2081 | writeRaw = false; 2082 | } 2083 | } 2084 | 2085 | if(writeRaw) { 2086 | uint32_t const size = ((mipmapsizes[i] + 3u) & ~3u); 2087 | callbacks->writeFn(user, mipmapsizes + i, sizeof(uint32_t)); 2088 | callbacks->writeFn(user, mipmaps[i], mipmapsizes[i]); 2089 | callbacks->writeFn(user, padding, size - mipmapsizes[i]); 2090 | } 2091 | 2092 | if(w > 1) w = w / 2; 2093 | if(h > 1) h = h / 2; 2094 | if(d > 1) d = d / 2; 2095 | } 2096 | 2097 | return true; 2098 | } 2099 | 2100 | bool TinyKtx_WriteImage(TinyKtx_WriteCallbacks const *callbacks, 2101 | void *user, 2102 | uint32_t width, 2103 | uint32_t height, 2104 | uint32_t depth, 2105 | uint32_t slices, 2106 | uint32_t mipmaplevels, 2107 | TinyKtx_Format format, 2108 | bool cubemap, 2109 | uint32_t const *mipmapsizes, 2110 | void const **mipmaps) { 2111 | uint32_t glformat; 2112 | uint32_t glinternalFormat; 2113 | uint32_t gltype; 2114 | uint32_t gltypeSize; 2115 | if (TinyKtx_CrackFormatToGL(format, &glformat, &gltype, &glinternalFormat, &gltypeSize) == false) 2116 | return false; 2117 | 2118 | return TinyKtx_WriteImageGL(callbacks, 2119 | user, 2120 | width, 2121 | height, 2122 | depth, 2123 | slices, 2124 | mipmaplevels, 2125 | glformat, 2126 | glinternalFormat, 2127 | glinternalFormat, //?? 2128 | gltype, 2129 | gltypeSize, 2130 | cubemap, 2131 | mipmapsizes, 2132 | mipmaps 2133 | ); 2134 | 2135 | } 2136 | 2137 | // tiny_imageformat/tinyimageformat.h pr tinyimageformat_base.h needs included 2138 | // before tinyktx.h for this functionality 2139 | #ifdef TINYIMAGEFORMAT_BASE_H_ 2140 | TinyImageFormat TinyImageFormat_FromTinyKtxFormat(TinyKtx_Format format) 2141 | { 2142 | switch(format) { 2143 | case TKTX_UNDEFINED: return TinyImageFormat_UNDEFINED; 2144 | case TKTX_R4G4_UNORM_PACK8: return TinyImageFormat_R4G4_UNORM; 2145 | case TKTX_R4G4B4A4_UNORM_PACK16: return TinyImageFormat_R4G4B4A4_UNORM; 2146 | case TKTX_B4G4R4A4_UNORM_PACK16: return TinyImageFormat_B4G4R4A4_UNORM; 2147 | case TKTX_R5G6B5_UNORM_PACK16: return TinyImageFormat_R5G6B5_UNORM; 2148 | case TKTX_B5G6R5_UNORM_PACK16: return TinyImageFormat_B5G6R5_UNORM; 2149 | case TKTX_R5G5B5A1_UNORM_PACK16: return TinyImageFormat_R5G5B5A1_UNORM; 2150 | case TKTX_B5G5R5A1_UNORM_PACK16: return TinyImageFormat_B5G5R5A1_UNORM; 2151 | case TKTX_A1R5G5B5_UNORM_PACK16: return TinyImageFormat_A1R5G5B5_UNORM; 2152 | case TKTX_R8_UNORM: return TinyImageFormat_R8_UNORM; 2153 | case TKTX_R8_SNORM: return TinyImageFormat_R8_SNORM; 2154 | case TKTX_R8_UINT: return TinyImageFormat_R8_UINT; 2155 | case TKTX_R8_SINT: return TinyImageFormat_R8_SINT; 2156 | case TKTX_R8_SRGB: return TinyImageFormat_R8_SRGB; 2157 | case TKTX_R8G8_UNORM: return TinyImageFormat_R8G8_UNORM; 2158 | case TKTX_R8G8_SNORM: return TinyImageFormat_R8G8_SNORM; 2159 | case TKTX_R8G8_UINT: return TinyImageFormat_R8G8_UINT; 2160 | case TKTX_R8G8_SINT: return TinyImageFormat_R8G8_SINT; 2161 | case TKTX_R8G8_SRGB: return TinyImageFormat_R8G8_SRGB; 2162 | case TKTX_R8G8B8_UNORM: return TinyImageFormat_R8G8B8_UNORM; 2163 | case TKTX_R8G8B8_SNORM: return TinyImageFormat_R8G8B8_SNORM; 2164 | case TKTX_R8G8B8_UINT: return TinyImageFormat_R8G8B8_UINT; 2165 | case TKTX_R8G8B8_SINT: return TinyImageFormat_R8G8B8_SINT; 2166 | case TKTX_R8G8B8_SRGB: return TinyImageFormat_R8G8B8_SRGB; 2167 | case TKTX_B8G8R8_UNORM: return TinyImageFormat_B8G8R8_UNORM; 2168 | case TKTX_B8G8R8_SNORM: return TinyImageFormat_B8G8R8_SNORM; 2169 | case TKTX_B8G8R8_UINT: return TinyImageFormat_B8G8R8_UINT; 2170 | case TKTX_B8G8R8_SINT: return TinyImageFormat_B8G8R8_SINT; 2171 | case TKTX_B8G8R8_SRGB: return TinyImageFormat_B8G8R8_SRGB; 2172 | case TKTX_R8G8B8A8_UNORM: return TinyImageFormat_R8G8B8A8_UNORM; 2173 | case TKTX_R8G8B8A8_SNORM: return TinyImageFormat_R8G8B8A8_SNORM; 2174 | case TKTX_R8G8B8A8_UINT: return TinyImageFormat_R8G8B8A8_UINT; 2175 | case TKTX_R8G8B8A8_SINT: return TinyImageFormat_R8G8B8A8_SINT; 2176 | case TKTX_R8G8B8A8_SRGB: return TinyImageFormat_R8G8B8A8_SRGB; 2177 | case TKTX_B8G8R8A8_UNORM: return TinyImageFormat_B8G8R8A8_UNORM; 2178 | case TKTX_B8G8R8A8_SNORM: return TinyImageFormat_B8G8R8A8_SNORM; 2179 | case TKTX_B8G8R8A8_UINT: return TinyImageFormat_B8G8R8A8_UINT; 2180 | case TKTX_B8G8R8A8_SINT: return TinyImageFormat_B8G8R8A8_SINT; 2181 | case TKTX_B8G8R8A8_SRGB: return TinyImageFormat_B8G8R8A8_SRGB; 2182 | case TKTX_E5B9G9R9_UFLOAT_PACK32: return TinyImageFormat_E5B9G9R9_UFLOAT; 2183 | case TKTX_A2R10G10B10_UNORM_PACK32: return TinyImageFormat_B10G10R10A2_UNORM; 2184 | case TKTX_A2R10G10B10_UINT_PACK32: return TinyImageFormat_B10G10R10A2_UINT; 2185 | case TKTX_A2B10G10R10_UNORM_PACK32: return TinyImageFormat_R10G10B10A2_UNORM; 2186 | case TKTX_A2B10G10R10_UINT_PACK32: return TinyImageFormat_R10G10B10A2_UINT; 2187 | case TKTX_B10G11R11_UFLOAT_PACK32: return TinyImageFormat_B10G11R11_UFLOAT; 2188 | case TKTX_R16_UNORM: return TinyImageFormat_R16_UNORM; 2189 | case TKTX_R16_SNORM: return TinyImageFormat_R16_SNORM; 2190 | case TKTX_R16_UINT: return TinyImageFormat_R16_UINT; 2191 | case TKTX_R16_SINT: return TinyImageFormat_R16_SINT; 2192 | case TKTX_R16_SFLOAT: return TinyImageFormat_R16_SFLOAT; 2193 | case TKTX_R16G16_UNORM: return TinyImageFormat_R16G16_UNORM; 2194 | case TKTX_R16G16_SNORM: return TinyImageFormat_R16G16_SNORM; 2195 | case TKTX_R16G16_UINT: return TinyImageFormat_R16G16_UINT; 2196 | case TKTX_R16G16_SINT: return TinyImageFormat_R16G16_SINT; 2197 | case TKTX_R16G16_SFLOAT: return TinyImageFormat_R16G16_SFLOAT; 2198 | case TKTX_R16G16B16_UNORM: return TinyImageFormat_R16G16B16_UNORM; 2199 | case TKTX_R16G16B16_SNORM: return TinyImageFormat_R16G16B16_SNORM; 2200 | case TKTX_R16G16B16_UINT: return TinyImageFormat_R16G16B16_UINT; 2201 | case TKTX_R16G16B16_SINT: return TinyImageFormat_R16G16B16_SINT; 2202 | case TKTX_R16G16B16_SFLOAT: return TinyImageFormat_R16G16B16_SFLOAT; 2203 | case TKTX_R16G16B16A16_UNORM: return TinyImageFormat_R16G16B16A16_UNORM; 2204 | case TKTX_R16G16B16A16_SNORM: return TinyImageFormat_R16G16B16A16_SNORM; 2205 | case TKTX_R16G16B16A16_UINT: return TinyImageFormat_R16G16B16A16_UINT; 2206 | case TKTX_R16G16B16A16_SINT: return TinyImageFormat_R16G16B16A16_SINT; 2207 | case TKTX_R16G16B16A16_SFLOAT: return TinyImageFormat_R16G16B16A16_SFLOAT; 2208 | case TKTX_R32_UINT: return TinyImageFormat_R32_UINT; 2209 | case TKTX_R32_SINT: return TinyImageFormat_R32_SINT; 2210 | case TKTX_R32_SFLOAT: return TinyImageFormat_R32_SFLOAT; 2211 | case TKTX_R32G32_UINT: return TinyImageFormat_R32G32_UINT; 2212 | case TKTX_R32G32_SINT: return TinyImageFormat_R32G32_SINT; 2213 | case TKTX_R32G32_SFLOAT: return TinyImageFormat_R32G32_SFLOAT; 2214 | case TKTX_R32G32B32_UINT: return TinyImageFormat_R32G32B32_UINT; 2215 | case TKTX_R32G32B32_SINT: return TinyImageFormat_R32G32B32_SINT; 2216 | case TKTX_R32G32B32_SFLOAT: return TinyImageFormat_R32G32B32_SFLOAT; 2217 | case TKTX_R32G32B32A32_UINT: return TinyImageFormat_R32G32B32A32_UINT; 2218 | case TKTX_R32G32B32A32_SINT: return TinyImageFormat_R32G32B32A32_SINT; 2219 | case TKTX_R32G32B32A32_SFLOAT: return TinyImageFormat_R32G32B32A32_SFLOAT; 2220 | case TKTX_BC1_RGB_UNORM_BLOCK: return TinyImageFormat_DXBC1_RGB_UNORM; 2221 | case TKTX_BC1_RGB_SRGB_BLOCK: return TinyImageFormat_DXBC1_RGB_SRGB; 2222 | case TKTX_BC1_RGBA_UNORM_BLOCK: return TinyImageFormat_DXBC1_RGBA_UNORM; 2223 | case TKTX_BC1_RGBA_SRGB_BLOCK: return TinyImageFormat_DXBC1_RGBA_SRGB; 2224 | case TKTX_BC2_UNORM_BLOCK: return TinyImageFormat_DXBC2_UNORM; 2225 | case TKTX_BC2_SRGB_BLOCK: return TinyImageFormat_DXBC2_SRGB; 2226 | case TKTX_BC3_UNORM_BLOCK: return TinyImageFormat_DXBC3_UNORM; 2227 | case TKTX_BC3_SRGB_BLOCK: return TinyImageFormat_DXBC3_SRGB; 2228 | case TKTX_BC4_UNORM_BLOCK: return TinyImageFormat_DXBC4_UNORM; 2229 | case TKTX_BC4_SNORM_BLOCK: return TinyImageFormat_DXBC4_SNORM; 2230 | case TKTX_BC5_UNORM_BLOCK: return TinyImageFormat_DXBC5_UNORM; 2231 | case TKTX_BC5_SNORM_BLOCK: return TinyImageFormat_DXBC5_SNORM; 2232 | case TKTX_BC6H_UFLOAT_BLOCK: return TinyImageFormat_DXBC6H_UFLOAT; 2233 | case TKTX_BC6H_SFLOAT_BLOCK: return TinyImageFormat_DXBC6H_SFLOAT; 2234 | case TKTX_BC7_UNORM_BLOCK: return TinyImageFormat_DXBC7_UNORM; 2235 | case TKTX_BC7_SRGB_BLOCK: return TinyImageFormat_DXBC7_SRGB; 2236 | case TKTX_PVR_2BPP_UNORM_BLOCK: return TinyImageFormat_PVRTC1_2BPP_UNORM; 2237 | case TKTX_PVR_2BPPA_UNORM_BLOCK: return TinyImageFormat_PVRTC1_2BPP_UNORM; 2238 | case TKTX_PVR_4BPP_UNORM_BLOCK: return TinyImageFormat_PVRTC1_4BPP_UNORM; 2239 | case TKTX_PVR_4BPPA_UNORM_BLOCK: return TinyImageFormat_PVRTC1_4BPP_UNORM; 2240 | case TKTX_PVR_2BPP_SRGB_BLOCK: return TinyImageFormat_PVRTC1_2BPP_SRGB; 2241 | case TKTX_PVR_2BPPA_SRGB_BLOCK: return TinyImageFormat_PVRTC1_2BPP_SRGB; 2242 | case TKTX_PVR_4BPP_SRGB_BLOCK: return TinyImageFormat_PVRTC1_4BPP_SRGB; 2243 | case TKTX_PVR_4BPPA_SRGB_BLOCK: return TinyImageFormat_PVRTC1_4BPP_SRGB; 2244 | 2245 | case TKTX_ETC2_R8G8B8_UNORM_BLOCK: return TinyImageFormat_ETC2_R8G8B8_UNORM; 2246 | case TKTX_ETC2_R8G8B8A1_UNORM_BLOCK: return TinyImageFormat_ETC2_R8G8B8A1_UNORM; 2247 | case TKTX_ETC2_R8G8B8A8_UNORM_BLOCK: return TinyImageFormat_ETC2_R8G8B8A8_UNORM; 2248 | case TKTX_ETC2_R8G8B8_SRGB_BLOCK: return TinyImageFormat_ETC2_R8G8B8_SRGB; 2249 | case TKTX_ETC2_R8G8B8A1_SRGB_BLOCK: return TinyImageFormat_ETC2_R8G8B8A1_SRGB; 2250 | case TKTX_ETC2_R8G8B8A8_SRGB_BLOCK: return TinyImageFormat_ETC2_R8G8B8A8_SRGB; 2251 | case TKTX_EAC_R11_UNORM_BLOCK: return TinyImageFormat_ETC2_EAC_R11_UNORM; 2252 | case TKTX_EAC_R11G11_UNORM_BLOCK: return TinyImageFormat_ETC2_EAC_R11G11_UNORM; 2253 | case TKTX_EAC_R11_SNORM_BLOCK: return TinyImageFormat_ETC2_EAC_R11_SNORM; 2254 | case TKTX_EAC_R11G11_SNORM_BLOCK: return TinyImageFormat_ETC2_EAC_R11G11_SNORM; 2255 | case TKTX_ASTC_4x4_UNORM_BLOCK: return TinyImageFormat_ASTC_4x4_UNORM; 2256 | case TKTX_ASTC_4x4_SRGB_BLOCK: return TinyImageFormat_ASTC_4x4_SRGB; 2257 | case TKTX_ASTC_5x4_UNORM_BLOCK: return TinyImageFormat_ASTC_5x4_UNORM; 2258 | case TKTX_ASTC_5x4_SRGB_BLOCK: return TinyImageFormat_ASTC_5x4_SRGB; 2259 | case TKTX_ASTC_5x5_UNORM_BLOCK: return TinyImageFormat_ASTC_5x5_UNORM; 2260 | case TKTX_ASTC_5x5_SRGB_BLOCK: return TinyImageFormat_ASTC_5x5_SRGB; 2261 | case TKTX_ASTC_6x5_UNORM_BLOCK: return TinyImageFormat_ASTC_6x5_UNORM; 2262 | case TKTX_ASTC_6x5_SRGB_BLOCK: return TinyImageFormat_ASTC_6x5_SRGB; 2263 | case TKTX_ASTC_6x6_UNORM_BLOCK: return TinyImageFormat_ASTC_6x6_UNORM; 2264 | case TKTX_ASTC_6x6_SRGB_BLOCK: return TinyImageFormat_ASTC_6x6_SRGB; 2265 | case TKTX_ASTC_8x5_UNORM_BLOCK: return TinyImageFormat_ASTC_8x5_UNORM; 2266 | case TKTX_ASTC_8x5_SRGB_BLOCK: return TinyImageFormat_ASTC_8x5_SRGB; 2267 | case TKTX_ASTC_8x6_UNORM_BLOCK: return TinyImageFormat_ASTC_8x6_UNORM; 2268 | case TKTX_ASTC_8x6_SRGB_BLOCK: return TinyImageFormat_ASTC_8x6_SRGB; 2269 | case TKTX_ASTC_8x8_UNORM_BLOCK: return TinyImageFormat_ASTC_8x8_UNORM; 2270 | case TKTX_ASTC_8x8_SRGB_BLOCK: return TinyImageFormat_ASTC_8x8_SRGB; 2271 | case TKTX_ASTC_10x5_UNORM_BLOCK: return TinyImageFormat_ASTC_10x5_UNORM; 2272 | case TKTX_ASTC_10x5_SRGB_BLOCK: return TinyImageFormat_ASTC_10x5_SRGB; 2273 | case TKTX_ASTC_10x6_UNORM_BLOCK: return TinyImageFormat_ASTC_10x6_UNORM; 2274 | case TKTX_ASTC_10x6_SRGB_BLOCK: return TinyImageFormat_ASTC_10x6_SRGB; 2275 | case TKTX_ASTC_10x8_UNORM_BLOCK: return TinyImageFormat_ASTC_10x8_UNORM; 2276 | case TKTX_ASTC_10x8_SRGB_BLOCK: return TinyImageFormat_ASTC_10x8_SRGB; 2277 | case TKTX_ASTC_10x10_UNORM_BLOCK: return TinyImageFormat_ASTC_10x10_UNORM; 2278 | case TKTX_ASTC_10x10_SRGB_BLOCK: return TinyImageFormat_ASTC_10x10_SRGB; 2279 | case TKTX_ASTC_12x10_UNORM_BLOCK: return TinyImageFormat_ASTC_12x10_UNORM; 2280 | case TKTX_ASTC_12x10_SRGB_BLOCK: return TinyImageFormat_ASTC_12x10_SRGB; 2281 | case TKTX_ASTC_12x12_UNORM_BLOCK: return TinyImageFormat_ASTC_12x12_UNORM; 2282 | case TKTX_ASTC_12x12_SRGB_BLOCK: return TinyImageFormat_ASTC_12x12_SRGB; 2283 | 2284 | case TKTX_A8B8G8R8_UNORM_PACK32:break; 2285 | case TKTX_A8B8G8R8_SNORM_PACK32:break; 2286 | case TKTX_A8B8G8R8_UINT_PACK32:break; 2287 | case TKTX_A8B8G8R8_SINT_PACK32:break; 2288 | case TKTX_A8B8G8R8_SRGB_PACK32:break; 2289 | } 2290 | 2291 | return TinyImageFormat_UNDEFINED; 2292 | } 2293 | 2294 | TinyKtx_Format TinyImageFormat_ToTinyKtxFormat(TinyImageFormat format) { 2295 | 2296 | switch (format) { 2297 | case TinyImageFormat_UNDEFINED: return TKTX_UNDEFINED; 2298 | case TinyImageFormat_R4G4_UNORM: return TKTX_R4G4_UNORM_PACK8; 2299 | case TinyImageFormat_R4G4B4A4_UNORM: return TKTX_R4G4B4A4_UNORM_PACK16; 2300 | case TinyImageFormat_B4G4R4A4_UNORM: return TKTX_B4G4R4A4_UNORM_PACK16; 2301 | case TinyImageFormat_R5G6B5_UNORM: return TKTX_R5G6B5_UNORM_PACK16; 2302 | case TinyImageFormat_B5G6R5_UNORM: return TKTX_B5G6R5_UNORM_PACK16; 2303 | case TinyImageFormat_R5G5B5A1_UNORM: return TKTX_R5G5B5A1_UNORM_PACK16; 2304 | case TinyImageFormat_B5G5R5A1_UNORM: return TKTX_B5G5R5A1_UNORM_PACK16; 2305 | case TinyImageFormat_A1R5G5B5_UNORM: return TKTX_A1R5G5B5_UNORM_PACK16; 2306 | case TinyImageFormat_R8_UNORM: return TKTX_R8_UNORM; 2307 | case TinyImageFormat_R8_SNORM: return TKTX_R8_SNORM; 2308 | case TinyImageFormat_R8_UINT: return TKTX_R8_UINT; 2309 | case TinyImageFormat_R8_SINT: return TKTX_R8_SINT; 2310 | case TinyImageFormat_R8_SRGB: return TKTX_R8_SRGB; 2311 | case TinyImageFormat_R8G8_UNORM: return TKTX_R8G8_UNORM; 2312 | case TinyImageFormat_R8G8_SNORM: return TKTX_R8G8_SNORM; 2313 | case TinyImageFormat_R8G8_UINT: return TKTX_R8G8_UINT; 2314 | case TinyImageFormat_R8G8_SINT: return TKTX_R8G8_SINT; 2315 | case TinyImageFormat_R8G8_SRGB: return TKTX_R8G8_SRGB; 2316 | case TinyImageFormat_R8G8B8_UNORM: return TKTX_R8G8B8_UNORM; 2317 | case TinyImageFormat_R8G8B8_SNORM: return TKTX_R8G8B8_SNORM; 2318 | case TinyImageFormat_R8G8B8_UINT: return TKTX_R8G8B8_UINT; 2319 | case TinyImageFormat_R8G8B8_SINT: return TKTX_R8G8B8_SINT; 2320 | case TinyImageFormat_R8G8B8_SRGB: return TKTX_R8G8B8_SRGB; 2321 | case TinyImageFormat_B8G8R8_UNORM: return TKTX_B8G8R8_UNORM; 2322 | case TinyImageFormat_B8G8R8_SNORM: return TKTX_B8G8R8_SNORM; 2323 | case TinyImageFormat_B8G8R8_UINT: return TKTX_B8G8R8_UINT; 2324 | case TinyImageFormat_B8G8R8_SINT: return TKTX_B8G8R8_SINT; 2325 | case TinyImageFormat_B8G8R8_SRGB: return TKTX_B8G8R8_SRGB; 2326 | case TinyImageFormat_R8G8B8A8_UNORM: return TKTX_R8G8B8A8_UNORM; 2327 | case TinyImageFormat_R8G8B8A8_SNORM: return TKTX_R8G8B8A8_SNORM; 2328 | case TinyImageFormat_R8G8B8A8_UINT: return TKTX_R8G8B8A8_UINT; 2329 | case TinyImageFormat_R8G8B8A8_SINT: return TKTX_R8G8B8A8_SINT; 2330 | case TinyImageFormat_R8G8B8A8_SRGB: return TKTX_R8G8B8A8_SRGB; 2331 | case TinyImageFormat_B8G8R8A8_UNORM: return TKTX_B8G8R8A8_UNORM; 2332 | case TinyImageFormat_B8G8R8A8_SNORM: return TKTX_B8G8R8A8_SNORM; 2333 | case TinyImageFormat_B8G8R8A8_UINT: return TKTX_B8G8R8A8_UINT; 2334 | case TinyImageFormat_B8G8R8A8_SINT: return TKTX_B8G8R8A8_SINT; 2335 | case TinyImageFormat_B8G8R8A8_SRGB: return TKTX_B8G8R8A8_SRGB; 2336 | case TinyImageFormat_R10G10B10A2_UNORM: return TKTX_A2B10G10R10_UNORM_PACK32; 2337 | case TinyImageFormat_R10G10B10A2_UINT: return TKTX_A2B10G10R10_UINT_PACK32; 2338 | case TinyImageFormat_B10G10R10A2_UNORM: return TKTX_A2R10G10B10_UNORM_PACK32; 2339 | case TinyImageFormat_B10G10R10A2_UINT: return TKTX_A2R10G10B10_UINT_PACK32; 2340 | case TinyImageFormat_R16_UNORM: return TKTX_R16_UNORM; 2341 | case TinyImageFormat_R16_SNORM: return TKTX_R16_SNORM; 2342 | case TinyImageFormat_R16_UINT: return TKTX_R16_UINT; 2343 | case TinyImageFormat_R16_SINT: return TKTX_R16_SINT; 2344 | case TinyImageFormat_R16_SFLOAT: return TKTX_R16_SFLOAT; 2345 | case TinyImageFormat_R16G16_UNORM: return TKTX_R16G16_UNORM; 2346 | case TinyImageFormat_R16G16_SNORM: return TKTX_R16G16_SNORM; 2347 | case TinyImageFormat_R16G16_UINT: return TKTX_R16G16_UINT; 2348 | case TinyImageFormat_R16G16_SINT: return TKTX_R16G16_SINT; 2349 | case TinyImageFormat_R16G16_SFLOAT: return TKTX_R16G16_SFLOAT; 2350 | case TinyImageFormat_R16G16B16_UNORM: return TKTX_R16G16B16_UNORM; 2351 | case TinyImageFormat_R16G16B16_SNORM: return TKTX_R16G16B16_SNORM; 2352 | case TinyImageFormat_R16G16B16_UINT: return TKTX_R16G16B16_UINT; 2353 | case TinyImageFormat_R16G16B16_SINT: return TKTX_R16G16B16_SINT; 2354 | case TinyImageFormat_R16G16B16_SFLOAT: return TKTX_R16G16B16_SFLOAT; 2355 | case TinyImageFormat_R16G16B16A16_UNORM: return TKTX_R16G16B16A16_UNORM; 2356 | case TinyImageFormat_R16G16B16A16_SNORM: return TKTX_R16G16B16A16_SNORM; 2357 | case TinyImageFormat_R16G16B16A16_UINT: return TKTX_R16G16B16A16_UINT; 2358 | case TinyImageFormat_R16G16B16A16_SINT: return TKTX_R16G16B16A16_SINT; 2359 | case TinyImageFormat_R16G16B16A16_SFLOAT: return TKTX_R16G16B16A16_SFLOAT; 2360 | case TinyImageFormat_R32_UINT: return TKTX_R32_UINT; 2361 | case TinyImageFormat_R32_SINT: return TKTX_R32_SINT; 2362 | case TinyImageFormat_R32_SFLOAT: return TKTX_R32_SFLOAT; 2363 | case TinyImageFormat_R32G32_UINT: return TKTX_R32G32_UINT; 2364 | case TinyImageFormat_R32G32_SINT: return TKTX_R32G32_SINT; 2365 | case TinyImageFormat_R32G32_SFLOAT: return TKTX_R32G32_SFLOAT; 2366 | case TinyImageFormat_R32G32B32_UINT: return TKTX_R32G32B32_UINT; 2367 | case TinyImageFormat_R32G32B32_SINT: return TKTX_R32G32B32_SINT; 2368 | case TinyImageFormat_R32G32B32_SFLOAT: return TKTX_R32G32B32_SFLOAT; 2369 | case TinyImageFormat_R32G32B32A32_UINT: return TKTX_R32G32B32A32_UINT; 2370 | case TinyImageFormat_R32G32B32A32_SINT: return TKTX_R32G32B32A32_SINT; 2371 | case TinyImageFormat_R32G32B32A32_SFLOAT: return TKTX_R32G32B32A32_SFLOAT; 2372 | case TinyImageFormat_B10G11R11_UFLOAT: return TKTX_B10G11R11_UFLOAT_PACK32; 2373 | case TinyImageFormat_E5B9G9R9_UFLOAT: return TKTX_E5B9G9R9_UFLOAT_PACK32; 2374 | 2375 | case TinyImageFormat_DXBC1_RGB_UNORM: return TKTX_BC1_RGB_UNORM_BLOCK; 2376 | case TinyImageFormat_DXBC1_RGB_SRGB: return TKTX_BC1_RGB_SRGB_BLOCK; 2377 | case TinyImageFormat_DXBC1_RGBA_UNORM: return TKTX_BC1_RGBA_UNORM_BLOCK; 2378 | case TinyImageFormat_DXBC1_RGBA_SRGB: return TKTX_BC1_RGBA_SRGB_BLOCK; 2379 | case TinyImageFormat_DXBC2_UNORM: return TKTX_BC2_UNORM_BLOCK; 2380 | case TinyImageFormat_DXBC2_SRGB: return TKTX_BC2_SRGB_BLOCK; 2381 | case TinyImageFormat_DXBC3_UNORM: return TKTX_BC3_UNORM_BLOCK; 2382 | case TinyImageFormat_DXBC3_SRGB: return TKTX_BC3_SRGB_BLOCK; 2383 | case TinyImageFormat_DXBC4_UNORM: return TKTX_BC4_UNORM_BLOCK; 2384 | case TinyImageFormat_DXBC4_SNORM: return TKTX_BC4_SNORM_BLOCK; 2385 | case TinyImageFormat_DXBC5_UNORM: return TKTX_BC5_UNORM_BLOCK; 2386 | case TinyImageFormat_DXBC5_SNORM: return TKTX_BC5_SNORM_BLOCK; 2387 | case TinyImageFormat_DXBC6H_UFLOAT: return TKTX_BC6H_UFLOAT_BLOCK; 2388 | case TinyImageFormat_DXBC6H_SFLOAT: return TKTX_BC6H_SFLOAT_BLOCK; 2389 | case TinyImageFormat_DXBC7_UNORM: return TKTX_BC7_UNORM_BLOCK; 2390 | case TinyImageFormat_DXBC7_SRGB: return TKTX_BC7_SRGB_BLOCK; 2391 | case TinyImageFormat_PVRTC1_2BPP_UNORM: return TKTX_PVR_2BPPA_UNORM_BLOCK; 2392 | case TinyImageFormat_PVRTC1_4BPP_UNORM: return TKTX_PVR_4BPPA_UNORM_BLOCK; 2393 | case TinyImageFormat_PVRTC1_2BPP_SRGB: return TKTX_PVR_2BPPA_SRGB_BLOCK; 2394 | case TinyImageFormat_PVRTC1_4BPP_SRGB: return TKTX_PVR_4BPPA_SRGB_BLOCK; 2395 | 2396 | default: return TKTX_UNDEFINED; 2397 | }; 2398 | 2399 | return TKTX_UNDEFINED; 2400 | } 2401 | #endif // end TinyImageFormat conversion 2402 | 2403 | #endif // end implementation 2404 | 2405 | #ifdef __cplusplus 2406 | }; 2407 | #endif 2408 | 2409 | #endif // end header 2410 | /* 2411 | MIT License 2412 | 2413 | Copyright (c) 2019 DeanoC 2414 | 2415 | Permission is hereby granted, free of charge, to any person obtaining a copy 2416 | of this software and associated documentation files (the "Software"), to deal 2417 | in the Software without restriction, including without limitation the rights 2418 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 2419 | copies of the Software, and to permit persons to whom the Software is 2420 | furnished to do so, subject to the following conditions: 2421 | 2422 | The above copyright notice and this permission notice shall be included in all 2423 | copies or substantial portions of the Software. 2424 | 2425 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2426 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2427 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2428 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2429 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2430 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2431 | SOFTWARE. 2432 | */ 2433 | -------------------------------------------------------------------------------- /include/tiny_ktx/tinyktx2.h: -------------------------------------------------------------------------------- 1 | // MIT license see full LICENSE text at end of file 2 | #pragma once 3 | #ifndef TINY_KTX_TINYKTX2_H 4 | #define TINY_KTX_TINYKTX2_H 5 | 6 | #ifndef TINYKTX_HAVE_UINTXX_T 7 | #include // for uint32_t and int64_t 8 | #endif 9 | #ifndef TINYKTX_HAVE_BOOL 10 | #include // for bool 11 | #endif 12 | #ifndef TINYKTX_HAVE_SIZE_T 13 | #include // for size_t 14 | #endif 15 | #ifndef TINYKTX_HAVE_MEMCPY 16 | #include // for memcpy 17 | #endif 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | typedef struct TinyKtx2_Context *TinyKtx2_ContextHandle; 24 | 25 | #define TINYKTX2_MAX_MIPMAPLEVELS 16 26 | 27 | typedef void *(*TinyKtx2_AllocFunc)(void *user, size_t size); 28 | typedef void (*TinyKtx2_FreeFunc)(void *user, void *memory); 29 | typedef size_t (*TinyKtx2_ReadFunc)(void *user, void *buffer, size_t byteCount); 30 | typedef bool (*TinyKtx2_SeekFunc)(void *user, int64_t offset); 31 | typedef int64_t (*TinyKtx2_TellFunc)(void *user); 32 | typedef void (*TinyKtx2_ErrorFunc)(void *user, char const *msg); 33 | typedef bool (*TinyKtx2_SuperDecompress)(void* user, void* const sgdData, void const* src, size_t srcSize, void const* dst, size_t dstSize); 34 | 35 | typedef struct TinyKtx2_SuperDecompressTableEntry { 36 | uint32_t superId; 37 | TinyKtx2_SuperDecompress decompressor; 38 | } TinyKtx2_SuperDecompressTableEntry; 39 | 40 | typedef struct TinyKtx2_Callbacks { 41 | TinyKtx2_ErrorFunc error; 42 | TinyKtx2_AllocFunc alloc; 43 | TinyKtx2_FreeFunc free; 44 | TinyKtx2_ReadFunc read; 45 | TinyKtx2_SeekFunc seek; 46 | TinyKtx2_TellFunc tell; 47 | 48 | size_t numSuperDecompressors; 49 | TinyKtx2_SuperDecompressTableEntry const* superDecompressors; 50 | } TinyKtx2_Callbacks; 51 | 52 | TinyKtx2_ContextHandle TinyKtx2_CreateContext(TinyKtx2_Callbacks const *callbacks, void *user); 53 | void TinyKtx2_DestroyContext(TinyKtx_ContextHandle handle); 54 | 55 | // reset lets you reuse the context for another file (saves an alloc/free cycle) 56 | void TinyKtx2_Reset(TinyKtx2_ContextHandle handle); 57 | 58 | // call this to read the header file should already be at the start of the KTX data 59 | bool TinyKtx2_ReadHeader(TinyKtx2_ContextHandle handle); 60 | 61 | // this is slow linear search. TODO add iterator style reading of key value pairs 62 | bool TinyKtx2_GetValue(TinyKtx2_ContextHandle handle, char const *key, void const **value); 63 | 64 | bool TinyKtx2_Is1D(TinyKtx2_ContextHandle handle); 65 | bool TinyKtx2_Is2D(TinyKtx2_ContextHandle handle); 66 | bool TinyKtx2_Is3D(TinyKtx2_ContextHandle handle); 67 | bool TinyKtx2_IsCubemap(TinyKtx2_ContextHandle handle); 68 | bool TinyKtx2_IsArray(TinyKtx2_ContextHandle handle); 69 | 70 | bool TinyKtx2_Dimensions(TinyKtx2_ContextHandle handle, uint32_t* width, uint32_t* height, uint32_t* depth, uint32_t* slices); 71 | uint32_t TinyKtx2_Width(TinyKtx2_ContextHandle handle); 72 | uint32_t TinyKtx2_Height(TinyKtx2_ContextHandle handle); 73 | uint32_t TinyKtx2_Depth(TinyKtx2_ContextHandle handle); 74 | uint32_t TinyKtx2_ArraySlices(TinyKtx2_ContextHandle handle); 75 | 76 | bool TinyKtx2_GetFormatGL(TinyKtx2_ContextHandle handle, uint32_t *glformat, uint32_t *gltype, uint32_t *glinternalformat, uint32_t* typesize, uint32_t* glbaseinternalformat); 77 | 78 | bool TinyKtx2_NeedsGenerationOfMipmaps(TinyKtx2_ContextHandle handle); 79 | bool TinyKtx2_NeedsEndianCorrecting(TinyKtx2_ContextHandle handle); 80 | 81 | uint32_t TinyKtx2_NumberOfMipmaps(TinyKtx2_ContextHandle handle); 82 | uint32_t TinyKtx2_ImageSize(TinyKtx2_ContextHandle handle, uint32_t mipmaplevel); 83 | 84 | bool TinyKtx2_IsMipMapLevelUnpacked(TinyKtx2_ContextHandle handle, uint32_t mipmaplevel); 85 | // this is required to read Unpacked data correctly 86 | uint32_t TinyKtx2_UnpackedRowStride(TinyKtx2_ContextHandle handle, uint32_t mipmaplevel); 87 | 88 | // data return by ImageRawData is owned by the context. Don't free it! 89 | void const *TinyKtx2_ImageRawData(TinyKtx2_ContextHandle handle, uint32_t mipmaplevel); 90 | 91 | typedef void (*TinyKtx2_WriteFunc)(void *user, void const *buffer, size_t byteCount); 92 | 93 | typedef struct TinyKtx2_WriteCallbacks { 94 | TinyKtx2_ErrorFunc error; 95 | TinyKtx2_AllocFunc alloc; 96 | TinyKtx2_FreeFunc free; 97 | TinyKtx2_WriteFunc write; 98 | } TinyKtx2_WriteCallbacks; 99 | 100 | 101 | bool TinyKtx2_WriteImageGL(TinyKtx2_WriteCallbacks const *callbacks, 102 | void *user, 103 | uint32_t width, 104 | uint32_t height, 105 | uint32_t depth, 106 | uint32_t slices, 107 | uint32_t mipmaplevels, 108 | uint32_t format, 109 | uint32_t internalFormat, 110 | uint32_t baseFormat, 111 | uint32_t type, 112 | uint32_t typeSize, 113 | bool cubemap, 114 | uint32_t const *mipmapsizes, 115 | void const **mipmaps); 116 | 117 | // ktx v1 is based on GL (slightly confusing imho) texture format system 118 | // there is format, internal format, type etc. 119 | 120 | // we try and expose a more dx12/vulkan/metal style of format 121 | // but obviously still need to GL data so bare with me. 122 | // a TinyKTX_Format is the equivilent to GL/KTX Format and Type 123 | // the API doesn't expose the actual values (which come from GL itself) 124 | // but provide an API call to crack them back into the actual GL values). 125 | 126 | // Ktx v2 is based on VkFormat and also DFD, so we now base the 127 | // enumeration values of TinyKtx_Format on the Vkformat values where possible 128 | 129 | #ifndef TINYKTX_DEFINED 130 | typedef enum TinyImageFormat_VkFormat { 131 | TIF_VK_FORMAT_UNDEFINED = 0, 132 | TIF_VK_FORMAT_R4G4_UNORM_PACK8 = 1, 133 | TIF_VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2, 134 | TIF_VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3, 135 | TIF_VK_FORMAT_R5G6B5_UNORM_PACK16 = 4, 136 | TIF_VK_FORMAT_B5G6R5_UNORM_PACK16 = 5, 137 | TIF_VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6, 138 | TIF_VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7, 139 | TIF_VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8, 140 | TIF_VK_FORMAT_R8_UNORM = 9, 141 | TIF_VK_FORMAT_R8_SNORM = 10, 142 | TIF_VK_FORMAT_R8_USCALED = 11, 143 | TIF_VK_FORMAT_R8_SSCALED = 12, 144 | TIF_VK_FORMAT_R8_UINT = 13, 145 | TIF_VK_FORMAT_R8_SINT = 14, 146 | TIF_VK_FORMAT_R8_SRGB = 15, 147 | TIF_VK_FORMAT_R8G8_UNORM = 16, 148 | TIF_VK_FORMAT_R8G8_SNORM = 17, 149 | TIF_VK_FORMAT_R8G8_USCALED = 18, 150 | TIF_VK_FORMAT_R8G8_SSCALED = 19, 151 | TIF_VK_FORMAT_R8G8_UINT = 20, 152 | TIF_VK_FORMAT_R8G8_SINT = 21, 153 | TIF_VK_FORMAT_R8G8_SRGB = 22, 154 | TIF_VK_FORMAT_R8G8B8_UNORM = 23, 155 | TIF_VK_FORMAT_R8G8B8_SNORM = 24, 156 | TIF_VK_FORMAT_R8G8B8_USCALED = 25, 157 | TIF_VK_FORMAT_R8G8B8_SSCALED = 26, 158 | TIF_VK_FORMAT_R8G8B8_UINT = 27, 159 | TIF_VK_FORMAT_R8G8B8_SINT = 28, 160 | TIF_VK_FORMAT_R8G8B8_SRGB = 29, 161 | TIF_VK_FORMAT_B8G8R8_UNORM = 30, 162 | TIF_VK_FORMAT_B8G8R8_SNORM = 31, 163 | TIF_VK_FORMAT_B8G8R8_USCALED = 32, 164 | TIF_VK_FORMAT_B8G8R8_SSCALED = 33, 165 | TIF_VK_FORMAT_B8G8R8_UINT = 34, 166 | TIF_VK_FORMAT_B8G8R8_SINT = 35, 167 | TIF_VK_FORMAT_B8G8R8_SRGB = 36, 168 | TIF_VK_FORMAT_R8G8B8A8_UNORM = 37, 169 | TIF_VK_FORMAT_R8G8B8A8_SNORM = 38, 170 | TIF_VK_FORMAT_R8G8B8A8_USCALED = 39, 171 | TIF_VK_FORMAT_R8G8B8A8_SSCALED = 40, 172 | TIF_VK_FORMAT_R8G8B8A8_UINT = 41, 173 | TIF_VK_FORMAT_R8G8B8A8_SINT = 42, 174 | TIF_VK_FORMAT_R8G8B8A8_SRGB = 43, 175 | TIF_VK_FORMAT_B8G8R8A8_UNORM = 44, 176 | TIF_VK_FORMAT_B8G8R8A8_SNORM = 45, 177 | TIF_VK_FORMAT_B8G8R8A8_USCALED = 46, 178 | TIF_VK_FORMAT_B8G8R8A8_SSCALED = 47, 179 | TIF_VK_FORMAT_B8G8R8A8_UINT = 48, 180 | TIF_VK_FORMAT_B8G8R8A8_SINT = 49, 181 | TIF_VK_FORMAT_B8G8R8A8_SRGB = 50, 182 | TIF_VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51, 183 | TIF_VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52, 184 | TIF_VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53, 185 | TIF_VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54, 186 | TIF_VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55, 187 | TIF_VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56, 188 | TIF_VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57, 189 | TIF_VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58, 190 | TIF_VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59, 191 | TIF_VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60, 192 | TIF_VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61, 193 | TIF_VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62, 194 | TIF_VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63, 195 | TIF_VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64, 196 | TIF_VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65, 197 | TIF_VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66, 198 | TIF_VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67, 199 | TIF_VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68, 200 | TIF_VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69, 201 | TIF_VK_FORMAT_R16_UNORM = 70, 202 | TIF_VK_FORMAT_R16_SNORM = 71, 203 | TIF_VK_FORMAT_R16_USCALED = 72, 204 | TIF_VK_FORMAT_R16_SSCALED = 73, 205 | TIF_VK_FORMAT_R16_UINT = 74, 206 | TIF_VK_FORMAT_R16_SINT = 75, 207 | TIF_VK_FORMAT_R16_SFLOAT = 76, 208 | TIF_VK_FORMAT_R16G16_UNORM = 77, 209 | TIF_VK_FORMAT_R16G16_SNORM = 78, 210 | TIF_VK_FORMAT_R16G16_USCALED = 79, 211 | TIF_VK_FORMAT_R16G16_SSCALED = 80, 212 | TIF_VK_FORMAT_R16G16_UINT = 81, 213 | TIF_VK_FORMAT_R16G16_SINT = 82, 214 | TIF_VK_FORMAT_R16G16_SFLOAT = 83, 215 | TIF_VK_FORMAT_R16G16B16_UNORM = 84, 216 | TIF_VK_FORMAT_R16G16B16_SNORM = 85, 217 | TIF_VK_FORMAT_R16G16B16_USCALED = 86, 218 | TIF_VK_FORMAT_R16G16B16_SSCALED = 87, 219 | TIF_VK_FORMAT_R16G16B16_UINT = 88, 220 | TIF_VK_FORMAT_R16G16B16_SINT = 89, 221 | TIF_VK_FORMAT_R16G16B16_SFLOAT = 90, 222 | TIF_VK_FORMAT_R16G16B16A16_UNORM = 91, 223 | TIF_VK_FORMAT_R16G16B16A16_SNORM = 92, 224 | TIF_VK_FORMAT_R16G16B16A16_USCALED = 93, 225 | TIF_VK_FORMAT_R16G16B16A16_SSCALED = 94, 226 | TIF_VK_FORMAT_R16G16B16A16_UINT = 95, 227 | TIF_VK_FORMAT_R16G16B16A16_SINT = 96, 228 | TIF_VK_FORMAT_R16G16B16A16_SFLOAT = 97, 229 | TIF_VK_FORMAT_R32_UINT = 98, 230 | TIF_VK_FORMAT_R32_SINT = 99, 231 | TIF_VK_FORMAT_R32_SFLOAT = 100, 232 | TIF_VK_FORMAT_R32G32_UINT = 101, 233 | TIF_VK_FORMAT_R32G32_SINT = 102, 234 | TIF_VK_FORMAT_R32G32_SFLOAT = 103, 235 | TIF_VK_FORMAT_R32G32B32_UINT = 104, 236 | TIF_VK_FORMAT_R32G32B32_SINT = 105, 237 | TIF_VK_FORMAT_R32G32B32_SFLOAT = 106, 238 | TIF_VK_FORMAT_R32G32B32A32_UINT = 107, 239 | TIF_VK_FORMAT_R32G32B32A32_SINT = 108, 240 | TIF_VK_FORMAT_R32G32B32A32_SFLOAT = 109, 241 | TIF_VK_FORMAT_R64_UINT = 110, 242 | TIF_VK_FORMAT_R64_SINT = 111, 243 | TIF_VK_FORMAT_R64_SFLOAT = 112, 244 | TIF_VK_FORMAT_R64G64_UINT = 113, 245 | TIF_VK_FORMAT_R64G64_SINT = 114, 246 | TIF_VK_FORMAT_R64G64_SFLOAT = 115, 247 | TIF_VK_FORMAT_R64G64B64_UINT = 116, 248 | TIF_VK_FORMAT_R64G64B64_SINT = 117, 249 | TIF_VK_FORMAT_R64G64B64_SFLOAT = 118, 250 | TIF_VK_FORMAT_R64G64B64A64_UINT = 119, 251 | TIF_VK_FORMAT_R64G64B64A64_SINT = 120, 252 | TIF_VK_FORMAT_R64G64B64A64_SFLOAT = 121, 253 | TIF_VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122, 254 | TIF_VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123, 255 | TIF_VK_FORMAT_D16_UNORM = 124, 256 | TIF_VK_FORMAT_X8_D24_UNORM_PACK32 = 125, 257 | TIF_VK_FORMAT_D32_SFLOAT = 126, 258 | TIF_VK_FORMAT_S8_UINT = 127, 259 | TIF_VK_FORMAT_D16_UNORM_S8_UINT = 128, 260 | TIF_VK_FORMAT_D24_UNORM_S8_UINT = 129, 261 | TIF_VK_FORMAT_D32_SFLOAT_S8_UINT = 130, 262 | TIF_VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131, 263 | TIF_VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132, 264 | TIF_VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133, 265 | TIF_VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134, 266 | TIF_VK_FORMAT_BC2_UNORM_BLOCK = 135, 267 | TIF_VK_FORMAT_BC2_SRGB_BLOCK = 136, 268 | TIF_VK_FORMAT_BC3_UNORM_BLOCK = 137, 269 | TIF_VK_FORMAT_BC3_SRGB_BLOCK = 138, 270 | TIF_VK_FORMAT_BC4_UNORM_BLOCK = 139, 271 | TIF_VK_FORMAT_BC4_SNORM_BLOCK = 140, 272 | TIF_VK_FORMAT_BC5_UNORM_BLOCK = 141, 273 | TIF_VK_FORMAT_BC5_SNORM_BLOCK = 142, 274 | TIF_VK_FORMAT_BC6H_UFLOAT_BLOCK = 143, 275 | TIF_VK_FORMAT_BC6H_SFLOAT_BLOCK = 144, 276 | TIF_VK_FORMAT_BC7_UNORM_BLOCK = 145, 277 | TIF_VK_FORMAT_BC7_SRGB_BLOCK = 146, 278 | TIF_VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147, 279 | TIF_VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148, 280 | TIF_VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149, 281 | TIF_VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150, 282 | TIF_VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151, 283 | TIF_VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152, 284 | TIF_VK_FORMAT_EAC_R11_UNORM_BLOCK = 153, 285 | TIF_VK_FORMAT_EAC_R11_SNORM_BLOCK = 154, 286 | TIF_VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155, 287 | TIF_VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156, 288 | TIF_VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157, 289 | TIF_VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158, 290 | TIF_VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159, 291 | TIF_VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160, 292 | TIF_VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161, 293 | TIF_VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162, 294 | TIF_VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163, 295 | TIF_VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164, 296 | TIF_VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165, 297 | TIF_VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166, 298 | TIF_VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167, 299 | TIF_VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168, 300 | TIF_VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169, 301 | TIF_VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170, 302 | TIF_VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171, 303 | TIF_VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172, 304 | TIF_VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173, 305 | TIF_VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174, 306 | TIF_VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175, 307 | TIF_VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176, 308 | TIF_VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177, 309 | TIF_VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178, 310 | TIF_VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179, 311 | TIF_VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180, 312 | TIF_VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181, 313 | TIF_VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182, 314 | TIF_VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183, 315 | TIF_VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184, 316 | 317 | TIF_VK_FORMAT_G8B8G8R8_422_UNORM = 1000156000, 318 | TIF_VK_FORMAT_B8G8R8G8_422_UNORM = 1000156001, 319 | TIF_VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM = 1000156002, 320 | TIF_VK_FORMAT_G8_B8R8_2PLANE_420_UNORM = 1000156003, 321 | TIF_VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM = 1000156004, 322 | TIF_VK_FORMAT_G8_B8R8_2PLANE_422_UNORM = 1000156005, 323 | TIF_VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM = 1000156006, 324 | TIF_VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007, 325 | TIF_VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008, 326 | TIF_VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009, 327 | TIF_VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010, 328 | TIF_VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011, 329 | TIF_VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 = 1000156012, 330 | TIF_VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 = 1000156013, 331 | TIF_VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 = 1000156014, 332 | TIF_VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 = 1000156015, 333 | TIF_VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 = 1000156016, 334 | TIF_VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017, 335 | TIF_VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018, 336 | TIF_VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019, 337 | TIF_VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020, 338 | TIF_VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021, 339 | TIF_VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 = 1000156022, 340 | TIF_VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 = 1000156023, 341 | TIF_VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 = 1000156024, 342 | TIF_VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 = 1000156025, 343 | TIF_VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 = 1000156026, 344 | TIF_VK_FORMAT_G16B16G16R16_422_UNORM = 1000156027, 345 | TIF_VK_FORMAT_B16G16R16G16_422_UNORM = 1000156028, 346 | TIF_VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM = 1000156029, 347 | TIF_VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030, 348 | TIF_VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031, 349 | TIF_VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032, 350 | TIF_VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033, 351 | TIF_VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000, 352 | TIF_VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001, 353 | TIF_VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002, 354 | TIF_VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003, 355 | TIF_VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004, 356 | TIF_VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005, 357 | TIF_VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006, 358 | TIF_VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007, 359 | } TinyKTX_VkFormat; 360 | 361 | #define TINYKTX_MEV(x) TKTX_##x = TIF_VK_FORMAT_##x 362 | typedef enum TinyKtx_Format { 363 | TINYKTX_MEV(UNDEFINED), 364 | TINYKTX_MEV(R4G4_UNORM_PACK8), 365 | TINYKTX_MEV(R4G4B4A4_UNORM_PACK16), 366 | TINYKTX_MEV(B4G4R4A4_UNORM_PACK16), 367 | TINYKTX_MEV(R5G6B5_UNORM_PACK16), 368 | TINYKTX_MEV(B5G6R5_UNORM_PACK16), 369 | TINYKTX_MEV(R5G5B5A1_UNORM_PACK16), 370 | TINYKTX_MEV(B5G5R5A1_UNORM_PACK16), 371 | TINYKTX_MEV(A1R5G5B5_UNORM_PACK16), 372 | 373 | TINYKTX_MEV(R8_UNORM), 374 | TINYKTX_MEV(R8_SNORM), 375 | TINYKTX_MEV(R8_UINT), 376 | TINYKTX_MEV(R8_SINT), 377 | TINYKTX_MEV(R8_SRGB), 378 | 379 | TINYKTX_MEV(R8G8_UNORM), 380 | TINYKTX_MEV(R8G8_SNORM), 381 | TINYKTX_MEV(R8G8_UINT), 382 | TINYKTX_MEV(R8G8_SINT), 383 | TINYKTX_MEV(R8G8_SRGB), 384 | 385 | TINYKTX_MEV(R8G8B8_UNORM), 386 | TINYKTX_MEV(R8G8B8_SNORM), 387 | TINYKTX_MEV(R8G8B8_UINT), 388 | TINYKTX_MEV(R8G8B8_SINT), 389 | TINYKTX_MEV(R8G8B8_SRGB), 390 | TINYKTX_MEV(B8G8R8_UNORM), 391 | TINYKTX_MEV(B8G8R8_SNORM), 392 | TINYKTX_MEV(B8G8R8_UINT), 393 | TINYKTX_MEV(B8G8R8_SINT), 394 | TINYKTX_MEV(B8G8R8_SRGB), 395 | 396 | TINYKTX_MEV(R8G8B8A8_UNORM), 397 | TINYKTX_MEV(R8G8B8A8_SNORM), 398 | TINYKTX_MEV(R8G8B8A8_UINT), 399 | TINYKTX_MEV(R8G8B8A8_SINT), 400 | TINYKTX_MEV(R8G8B8A8_SRGB), 401 | TINYKTX_MEV(B8G8R8A8_UNORM), 402 | TINYKTX_MEV(B8G8R8A8_SNORM), 403 | TINYKTX_MEV(B8G8R8A8_UINT), 404 | TINYKTX_MEV(B8G8R8A8_SINT), 405 | TINYKTX_MEV(B8G8R8A8_SRGB), 406 | 407 | TINYKTX_MEV(A8B8G8R8_UNORM_PACK32), 408 | TINYKTX_MEV(A8B8G8R8_SNORM_PACK32), 409 | TINYKTX_MEV(A8B8G8R8_UINT_PACK32), 410 | TINYKTX_MEV(A8B8G8R8_SINT_PACK32), 411 | TINYKTX_MEV(A8B8G8R8_SRGB_PACK32), 412 | 413 | TINYKTX_MEV(E5B9G9R9_UFLOAT_PACK32), 414 | TINYKTX_MEV(A2R10G10B10_UNORM_PACK32), 415 | TINYKTX_MEV(A2R10G10B10_UINT_PACK32), 416 | TINYKTX_MEV(A2B10G10R10_UNORM_PACK32), 417 | TINYKTX_MEV(A2B10G10R10_UINT_PACK32), 418 | TINYKTX_MEV(B10G11R11_UFLOAT_PACK32), 419 | 420 | TINYKTX_MEV(R16_UNORM), 421 | TINYKTX_MEV(R16_SNORM), 422 | TINYKTX_MEV(R16_UINT), 423 | TINYKTX_MEV(R16_SINT), 424 | TINYKTX_MEV(R16_SFLOAT), 425 | TINYKTX_MEV(R16G16_UNORM), 426 | TINYKTX_MEV(R16G16_SNORM), 427 | TINYKTX_MEV(R16G16_UINT), 428 | TINYKTX_MEV(R16G16_SINT), 429 | TINYKTX_MEV(R16G16_SFLOAT), 430 | TINYKTX_MEV(R16G16B16_UNORM), 431 | TINYKTX_MEV(R16G16B16_SNORM), 432 | TINYKTX_MEV(R16G16B16_UINT), 433 | TINYKTX_MEV(R16G16B16_SINT), 434 | TINYKTX_MEV(R16G16B16_SFLOAT), 435 | TINYKTX_MEV(R16G16B16A16_UNORM), 436 | TINYKTX_MEV(R16G16B16A16_SNORM), 437 | TINYKTX_MEV(R16G16B16A16_UINT), 438 | TINYKTX_MEV(R16G16B16A16_SINT), 439 | TINYKTX_MEV(R16G16B16A16_SFLOAT), 440 | TINYKTX_MEV(R32_UINT), 441 | TINYKTX_MEV(R32_SINT), 442 | TINYKTX_MEV(R32_SFLOAT), 443 | TINYKTX_MEV(R32G32_UINT), 444 | TINYKTX_MEV(R32G32_SINT), 445 | TINYKTX_MEV(R32G32_SFLOAT), 446 | TINYKTX_MEV(R32G32B32_UINT), 447 | TINYKTX_MEV(R32G32B32_SINT), 448 | TINYKTX_MEV(R32G32B32_SFLOAT), 449 | TINYKTX_MEV(R32G32B32A32_UINT), 450 | TINYKTX_MEV(R32G32B32A32_SINT), 451 | TINYKTX_MEV(R32G32B32A32_SFLOAT), 452 | 453 | TINYKTX_MEV(BC1_RGB_UNORM_BLOCK), 454 | TINYKTX_MEV(BC1_RGB_SRGB_BLOCK), 455 | TINYKTX_MEV(BC1_RGBA_UNORM_BLOCK), 456 | TINYKTX_MEV(BC1_RGBA_SRGB_BLOCK), 457 | TINYKTX_MEV(BC2_UNORM_BLOCK), 458 | TINYKTX_MEV(BC2_SRGB_BLOCK), 459 | TINYKTX_MEV(BC3_UNORM_BLOCK), 460 | TINYKTX_MEV(BC3_SRGB_BLOCK), 461 | TINYKTX_MEV(BC4_UNORM_BLOCK), 462 | TINYKTX_MEV(BC4_SNORM_BLOCK), 463 | TINYKTX_MEV(BC5_UNORM_BLOCK), 464 | TINYKTX_MEV(BC5_SNORM_BLOCK), 465 | TINYKTX_MEV(BC6H_UFLOAT_BLOCK), 466 | TINYKTX_MEV(BC6H_SFLOAT_BLOCK), 467 | TINYKTX_MEV(BC7_UNORM_BLOCK), 468 | TINYKTX_MEV(BC7_SRGB_BLOCK), 469 | 470 | TINYKTX_MEV(ETC2_R8G8B8_UNORM_BLOCK), 471 | TINYKTX_MEV(ETC2_R8G8B8A1_UNORM_BLOCK), 472 | TINYKTX_MEV(ETC2_R8G8B8A8_UNORM_BLOCK), 473 | TINYKTX_MEV(ETC2_R8G8B8_SRGB_BLOCK), 474 | TINYKTX_MEV(ETC2_R8G8B8A1_SRGB_BLOCK), 475 | TINYKTX_MEV(ETC2_R8G8B8A8_SRGB_BLOCK), 476 | TINYKTX_MEV(EAC_R11_UNORM_BLOCK), 477 | TINYKTX_MEV(EAC_R11G11_UNORM_BLOCK), 478 | TINYKTX_MEV(EAC_R11_SNORM_BLOCK), 479 | TINYKTX_MEV(EAC_R11G11_SNORM_BLOCK), 480 | 481 | TKTX_PVR_2BPP_BLOCK = TIF_VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, 482 | TKTX_PVR_2BPPA_BLOCK = TIF_VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG, 483 | TKTX_PVR_4BPP_BLOCK = TIF_VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, 484 | TKTX_PVR_4BPPA_BLOCK = TIF_VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG, 485 | TKTX_PVR_2BPP_SRGB_BLOCK = TIF_VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, 486 | TKTX_PVR_2BPPA_SRGB_BLOCK = TIF_VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG, 487 | TKTX_PVR_4BPP_SRGB_BLOCK = TIF_VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG, 488 | TKTX_PVR_4BPPA_SRGB_BLOCK = TIF_VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG, 489 | 490 | TINYKTX_MEV(ASTC_4x4_UNORM_BLOCK), 491 | TINYKTX_MEV(ASTC_4x4_SRGB_BLOCK), 492 | TINYKTX_MEV(ASTC_5x4_UNORM_BLOCK), 493 | TINYKTX_MEV(ASTC_5x4_SRGB_BLOCK), 494 | TINYKTX_MEV(ASTC_5x5_UNORM_BLOCK), 495 | TINYKTX_MEV(ASTC_5x5_SRGB_BLOCK), 496 | TINYKTX_MEV(ASTC_6x5_UNORM_BLOCK), 497 | TINYKTX_MEV(ASTC_6x5_SRGB_BLOCK), 498 | TINYKTX_MEV(ASTC_6x6_UNORM_BLOCK), 499 | TINYKTX_MEV(ASTC_6x6_SRGB_BLOCK), 500 | TINYKTX_MEV(ASTC_8x5_UNORM_BLOCK), 501 | TINYKTX_MEV(ASTC_8x5_SRGB_BLOCK), 502 | TINYKTX_MEV(ASTC_8x6_UNORM_BLOCK), 503 | TINYKTX_MEV(ASTC_8x6_SRGB_BLOCK), 504 | TINYKTX_MEV(ASTC_8x8_UNORM_BLOCK), 505 | TINYKTX_MEV(ASTC_8x8_SRGB_BLOCK), 506 | TINYKTX_MEV(ASTC_10x5_UNORM_BLOCK), 507 | TINYKTX_MEV(ASTC_10x5_SRGB_BLOCK), 508 | TINYKTX_MEV(ASTC_10x6_UNORM_BLOCK), 509 | TINYKTX_MEV(ASTC_10x6_SRGB_BLOCK), 510 | TINYKTX_MEV(ASTC_10x8_UNORM_BLOCK), 511 | TINYKTX_MEV(ASTC_10x8_SRGB_BLOCK), 512 | TINYKTX_MEV(ASTC_10x10_UNORM_BLOCK), 513 | TINYKTX_MEV(ASTC_10x10_SRGB_BLOCK), 514 | TINYKTX_MEV(ASTC_12x10_UNORM_BLOCK), 515 | TINYKTX_MEV(ASTC_12x10_SRGB_BLOCK), 516 | TINYKTX_MEV(ASTC_12x12_UNORM_BLOCK), 517 | TINYKTX_MEV(ASTC_12x12_SRGB_BLOCK), 518 | 519 | } TinyKtx_Format; 520 | #undef TINYKTX_MEV 521 | 522 | #define TINYKTX_DEFINED 523 | #endif 524 | 525 | TinyKtx_Format TinyKtx_GetFormat(TinyKtx2_ContextHandle handle); 526 | bool TinyKtx2_WriteImage(TinyKtx2_WriteCallbacks const *callbacks, 527 | void *user, 528 | uint32_t width, 529 | uint32_t height, 530 | uint32_t depth, 531 | uint32_t slices, 532 | uint32_t mipmaplevels, 533 | TinyKtx_Format format, 534 | bool cubemap, 535 | uint32_t const *mipmapsizes, 536 | void const **mipmaps); 537 | 538 | #ifdef TINYKTX2_IMPLEMENTATION 539 | 540 | typedef struct TinyKtx2_KeyValuePair { 541 | uint32_t size; 542 | } TinyKtx2_KeyValuePair; // followed by at least size bytes (aligned to 4) 543 | 544 | typedef struct TinyKtx2_HeaderV2 { 545 | uint8_t identifier[12]; 546 | TinyKtx_Format vkFormat; 547 | uint32_t pixelWidth; 548 | uint32_t pixelHeight; 549 | uint32_t pixelDepth; 550 | uint32_t arrayElementCount; 551 | uint32_t faceCount; 552 | uint32_t levelCount; 553 | uint32_t supercompressionScheme; 554 | 555 | uint32_t dfdByteOffset; 556 | uint32_t dfdByteLength; 557 | uint32_t kvdByteOffset; 558 | uint32_t kvdByteLength; 559 | uint64_t sgdByteOffset; 560 | uint64_t sgdByteLength; 561 | } TinyKtx2_Header; 562 | 563 | typedef struct TinyKtx2_Level { 564 | uint64_t byteOffset; 565 | uint64_t byteLength; 566 | uint64_t uncompressedByteLength; 567 | } TinyKtx2_Level; 568 | 569 | typedef enum TinyKtx2_SuperCompressionScheme { 570 | TKTX2_SUPERCOMPRESSION_NONE = 0, 571 | TKTX2_SUPERCOMPRESSION_CRN = 1, 572 | TKTX2_SUPERCOMPRESSION_ZLIB = 2, 573 | TKTX2_SUPERCOMPRESSION_ZSTD = 3, 574 | } TinyKtx2_SuperCompressionScheme; 575 | 576 | typedef struct TinyKtx2_Context { 577 | TinyKtx2_Callbacks callbacks; 578 | void *user; 579 | uint64_t headerPos; 580 | uint64_t firstImagePos; 581 | 582 | TinyKtx2_Header header; 583 | 584 | TinyKtx2_KeyValuePair const *keyData; 585 | bool headerValid; 586 | bool sameEndian; 587 | void* sgdData; 588 | 589 | TinyKtx2_Level levels[TINYKTX_MAX_MIPMAPLEVELS]; 590 | uint8_t const *mipmaps[TINYKTX_MAX_MIPMAPLEVELS]; 591 | 592 | } TinyKtx2_Context; 593 | 594 | 595 | static uint8_t TinyKtx2_fileIdentifier[12] = { 596 | 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x32, 0x30, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A 597 | }; 598 | 599 | static void TinyKtx2_NullErrorFunc(void *user, char const *msg) {} 600 | 601 | TinyKtx2_ContextHandle TinyKtx2_CreateContext(TinyKtx2_Callbacks const *callbacks, void *user) { 602 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) callbacks->alloc(user, sizeof(TinyKtx2_Context)); 603 | if (ctx == NULL) 604 | return NULL; 605 | 606 | memset(ctx, 0, sizeof(TinyKtx2_Context)); 607 | memcpy(&ctx->callbacks, callbacks, sizeof(TinyKtx2_Callbacks)); 608 | ctx->user = user; 609 | if (ctx->callbacks.error == NULL) { 610 | ctx->callbacks.error = &TinyKtx_NullErrorFunc; 611 | } 612 | 613 | if (ctx->callbacks.read == NULL) { 614 | ctx->callbacks.error(user, "TinyKtx must have read callback"); 615 | return NULL; 616 | } 617 | if (ctx->callbacks.alloc == NULL) { 618 | ctx->callbacks.error(user, "TinyKtx must have alloc callback"); 619 | return NULL; 620 | } 621 | if (ctx->callbacks.free == NULL) { 622 | ctx->callbacks.error(user, "TinyKtx must have free callback"); 623 | return NULL; 624 | } 625 | if (ctx->callbacks.seek == NULL) { 626 | ctx->callbacks.error(user, "TinyKtx must have seek callback"); 627 | return NULL; 628 | } 629 | if (ctx->callbacks.tell == NULL) { 630 | ctx->callbacks.error(user, "TinyKtx must have tell callback"); 631 | return NULL; 632 | } 633 | 634 | TinyKtx2_Reset(ctx); 635 | 636 | return ctx; 637 | } 638 | 639 | void TinyKtx2_DestroyContext(TinyKtx2_ContextHandle handle) { 640 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 641 | if (ctx == NULL) 642 | return; 643 | TinyKtx2_Reset(handle); 644 | 645 | ctx->callbacks.free(ctx->user, ctx); 646 | } 647 | 648 | void TinyKtx2_Reset(TinyKtx2_ContextHandle handle) { 649 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 650 | if (ctx == NULL) 651 | return; 652 | 653 | // backup user provided callbacks and data 654 | TinyKtx2_Callbacks callbacks; 655 | memcpy(&callbacks, &ctx->callbacks, sizeof(TinyKtx_Callbacks)); 656 | void *user = ctx->user; 657 | 658 | // free any super compression global data we've allocated 659 | if (ctx->sgdData != NULL) { 660 | callbacks.free(user, (void *) ctx->sgdData); 661 | } 662 | 663 | // free memory of sub data 664 | if (ctx->keyData != NULL) { 665 | callbacks.free(user, (void *) ctx->keyData); 666 | } 667 | 668 | for (int i = 0; i < TINYKTX_MAX_MIPMAPLEVELS; ++i) { 669 | if (ctx->mipmaps[i] != NULL) { 670 | callbacks.free(user, (void *) ctx->mipmaps[i]); 671 | } 672 | } 673 | 674 | // reset to default state 675 | memset(ctx, 0, sizeof(TinyKtx_Context)); 676 | memcpy(&ctx->callbacks, &callbacks, sizeof(TinyKtx_Callbacks)); 677 | ctx->user = user; 678 | 679 | } 680 | 681 | 682 | bool TinyKtx2_ReadHeader(TinyKtx_ContextHandle handle) { 683 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 684 | if (ctx == NULL) 685 | return false; 686 | 687 | 688 | ctx->headerPos = ctx->callbacks.tell(ctx->user); 689 | ctx->callbacks.read(ctx->user, &ctx->header, sizeof(TinyKtx2_Header)); 690 | 691 | if (memcmp(&ctx->header.identifier, TinyKtx2_fileIdentifier, 12) != 0) { 692 | ctx->callbacks.error(ctx->user, "Not a KTX V2 file or corrupted as identified isn't valid"); 693 | return false; 694 | } 695 | 696 | if (ctx->header.faceCount != 1 && ctx->header.faceCount != 6) { 697 | ctx->callbacks.error(ctx->user, "no. of Faces must be 1 or 6"); 698 | return false; 699 | } 700 | // cap level to max 701 | if(ctx->header.levelCount >= TINYKTX2_MAX_MIPMAPLEVELS) { 702 | ctx->header.levelCount = TINYKTX2_MAX_MIPMAPLEVELS; 703 | } 704 | // 0 level count means wants mip maps from the 1 stored 705 | uint32_t const levelCount = ctx->header.levelCount ? ctx->header.levelCount : 1; 706 | 707 | ctx->callbacks.read(ctx->user, &ctx->levels, sizeof(TinyKtx2_Header) * levelCount); 708 | 709 | if(ctx->header.sgdByteLength > 0) { 710 | ctx->sgdData = ctx->callbacks.alloc(ctx->user, ctx->header.sgdByteLength); 711 | ctx->callbacks.seek(ctx->user, ctx->header.sgdByteOffset); 712 | ctx->callbacks.read(ctx->user, ctx->sgdData, ctx->header.sgdByteLength); 713 | } 714 | 715 | return true; 716 | } 717 | 718 | bool TinyKtx2_GetValue(TinyKtx2_ContextHandle handle, char const *key, void const **value) { 719 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 720 | if (ctx == NULL) 721 | return false; 722 | if (ctx->headerValid == false) { 723 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 724 | return false; 725 | } 726 | 727 | if (ctx->keyData == NULL) { 728 | ctx->callbacks.error(ctx->user, "No key value data in this KTX"); 729 | return false; 730 | } 731 | 732 | TinyKtx2_KeyValuePair const *curKey = ctx->keyData; 733 | while (((uint8_t *) curKey - (uint8_t *) ctx->keyData) < ctx->header.bytesOfKeyValueData) { 734 | char const *kvp = (char const *) curKey; 735 | 736 | if (strcmp(kvp, key) == 0) { 737 | size_t sl = strlen(kvp); 738 | *value = (void const *) (kvp + sl); 739 | return true; 740 | } 741 | curKey = curKey + ((curKey->size + 3u) & ~3u); 742 | } 743 | return false; 744 | } 745 | 746 | bool TinyKtx2_Is1D(TinyKtx2_ContextHandle handle) { 747 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 748 | if (ctx == NULL) 749 | return false; 750 | if (ctx->headerValid == false) { 751 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 752 | return false; 753 | } 754 | return (ctx->header.pixelHeight <= 1) && (ctx->header.pixelDepth <= 1 ); 755 | } 756 | bool TinyKtx2_Is2D(TinyKtx_ContextHandle handle) { 757 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 758 | if (ctx == NULL) 759 | return false; 760 | if (ctx->headerValid == false) { 761 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 762 | return false; 763 | } 764 | 765 | return (ctx->header.pixelHeight > 1 && ctx->header.pixelDepth <= 1); 766 | } 767 | bool TinyKtx2_Is3D(TinyKtx2_ContextHandle handle) { 768 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 769 | if (ctx == NULL) 770 | return false; 771 | if (ctx->headerValid == false) { 772 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 773 | return false; 774 | } 775 | 776 | return (ctx->header.pixelHeight > 1 && ctx->header.pixelDepth > 1); 777 | } 778 | 779 | bool TinyKtx2_IsCubemap(TinyKtx2_ContextHandle handle) { 780 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 781 | if (ctx == NULL) 782 | return false; 783 | if (ctx->headerValid == false) { 784 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 785 | return false; 786 | } 787 | 788 | return (ctx->header.numberOfFaces == 6); 789 | } 790 | bool TinyKtx2_IsArray(TinyKtx2_ContextHandle handle) { 791 | TinyKtx_Context *ctx = (TinyKtx2_Context *) handle; 792 | if (ctx == NULL) 793 | return false; 794 | if (ctx->headerValid == false) { 795 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 796 | return false; 797 | } 798 | 799 | return (ctx->header.numberOfArrayElements > 1); 800 | } 801 | 802 | bool TinyKtx2_Dimensions(TinyKtx2_ContextHandle handle, 803 | uint32_t *width, 804 | uint32_t *height, 805 | uint32_t *depth, 806 | uint32_t *slices) { 807 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 808 | if (ctx == NULL) 809 | return false; 810 | if (ctx->headerValid == false) { 811 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 812 | return false; 813 | } 814 | if (width) 815 | *width = ctx->header.pixelWidth; 816 | if (height) 817 | *height = ctx->header.pixelWidth; 818 | if (depth) 819 | *depth = ctx->header.pixelDepth; 820 | if (slices) 821 | *slices = ctx->header.numberOfArrayElements; 822 | return true; 823 | } 824 | 825 | uint32_t TinyKtx2_Width(TinyKtx2_ContextHandle handle) { 826 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 827 | if (ctx == NULL) 828 | return 0; 829 | if (ctx->headerValid == false) { 830 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 831 | return 0; 832 | } 833 | return ctx->header.pixelWidth; 834 | 835 | } 836 | 837 | uint32_t TinyKtx2_Height(TinyKtx2_ContextHandle handle) { 838 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 839 | if (ctx == NULL) 840 | return 0; 841 | if (ctx->headerValid == false) { 842 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 843 | return 0; 844 | } 845 | 846 | return ctx->header.pixelHeight; 847 | } 848 | 849 | uint32_t TinyKtx2_Depth(TinyKtx2_ContextHandle handle) { 850 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 851 | if (ctx == NULL) 852 | return 0; 853 | if (ctx->headerValid == false) { 854 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 855 | return 0; 856 | } 857 | return ctx->header.pixelDepth; 858 | } 859 | 860 | uint32_t TinyKtx2_ArraySlices(TinyKtx2_ContextHandle handle) { 861 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 862 | if (ctx == NULL) 863 | return 0; 864 | if (ctx->headerValid == false) { 865 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 866 | return 0; 867 | } 868 | 869 | return ctx->header.numberOfArrayElements; 870 | } 871 | 872 | uint32_t TinyKtx2_NumberOfMipmaps(TinyKtx2_ContextHandle handle) { 873 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 874 | if (ctx == NULL) 875 | return 0; 876 | if (ctx->headerValid == false) { 877 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 878 | return 0; 879 | } 880 | return ctx->header.levelCount ? ctx->header.levelCount : 1; 881 | } 882 | 883 | bool TinyKtx2_NeedsGenerationOfMipmaps(TinyKtx2_ContextHandle handle) { 884 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 885 | if (ctx == NULL) 886 | return false; 887 | if (ctx->headerValid == false) { 888 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 889 | return false; 890 | } 891 | 892 | return ctx->header.levelCount == 0; 893 | } 894 | 895 | uint32_t TinyKtx_ImageSize(TinyKtx_ContextHandle handle, uint32_t mipmaplevel) { 896 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 897 | 898 | if (mipmaplevel >= ctx->header.levelCount) { 899 | ctx->callbacks.error(ctx->user, "Invalid mipmap level"); 900 | return 0; 901 | } 902 | if (mipmaplevel >= TINYKTX2_MAX_MIPMAPLEVELS) { 903 | ctx->callbacks.error(ctx->user, "Invalid mipmap level"); 904 | return 0; 905 | } 906 | 907 | return ctx->levels[mipmaplevel].uncompressedByteLength; 908 | } 909 | 910 | void const *TinyKtx2_ImageRawData(TinyKtx2_ContextHandle handle, uint32_t mipmaplevel) { 911 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 912 | if (ctx == NULL) 913 | return NULL; 914 | 915 | if (ctx->headerValid == false) { 916 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 917 | return NULL; 918 | } 919 | 920 | if (mipmaplevel >= ctx->header.levelCount) { 921 | ctx->callbacks.error(ctx->user, "Invalid mipmap level"); 922 | return NULL; 923 | } 924 | 925 | if (mipmaplevel >= TINYKTX2_MAX_MIPMAPLEVELS) { 926 | ctx->callbacks.error(ctx->user, "Invalid mipmap level"); 927 | return NULL; 928 | } 929 | 930 | if (ctx->mipmaps[mipmaplevel] != NULL) 931 | return ctx->mipmaps[mipmaplevel]; 932 | 933 | TinyKtx_Level* lvl = &ctx->levels[mipmaplevel]; 934 | if (lvl->byteLength == 0 || lvl->uncompressedByteLength == 0) 935 | return NULL; 936 | 937 | // allocate decompressed buffer 938 | ctx->mipmaps[mipmaplevel] = (uint8_t const*) ctx->callbacks.alloc(ctx->user, lvl->uncompressedByteLength); 939 | if (ctx->mipmaps[mipmaplevel] == NULL) 940 | return NULL; 941 | 942 | // handle no super compression first (save an buffer allocation) 943 | if(ctx->header.supercompressionScheme == TKTX2_SUPERCOMPRESSION_NONE) { 944 | if(lvl->uncompressedByteLength != lvl->byteLength) { 945 | ctx->callbacks.error(ctx->user, "mipmap image data has no super compression but compressed and uncompressed data sizes are different"); 946 | ctx->callbacks.free(ctx->user, (void*)ctx->mipmaps[mipmaplevel]); 947 | return NULL; 948 | } 949 | ctx->callbacks.seek(ctx->user, lvl->byteOffset); 950 | ctx->callbacks.read(ctx->user, (void *) ctx->mipmaps[mipmaplevel], lvl->byteLength); 951 | return ctx->mipmaps[mipmaplevel]; 952 | } 953 | 954 | // this data is super compressed, we need to see if the user provided a decompressor and if so use it 955 | 956 | TinyKtx_SuperDecompress decompressor = NULL; 957 | // see if the user provided the decompressor we need 958 | for(size_t i = 0; i < ctx->callbacks.numSuperDecompressors;++i) { 959 | if(ctx->callbacks.superDecompressors[i].superId == ctx->headerV2.supercompressionScheme) { 960 | decompressor = ctx->callbacks.superDecompressors[i].decompressor; 961 | } 962 | } 963 | if(decompressor == NULL) { 964 | ctx->callbacks.error(ctx->user, "user did not provide a decompressor for use with this type of super decompressor"); 965 | ctx->callbacks.free(ctx->user, (void*)ctx->mipmaps[mipmaplevel]); 966 | return NULL; 967 | } 968 | 969 | // read the compressed data into its own buffer (free once decompression has occured) 970 | uint8_t const* compressedBuffer = (uint8_t const*)ctx->callbacks.alloc(ctx->user, lvl->byteLength); 971 | if(compressedBuffer == NULL) { 972 | ctx->callbacks.free(ctx->user, (void*)ctx->mipmaps[mipmaplevel]); 973 | return NULL; 974 | } 975 | ctx->callbacks.seek(ctx->user, lvl->byteOffset); 976 | ctx->callbacks.read(ctx->user, (void *) compressedBuffer, lvl->byteLength); 977 | bool okay = decompressor(ctx->user, ctx->sgdData, compressedBuffer, lvl->byteLength, ctx->mipmaps[mipmaplevel], lvl->uncompressedByteLength); 978 | 979 | if(!okay) { 980 | ctx->callbacks.error(ctx->user, "user decompressor failed"); 981 | ctx->callbacks.free(ctx->user, (void *) compressedBuffer); 982 | ctx->callbacks.free(ctx->user, (void *) ctx->mipmaps[mipmaplevel]); 983 | return NULL; 984 | } 985 | 986 | ctx->callbacks.free(ctx->user, (void *) compressedBuffer); 987 | return ctx->mipmaps[mipmaplevel]; 988 | 989 | } 990 | 991 | TinyKtx_Format TinyKtx2_GetFormat(TinyKtx2_ContextHandle handle) { 992 | TinyKtx2_Context *ctx = (TinyKtx2_Context *) handle; 993 | if (ctx == NULL) 994 | return TKTX_UNDEFINED; 995 | 996 | if (ctx->headerValid == false) { 997 | ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid"); 998 | return TKTX_UNDEFINED; 999 | } 1000 | // TODO handle DFD only described formats (VK_FORMAT_UNDEFINED) 1001 | return (TinyKtx_Format)ctx->header.vkFormat; 1002 | } 1003 | static uint32_t TinyKtx2_MipMapReduce(uint32_t value, uint32_t mipmaplevel) { 1004 | 1005 | // handle 0 being passed in 1006 | if(value <= 1) return 1; 1007 | 1008 | // there are better ways of doing this (log2 etc.) but this doesn't require any 1009 | // dependecies and isn't used enough to matter imho 1010 | for (uint32_t i = 0u; i < mipmaplevel;++i) { 1011 | if(value <= 1) return 1; 1012 | value = value / 2; 1013 | } 1014 | return value; 1015 | } 1016 | 1017 | 1018 | 1019 | bool TinyKtx2_WriteImage(TinyKtx2_WriteCallbacks const *callbacks, 1020 | void *user, 1021 | uint32_t width, 1022 | uint32_t height, 1023 | uint32_t depth, 1024 | uint32_t slices, 1025 | uint32_t mipmaplevels, 1026 | TinyKtx_Format format, 1027 | bool cubemap, 1028 | uint32_t const *mipmapsizes, 1029 | void const **mipmaps) { 1030 | ASSERT(false); 1031 | } 1032 | #endif 1033 | 1034 | #ifdef __cplusplus 1035 | }; 1036 | #endif 1037 | 1038 | #endif // end header 1039 | /* 1040 | MIT License 1041 | 1042 | Copyright (c) 2019 DeanoC 1043 | 1044 | Permission is hereby granted, free of charge, to any person obtaining a copy 1045 | of this software and associated documentation files (the "Software"), to deal 1046 | in the Software without restriction, including without limitation the rights 1047 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1048 | copies of the Software, and to permit persons to whom the Software is 1049 | furnished to do so, subject to the following conditions: 1050 | 1051 | The above copyright notice and this permission notice shall be included in all 1052 | copies or substantial portions of the Software. 1053 | 1054 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1055 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1056 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1057 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1058 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1059 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1060 | SOFTWARE. 1061 | */ 1062 | -------------------------------------------------------------------------------- /src/tinyktx.c: -------------------------------------------------------------------------------- 1 | #define TINYKTX_IMPLEMENTATION 2 | #include "tiny_imageformat/tinyimageformat_base.h" 3 | #include "tiny_ktx/tinyktx.h" 4 | -------------------------------------------------------------------------------- /tests/runner.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_RUNNER 2 | #include "al2o3_catch2/catch2.hpp" 3 | #include "utils_simple_logmanager/logmanager.h" 4 | 5 | int main(int argc, char const *argv[]) { 6 | auto logger = SimpleLogManager_Alloc(); 7 | 8 | auto ret = Catch::Session().run(argc, (char **) argv); 9 | 10 | SimpleLogManager_Free(logger); 11 | 12 | return ret; 13 | } 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/test_tinyktx.cpp: -------------------------------------------------------------------------------- 1 | #include "tiny_ktx/tinyktx.h" 2 | #include "al2o3_platform/platform.h" 3 | #include "al2o3_memory/memory.h" 4 | #include "al2o3_catch2/catch2.hpp" 5 | #include "al2o3_vfile/vfile.hpp" 6 | #include "al2o3_stb/stb_image.h" 7 | #include "al2o3_os/filesystem.h" 8 | 9 | static const char* gBasePath = "input/testimages"; 10 | 11 | #define SET_PATH() char existCurDir[1024]; \ 12 | Os_GetCurrentDir(existCurDir, sizeof(existCurDir)); \ 13 | char path[2048]; \ 14 | strcpy(path, existCurDir); \ 15 | strcat(path, gBasePath); \ 16 | Os_SetCurrentDir(path) 17 | #define RESTORE_PATH() Os_SetCurrentDir(existCurDir) 18 | 19 | static void tinyktxCallbackError(void *user, char const *msg) { 20 | LOGERROR("Tiny_Ktx ERROR: %s", msg); 21 | } 22 | static void *tinyktxCallbackAlloc(void *user, size_t size) { 23 | return MEMORY_MALLOC(size); 24 | } 25 | static void tinyktxCallbackFree(void *user, void *data) { 26 | MEMORY_FREE(data); 27 | } 28 | static size_t tinyktxCallbackRead(void *user, void* data, size_t size) { 29 | auto handle = (VFile_Handle) user; 30 | return VFile_Read(handle, data, size); 31 | } 32 | static bool tinyktxCallbackSeek(void *user, int64_t offset) { 33 | auto handle = (VFile_Handle) user; 34 | return VFile_Seek(handle, offset, VFile_SD_Begin); 35 | } 36 | static int64_t tinyktxCallbackTell(void *user) { 37 | auto handle = (VFile_Handle) user; 38 | return VFile_Tell(handle); 39 | } 40 | static int stbIoCallbackRead(void *user, char *data, int size) { 41 | auto handle = (VFile_Handle) user; 42 | return (int) VFile_Read(handle, data, size); 43 | } 44 | static void stbIoCallbackSkip(void *user, int n) { 45 | auto handle = (VFile_Handle) user; 46 | VFile_Seek(handle, n, VFile_SD_Current); 47 | } 48 | static int stbIoCallbackEof(void *user) { 49 | auto handle = (VFile_Handle) user; 50 | return VFile_IsEOF(handle); 51 | } 52 | 53 | 54 | TEST_CASE("Check Files", "[TinyKtx Loader]") { 55 | SET_PATH(); 56 | #define CHK_FILE_EXISTS(filename) \ 57 | { VFile::ScopedFile reffile = VFile::File::FromFile(filename, Os_FM_ReadBinary); \ 58 | if(!reffile) { \ 59 | LOGERROR("This must run in the directory input/testimages/ that can be got from http://github/DeanoC/taylor_imagetests"); \ 60 | REQUIRE(reffile); \ 61 | } } 62 | 63 | CHK_FILE_EXISTS("rgb-reference.ktx"); 64 | CHK_FILE_EXISTS("rgb.ppm"); 65 | CHK_FILE_EXISTS("luminance-reference-metadata.ktx"); 66 | CHK_FILE_EXISTS("luminance.pgm"); 67 | CHK_FILE_EXISTS("level0.ppm"); 68 | CHK_FILE_EXISTS("level1.ppm"); 69 | CHK_FILE_EXISTS("level2.ppm"); 70 | CHK_FILE_EXISTS("level3.ppm"); 71 | CHK_FILE_EXISTS("level4.ppm"); 72 | CHK_FILE_EXISTS("level5.ppm"); 73 | CHK_FILE_EXISTS("level6.ppm"); 74 | 75 | #undef CHK_FILE_EXISTS 76 | 77 | } 78 | 79 | TEST_CASE("TinyKtx Create/Destroy Context", "[TinyKtx Loader]") { 80 | TinyKtx_Callbacks callbacks { 81 | &tinyktxCallbackError, 82 | &tinyktxCallbackAlloc, 83 | &tinyktxCallbackFree, 84 | tinyktxCallbackRead, 85 | &tinyktxCallbackSeek, 86 | &tinyktxCallbackTell 87 | }; 88 | 89 | VFile::ScopedFile file = VFile::File::FromFile("rgb-reference.ktx", Os_FM_ReadBinary); 90 | if(!file) { 91 | LOGERROR("This must run in the directory input/testimages/ that can be got from http://github/DeanoC/taylor_imagetests"); 92 | REQUIRE(file); 93 | } 94 | 95 | auto ctx = TinyKtx_CreateContext(&callbacks, (void*)file.owned); 96 | REQUIRE(ctx); 97 | 98 | TinyKtx_DestroyContext(ctx); 99 | } 100 | 101 | TEST_CASE("TinyKtx readheader & dimensions", "[TinyKtx Loader]") { 102 | TinyKtx_Callbacks callbacks { 103 | &tinyktxCallbackError, 104 | &tinyktxCallbackAlloc, 105 | &tinyktxCallbackFree, 106 | tinyktxCallbackRead, 107 | &tinyktxCallbackSeek, 108 | &tinyktxCallbackTell 109 | }; 110 | 111 | VFile::ScopedFile file = VFile::File::FromFile("rgb-reference.ktx", Os_FM_ReadBinary); 112 | REQUIRE(file); 113 | auto ctx = TinyKtx_CreateContext(&callbacks, (void*)file.owned); 114 | REQUIRE(TinyKtx_ReadHeader(ctx)); 115 | 116 | auto w = TinyKtx_Width(ctx); 117 | auto h = TinyKtx_Height(ctx); 118 | auto d = TinyKtx_Depth(ctx); 119 | auto s = TinyKtx_ArraySlices(ctx); 120 | 121 | uint32_t wd, hd, dd, sd; 122 | TinyKtx_Dimensions(ctx, &wd, &hd, &dd, &sd); 123 | 124 | REQUIRE(w == wd); 125 | REQUIRE(h == hd); 126 | REQUIRE(d == dd); 127 | REQUIRE(s == sd); 128 | 129 | REQUIRE(w == 128); 130 | REQUIRE(h == 128); 131 | REQUIRE(d == 0); 132 | REQUIRE(s == 0); 133 | 134 | REQUIRE(TinyKtx_NumberOfMipmaps(ctx) == 1); 135 | 136 | TinyKtx_DestroyContext(ctx); 137 | } 138 | 139 | static bool CmpFlipped( uint32_t w, 140 | uint32_t h, 141 | uint8_t pixByte, 142 | uint32_t srcStride, 143 | uint32_t dstStride, 144 | uint8_t const* src, 145 | uint8_t const* dst) { 146 | 147 | dst = dst + ((h-1) * dstStride); 148 | 149 | for (auto i = 0u; i < h; ++i) { 150 | uint8_t const *srcBackup = src; 151 | uint8_t const *dstBackup = dst; 152 | 153 | for (auto j = 0u; j < w; ++j) { 154 | for(auto p = 0u; p < pixByte;++p) { 155 | if(src[p] != dst[p]) return false; 156 | } 157 | src += pixByte; 158 | dst += pixByte; 159 | } 160 | 161 | src = srcBackup + srcStride; 162 | dst = dstBackup - dstStride; 163 | } 164 | 165 | return true; 166 | } 167 | 168 | static bool CmpSame( uint32_t w, 169 | uint32_t h, 170 | uint8_t pixByte, 171 | uint32_t srcStride, 172 | uint32_t dstStride, 173 | uint8_t const* src, 174 | uint8_t const* dst) { 175 | 176 | for (auto i = 0u; i < h; ++i) { 177 | uint8_t const *srcBackup = src; 178 | uint8_t const *dstBackup = dst; 179 | 180 | for (auto j = 0u; j < w; ++j) { 181 | for(auto p = 0u; p < pixByte;++p) { 182 | if(src[p] != dst[p]) return false; 183 | } 184 | src += pixByte; 185 | dst += pixByte; 186 | } 187 | 188 | src = srcBackup + srcStride; 189 | dst = dstBackup + dstStride; 190 | } 191 | 192 | return true; 193 | } 194 | 195 | TEST_CASE("TinyKtx rgb-reference okay", "[TinyKtx Loader]") { 196 | TinyKtx_Callbacks callbacks { 197 | &tinyktxCallbackError, 198 | &tinyktxCallbackAlloc, 199 | &tinyktxCallbackFree, 200 | tinyktxCallbackRead, 201 | &tinyktxCallbackSeek, 202 | &tinyktxCallbackTell 203 | }; 204 | 205 | stbi_io_callbacks stbi_callbacks{ 206 | &stbIoCallbackRead, 207 | &stbIoCallbackSkip, 208 | &stbIoCallbackEof 209 | }; 210 | 211 | VFile::ScopedFile file = VFile::File::FromFile("rgb-reference.ktx", Os_FM_ReadBinary); 212 | VFile::ScopedFile reffile = VFile::File::FromFile("rgb.ppm", Os_FM_ReadBinary); 213 | REQUIRE(file); 214 | REQUIRE(reffile); 215 | 216 | auto ctx = TinyKtx_CreateContext(&callbacks, (void*)file.owned); 217 | 218 | REQUIRE(TinyKtx_ReadHeader(ctx)); 219 | 220 | size_t origin = VFile_Tell(reffile); 221 | 222 | int w = 0, h = 0, cmp = 0; 223 | stbi_info_from_callbacks(&stbi_callbacks, (void*)reffile.owned, &w, &h, &cmp); 224 | REQUIRE(w == TinyKtx_Width(ctx)); 225 | REQUIRE(h == TinyKtx_Height(ctx)); 226 | REQUIRE(TinyKtx_GetFormat(ctx) == TKTX_R8G8B8_UNORM); 227 | 228 | VFile_Seek(reffile, origin, VFile_SD_Begin); 229 | stbi_uc *refdata = stbi_load_from_callbacks(&stbi_callbacks, (void*)reffile.owned, &w, &h, &cmp, cmp); 230 | REQUIRE(refdata); 231 | 232 | auto ktxdata = (uint8_t const*)TinyKtx_ImageRawData(ctx, 0); 233 | REQUIRE(CmpFlipped(w, h, 3, w * cmp, w * cmp, refdata, ktxdata)); 234 | 235 | MEMORY_FREE((void*)refdata); 236 | TinyKtx_DestroyContext(ctx); 237 | } 238 | 239 | TEST_CASE("TinyKtx luminance-reference okay", "[TinyKtx Loader]") { 240 | TinyKtx_Callbacks callbacks { 241 | &tinyktxCallbackError, 242 | &tinyktxCallbackAlloc, 243 | &tinyktxCallbackFree, 244 | tinyktxCallbackRead, 245 | &tinyktxCallbackSeek, 246 | &tinyktxCallbackTell 247 | }; 248 | 249 | stbi_io_callbacks stbi_callbacks{ 250 | &stbIoCallbackRead, 251 | &stbIoCallbackSkip, 252 | &stbIoCallbackEof 253 | }; 254 | 255 | VFile::ScopedFile file = VFile::File::FromFile("luminance-reference-metadata.ktx", Os_FM_ReadBinary); 256 | VFile::ScopedFile reffile = VFile::File::FromFile("luminance.pgm", Os_FM_ReadBinary); 257 | REQUIRE(file); 258 | REQUIRE(reffile); 259 | 260 | auto ctx = TinyKtx_CreateContext(&callbacks, (void*)file.owned); 261 | 262 | REQUIRE(TinyKtx_ReadHeader(ctx)); 263 | 264 | size_t origin = VFile_Tell(reffile); 265 | 266 | int w = 0, h = 0, cmp = 0; 267 | stbi_info_from_callbacks(&stbi_callbacks, (void*)reffile.owned, &w, &h, &cmp); 268 | REQUIRE(w == TinyKtx_Width(ctx)); 269 | REQUIRE(h == TinyKtx_Height(ctx)); 270 | REQUIRE(TinyKtx_GetFormat(ctx) == TKTX_R8_UNORM); 271 | REQUIRE(cmp == 1); 272 | 273 | VFile_Seek(reffile, origin, VFile_SD_Begin); 274 | stbi_uc *refdata = stbi_load_from_callbacks(&stbi_callbacks, (void*)reffile.owned, &w, &h, &cmp, cmp); 275 | REQUIRE(refdata); 276 | 277 | auto ktxdata = (uint8_t const*)TinyKtx_ImageRawData(ctx, 0); 278 | REQUIRE(CmpSame(w, h, 1, w * cmp, w * cmp, refdata, ktxdata)); 279 | 280 | MEMORY_FREE((void*)refdata); 281 | TinyKtx_DestroyContext(ctx); 282 | } 283 | 284 | TEST_CASE("TinyKtx git hub #2 (image size before image raw data broken) fix test", "[TinyKtx Loader]") { 285 | TinyKtx_Callbacks callbacks { 286 | &tinyktxCallbackError, 287 | &tinyktxCallbackAlloc, 288 | &tinyktxCallbackFree, 289 | tinyktxCallbackRead, 290 | &tinyktxCallbackSeek, 291 | &tinyktxCallbackTell 292 | }; 293 | 294 | stbi_io_callbacks stbi_callbacks{ 295 | &stbIoCallbackRead, 296 | &stbIoCallbackSkip, 297 | &stbIoCallbackEof 298 | }; 299 | 300 | VFile::ScopedFile file = VFile::File::FromFile("rgb-reference.ktx", Os_FM_ReadBinary); 301 | VFile::ScopedFile reffile = VFile::File::FromFile("rgb.ppm", Os_FM_ReadBinary); 302 | REQUIRE(file); 303 | REQUIRE(reffile); 304 | auto ctx = TinyKtx_CreateContext(&callbacks, (void*)file.owned); 305 | 306 | REQUIRE(TinyKtx_ReadHeader(ctx)); 307 | 308 | 309 | size_t origin = VFile_Tell(reffile); 310 | 311 | int w = 0, h = 0, cmp = 0; 312 | stbi_info_from_callbacks(&stbi_callbacks, (void*)reffile.owned, &w, &h, &cmp); 313 | 314 | uint64_t memoryRequirement = sizeof(stbi_uc) * w * h * cmp; 315 | 316 | // perform an image size op, this shouldn't break the later image raw data if this if fixed 317 | REQUIRE(memoryRequirement == TinyKtx_ImageSize(ctx, 0)); 318 | 319 | VFile_Seek(reffile, origin, VFile_SD_Begin); 320 | stbi_uc const *refdata = stbi_load_from_callbacks(&stbi_callbacks, (void*)reffile.owned, &w, &h, &cmp, cmp); 321 | REQUIRE(refdata); 322 | 323 | auto ktxdata = (uint8_t const*)TinyKtx_ImageRawData(ctx, 0); 324 | REQUIRE(CmpFlipped(w, h, 3, w * cmp, w * cmp, refdata, ktxdata)); 325 | 326 | MEMORY_FREE((void*)refdata); 327 | TinyKtx_DestroyContext(ctx); 328 | } 329 | 330 | TEST_CASE("TinyKtx mipmap reference check", "[TinyKtx Loader]") { 331 | TinyKtx_Callbacks callbacks { 332 | &tinyktxCallbackError, 333 | &tinyktxCallbackAlloc, 334 | &tinyktxCallbackFree, 335 | tinyktxCallbackRead, 336 | &tinyktxCallbackSeek, 337 | &tinyktxCallbackTell 338 | }; 339 | 340 | stbi_io_callbacks stbi_callbacks{ 341 | &stbIoCallbackRead, 342 | &stbIoCallbackSkip, 343 | &stbIoCallbackEof 344 | }; 345 | 346 | VFile::ScopedFile file = VFile::File::FromFile("rgb-mipmap-reference.ktx", Os_FM_ReadBinary); 347 | VFile::ScopedFile reffile[7] { 348 | VFile::File::FromFile("level0.ppm", Os_FM_ReadBinary), 349 | VFile::File::FromFile("level1.ppm", Os_FM_ReadBinary), 350 | VFile::File::FromFile("level2.ppm", Os_FM_ReadBinary), 351 | VFile::File::FromFile("level3.ppm", Os_FM_ReadBinary), 352 | VFile::File::FromFile("level4.ppm", Os_FM_ReadBinary), 353 | VFile::File::FromFile("level5.ppm", Os_FM_ReadBinary), 354 | VFile::File::FromFile("level6.ppm", Os_FM_ReadBinary), 355 | }; 356 | REQUIRE(file); 357 | 358 | auto ctx = TinyKtx_CreateContext(&callbacks, (void*)file.owned); 359 | REQUIRE(TinyKtx_ReadHeader(ctx)); 360 | 361 | REQUIRE(TinyKtx_NumberOfMipmaps(ctx) == 7); 362 | 363 | for (auto i = 0u; i < 7; ++i) { 364 | size_t origin = VFile_Tell(reffile[i]); 365 | int w = 0, h = 0, cmp = 0; 366 | 367 | stbi_info_from_callbacks(&stbi_callbacks, (void*)reffile[i].owned, &w, &h, &cmp); 368 | VFile_Seek(reffile[i], origin, VFile_SD_Begin); 369 | stbi_uc const *refdata = stbi_load_from_callbacks(&stbi_callbacks, (void*)reffile[i].owned, &w, &h, &cmp, cmp); 370 | REQUIRE(refdata); 371 | 372 | uint32_t const srcStride = w * cmp; 373 | uint32_t dstStride = srcStride; 374 | 375 | if( i < 5) { 376 | uint64_t const memoryRequirement = sizeof(stbi_uc) * w * h * cmp; 377 | REQUIRE(memoryRequirement == TinyKtx_ImageSize(ctx, i)); 378 | REQUIRE(!TinyKtx_IsMipMapLevelUnpacked(ctx,i)); 379 | } else { 380 | REQUIRE(TinyKtx_IsMipMapLevelUnpacked(ctx,i)); 381 | dstStride = TinyKtx_UnpackedRowStride(ctx,i); 382 | if(i == 5) { 383 | REQUIRE(dstStride == 8); 384 | } else if(i == 6) { 385 | REQUIRE(dstStride == 4); 386 | } 387 | } 388 | 389 | auto ktxdata = (uint8_t const*)TinyKtx_ImageRawData(ctx, i); 390 | REQUIRE(CmpFlipped(w, h, 3, srcStride, dstStride, refdata, ktxdata)); 391 | MEMORY_FREE((void*)refdata); 392 | } 393 | 394 | TinyKtx_DestroyContext(ctx); 395 | } -------------------------------------------------------------------------------- /tests/test_tinyktx_tinyimageformat.cpp: -------------------------------------------------------------------------------- 1 | #include "al2o3_platform/platform.h" 2 | #include "tiny_imageformat/tinyimageformat_base.h" 3 | #include "tiny_ktx/tinyktx.h" 4 | --------------------------------------------------------------------------------