├── .gitignore ├── LICENSE ├── README.md ├── ctexview ├── compile-shaders.bat ├── ctexview.c ├── ctexview.ico ├── quad.frag ├── quad.vert ├── quad_cubemap_glsl.frag.h ├── quad_cubemap_hlsl.frag.h ├── quad_cubemap_metal.frag.h ├── quad_glsl.frag.h ├── quad_glsl.vert.h ├── quad_hlsl.frag.h ├── quad_hlsl.vert.h ├── quad_metal.frag.h ├── quad_metal.vert.h ├── sokol_app.h ├── sokol_debugtext.h ├── sokol_gfx.h └── sokol_glue.h └── dds-ktx.h /.gitignore: -------------------------------------------------------------------------------- 1 | # External junk 2 | .DS_Store 3 | _ReSharper* 4 | *.opensdf 5 | *.sdf 6 | *.dir 7 | *.suo 8 | *.user 9 | *.bak 10 | *.scor 11 | *.scor.* 12 | Win32 13 | Win64 14 | Debug 15 | Release 16 | Profile 17 | Development 18 | Obj 19 | Bin 20 | Build 21 | Lib 22 | .tags 23 | .tags_sorted_by_file 24 | *.lnk 25 | ipch 26 | __pycache__ 27 | Thumbs.db 28 | .build* 29 | .downloads 30 | .clangd 31 | *.obj 32 | *.exe 33 | *.pdb 34 | *.dll 35 | *.o 36 | .vs 37 | xcuserdata 38 | *imgui.ini 39 | *.tmp 40 | /*.ini 41 | .cache 42 | 43 | # build analyzer 44 | .vcperf 45 | *.etl 46 | StructLayoutSettings.json 47 | 48 | 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2018, Sepehr Taghdisian 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## dds-ktx: Portable single header DDS/KTX reader for C/C++ 2 | [@septag](https://twitter.com/septagh) 3 | 4 | - Parses from memory blob. No allocations 5 | - No dependencies 6 | - Single-header for easy integration 7 | - Overridable libc functions 8 | 9 | ### Build Example (ctexview) 10 | [**ctexview**](ctexview/ctexview.c) is a tiny ddx-ktx viewer that can be built on linux/mac and windows. To build it just compile the single file with your compiler. 11 | 12 | **Windows:** 13 | ``` 14 | cl ctexview.c /O2 15 | ``` 16 | 17 | **Linuxx** 18 | ``` 19 | gcc ctexview.c -O2 -lGL -ldl -lX11 -lXi -lXcursor -lm -o ctexview 20 | ``` 21 | 22 | **MacOS** 23 | ``` 24 | clang -framework Foundation -framework CoreServices -framework CoreFoundation -O2 -fobjc-arc -x objective-c -fmodules -x objective-c ctexview.c -o ./ctexview 25 | ``` 26 | 27 | to view images just provide the image path as an argument: 28 | 29 | ``` 30 | ctexview [dds_or_ktx_image_file_path] 31 | ``` 32 | 33 | Used open-source libraries for app creation/graphics: [**Sokol**](https://github.com/floooh/sokol) 34 | 35 | **Keys:** 36 | 37 | - UP/DOWN: change current mipmap 38 | - Apostrophe: change text color 39 | - F: Next cube-map face 40 | - R: Toggle Red channel 41 | - G: Toggle Green channel 42 | - B: Toggle Blue channel 43 | - A: Toggle Alpha channel 44 | 45 | ### Usage 46 | In this example, a simple 2D texture is parsed and created using OpenGL 47 | 48 | ```c 49 | #define DDSKTX_IMPLEMENT 50 | #include "dds-ktx.h" 51 | 52 | int size; 53 | void* dds_data = load_file("test.dds", &size); 54 | assert(dds_data); 55 | ddsktx_texture_info tc = {0}; 56 | GLuint tex = 0; 57 | if (ddsktx_parse(&tc, dds_data, size, NULL)) { 58 | assert(tc.depth == 1); 59 | assert(!(tc.flags & STC_TEXTURE_FLAG_CUBEMAP)); 60 | assert(tc.num_layers == 1); 61 | 62 | //Create GPU texture from tc data 63 | glGenTextures(1, &tex); 64 | glActiveTexture(GL_TEXTURE0); 65 | glBindTexture(img->gl_target, tex); 66 | 67 | for (int mip = 0; mip < tc->num_mips; mip++) { 68 | ddsktx_sub_data sub_data; 69 | ddsktx_get_sub(&tc, &sub_data, dds_data, size, 0, 0, mip); 70 | // Fill/Set texture sub resource data (mips in this case) 71 | if (ddsktx_format_compressed(tc.format)) 72 | glCompressedTexImage2D(..); 73 | else 74 | glTexImage2D(..); 75 | } 76 | 77 | // Now we can delete file data 78 | free(dds_data); 79 | } 80 | ``` 81 | 82 | ### Links 83 | - [DdsKtxSharp](https://github.com/rds1983/DdsKtxSharp): C# port of dds-ktx by [Roman Shapiro](https://github.com/rds1983) 84 | 85 | ### TODO 86 | 87 | - Write KTX/DDS 88 | - Read KTX metadata. currently it just stores the offset/size to the metadata block 89 | 90 | ### Others 91 | 92 | - [stb_image](https://github.com/nothings/stb/blob/master/stb_image.h) - Single header library that loads images (.png, .jpg, .bmp, etc) 93 | - [bimg](https://github.com/bkaradzic/bimg) - Extensive C++ image library 94 | 95 | **NOTE**: Many parts of the code is taken from _bimg_ library. 96 | 97 | 98 | [License (BSD 2-clause)](https://github.com/septag/dds-ktx/blob/master/LICENSE) 99 | -------------------------------------------------------------------------- 100 | 101 | 102 | 103 | 104 | 105 | Copyright 2018 Sepehr Taghdisian. All rights reserved. 106 | 107 | https://github.com/septag/dds-ktx 108 | 109 | Redistribution and use in source and binary forms, with or without 110 | modification, are permitted provided that the following conditions are met: 111 | 112 | 1. Redistributions of source code must retain the above copyright notice, 113 | this list of conditions and the following disclaimer. 114 | 115 | 2. Redistributions in binary form must reproduce the above copyright notice, 116 | this list of conditions and the following disclaimer in the documentation 117 | and/or other materials provided with the distribution. 118 | 119 | THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR 120 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 121 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 122 | EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 123 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 124 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 125 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 126 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 127 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 128 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 129 | -------------------------------------------------------------------------------- /ctexview/compile-shaders.bat: -------------------------------------------------------------------------------- 1 | glslcc -i quad.vert --lang hlsl --bin -o quad_hlsl.vert.h --cvar quad 2 | glslcc -i quad.vert --lang glsl --flatten-ubos --profile 330 -o quad_glsl.vert.h --cvar quad 3 | glslcc -i quad.vert --lang metal -o quad_metal.vert.h --cvar quad 4 | 5 | glslcc -i quad.frag --lang hlsl --bin -o quad_hlsl.frag.h --cvar quad 6 | glslcc -i quad.frag --lang glsl --flatten-ubos --profile 330 -o quad_glsl.frag.h --cvar quad 7 | glslcc -i quad.frag --lang metal -o quad_metal.frag.h --cvar quad 8 | 9 | glslcc -i quad.frag --lang hlsl --bin -o quad_cubemap_hlsl.frag.h --cvar quad_cubemap --defines CUBEMAP 10 | glslcc -i quad.frag --lang glsl --flatten-ubos --profile 330 -o quad_cubemap_glsl.frag.h --cvar quad_cubemap --defines CUBEMAP 11 | glslcc -i quad.frag --lang metal -o quad_cubemap_metal.frag.h --cvar quad_cubemap --defines CUBEMAP 12 | -------------------------------------------------------------------------------- /ctexview/ctexview.c: -------------------------------------------------------------------------------- 1 | 2 | #if defined(_WIN32) || defined(_WIN64) 3 | # define SOKOL_D3D11 4 | # define _CRT_SECURE_NO_WARNINGS 5 | # include "quad_hlsl.vert.h" 6 | # include "quad_hlsl.frag.h" 7 | # include "quad_cubemap_hlsl.frag.h" 8 | # define SOKOL_LOG(s) OutputDebugStringA(s) 9 | #elif defined(__linux__) 10 | # include "quad_glsl.vert.h" 11 | # include "quad_glsl.frag.h" 12 | # include "quad_cubemap_glsl.frag.h" 13 | # define SOKOL_GLCORE33 14 | #elif defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) 15 | # include "quad_metal.vert.h" 16 | # include "quad_metal.frag.h" 17 | # include "quad_cubemap_metal.frag.h" 18 | # define SOKOL_METAL 19 | #endif 20 | 21 | #define SOKOL_IMPL 22 | #define DDSKTX_IMPLEMENT 23 | 24 | #define SOKOL_API_DECL static 25 | #include "sokol_app.h" 26 | #include "sokol_gfx.h" 27 | #include "sokol_glue.h" 28 | 29 | #define DDSKTX_API static 30 | #include "../dds-ktx.h" 31 | 32 | #ifndef __APPLE__ 33 | # include 34 | #endif 35 | #include 36 | #include 37 | #include 38 | 39 | #define SOKOL_DEBUGTEXT_IMPL 40 | #include "sokol_debugtext.h" 41 | 42 | #define FONT_SCALE 1.1f 43 | #define CHECKER_SIZE 8 44 | 45 | typedef struct uniforms_fs 46 | { 47 | float color[4]; 48 | float args[4]; 49 | } uniforms_fs; 50 | 51 | typedef struct uniforms_vs 52 | { 53 | float proj_mat[16]; 54 | } uniforms_vs; 55 | 56 | typedef struct vertex 57 | { 58 | float x; 59 | float y; 60 | float u; 61 | float v; 62 | float w; // reserved for cubemapping 63 | } vertex; 64 | 65 | 66 | typedef struct ctexview_state 67 | { 68 | sg_pass_action pass_action; 69 | void* file_data; 70 | int file_size; 71 | ddsktx_texture_info texinfo; 72 | sg_image tex; 73 | sg_shader shader; 74 | sg_shader shader_cubemap; 75 | sg_pipeline pip; 76 | sg_pipeline pip_cubemap; 77 | sg_pipeline pip_checker; 78 | sg_buffer vb; 79 | sg_buffer ib; 80 | sg_buffer vb_checker; 81 | sg_image checker; 82 | bool inv_text_color; 83 | uniforms_fs vars_fs; 84 | int cur_mip; 85 | int cur_slice; 86 | int cube_face; 87 | } ctexview_state; 88 | 89 | ctexview_state g_state; 90 | 91 | static const vertex k_vertices[] = { 92 | { -1.0f, -1.0f, 0.0f, 1.0f, 0 }, 93 | { 1.0f, -1.0f, 1.0f, 1.0f, 0 }, 94 | { 1.0f, 1.0f, 1.0f, 0.0f, 0 }, 95 | { -1.0f, 1.0f, 0.0f, 0.0f, 0 }, 96 | }; 97 | 98 | static const uint16_t k_indices[] = { 0, 2, 1, 2, 0, 3 }; 99 | 100 | static const char* k_cube_face_names[DDSKTX_CUBE_FACE_COUNT] = { 101 | "X+", 102 | "X-", 103 | "Y+", 104 | "Y-", 105 | "Z+", 106 | "Z-" 107 | }; 108 | 109 | #if defined(_WIN32) || defined(_WIN64) 110 | static desktop_size(int* width, int* height) 111 | { 112 | RECT desktop; 113 | const HWND hDesktop = GetDesktopWindow(); 114 | GetWindowRect(hDesktop, &desktop); 115 | *width = desktop.right; 116 | *height = desktop.bottom; 117 | } 118 | #endif 119 | 120 | static int nearest_pow2(int n) 121 | { 122 | n--; 123 | n |= n >> 1; 124 | n |= n >> 2; 125 | n |= n >> 4; 126 | n |= n >> 8; 127 | n |= n >> 16; 128 | n++; 129 | return n; 130 | } 131 | 132 | // https://en.wikipedia.org/wiki/Cube_mapping 133 | static void convert_cube_uv_to_xyz(int index, float u, float v, float* x, float* y, float* z) 134 | { 135 | // convert range 0 to 1 to -1 to 1 136 | float uc = 2.0f * u - 1.0f; 137 | float vc = 2.0f * v - 1.0f; 138 | switch (index) { 139 | case 0: *x = 1.0f; *y = vc; *z = -uc; break; // POSITIVE X 140 | case 1: *x = -1.0f; *y = vc; *z = uc; break; // NEGATIVE X 141 | case 2: *x = uc; *y = 1.0f; *z = -vc; break; // POSITIVE Y 142 | case 3: *x = uc; *y = -1.0f; *z = vc; break; // NEGATIVE Y 143 | case 4: *x = uc; *y = vc; *z = 1.0f; break; // POSITIVE Z 144 | case 5: *x = -uc; *y = vc; *z = -1.0f; break; // NEGATIVE Z 145 | } 146 | } 147 | 148 | static void set_cube_face(int index) 149 | { 150 | if (g_state.texinfo.flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) { 151 | assert(index >= 0 && index < DDSKTX_CUBE_FACE_COUNT); 152 | 153 | vertex vertices[4]; 154 | memcpy(vertices, k_vertices, sizeof(k_vertices)); 155 | 156 | for (int i = 0; i < 4; i++) { 157 | float x, y, z; 158 | convert_cube_uv_to_xyz(index, vertices[i].u, vertices[i].v, &x, &y, &z); 159 | vertices[i].u = x; 160 | vertices[i].v = y; 161 | vertices[i].w = z; 162 | } 163 | 164 | sg_update_buffer(g_state.vb, vertices, sizeof(vertices)); 165 | } 166 | } 167 | 168 | static void adjust_checker_coords(int width, int height) 169 | { 170 | int count_x = width/CHECKER_SIZE; 171 | int count_y = height/CHECKER_SIZE; 172 | 173 | float ratio = (float)width / (float)height; 174 | float u, v; 175 | if (width > height) { 176 | u = (float)count_x; 177 | v = (float)count_y * ratio; 178 | } 179 | else { 180 | v = (float)count_y; 181 | u = (float)count_x / ratio; 182 | } 183 | 184 | vertex vertices[4]; 185 | memcpy(vertices, k_vertices, sizeof(k_vertices)); 186 | 187 | for (int i = 0; i < 4; i++) { 188 | vertices[i].u = vertices[i].u != 0 ? u : 0; 189 | vertices[i].v = vertices[i].v != 0 ? v : 0; 190 | } 191 | sg_update_buffer(g_state.vb_checker, vertices, sizeof(vertices)); 192 | } 193 | 194 | static void sx_mat4_ortho(float mat[16], float width, float height, float zn, float zf, float offset, bool ogl_ndc) 195 | { 196 | const float d = zf - zn; 197 | const float cc = (ogl_ndc ? 2.0f : 1.0f) / d; 198 | const float ff = ogl_ndc ? -(zn + zf) / d : -zn / d; 199 | 200 | mat[0] = 2.0f / width; 201 | mat[1] = 0; 202 | mat[2] = 0; 203 | mat[3] = 0; 204 | 205 | mat[4] = 0; 206 | mat[5] = 2.0f / height; 207 | mat[6] = 0; 208 | mat[7] = 0; 209 | 210 | mat[8] = 0; 211 | mat[9] = 0; 212 | mat[10] = -cc; 213 | mat[11] = 0; 214 | 215 | mat[12] = offset; 216 | mat[13] = 0; 217 | mat[14] = ff; 218 | mat[15] = 1.0f; 219 | } 220 | 221 | static void sx_mat4_ident(float mat[16]) 222 | { 223 | mat[0] = 1.0f; 224 | mat[1] = 0; 225 | mat[2] = 0; 226 | mat[3] = 0; 227 | 228 | mat[4] = 0; 229 | mat[5] = 1.0f; 230 | mat[6] = 0; 231 | mat[7] = 0; 232 | 233 | mat[8] = 0; 234 | mat[9] = 0; 235 | mat[10] = 1.0f; 236 | mat[11] = 0; 237 | 238 | mat[12] = 0; 239 | mat[13] = 0; 240 | mat[14] = 0; 241 | mat[15] = 1.0f; 242 | } 243 | 244 | 245 | static sg_image create_checker_texture(int checker_size, int size, uint32_t colors[2]) 246 | { 247 | assert(size % 4 == 0 && "size must be multiple of four"); 248 | assert(size % checker_size == 0 && "checker_size must be dividable by size"); 249 | 250 | int size_bytes = size * size * sizeof(uint32_t); 251 | uint32_t* pixels = malloc(size_bytes); 252 | assert(pixels); 253 | 254 | // split into tiles and color them 255 | int tiles_x = size / checker_size; 256 | int tiles_y = size / checker_size; 257 | int num_tiles = tiles_x * tiles_y; 258 | 259 | int* poss = malloc(sizeof(int) * 2 * num_tiles); 260 | assert(poss); 261 | int _x = 0, _y = 0; 262 | for (int i = 0; i < num_tiles; i++) { 263 | poss[i*2] = _x; 264 | poss[i*2 + 1] = _y; 265 | _x += checker_size; 266 | if (_x >= size) { 267 | _x = 0; 268 | _y += checker_size; 269 | } 270 | } 271 | 272 | int color_idx = 0; 273 | for (int i = 0; i < num_tiles; i++) { 274 | int* p = poss + i*2; 275 | uint32_t c = colors[color_idx]; 276 | if (i == 0 || ((i + 1) % tiles_x) != 0) 277 | color_idx = !color_idx; 278 | int end_x = p[0] + checker_size; 279 | int end_y = p[1] + checker_size; 280 | for (int y = p[1]; y < end_y; y++) { 281 | for (int x = p[0]; x < end_x; x++) { 282 | int pixel = x + y * size; 283 | pixels[pixel] = c; 284 | } 285 | } 286 | } 287 | 288 | sg_image tex = sg_make_image(&(sg_image_desc) { 289 | .width = size, 290 | .height = size, 291 | .num_mipmaps = 1, 292 | .pixel_format = SG_PIXELFORMAT_RGBA8, 293 | .content = (sg_image_content){.subimage[0][0].ptr = pixels, 294 | .subimage[0][0].size = size_bytes } 295 | }); 296 | 297 | free(poss); 298 | free(pixels); 299 | 300 | return tex; 301 | } 302 | 303 | 304 | static void print_msg(const char* fmt, ...) 305 | { 306 | char msg[1024]; 307 | va_list args; 308 | va_start(args, fmt); 309 | vsnprintf(msg, sizeof(msg), fmt, args); 310 | va_end(args); 311 | 312 | #if defined(_WIN32) || defined(_WIN64) 313 | MessageBoxA(NULL, msg, "DDS/KTX viewer", MB_OK); 314 | #else 315 | puts(msg); 316 | #endif 317 | } 318 | 319 | static sg_shader_desc get_shader_desc(const void* vs_data, uint32_t vs_size, const void* fs_data, 320 | uint32_t fs_size, sg_image_type imgtype) 321 | { 322 | return (sg_shader_desc){ 323 | .attrs = { 324 | [0] = {.name = "a_pos", .sem_name = "POSITION" }, 325 | [1] = {.name = "a_uv", .sem_name = "TEXCOORD" } 326 | }, 327 | .vs = { 328 | #ifdef SOKOL_D3D11 329 | .byte_code = (const uint8_t*)vs_data, 330 | .byte_code_size = vs_size, 331 | #else 332 | .source = (const char*)vs_data, 333 | #endif 334 | #ifdef SOKOL_METAL 335 | .entry = "main0", 336 | #endif 337 | .uniform_blocks[0] = { 338 | .size = sizeof(uniforms_vs), 339 | .uniforms = { 340 | [0] = {.name = "proj_mat", .type = SG_UNIFORMTYPE_MAT4 }, 341 | } 342 | } 343 | }, 344 | .fs = { 345 | #ifdef SOKOL_D3D11 346 | .byte_code = (const uint8_t*)fs_data, 347 | .byte_code_size = fs_size, 348 | #else 349 | .source = (const char*)fs_data, 350 | #endif 351 | #ifdef SOKOL_METAL 352 | .entry = "main0", 353 | #endif 354 | .images[0] = { 355 | .name = "tex_image", 356 | .type = imgtype 357 | }, 358 | .uniform_blocks[0] = { 359 | .size = sizeof(uniforms_fs), 360 | .uniforms = { 361 | [0] = {.name = "color", .type = SG_UNIFORMTYPE_FLOAT4 }, 362 | [1] = {.name = "target_lod", SG_UNIFORMTYPE_FLOAT4 } 363 | } 364 | } 365 | } 366 | }; 367 | } 368 | 369 | static void init(void) 370 | { 371 | sg_setup(&(sg_desc) { 372 | .context = sapp_sgcontext() 373 | }); 374 | 375 | sg_image_type imgtype = (g_state.texinfo.flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) ? SG_IMAGETYPE_CUBE : SG_IMAGETYPE_2D; 376 | 377 | g_state.pass_action = (sg_pass_action) { 378 | .colors[0] = { .action = SG_ACTION_CLEAR, .val = {0, 0, 0, 1.0f} } 379 | }; 380 | 381 | g_state.vb = sg_make_buffer(&(sg_buffer_desc) { 382 | .usage = SG_USAGE_DYNAMIC, 383 | .type = SG_BUFFERTYPE_VERTEXBUFFER, 384 | .size = sizeof(k_vertices) 385 | }); 386 | 387 | g_state.vb_checker = sg_make_buffer(&(sg_buffer_desc) { 388 | .usage = SG_USAGE_DYNAMIC, 389 | .type = SG_BUFFERTYPE_VERTEXBUFFER, 390 | .size = sizeof(k_vertices) 391 | }); 392 | 393 | g_state.ib = sg_make_buffer(&(sg_buffer_desc) { 394 | .usage = SG_USAGE_IMMUTABLE, 395 | .type = SG_BUFFERTYPE_INDEXBUFFER, 396 | .size = sizeof(k_indices), 397 | .content = k_indices 398 | }); 399 | 400 | 401 | { 402 | sg_shader_desc desc = get_shader_desc(quad_vs_data, quad_vs_size, quad_fs_data, quad_fs_size, 403 | SG_IMAGETYPE_2D); 404 | g_state.shader = sg_make_shader(&desc); 405 | } 406 | 407 | { 408 | sg_shader_desc desc = get_shader_desc(quad_vs_data, quad_vs_size, quad_cubemap_fs_data, 409 | quad_cubemap_fs_size, SG_IMAGETYPE_CUBE); 410 | g_state.shader_cubemap = sg_make_shader(&desc); 411 | } 412 | 413 | sg_pipeline_desc pip_desc = (sg_pipeline_desc) { 414 | .layout = { 415 | .buffers[0] = { 416 | .stride = sizeof(vertex), 417 | }, 418 | .attrs = { 419 | [0] = {.offset = 0, .format = SG_VERTEXFORMAT_FLOAT2 }, 420 | [1] = {.offset = 8, .format = SG_VERTEXFORMAT_FLOAT3 } 421 | } 422 | }, 423 | .primitive_type = SG_PRIMITIVETYPE_TRIANGLES, 424 | .index_type = SG_INDEXTYPE_UINT16, 425 | .rasterizer = { 426 | .cull_mode = SG_CULLMODE_BACK 427 | }, 428 | .blend = { 429 | .enabled = true, 430 | .src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA, 431 | .dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA 432 | } 433 | }; 434 | 435 | { 436 | pip_desc.shader = g_state.shader; 437 | g_state.pip = sg_make_pipeline(&pip_desc); 438 | } 439 | 440 | { 441 | pip_desc.shader = g_state.shader_cubemap; 442 | g_state.pip_cubemap = sg_make_pipeline(&pip_desc); 443 | } 444 | 445 | // main texture (dds-ktx) 446 | if (imgtype == SG_IMAGETYPE_CUBE) { 447 | set_cube_face(0); 448 | } else { 449 | sg_update_buffer(g_state.vb, k_vertices, sizeof(k_vertices)); 450 | } 451 | 452 | adjust_checker_coords(sapp_width(), sapp_height()); 453 | 454 | sg_image_desc desc = { 455 | .type = imgtype, 456 | .width = g_state.texinfo.width, 457 | .height = g_state.texinfo.height, 458 | .depth = 1, 459 | .num_mipmaps = g_state.texinfo.num_mips, 460 | .min_filter = SG_FILTER_NEAREST, 461 | .mag_filter = SG_FILTER_NEAREST 462 | }; 463 | 464 | switch (g_state.texinfo.format) { 465 | case DDSKTX_FORMAT_BC1: desc.pixel_format = SG_PIXELFORMAT_BC1_RGBA; break; 466 | case DDSKTX_FORMAT_BC2: desc.pixel_format = SG_PIXELFORMAT_BC2_RGBA; break; 467 | case DDSKTX_FORMAT_BC3: desc.pixel_format = SG_PIXELFORMAT_BC3_RGBA; break; 468 | case DDSKTX_FORMAT_BC4: desc.pixel_format = SG_PIXELFORMAT_BC4_R; break; 469 | case DDSKTX_FORMAT_BC5: desc.pixel_format = SG_PIXELFORMAT_BC5_RG; break; 470 | case DDSKTX_FORMAT_BC6H: desc.pixel_format = SG_PIXELFORMAT_BC6H_RGBF; break; 471 | case DDSKTX_FORMAT_BC7: desc.pixel_format = SG_PIXELFORMAT_BC7_RGBA; break; 472 | case DDSKTX_FORMAT_A8: 473 | case DDSKTX_FORMAT_R8: desc.pixel_format = SG_PIXELFORMAT_R8; break; 474 | case DDSKTX_FORMAT_RGBA8: 475 | case DDSKTX_FORMAT_RGBA8S: desc.pixel_format = SG_PIXELFORMAT_RGBA8; break; 476 | case DDSKTX_FORMAT_RG16: desc.pixel_format = SG_PIXELFORMAT_RG16; break; 477 | case DDSKTX_FORMAT_RGB8: desc.pixel_format = SG_PIXELFORMAT_RGBA8; break; 478 | case DDSKTX_FORMAT_R16: desc.pixel_format = SG_PIXELFORMAT_R16; break; 479 | case DDSKTX_FORMAT_R32F: desc.pixel_format = SG_PIXELFORMAT_R32F; break; 480 | case DDSKTX_FORMAT_R16F: desc.pixel_format = SG_PIXELFORMAT_R16F; break; 481 | case DDSKTX_FORMAT_RG16F: desc.pixel_format = SG_PIXELFORMAT_RG16F; break; 482 | case DDSKTX_FORMAT_RG16S: desc.pixel_format = SG_PIXELFORMAT_RG16; break; 483 | case DDSKTX_FORMAT_RGBA16F: desc.pixel_format = SG_PIXELFORMAT_RGBA16F; break; 484 | case DDSKTX_FORMAT_RGBA16: desc.pixel_format = SG_PIXELFORMAT_RGBA16; break; 485 | case DDSKTX_FORMAT_BGRA8: desc.pixel_format = SG_PIXELFORMAT_BGRA8; break; 486 | case DDSKTX_FORMAT_RGB10A2: desc.pixel_format = SG_PIXELFORMAT_RGB10A2; break; 487 | case DDSKTX_FORMAT_RG11B10F: desc.pixel_format = SG_PIXELFORMAT_RG11B10F; break; 488 | case DDSKTX_FORMAT_RG8: desc.pixel_format = SG_PIXELFORMAT_RG8; break; 489 | case DDSKTX_FORMAT_RG8S: desc.pixel_format = SG_PIXELFORMAT_RG8; break; 490 | default: assert(0); exit(-1); 491 | } 492 | 493 | int num_faces = imgtype == SG_IMAGETYPE_CUBE ? 6 : 1; 494 | for (int face = 0; face < num_faces; face++) { 495 | for (int mip = 0; mip < g_state.texinfo.num_mips; mip++) { 496 | ddsktx_sub_data subdata; 497 | ddsktx_get_sub(&g_state.texinfo, &subdata, g_state.file_data, g_state.file_size, 0, face, mip); 498 | desc.content.subimage[face][mip].ptr = subdata.buff; 499 | desc.content.subimage[face][mip].size = subdata.size_bytes; 500 | } 501 | } 502 | 503 | g_state.tex = sg_make_image(&desc); 504 | 505 | sdtx_setup(&(sdtx_desc_t) { 506 | .fonts = { 507 | [0] = sdtx_font_c64(), 508 | }, 509 | }); 510 | sdtx_set_context(SDTX_DEFAULT_CONTEXT); 511 | sdtx_canvas((float)sapp_width() * (1.0f/FONT_SCALE), (float)sapp_height() * (1.0f/FONT_SCALE)); 512 | 513 | uint32_t checker_colors[] = { 0xff999999, 0xff666666 }; 514 | 515 | g_state.checker = create_checker_texture(8, 16, checker_colors); 516 | 517 | g_state.vars_fs.color[0] = g_state.vars_fs.color[1] = g_state.vars_fs.color[2] = g_state.vars_fs.color[3] = 1.0f; 518 | } 519 | 520 | static const char* texture_type_info() 521 | { 522 | static char info[128]; 523 | 524 | const char* type = "2D"; 525 | if (g_state.texinfo.flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) { 526 | snprintf(info, sizeof(info), "Cube (%s)", k_cube_face_names[g_state.cube_face]); 527 | } else if (g_state.texinfo.depth > 1) { 528 | snprintf(info, sizeof(info), "3D (%d/%d)", g_state.cur_slice, g_state.texinfo.depth); 529 | } else { 530 | strcpy(info, "2D"); 531 | } 532 | 533 | return info; 534 | 535 | } 536 | 537 | static void frame(void) 538 | { 539 | sdtx_home(); 540 | sdtx_origin(1, 1); 541 | sdtx_pos(0, 0); 542 | sdtx_color3b(!g_state.inv_text_color ? 255 : 0, !g_state.inv_text_color ? 255 : 0, 0); 543 | 544 | sdtx_printf("%s\t%dx%d (mip %d/%d)", 545 | ddsktx_format_str(g_state.texinfo.format), g_state.texinfo.width, 546 | g_state.texinfo.height, g_state.cur_mip + 1, g_state.texinfo.num_mips); 547 | sdtx_crlf(); 548 | sdtx_printf("%s\tmask: %c%c%c%c\t", 549 | texture_type_info(), 550 | g_state.vars_fs.color[0] == 1.0f ? 'R' : 'X', 551 | g_state.vars_fs.color[1] == 1.0f ? 'G' : 'X', 552 | g_state.vars_fs.color[2] == 1.0f ? 'B' : 'X', 553 | g_state.vars_fs.color[3] == 1.0f ? 'A' : 'X'); 554 | sdtx_crlf(); 555 | 556 | g_state.vars_fs.args[0] = (float)g_state.cur_mip; 557 | 558 | sg_begin_default_pass(&g_state.pass_action, sapp_width(), sapp_height()); 559 | if (g_state.tex.id) { 560 | sg_bindings bindings = { 561 | .index_buffer = g_state.ib, 562 | }; 563 | 564 | if (g_state.checker.id) { 565 | bindings.fs_images[0] = g_state.checker; 566 | bindings.vertex_buffers[0] = g_state.vb_checker; 567 | uniforms_fs ufs = { 568 | {1.0f, 1.0f, 1.0f, 1.0f}, 569 | {0, 0, 0, 0} 570 | }; 571 | 572 | uniforms_vs uvs; 573 | 574 | float ratio = (float)sapp_width() / (float)sapp_height(); 575 | float w = 1.0f, h = 1.0f; 576 | if (sapp_width() > sapp_height()) { 577 | h = w/ratio; 578 | } else { 579 | w = h*ratio; 580 | } 581 | sx_mat4_ortho(uvs.proj_mat, w, h, -1.0f, 1.0f, 0, false); 582 | 583 | sg_apply_pipeline(g_state.pip); 584 | sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &uvs, sizeof(uvs)); 585 | sg_apply_uniforms(SG_SHADERSTAGE_FS, 0, &ufs, sizeof(ufs)); 586 | sg_apply_bindings(&bindings); 587 | sg_draw(0, 6, 1); 588 | } 589 | 590 | 591 | uniforms_vs uvs; 592 | sx_mat4_ident(uvs.proj_mat); 593 | bindings.fs_images[0] = g_state.tex; 594 | bindings.vertex_buffers[0] = g_state.vb; 595 | 596 | // for the image to the window and keep the ratio 597 | int w = g_state.texinfo.width; 598 | int h = g_state.texinfo.height; 599 | { 600 | float ratio_outer = (float)sapp_width() / (float)sapp_height(); 601 | float ratio_inner = (float)w / (float)h; 602 | float scale = (ratio_inner >= ratio_outer) ? 603 | ((float)sapp_width()/(float)w) : 604 | ((float)sapp_height()/(float)h); 605 | w = (int)((float)w * scale); 606 | h = (int)((float)h * scale); 607 | } 608 | 609 | sg_apply_viewport((sapp_width() - w)/2, (sapp_height() - h)/2, w, h, true); 610 | 611 | sg_apply_pipeline((g_state.texinfo.flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) ? g_state.pip_cubemap : g_state.pip); 612 | sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &uvs, sizeof(uvs)); 613 | sg_apply_uniforms(SG_SHADERSTAGE_FS, 0, &g_state.vars_fs, sizeof(g_state.vars_fs)); 614 | sg_apply_bindings(&bindings); 615 | sg_draw(0, 6, 1); 616 | } 617 | 618 | sg_apply_viewport(0, 0, sapp_width(), sapp_height(), true); 619 | sdtx_draw(); 620 | 621 | sg_end_pass(); 622 | sg_commit(); 623 | } 624 | 625 | static void release(void) 626 | { 627 | free(g_state.file_data); 628 | sg_destroy_pipeline(g_state.pip); 629 | sg_destroy_pipeline(g_state.pip_checker); 630 | sg_destroy_pipeline(g_state.pip_cubemap); 631 | sg_destroy_shader(g_state.shader); 632 | sg_destroy_shader(g_state.shader_cubemap); 633 | sg_destroy_buffer(g_state.vb); 634 | sg_destroy_buffer(g_state.vb_checker); 635 | sg_destroy_buffer(g_state.ib); 636 | sg_destroy_image(g_state.tex); 637 | sg_destroy_image(g_state.checker); 638 | sdtx_shutdown(); 639 | sg_shutdown(); 640 | } 641 | 642 | static void on_events(const sapp_event* e) 643 | { 644 | switch (e->type) { 645 | case SAPP_EVENTTYPE_RESIZED: 646 | sdtx_canvas((float)sapp_width() * (1.0f/FONT_SCALE), (float)sapp_height() * (1.0f/FONT_SCALE)); 647 | adjust_checker_coords(e->window_width, e->window_height); 648 | break; 649 | 650 | case SAPP_EVENTTYPE_KEY_DOWN: 651 | if (e->key_code == SAPP_KEYCODE_GRAVE_ACCENT) { 652 | g_state.inv_text_color = !g_state.inv_text_color; 653 | } 654 | if (e->key_code == SAPP_KEYCODE_A) { 655 | g_state.vars_fs.color[3] = g_state.vars_fs.color[3] == 1.0f ? 0 : 1.0f; 656 | } 657 | if (e->key_code == SAPP_KEYCODE_R) { 658 | g_state.vars_fs.color[0] = g_state.vars_fs.color[0] == 1.0f ? 0 : 1.0f; 659 | } 660 | if (e->key_code == SAPP_KEYCODE_G) { 661 | g_state.vars_fs.color[1] = g_state.vars_fs.color[1] == 1.0f ? 0 : 1.0f; 662 | } 663 | if (e->key_code == SAPP_KEYCODE_B) { 664 | g_state.vars_fs.color[2] = g_state.vars_fs.color[2] == 1.0f ? 0 : 1.0f; 665 | } 666 | if (e->key_code == SAPP_KEYCODE_UP) { 667 | g_state.cur_mip = (g_state.cur_mip + 1) >= g_state.texinfo.num_mips ? (g_state.texinfo.num_mips - 1) : g_state.cur_mip + 1; 668 | } 669 | if (e->key_code == SAPP_KEYCODE_DOWN) { 670 | g_state.cur_mip = (g_state.cur_mip > 0) ? g_state.cur_mip - 1 : 0; 671 | } 672 | 673 | if (e->key_code == SAPP_KEYCODE_ESCAPE) { 674 | sapp_request_quit(); 675 | } 676 | 677 | if (e->key_code == SAPP_KEYCODE_F) { 678 | g_state.cube_face = (g_state.cube_face + 1) % DDSKTX_CUBE_FACE_COUNT; 679 | set_cube_face(g_state.cube_face); 680 | } 681 | 682 | break; 683 | } 684 | } 685 | 686 | sapp_desc sokol_main(int argc, char* argv[]) 687 | { 688 | if (argc <= 1) { 689 | print_msg("Provide a file to load as argument"); 690 | exit(-1); 691 | } 692 | 693 | FILE* f = fopen(argv[1], "rb"); 694 | if (!f) { 695 | print_msg("Error: could not open file: %s\n", argv[1]); 696 | exit(-1); 697 | } 698 | 699 | fseek(f, 0, SEEK_END); 700 | int size = (int)ftell(f); 701 | if (size == 0) { 702 | print_msg("Error: file '%s' is empty\n", argv[1]); 703 | exit(-1); 704 | } 705 | fseek(f, 0, SEEK_SET); 706 | 707 | void* data = malloc(size); 708 | if (!data) { 709 | print_msg("out of memory: requested size: %d\n", (int)size); 710 | exit(-1); 711 | } 712 | 713 | if (fread(data, 1, size, f) != size) { 714 | print_msg("could not read file data : %s\n", argv[1]); 715 | exit(-1); 716 | } 717 | 718 | g_state.file_data = data; 719 | g_state.file_size = size; 720 | 721 | fclose(f); 722 | 723 | ddsktx_texture_info tc = {0}; 724 | ddsktx_error img_err; 725 | if (!ddsktx_parse(&tc, data, size, &img_err)) { 726 | print_msg("Loading image '%s' failed: %s", argv[1], img_err.msg); 727 | exit(-1); 728 | } 729 | 730 | g_state.texinfo = tc; 731 | 732 | int window_w = tc.width; 733 | int window_h = tc.height; 734 | #if defined(_WIN32) || defined(_WIN64) 735 | int desktop_w, desktop_h; 736 | desktop_size(&desktop_w, &desktop_h); 737 | float ratio = (float)tc.width / (float)tc.height; 738 | if (window_w > (desktop_w - 50)) { 739 | window_w = desktop_w - 50; 740 | window_h = (int)((float)window_w / ratio); 741 | } 742 | if (window_h > (desktop_h - 50)) { 743 | window_h = desktop_h - 50; 744 | window_w = (int)((float)window_h * ratio); 745 | } 746 | #endif 747 | 748 | return (sapp_desc) { 749 | .init_cb = init, 750 | .frame_cb = frame, 751 | .cleanup_cb = release, 752 | .event_cb = on_events, 753 | .width = window_w, 754 | .height = window_h, 755 | .window_title = "DDS/KTX viewer", 756 | .swap_interval = 2, 757 | .sample_count = 1 758 | }; 759 | } 760 | -------------------------------------------------------------------------------- /ctexview/ctexview.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/septag/dds-ktx/c3ca8febc2457ab5c581604f3236a8a511fc2e45/ctexview/ctexview.ico -------------------------------------------------------------------------------- /ctexview/quad.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | precision mediump float; 4 | 5 | 6 | layout (location = TEXCOORD0) in vec3 f_uv; 7 | layout (location = SV_Target0) out vec4 frag_color; 8 | 9 | #ifdef CUBEMAP 10 | layout (binding = 0) uniform samplerCube tex_image; 11 | #else 12 | layout (binding = 0) uniform sampler2D tex_image; 13 | #endif 14 | 15 | layout (binding = 0, std140) uniform globals { 16 | vec4 color; 17 | vec4 target_lod; 18 | }; 19 | 20 | void main() 21 | { 22 | #ifdef CUBEMAP 23 | frag_color = textureLod(tex_image, f_uv, target_lod.x) * vec4(color.xyz, 1.0); 24 | #else 25 | frag_color = textureLod(tex_image, f_uv.xy, target_lod.x) * vec4(color.rgb, 1.0); 26 | #endif 27 | frag_color.a = color.a < 1.0 ? 1.0 : frag_color.a; 28 | } 29 | -------------------------------------------------------------------------------- /ctexview/quad.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (location = POSITION) in vec2 a_pos; 4 | layout (location = TEXCOORD0) in vec3 a_uv; 5 | 6 | layout (location = TEXCOORD0) out vec3 f_uv; 7 | 8 | layout (binding = 0, std140) uniform globals { 9 | mat4 proj_mat; 10 | }; 11 | 12 | void main() { 13 | gl_Position = proj_mat * vec4(a_pos, 0, 1.0); 14 | f_uv = a_uv; 15 | } -------------------------------------------------------------------------------- /ctexview/quad_cubemap_glsl.frag.h: -------------------------------------------------------------------------------- 1 | // This file is automatically created by glslcc v1.7.3 2 | // http://www.github.com/septag/glslcc 3 | // 4 | #pragma once 5 | 6 | static const unsigned int quad_cubemap_fs_size = 381; 7 | static const unsigned int quad_cubemap_fs_data[384/4] = { 8 | 0x72657623, 0x6e6f6973, 0x30333320, 0x6e750a0a, 0x726f6669, 0x6576206d, 0x67203463, 0x61626f6c, 9 | 0x325b736c, 0x750a3b5d, 0x6f66696e, 0x73206d72, 0x6c706d61, 0x75437265, 0x74206562, 0x695f7865, 10 | 0x6567616d, 0x6c0a0a3b, 0x756f7961, 0x6f6c2874, 0x69746163, 0x3d206e6f, 0x20293020, 0x2074756f, 11 | 0x34636576, 0x61726620, 0x6f635f67, 0x3b726f6c, 0x206e690a, 0x33636576, 0x755f6620, 0x0a0a3b76, 12 | 0x64696f76, 0x69616d20, 0x0a29286e, 0x20200a7b, 0x72662020, 0x635f6761, 0x726f6c6f, 0x74203d20, 13 | 0x75747865, 0x6f4c6572, 0x65742864, 0x6d695f78, 0x2c656761, 0x755f6620, 0x67202c76, 0x61626f6c, 14 | 0x315b736c, 0x29782e5d, 0x76202a20, 0x28346365, 0x626f6c67, 0x5b736c61, 0x782e5d30, 0x202c7a79, 15 | 0x29302e31, 0x20200a3b, 0x6c662020, 0x2074616f, 0x3b37345f, 0x2020200a, 0x20666920, 0x6f6c6728, 16 | 0x736c6162, 0x2e5d305b, 0x203c2077, 0x29302e31, 0x2020200a, 0x200a7b20, 0x20202020, 0x5f202020, 17 | 0x3d203734, 0x302e3120, 0x20200a3b, 0x0a7d2020, 0x20202020, 0x65736c65, 0x2020200a, 0x200a7b20, 18 | 0x20202020, 0x5f202020, 0x3d203734, 0x61726620, 0x6f635f67, 0x2e726f6c, 0x200a3b77, 0x7d202020, 19 | 0x2020200a, 0x61726620, 0x6f635f67, 0x2e726f6c, 0x203d2077, 0x3b37345f, 0x0a0a7d0a, 0x00000000 }; 20 | 21 | 22 | -------------------------------------------------------------------------------- /ctexview/quad_cubemap_hlsl.frag.h: -------------------------------------------------------------------------------- 1 | // This file is automatically created by glslcc v1.7.3 2 | // http://www.github.com/septag/glslcc 3 | // 4 | #pragma once 5 | 6 | static const unsigned int quad_cubemap_fs_size = 988; 7 | static const unsigned int quad_cubemap_fs_data[988/4] = { 8 | 0x43425844, 0xdcce51ee, 0x91aaa444, 0x1f1ddd8b, 0x4bd76050, 0x00000001, 0x000003dc, 0x00000005, 9 | 0x00000034, 0x000001d8, 0x0000020c, 0x00000240, 0x00000340, 0x46454452, 0x0000019c, 0x00000001, 10 | 0x000000c4, 0x00000003, 0x0000003c, 0xffff0500, 0x00008100, 0x00000173, 0x31314452, 0x0000003c, 11 | 0x00000018, 0x00000020, 0x00000028, 0x00000024, 0x0000000c, 0x00000000, 0x0000009c, 0x00000003, 12 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x000000af, 0x00000002, 13 | 0x00000005, 0x00000009, 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x000000b9, 0x00000000, 14 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x7865745f, 0x616d695f, 15 | 0x735f6567, 0x6c706d61, 0x74007265, 0x695f7865, 0x6567616d, 0x6f6c6700, 0x736c6162, 0xababab00, 16 | 0x000000b9, 0x00000002, 0x000000dc, 0x00000020, 0x00000000, 0x00000000, 0x0000012c, 0x00000000, 17 | 0x00000010, 0x00000002, 0x00000140, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 18 | 0x00000164, 0x00000010, 0x00000010, 0x00000002, 0x00000140, 0x00000000, 0xffffffff, 0x00000000, 19 | 0xffffffff, 0x00000000, 0x5f31325f, 0x6f6c6f63, 0x6c660072, 0x3474616f, 0xababab00, 0x00030001, 20 | 0x00040001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000136, 21 | 0x5f31325f, 0x67726174, 0x6c5f7465, 0x4d00646f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 22 | 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x30312072, 0xab00312e, 0x4e475349, 0x0000002c, 23 | 0x00000001, 0x00000008, 0x00000020, 0x00000002, 0x00000000, 0x00000003, 0x00000000, 0x00000707, 24 | 0x43584554, 0x44524f4f, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 25 | 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 26 | 0x58454853, 0x000000f8, 0x00000050, 0x0000003e, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 27 | 0x00000002, 0x0300005a, 0x00106000, 0x00000000, 0x04003058, 0x00107000, 0x00000000, 0x00005555, 28 | 0x03001062, 0x00101072, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 29 | 0x08000031, 0x00100012, 0x00000000, 0x0020803a, 0x00000000, 0x00000000, 0x00004001, 0x3f800000, 30 | 0x8e000048, 0x80000182, 0x00155543, 0x001000f2, 0x00000001, 0x00101246, 0x00000000, 0x00107936, 31 | 0x00000000, 0x00106000, 0x00000000, 0x0020800a, 0x00000000, 0x00000001, 0x08000038, 0x00102072, 32 | 0x00000000, 0x00100796, 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x09000037, 0x00102082, 33 | 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0010000a, 0x00000001, 0x0100003e, 34 | 0x54415453, 0x00000094, 0x00000005, 0x00000002, 0x00000000, 0x00000002, 0x00000002, 0x00000000, 35 | 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36 | 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 37 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; 39 | 40 | -------------------------------------------------------------------------------- /ctexview/quad_cubemap_metal.frag.h: -------------------------------------------------------------------------------- 1 | // This file is automatically created by glslcc v1.7.3 2 | // http://www.github.com/septag/glslcc 3 | // 4 | #pragma once 5 | 6 | static const unsigned int quad_cubemap_fs_size = 738; 7 | static const unsigned int quad_cubemap_fs_data[740/4] = { 8 | 0x636e6923, 0x6564756c, 0x656d3c20, 0x5f6c6174, 0x6c647473, 0x0a3e6269, 0x636e6923, 0x6564756c, 9 | 0x69733c20, 0x732f646d, 0x2e646d69, 0x0a0a3e68, 0x6e697375, 0x616e2067, 0x7073656d, 0x20656361, 10 | 0x6174656d, 0x0a0a3b6c, 0x75727473, 0x67207463, 0x61626f6c, 0x7b0a736c, 0x2020200a, 0x6f6c6620, 11 | 0x20347461, 0x6f6c6f63, 0x200a3b72, 0x66202020, 0x74616f6c, 0x61742034, 0x74656772, 0x646f6c5f, 12 | 0x3b7d0a3b, 0x74730a0a, 0x74637572, 0x69616d20, 0x6f5f306e, 0x7b0a7475, 0x2020200a, 0x6f6c6620, 13 | 0x20347461, 0x67617266, 0x6c6f635f, 0x5b20726f, 0x6c6f635b, 0x3028726f, 0x3b5d5d29, 0x0a3b7d0a, 14 | 0x7274730a, 0x20746375, 0x6e69616d, 0x6e695f30, 0x200a7b0a, 0x66202020, 0x74616f6c, 0x5f662033, 15 | 0x5b207675, 0x6573755b, 0x6f6c2872, 0x29326e63, 0x0a3b5d5d, 0x0a0a3b7d, 0x67617266, 0x746e656d, 16 | 0x69616d20, 0x6f5f306e, 0x6d207475, 0x306e6961, 0x69616d28, 0x695f306e, 0x6e69206e, 0x735b5b20, 17 | 0x65676174, 0x5d6e695f, 0x63202c5d, 0x74736e6f, 0x20746e61, 0x626f6c67, 0x26736c61, 0x31325f20, 18 | 0x625b5b20, 0x65666675, 0x29302872, 0x202c5d5d, 0x74786574, 0x63657275, 0x3c656275, 0x616f6c66, 19 | 0x74203e74, 0x695f7865, 0x6567616d, 0x745b5b20, 0x75747865, 0x30286572, 0x2c5d5d29, 0x6d617320, 20 | 0x72656c70, 0x78657420, 0x616d695f, 0x6d536567, 0x20726c70, 0x61735b5b, 0x656c706d, 0x29302872, 21 | 0x0a295d5d, 0x20200a7b, 0x616d2020, 0x5f306e69, 0x2074756f, 0x2074756f, 0x7d7b203d, 0x20200a3b, 22 | 0x756f2020, 0x72662e74, 0x635f6761, 0x726f6c6f, 0x74203d20, 0x695f7865, 0x6567616d, 0x6d61732e, 23 | 0x28656c70, 0x5f786574, 0x67616d69, 0x706d5365, 0x202c726c, 0x662e6e69, 0x2c76755f, 0x76656c20, 24 | 0x5f286c65, 0x742e3132, 0x65677261, 0x6f6c5f74, 0x29782e64, 0x202a2029, 0x616f6c66, 0x5f283474, 25 | 0x632e3132, 0x726f6c6f, 0x7a79782e, 0x2e31202c, 0x0a3b2930, 0x20202020, 0x616f6c66, 0x345f2074, 26 | 0x200a3b37, 0x69202020, 0x5f282066, 0x632e3132, 0x726f6c6f, 0x3c20772e, 0x302e3120, 0x20200a29, 27 | 0x0a7b2020, 0x20202020, 0x20202020, 0x2037345f, 0x2e31203d, 0x200a3b30, 0x7d202020, 0x2020200a, 28 | 0x736c6520, 0x20200a65, 0x0a7b2020, 0x20202020, 0x20202020, 0x2037345f, 0x756f203d, 0x72662e74, 29 | 0x635f6761, 0x726f6c6f, 0x0a3b772e, 0x20202020, 0x20200a7d, 0x756f2020, 0x72662e74, 0x635f6761, 30 | 0x726f6c6f, 0x3d20772e, 0x37345f20, 0x20200a3b, 0x65722020, 0x6e727574, 0x74756f20, 0x0a7d0a3b, 31 | 0x0000000a }; 32 | 33 | -------------------------------------------------------------------------------- /ctexview/quad_glsl.frag.h: -------------------------------------------------------------------------------- 1 | // This file is automatically created by glslcc v1.7.3 2 | // http://www.github.com/septag/glslcc 3 | // 4 | #pragma once 5 | 6 | static const unsigned int quad_fs_size = 382; 7 | static const unsigned int quad_fs_data[384/4] = { 8 | 0x72657623, 0x6e6f6973, 0x30333320, 0x6e750a0a, 0x726f6669, 0x6576206d, 0x67203463, 0x61626f6c, 9 | 0x325b736c, 0x750a3b5d, 0x6f66696e, 0x73206d72, 0x6c706d61, 0x44327265, 0x78657420, 0x616d695f, 10 | 0x0a3b6567, 0x79616c0a, 0x2874756f, 0x61636f6c, 0x6e6f6974, 0x30203d20, 0x756f2029, 0x65762074, 11 | 0x66203463, 0x5f676172, 0x6f6c6f63, 0x690a3b72, 0x6576206e, 0x66203363, 0x3b76755f, 0x6f760a0a, 12 | 0x6d206469, 0x286e6961, 0x0a7b0a29, 0x20202020, 0x67617266, 0x6c6f635f, 0x3d20726f, 0x78657420, 13 | 0x65727574, 0x28646f4c, 0x5f786574, 0x67616d69, 0x66202c65, 0x2e76755f, 0x202c7978, 0x626f6c67, 14 | 0x5b736c61, 0x782e5d31, 0x202a2029, 0x34636576, 0x6f6c6728, 0x736c6162, 0x2e5d305b, 0x2c7a7978, 15 | 0x302e3120, 0x200a3b29, 0x66202020, 0x74616f6c, 0x39345f20, 0x20200a3b, 0x66692020, 0x6c672820, 16 | 0x6c61626f, 0x5d305b73, 0x3c20772e, 0x302e3120, 0x20200a29, 0x0a7b2020, 0x20202020, 0x20202020, 17 | 0x2039345f, 0x2e31203d, 0x200a3b30, 0x7d202020, 0x2020200a, 0x736c6520, 0x20200a65, 0x0a7b2020, 18 | 0x20202020, 0x20202020, 0x2039345f, 0x7266203d, 0x635f6761, 0x726f6c6f, 0x0a3b772e, 0x20202020, 19 | 0x20200a7d, 0x72662020, 0x635f6761, 0x726f6c6f, 0x3d20772e, 0x39345f20, 0x0a7d0a3b, 0x0000000a }; 20 | 21 | 22 | -------------------------------------------------------------------------------- /ctexview/quad_glsl.vert.h: -------------------------------------------------------------------------------- 1 | // This file is automatically created by glslcc v1.7.3 2 | // http://www.github.com/septag/glslcc 3 | // 4 | #pragma once 5 | 6 | static const unsigned int quad_vs_size = 257; 7 | static const unsigned int quad_vs_data[260/4] = { 8 | 0x72657623, 0x6e6f6973, 0x30333320, 0x6e750a0a, 0x726f6669, 0x6576206d, 0x67203463, 0x61626f6c, 9 | 0x345b736c, 0x6c0a3b5d, 0x756f7961, 0x6f6c2874, 0x69746163, 0x3d206e6f, 0x20293020, 0x76206e69, 10 | 0x20326365, 0x6f705f61, 0x6f0a3b73, 0x76207475, 0x20336365, 0x76755f66, 0x616c0a3b, 0x74756f79, 11 | 0x636f6c28, 0x6f697461, 0x203d206e, 0x69202932, 0x6576206e, 0x61203363, 0x3b76755f, 0x6f760a0a, 12 | 0x6d206469, 0x286e6961, 0x0a7b0a29, 0x20202020, 0x505f6c67, 0x7469736f, 0x206e6f69, 0x616d203d, 13 | 0x67283474, 0x61626f6c, 0x305b736c, 0x67202c5d, 0x61626f6c, 0x315b736c, 0x67202c5d, 0x61626f6c, 14 | 0x325b736c, 0x67202c5d, 0x61626f6c, 0x335b736c, 0x2a20295d, 0x63657620, 0x5f612834, 0x2c736f70, 15 | 0x302e3020, 0x2e31202c, 0x0a3b2930, 0x20202020, 0x76755f66, 0x61203d20, 0x3b76755f, 0x0a0a7d0a, 16 | 0x00000000 }; 17 | 18 | -------------------------------------------------------------------------------- /ctexview/quad_hlsl.frag.h: -------------------------------------------------------------------------------- 1 | // This file is automatically created by glslcc v1.7.3 2 | // http://www.github.com/septag/glslcc 3 | // 4 | #pragma once 5 | 6 | static const unsigned int quad_fs_size = 988; 7 | static const unsigned int quad_fs_data[988/4] = { 8 | 0x43425844, 0x1f031d00, 0xb00294b3, 0x863dd79d, 0x353015d5, 0x00000001, 0x000003dc, 0x00000005, 9 | 0x00000034, 0x000001d8, 0x0000020c, 0x00000240, 0x00000340, 0x46454452, 0x0000019c, 0x00000001, 10 | 0x000000c4, 0x00000003, 0x0000003c, 0xffff0500, 0x00008100, 0x00000173, 0x31314452, 0x0000003c, 11 | 0x00000018, 0x00000020, 0x00000028, 0x00000024, 0x0000000c, 0x00000000, 0x0000009c, 0x00000003, 12 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x000000af, 0x00000002, 13 | 0x00000005, 0x00000004, 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x000000b9, 0x00000000, 14 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x7865745f, 0x616d695f, 15 | 0x735f6567, 0x6c706d61, 0x74007265, 0x695f7865, 0x6567616d, 0x6f6c6700, 0x736c6162, 0xababab00, 16 | 0x000000b9, 0x00000002, 0x000000dc, 0x00000020, 0x00000000, 0x00000000, 0x0000012c, 0x00000000, 17 | 0x00000010, 0x00000002, 0x00000140, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 18 | 0x00000164, 0x00000010, 0x00000010, 0x00000002, 0x00000140, 0x00000000, 0xffffffff, 0x00000000, 19 | 0xffffffff, 0x00000000, 0x5f33325f, 0x6f6c6f63, 0x6c660072, 0x3474616f, 0xababab00, 0x00030001, 20 | 0x00040001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000136, 21 | 0x5f33325f, 0x67726174, 0x6c5f7465, 0x4d00646f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 22 | 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x30312072, 0xab00312e, 0x4e475349, 0x0000002c, 23 | 0x00000001, 0x00000008, 0x00000020, 0x00000002, 0x00000000, 0x00000003, 0x00000000, 0x00000307, 24 | 0x43584554, 0x44524f4f, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 25 | 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 26 | 0x58454853, 0x000000f8, 0x00000050, 0x0000003e, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 27 | 0x00000002, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 28 | 0x03001062, 0x00101032, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 29 | 0x08000031, 0x00100012, 0x00000000, 0x0020803a, 0x00000000, 0x00000000, 0x00004001, 0x3f800000, 30 | 0x8e000048, 0x800000c2, 0x00155543, 0x001000f2, 0x00000001, 0x00101046, 0x00000000, 0x00107936, 31 | 0x00000000, 0x00106000, 0x00000000, 0x0020800a, 0x00000000, 0x00000001, 0x08000038, 0x00102072, 32 | 0x00000000, 0x00100796, 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x09000037, 0x00102082, 33 | 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0010000a, 0x00000001, 0x0100003e, 34 | 0x54415453, 0x00000094, 0x00000005, 0x00000002, 0x00000000, 0x00000002, 0x00000002, 0x00000000, 35 | 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36 | 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 37 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; 39 | 40 | -------------------------------------------------------------------------------- /ctexview/quad_hlsl.vert.h: -------------------------------------------------------------------------------- 1 | // This file is automatically created by glslcc v1.7.3 2 | // http://www.github.com/septag/glslcc 3 | // 4 | #pragma once 5 | 6 | static const unsigned int quad_vs_size = 876; 7 | static const unsigned int quad_vs_data[876/4] = { 8 | 0x43425844, 0x850b49a2, 0x1c1eb79a, 0x88cec8a9, 0xac646615, 0x00000001, 0x0000036c, 0x00000005, 9 | 0x00000034, 0x00000144, 0x00000198, 0x000001f0, 0x000002d0, 0x46454452, 0x00000108, 0x00000001, 10 | 0x00000064, 0x00000001, 0x0000003c, 0xfffe0500, 0x00008100, 0x000000e0, 0x31314452, 0x0000003c, 11 | 0x00000018, 0x00000020, 0x00000028, 0x00000024, 0x0000000c, 0x00000000, 0x0000005c, 0x00000000, 12 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x626f6c67, 0x00736c61, 13 | 0x0000005c, 0x00000001, 0x0000007c, 0x00000040, 0x00000000, 0x00000000, 0x000000a4, 0x00000000, 14 | 0x00000040, 0x00000002, 0x000000bc, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 15 | 0x5f39315f, 0x6a6f7270, 0x74616d5f, 0x6f6c6600, 0x78347461, 0xabab0034, 0x00030002, 0x00040004, 16 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000b1, 0x7263694d, 17 | 0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x31207265, 18 | 0x00312e30, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 19 | 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 20 | 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044, 0x4e47534f, 0x00000050, 21 | 0x00000002, 0x00000008, 0x00000038, 0x00000002, 0x00000000, 0x00000003, 0x00000000, 0x00000807, 22 | 0x00000041, 0x00000000, 0x00000001, 0x00000003, 0x00000001, 0x0000000f, 0x43584554, 0x44524f4f, 23 | 0x5f565300, 0x69736f50, 0x6e6f6974, 0xababab00, 0x58454853, 0x000000d8, 0x00010050, 0x00000036, 24 | 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000, 25 | 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102072, 0x00000000, 0x04000067, 0x001020f2, 26 | 0x00000001, 0x00000001, 0x02000068, 0x00000001, 0x05000036, 0x00102072, 0x00000000, 0x00101246, 27 | 0x00000001, 0x08000038, 0x001000f2, 0x00000000, 0x00101556, 0x00000000, 0x00208e46, 0x00000000, 28 | 0x00000001, 0x0a000032, 0x001000f2, 0x00000000, 0x00101006, 0x00000000, 0x00208e46, 0x00000000, 29 | 0x00000000, 0x00100e46, 0x00000000, 0x08000000, 0x001020f2, 0x00000001, 0x00100e46, 0x00000000, 30 | 0x00208e46, 0x00000000, 0x00000003, 0x0100003e, 0x54415453, 0x00000094, 0x00000005, 0x00000001, 31 | 0x00000000, 0x00000004, 0x00000003, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 32 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33 | 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 35 | 0x00000000, 0x00000000, 0x00000000 }; 36 | 37 | -------------------------------------------------------------------------------- /ctexview/quad_metal.frag.h: -------------------------------------------------------------------------------- 1 | // This file is automatically created by glslcc v1.7.3 2 | // http://www.github.com/septag/glslcc 3 | // 4 | #pragma once 5 | 6 | static const unsigned int quad_fs_size = 739; 7 | static const unsigned int quad_fs_data[740/4] = { 8 | 0x636e6923, 0x6564756c, 0x656d3c20, 0x5f6c6174, 0x6c647473, 0x0a3e6269, 0x636e6923, 0x6564756c, 9 | 0x69733c20, 0x732f646d, 0x2e646d69, 0x0a0a3e68, 0x6e697375, 0x616e2067, 0x7073656d, 0x20656361, 10 | 0x6174656d, 0x0a0a3b6c, 0x75727473, 0x67207463, 0x61626f6c, 0x7b0a736c, 0x2020200a, 0x6f6c6620, 11 | 0x20347461, 0x6f6c6f63, 0x200a3b72, 0x66202020, 0x74616f6c, 0x61742034, 0x74656772, 0x646f6c5f, 12 | 0x3b7d0a3b, 0x74730a0a, 0x74637572, 0x69616d20, 0x6f5f306e, 0x7b0a7475, 0x2020200a, 0x6f6c6620, 13 | 0x20347461, 0x67617266, 0x6c6f635f, 0x5b20726f, 0x6c6f635b, 0x3028726f, 0x3b5d5d29, 0x0a3b7d0a, 14 | 0x7274730a, 0x20746375, 0x6e69616d, 0x6e695f30, 0x200a7b0a, 0x66202020, 0x74616f6c, 0x5f662033, 15 | 0x5b207675, 0x6573755b, 0x6f6c2872, 0x29326e63, 0x0a3b5d5d, 0x0a0a3b7d, 0x67617266, 0x746e656d, 16 | 0x69616d20, 0x6f5f306e, 0x6d207475, 0x306e6961, 0x69616d28, 0x695f306e, 0x6e69206e, 0x735b5b20, 17 | 0x65676174, 0x5d6e695f, 0x63202c5d, 0x74736e6f, 0x20746e61, 0x626f6c67, 0x26736c61, 0x33325f20, 18 | 0x625b5b20, 0x65666675, 0x29302872, 0x202c5d5d, 0x74786574, 0x32657275, 0x6c663c64, 0x3e74616f, 19 | 0x78657420, 0x616d695f, 0x5b206567, 0x7865745b, 0x65727574, 0x5d293028, 0x73202c5d, 0x6c706d61, 20 | 0x74207265, 0x695f7865, 0x6567616d, 0x6c706d53, 0x5b5b2072, 0x706d6173, 0x2872656c, 0x5d5d2930, 21 | 0x0a7b0a29, 0x20202020, 0x6e69616d, 0x756f5f30, 0x756f2074, 0x203d2074, 0x0a3b7d7b, 0x20202020, 22 | 0x2e74756f, 0x67617266, 0x6c6f635f, 0x3d20726f, 0x78657420, 0x616d695f, 0x732e6567, 0x6c706d61, 23 | 0x65742865, 0x6d695f78, 0x53656761, 0x726c706d, 0x6e69202c, 0x755f662e, 0x79782e76, 0x656c202c, 24 | 0x286c6576, 0x2e33325f, 0x67726174, 0x6c5f7465, 0x782e646f, 0x2a202929, 0x6f6c6620, 0x28347461, 25 | 0x2e33325f, 0x6f6c6f63, 0x79782e72, 0x31202c7a, 0x3b29302e, 0x2020200a, 0x6f6c6620, 0x5f207461, 26 | 0x0a3b3934, 0x20202020, 0x28206669, 0x2e33325f, 0x6f6c6f63, 0x20772e72, 0x2e31203c, 0x200a2930, 27 | 0x7b202020, 0x2020200a, 0x20202020, 0x39345f20, 0x31203d20, 0x0a3b302e, 0x20202020, 0x20200a7d, 28 | 0x6c652020, 0x200a6573, 0x7b202020, 0x2020200a, 0x20202020, 0x39345f20, 0x6f203d20, 0x662e7475, 29 | 0x5f676172, 0x6f6c6f63, 0x3b772e72, 0x2020200a, 0x200a7d20, 0x6f202020, 0x662e7475, 0x5f676172, 30 | 0x6f6c6f63, 0x20772e72, 0x345f203d, 0x200a3b39, 0x72202020, 0x72757465, 0x756f206e, 0x7d0a3b74, 31 | 0x00000a0a }; 32 | 33 | -------------------------------------------------------------------------------- /ctexview/quad_metal.vert.h: -------------------------------------------------------------------------------- 1 | // This file is automatically created by glslcc v1.7.3 2 | // http://www.github.com/septag/glslcc 3 | // 4 | #pragma once 5 | 6 | static const unsigned int quad_vs_size = 521; 7 | static const unsigned int quad_vs_data[524/4] = { 8 | 0x636e6923, 0x6564756c, 0x656d3c20, 0x5f6c6174, 0x6c647473, 0x0a3e6269, 0x636e6923, 0x6564756c, 9 | 0x69733c20, 0x732f646d, 0x2e646d69, 0x0a0a3e68, 0x6e697375, 0x616e2067, 0x7073656d, 0x20656361, 10 | 0x6174656d, 0x0a0a3b6c, 0x75727473, 0x67207463, 0x61626f6c, 0x7b0a736c, 0x2020200a, 0x6f6c6620, 11 | 0x78347461, 0x72702034, 0x6d5f6a6f, 0x0a3b7461, 0x0a0a3b7d, 0x75727473, 0x6d207463, 0x306e6961, 12 | 0x74756f5f, 0x200a7b0a, 0x66202020, 0x74616f6c, 0x5f662033, 0x5b207675, 0x6573755b, 0x6f6c2872, 13 | 0x29326e63, 0x0a3b5d5d, 0x20202020, 0x616f6c66, 0x67203474, 0x6f505f6c, 0x69746973, 0x5b206e6f, 14 | 0x736f705b, 0x6f697469, 0x3b5d5d6e, 0x0a3b7d0a, 0x7274730a, 0x20746375, 0x6e69616d, 0x6e695f30, 15 | 0x200a7b0a, 0x66202020, 0x74616f6c, 0x5f612032, 0x20736f70, 0x74615b5b, 0x62697274, 0x28657475, 16 | 0x5d5d2930, 0x20200a3b, 0x6c662020, 0x3374616f, 0x755f6120, 0x5b5b2076, 0x72747461, 0x74756269, 17 | 0x29312865, 0x0a3b5d5d, 0x0a0a3b7d, 0x74726576, 0x6d207865, 0x306e6961, 0x74756f5f, 0x69616d20, 18 | 0x6d28306e, 0x306e6961, 0x206e695f, 0x5b206e69, 0x6174735b, 0x695f6567, 0x2c5d5d6e, 0x6e6f6320, 19 | 0x6e617473, 0x6c672074, 0x6c61626f, 0x5f202673, 0x5b203931, 0x6675625b, 0x28726566, 0x5d5d2930, 20 | 0x0a7b0a29, 0x20202020, 0x6e69616d, 0x756f5f30, 0x756f2074, 0x203d2074, 0x0a3b7d7b, 0x20202020, 21 | 0x2e74756f, 0x505f6c67, 0x7469736f, 0x206e6f69, 0x315f203d, 0x72702e39, 0x6d5f6a6f, 0x2a207461, 22 | 0x6f6c6620, 0x28347461, 0x612e6e69, 0x736f705f, 0x2e30202c, 0x31202c30, 0x3b29302e, 0x2020200a, 23 | 0x74756f20, 0x755f662e, 0x203d2076, 0x612e6e69, 0x3b76755f, 0x2020200a, 0x74657220, 0x206e7275, 24 | 0x3b74756f, 0x0a0a7d0a, 0x00000000 }; 25 | 26 | -------------------------------------------------------------------------------- /ctexview/sokol_glue.h: -------------------------------------------------------------------------------- 1 | #ifndef SOKOL_GLUE_INCLUDED 2 | /* 3 | sokol_glue.h -- glue helper functions for sokol headers 4 | 5 | Project URL: https://github.com/floooh/sokol 6 | 7 | Do this: 8 | #define SOKOL_IMPL 9 | before you include this file in *one* C or C++ file to create the 10 | implementation. 11 | 12 | ...optionally provide the following macros to override defaults: 13 | 14 | SOKOL_ASSERT(c) - your own assert macro (default: assert(c)) 15 | SOKOL_API_DECL - public function declaration prefix (default: extern) 16 | SOKOL_API_IMPL - public function implementation prefix (default: -) 17 | 18 | If sokol_glue.h is compiled as a DLL, define the following before 19 | including the declaration or implementation: 20 | 21 | SOKOL_DLL 22 | 23 | On Windows, SOKOL_DLL will define SOKOL_API_DECL as __declspec(dllexport) 24 | or __declspec(dllimport) as needed. 25 | 26 | OVERVIEW 27 | ======== 28 | The sokol core headers should not depend on each other, but sometimes 29 | it's useful to have a set of helper functions as "glue" between 30 | two or more sokol headers. 31 | 32 | This is what sokol_glue.h is for. Simply include the header after other 33 | sokol headers (both for the implementation and declaration), and 34 | depending on what headers have been included before, sokol_glue.h 35 | will make available "glue functions". 36 | 37 | PROVIDED FUNCTIONS 38 | ================== 39 | 40 | - if sokol_app.h and sokol_gfx.h is included: 41 | 42 | sg_context_desc sapp_sgcontext(void): 43 | 44 | Returns an initialized sg_context_desc function initialized 45 | by calling sokol_app.h functions. 46 | 47 | LICENSE 48 | ======= 49 | zlib/libpng license 50 | 51 | Copyright (c) 2018 Andre Weissflog 52 | 53 | This software is provided 'as-is', without any express or implied warranty. 54 | In no event will the authors be held liable for any damages arising from the 55 | use of this software. 56 | 57 | Permission is granted to anyone to use this software for any purpose, 58 | including commercial applications, and to alter it and redistribute it 59 | freely, subject to the following restrictions: 60 | 61 | 1. The origin of this software must not be misrepresented; you must not 62 | claim that you wrote the original software. If you use this software in a 63 | product, an acknowledgment in the product documentation would be 64 | appreciated but is not required. 65 | 66 | 2. Altered source versions must be plainly marked as such, and must not 67 | be misrepresented as being the original software. 68 | 69 | 3. This notice may not be removed or altered from any source 70 | distribution. 71 | */ 72 | #define SOKOL_GLUE_INCLUDED 73 | 74 | #ifndef SOKOL_API_DECL 75 | #if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_IMPL) 76 | #define SOKOL_API_DECL __declspec(dllexport) 77 | #elif defined(_WIN32) && defined(SOKOL_DLL) 78 | #define SOKOL_API_DECL __declspec(dllimport) 79 | #else 80 | #define SOKOL_API_DECL extern 81 | #endif 82 | #endif 83 | 84 | #ifdef __cplusplus 85 | extern "C" { 86 | #endif 87 | 88 | #if defined(SOKOL_GFX_INCLUDED) && defined(SOKOL_APP_INCLUDED) 89 | SOKOL_API_DECL sg_context_desc sapp_sgcontext(void); 90 | #endif 91 | 92 | #ifdef __cplusplus 93 | } /* extern "C" */ 94 | #endif 95 | #endif /* SOKOL_GLUE_INCLUDED */ 96 | 97 | /*-- IMPLEMENTATION ----------------------------------------------------------*/ 98 | #ifdef SOKOL_IMPL 99 | #define SOKOL_GLUE_IMPL_INCLUDED (1) 100 | #include /* memset */ 101 | 102 | #ifndef SOKOL_API_IMPL 103 | #define SOKOL_API_IMPL 104 | #endif 105 | 106 | #if defined(SOKOL_GFX_INCLUDED) && defined(SOKOL_APP_INCLUDED) 107 | SOKOL_API_IMPL sg_context_desc sapp_sgcontext(void) { 108 | sg_context_desc desc; 109 | memset(&desc, 0, sizeof(desc)); 110 | desc.color_format = (sg_pixel_format) sapp_color_format(); 111 | desc.depth_format = (sg_pixel_format) sapp_depth_format(); 112 | desc.sample_count = sapp_sample_count(); 113 | desc.gl.force_gles2 = sapp_gles2(); 114 | desc.metal.device = sapp_metal_get_device(); 115 | desc.metal.renderpass_descriptor_cb = sapp_metal_get_renderpass_descriptor; 116 | desc.metal.drawable_cb = sapp_metal_get_drawable; 117 | desc.d3d11.device = sapp_d3d11_get_device(); 118 | desc.d3d11.device_context = sapp_d3d11_get_device_context(); 119 | desc.d3d11.render_target_view_cb = sapp_d3d11_get_render_target_view; 120 | desc.d3d11.depth_stencil_view_cb = sapp_d3d11_get_depth_stencil_view; 121 | desc.wgpu.device = sapp_wgpu_get_device(); 122 | desc.wgpu.render_view_cb = sapp_wgpu_get_render_view; 123 | desc.wgpu.resolve_view_cb = sapp_wgpu_get_resolve_view; 124 | desc.wgpu.depth_stencil_view_cb = sapp_wgpu_get_depth_stencil_view; 125 | return desc; 126 | } 127 | #endif 128 | 129 | #endif /* SOKOL_IMPL */ 130 | -------------------------------------------------------------------------------- /dds-ktx.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2018 Sepehr Taghdisian (septag@github). All rights reserved. 3 | // License: https://github.com/septag/dds-ktx#license-bsd-2-clause 4 | // 5 | // Many parts of this code is taken from bimg library: 6 | // https://github.com/bkaradzic/bimg 7 | // 8 | // Copyright 2011-2019 Branimir Karadzic. All rights reserved. 9 | // License: https://github.com/bkaradzic/bimg#license-bsd-2-clause 10 | // 11 | // dds-ktx.h - v1.1.0 - Reader/Writer for DDS/KTX formats 12 | // Parses DDS and KTX files from a memory blob, written in C99 13 | // 14 | // Supported formats: 15 | // For supported formats, see ddsktx_format enum. 16 | // Both KTX/DDS parser supports all formats defined in ddsktx_format 17 | // 18 | // Overriable macros: 19 | // DDSKTX_API Define any function specifier for public functions (default: extern) 20 | // ddsktx_memcpy default: memcpy(dst, src, size) 21 | // ddsktx_memset default: memset(dst, v, size) 22 | // ddsktx_assert default: assert(a) 23 | // ddsktx_strcpy default: strcpy(dst, src) 24 | // ddsktx_memcmp default: memcmp(ptr1, ptr2, size) 25 | // 26 | // API: 27 | // bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err); 28 | // Parses texture file and fills the ddsktx_texture_info struct 29 | // Returns true if successfully parsed, false if failed with an error message inside ddsktx_error parameter (optional) 30 | // After format is parsed, you can read the contents of ddsktx_format and create your GPU texture 31 | // To get pointer to mips and slices see ddsktx_get_sub function 32 | // 33 | // void ddsktx_get_sub(const ddsktx_texture_info* tex, ddsktx_sub_data* buff, 34 | // const void* file_data, int size, 35 | // int array_idx, int slice_face_idx, int mip_idx); 36 | // Gets sub-image data, form a parsed texture file 37 | // user must provided the container object and the original file data which was passed to ddsktx_parse 38 | // array_idx: array index (0..num_layers) 39 | // slice_face_idx: depth-slice or cube-face index. 40 | // if 'flags' have DDSKTX_TEXTURE_FLAG_CUBEMAP bit, then this value represents cube-face-index (0..DDSKTX_CUBE_FACE_COUNT) 41 | // else it represents depth slice index (0..depth) 42 | // mip_idx: mip index (0..num_mips-1 in ddsktx_texture_info) 43 | // 44 | // const char* ddsktx_format_str(ddsktx_format format); 45 | // Converts a format enumeration to string 46 | // 47 | // bool ddsktx_format_compressed(ddsktx_format format); 48 | // Returns true if format is compressed 49 | // 50 | // Example (for 2D textures only): 51 | // int size; 52 | // void* dds_data = load_file("test.dds", &size); 53 | // assert(dds_data); 54 | // ddsktx_texture_info tc = {0}; 55 | // if (ddsktx_parse(&tc, dds_data, size, NULL)) { 56 | // assert(tc.depth == 1); 57 | // assert(!(tc.flags & DDSKTX_TEXTURE_FLAG_CUBEMAP)); 58 | // assert(tc.num_layers == 1); 59 | // // Create GPU texture from tc data 60 | // for (int mip = 0; mip < tc.num_mips; mip++) { 61 | // ddsktx_sub_data sub_data; 62 | // ddsktx_get_sub(&tc, &sub_data, dds_data, size, 0, 0, mip); 63 | // // Fill/Set texture sub resource data (mips in this case) 64 | // } 65 | // } 66 | // free(dds_data); // memory must be valid during stc_ calls 67 | // 68 | // Version history: 69 | // 0.9.0 Initial release, ktx is incomplete 70 | // 1.0.0 Api change: ddsktx_sub_data 71 | // Added KTX support 72 | // 1.0.1 Fixed major bugs in KTX parsing 73 | // 1.1.0 Fixed bugs in get_sub routine, refactored some parts, image-viewer example 74 | // 75 | // TODO 76 | // Write KTX/DDS 77 | // Read KTX metadata. currently it just stores the offset/size to the metadata block 78 | // 79 | 80 | #pragma once 81 | 82 | #include 83 | #include 84 | #include 85 | 86 | #ifndef DDSKTX_API 87 | # ifdef __cplusplus 88 | # define DDSKTX_API extern "C" 89 | # else 90 | # define DDSKTX_API 91 | # endif 92 | #endif 93 | 94 | typedef struct ddsktx_sub_data 95 | { 96 | const void* buff; 97 | int width; 98 | int height; 99 | int size_bytes; 100 | int row_pitch_bytes; 101 | } ddsktx_sub_data; 102 | 103 | typedef enum ddsktx_format 104 | { 105 | DDSKTX_FORMAT_BC1, // DXT1 106 | DDSKTX_FORMAT_BC2, // DXT3 107 | DDSKTX_FORMAT_BC3, // DXT5 108 | DDSKTX_FORMAT_BC4, // ATI1 109 | DDSKTX_FORMAT_BC5, // ATI2 110 | DDSKTX_FORMAT_BC6H, // BC6H 111 | DDSKTX_FORMAT_BC7, // BC7 112 | DDSKTX_FORMAT_ETC1, // ETC1 RGB8 113 | DDSKTX_FORMAT_ETC2, // ETC2 RGB8 114 | DDSKTX_FORMAT_ETC2A, // ETC2 RGBA8 115 | DDSKTX_FORMAT_ETC2A1, // ETC2 RGB8A1 116 | DDSKTX_FORMAT_PTC12, // PVRTC1 RGB 2bpp 117 | DDSKTX_FORMAT_PTC14, // PVRTC1 RGB 4bpp 118 | DDSKTX_FORMAT_PTC12A, // PVRTC1 RGBA 2bpp 119 | DDSKTX_FORMAT_PTC14A, // PVRTC1 RGBA 4bpp 120 | DDSKTX_FORMAT_PTC22, // PVRTC2 RGBA 2bpp 121 | DDSKTX_FORMAT_PTC24, // PVRTC2 RGBA 4bpp 122 | DDSKTX_FORMAT_ATC, // ATC RGB 4BPP 123 | DDSKTX_FORMAT_ATCE, // ATCE RGBA 8 BPP explicit alpha 124 | DDSKTX_FORMAT_ATCI, // ATCI RGBA 8 BPP interpolated alpha 125 | DDSKTX_FORMAT_ASTC4x4, // ASTC 4x4 8.0 BPP 126 | DDSKTX_FORMAT_ASTC5x5, // ASTC 5x5 5.12 BPP 127 | DDSKTX_FORMAT_ASTC6x6, // ASTC 6x6 3.56 BPP 128 | DDSKTX_FORMAT_ASTC8x5, // ASTC 8x5 3.20 BPP 129 | DDSKTX_FORMAT_ASTC8x6, // ASTC 8x6 2.67 BPP 130 | DDSKTX_FORMAT_ASTC10x5, // ASTC 10x5 2.56 BPP 131 | _DDSKTX_FORMAT_COMPRESSED, 132 | DDSKTX_FORMAT_A8, 133 | DDSKTX_FORMAT_R8, 134 | DDSKTX_FORMAT_RGBA8, 135 | DDSKTX_FORMAT_RGBA8S, 136 | DDSKTX_FORMAT_RG16, 137 | DDSKTX_FORMAT_RGB8, 138 | DDSKTX_FORMAT_R16, 139 | DDSKTX_FORMAT_R32F, 140 | DDSKTX_FORMAT_R16F, 141 | DDSKTX_FORMAT_RG16F, 142 | DDSKTX_FORMAT_RG16S, 143 | DDSKTX_FORMAT_RGBA16F, 144 | DDSKTX_FORMAT_RGBA16, 145 | DDSKTX_FORMAT_BGRA8, 146 | DDSKTX_FORMAT_RGB10A2, 147 | DDSKTX_FORMAT_RG11B10F, 148 | DDSKTX_FORMAT_RG8, 149 | DDSKTX_FORMAT_RG8S, 150 | _DDSKTX_FORMAT_COUNT 151 | } ddsktx_format; 152 | 153 | typedef enum ddsktx_texture_flags 154 | { 155 | DDSKTX_TEXTURE_FLAG_CUBEMAP = 0x01, 156 | DDSKTX_TEXTURE_FLAG_SRGB = 0x02, 157 | DDSKTX_TEXTURE_FLAG_ALPHA = 0x04, // Has alpha channel 158 | DDSKTX_TEXTURE_FLAG_DDS = 0x08, // container was DDS file 159 | DDSKTX_TEXTURE_FLAG_KTX = 0x10, // container was KTX file 160 | DDSKTX_TEXTURE_FLAG_VOLUME = 0x20, // 3D volume 161 | } ddsktx_texture_flags; 162 | 163 | typedef struct ddsktx_texture_info 164 | { 165 | int data_offset; // start offset of pixel data 166 | int size_bytes; 167 | ddsktx_format format; 168 | unsigned int flags; // ddsktx_texture_flags 169 | int width; 170 | int height; 171 | int depth; 172 | int num_layers; 173 | int num_mips; 174 | int bpp; 175 | int metadata_offset; // ktx only 176 | int metadata_size; // ktx only 177 | } ddsktx_texture_info; 178 | 179 | typedef enum ddsktx_cube_face 180 | { 181 | DDSKTX_CUBE_FACE_X_POSITIVE = 0, 182 | DDSKTX_CUBE_FACE_X_NEGATIVE, 183 | DDSKTX_CUBE_FACE_Y_POSITIVE, 184 | DDSKTX_CUBE_FACE_Y_NEGATIVE, 185 | DDSKTX_CUBE_FACE_Z_POSITIVE, 186 | DDSKTX_CUBE_FACE_Z_NEGATIVE, 187 | DDSKTX_CUBE_FACE_COUNT 188 | } ddsktx_cube_face; 189 | 190 | typedef struct ddsktx_error 191 | { 192 | char msg[256]; 193 | } ddsktx_error; 194 | 195 | #ifdef __cplusplus 196 | # define ddsktx_default(_v) =_v 197 | #else 198 | # define ddsktx_default(_v) 199 | #endif 200 | 201 | DDSKTX_API bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err ddsktx_default(NULL)); 202 | DDSKTX_API void ddsktx_get_sub(const ddsktx_texture_info* tex, ddsktx_sub_data* buff, 203 | const void* file_data, int size, 204 | int array_idx, int slice_face_idx, int mip_idx); 205 | DDSKTX_API const char* ddsktx_format_str(ddsktx_format format); 206 | DDSKTX_API bool ddsktx_format_compressed(ddsktx_format format); 207 | 208 | //////////////////////////////////////////////////////////////////////////////////////////////////// 209 | // Implementation 210 | #ifdef DDSKTX_IMPLEMENT 211 | 212 | #define stc__makefourcc(_a, _b, _c, _d) ( ( (uint32_t)(_a) | ( (uint32_t)(_b) << 8) | \ 213 | ( (uint32_t)(_c) << 16) | ( (uint32_t)(_d) << 24) ) ) 214 | 215 | // DDS: https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dx-graphics-dds-pguide 216 | #define DDSKTX__DDS_HEADER_SIZE 124 217 | #define DDSKTX__DDS_MAGIC stc__makefourcc('D', 'D', 'S', ' ') 218 | #define DDSKTX__DDS_DXT1 stc__makefourcc('D', 'X', 'T', '1') 219 | #define DDSKTX__DDS_DXT2 stc__makefourcc('D', 'X', 'T', '2') 220 | #define DDSKTX__DDS_DXT3 stc__makefourcc('D', 'X', 'T', '3') 221 | #define DDSKTX__DDS_DXT4 stc__makefourcc('D', 'X', 'T', '4') 222 | #define DDSKTX__DDS_DXT5 stc__makefourcc('D', 'X', 'T', '5') 223 | #define DDSKTX__DDS_ATI1 stc__makefourcc('A', 'T', 'I', '1') 224 | #define DDSKTX__DDS_BC4U stc__makefourcc('B', 'C', '4', 'U') 225 | #define DDSKTX__DDS_ATI2 stc__makefourcc('A', 'T', 'I', '2') 226 | #define DDSKTX__DDS_BC5U stc__makefourcc('B', 'C', '5', 'U') 227 | #define DDSKTX__DDS_DX10 stc__makefourcc('D', 'X', '1', '0') 228 | 229 | #define DDSKTX__DDS_ETC1 stc__makefourcc('E', 'T', 'C', '1') 230 | #define DDSKTX__DDS_ETC2 stc__makefourcc('E', 'T', 'C', '2') 231 | #define DDSKTX__DDS_ET2A stc__makefourcc('E', 'T', '2', 'A') 232 | #define DDSKTX__DDS_PTC2 stc__makefourcc('P', 'T', 'C', '2') 233 | #define DDSKTX__DDS_PTC4 stc__makefourcc('P', 'T', 'C', '4') 234 | #define DDSKTX__DDS_ATC stc__makefourcc('A', 'T', 'C', ' ') 235 | #define DDSKTX__DDS_ATCE stc__makefourcc('A', 'T', 'C', 'E') 236 | #define DDSKTX__DDS_ATCI stc__makefourcc('A', 'T', 'C', 'I') 237 | #define DDSKTX__DDS_ASTC4x4 stc__makefourcc('A', 'S', '4', '4') 238 | #define DDSKTX__DDS_ASTC5x5 stc__makefourcc('A', 'S', '5', '5') 239 | #define DDSKTX__DDS_ASTC6x6 stc__makefourcc('A', 'S', '6', '6') 240 | #define DDSKTX__DDS_ASTC8x5 stc__makefourcc('A', 'S', '8', '5') 241 | #define DDSKTX__DDS_ASTC8x6 stc__makefourcc('A', 'S', '8', '6') 242 | #define DDSKTX__DDS_ASTC10x5 stc__makefourcc('A', 'S', ':', '5') 243 | 244 | #define DDSKTX__DDS_R8G8B8 20 245 | #define DDSKTX__DDS_A8R8G8B8 21 246 | #define DDSKTX__DDS_R5G6B5 23 247 | #define DDSKTX__DDS_A1R5G5B5 25 248 | #define DDSKTX__DDS_A4R4G4B4 26 249 | #define DDSKTX__DDS_A2B10G10R10 31 250 | #define DDSKTX__DDS_G16R16 34 251 | #define DDSKTX__DDS_A2R10G10B10 35 252 | #define DDSKTX__DDS_A16B16G16R16 36 253 | #define DDSKTX__DDS_A8L8 51 254 | #define DDSKTX__DDS_R16F 111 255 | #define DDSKTX__DDS_G16R16F 112 256 | #define DDSKTX__DDS_A16B16G16R16F 113 257 | #define DDSKTX__DDS_R32F 114 258 | #define DDSKTX__DDS_G32R32F 115 259 | #define DDSKTX__DDS_A32B32G32R32F 116 260 | 261 | #define DDSKTX__DDS_FORMAT_R32G32B32A32_FLOAT 2 262 | #define DDSKTX__DDS_FORMAT_R32G32B32A32_UINT 3 263 | #define DDSKTX__DDS_FORMAT_R16G16B16A16_FLOAT 10 264 | #define DDSKTX__DDS_FORMAT_R16G16B16A16_UNORM 11 265 | #define DDSKTX__DDS_FORMAT_R16G16B16A16_UINT 12 266 | #define DDSKTX__DDS_FORMAT_R32G32_FLOAT 16 267 | #define DDSKTX__DDS_FORMAT_R32G32_UINT 17 268 | #define DDSKTX__DDS_FORMAT_R10G10B10A2_UNORM 24 269 | #define DDSKTX__DDS_FORMAT_R11G11B10_FLOAT 26 270 | #define DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM 28 271 | #define DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM_SRGB 29 272 | #define DDSKTX__DDS_FORMAT_R16G16_FLOAT 34 273 | #define DDSKTX__DDS_FORMAT_R16G16_UNORM 35 274 | #define DDSKTX__DDS_FORMAT_R32_FLOAT 41 275 | #define DDSKTX__DDS_FORMAT_R32_UINT 42 276 | #define DDSKTX__DDS_FORMAT_R8G8_UNORM 49 277 | #define DDSKTX__DDS_FORMAT_R16_FLOAT 54 278 | #define DDSKTX__DDS_FORMAT_R16_UNORM 56 279 | #define DDSKTX__DDS_FORMAT_R8_UNORM 61 280 | #define DDSKTX__DDS_FORMAT_R1_UNORM 66 281 | #define DDSKTX__DDS_FORMAT_BC1_UNORM 71 282 | #define DDSKTX__DDS_FORMAT_BC1_UNORM_SRGB 72 283 | #define DDSKTX__DDS_FORMAT_BC2_UNORM 74 284 | #define DDSKTX__DDS_FORMAT_BC2_UNORM_SRGB 75 285 | #define DDSKTX__DDS_FORMAT_BC3_UNORM 77 286 | #define DDSKTX__DDS_FORMAT_BC3_UNORM_SRGB 78 287 | #define DDSKTX__DDS_FORMAT_BC4_UNORM 80 288 | #define DDSKTX__DDS_FORMAT_BC5_UNORM 83 289 | #define DDSKTX__DDS_FORMAT_B5G6R5_UNORM 85 290 | #define DDSKTX__DDS_FORMAT_B5G5R5A1_UNORM 86 291 | #define DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM 87 292 | #define DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM_SRGB 91 293 | #define DDSKTX__DDS_FORMAT_BC6H_SF16 96 294 | #define DDSKTX__DDS_FORMAT_BC7_UNORM 98 295 | #define DDSKTX__DDS_FORMAT_BC7_UNORM_SRGB 99 296 | #define DDSKTX__DDS_FORMAT_B4G4R4A4_UNORM 115 297 | 298 | #define DDSKTX__DDS_DX10_DIMENSION_TEXTURE2D 3 299 | #define DDSKTX__DDS_DX10_DIMENSION_TEXTURE3D 4 300 | #define DDSKTX__DDS_DX10_MISC_TEXTURECUBE 4 301 | 302 | #define DDSKTX__DDSD_CAPS 0x00000001 303 | #define DDSKTX__DDSD_HEIGHT 0x00000002 304 | #define DDSKTX__DDSD_WIDTH 0x00000004 305 | #define DDSKTX__DDSD_PITCH 0x00000008 306 | #define DDSKTX__DDSD_PIXELFORMAT 0x00001000 307 | #define DDSKTX__DDSD_MIPMAPCOUNT 0x00020000 308 | #define DDSKTX__DDSD_LINEARSIZE 0x00080000 309 | #define DDSKTX__DDSD_DEPTH 0x00800000 310 | 311 | #define DDSKTX__DDPF_ALPHAPIXELS 0x00000001 312 | #define DDSKTX__DDPF_ALPHA 0x00000002 313 | #define DDSKTX__DDPF_FOURCC 0x00000004 314 | #define DDSKTX__DDPF_INDEXED 0x00000020 315 | #define DDSKTX__DDPF_RGB 0x00000040 316 | #define DDSKTX__DDPF_YUV 0x00000200 317 | #define DDSKTX__DDPF_LUMINANCE 0x00020000 318 | #define DDSKTX__DDPF_BUMPDUDV 0x00080000 319 | 320 | #define DDSKTX__DDSCAPS_COMPLEX 0x00000008 321 | #define DDSKTX__DDSCAPS_TEXTURE 0x00001000 322 | #define DDSKTX__DDSCAPS_MIPMAP 0x00400000 323 | 324 | #define DDSKTX__DDSCAPS2_VOLUME 0x00200000 325 | #define DDSKTX__DDSCAPS2_CUBEMAP 0x00000200 326 | #define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400 327 | #define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800 328 | #define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000 329 | #define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000 330 | #define DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000 331 | #define DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000 332 | 333 | #define DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES (0 \ 334 | | DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEX \ 335 | | DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEX \ 336 | | DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEY \ 337 | | DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEY \ 338 | | DDSKTX__DDSCAPS2_CUBEMAP_POSITIVEZ \ 339 | | DDSKTX__DDSCAPS2_CUBEMAP_NEGATIVEZ ) 340 | 341 | #pragma pack(push, 1) 342 | typedef struct ddsktx__dds_pixel_format 343 | { 344 | uint32_t size; 345 | uint32_t flags; 346 | uint32_t fourcc; 347 | uint32_t rgb_bit_count; 348 | uint32_t bit_mask[4]; 349 | } ddsktx__dds_pixel_format; 350 | 351 | // https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dds-header 352 | typedef struct ddsktx__dds_header 353 | { 354 | uint32_t size; 355 | uint32_t flags; 356 | uint32_t height; 357 | uint32_t width; 358 | uint32_t pitch_lin_size; 359 | uint32_t depth; 360 | uint32_t mip_count; 361 | uint32_t reserved1[11]; 362 | ddsktx__dds_pixel_format pixel_format; 363 | uint32_t caps1; 364 | uint32_t caps2; 365 | uint32_t caps3; 366 | uint32_t caps4; 367 | uint32_t reserved2; 368 | } ddsktx__dds_header; 369 | 370 | // https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dds-header-dxt10 371 | typedef struct ddsktx__dds_header_dxgi 372 | { 373 | uint32_t dxgi_format; 374 | uint32_t dimension; 375 | uint32_t misc_flags; 376 | uint32_t array_size; 377 | uint32_t misc_flags2; 378 | } ddsktx__dds_header_dxgi; 379 | 380 | typedef struct ddsktx__ktx_header 381 | { 382 | uint8_t id[8]; 383 | uint32_t endianess; 384 | uint32_t type; 385 | uint32_t type_size; 386 | uint32_t format; 387 | uint32_t internal_format; 388 | uint32_t base_internal_format; 389 | uint32_t width; 390 | uint32_t height; 391 | uint32_t depth; 392 | uint32_t array_count; 393 | uint32_t face_count; 394 | uint32_t mip_count; 395 | uint32_t metadata_size; 396 | } ddsktx__ktx_header; 397 | #pragma pack(pop) 398 | 399 | typedef struct ddsktx__dds_translate_fourcc_format 400 | { 401 | uint32_t dds_format; 402 | ddsktx_format format; 403 | bool srgb; 404 | } ddsktx__dds_translate_fourcc_format; 405 | 406 | typedef struct ddsktx__dds_translate_pixel_format 407 | { 408 | uint32_t bit_count; 409 | uint32_t flags; 410 | uint32_t bit_mask[4]; 411 | ddsktx_format format; 412 | } ddsktx__dds_translate_pixel_format; 413 | 414 | typedef struct ddsktx__mem_reader 415 | { 416 | const uint8_t* buff; 417 | int total; 418 | int offset; 419 | } ddsktx__mem_reader; 420 | 421 | typedef struct ddsktx__block_info 422 | { 423 | uint8_t bpp; 424 | uint8_t block_width; 425 | uint8_t block_height; 426 | uint8_t block_size; 427 | uint8_t min_block_x; 428 | uint8_t min_block_y; 429 | uint8_t depth_bits; 430 | uint8_t stencil_bits; 431 | uint8_t r_bits; 432 | uint8_t g_bits; 433 | uint8_t b_bits; 434 | uint8_t a_bits; 435 | uint8_t encoding; 436 | } ddsktx__block_info; 437 | 438 | #ifndef ddsktx_memcpy 439 | # include 440 | # define ddsktx_memcpy(_dst, _src, _size) memcpy((_dst), (_src), (_size)) 441 | #endif 442 | 443 | #ifndef ddsktx_memset 444 | # include 445 | # define ddsktx_memset(_dst, _v, _size) memset((_dst), (_v), (_size)) 446 | #endif 447 | 448 | #ifndef ddsktx_assert 449 | # include 450 | # define ddsktx_assert(_a) assert(_a) 451 | #endif 452 | 453 | #ifndef ddsktx_strcpy 454 | # include 455 | # ifdef _MSC_VER 456 | # define ddsktx_strcpy(_dst, _src) strcpy_s((_dst), sizeof(_dst), (_src)) 457 | # else 458 | # define ddsktx_strcpy(_dst, _src) strcpy((_dst), (_src)) 459 | # endif 460 | #endif 461 | 462 | #ifndef ddsktx_memcmp 463 | # include 464 | # define ddsktx_memcmp(_ptr1, _ptr2, _num) memcmp((_ptr1), (_ptr2), (_num)) 465 | #endif 466 | 467 | #define ddsktx__max(a, b) ((a) > (b) ? (a) : (b)) 468 | #define ddsktx__min(a, b) ((a) < (b) ? (a) : (b)) 469 | #define ddsktx__align_mask(_value, _mask) (((_value)+(_mask)) & ((~0)&(~(_mask)))) 470 | #define ddsktx__err(_err, _msg) if (_err) ddsktx_strcpy(_err->msg, _msg); return false 471 | 472 | static const ddsktx__dds_translate_fourcc_format k__translate_dds_fourcc[] = { 473 | { DDSKTX__DDS_DXT1, DDSKTX_FORMAT_BC1, false }, 474 | { DDSKTX__DDS_DXT2, DDSKTX_FORMAT_BC2, false }, 475 | { DDSKTX__DDS_DXT3, DDSKTX_FORMAT_BC2, false }, 476 | { DDSKTX__DDS_DXT4, DDSKTX_FORMAT_BC3, false }, 477 | { DDSKTX__DDS_DXT5, DDSKTX_FORMAT_BC3, false }, 478 | { DDSKTX__DDS_ATI1, DDSKTX_FORMAT_BC4, false }, 479 | { DDSKTX__DDS_BC4U, DDSKTX_FORMAT_BC4, false }, 480 | { DDSKTX__DDS_ATI2, DDSKTX_FORMAT_BC5, false }, 481 | { DDSKTX__DDS_BC5U, DDSKTX_FORMAT_BC5, false }, 482 | { DDSKTX__DDS_ETC1, DDSKTX_FORMAT_ETC1, false }, 483 | { DDSKTX__DDS_ETC2, DDSKTX_FORMAT_ETC2, false }, 484 | { DDSKTX__DDS_ET2A, DDSKTX_FORMAT_ETC2A, false }, 485 | { DDSKTX__DDS_PTC2, DDSKTX_FORMAT_PTC12A, false }, 486 | { DDSKTX__DDS_PTC4, DDSKTX_FORMAT_PTC14A, false }, 487 | { DDSKTX__DDS_ATC , DDSKTX_FORMAT_ATC, false }, 488 | { DDSKTX__DDS_ATCE, DDSKTX_FORMAT_ATCE, false }, 489 | { DDSKTX__DDS_ATCI, DDSKTX_FORMAT_ATCI, false }, 490 | { DDSKTX__DDS_ASTC4x4, DDSKTX_FORMAT_ASTC4x4, false }, 491 | { DDSKTX__DDS_ASTC5x5, DDSKTX_FORMAT_ASTC5x5, false }, 492 | { DDSKTX__DDS_ASTC6x6, DDSKTX_FORMAT_ASTC6x6, false }, 493 | { DDSKTX__DDS_ASTC8x5, DDSKTX_FORMAT_ASTC8x5, false }, 494 | { DDSKTX__DDS_ASTC8x6, DDSKTX_FORMAT_ASTC8x6, false }, 495 | { DDSKTX__DDS_ASTC10x5, DDSKTX_FORMAT_ASTC10x5, false }, 496 | { DDSKTX__DDS_A16B16G16R16, DDSKTX_FORMAT_RGBA16, false }, 497 | { DDSKTX__DDS_A16B16G16R16F, DDSKTX_FORMAT_RGBA16F, false }, 498 | { DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, DDSKTX_FORMAT_BGRA8, false }, 499 | { DDSKTX__DDPF_INDEXED, DDSKTX_FORMAT_R8, false }, 500 | { DDSKTX__DDPF_LUMINANCE, DDSKTX_FORMAT_R8, false }, 501 | { DDSKTX__DDPF_ALPHA, DDSKTX_FORMAT_R8, false }, 502 | { DDSKTX__DDS_R16F, DDSKTX_FORMAT_R16F, false }, 503 | { DDSKTX__DDS_R32F, DDSKTX_FORMAT_R32F, false }, 504 | { DDSKTX__DDS_A8L8, DDSKTX_FORMAT_RG8, false }, 505 | { DDSKTX__DDS_G16R16, DDSKTX_FORMAT_RG16, false }, 506 | { DDSKTX__DDS_G16R16F, DDSKTX_FORMAT_RG16F, false }, 507 | { DDSKTX__DDS_R8G8B8, DDSKTX_FORMAT_RGB8, false }, 508 | { DDSKTX__DDS_A8R8G8B8, DDSKTX_FORMAT_BGRA8, false }, 509 | { DDSKTX__DDS_A16B16G16R16, DDSKTX_FORMAT_RGBA16, false }, 510 | { DDSKTX__DDS_A16B16G16R16F, DDSKTX_FORMAT_RGBA16F, false }, 511 | { DDSKTX__DDS_A2B10G10R10, DDSKTX_FORMAT_RGB10A2, false }, 512 | }; 513 | 514 | static const ddsktx__dds_translate_fourcc_format k__translate_dxgi[] = { 515 | { DDSKTX__DDS_FORMAT_BC1_UNORM, DDSKTX_FORMAT_BC1, false }, 516 | { DDSKTX__DDS_FORMAT_BC1_UNORM_SRGB, DDSKTX_FORMAT_BC1, true }, 517 | { DDSKTX__DDS_FORMAT_BC2_UNORM, DDSKTX_FORMAT_BC2, false }, 518 | { DDSKTX__DDS_FORMAT_BC2_UNORM_SRGB, DDSKTX_FORMAT_BC2, true }, 519 | { DDSKTX__DDS_FORMAT_BC3_UNORM, DDSKTX_FORMAT_BC3, false }, 520 | { DDSKTX__DDS_FORMAT_BC3_UNORM_SRGB, DDSKTX_FORMAT_BC3, true }, 521 | { DDSKTX__DDS_FORMAT_BC4_UNORM, DDSKTX_FORMAT_BC4, false }, 522 | { DDSKTX__DDS_FORMAT_BC5_UNORM, DDSKTX_FORMAT_BC5, false }, 523 | { DDSKTX__DDS_FORMAT_BC6H_SF16, DDSKTX_FORMAT_BC6H, false }, 524 | { DDSKTX__DDS_FORMAT_BC7_UNORM, DDSKTX_FORMAT_BC7, false }, 525 | { DDSKTX__DDS_FORMAT_BC7_UNORM_SRGB, DDSKTX_FORMAT_BC7, true }, 526 | 527 | { DDSKTX__DDS_FORMAT_R8_UNORM, DDSKTX_FORMAT_R8, false }, 528 | { DDSKTX__DDS_FORMAT_R16_UNORM, DDSKTX_FORMAT_R16, false }, 529 | { DDSKTX__DDS_FORMAT_R16_FLOAT, DDSKTX_FORMAT_R16F, false }, 530 | { DDSKTX__DDS_FORMAT_R32_FLOAT, DDSKTX_FORMAT_R32F, false }, 531 | { DDSKTX__DDS_FORMAT_R8G8_UNORM, DDSKTX_FORMAT_RG8, false }, 532 | { DDSKTX__DDS_FORMAT_R16G16_UNORM, DDSKTX_FORMAT_RG16, false }, 533 | { DDSKTX__DDS_FORMAT_R16G16_FLOAT, DDSKTX_FORMAT_RG16F, false }, 534 | { DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM, DDSKTX_FORMAT_BGRA8, false }, 535 | { DDSKTX__DDS_FORMAT_B8G8R8A8_UNORM_SRGB, DDSKTX_FORMAT_BGRA8, true }, 536 | { DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM, DDSKTX_FORMAT_RGBA8, false }, 537 | { DDSKTX__DDS_FORMAT_R8G8B8A8_UNORM_SRGB, DDSKTX_FORMAT_RGBA8, true }, 538 | { DDSKTX__DDS_FORMAT_R16G16B16A16_UNORM, DDSKTX_FORMAT_RGBA16, false }, 539 | { DDSKTX__DDS_FORMAT_R16G16B16A16_FLOAT, DDSKTX_FORMAT_RGBA16F, false }, 540 | { DDSKTX__DDS_FORMAT_R10G10B10A2_UNORM, DDSKTX_FORMAT_RGB10A2, false }, 541 | { DDSKTX__DDS_FORMAT_R11G11B10_FLOAT, DDSKTX_FORMAT_RG11B10F, false }, 542 | }; 543 | 544 | static const ddsktx__dds_translate_pixel_format k__translate_dds_pixel[] = { 545 | { 8, DDSKTX__DDPF_LUMINANCE, { 0x000000ff, 0x00000000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_R8 }, 546 | { 16, DDSKTX__DDPF_BUMPDUDV, { 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG8S }, 547 | { 24, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_RGB8 }, 548 | { 24, DDSKTX__DDPF_RGB, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }, DDSKTX_FORMAT_RGB8 }, 549 | { 32, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_BGRA8 }, 550 | { 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, DDSKTX_FORMAT_RGBA8 }, 551 | { 32, DDSKTX__DDPF_BUMPDUDV, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, DDSKTX_FORMAT_RGBA8S }, 552 | { 32, DDSKTX__DDPF_RGB, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSKTX_FORMAT_BGRA8 }, 553 | { 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSKTX_FORMAT_BGRA8 }, // D3DFMT_A8R8G8B8 554 | { 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, DDSKTX_FORMAT_BGRA8 }, // D3DFMT_X8R8G8B8 555 | { 32, DDSKTX__DDPF_RGB|DDSKTX__DDPF_ALPHAPIXELS, { 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 }, DDSKTX_FORMAT_RGB10A2 }, 556 | { 32, DDSKTX__DDPF_RGB, { 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG16 }, 557 | { 32, DDSKTX__DDPF_BUMPDUDV, { 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }, DDSKTX_FORMAT_RG16S } 558 | }; 559 | 560 | typedef enum ddsktx__encode_type 561 | { 562 | DDSKTX__ENCODE_UNORM, 563 | DDSKTX__ENCODE_SNORM, 564 | DDSKTX__ENCODE_FLOAT, 565 | DDSKTX__ENCODE_INT, 566 | DDSKTX__ENCODE_UINT, 567 | DDSKTX__ENCODE_COUNT 568 | } ddsktx__encode_type; 569 | 570 | static const ddsktx__block_info k__block_info[] = 571 | { 572 | // +-------------------------------------------- bits per pixel 573 | // | +----------------------------------------- block width 574 | // | | +-------------------------------------- block height 575 | // | | | +---------------------------------- block size 576 | // | | | | +------------------------------- min blocks x 577 | // | | | | | +---------------------------- min blocks y 578 | // | | | | | | +------------------------ depth bits 579 | // | | | | | | | +--------------------- stencil bits 580 | // | | | | | | | | +---+---+---+----- r, g, b, a bits 581 | // | | | | | | | | r g b a +-- encoding type 582 | // | | | | | | | | | | | | | 583 | { 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC1 584 | { 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC2 585 | { 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC3 586 | { 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC4 587 | { 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC5 588 | { 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // BC6H 589 | { 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BC7 590 | { 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC1 591 | { 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2 592 | { 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2A 593 | { 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ETC2A1 594 | { 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC12 595 | { 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC14 596 | { 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC12A 597 | { 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC14A 598 | { 2, 8, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC22 599 | { 4, 4, 4, 8, 2, 2, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // PTC24 600 | { 4, 4, 4, 8, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATC 601 | { 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATCE 602 | { 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ATCI 603 | { 8, 4, 4, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC4x4 604 | { 6, 5, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC5x5 605 | { 4, 6, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC6x6 606 | { 4, 8, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC8x5 607 | { 3, 8, 6, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC8x6 608 | { 3, 10, 5, 16, 1, 1, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // ASTC10x5 609 | { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_COUNT) }, // Unknown 610 | { 8, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // A8 611 | { 8, 1, 1, 1, 1, 1, 0, 0, 8, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // R8 612 | { 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGBA8 613 | { 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_SNORM) }, // RGBA8S 614 | { 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG16 615 | { 24, 1, 1, 3, 1, 1, 0, 0, 8, 8, 8, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGB8 616 | { 16, 1, 1, 2, 1, 1, 0, 0, 16, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // R16 617 | { 32, 1, 1, 4, 1, 1, 0, 0, 32, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // R32F 618 | { 16, 1, 1, 2, 1, 1, 0, 0, 16, 0, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // R16F 619 | { 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // RG16F 620 | { 32, 1, 1, 4, 1, 1, 0, 0, 16, 16, 0, 0, (uint8_t)(DDSKTX__ENCODE_SNORM) }, // RG16S 621 | { 64, 1, 1, 8, 1, 1, 0, 0, 16, 16, 16, 16, (uint8_t)(DDSKTX__ENCODE_FLOAT) }, // RGBA16F 622 | { 64, 1, 1, 8, 1, 1, 0, 0, 16, 16, 16, 16, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGBA16 623 | { 32, 1, 1, 4, 1, 1, 0, 0, 8, 8, 8, 8, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // BGRA8 624 | { 32, 1, 1, 4, 1, 1, 0, 0, 10, 10, 10, 2, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RGB10A2 625 | { 32, 1, 1, 4, 1, 1, 0, 0, 11, 11, 10, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG11B10F 626 | { 16, 1, 1, 2, 1, 1, 0, 0, 8, 8, 0, 0, (uint8_t)(DDSKTX__ENCODE_UNORM) }, // RG8 627 | { 16, 1, 1, 2, 1, 1, 0, 0, 8, 8, 0, 0, (uint8_t)(DDSKTX__ENCODE_SNORM) } // RG8S 628 | }; 629 | 630 | // KTX: https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ 631 | #define DDSKTX__KTX_MAGIC stc__makefourcc(0xAB, 'K', 'T', 'X') 632 | #define DDSKTX__KTX_HEADER_SIZE 60 // actual header size is 64, but we read 4 bytes for the 'magic' 633 | 634 | #define DDSKTX__KTX_ETC1_RGB8_OES 0x8D64 635 | #define DDSKTX__KTX_COMPRESSED_R11_EAC 0x9270 636 | #define DDSKTX__KTX_COMPRESSED_SIGNED_R11_EAC 0x9271 637 | #define DDSKTX__KTX_COMPRESSED_RG11_EAC 0x9272 638 | #define DDSKTX__KTX_COMPRESSED_SIGNED_RG11_EAC 0x9273 639 | #define DDSKTX__KTX_COMPRESSED_RGB8_ETC2 0x9274 640 | #define DDSKTX__KTX_COMPRESSED_SRGB8_ETC2 0x9275 641 | #define DDSKTX__KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 642 | #define DDSKTX__KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 643 | #define DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC 0x9278 644 | #define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 645 | #define DDSKTX__KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 646 | #define DDSKTX__KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 647 | #define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 648 | #define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 649 | #define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137 650 | #define DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138 651 | #define DDSKTX__KTX_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 652 | #define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 653 | #define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 654 | #define DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 655 | #define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D 656 | #define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E 657 | #define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F 658 | #define DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 659 | #define DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 660 | #define DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C 661 | #define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D 662 | #define DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E 663 | #define DDSKTX__KTX_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F 664 | #define DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54 665 | #define DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55 666 | #define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56 667 | #define DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57 668 | #define DDSKTX__KTX_ATC_RGB_AMD 0x8C92 669 | #define DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 670 | #define DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE 671 | #define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_4x4_KHR 0x93B0 672 | #define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_5x5_KHR 0x93B2 673 | #define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_6x6_KHR 0x93B4 674 | #define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x5_KHR 0x93B5 675 | #define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x6_KHR 0x93B6 676 | #define DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_10x5_KHR 0x93B8 677 | #define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_4x4_KHR 0x93D0 678 | #define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_5x5_KHR 0x93D2 679 | #define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_6x6_KHR 0x93D4 680 | #define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_8x5_KHR 0x93D5 681 | #define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_8x6_KHR 0x93D6 682 | #define DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_10x5_KHR 0x93D8 683 | 684 | #define DDSKTX__KTX_A8 0x803C 685 | #define DDSKTX__KTX_R8 0x8229 686 | #define DDSKTX__KTX_R16 0x822A 687 | #define DDSKTX__KTX_RG8 0x822B 688 | #define DDSKTX__KTX_RG16 0x822C 689 | #define DDSKTX__KTX_R16F 0x822D 690 | #define DDSKTX__KTX_R32F 0x822E 691 | #define DDSKTX__KTX_RG16F 0x822F 692 | #define DDSKTX__KTX_RG32F 0x8230 693 | #define DDSKTX__KTX_RGBA8 0x8058 694 | #define DDSKTX__KTX_RGBA16 0x805B 695 | #define DDSKTX__KTX_RGBA16F 0x881A 696 | #define DDSKTX__KTX_R32UI 0x8236 697 | #define DDSKTX__KTX_RG32UI 0x823C 698 | #define DDSKTX__KTX_RGBA32UI 0x8D70 699 | #define DDSKTX__KTX_RGBA32F 0x8814 700 | #define DDSKTX__KTX_RGB565 0x8D62 701 | #define DDSKTX__KTX_RGBA4 0x8056 702 | #define DDSKTX__KTX_RGB5_A1 0x8057 703 | #define DDSKTX__KTX_RGB10_A2 0x8059 704 | #define DDSKTX__KTX_R8I 0x8231 705 | #define DDSKTX__KTX_R8UI 0x8232 706 | #define DDSKTX__KTX_R16I 0x8233 707 | #define DDSKTX__KTX_R16UI 0x8234 708 | #define DDSKTX__KTX_R32I 0x8235 709 | #define DDSKTX__KTX_R32UI 0x8236 710 | #define DDSKTX__KTX_RG8I 0x8237 711 | #define DDSKTX__KTX_RG8UI 0x8238 712 | #define DDSKTX__KTX_RG16I 0x8239 713 | #define DDSKTX__KTX_RG16UI 0x823A 714 | #define DDSKTX__KTX_RG32I 0x823B 715 | #define DDSKTX__KTX_RG32UI 0x823C 716 | #define DDSKTX__KTX_R8_SNORM 0x8F94 717 | #define DDSKTX__KTX_RG8_SNORM 0x8F95 718 | #define DDSKTX__KTX_RGB8_SNORM 0x8F96 719 | #define DDSKTX__KTX_RGBA8_SNORM 0x8F97 720 | #define DDSKTX__KTX_R16_SNORM 0x8F98 721 | #define DDSKTX__KTX_RG16_SNORM 0x8F99 722 | #define DDSKTX__KTX_RGB16_SNORM 0x8F9A 723 | #define DDSKTX__KTX_RGBA16_SNORM 0x8F9B 724 | #define DDSKTX__KTX_SRGB8 0x8C41 725 | #define DDSKTX__KTX_SRGB8_ALPHA8 0x8C43 726 | #define DDSKTX__KTX_RGBA32UI 0x8D70 727 | #define DDSKTX__KTX_RGB32UI 0x8D71 728 | #define DDSKTX__KTX_RGBA16UI 0x8D76 729 | #define DDSKTX__KTX_RGB16UI 0x8D77 730 | #define DDSKTX__KTX_RGBA8UI 0x8D7C 731 | #define DDSKTX__KTX_RGB8UI 0x8D7D 732 | #define DDSKTX__KTX_RGBA32I 0x8D82 733 | #define DDSKTX__KTX_RGB32I 0x8D83 734 | #define DDSKTX__KTX_RGBA16I 0x8D88 735 | #define DDSKTX__KTX_RGB16I 0x8D89 736 | #define DDSKTX__KTX_RGBA8I 0x8D8E 737 | #define DDSKTX__KTX_RGB8 0x8051 738 | #define DDSKTX__KTX_RGB8I 0x8D8F 739 | #define DDSKTX__KTX_RGB9_E5 0x8C3D 740 | #define DDSKTX__KTX_R11F_G11F_B10F 0x8C3A 741 | 742 | #define DDSKTX__KTX_ZERO 0 743 | #define DDSKTX__KTX_RED 0x1903 744 | #define DDSKTX__KTX_ALPHA 0x1906 745 | #define DDSKTX__KTX_RGB 0x1907 746 | #define DDSKTX__KTX_RGBA 0x1908 747 | #define DDSKTX__KTX_BGRA 0x80E1 748 | #define DDSKTX__KTX_RG 0x8227 749 | 750 | #define DDSKTX__KTX_BYTE 0x1400 751 | #define DDSKTX__KTX_UNSIGNED_BYTE 0x1401 752 | #define DDSKTX__KTX_SHORT 0x1402 753 | #define DDSKTX__KTX_UNSIGNED_SHORT 0x1403 754 | #define DDSKTX__KTX_INT 0x1404 755 | #define DDSKTX__KTX_UNSIGNED_INT 0x1405 756 | #define DDSKTX__KTX_FLOAT 0x1406 757 | #define DDSKTX__KTX_HALF_FLOAT 0x140B 758 | #define DDSKTX__KTX_UNSIGNED_INT_5_9_9_9_REV 0x8C3E 759 | #define DDSKTX__KTX_UNSIGNED_SHORT_5_6_5 0x8363 760 | #define DDSKTX__KTX_UNSIGNED_SHORT_4_4_4_4 0x8033 761 | #define DDSKTX__KTX_UNSIGNED_SHORT_5_5_5_1 0x8034 762 | #define DDSKTX__KTX_UNSIGNED_INT_2_10_10_10_REV 0x8368 763 | #define DDSKTX__KTX_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B 764 | 765 | typedef struct ddsktx__ktx_format_info 766 | { 767 | uint32_t internal_fmt; 768 | uint32_t internal_fmt_srgb; 769 | uint32_t fmt; 770 | uint32_t type; 771 | } ddsktx__ktx_format_info; 772 | 773 | typedef struct ddsktx__ktx_format_info2 774 | { 775 | uint32_t internal_fmt; 776 | ddsktx_format format; 777 | } ddsktx__ktx_format_info2; 778 | 779 | static const ddsktx__ktx_format_info k__translate_ktx_fmt[] = { 780 | { DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT, DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT, DDSKTX__KTX_ZERO, }, // BC1 781 | { DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT, DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT, DDSKTX__KTX_ZERO, }, // BC2 782 | { DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT, DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, DDSKTX__KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT, DDSKTX__KTX_ZERO, }, // BC3 783 | { DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_LUMINANCE_LATC1_EXT, DDSKTX__KTX_ZERO, }, // BC4 784 | { DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, DDSKTX__KTX_ZERO, }, // BC5 785 | { DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, DDSKTX__KTX_ZERO, }, // BC6H 786 | { DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_BPTC_UNORM_ARB, DDSKTX__KTX_ZERO, }, // BC7 787 | { DDSKTX__KTX_ETC1_RGB8_OES, DDSKTX__KTX_ZERO, DDSKTX__KTX_ETC1_RGB8_OES, DDSKTX__KTX_ZERO, }, // ETC1 788 | { DDSKTX__KTX_COMPRESSED_RGB8_ETC2, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGB8_ETC2, DDSKTX__KTX_ZERO, }, // ETC2 789 | { DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC, DDSKTX__KTX_COMPRESSED_SRGB8_ETC2, DDSKTX__KTX_COMPRESSED_RGBA8_ETC2_EAC, DDSKTX__KTX_ZERO, }, // ETC2A 790 | { DDSKTX__KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DDSKTX__KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DDSKTX__KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DDSKTX__KTX_ZERO, }, // ETC2A1 791 | { DDSKTX__KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT, DDSKTX__KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, DDSKTX__KTX_ZERO, }, // PTC12 792 | { DDSKTX__KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, DDSKTX__KTX_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT, DDSKTX__KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, DDSKTX__KTX_ZERO, }, // PTC14 793 | { DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, DDSKTX__KTX_ZERO, }, // PTC12A 794 | { DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, DDSKTX__KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, DDSKTX__KTX_ZERO, }, // PTC14A 795 | { DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, DDSKTX__KTX_ZERO, }, // PTC22 796 | { DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, DDSKTX__KTX_ZERO, DDSKTX__KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, DDSKTX__KTX_ZERO, }, // PTC24 797 | { DDSKTX__KTX_ATC_RGB_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGB_AMD, DDSKTX__KTX_ZERO, }, // ATC 798 | { DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGBA_EXPLICIT_ALPHA_AMD, DDSKTX__KTX_ZERO, }, // ATCE 799 | { DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, DDSKTX__KTX_ZERO, DDSKTX__KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD, DDSKTX__KTX_ZERO, }, // ATCI 800 | { DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_4x4_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_4x4_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_4x4_KHR, DDSKTX__KTX_ZERO, }, // ASTC4x4 801 | { DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_5x5_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_5x5_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_5x5_KHR, DDSKTX__KTX_ZERO, }, // ASTC5x5 802 | { DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_6x6_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_6x6_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_6x6_KHR, DDSKTX__KTX_ZERO, }, // ASTC6x6 803 | { DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x5_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_8x5_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x5_KHR, DDSKTX__KTX_ZERO, }, // ASTC8x5 804 | { DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x6_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_8x6_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_8x6_KHR, DDSKTX__KTX_ZERO, }, // ASTC8x6 805 | { DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_10x5_KHR, DDSKTX__KTX_COMPRESSED_SRGB8_ALPHA8_ADDSKTX_10x5_KHR, DDSKTX__KTX_COMPRESSED_RGBA_ADDSKTX_10x5_KHR, DDSKTX__KTX_ZERO, }, // ASTC10x5 806 | { DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, DDSKTX__KTX_ZERO, }, // Unknown 807 | { DDSKTX__KTX_ALPHA, DDSKTX__KTX_ZERO, DDSKTX__KTX_ALPHA, DDSKTX__KTX_UNSIGNED_BYTE, }, // A8 808 | { DDSKTX__KTX_R8, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_BYTE, }, // R8 809 | { DDSKTX__KTX_RGBA8, DDSKTX__KTX_SRGB8_ALPHA8, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_BYTE, }, // RGBA8 810 | { DDSKTX__KTX_RGBA8_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_BYTE, }, // RGBA8S 811 | { DDSKTX__KTX_RG16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_UNSIGNED_SHORT, }, // RG16 812 | { DDSKTX__KTX_RGB8, DDSKTX__KTX_SRGB8, DDSKTX__KTX_RGB, DDSKTX__KTX_UNSIGNED_BYTE, }, // RGB8 813 | { DDSKTX__KTX_R16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16 814 | { DDSKTX__KTX_R32F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_FLOAT, }, // R32F 815 | { DDSKTX__KTX_R16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_HALF_FLOAT, }, // R16F 816 | { DDSKTX__KTX_RG16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_FLOAT, }, // RG16F 817 | { DDSKTX__KTX_RG16_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_SHORT, }, // RG16S 818 | { DDSKTX__KTX_RGBA16F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_HALF_FLOAT, }, // RGBA16F 819 | { DDSKTX__KTX_RGBA16, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_SHORT, }, // RGBA16 820 | { DDSKTX__KTX_BGRA, DDSKTX__KTX_SRGB8_ALPHA8, DDSKTX__KTX_BGRA, DDSKTX__KTX_UNSIGNED_BYTE, }, // BGRA8 821 | { DDSKTX__KTX_RGB10_A2, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGBA, DDSKTX__KTX_UNSIGNED_INT_2_10_10_10_REV, }, // RGB10A2 822 | { DDSKTX__KTX_R11F_G11F_B10F, DDSKTX__KTX_ZERO, DDSKTX__KTX_RGB, DDSKTX__KTX_UNSIGNED_INT_10F_11F_11F_REV, }, // RG11B10F 823 | { DDSKTX__KTX_RG8, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_UNSIGNED_BYTE, }, // RG8 824 | { DDSKTX__KTX_RG8_SNORM, DDSKTX__KTX_ZERO, DDSKTX__KTX_RG, DDSKTX__KTX_BYTE, }, // RG8S 825 | { DDSKTX__KTX_R16I, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16I 826 | { DDSKTX__KTX_R16UI, DDSKTX__KTX_ZERO, DDSKTX__KTX_RED, DDSKTX__KTX_UNSIGNED_SHORT, }, // R16UI 827 | }; 828 | 829 | static const ddsktx__ktx_format_info2 k__translate_ktx_fmt2[] = 830 | { 831 | { DDSKTX__KTX_A8, DDSKTX_FORMAT_A8 }, 832 | { DDSKTX__KTX_RED, DDSKTX_FORMAT_R8 }, 833 | { DDSKTX__KTX_RGB, DDSKTX_FORMAT_RGB8 }, 834 | { DDSKTX__KTX_RGBA, DDSKTX_FORMAT_RGBA8 }, 835 | { DDSKTX__KTX_COMPRESSED_RGB_S3TC_DXT1_EXT, DDSKTX_FORMAT_BC1 }, 836 | }; 837 | 838 | typedef struct ddsktx__format_info 839 | { 840 | const char* name; 841 | bool has_alpha; 842 | } ddsktx__format_info; 843 | 844 | static const ddsktx__format_info k__formats_info[] = { 845 | {"BC1", false}, 846 | {"BC2", true}, 847 | {"BC3", true}, 848 | {"BC4", false}, 849 | {"BC5", false}, 850 | {"BC6H", false}, 851 | {"BC7", true}, 852 | {"ETC1", false}, 853 | {"ETC2", false}, 854 | {"ETC2A", true}, 855 | {"ETC2A1", true}, 856 | {"PTC12", false}, 857 | {"PTC14", false}, 858 | {"PTC12A", true}, 859 | {"PTC14A", true}, 860 | {"PTC22", true}, 861 | {"PTC24", true}, 862 | {"ATC", false}, 863 | {"ATCE", false}, 864 | {"ATCI", false}, 865 | {"ASTC4x4", true}, 866 | {"ASTC5x5", true}, 867 | {"ASTC6x6", false}, 868 | {"ASTC8x5", true}, 869 | {"ASTC8x6", false}, 870 | {"ASTC10x5", false}, 871 | {"", false}, 872 | {"A8", true}, 873 | {"R8", false}, 874 | {"RGBA8", true}, 875 | {"RGBA8S", true}, 876 | {"RG16", false}, 877 | {"RGB8", false}, 878 | {"R16", false}, 879 | {"R32F", false}, 880 | {"R16F", false}, 881 | {"RG16F", false}, 882 | {"RG16S", false}, 883 | {"RGBA16F", true}, 884 | {"RGBA16",true}, 885 | {"BGRA8", true}, 886 | {"RGB10A2", true}, 887 | {"RG11B10F", false}, 888 | {"RG8", false}, 889 | {"RG8S", false} 890 | }; 891 | 892 | 893 | static inline int ddsktx__read(ddsktx__mem_reader* reader, void* buff, int size) 894 | { 895 | int read_bytes = (reader->offset + size) <= reader->total ? size : (reader->total - reader->offset); 896 | ddsktx_memcpy(buff, reader->buff + reader->offset, read_bytes); 897 | reader->offset += read_bytes; 898 | return read_bytes; 899 | } 900 | 901 | static bool ddsktx__parse_ktx(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err) 902 | { 903 | static const uint8_t ktx__id[] = { 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }; 904 | 905 | ddsktx_memset(tc, 0x0, sizeof(ddsktx_texture_info)); 906 | 907 | ddsktx__mem_reader r = {(const uint8_t*)file_data, size, sizeof(uint32_t)}; 908 | ddsktx__ktx_header header; 909 | if (ddsktx__read(&r, &header, sizeof(header)) != DDSKTX__KTX_HEADER_SIZE) { 910 | ddsktx__err(err, "ktx; header size does not match"); 911 | } 912 | 913 | if (ddsktx_memcmp(header.id, ktx__id, sizeof(header.id)) != 0) { 914 | ddsktx__err(err, "ktx: invalid file header"); 915 | } 916 | 917 | // TODO: support big endian 918 | if (header.endianess != 0x04030201) { 919 | ddsktx__err(err, "ktx: big-endian format is not supported"); 920 | } 921 | 922 | tc->metadata_offset = r.offset; 923 | tc->metadata_size = (int)header.metadata_size; 924 | r.offset += (int)header.metadata_size; 925 | 926 | ddsktx_format format = _DDSKTX_FORMAT_COUNT; 927 | 928 | int count = sizeof(k__translate_ktx_fmt)/sizeof(ddsktx__ktx_format_info); 929 | for (int i = 0; i < count; i++) { 930 | if (k__translate_ktx_fmt[i].internal_fmt == header.internal_format) { 931 | format = (ddsktx_format)i; 932 | break; 933 | } 934 | } 935 | 936 | if (format == _DDSKTX_FORMAT_COUNT) { 937 | count = sizeof(k__translate_ktx_fmt2)/sizeof(ddsktx__ktx_format_info2); 938 | for (int i = 0; i < count; i++) { 939 | if (k__translate_ktx_fmt2[i].internal_fmt == header.internal_format) { 940 | format = (ddsktx_format)k__translate_ktx_fmt2[i].format; 941 | break; 942 | } 943 | } 944 | } 945 | 946 | if (format == _DDSKTX_FORMAT_COUNT) { 947 | ddsktx__err(err, "ktx: unsupported format"); 948 | } 949 | 950 | if (header.face_count > 1 && header.face_count != DDSKTX_CUBE_FACE_COUNT) { 951 | ddsktx__err(err, "ktx: incomplete cubemap"); 952 | } 953 | 954 | tc->data_offset = r.offset; 955 | tc->size_bytes = r.total - r.offset; 956 | tc->format = format; 957 | tc->width = (int)header.width; 958 | tc->height = (int)header.height; 959 | tc->depth = ddsktx__max((int)header.depth, 1); 960 | tc->num_layers = ddsktx__max((int)header.array_count, 1); 961 | tc->num_mips = ddsktx__max((int)header.mip_count, 1); 962 | tc->bpp = k__block_info[format].bpp; 963 | 964 | if (header.face_count == 6) 965 | tc->flags |= DDSKTX_TEXTURE_FLAG_CUBEMAP; 966 | tc->flags |= k__formats_info[format].has_alpha ? DDSKTX_TEXTURE_FLAG_ALPHA : 0; 967 | tc->flags |= DDSKTX_TEXTURE_FLAG_KTX; 968 | 969 | return true; 970 | } 971 | 972 | static bool ddsktx__parse_dds(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err) 973 | { 974 | ddsktx__mem_reader r = {(const uint8_t*)file_data, size, sizeof(uint32_t)}; 975 | ddsktx__dds_header header; 976 | if (ddsktx__read(&r, &header, sizeof(header)) < DDSKTX__DDS_HEADER_SIZE || 977 | header.size != DDSKTX__DDS_HEADER_SIZE) 978 | { 979 | ddsktx__err(err, "dds: header size does not match"); 980 | } 981 | 982 | uint32_t required_flags = (DDSKTX__DDSD_HEIGHT|DDSKTX__DDSD_WIDTH); 983 | if ((header.flags & required_flags) != required_flags) { 984 | ddsktx__err(err, "dds: have invalid flags"); 985 | } 986 | 987 | if (header.pixel_format.size != sizeof(ddsktx__dds_pixel_format)) { 988 | ddsktx__err(err, "dds: pixel format header is invalid"); 989 | } 990 | 991 | uint32_t dxgi_format = 0; 992 | uint32_t array_size = 1; 993 | if (DDSKTX__DDPF_FOURCC == (header.flags & DDSKTX__DDPF_FOURCC) && 994 | header.pixel_format.fourcc == DDSKTX__DDS_DX10) 995 | { 996 | ddsktx__dds_header_dxgi dxgi_header; 997 | ddsktx__read(&r, &dxgi_header, sizeof(dxgi_header)); 998 | dxgi_format = dxgi_header.dxgi_format; 999 | array_size = dxgi_header.array_size; 1000 | } 1001 | 1002 | if ((header.caps1 & DDSKTX__DDSCAPS_TEXTURE) == 0) { 1003 | ddsktx__err(err, "dds: unsupported caps"); 1004 | } 1005 | 1006 | bool cubemap = (header.caps2 & DDSKTX__DDSCAPS2_CUBEMAP) != 0; 1007 | if (cubemap && (header.caps2 & DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES) != DDSKTX__DDSCAPS2_CUBEMAP_ALLSIDES) { 1008 | ddsktx__err(err, "dds: incomplete cubemap"); 1009 | } 1010 | bool volume = (header.caps2 & DDSKTX__DDSCAPS2_VOLUME) != 0; 1011 | 1012 | ddsktx_format format = _DDSKTX_FORMAT_COUNT; 1013 | bool has_alpha = (header.pixel_format.flags & DDSKTX__DDPF_ALPHA) != 0; 1014 | bool srgb = false; 1015 | 1016 | if (dxgi_format == 0) { 1017 | if ((header.pixel_format.flags & DDSKTX__DDPF_FOURCC) == DDSKTX__DDPF_FOURCC) { 1018 | int count = sizeof(k__translate_dds_fourcc)/sizeof(ddsktx__dds_translate_fourcc_format); 1019 | for (int i = 0; i < count; i++) { 1020 | if (k__translate_dds_fourcc[i].dds_format == header.pixel_format.fourcc) { 1021 | format = k__translate_dds_fourcc[i].format; 1022 | break; 1023 | } 1024 | } 1025 | } else { 1026 | int count = sizeof(k__translate_dds_pixel)/sizeof(ddsktx__dds_translate_pixel_format); 1027 | for (int i = 0; i < count; i++) { 1028 | const ddsktx__dds_translate_pixel_format* f = &k__translate_dds_pixel[i]; 1029 | if (f->bit_count == header.pixel_format.rgb_bit_count && 1030 | f->flags == header.pixel_format.flags && 1031 | f->bit_mask[0] == header.pixel_format.bit_mask[0] && 1032 | f->bit_mask[1] == header.pixel_format.bit_mask[1] && 1033 | f->bit_mask[2] == header.pixel_format.bit_mask[2] && 1034 | f->bit_mask[3] == header.pixel_format.bit_mask[3]) 1035 | { 1036 | format = f->format; 1037 | break; 1038 | } 1039 | } 1040 | } 1041 | } else { 1042 | int count = sizeof(k__translate_dxgi)/sizeof(ddsktx__dds_translate_fourcc_format); 1043 | for (int i = 0; i < count; i++) { 1044 | if (k__translate_dxgi[i].dds_format == dxgi_format) { 1045 | format = k__translate_dxgi[i].format; 1046 | srgb = k__translate_dxgi[i].srgb; 1047 | break; 1048 | } 1049 | } 1050 | } 1051 | 1052 | if (format == _DDSKTX_FORMAT_COUNT) { 1053 | ddsktx__err(err, "dds: unknown format"); 1054 | } 1055 | 1056 | ddsktx_memset(tc, 0x0, sizeof(ddsktx_texture_info)); 1057 | tc->data_offset = r.offset; 1058 | tc->size_bytes = r.total - r.offset; 1059 | tc->format = format; 1060 | tc->width = (int)header.width; 1061 | tc->height = (int)header.height; 1062 | tc->depth = ddsktx__max(1, (int)header.depth); 1063 | tc->num_layers = ddsktx__max(1, (int)array_size); 1064 | tc->num_mips = (header.caps1 & DDSKTX__DDSCAPS_MIPMAP) ? (int)header.mip_count : 1; 1065 | tc->bpp = k__block_info[format].bpp; 1066 | if (has_alpha || k__formats_info[format].has_alpha) 1067 | tc->flags |= DDSKTX_TEXTURE_FLAG_ALPHA; 1068 | if (cubemap) 1069 | tc->flags |= DDSKTX_TEXTURE_FLAG_CUBEMAP; 1070 | if (volume) 1071 | tc->flags |= DDSKTX_TEXTURE_FLAG_VOLUME; 1072 | if (srgb) 1073 | tc->flags |= DDSKTX_TEXTURE_FLAG_SRGB; 1074 | tc->flags |= DDSKTX_TEXTURE_FLAG_DDS; 1075 | 1076 | return true; 1077 | } 1078 | 1079 | void ddsktx_get_sub(const ddsktx_texture_info* tc, ddsktx_sub_data* sub_data, 1080 | const void* file_data, int size, 1081 | int array_idx, int slice_face_idx, int mip_idx) 1082 | { 1083 | ddsktx_assert(tc); 1084 | ddsktx_assert(sub_data); 1085 | ddsktx_assert(file_data); 1086 | ddsktx_assert(size > 0); 1087 | ddsktx_assert(array_idx < tc->num_layers); 1088 | ddsktx_assert(!((tc->flags&DDSKTX_TEXTURE_FLAG_CUBEMAP) && (slice_face_idx >= DDSKTX_CUBE_FACE_COUNT)) && "invalid cube-face index"); 1089 | ddsktx_assert(!(!(tc->flags&DDSKTX_TEXTURE_FLAG_CUBEMAP) && (slice_face_idx >= tc->depth)) && "invalid depth-slice index"); 1090 | ddsktx_assert(mip_idx < tc->num_mips); 1091 | 1092 | ddsktx__mem_reader r = { (uint8_t*)file_data, size, tc->data_offset }; 1093 | ddsktx_format format = tc->format; 1094 | 1095 | ddsktx_assert(format < _DDSKTX_FORMAT_COUNT && format != _DDSKTX_FORMAT_COMPRESSED); 1096 | const ddsktx__block_info* binfo = &k__block_info[format]; 1097 | const int bpp = binfo->bpp; 1098 | const int block_size = binfo->block_size; 1099 | const int min_block_x = binfo->min_block_x; 1100 | const int min_block_y = binfo->min_block_y; 1101 | 1102 | int num_faces; 1103 | 1104 | ddsktx_assert(!((tc->flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) && tc->depth > 1) && "textures must be either Cube or 3D"); 1105 | int slice_idx, face_idx, num_slices; 1106 | if (tc->flags & DDSKTX_TEXTURE_FLAG_CUBEMAP) { 1107 | slice_idx = 0; 1108 | face_idx = slice_face_idx; 1109 | num_faces = DDSKTX_CUBE_FACE_COUNT; 1110 | num_slices = 1; 1111 | } else { 1112 | slice_idx = slice_face_idx; 1113 | face_idx = 0; 1114 | num_faces = 1; 1115 | num_slices = tc->depth; 1116 | } 1117 | 1118 | if (tc->flags & DDSKTX_TEXTURE_FLAG_DDS) { 1119 | for (int layer = 0, num_layers = tc->num_layers; layer < num_layers; layer++) { 1120 | for (int face = 0; face < num_faces; face++) { 1121 | int width = tc->width; 1122 | int height = tc->height; 1123 | 1124 | for (int mip = 0, mip_count = tc->num_mips; mip < mip_count; mip++) { 1125 | int row_bytes, mip_size; 1126 | 1127 | if (format < _DDSKTX_FORMAT_COMPRESSED) { 1128 | int num_blocks_wide = width > 0 ? ddsktx__max(1, (width + 3)/4) : 0; 1129 | num_blocks_wide = ddsktx__max(min_block_x, num_blocks_wide); 1130 | 1131 | int num_blocks_high = height > 0 ? ddsktx__max(1, (height + 3)/4) : 0; 1132 | num_blocks_high = ddsktx__max(min_block_y, num_blocks_high); 1133 | 1134 | row_bytes = num_blocks_wide * block_size; 1135 | mip_size = row_bytes * num_blocks_high; 1136 | } else { 1137 | row_bytes = (width*bpp + 7)/8; // round to nearest byte 1138 | mip_size = row_bytes * height; 1139 | } 1140 | 1141 | for (int slice = 0; slice < num_slices; slice++) { 1142 | if (layer == array_idx && mip == mip_idx && 1143 | slice == slice_idx && face_idx == face) 1144 | { 1145 | sub_data->buff = r.buff + r.offset; 1146 | sub_data->width = width; 1147 | sub_data->height = height; 1148 | sub_data->size_bytes = mip_size; 1149 | sub_data->row_pitch_bytes = row_bytes; 1150 | return; 1151 | } 1152 | 1153 | r.offset += mip_size; 1154 | ddsktx_assert(r.offset <= r.total && "texture buffer overflow"); 1155 | } // foreach slice 1156 | 1157 | width >>= 1; 1158 | height >>= 1; 1159 | 1160 | if (width == 0) { 1161 | width = 1; 1162 | } 1163 | if (height == 0) { 1164 | height = 1; 1165 | } 1166 | } // foreach mip 1167 | } // foreach face 1168 | } // foreach array-item 1169 | } else if (tc->flags & DDSKTX_TEXTURE_FLAG_KTX) { 1170 | int width = tc->width; 1171 | int height = tc->height; 1172 | 1173 | for (int mip = 0, c = tc->num_mips; mip < c; mip++) { 1174 | int row_bytes, mip_size; 1175 | 1176 | if (format < _DDSKTX_FORMAT_COMPRESSED) { 1177 | int num_blocks_wide = width > 0 ? ddsktx__max(1, (width + 3)/4) : 0; 1178 | num_blocks_wide = ddsktx__max(min_block_x, num_blocks_wide); 1179 | 1180 | int num_blocks_high = height > 0 ? ddsktx__max(1, (height + 3)/4) : 0; 1181 | num_blocks_high = ddsktx__max(min_block_y, num_blocks_high); 1182 | 1183 | row_bytes = num_blocks_wide * block_size; 1184 | mip_size = row_bytes * num_blocks_high; 1185 | } 1186 | else { 1187 | row_bytes = (width*bpp + 7)/8; // round to nearest byte 1188 | mip_size = row_bytes * height; 1189 | } 1190 | 1191 | int image_size; 1192 | ddsktx__read(&r, &image_size, sizeof(image_size)); 1193 | ddsktx_assert(image_size == (mip_size*num_faces*num_slices) && "image size mismatch"); 1194 | 1195 | for (int layer = 0, num_layers = tc->num_layers; layer < num_layers; layer++) { 1196 | for (int face = 0; face < num_faces; face++) { 1197 | for (int slice = 0; slice < num_slices; slice++) { 1198 | if (layer == array_idx && mip == mip_idx && 1199 | slice == slice_idx && face_idx == face) 1200 | { 1201 | sub_data->buff = r.buff + r.offset; 1202 | sub_data->width = width; 1203 | sub_data->height = height; 1204 | sub_data->size_bytes = mip_size; 1205 | sub_data->row_pitch_bytes = row_bytes; 1206 | return; 1207 | } 1208 | 1209 | r.offset += mip_size; 1210 | ddsktx_assert(r.offset <= r.total && "texture buffer overflow"); 1211 | } // foreach slice 1212 | 1213 | 1214 | r.offset = ddsktx__align_mask(r.offset, 3); // cube-padding 1215 | } // foreach face 1216 | } // foreach array-item 1217 | 1218 | width >>= 1; 1219 | height >>= 1; 1220 | 1221 | if (width == 0) { 1222 | width = 1; 1223 | } 1224 | if (height == 0) { 1225 | height = 1; 1226 | } 1227 | 1228 | r.offset = ddsktx__align_mask(r.offset, 3); // mip-padding 1229 | } // foreach mip 1230 | } else { 1231 | ddsktx_assert(0 && "invalid file format"); 1232 | } 1233 | } 1234 | 1235 | bool ddsktx_parse(ddsktx_texture_info* tc, const void* file_data, int size, ddsktx_error* err) 1236 | { 1237 | ddsktx_assert(tc); 1238 | ddsktx_assert(file_data); 1239 | ddsktx_assert(size > 0); 1240 | 1241 | ddsktx__mem_reader r = {(const uint8_t*)file_data, size, 0}; 1242 | 1243 | // Read file flag and determine the file type 1244 | uint32_t file_flag = 0; 1245 | if (ddsktx__read(&r, &file_flag, sizeof(file_flag)) != sizeof(file_flag)) { 1246 | ddsktx__err(err, "invalid texture file"); 1247 | } 1248 | 1249 | switch (file_flag) { 1250 | case DDSKTX__DDS_MAGIC: 1251 | return ddsktx__parse_dds(tc, file_data, size, err); 1252 | case DDSKTX__KTX_MAGIC: 1253 | return ddsktx__parse_ktx(tc, file_data, size, err); 1254 | default: 1255 | ddsktx__err(err, "unknown texture format"); 1256 | } 1257 | } 1258 | 1259 | const char* ddsktx_format_str(ddsktx_format format) 1260 | { 1261 | return k__formats_info[format].name; 1262 | } 1263 | 1264 | bool ddsktx_format_compressed(ddsktx_format format) 1265 | { 1266 | ddsktx_assert(format != _DDSKTX_FORMAT_COMPRESSED && format != _DDSKTX_FORMAT_COUNT); 1267 | return format < _DDSKTX_FORMAT_COMPRESSED; 1268 | } 1269 | 1270 | #endif // DDSKTX_IMPLEMENT 1271 | 1272 | --------------------------------------------------------------------------------