Add support for KTX & KTX2 image format

Add support glTF KHR_texture_basisu extension
This commit is contained in:
acazuc 2023-04-28 18:26:01 +02:00
parent ff5c884153
commit a00cf02241
55 changed files with 20856 additions and 0 deletions

View File

@ -256,6 +256,12 @@ Comment: jpeg-compressor
Copyright: 2012, Rich Geldreich Copyright: 2012, Rich Geldreich
License: public-domain or Apache-2.0 License: public-domain or Apache-2.0
Files: ./thirdparty/libktx/
Comment: KTX
Copyright: 2013-2020, Mark Callow
2010-2020 The Khronos Group, Inc.
License: Apache-2.0
Files: ./thirdparty/libogg/ Files: ./thirdparty/libogg/
Comment: OggVorbis Comment: OggVorbis
Copyright: 2002, Xiph.org Foundation Copyright: 2002, Xiph.org Foundation

View File

@ -3018,6 +3018,7 @@ ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr; ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr;
ScalableImageMemLoadFunc Image::_svg_scalable_mem_loader_func = nullptr; ScalableImageMemLoadFunc Image::_svg_scalable_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_dds_mem_loader_func = nullptr; ImageMemLoadFunc Image::_dds_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_ktx_mem_loader_func = nullptr;
void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr; void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr; void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr;
@ -3490,6 +3491,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_tga_from_buffer", "buffer"), &Image::load_tga_from_buffer); ClassDB::bind_method(D_METHOD("load_tga_from_buffer", "buffer"), &Image::load_tga_from_buffer);
ClassDB::bind_method(D_METHOD("load_bmp_from_buffer", "buffer"), &Image::load_bmp_from_buffer); ClassDB::bind_method(D_METHOD("load_bmp_from_buffer", "buffer"), &Image::load_bmp_from_buffer);
ClassDB::bind_method(D_METHOD("load_dds_from_buffer", "buffer"), &Image::load_dds_from_buffer); ClassDB::bind_method(D_METHOD("load_dds_from_buffer", "buffer"), &Image::load_dds_from_buffer);
ClassDB::bind_method(D_METHOD("load_ktx_from_buffer", "buffer"), &Image::load_ktx_from_buffer);
ClassDB::bind_method(D_METHOD("load_svg_from_buffer", "buffer", "scale"), &Image::load_svg_from_buffer, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("load_svg_from_buffer", "buffer", "scale"), &Image::load_svg_from_buffer, DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("load_svg_from_string", "svg_str", "scale"), &Image::load_svg_from_string, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("load_svg_from_string", "svg_str", "scale"), &Image::load_svg_from_string, DEFVAL(1.0));
@ -3873,6 +3875,14 @@ Error Image::load_dds_from_buffer(const Vector<uint8_t> &p_array) {
return _load_from_buffer(p_array, _dds_mem_loader_func); return _load_from_buffer(p_array, _dds_mem_loader_func);
} }
Error Image::load_ktx_from_buffer(const Vector<uint8_t> &p_array) {
ERR_FAIL_NULL_V_MSG(
_ktx_mem_loader_func,
ERR_UNAVAILABLE,
"The KTX module isn't enabled. Recompile the Godot editor or export template binary with the `module_ktx_enabled=yes` SCons option.");
return _load_from_buffer(p_array, _ktx_mem_loader_func);
}
void Image::convert_rg_to_ra_rgba8() { void Image::convert_rg_to_ra_rgba8() {
ERR_FAIL_COND(format != FORMAT_RGBA8); ERR_FAIL_COND(format != FORMAT_RGBA8);
ERR_FAIL_COND(!data.size()); ERR_FAIL_COND(!data.size());

View File

@ -151,6 +151,7 @@ public:
static ImageMemLoadFunc _bmp_mem_loader_func; static ImageMemLoadFunc _bmp_mem_loader_func;
static ScalableImageMemLoadFunc _svg_scalable_mem_loader_func; static ScalableImageMemLoadFunc _svg_scalable_mem_loader_func;
static ImageMemLoadFunc _dds_mem_loader_func; static ImageMemLoadFunc _dds_mem_loader_func;
static ImageMemLoadFunc _ktx_mem_loader_func;
static void (*_image_compress_bc_func)(Image *, UsedChannels p_channels); static void (*_image_compress_bc_func)(Image *, UsedChannels p_channels);
static void (*_image_compress_bptc_func)(Image *, UsedChannels p_channels); static void (*_image_compress_bptc_func)(Image *, UsedChannels p_channels);
@ -404,6 +405,7 @@ public:
Error load_tga_from_buffer(const Vector<uint8_t> &p_array); Error load_tga_from_buffer(const Vector<uint8_t> &p_array);
Error load_bmp_from_buffer(const Vector<uint8_t> &p_array); Error load_bmp_from_buffer(const Vector<uint8_t> &p_array);
Error load_dds_from_buffer(const Vector<uint8_t> &p_array); Error load_dds_from_buffer(const Vector<uint8_t> &p_array);
Error load_ktx_from_buffer(const Vector<uint8_t> &p_array);
Error load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale = 1.0); Error load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale = 1.0);
Error load_svg_from_string(const String &p_svg_str, float scale = 1.0); Error load_svg_from_string(const String &p_svg_str, float scale = 1.0);

View File

@ -333,6 +333,13 @@
Loads an image from the binary contents of a JPEG file. Loads an image from the binary contents of a JPEG file.
</description> </description>
</method> </method>
<method name="load_ktx_from_buffer">
<return type="int" enum="Error" />
<param index="0" name="buffer" type="PackedByteArray" />
<description>
Loads an image from the binary contents of a KTX file.
</description>
</method>
<method name="load_png_from_buffer"> <method name="load_png_from_buffer">
<return type="int" enum="Error" /> <return type="int" enum="Error" />
<param index="0" name="buffer" type="PackedByteArray" /> <param index="0" name="buffer" type="PackedByteArray" />

View File

@ -0,0 +1,66 @@
/**************************************************************************/
/* gltf_document_extension_texture_ktx.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "gltf_document_extension_texture_ktx.h"
// Import process.
Error GLTFDocumentExtensionTextureKTX::import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) {
if (!p_extensions.has("KHR_texture_basisu")) {
return ERR_SKIP;
}
return OK;
}
Vector<String> GLTFDocumentExtensionTextureKTX::get_supported_extensions() {
Vector<String> ret;
ret.push_back("KHR_texture_basisu");
return ret;
}
Error GLTFDocumentExtensionTextureKTX::parse_image_data(Ref<GLTFState> p_state, const PackedByteArray &p_image_data, const String &p_mime_type, Ref<Image> r_image) {
if (p_mime_type == "image/ktx2") {
return r_image->load_ktx_from_buffer(p_image_data);
}
return OK;
}
Error GLTFDocumentExtensionTextureKTX::parse_texture_json(Ref<GLTFState> p_state, const Dictionary &p_texture_json, Ref<GLTFTexture> r_gltf_texture) {
if (!p_texture_json.has("extensions")) {
return OK;
}
const Dictionary &extensions = p_texture_json["extensions"];
if (!extensions.has("KHR_texture_basisu")) {
return OK;
}
const Dictionary &texture_ktx = extensions["KHR_texture_basisu"];
ERR_FAIL_COND_V(!texture_ktx.has("source"), ERR_PARSE_ERROR);
r_gltf_texture->set_src_image(texture_ktx["source"]);
return OK;
}

View File

@ -0,0 +1,47 @@
/**************************************************************************/
/* gltf_document_extension_texture_ktx.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GLTF_DOCUMENT_EXTENSION_TEXTURE_KTX_H
#define GLTF_DOCUMENT_EXTENSION_TEXTURE_KTX_H
#include "gltf_document_extension.h"
class GLTFDocumentExtensionTextureKTX : public GLTFDocumentExtension {
GDCLASS(GLTFDocumentExtensionTextureKTX, GLTFDocumentExtension);
public:
// Import process.
Error import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) override;
Vector<String> get_supported_extensions() override;
Error parse_image_data(Ref<GLTFState> p_state, const PackedByteArray &p_image_data, const String &p_mime_type, Ref<Image> r_image) override;
Error parse_texture_json(Ref<GLTFState> p_state, const Dictionary &p_texture_json, Ref<GLTFTexture> r_gltf_texture) override;
};
#endif // GLTF_DOCUMENT_EXTENSION_TEXTURE_KTX_H

View File

@ -31,6 +31,7 @@
#include "register_types.h" #include "register_types.h"
#include "extensions/gltf_document_extension_convert_importer_mesh.h" #include "extensions/gltf_document_extension_convert_importer_mesh.h"
#include "extensions/gltf_document_extension_texture_ktx.h"
#include "extensions/gltf_document_extension_texture_webp.h" #include "extensions/gltf_document_extension_texture_webp.h"
#include "extensions/gltf_spec_gloss.h" #include "extensions/gltf_spec_gloss.h"
#include "extensions/physics/gltf_document_extension_physics.h" #include "extensions/physics/gltf_document_extension_physics.h"
@ -133,6 +134,7 @@ void initialize_gltf_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(GLTFTextureSampler); GDREGISTER_CLASS(GLTFTextureSampler);
// Register GLTFDocumentExtension classes with GLTFDocument. // Register GLTFDocumentExtension classes with GLTFDocument.
GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionPhysics); GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionPhysics);
GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionTextureKTX);
GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionTextureWebP); GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionTextureWebP);
bool is_editor = ::Engine::get_singleton()->is_editor_hint(); bool is_editor = ::Engine::get_singleton()->is_editor_hint();
if (!is_editor) { if (!is_editor) {

60
modules/ktx/SCsub Normal file
View File

@ -0,0 +1,60 @@
#!/usr/bin/env python
Import("env")
Import("env_modules")
env_ktx = env_modules.Clone()
# libktx thirdparty source files
thirdparty_obj = []
thirdparty_dir = "#thirdparty/libktx/"
thirdparty_sources = [
"lib/checkheader.c",
"lib/filestream.c",
"lib/hashlist.c",
"lib/memstream.c",
"lib/swap.c",
"lib/texture.c",
"lib/texture1.c",
"lib/texture2.c",
"lib/dfdutils/createdfd.c",
"lib/dfdutils/colourspaces.c",
"lib/dfdutils/interpretdfd.c",
"lib/dfdutils/printdfd.c",
"lib/dfdutils/queries.c",
"lib/dfdutils/vk2dfd.c",
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_ktx.Prepend(CPPPATH=[thirdparty_dir + "include"])
env_ktx.Prepend(CPPPATH=[thirdparty_dir + "utils"])
env_ktx.Prepend(CPPPATH=[thirdparty_dir + "lib"])
env_ktx.Prepend(CPPPATH=[thirdparty_dir + "other_include"])
if env["module_basis_universal_enabled"]:
thirdparty_sources += [thirdparty_dir + "lib/basis_transcode.cpp"]
env_ktx.Prepend(CPPPATH=["#thirdparty/basis_universal"])
if env["vulkan"]:
env_ktx.Prepend(CPPPATH=["#thirdparty/vulkan/include"])
else:
# Falls back on bundled `vkformat_enum.h`.
env_ktx.Append(CPPDEFINES=["LIBKTX"])
env_ktx.Append(CPPDEFINES=[("KHRONOS_STATIC", 1)])
env_thirdparty = env_ktx.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
env.modules_sources += thirdparty_obj
# Godot source files
module_obj = []
env_ktx.add_source_files(module_obj, "*.cpp")
env.modules_sources += module_obj
# Needed to force rebuilding the module files when the thirdparty library is updated.
env.Depends(module_obj, thirdparty_obj)

6
modules/ktx/config.py Normal file
View File

@ -0,0 +1,6 @@
def can_build(env, platform):
return True
def configure(env):
pass

View File

@ -0,0 +1,53 @@
/**************************************************************************/
/* register_types.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "register_types.h"
#include "texture_loader_ktx.h"
static Ref<ResourceFormatKTX> resource_loader_ktx;
void initialize_ktx_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
resource_loader_ktx.instantiate();
ResourceLoader::add_resource_format_loader(resource_loader_ktx);
}
void uninitialize_ktx_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
ResourceLoader::remove_resource_format_loader(resource_loader_ktx);
resource_loader_ktx.unref();
}

View File

@ -0,0 +1,39 @@
/**************************************************************************/
/* register_types.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef KTX_REGISTER_TYPES_H
#define KTX_REGISTER_TYPES_H
#include "modules/register_module_types.h"
void initialize_ktx_module(ModuleInitializationLevel p_level);
void uninitialize_ktx_module(ModuleInitializationLevel p_level);
#endif // KTX_REGISTER_TYPES_H

View File

@ -0,0 +1,562 @@
/**************************************************************************/
/* texture_loader_ktx.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "texture_loader_ktx.h"
#include "core/io/file_access.h"
#include "core/io/file_access_memory.h"
#include "scene/resources/image_texture.h"
#include <ktx.h>
#include <vk_format.h>
KTX_error_code ktx_read(ktxStream *stream, void *dst, const ktx_size_t count) {
Ref<FileAccess> *f = reinterpret_cast<Ref<FileAccess> *>(stream->data.custom_ptr.address);
(*f)->get_buffer(reinterpret_cast<uint8_t *>(dst), count);
return KTX_SUCCESS;
}
KTX_error_code ktx_skip(ktxStream *stream, const ktx_size_t count) {
Ref<FileAccess> *f = reinterpret_cast<Ref<FileAccess> *>(stream->data.custom_ptr.address);
for (ktx_size_t i = 0; i < count; ++i) {
(*f)->get_8();
}
return KTX_SUCCESS;
}
KTX_error_code ktx_write(ktxStream *stream, const void *src, const ktx_size_t size, const ktx_size_t count) {
Ref<FileAccess> *f = reinterpret_cast<Ref<FileAccess> *>(stream->data.custom_ptr.address);
(*f)->store_buffer(reinterpret_cast<const uint8_t *>(src), size * count);
return KTX_SUCCESS;
}
KTX_error_code ktx_getpos(ktxStream *stream, ktx_off_t *const offset) {
Ref<FileAccess> *f = reinterpret_cast<Ref<FileAccess> *>(stream->data.custom_ptr.address);
*offset = (*f)->get_position();
return KTX_SUCCESS;
}
KTX_error_code ktx_setpos(ktxStream *stream, const ktx_off_t offset) {
Ref<FileAccess> *f = reinterpret_cast<Ref<FileAccess> *>(stream->data.custom_ptr.address);
(*f)->seek(offset);
return KTX_SUCCESS;
}
KTX_error_code ktx_getsize(ktxStream *stream, ktx_size_t *const size) {
Ref<FileAccess> *f = reinterpret_cast<Ref<FileAccess> *>(stream->data.custom_ptr.address);
*size = (*f)->get_length();
return KTX_SUCCESS;
}
void ktx_destruct(ktxStream *stream) {
(void)stream;
}
static Ref<Image> load_from_file_access(Ref<FileAccess> f, Error *r_error) {
ktxStream ktx_stream;
ktx_stream.read = ktx_read;
ktx_stream.skip = ktx_skip;
ktx_stream.write = ktx_write;
ktx_stream.getpos = ktx_getpos;
ktx_stream.setpos = ktx_setpos;
ktx_stream.getsize = ktx_getsize;
ktx_stream.destruct = ktx_destruct;
ktx_stream.type = eStreamTypeCustom;
ktx_stream.data.custom_ptr.address = &f;
ktx_stream.data.custom_ptr.allocatorAddress = NULL;
ktx_stream.data.custom_ptr.size = 0;
ktx_stream.readpos = 0;
ktx_stream.closeOnDestruct = false;
ktxTexture *ktx_texture;
KTX_error_code result = ktxTexture_CreateFromStream(&ktx_stream,
KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT,
&ktx_texture);
if (result != KTX_SUCCESS) {
ERR_FAIL_V_MSG(Ref<Resource>(), "Invalid or unsupported KTX texture file.");
}
if (ktx_texture->numDimensions != 2) {
ktxTexture_Destroy(ktx_texture);
ERR_FAIL_V_MSG(Ref<Resource>(), "Unsupported non-2D KTX texture file.");
}
if (ktx_texture->isCubemap || ktx_texture->numFaces != 1) {
ktxTexture_Destroy(ktx_texture);
ERR_FAIL_V_MSG(Ref<Resource>(), "Unsupported cube map KTX texture file.");
}
if (ktx_texture->isArray) {
ktxTexture_Destroy(ktx_texture);
ERR_FAIL_V_MSG(Ref<Resource>(), "Unsupported array KTX texture file.");
}
uint32_t width = ktx_texture->baseWidth;
uint32_t height = ktx_texture->baseHeight;
uint32_t mipmaps = ktx_texture->numLevels;
Image::Format format;
bool srgb = false;
switch (ktx_texture->classId) {
case ktxTexture1_c:
switch (((ktxTexture1 *)ktx_texture)->glInternalformat) {
case GL_LUMINANCE:
format = Image::FORMAT_L8;
break;
case GL_LUMINANCE_ALPHA:
format = Image::FORMAT_LA8;
break;
case GL_SRGB8:
format = Image::FORMAT_RGB8;
srgb = true;
break;
case GL_SRGB8_ALPHA8:
format = Image::FORMAT_RGBA8;
srgb = true;
break;
case GL_R8:
case GL_R8UI:
format = Image::FORMAT_R8;
break;
case GL_RG8:
format = Image::FORMAT_RG8;
break;
case GL_RGB8:
format = Image::FORMAT_RGB8;
break;
case GL_RGBA8:
format = Image::FORMAT_RGBA8;
break;
case GL_RGBA4:
format = Image::FORMAT_RGBA4444;
break;
case GL_RGB565:
format = Image::FORMAT_RGB565;
break;
case GL_R32F:
format = Image::FORMAT_RF;
break;
case GL_RG32F:
format = Image::FORMAT_RGF;
break;
case GL_RGB32F:
format = Image::FORMAT_RGBF;
break;
case GL_RGBA32F:
format = Image::FORMAT_RGBAF;
break;
case GL_R16F:
format = Image::FORMAT_RH;
break;
case GL_RG16F:
format = Image::FORMAT_RGH;
break;
case GL_RGB16F:
format = Image::FORMAT_RGBH;
break;
case GL_RGBA16F:
format = Image::FORMAT_RGBAH;
break;
case GL_RGB9_E5:
format = Image::FORMAT_RGBE9995;
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
format = Image::FORMAT_DXT1;
break;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
format = Image::FORMAT_DXT3;
break;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
format = Image::FORMAT_DXT5;
break;
case GL_COMPRESSED_RED_RGTC1:
format = Image::FORMAT_RGTC_R;
break;
case GL_COMPRESSED_RG_RGTC2:
format = Image::FORMAT_RGTC_RG;
break;
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
format = Image::FORMAT_BPTC_RGBFU;
break;
case GL_COMPRESSED_RGBA_BPTC_UNORM:
format = Image::FORMAT_BPTC_RGBA;
break;
#if 0 // TODO: ETC compression is bogus.
case GL_ETC1_RGB8_OES:
format = Image::FORMAT_ETC;
break;
case GL_COMPRESSED_R11_EAC:
format = Image::FORMAT_ETC2_R11;
break;
case GL_COMPRESSED_SIGNED_R11_EAC:
format = Image::FORMAT_ETC2_R11S;
break;
case GL_COMPRESSED_RG11_EAC:
format = Image::FORMAT_ETC2_RG11;
break;
case GL_COMPRESSED_SIGNED_RG11_EAC:
format = Image::FORMAT_ETC2_RG11S;
break;
case GL_COMPRESSED_RGB8_ETC2:
format = Image::FORMAT_ETC2_RGB8;
break;
case GL_COMPRESSED_RGBA8_ETC2_EAC:
format = Image::FORMAT_ETC2_RGBA8;
break;
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
format = Image::FORMAT_ETC2_RGB8A1;
break;
#endif
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
format = Image::FORMAT_ASTC_4x4;
break;
case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
format = Image::FORMAT_ASTC_4x4_HDR;
break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
format = Image::FORMAT_ASTC_8x8;
break;
case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
format = Image::FORMAT_ASTC_8x8_HDR;
break;
default:
ktxTexture_Destroy(ktx_texture);
ERR_FAIL_V_MSG(Ref<Resource>(), "Unsupported format " + itos(((ktxTexture1 *)ktx_texture)->glInternalformat) + " of KTX1 texture file.");
}
break;
case ktxTexture2_c: {
ktxTexture2 *ktx_texture2 = reinterpret_cast<ktxTexture2 *>(ktx_texture);
if (ktx_texture2->vkFormat == VK_FORMAT_UNDEFINED) {
if (!ktxTexture2_NeedsTranscoding(ktx_texture2)) {
ktxTexture_Destroy(ktx_texture);
ERR_FAIL_V_MSG(Ref<Resource>(), "Invalid VK_FORMAT_UNDEFINED of KTX2 texture file.");
}
ktx_transcode_fmt_e ktxfmt;
switch (ktxTexture2_GetNumComponents(ktx_texture2)) {
case 1: {
if (ktxTexture2_GetOETF_e(ktx_texture2) == KHR_DF_TRANSFER_SRGB) { // TODO srgb native support
ktxfmt = KTX_TTF_RGBA32;
} else if (RS::get_singleton()->has_os_feature("rgtc")) {
ktxfmt = KTX_TTF_BC4_R;
} else {
ktxfmt = KTX_TTF_RGBA32;
}
break;
}
case 2: {
if (ktxTexture2_GetOETF_e(ktx_texture2) == KHR_DF_TRANSFER_SRGB) { // TODO srgb native support
ktxfmt = KTX_TTF_RGBA32;
} else if (RS::get_singleton()->has_os_feature("rgtc")) {
ktxfmt = KTX_TTF_BC5_RG;
} else {
ktxfmt = KTX_TTF_RGBA32;
}
break;
}
case 3: {
if (ktxTexture2_GetOETF_e(ktx_texture2) == KHR_DF_TRANSFER_SRGB) { // TODO: srgb native support
ktxfmt = KTX_TTF_RGBA32;
} else if (RS::get_singleton()->has_os_feature("bptc")) {
ktxfmt = KTX_TTF_BC7_RGBA;
} else if (RS::get_singleton()->has_os_feature("s3tc")) {
ktxfmt = KTX_TTF_BC1_RGB;
} else if (RS::get_singleton()->has_os_feature("etc")) {
ktxfmt = KTX_TTF_ETC1_RGB;
} else {
ktxfmt = KTX_TTF_RGBA32;
}
break;
}
case 4: {
if (ktxTexture2_GetOETF_e(ktx_texture2) == KHR_DF_TRANSFER_SRGB) { // TODO srgb native support
ktxfmt = KTX_TTF_RGBA32;
} else if (RS::get_singleton()->has_os_feature("astc")) {
ktxfmt = KTX_TTF_ASTC_4x4_RGBA;
} else if (RS::get_singleton()->has_os_feature("bptc")) {
ktxfmt = KTX_TTF_BC7_RGBA;
} else if (RS::get_singleton()->has_os_feature("s3tc")) {
ktxfmt = KTX_TTF_BC3_RGBA;
} else if (RS::get_singleton()->has_os_feature("etc2")) {
ktxfmt = KTX_TTF_ETC2_RGBA;
} else {
ktxfmt = KTX_TTF_RGBA32;
}
break;
}
default: {
ktxTexture_Destroy(ktx_texture);
ERR_FAIL_V_MSG(Ref<Resource>(), "Invalid components of KTX2 texture file.");
}
}
result = ktxTexture2_TranscodeBasis(ktx_texture2, ktxfmt, 0);
if (result != KTX_SUCCESS) {
ktxTexture_Destroy(ktx_texture);
ERR_FAIL_V_MSG(Ref<Resource>(), "Failed to transcode KTX2 texture file.");
}
}
switch (ktx_texture2->vkFormat) {
case VK_FORMAT_R8_UNORM:
format = Image::FORMAT_L8;
break;
case VK_FORMAT_R8G8_UNORM:
format = Image::FORMAT_LA8;
break;
case VK_FORMAT_R8G8B8_SRGB:
format = Image::FORMAT_RGB8;
srgb = true;
break;
case VK_FORMAT_R8G8B8A8_SRGB:
format = Image::FORMAT_RGBA8;
srgb = true;
break;
case VK_FORMAT_R8_UINT:
format = Image::FORMAT_R8;
break;
case VK_FORMAT_R8G8_UINT:
format = Image::FORMAT_RG8;
break;
case VK_FORMAT_R8G8B8_UINT:
format = Image::FORMAT_RGB8;
break;
case VK_FORMAT_R8G8B8A8_UINT:
format = Image::FORMAT_RGBA8;
break;
case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
format = Image::FORMAT_RGBA4444;
break;
case VK_FORMAT_R5G6B5_UNORM_PACK16:
format = Image::FORMAT_RGB565;
break;
case VK_FORMAT_R32_SFLOAT:
format = Image::FORMAT_RF;
break;
case VK_FORMAT_R32G32_SFLOAT:
format = Image::FORMAT_RGF;
break;
case VK_FORMAT_R32G32B32_SFLOAT:
format = Image::FORMAT_RGBF;
break;
case VK_FORMAT_R32G32B32A32_SFLOAT:
format = Image::FORMAT_RGBAF;
break;
case VK_FORMAT_R16_SFLOAT:
format = Image::FORMAT_RH;
break;
case VK_FORMAT_R16G16_SFLOAT:
format = Image::FORMAT_RGH;
break;
case VK_FORMAT_R16G16B16_SFLOAT:
format = Image::FORMAT_RGBH;
break;
case VK_FORMAT_R16G16B16A16_SFLOAT:
format = Image::FORMAT_RGBAH;
break;
case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
format = Image::FORMAT_RGBE9995;
break;
case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
format = Image::FORMAT_DXT1;
break;
case VK_FORMAT_BC2_UNORM_BLOCK:
format = Image::FORMAT_DXT3;
break;
case VK_FORMAT_BC3_UNORM_BLOCK:
format = Image::FORMAT_DXT5;
break;
case VK_FORMAT_BC4_UNORM_BLOCK:
format = Image::FORMAT_RGTC_R;
break;
case VK_FORMAT_BC5_UNORM_BLOCK:
format = Image::FORMAT_RGTC_RG;
break;
case VK_FORMAT_BC6H_UFLOAT_BLOCK:
format = Image::FORMAT_BPTC_RGBFU;
break;
case VK_FORMAT_BC6H_SFLOAT_BLOCK:
format = Image::FORMAT_BPTC_RGBF;
break;
case VK_FORMAT_BC7_UNORM_BLOCK:
format = Image::FORMAT_BPTC_RGBA;
break;
#if 0 // TODO: ETC compression is bogus.
case VK_FORMAT_EAC_R11_UNORM_BLOCK:
format = Image::FORMAT_ETC2_R11;
break;
case VK_FORMAT_EAC_R11_SNORM_BLOCK:
format = Image::FORMAT_ETC2_R11S;
break;
case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
format = Image::FORMAT_ETC2_RG11;
break;
case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
format = Image::FORMAT_ETC2_RG11S;
break;
case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
format = Image::FORMAT_ETC2_RGB8;
break;
case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
format = Image::FORMAT_ETC2_RGBA8;
break;
case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
format = Image::FORMAT_ETC2_RGB8A1;
break;
#endif
case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
format = Image::FORMAT_ASTC_4x4;
break;
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
format = Image::FORMAT_ASTC_4x4_HDR;
break;
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
format = Image::FORMAT_ASTC_8x8;
break;
case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
format = Image::FORMAT_ASTC_8x8_HDR;
break;
default:
ktxTexture_Destroy(ktx_texture);
ERR_FAIL_V_MSG(Ref<Resource>(), "Unsupported format " + itos(((ktxTexture2 *)ktx_texture)->vkFormat) + " of KTX2 texture file.");
break;
}
break;
}
default:
ktxTexture_Destroy(ktx_texture);
ERR_FAIL_V_MSG(Ref<Resource>(), "Unsupported version KTX texture file.");
break;
}
Vector<uint8_t> src_data;
// KTX use 4-bytes padding, don't use mipmaps if padding is effective
// TODO: unpad dynamically
int pixel_size = Image::get_format_pixel_size(format);
int pixel_rshift = Image::get_format_pixel_rshift(format);
int block = Image::get_format_block_size(format);
int minw, minh;
Image::get_format_min_pixel_size(format, minw, minh);
int w = width;
int h = height;
for (uint32_t i = 0; i < mipmaps; ++i) {
ktx_size_t mip_size = ktxTexture_GetImageSize(ktx_texture, i);
size_t bw = w % block != 0 ? w + (block - w % block) : w;
size_t bh = h % block != 0 ? h + (block - h % block) : h;
size_t s = bw * bh;
s *= pixel_size;
s >>= pixel_rshift;
if (mip_size != static_cast<ktx_size_t>(s)) {
if (!i) {
ktxTexture_Destroy(ktx_texture);
ERR_FAIL_V_MSG(Ref<Resource>(), "Unsupported padded KTX texture file.");
}
mipmaps = 1;
break;
}
w = MAX(minw, w >> 1);
h = MAX(minh, h >> 1);
}
for (uint32_t i = 0; i < mipmaps; ++i) {
ktx_size_t mip_size = ktxTexture_GetImageSize(ktx_texture, i);
ktx_size_t offset;
if (ktxTexture_GetImageOffset(ktx_texture, i, 0, 0, &offset) != KTX_SUCCESS) {
ktxTexture_Destroy(ktx_texture);
ERR_FAIL_V_MSG(Ref<Resource>(), "Invalid KTX texture file.");
}
int prev_size = src_data.size();
src_data.resize(prev_size + mip_size);
memcpy(src_data.ptrw() + prev_size, ktxTexture_GetData(ktx_texture) + offset, mip_size);
}
Ref<Image> img = memnew(Image(width, height, mipmaps - 1, format, src_data));
if (srgb) {
img->srgb_to_linear();
}
if (r_error) {
*r_error = OK;
}
ktxTexture_Destroy(ktx_texture);
return img;
}
Ref<Resource> ResourceFormatKTX::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
Error err;
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
if (f.is_null()) {
return Ref<Resource>();
}
Ref<FileAccess> fref(f);
if (r_error) {
*r_error = ERR_FILE_CORRUPT;
}
ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), "Unable to open KTX texture file '" + p_path + "'.");
Ref<Image> img = load_from_file_access(f, r_error);
Ref<ImageTexture> texture = ImageTexture::create_from_image(img);
return texture;
}
static Ref<Image> _ktx_mem_loader_func(const uint8_t *p_ktx, int p_size) {
Ref<FileAccessMemory> f;
f.instantiate();
f->open_custom(p_ktx, p_size);
Error err;
Ref<Image> img = load_from_file_access(f, &err);
ERR_FAIL_COND_V(err, Ref<Image>());
return img;
}
void ResourceFormatKTX::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("ktx");
p_extensions->push_back("ktx2");
}
bool ResourceFormatKTX::handles_type(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "Texture2D");
}
String ResourceFormatKTX::get_resource_type(const String &p_path) const {
if (p_path.get_extension().to_lower() == "ktx" || p_path.get_extension().to_lower() == "ktx2") {
return "ImageTexture";
}
return "";
}
ResourceFormatKTX::ResourceFormatKTX() {
Image::_ktx_mem_loader_func = _ktx_mem_loader_func;
}

View File

@ -0,0 +1,48 @@
/**************************************************************************/
/* texture_loader_ktx.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEXTURE_LOADER_KTX_H
#define TEXTURE_LOADER_KTX_H
#include "core/io/resource_loader.h"
#include "scene/resources/texture.h"
class ResourceFormatKTX : public ResourceFormatLoader {
public:
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
virtual ~ResourceFormatKTX() {}
ResourceFormatKTX();
};
#endif // TEXTURE_LOADER_KTX_H

19
thirdparty/README.md vendored
View File

@ -299,6 +299,25 @@ Files extracted from upstream source:
- `jpge*.{c,h}` - `jpge*.{c,h}`
## libktx
- Upstream: https://github.com/KhronosGroup/KTX-Software
- Version: 4.1.0 (d7255fe73cd53b856731ceb9f2c279181d0dbbca, 2023)
- License: Apache-2.0
Files extracted from upstream source:
- `LICENSE.md`
- `include/*`
- `lib/dfdutils/{LICENSES/Apache-2.0.txt,KHR,*.c,*.h,*.inl}`
- `lib/{basis_sgd.h,basis_transcode.cpp,checkheader.c,filestream.*,formatsize.h,gl_format.h,hashlist.c,ktxint.h,memstream.*,swap.c,texture*,uthash.h,vk_format.h,vkformat_enum.h`
- `utils/unused.h`
- `other_include/KHR/*`
- ifndef-protect NOMINMAX define in `lib/gl_format.h` (see godot.patch)
- remove `basisu/` prefix from `thirdparty/libktx/lib/basis_transcode.cpp` basisu includes (see godot.patch)
- comment `VK_FORMAT_ASTC_*x*x*_UNORM_BLOCK_EXT` cases in `lib/dfdutils/vk2dfd.inl` (see godot.patch)
## libogg ## libogg
- Upstream: https://www.xiph.org/ogg - Upstream: https://www.xiph.org/ogg

208
thirdparty/libktx/Apache-2.0.txt vendored Normal file
View File

@ -0,0 +1,208 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION,
AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution
as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct
or indirect, to cause the direction or management of such entity, whether
by contract or otherwise, or (ii) ownership of fifty percent (50%) or more
of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions
granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation
or translation of a Source form, including but not limited to compiled object
code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form,
made available under the License, as indicated by a copyright notice that
is included in or attached to the work (an example is provided in the Appendix
below).
"Derivative Works" shall mean any work, whether in Source or Object form,
that is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative
Works shall not include works that remain separable from, or merely link (or
bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative
Works thereof, that is intentionally submitted to Licensor for inclusion in
the Work by the copyright owner or by an individual or Legal Entity authorized
to submit on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication
sent to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor
for the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently incorporated
within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this
License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
Derivative Works of, publicly display, publicly perform, sublicense, and distribute
the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License,
each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section) patent
license to make, have made, use, offer to sell, sell, import, and otherwise
transfer the Work, where such license applies only to those patent claims
licensable by such Contributor that are necessarily infringed by their Contribution(s)
alone or by combination of their Contribution(s) with the Work to which such
Contribution(s) was submitted. If You institute patent litigation against
any entity (including a cross-claim or counterclaim in a lawsuit) alleging
that the Work or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses granted to You
under this License for that Work shall terminate as of the date such litigation
is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or
Derivative Works thereof in any medium, with or without modifications, and
in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy
of this License; and
(b) You must cause any modified files to carry prominent notices stating that
You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source
form of the Work, excluding those notices that do not pertain to any part
of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution,
then any Derivative Works that You distribute must include a readable copy
of the attribution notices contained within such NOTICE file, excluding those
notices that do not pertain to any part of the Derivative Works, in at least
one of the following places: within a NOTICE text file distributed as part
of the Derivative Works; within the Source form or documentation, if provided
along with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works
that You distribute, alongside or as an addendum to the NOTICE text from the
Work, provided that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction,
or distribution of Your modifications, or for any such Derivative Works as
a whole, provided Your use, reproduction, and distribution of the Work otherwise
complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any
Contribution intentionally submitted for inclusion in the Work by You to the
Licensor shall be under the terms and conditions of this License, without
any additional terms or conditions. Notwithstanding the above, nothing herein
shall supersede or modify the terms of any separate license agreement you
may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names,
trademarks, service marks, or product names of the Licensor, except as required
for reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to
in writing, Licensor provides the Work (and each Contributor provides its
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied, including, without limitation, any warranties
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR
A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness
of using or redistributing the Work and assume any risks associated with Your
exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether
in tort (including negligence), contract, or otherwise, unless required by
applicable law (such as deliberate and grossly negligent acts) or agreed to
in writing, shall any Contributor be liable to You for damages, including
any direct, indirect, special, incidental, or consequential damages of any
character arising as a result of this License or out of the use or inability
to use the Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all other commercial
damages or losses), even if such Contributor has been advised of the possibility
of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work
or Derivative Works thereof, You may choose to offer, and charge a fee for,
acceptance of support, warranty, indemnity, or other liability obligations
and/or rights consistent with this License. However, in accepting such obligations,
You may act only on Your own behalf and on Your sole responsibility, not on
behalf of any other Contributor, and only if You agree to indemnify, defend,
and hold each Contributor harmless for any liability incurred by, or claims
asserted against, such Contributor by reason of your accepting any such warranty
or additional liability. END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own identifying
information. (Don't include the brackets!) The text should be enclosed in
the appropriate comment syntax for the file format. We also recommend that
a file or class name and description of purpose be included on the same "printed
page" as the copyright notice for easier identification within third-party
archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

10
thirdparty/libktx/LICENSE.dfdutils.adoc vendored Normal file
View File

@ -0,0 +1,10 @@
= LICENSE file for the KhronosGroup/dfdutils project
Files in this repository fall under this license:
* SPDX license identifier: "`Apache-2.0`"
** Apache License 2.0
Full license text is available at:
* Apache-2.0: https://opensource.org/licenses/Apache-2.0

36
thirdparty/libktx/LICENSE.md vendored Normal file
View File

@ -0,0 +1,36 @@
LICENSE file for the KhronosGroup/KTX-Software project {#license}
======================================================
<!--
Can't put at start. Doxygen requires page title on first line.
Copyright 2013-2020 Mark Callow
SPDX-License-Identifier: Apache-2.0
-->
Files unique to this repository generally fall under the Apache 2.0 license
with copyright holders including Mark Callow, the KTX-Software author; The
Khronos Group Inc., which has supported KTX development; and other
contributors to the KTX project.
Because KTX-Software incorporates material and contributions from many other
projects, which often have their own licenses, there are many other licenses
in use in this repository. While there are many licenses in this repository,
with rare exceptions all are open source licenses that we believe to be
mutually compatible.
The complete text of each of the licenses used in this repository is found
in LICENSES/*.txt . Additionally, we have updated the repository to pass the
REUSE compliance checker tool (see https://reuse.software/). REUSE verifies
that every file in a git repository either incorporates a license, or that
the license is present in auxiliary files such as .reuse/dep5 . To obtain a
bill of materials for the repository identifying the license for each file,
install the REUSE tool and run
reuse spdx
inside the repository.
## Special Cases
The file lib/etcdec.cxx is not open source. It is made available under the
terms of an Ericsson license, found in the file itself.

45
thirdparty/libktx/godot.patch vendored Normal file
View File

@ -0,0 +1,45 @@
--- thirdparty/libktx/lib/gl_format.h
+++ thirdparty/libktx/lib/gl_format.h
@@ -92,7 +92,9 @@
#include "vkformat_enum.h"
#if defined(_WIN32) && !defined(__MINGW32__)
+#ifndef NOMINMAX
#define NOMINMAX
+#endif
#ifndef __cplusplus
#undef inline
#define inline __inline
--- thirdparty/libktx/lib/basis_transcode.cpp
+++ thirdparty/libktx/lib/basis_transcode.cpp
@@ -29,9 +29,9 @@
#include "vkformat_enum.h"
#include "vk_format.h"
#include "basis_sgd.h"
-#include "basisu/transcoder/basisu_file_headers.h"
-#include "basisu/transcoder/basisu_transcoder.h"
-#include "basisu/transcoder/basisu_transcoder_internal.h"
+#include "transcoder/basisu_file_headers.h"
+#include "transcoder/basisu_transcoder.h"
+#include "transcoder/basisu_transcoder_internal.h"
#undef DECLARE_PRIVATE
#undef DECLARE_PROTECTED
--- thirdparty/libktx/lib/dfdutils/vk2dfd.inl
+++ thirdparty/libktx/lib/dfdutils/vk2dfd.inl
@@ -298,6 +298,7 @@
case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 10, 10, 1, s_SFLOAT);
case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 12, 10, 1, s_SFLOAT);
case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 12, 12, 1, s_SFLOAT);
+#if 0
case VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 3, 3, 3, s_UNORM);
case VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 3, 3, 3, s_SRGB);
case VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 3, 3, 3, s_SFLOAT);
@@ -328,6 +329,7 @@
case VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 6, s_UNORM);
case VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 6, s_SRGB);
case VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 6, s_SFLOAT);
+#endif
case VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT: {
int channels[] = {2,1,0,3}; int bits[] = {4,4,4,4};
return createDFDPacked(0, 4, bits, channels, s_UNORM);

619
thirdparty/libktx/include/KHR/khr_df.h vendored Normal file
View File

@ -0,0 +1,619 @@
/* The Khronos Data Format Specification (version 1.3) */
/*
** Copyright 2015-2020 The Khronos Group Inc.
** SPDX-License-Identifier: Apache-2.0
*/
/* This header defines a structure that can describe the layout of image
formats in memory. This means that the data format is transparent to
the application, and the expectation is that this should be used when
the layout is defined external to the API. Many Khronos APIs deliberately
keep the internal layout of images opaque, to allow proprietary layouts
and optimisations. This structure is not appropriate for describing
opaque layouts. */
/* We stick to standard C89 constructs for simplicity and portability. */
#ifndef _KHR_DATA_FORMAT_H_
#define _KHR_DATA_FORMAT_H_
/* Accessors */
typedef enum _khr_word_e {
KHR_DF_WORD_VENDORID = 0U,
KHR_DF_WORD_DESCRIPTORTYPE = 0U,
KHR_DF_WORD_VERSIONNUMBER = 1U,
KHR_DF_WORD_DESCRIPTORBLOCKSIZE = 1U,
KHR_DF_WORD_MODEL = 2U,
KHR_DF_WORD_PRIMARIES = 2U,
KHR_DF_WORD_TRANSFER = 2U,
KHR_DF_WORD_FLAGS = 2U,
KHR_DF_WORD_TEXELBLOCKDIMENSION0 = 3U,
KHR_DF_WORD_TEXELBLOCKDIMENSION1 = 3U,
KHR_DF_WORD_TEXELBLOCKDIMENSION2 = 3U,
KHR_DF_WORD_TEXELBLOCKDIMENSION3 = 3U,
KHR_DF_WORD_BYTESPLANE0 = 4U,
KHR_DF_WORD_BYTESPLANE1 = 4U,
KHR_DF_WORD_BYTESPLANE2 = 4U,
KHR_DF_WORD_BYTESPLANE3 = 4U,
KHR_DF_WORD_BYTESPLANE4 = 5U,
KHR_DF_WORD_BYTESPLANE5 = 5U,
KHR_DF_WORD_BYTESPLANE6 = 5U,
KHR_DF_WORD_BYTESPLANE7 = 5U,
KHR_DF_WORD_SAMPLESTART = 6U,
KHR_DF_WORD_SAMPLEWORDS = 4U
} khr_df_word_e;
typedef enum _khr_df_shift_e {
KHR_DF_SHIFT_VENDORID = 0U,
KHR_DF_SHIFT_DESCRIPTORTYPE = 17U,
KHR_DF_SHIFT_VERSIONNUMBER = 0U,
KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE = 16U,
KHR_DF_SHIFT_MODEL = 0U,
KHR_DF_SHIFT_PRIMARIES = 8U,
KHR_DF_SHIFT_TRANSFER = 16U,
KHR_DF_SHIFT_FLAGS = 24U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION0 = 0U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION1 = 8U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION2 = 16U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION3 = 24U,
KHR_DF_SHIFT_BYTESPLANE0 = 0U,
KHR_DF_SHIFT_BYTESPLANE1 = 8U,
KHR_DF_SHIFT_BYTESPLANE2 = 16U,
KHR_DF_SHIFT_BYTESPLANE3 = 24U,
KHR_DF_SHIFT_BYTESPLANE4 = 0U,
KHR_DF_SHIFT_BYTESPLANE5 = 8U,
KHR_DF_SHIFT_BYTESPLANE6 = 16U,
KHR_DF_SHIFT_BYTESPLANE7 = 24U
} khr_df_shift_e;
typedef enum _khr_df_mask_e {
KHR_DF_MASK_VENDORID = 0x1FFFFU,
KHR_DF_MASK_DESCRIPTORTYPE = 0x7FFFU,
KHR_DF_MASK_VERSIONNUMBER = 0xFFFFU,
KHR_DF_MASK_DESCRIPTORBLOCKSIZE = 0xFFFFU,
KHR_DF_MASK_MODEL = 0xFFU,
KHR_DF_MASK_PRIMARIES = 0xFFU,
KHR_DF_MASK_TRANSFER = 0xFFU,
KHR_DF_MASK_FLAGS = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION0 = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION1 = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION2 = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION3 = 0xFFU,
KHR_DF_MASK_BYTESPLANE0 = 0xFFU,
KHR_DF_MASK_BYTESPLANE1 = 0xFFU,
KHR_DF_MASK_BYTESPLANE2 = 0xFFU,
KHR_DF_MASK_BYTESPLANE3 = 0xFFU,
KHR_DF_MASK_BYTESPLANE4 = 0xFFU,
KHR_DF_MASK_BYTESPLANE5 = 0xFFU,
KHR_DF_MASK_BYTESPLANE6 = 0xFFU,
KHR_DF_MASK_BYTESPLANE7 = 0xFFU
} khr_df_mask_e;
/* Helper macro:
Extract field X from basic descriptor block BDB */
#define KHR_DFDVAL(BDB, X) \
(((BDB)[KHR_DF_WORD_ ## X] >> (KHR_DF_SHIFT_ ## X)) \
& (KHR_DF_MASK_ ## X))
/* Helper macro:
Set field X of basic descriptor block BDB */
#define KHR_DFDSETVAL(BDB, X, val) \
((BDB)[KHR_DF_WORD_ ## X] = \
((BDB)[KHR_DF_WORD_ ## X] & \
~((KHR_DF_MASK_ ## X) << (KHR_DF_SHIFT_ ## X))) | \
(((val) & (KHR_DF_MASK_ ## X)) << (KHR_DF_SHIFT_ ## X)))
/* Offsets relative to the start of a sample */
typedef enum _khr_df_sampleword_e {
KHR_DF_SAMPLEWORD_BITOFFSET = 0U,
KHR_DF_SAMPLEWORD_BITLENGTH = 0U,
KHR_DF_SAMPLEWORD_CHANNELID = 0U,
KHR_DF_SAMPLEWORD_QUALIFIERS = 0U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION0 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION1 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION2 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION3 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL = 1U,
KHR_DF_SAMPLEWORD_SAMPLELOWER = 2U,
KHR_DF_SAMPLEWORD_SAMPLEUPPER = 3U
} khr_df_sampleword_e;
typedef enum _khr_df_sampleshift_e {
KHR_DF_SAMPLESHIFT_BITOFFSET = 0U,
KHR_DF_SAMPLESHIFT_BITLENGTH = 16U,
KHR_DF_SAMPLESHIFT_CHANNELID = 24U,
/* N.B. Qualifiers are defined as an offset into a byte */
KHR_DF_SAMPLESHIFT_QUALIFIERS = 24U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION0 = 0U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION1 = 8U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION2 = 16U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION3 = 24U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION_ALL = 0U,
KHR_DF_SAMPLESHIFT_SAMPLELOWER = 0U,
KHR_DF_SAMPLESHIFT_SAMPLEUPPER = 0U
} khr_df_sampleshift_e;
typedef enum _khr_df_samplemask_e {
KHR_DF_SAMPLEMASK_BITOFFSET = 0xFFFFU,
KHR_DF_SAMPLEMASK_BITLENGTH = 0xFF,
KHR_DF_SAMPLEMASK_CHANNELID = 0xF,
/* N.B. Qualifiers are defined as an offset into a byte */
KHR_DF_SAMPLEMASK_QUALIFIERS = 0xF0,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION0 = 0xFF,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION1 = 0xFF,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION2 = 0xFF,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION3 = 0xFF,
/* ISO C restricts enum values to range of int hence the
cast. We do it verbosely instead of using -1 to ensure
it is a 32-bit value even if int is 64 bits. */
KHR_DF_SAMPLEMASK_SAMPLEPOSITION_ALL = (int) 0xFFFFFFFFU,
KHR_DF_SAMPLEMASK_SAMPLELOWER = (int) 0xFFFFFFFFU,
KHR_DF_SAMPLEMASK_SAMPLEUPPER = (int) 0xFFFFFFFFU
} khr_df_samplemask_e;
/* Helper macro:
Extract field X of sample S from basic descriptor block BDB */
#define KHR_DFDSVAL(BDB, S, X) \
(((BDB)[KHR_DF_WORD_SAMPLESTART + \
((S) * KHR_DF_WORD_SAMPLEWORDS) + \
KHR_DF_SAMPLEWORD_ ## X] >> (KHR_DF_SAMPLESHIFT_ ## X)) \
& (KHR_DF_SAMPLEMASK_ ## X))
/* Helper macro:
Set field X of sample S of basic descriptor block BDB */
#define KHR_DFDSETSVAL(BDB, S, X, val) \
((BDB)[KHR_DF_WORD_SAMPLESTART + \
((S) * KHR_DF_WORD_SAMPLEWORDS) + \
KHR_DF_SAMPLEWORD_ ## X] = \
((BDB)[KHR_DF_WORD_SAMPLESTART + \
((S) * KHR_DF_WORD_SAMPLEWORDS) + \
KHR_DF_SAMPLEWORD_ ## X] & \
~((uint32_t)(KHR_DF_SAMPLEMASK_ ## X) << (KHR_DF_SAMPLESHIFT_ ## X))) | \
(((val) & (uint32_t)(KHR_DF_SAMPLEMASK_ ## X)) << (KHR_DF_SAMPLESHIFT_ ## X)))
/* Helper macro:
Number of samples in basic descriptor block BDB */
#define KHR_DFDSAMPLECOUNT(BDB) \
(((KHR_DFDVAL(BDB, DESCRIPTORBLOCKSIZE) >> 2) - \
KHR_DF_WORD_SAMPLESTART) \
/ KHR_DF_WORD_SAMPLEWORDS)
/* Helper macro:
Size in words of basic descriptor block for S samples */
#define KHR_DFDSIZEWORDS(S) \
(KHR_DF_WORD_SAMPLESTART + \
(S) * KHR_DF_WORD_SAMPLEWORDS)
/* Vendor ids */
typedef enum _khr_df_vendorid_e {
/* Standard Khronos descriptor */
KHR_DF_VENDORID_KHRONOS = 0U,
KHR_DF_VENDORID_MAX = 0x1FFFFU
} khr_df_vendorid_e;
/* Descriptor types */
typedef enum _khr_df_khr_descriptortype_e {
/* Default Khronos basic descriptor block */
KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT = 0U,
/* Extension descriptor block for additional planes */
KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_PLANES = 0x6001U,
/* Extension descriptor block for additional dimensions */
KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS = 0x6002U,
/* Bit indicates modifying requires understanding this extension */
KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_WRITE_BIT = 0x2000U,
/* Bit indicates processing requires understanding this extension */
KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_DECODE_BIT = 0x4000U,
KHR_DF_KHR_DESCRIPTORTYPE_MAX = 0x7FFFU
} khr_df_khr_descriptortype_e;
/* Descriptor block version */
typedef enum _khr_df_versionnumber_e {
/* Standard Khronos descriptor */
KHR_DF_VERSIONNUMBER_1_0 = 0U, /* Version 1.0 of the specification */
KHR_DF_VERSIONNUMBER_1_1 = 0U, /* Version 1.1 did not bump the version number */
KHR_DF_VERSIONNUMBER_1_2 = 1U, /* Version 1.2 increased the version number */
KHR_DF_VERSIONNUMBER_1_3 = 2U, /* Version 1.3 increased the version number */
KHR_DF_VERSIONNUMBER_LATEST = KHR_DF_VERSIONNUMBER_1_3,
KHR_DF_VERSIONNUMBER_MAX = 0xFFFFU
} khr_df_versionnumber_e;
/* Model in which the color coordinate space is defined.
There is no requirement that a color format use all the
channel types that are defined in the color model. */
typedef enum _khr_df_model_e {
/* No interpretation of color channels defined */
KHR_DF_MODEL_UNSPECIFIED = 0U,
/* Color primaries (red, green, blue) + alpha, depth and stencil */
KHR_DF_MODEL_RGBSDA = 1U,
/* Color differences (Y', Cb, Cr) + alpha, depth and stencil */
KHR_DF_MODEL_YUVSDA = 2U,
/* Color differences (Y', I, Q) + alpha, depth and stencil */
KHR_DF_MODEL_YIQSDA = 3U,
/* Perceptual color (CIE L*a*b*) + alpha, depth and stencil */
KHR_DF_MODEL_LABSDA = 4U,
/* Subtractive colors (cyan, magenta, yellow, black) + alpha */
KHR_DF_MODEL_CMYKA = 5U,
/* Non-color coordinate data (X, Y, Z, W) */
KHR_DF_MODEL_XYZW = 6U,
/* Hue, saturation, value, hue angle on color circle, plus alpha */
KHR_DF_MODEL_HSVA_ANG = 7U,
/* Hue, saturation, lightness, hue angle on color circle, plus alpha */
KHR_DF_MODEL_HSLA_ANG = 8U,
/* Hue, saturation, value, hue on color hexagon, plus alpha */
KHR_DF_MODEL_HSVA_HEX = 9U,
/* Hue, saturation, lightness, hue on color hexagon, plus alpha */
KHR_DF_MODEL_HSLA_HEX = 10U,
/* Lightweight approximate color difference (luma, orange, green) */
KHR_DF_MODEL_YCGCOA = 11U,
/* ITU BT.2020 constant luminance YcCbcCrc */
KHR_DF_MODEL_YCCBCCRC = 12U,
/* ITU BT.2100 constant intensity ICtCp */
KHR_DF_MODEL_ICTCP = 13U,
/* CIE 1931 XYZ color coordinates (X, Y, Z) */
KHR_DF_MODEL_CIEXYZ = 14U,
/* CIE 1931 xyY color coordinates (X, Y, Y) */
KHR_DF_MODEL_CIEXYY = 15U,
/* Compressed formats start at 128. */
/* These compressed formats should generally have a single sample,
sited at the 0,0 position of the texel block. Where multiple
channels are used to distinguish formats, these should be cosited. */
/* Direct3D (and S3) compressed formats */
/* Note that premultiplied status is recorded separately */
/* DXT1 "channels" are RGB (0), Alpha (1) */
/* DXT1/BC1 with one channel is opaque */
/* DXT1/BC1 with a cosited alpha sample is transparent */
KHR_DF_MODEL_DXT1A = 128U,
KHR_DF_MODEL_BC1A = 128U,
/* DXT2/DXT3/BC2, with explicit 4-bit alpha */
KHR_DF_MODEL_DXT2 = 129U,
KHR_DF_MODEL_DXT3 = 129U,
KHR_DF_MODEL_BC2 = 129U,
/* DXT4/DXT5/BC3, with interpolated alpha */
KHR_DF_MODEL_DXT4 = 130U,
KHR_DF_MODEL_DXT5 = 130U,
KHR_DF_MODEL_BC3 = 130U,
/* BC4 - single channel interpolated 8-bit data */
/* (The UNORM/SNORM variation is recorded in the channel data) */
KHR_DF_MODEL_BC4 = 131U,
/* BC5 - two channel interpolated 8-bit data */
/* (The UNORM/SNORM variation is recorded in the channel data) */
KHR_DF_MODEL_BC5 = 132U,
/* BC6H - DX11 format for 16-bit float channels */
KHR_DF_MODEL_BC6H = 133U,
/* BC7 - DX11 format */
KHR_DF_MODEL_BC7 = 134U,
/* Gap left for future desktop expansion */
/* Mobile compressed formats follow */
/* A format of ETC1 indicates that the format shall be decodable
by an ETC1-compliant decoder and not rely on ETC2 features */
KHR_DF_MODEL_ETC1 = 160U,
/* A format of ETC2 is permitted to use ETC2 encodings on top of
the baseline ETC1 specification */
/* The ETC2 format has channels "red", "green", "RGB" and "alpha",
which should be cosited samples */
/* Punch-through alpha can be distinguished from full alpha by
the plane size in bytes required for the texel block */
KHR_DF_MODEL_ETC2 = 161U,
/* Adaptive Scalable Texture Compression */
/* ASTC HDR vs LDR is determined by the float flag in the channel */
/* ASTC block size can be distinguished by texel block size */
KHR_DF_MODEL_ASTC = 162U,
/* ETC1S is a simplified subset of ETC1 */
KHR_DF_MODEL_ETC1S = 163U,
/* PowerVR Texture Compression */
KHR_DF_MODEL_PVRTC = 164U,
KHR_DF_MODEL_PVRTC2 = 165U,
KHR_DF_MODEL_UASTC = 166U,
/* Proprietary formats (ATITC, etc.) should follow */
KHR_DF_MODEL_MAX = 0xFFU
} khr_df_model_e;
/* Definition of channel names for each color model */
typedef enum _khr_df_model_channels_e {
/* Unspecified format with nominal channel numbering */
KHR_DF_CHANNEL_UNSPECIFIED_0 = 0U,
KHR_DF_CHANNEL_UNSPECIFIED_1 = 1U,
KHR_DF_CHANNEL_UNSPECIFIED_2 = 2U,
KHR_DF_CHANNEL_UNSPECIFIED_3 = 3U,
KHR_DF_CHANNEL_UNSPECIFIED_4 = 4U,
KHR_DF_CHANNEL_UNSPECIFIED_5 = 5U,
KHR_DF_CHANNEL_UNSPECIFIED_6 = 6U,
KHR_DF_CHANNEL_UNSPECIFIED_7 = 7U,
KHR_DF_CHANNEL_UNSPECIFIED_8 = 8U,
KHR_DF_CHANNEL_UNSPECIFIED_9 = 9U,
KHR_DF_CHANNEL_UNSPECIFIED_10 = 10U,
KHR_DF_CHANNEL_UNSPECIFIED_11 = 11U,
KHR_DF_CHANNEL_UNSPECIFIED_12 = 12U,
KHR_DF_CHANNEL_UNSPECIFIED_13 = 13U,
KHR_DF_CHANNEL_UNSPECIFIED_14 = 14U,
KHR_DF_CHANNEL_UNSPECIFIED_15 = 15U,
/* MODEL_RGBSDA - red, green, blue, stencil, depth, alpha */
KHR_DF_CHANNEL_RGBSDA_RED = 0U,
KHR_DF_CHANNEL_RGBSDA_R = 0U,
KHR_DF_CHANNEL_RGBSDA_GREEN = 1U,
KHR_DF_CHANNEL_RGBSDA_G = 1U,
KHR_DF_CHANNEL_RGBSDA_BLUE = 2U,
KHR_DF_CHANNEL_RGBSDA_B = 2U,
KHR_DF_CHANNEL_RGBSDA_STENCIL = 13U,
KHR_DF_CHANNEL_RGBSDA_S = 13U,
KHR_DF_CHANNEL_RGBSDA_DEPTH = 14U,
KHR_DF_CHANNEL_RGBSDA_D = 14U,
KHR_DF_CHANNEL_RGBSDA_ALPHA = 15U,
KHR_DF_CHANNEL_RGBSDA_A = 15U,
/* MODEL_YUVSDA - luma, Cb, Cr, stencil, depth, alpha */
KHR_DF_CHANNEL_YUVSDA_Y = 0U,
KHR_DF_CHANNEL_YUVSDA_CB = 1U,
KHR_DF_CHANNEL_YUVSDA_U = 1U,
KHR_DF_CHANNEL_YUVSDA_CR = 2U,
KHR_DF_CHANNEL_YUVSDA_V = 2U,
KHR_DF_CHANNEL_YUVSDA_STENCIL = 13U,
KHR_DF_CHANNEL_YUVSDA_S = 13U,
KHR_DF_CHANNEL_YUVSDA_DEPTH = 14U,
KHR_DF_CHANNEL_YUVSDA_D = 14U,
KHR_DF_CHANNEL_YUVSDA_ALPHA = 15U,
KHR_DF_CHANNEL_YUVSDA_A = 15U,
/* MODEL_YIQSDA - luma, in-phase, quadrature, stencil, depth, alpha */
KHR_DF_CHANNEL_YIQSDA_Y = 0U,
KHR_DF_CHANNEL_YIQSDA_I = 1U,
KHR_DF_CHANNEL_YIQSDA_Q = 2U,
KHR_DF_CHANNEL_YIQSDA_STENCIL = 13U,
KHR_DF_CHANNEL_YIQSDA_S = 13U,
KHR_DF_CHANNEL_YIQSDA_DEPTH = 14U,
KHR_DF_CHANNEL_YIQSDA_D = 14U,
KHR_DF_CHANNEL_YIQSDA_ALPHA = 15U,
KHR_DF_CHANNEL_YIQSDA_A = 15U,
/* MODEL_LABSDA - CIELAB/L*a*b* luma, red-green, blue-yellow, stencil, depth, alpha */
KHR_DF_CHANNEL_LABSDA_L = 0U,
KHR_DF_CHANNEL_LABSDA_A = 1U,
KHR_DF_CHANNEL_LABSDA_B = 2U,
KHR_DF_CHANNEL_LABSDA_STENCIL = 13U,
KHR_DF_CHANNEL_LABSDA_S = 13U,
KHR_DF_CHANNEL_LABSDA_DEPTH = 14U,
KHR_DF_CHANNEL_LABSDA_D = 14U,
KHR_DF_CHANNEL_LABSDA_ALPHA = 15U,
/* NOTE: KHR_DF_CHANNEL_LABSDA_A is not a synonym for alpha! */
/* MODEL_CMYKA - cyan, magenta, yellow, key/blacK, alpha */
KHR_DF_CHANNEL_CMYKSDA_CYAN = 0U,
KHR_DF_CHANNEL_CMYKSDA_C = 0U,
KHR_DF_CHANNEL_CMYKSDA_MAGENTA = 1U,
KHR_DF_CHANNEL_CMYKSDA_M = 1U,
KHR_DF_CHANNEL_CMYKSDA_YELLOW = 2U,
KHR_DF_CHANNEL_CMYKSDA_Y = 2U,
KHR_DF_CHANNEL_CMYKSDA_KEY = 3U,
KHR_DF_CHANNEL_CMYKSDA_BLACK = 3U,
KHR_DF_CHANNEL_CMYKSDA_K = 3U,
KHR_DF_CHANNEL_CMYKSDA_ALPHA = 15U,
KHR_DF_CHANNEL_CMYKSDA_A = 15U,
/* MODEL_XYZW - coordinates x, y, z, w */
KHR_DF_CHANNEL_XYZW_X = 0U,
KHR_DF_CHANNEL_XYZW_Y = 1U,
KHR_DF_CHANNEL_XYZW_Z = 2U,
KHR_DF_CHANNEL_XYZW_W = 3U,
/* MODEL_HSVA_ANG - value (luma), saturation, hue, alpha, angular projection, conical space */
KHR_DF_CHANNEL_HSVA_ANG_VALUE = 0U,
KHR_DF_CHANNEL_HSVA_ANG_V = 0U,
KHR_DF_CHANNEL_HSVA_ANG_SATURATION = 1U,
KHR_DF_CHANNEL_HSVA_ANG_S = 1U,
KHR_DF_CHANNEL_HSVA_ANG_HUE = 2U,
KHR_DF_CHANNEL_HSVA_ANG_H = 2U,
KHR_DF_CHANNEL_HSVA_ANG_ALPHA = 15U,
KHR_DF_CHANNEL_HSVA_ANG_A = 15U,
/* MODEL_HSLA_ANG - lightness (luma), saturation, hue, alpha, angular projection, double conical space */
KHR_DF_CHANNEL_HSLA_ANG_LIGHTNESS = 0U,
KHR_DF_CHANNEL_HSLA_ANG_L = 0U,
KHR_DF_CHANNEL_HSLA_ANG_SATURATION = 1U,
KHR_DF_CHANNEL_HSLA_ANG_S = 1U,
KHR_DF_CHANNEL_HSLA_ANG_HUE = 2U,
KHR_DF_CHANNEL_HSLA_ANG_H = 2U,
KHR_DF_CHANNEL_HSLA_ANG_ALPHA = 15U,
KHR_DF_CHANNEL_HSLA_ANG_A = 15U,
/* MODEL_HSVA_HEX - value (luma), saturation, hue, alpha, hexagonal projection, conical space */
KHR_DF_CHANNEL_HSVA_HEX_VALUE = 0U,
KHR_DF_CHANNEL_HSVA_HEX_V = 0U,
KHR_DF_CHANNEL_HSVA_HEX_SATURATION = 1U,
KHR_DF_CHANNEL_HSVA_HEX_S = 1U,
KHR_DF_CHANNEL_HSVA_HEX_HUE = 2U,
KHR_DF_CHANNEL_HSVA_HEX_H = 2U,
KHR_DF_CHANNEL_HSVA_HEX_ALPHA = 15U,
KHR_DF_CHANNEL_HSVA_HEX_A = 15U,
/* MODEL_HSLA_HEX - lightness (luma), saturation, hue, alpha, hexagonal projection, double conical space */
KHR_DF_CHANNEL_HSLA_HEX_LIGHTNESS = 0U,
KHR_DF_CHANNEL_HSLA_HEX_L = 0U,
KHR_DF_CHANNEL_HSLA_HEX_SATURATION = 1U,
KHR_DF_CHANNEL_HSLA_HEX_S = 1U,
KHR_DF_CHANNEL_HSLA_HEX_HUE = 2U,
KHR_DF_CHANNEL_HSLA_HEX_H = 2U,
KHR_DF_CHANNEL_HSLA_HEX_ALPHA = 15U,
KHR_DF_CHANNEL_HSLA_HEX_A = 15U,
/* MODEL_YCGCOA - luma, green delta, orange delta, alpha */
KHR_DF_CHANNEL_YCGCOA_Y = 0U,
KHR_DF_CHANNEL_YCGCOA_CG = 1U,
KHR_DF_CHANNEL_YCGCOA_CO = 2U,
KHR_DF_CHANNEL_YCGCOA_ALPHA = 15U,
KHR_DF_CHANNEL_YCGCOA_A = 15U,
/* MODEL_CIEXYZ - CIE 1931 X, Y, Z */
KHR_DF_CHANNEL_CIEXYZ_X = 0U,
KHR_DF_CHANNEL_CIEXYZ_Y = 1U,
KHR_DF_CHANNEL_CIEXYZ_Z = 2U,
/* MODEL_CIEXYY - CIE 1931 x, y, Y */
KHR_DF_CHANNEL_CIEXYY_X = 0U,
KHR_DF_CHANNEL_CIEXYY_YCHROMA = 1U,
KHR_DF_CHANNEL_CIEXYY_YLUMA = 2U,
/* Compressed formats */
/* MODEL_DXT1A/MODEL_BC1A */
KHR_DF_CHANNEL_DXT1A_COLOR = 0U,
KHR_DF_CHANNEL_BC1A_COLOR = 0U,
KHR_DF_CHANNEL_DXT1A_ALPHAPRESENT = 1U,
KHR_DF_CHANNEL_DXT1A_ALPHA = 1U,
KHR_DF_CHANNEL_BC1A_ALPHAPRESENT = 1U,
KHR_DF_CHANNEL_BC1A_ALPHA = 1U,
/* MODEL_DXT2/3/MODEL_BC2 */
KHR_DF_CHANNEL_DXT2_COLOR = 0U,
KHR_DF_CHANNEL_DXT3_COLOR = 0U,
KHR_DF_CHANNEL_BC2_COLOR = 0U,
KHR_DF_CHANNEL_DXT2_ALPHA = 15U,
KHR_DF_CHANNEL_DXT3_ALPHA = 15U,
KHR_DF_CHANNEL_BC2_ALPHA = 15U,
/* MODEL_DXT4/5/MODEL_BC3 */
KHR_DF_CHANNEL_DXT4_COLOR = 0U,
KHR_DF_CHANNEL_DXT5_COLOR = 0U,
KHR_DF_CHANNEL_BC3_COLOR = 0U,
KHR_DF_CHANNEL_DXT4_ALPHA = 15U,
KHR_DF_CHANNEL_DXT5_ALPHA = 15U,
KHR_DF_CHANNEL_BC3_ALPHA = 15U,
/* MODEL_BC4 */
KHR_DF_CHANNEL_BC4_DATA = 0U,
/* MODEL_BC5 */
KHR_DF_CHANNEL_BC5_RED = 0U,
KHR_DF_CHANNEL_BC5_R = 0U,
KHR_DF_CHANNEL_BC5_GREEN = 1U,
KHR_DF_CHANNEL_BC5_G = 1U,
/* MODEL_BC6H */
KHR_DF_CHANNEL_BC6H_COLOR = 0U,
KHR_DF_CHANNEL_BC6H_DATA = 0U,
/* MODEL_BC7 */
KHR_DF_CHANNEL_BC7_DATA = 0U,
KHR_DF_CHANNEL_BC7_COLOR = 0U,
/* MODEL_ETC1 */
KHR_DF_CHANNEL_ETC1_DATA = 0U,
KHR_DF_CHANNEL_ETC1_COLOR = 0U,
/* MODEL_ETC2 */
KHR_DF_CHANNEL_ETC2_RED = 0U,
KHR_DF_CHANNEL_ETC2_R = 0U,
KHR_DF_CHANNEL_ETC2_GREEN = 1U,
KHR_DF_CHANNEL_ETC2_G = 1U,
KHR_DF_CHANNEL_ETC2_COLOR = 2U,
KHR_DF_CHANNEL_ETC2_ALPHA = 15U,
KHR_DF_CHANNEL_ETC2_A = 15U,
/* MODEL_ASTC */
KHR_DF_CHANNEL_ASTC_DATA = 0U,
/* MODEL_ETC1S */
KHR_DF_CHANNEL_ETC1S_RGB = 0U,
KHR_DF_CHANNEL_ETC1S_RRR = 3U,
KHR_DF_CHANNEL_ETC1S_GGG = 4U,
KHR_DF_CHANNEL_ETC1S_AAA = 15U,
/* MODEL_PVRTC */
KHR_DF_CHANNEL_PVRTC_DATA = 0U,
KHR_DF_CHANNEL_PVRTC_COLOR = 0U,
/* MODEL_PVRTC2 */
KHR_DF_CHANNEL_PVRTC2_DATA = 0U,
KHR_DF_CHANNEL_PVRTC2_COLOR = 0U,
/* MODEL UASTC */
KHR_DF_CHANNEL_UASTC_DATA = 0U,
KHR_DF_CHANNEL_UASTC_RGB = 0U,
KHR_DF_CHANNEL_UASTC_RGBA = 3U,
KHR_DF_CHANNEL_UASTC_RRR = 4U,
KHR_DF_CHANNEL_UASTC_RRRG = 5U,
KHR_DF_CHANNEL_UASTC_RG = 6U,
/* Common channel names shared by multiple formats */
KHR_DF_CHANNEL_COMMON_LUMA = 0U,
KHR_DF_CHANNEL_COMMON_L = 0U,
KHR_DF_CHANNEL_COMMON_STENCIL = 13U,
KHR_DF_CHANNEL_COMMON_S = 13U,
KHR_DF_CHANNEL_COMMON_DEPTH = 14U,
KHR_DF_CHANNEL_COMMON_D = 14U,
KHR_DF_CHANNEL_COMMON_ALPHA = 15U,
KHR_DF_CHANNEL_COMMON_A = 15U
} khr_df_model_channels_e;
/* Definition of the primary colors in color coordinates.
This is implicitly responsible for defining the conversion
between RGB an YUV color spaces.
LAB and related absolute color models should use
KHR_DF_PRIMARIES_CIEXYZ. */
typedef enum _khr_df_primaries_e {
/* No color primaries defined */
KHR_DF_PRIMARIES_UNSPECIFIED = 0U,
/* Color primaries of ITU-R BT.709 and sRGB */
KHR_DF_PRIMARIES_BT709 = 1U,
/* Synonym for KHR_DF_PRIMARIES_BT709 */
KHR_DF_PRIMARIES_SRGB = 1U,
/* Color primaries of ITU-R BT.601 (625-line EBU variant) */
KHR_DF_PRIMARIES_BT601_EBU = 2U,
/* Color primaries of ITU-R BT.601 (525-line SMPTE C variant) */
KHR_DF_PRIMARIES_BT601_SMPTE = 3U,
/* Color primaries of ITU-R BT.2020 */
KHR_DF_PRIMARIES_BT2020 = 4U,
/* CIE theoretical color coordinate space */
KHR_DF_PRIMARIES_CIEXYZ = 5U,
/* Academy Color Encoding System primaries */
KHR_DF_PRIMARIES_ACES = 6U,
/* Color primaries of ACEScc */
KHR_DF_PRIMARIES_ACESCC = 7U,
/* Legacy NTSC 1953 primaries */
KHR_DF_PRIMARIES_NTSC1953 = 8U,
/* Legacy PAL 525-line primaries */
KHR_DF_PRIMARIES_PAL525 = 9U,
/* Color primaries of Display P3 */
KHR_DF_PRIMARIES_DISPLAYP3 = 10U,
/* Color primaries of Adobe RGB (1998) */
KHR_DF_PRIMARIES_ADOBERGB = 11U,
KHR_DF_PRIMARIES_MAX = 0xFFU
} khr_df_primaries_e;
/* Definition of the optical to digital transfer function
("gamma correction"). Most transfer functions are not a pure
power function and also include a linear element.
LAB and related absolute color representations should use
KHR_DF_TRANSFER_UNSPECIFIED. */
typedef enum _khr_df_transfer_e {
/* No transfer function defined */
KHR_DF_TRANSFER_UNSPECIFIED = 0U,
/* Linear transfer function (value proportional to intensity) */
KHR_DF_TRANSFER_LINEAR = 1U,
/* Perceptually-linear transfer function of sRGH (~2.4) */
KHR_DF_TRANSFER_SRGB = 2U,
/* Perceptually-linear transfer function of ITU BT.601, BT.709 and BT.2020 (~1/.45) */
KHR_DF_TRANSFER_ITU = 3U,
/* SMTPE170M (digital NTSC) defines an alias for the ITU transfer function (~1/.45) */
KHR_DF_TRANSFER_SMTPE170M = 3U,
/* Perceptually-linear gamma function of original NTSC (simple 2.2 gamma) */
KHR_DF_TRANSFER_NTSC = 4U,
/* Sony S-log used by Sony video cameras */
KHR_DF_TRANSFER_SLOG = 5U,
/* Sony S-log 2 used by Sony video cameras */
KHR_DF_TRANSFER_SLOG2 = 6U,
/* ITU BT.1886 EOTF */
KHR_DF_TRANSFER_BT1886 = 7U,
/* ITU BT.2100 HLG OETF */
KHR_DF_TRANSFER_HLG_OETF = 8U,
/* ITU BT.2100 HLG EOTF */
KHR_DF_TRANSFER_HLG_EOTF = 9U,
/* ITU BT.2100 PQ EOTF */
KHR_DF_TRANSFER_PQ_EOTF = 10U,
/* ITU BT.2100 PQ OETF */
KHR_DF_TRANSFER_PQ_OETF = 11U,
/* DCI P3 transfer function */
KHR_DF_TRANSFER_DCIP3 = 12U,
/* Legacy PAL OETF */
KHR_DF_TRANSFER_PAL_OETF = 13U,
/* Legacy PAL 625-line EOTF */
KHR_DF_TRANSFER_PAL625_EOTF = 14U,
/* Legacy ST240 transfer function */
KHR_DF_TRANSFER_ST240 = 15U,
/* ACEScc transfer function */
KHR_DF_TRANSFER_ACESCC = 16U,
/* ACEScct transfer function */
KHR_DF_TRANSFER_ACESCCT = 17U,
/* Adobe RGB (1998) transfer function */
KHR_DF_TRANSFER_ADOBERGB = 18U,
KHR_DF_TRANSFER_MAX = 0xFFU
} khr_df_transfer_e;
typedef enum _khr_df_flags_e {
KHR_DF_FLAG_ALPHA_STRAIGHT = 0U,
KHR_DF_FLAG_ALPHA_PREMULTIPLIED = 1U
} khr_df_flags_e;
typedef enum _khr_df_sample_datatype_qualifiers_e {
KHR_DF_SAMPLE_DATATYPE_LINEAR = 1U << 4U,
KHR_DF_SAMPLE_DATATYPE_EXPONENT = 1U << 5U,
KHR_DF_SAMPLE_DATATYPE_SIGNED = 1U << 6U,
KHR_DF_SAMPLE_DATATYPE_FLOAT = 1U << 7U
} khr_df_sample_datatype_qualifiers_e;
#endif

1810
thirdparty/libktx/include/ktx.h vendored Normal file

File diff suppressed because it is too large Load Diff

253
thirdparty/libktx/include/ktxvulkan.h vendored Normal file
View File

@ -0,0 +1,253 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
#ifndef KTX_H_C54B42AEE39611E68E1E4FF8C51D1C66
#define KTX_H_C54B42AEE39611E68E1E4FF8C51D1C66
/*
* Copyright 2017-2020 The Khronos Group, Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file
* @~English
*
* @brief Declares the public functions and structures of the
* KTX Vulkan texture loading API.
*
* A separate header file is used to avoid extra dependencies for those not
* using Vulkan. The nature of the Vulkan API, rampant structures and enums,
* means that vulkan.h must be included @e before including this file. The
* alternative is duplicating unattractively large parts of it.
*
* @author Mark Callow, Edgewise Consulting
*
* $Date$
*/
#include <ktx.h>
#if 0
/* Avoid Vulkan include file */
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
#else
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
#endif
VK_DEFINE_HANDLE(VkPhysicalDevice)
VK_DEFINE_HANDLE(VkDevice)
VK_DEFINE_HANDLE(VkQueue)
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool)
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory)
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage)
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView)
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler)
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @struct ktxVulkanFunctions
* @~English
* @brief Struct for applications to pass Vulkan function pointers to the
* ktxTexture_VkUpload functions via a ktxVulkanDeviceInfo struct.
*
* @c vkGetInstanceProcAddr and @c vkGetDeviceProcAddr should be set, others
* are optional.
*/
typedef struct ktxVulkanFunctions {
// These are functions pointers we need to perform our vulkan duties.
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
// These we optionally specify
PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers;
PFN_vkAllocateMemory vkAllocateMemory;
PFN_vkBeginCommandBuffer vkBeginCommandBuffer;
PFN_vkBindBufferMemory vkBindBufferMemory;
PFN_vkBindImageMemory vkBindImageMemory;
PFN_vkCmdBlitImage vkCmdBlitImage;
PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage;
PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier;
PFN_vkCreateImage vkCreateImage;
PFN_vkDestroyImage vkDestroyImage;
PFN_vkCreateBuffer vkCreateBuffer;
PFN_vkDestroyBuffer vkDestroyBuffer;
PFN_vkCreateFence vkCreateFence;
PFN_vkDestroyFence vkDestroyFence;
PFN_vkEndCommandBuffer vkEndCommandBuffer;
PFN_vkFreeCommandBuffers vkFreeCommandBuffers;
PFN_vkFreeMemory vkFreeMemory;
PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout;
PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties;
PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties;
PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
PFN_vkMapMemory vkMapMemory;
PFN_vkQueueSubmit vkQueueSubmit;
PFN_vkQueueWaitIdle vkQueueWaitIdle;
PFN_vkUnmapMemory vkUnmapMemory;
PFN_vkWaitForFences vkWaitForFences;
} ktxVulkanFunctions;
/**
* @class ktxVulkanTexture
* @~English
* @brief Struct for returning information about the Vulkan texture image
* created by the ktxTexture_VkUpload* functions.
*
* Creation of these objects is internal to the upload functions.
*/
typedef struct ktxVulkanTexture
{
PFN_vkDestroyImage vkDestroyImage; /*!< Pointer to vkDestroyImage function */
PFN_vkFreeMemory vkFreeMemory; /*!< Pointer to vkFreeMemory function */
VkImage image; /*!< Handle to the Vulkan image created by the loader. */
VkFormat imageFormat; /*!< Format of the image data. */
VkImageLayout imageLayout; /*!< Layout of the created image. Has the same
value as @p layout parameter passed to the
loader. */
VkDeviceMemory deviceMemory; /*!< The memory allocated for the image on
the Vulkan device. */
VkImageViewType viewType; /*!< ViewType corresponding to @p image. Reflects
the dimensionality, cubeness and arrayness
of the image. */
uint32_t width; /*!< The width of the image. */
uint32_t height; /*!< The height of the image. */
uint32_t depth; /*!< The depth of the image. */
uint32_t levelCount; /*!< The number of MIP levels in the image. */
uint32_t layerCount; /*!< The number of array layers in the image. */
} ktxVulkanTexture;
KTX_API void KTX_APIENTRY
ktxVulkanTexture_Destruct(ktxVulkanTexture* This, VkDevice device,
const VkAllocationCallbacks* pAllocator);
/**
* @class ktxVulkanDeviceInfo
* @~English
* @brief Struct for passing information about the Vulkan device on which
* to create images to the texture image loading functions.
*
* Avoids passing a large number of parameters to each loading function.
* Use of ktxVulkanDeviceInfo_create() or ktxVulkanDeviceInfo_construct() to
* populate this structure is highly recommended.
*
* @code
ktxVulkanDeviceInfo vdi;
ktxVulkanTexture texture;
vdi = ktxVulkanDeviceInfo_create(physicalDevice,
device,
queue,
cmdPool,
&allocator);
ktxLoadVkTextureN("texture_1.ktx", vdi, &texture, NULL, NULL);
// ...
ktxLoadVkTextureN("texture_n.ktx", vdi, &texture, NULL, NULL);
ktxVulkanDeviceInfo_destroy(vdi);
* @endcode
*/
typedef struct ktxVulkanDeviceInfo {
VkInstance instance; /*!< Instance used to communicate with vulkan. */
VkPhysicalDevice physicalDevice; /*!< Handle of the physical device. */
VkDevice device; /*!< Handle of the logical device. */
VkQueue queue; /*!< Handle to the queue to which to submit commands. */
VkCommandBuffer cmdBuffer; /*!< Handle of the cmdBuffer to use. */
/** Handle of the command pool from which to allocate the command buffer. */
VkCommandPool cmdPool;
/** Pointer to the allocator to use for the command buffer and created
* images.
*/
const VkAllocationCallbacks* pAllocator;
/** Memory properties of the Vulkan physical device. */
VkPhysicalDeviceMemoryProperties deviceMemoryProperties;
/** The functions needed to operate functions */
ktxVulkanFunctions vkFuncs;
} ktxVulkanDeviceInfo;
KTX_API ktxVulkanDeviceInfo* KTX_APIENTRY
ktxVulkanDeviceInfo_CreateEx(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device,
VkQueue queue, VkCommandPool cmdPool,
const VkAllocationCallbacks* pAllocator,
const ktxVulkanFunctions* pFunctions);
KTX_API ktxVulkanDeviceInfo* KTX_APIENTRY
ktxVulkanDeviceInfo_Create(VkPhysicalDevice physicalDevice, VkDevice device,
VkQueue queue, VkCommandPool cmdPool,
const VkAllocationCallbacks* pAllocator);
KTX_API KTX_error_code KTX_APIENTRY
ktxVulkanDeviceInfo_Construct(ktxVulkanDeviceInfo* This,
VkPhysicalDevice physicalDevice, VkDevice device,
VkQueue queue, VkCommandPool cmdPool,
const VkAllocationCallbacks* pAllocator);
KTX_API KTX_error_code KTX_APIENTRY
ktxVulkanDeviceInfo_ConstructEx(ktxVulkanDeviceInfo* This,
VkInstance instance,
VkPhysicalDevice physicalDevice, VkDevice device,
VkQueue queue, VkCommandPool cmdPool,
const VkAllocationCallbacks* pAllocator,
const ktxVulkanFunctions* pFunctions);
KTX_API void KTX_APIENTRY
ktxVulkanDeviceInfo_Destruct(ktxVulkanDeviceInfo* This);
KTX_API void KTX_APIENTRY
ktxVulkanDeviceInfo_Destroy(ktxVulkanDeviceInfo* This);
KTX_API KTX_error_code KTX_APIENTRY
ktxTexture_VkUploadEx(ktxTexture* This, ktxVulkanDeviceInfo* vdi,
ktxVulkanTexture* vkTexture,
VkImageTiling tiling,
VkImageUsageFlags usageFlags,
VkImageLayout finalLayout);
KTX_API KTX_error_code KTX_APIENTRY
ktxTexture_VkUpload(ktxTexture* texture, ktxVulkanDeviceInfo* vdi,
ktxVulkanTexture *vkTexture);
KTX_API KTX_error_code KTX_APIENTRY
ktxTexture1_VkUploadEx(ktxTexture1* This, ktxVulkanDeviceInfo* vdi,
ktxVulkanTexture* vkTexture,
VkImageTiling tiling,
VkImageUsageFlags usageFlags,
VkImageLayout finalLayout);
KTX_API KTX_error_code KTX_APIENTRY
ktxTexture1_VkUpload(ktxTexture1* texture, ktxVulkanDeviceInfo* vdi,
ktxVulkanTexture *vkTexture);
KTX_API KTX_error_code KTX_APIENTRY
ktxTexture2_VkUploadEx(ktxTexture2* This, ktxVulkanDeviceInfo* vdi,
ktxVulkanTexture* vkTexture,
VkImageTiling tiling,
VkImageUsageFlags usageFlags,
VkImageLayout finalLayout);
KTX_API KTX_error_code KTX_APIENTRY
ktxTexture2_VkUpload(ktxTexture2* texture, ktxVulkanDeviceInfo* vdi,
ktxVulkanTexture *vkTexture);
KTX_API VkFormat KTX_APIENTRY
ktxTexture_GetVkFormat(ktxTexture* This);
KTX_API VkFormat KTX_APIENTRY
ktxTexture1_GetVkFormat(ktxTexture1* This);
KTX_API VkFormat KTX_APIENTRY
ktxTexture2_GetVkFormat(ktxTexture2* This);
#ifdef __cplusplus
}
#endif
#endif /* KTX_H_A55A6F00956F42F3A137C11929827FE1 */

85
thirdparty/libktx/lib/basis_sgd.h vendored Normal file
View File

@ -0,0 +1,85 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab textwidth=70: */
/*
* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file basisu_sgd.h
* @~English
*
* @brief Declare global data for Basis LZ supercompression with ETC1S.
*
* These functions are private and should not be used outside the library.
*/
#ifndef _BASIS_SGD_H_
#define _BASIS_SGD_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// This must be the same value as cSliceDescFlagsFrameIsIFrame so we can just
// invert the bit when passing back & forth. As FrameIsIFrame is within
// a C namespace it can't easily be accessed from a c header.
enum bu_image_flags__bits_e { eBUImageIsPframe = 0x02 };
typedef uint32_t buFlags;
typedef struct ktxBasisLzGlobalHeader {
uint16_t endpointCount;
uint16_t selectorCount;
uint32_t endpointsByteLength;
uint32_t selectorsByteLength;
uint32_t tablesByteLength;
uint32_t extendedByteLength;
} ktxBasisLzGlobalHeader;
// This header is followed by imageCount "slice" descriptions.
// 1, or 2 slices per image (i.e. layer, face & slice).
// These offsets are relative to start of a mip level as given by the
// main levelIndex.
typedef struct ktxBasisLzEtc1sImageDesc {
buFlags imageFlags;
uint32_t rgbSliceByteOffset;
uint32_t rgbSliceByteLength;
uint32_t alphaSliceByteOffset;
uint32_t alphaSliceByteLength;
} ktxBasisLzEtc1sImageDesc;
#define BGD_ETC1S_IMAGE_DESCS(bgd) \
reinterpret_cast<ktxBasisLzEtc1sImageDesc*>(bgd + sizeof(ktxBasisLzGlobalHeader))
// The are followed in the global data by these ...
// uint8_t[endpointsByteLength] endpointsData;
// uint8_t[selectorsByteLength] selectorsData;
// uint8_t[tablesByteLength] tablesData;
#define BGD_ENDPOINTS_ADDR(bgd, imageCount) \
(bgd + sizeof(ktxBasisLzGlobalHeader) + sizeof(ktxBasisLzEtc1sImageDesc) * imageCount)
#define BGD_SELECTORS_ADDR(bgd, bgdh, imageCount) (BGD_ENDPOINTS_ADDR(bgd, imageCount) + bgdh.endpointsByteLength)
#define BGD_TABLES_ADDR(bgd, bgdh, imageCount) (BGD_SELECTORS_ADDR(bgd, bgdh, imageCount) + bgdh.selectorsByteLength)
#define BGD_EXTENDED_ADDR(bgd, bgdh, imageCount) (BGD_TABLES_ADDR(bgd, bgdh, imageCount) + bgdh.tablesByteLength)
// Just because this is a convenient place to put it for basis_{en,trans}code.
enum alpha_content_e {
eNone,
eAlpha,
eGreen
};
#ifdef __cplusplus
}
#endif
#endif /* _BASIS_SGD_H_ */

View File

@ -0,0 +1,733 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file basis_transcode.cpp
* @~English
*
* @brief Functions for transcoding Basis Universal BasisLZ/ETC1S and UASTC textures.
*
* Two worlds collide here too. More uglyness!
*
* @author Mark Callow, www.edgewise-consulting.com
*/
#include <inttypes.h>
#include <stdio.h>
#include <KHR/khr_df.h>
#include "dfdutils/dfd.h"
#include "ktx.h"
#include "ktxint.h"
#include "texture2.h"
#include "vkformat_enum.h"
#include "vk_format.h"
#include "basis_sgd.h"
#include "transcoder/basisu_file_headers.h"
#include "transcoder/basisu_transcoder.h"
#include "transcoder/basisu_transcoder_internal.h"
#undef DECLARE_PRIVATE
#undef DECLARE_PROTECTED
#define DECLARE_PRIVATE(n,t2) ktxTexture2_private& n = *(t2->_private)
#define DECLARE_PROTECTED(n,t2) ktxTexture_protected& n = *(t2->_protected)
using namespace basisu;
using namespace basist;
inline bool isPow2(uint32_t x) { return x && ((x & (x - 1U)) == 0U); }
inline bool isPow2(uint64_t x) { return x && ((x & (x - 1U)) == 0U); }
KTX_error_code
ktxTexture2_transcodeLzEtc1s(ktxTexture2* This,
alpha_content_e alphaContent,
ktxTexture2* prototype,
ktx_transcode_fmt_e outputFormat,
ktx_transcode_flags transcodeFlags);
KTX_error_code
ktxTexture2_transcodeUastc(ktxTexture2* This,
alpha_content_e alphaContent,
ktxTexture2* prototype,
ktx_transcode_fmt_e outputFormat,
ktx_transcode_flags transcodeFlags);
/**
* @memberof ktxTexture2
* @ingroup reader
* @~English
* @brief Transcode a KTX2 texture with BasisLZ/ETC1S or UASTC images.
*
* If the texture contains BasisLZ supercompressed images, Inflates them from
* back to ETC1S then transcodes them to the specified block-compressed
* format. If the texture contains UASTC images, inflates them, if they have been
* supercompressed with zstd, then transcodes then to the specified format, The
* transcoded images replace the original images and the texture's fields including
* the DFD are modified to reflect the new format.
*
* These types of textures must be transcoded to a desired target
* block-compressed format before they can be uploaded to a GPU via a
* graphics API.
*
* The following block compressed transcode targets are available: @c KTX_TTF_ETC1_RGB,
* @c KTX_TTF_ETC2_RGBA, @c KTX_TTF_BC1_RGB, @c KTX_TTF_BC3_RGBA,
* @c KTX_TTF_BC4_R, @c KTX_TTF_BC5_RG, @c KTX_TTF_BC7_RGBA,
* @c @c KTX_TTF_PVRTC1_4_RGB, @c KTX_TTF_PVRTC1_4_RGBA,
* @c KTX_TTF_PVRTC2_4_RGB, @c KTX_TTF_PVRTC2_4_RGBA, @c KTX_TTF_ASTC_4x4_RGBA,
* @c KTX_TTF_ETC2_EAC_R11, @c KTX_TTF_ETC2_EAC_RG11, @c KTX_TTF_ETC and
* @c KTX_TTF_BC1_OR_3.
*
* @c KTX_TTF_ETC automatically selects between @c KTX_TTF_ETC1_RGB and
* @c KTX_TTF_ETC2_RGBA according to whether an alpha channel is available. @c KTX_TTF_BC1_OR_3
* does likewise between @c KTX_TTF_BC1_RGB and @c KTX_TTF_BC3_RGBA. Note that if
* @c KTX_TTF_PVRTC1_4_RGBA or @c KTX_TTF_PVRTC2_4_RGBA is specified and there is no alpha
* channel @c KTX_TTF_PVRTC1_4_RGB or @c KTX_TTF_PVRTC2_4_RGB respectively will be selected.
*
* Transcoding to ATC & FXT1 formats is not supported by libktx as there
* are no equivalent Vulkan formats.
*
* The following uncompressed transcode targets are also available: @c KTX_TTF_RGBA32,
* @c KTX_TTF_RGB565, KTX_TTF_BGR565 and KTX_TTF_RGBA4444.
*
* The following @p transcodeFlags are available.
*
* @sa ktxtexture2_CompressBasis().
*
* @param[in] This pointer to the ktxTexture2 object of interest.
* @param[in] outputFormat a value from the ktx_texture_transcode_fmt_e enum
* specifying the target format.
* @param[in] transcodeFlags bitfield of flags modifying the transcode
* operation. @sa ktx_texture_decode_flags_e.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_FILE_DATA_ERROR
* Supercompression global data is corrupted.
* @exception KTX_INVALID_OPERATION
* The texture's format is not transcodable (not
* ETC1S/BasisLZ or UASTC).
* @exception KTX_INVALID_OPERATION
* Supercompression global data is missing, i.e.,
* the texture object is invalid.
* @exception KTX_INVALID_OPERATION
* Image data is missing, i.e., the texture object
* is invalid.
* @exception KTX_INVALID_OPERATION
* @p outputFormat is PVRTC1 but the texture does
* does not have power-of-two dimensions.
* @exception KTX_INVALID_VALUE @p outputFormat is invalid.
* @exception KTX_TRANSCODE_FAILED
* Something went wrong during transcoding.
* @exception KTX_UNSUPPORTED_FEATURE
* KTX_TF_PVRTC_DECODE_TO_NEXT_POW2 was requested
* or the specified transcode target has not been
* included in the library being used.
* @exception KTX_OUT_OF_MEMORY Not enough memory to carry out transcoding.
*/
KTX_error_code
ktxTexture2_TranscodeBasis(ktxTexture2* This,
ktx_transcode_fmt_e outputFormat,
ktx_transcode_flags transcodeFlags)
{
uint32_t* BDB = This->pDfd + 1;
khr_df_model_e colorModel = (khr_df_model_e)KHR_DFDVAL(BDB, MODEL);
if (colorModel != KHR_DF_MODEL_UASTC
// Constructor has checked color model matches BASIS_LZ.
&& This->supercompressionScheme != KTX_SS_BASIS_LZ)
{
return KTX_INVALID_OPERATION; // Not in a transcodable format.
}
DECLARE_PRIVATE(priv, This);
if (This->supercompressionScheme == KTX_SS_BASIS_LZ) {
if (!priv._supercompressionGlobalData || priv._sgdByteLength == 0)
return KTX_INVALID_OPERATION;
}
if (transcodeFlags & KTX_TF_PVRTC_DECODE_TO_NEXT_POW2) {
debug_printf("ktxTexture_TranscodeBasis: KTX_TF_PVRTC_DECODE_TO_NEXT_POW2 currently unsupported\n");
return KTX_UNSUPPORTED_FEATURE;
}
if (outputFormat == KTX_TTF_PVRTC1_4_RGB
|| outputFormat == KTX_TTF_PVRTC1_4_RGBA) {
if ((!isPow2(This->baseWidth)) || (!isPow2(This->baseHeight))) {
debug_printf("ktxTexture_TranscodeBasis: PVRTC1 only supports power of 2 dimensions\n");
return KTX_INVALID_OPERATION;
}
}
const bool srgb = (KHR_DFDVAL(BDB, TRANSFER) == KHR_DF_TRANSFER_SRGB);
alpha_content_e alphaContent = eNone;
if (colorModel == KHR_DF_MODEL_ETC1S) {
if (KHR_DFDSAMPLECOUNT(BDB) == 2) {
uint32_t channelId = KHR_DFDSVAL(BDB, 1, CHANNELID);
if (channelId == KHR_DF_CHANNEL_ETC1S_AAA) {
alphaContent = eAlpha;
} else if (channelId == KHR_DF_CHANNEL_ETC1S_GGG){
alphaContent = eGreen;
} else {
return KTX_FILE_DATA_ERROR;
}
}
} else {
uint32_t channelId = KHR_DFDSVAL(BDB, 0, CHANNELID);
if (channelId == KHR_DF_CHANNEL_UASTC_RGBA)
alphaContent = eAlpha;
else if (channelId == KHR_DF_CHANNEL_UASTC_RRRG)
alphaContent = eGreen;
}
VkFormat vkFormat;
// Do some format mapping.
switch (outputFormat) {
case KTX_TTF_BC1_OR_3:
outputFormat = alphaContent != eNone ? KTX_TTF_BC3_RGBA
: KTX_TTF_BC1_RGB;
break;
case KTX_TTF_ETC:
outputFormat = alphaContent != eNone ? KTX_TTF_ETC2_RGBA
: KTX_TTF_ETC1_RGB;
break;
case KTX_TTF_PVRTC1_4_RGBA:
// This transcoder does not write opaque alpha blocks.
outputFormat = alphaContent != eNone ? KTX_TTF_PVRTC1_4_RGBA
: KTX_TTF_PVRTC1_4_RGB;
break;
case KTX_TTF_PVRTC2_4_RGBA:
// This transcoder does not write opaque alpha blocks.
outputFormat = alphaContent != eNone ? KTX_TTF_PVRTC2_4_RGBA
: KTX_TTF_PVRTC2_4_RGB;
break;
default:
/*NOP*/;
}
switch (outputFormat) {
case KTX_TTF_ETC1_RGB:
vkFormat = srgb ? VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK
: VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
break;
case KTX_TTF_ETC2_RGBA:
vkFormat = srgb ? VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK
: VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
break;
case KTX_TTF_ETC2_EAC_R11:
vkFormat = VK_FORMAT_EAC_R11_UNORM_BLOCK;
break;
case KTX_TTF_ETC2_EAC_RG11:
vkFormat = VK_FORMAT_EAC_R11G11_UNORM_BLOCK;
break;
case KTX_TTF_BC1_RGB:
// Transcoding doesn't support BC1 alpha.
vkFormat = srgb ? VK_FORMAT_BC1_RGB_SRGB_BLOCK
: VK_FORMAT_BC1_RGB_UNORM_BLOCK;
break;
case KTX_TTF_BC3_RGBA:
vkFormat = srgb ? VK_FORMAT_BC3_SRGB_BLOCK
: VK_FORMAT_BC3_UNORM_BLOCK;
break;
case KTX_TTF_BC4_R:
vkFormat = VK_FORMAT_BC4_UNORM_BLOCK;
break;
case KTX_TTF_BC5_RG:
vkFormat = VK_FORMAT_BC5_UNORM_BLOCK;
break;
case KTX_TTF_PVRTC1_4_RGB:
case KTX_TTF_PVRTC1_4_RGBA:
vkFormat = srgb ? VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG
: VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
break;
case KTX_TTF_PVRTC2_4_RGB:
case KTX_TTF_PVRTC2_4_RGBA:
vkFormat = srgb ? VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG
: VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG;
break;
case KTX_TTF_BC7_RGBA:
vkFormat = srgb ? VK_FORMAT_BC7_SRGB_BLOCK
: VK_FORMAT_BC7_UNORM_BLOCK;
break;
case KTX_TTF_ASTC_4x4_RGBA:
vkFormat = srgb ? VK_FORMAT_ASTC_4x4_SRGB_BLOCK
: VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
break;
case KTX_TTF_RGB565:
vkFormat = VK_FORMAT_R5G6B5_UNORM_PACK16;
break;
case KTX_TTF_BGR565:
vkFormat = VK_FORMAT_B5G6R5_UNORM_PACK16;
break;
case KTX_TTF_RGBA4444:
vkFormat = VK_FORMAT_R4G4B4A4_UNORM_PACK16;
break;
case KTX_TTF_RGBA32:
vkFormat = srgb ? VK_FORMAT_R8G8B8A8_SRGB
: VK_FORMAT_R8G8B8A8_UNORM;
break;
default:
return KTX_INVALID_VALUE;
}
basis_tex_format textureFormat;
if (colorModel == KHR_DF_MODEL_UASTC)
textureFormat = basis_tex_format::cUASTC4x4;
else
textureFormat = basis_tex_format::cETC1S;
if (!basis_is_format_supported((transcoder_texture_format)outputFormat,
textureFormat)) {
return KTX_UNSUPPORTED_FEATURE;
}
// Create a prototype texture to use for calculating sizes in the target
// format and, as useful side effects, provide us with a properly sized
// data allocation and the DFD for the target format.
ktxTextureCreateInfo createInfo;
createInfo.glInternalformat = 0;
createInfo.vkFormat = vkFormat;
createInfo.baseWidth = This->baseWidth;
createInfo.baseHeight = This->baseHeight;
createInfo.baseDepth = This->baseDepth;
createInfo.generateMipmaps = This->generateMipmaps;
createInfo.isArray = This->isArray;
createInfo.numDimensions = This->numDimensions;
createInfo.numFaces = This->numFaces;
createInfo.numLayers = This->numLayers;
createInfo.numLevels = This->numLevels;
createInfo.pDfd = nullptr;
KTX_error_code result;
ktxTexture2* prototype;
result = ktxTexture2_Create(&createInfo, KTX_TEXTURE_CREATE_ALLOC_STORAGE,
&prototype);
if (result != KTX_SUCCESS) {
assert(result == KTX_OUT_OF_MEMORY); // The only run time error
return result;
}
if (!This->pData) {
if (ktxTexture_isActiveStream((ktxTexture*)This)) {
// Load pending. Complete it.
result = ktxTexture2_LoadImageData(This, NULL, 0);
if (result != KTX_SUCCESS)
{
ktxTexture2_Destroy(prototype);
return result;
}
} else {
// No data to transcode.
ktxTexture2_Destroy(prototype);
return KTX_INVALID_OPERATION;
}
}
// Transcoder global initialization. Requires ~9 milliseconds when compiled
// and executed natively on a Core i7 2.2 GHz. If this is too slow, the
// tables it computes can easily be moved to be compiled in.
static bool transcoderInitialized;
if (!transcoderInitialized) {
basisu_transcoder_init();
transcoderInitialized = true;
}
if (textureFormat == basis_tex_format::cETC1S) {
result = ktxTexture2_transcodeLzEtc1s(This, alphaContent,
prototype, outputFormat,
transcodeFlags);
} else {
result = ktxTexture2_transcodeUastc(This, alphaContent,
prototype, outputFormat,
transcodeFlags);
}
if (result == KTX_SUCCESS) {
// Fix up the current texture
DECLARE_PROTECTED(thisPrtctd, This);
DECLARE_PRIVATE(protoPriv, prototype);
DECLARE_PROTECTED(protoPrtctd, prototype);
memcpy(&thisPrtctd._formatSize, &protoPrtctd._formatSize,
sizeof(ktxFormatSize));
This->vkFormat = vkFormat;
This->isCompressed = prototype->isCompressed;
This->supercompressionScheme = KTX_SS_NONE;
priv._requiredLevelAlignment = protoPriv._requiredLevelAlignment;
// Copy the levelIndex from the prototype to This.
memcpy(priv._levelIndex, protoPriv._levelIndex,
This->numLevels * sizeof(ktxLevelIndexEntry));
// Move the DFD and data from the prototype to This.
free(This->pDfd);
This->pDfd = prototype->pDfd;
prototype->pDfd = 0;
free(This->pData);
This->pData = prototype->pData;
This->dataSize = prototype->dataSize;
prototype->pData = 0;
prototype->dataSize = 0;
}
ktxTexture2_Destroy(prototype);
return result;
}
/**
* @memberof ktxTexture2 @private
* @ingroup reader
* @~English
* @brief Transcode a KTX2 texture with BasisLZ supercompressed ETC1S images.
*
* Inflates the images from BasisLZ supercompression back to ETC1S
* then transcodes them to the specified block-compressed format. The
* transcoded images replace the original images and the texture's fields
* including the DFD are modified to reflect the new format.
*
* BasisLZ supercompressed textures must be transcoded to a desired target
* block-compressed format before they can be uploaded to a GPU via a graphics
* API.
*
* The following block compressed transcode targets are available: @c KTX_TTF_ETC1_RGB,
* @c KTX_TTF_ETC2_RGBA, @c KTX_TTF_BC1_RGB, @c KTX_TTF_BC3_RGBA,
* @c KTX_TTF_BC4_R, @c KTX_TTF_BC5_RG, @c KTX_TTF_BC7_RGBA,
* @c @c KTX_TTF_PVRTC1_4_RGB, @c KTX_TTF_PVRTC1_4_RGBA,
* @c KTX_TTF_PVRTC2_4_RGB, @c KTX_TTF_PVRTC2_4_RGBA, @c KTX_TTF_ASTC_4x4_RGBA,
* @c KTX_TTF_ETC2_EAC_R11, @c KTX_TTF_ETC2_EAC_RG11, @c KTX_TTF_ETC and
* @c KTX_TTF_BC1_OR_3.
*
* @c KTX_TTF_ETC automatically selects between @c KTX_TTF_ETC1_RGB and
* @c KTX_TTF_ETC2_RGBA according to whether an alpha channel is available. @c KTX_TTF_BC1_OR_3
* does likewise between @c KTX_TTF_BC1_RGB and @c KTX_TTF_BC3_RGBA. Note that if
* @c KTX_TTF_PVRTC1_4_RGBA or @c KTX_TTF_PVRTC2_4_RGBA is specified and there is no alpha
* channel @c KTX_TTF_PVRTC1_4_RGB or @c KTX_TTF_PVRTC2_4_RGB respectively will be selected.
*
* ATC & FXT1 formats are not supported by KTX2 & libktx as there are no equivalent Vulkan formats.
*
* The following uncompressed transcode targets are also available: @c KTX_TTF_RGBA32,
* @c KTX_TTF_RGB565, KTX_TTF_BGR565 and KTX_TTF_RGBA4444.
*
* The following @p transcodeFlags are available.
*
* @sa ktxtexture2_CompressBasis().
*
* @param[in] This pointer to the ktxTexture2 object of interest.
* @param[in] outputFormat a value from the ktx_texture_transcode_fmt_e enum
* specifying the target format.
* @param[in] transcodeFlags bitfield of flags modifying the transcode
* operation. @sa ktx_texture_decode_flags_e.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_FILE_DATA_ERROR
* Supercompression global data is corrupted.
* @exception KTX_INVALID_OPERATION
* The texture's format is not transcodable (not
* ETC1S/BasisLZ or UASTC).
* @exception KTX_INVALID_OPERATION
* Supercompression global data is missing, i.e.,
* the texture object is invalid.
* @exception KTX_INVALID_OPERATION
* Image data is missing, i.e., the texture object
* is invalid.
* @exception KTX_INVALID_OPERATION
* @p outputFormat is PVRTC1 but the texture does
* does not have power-of-two dimensions.
* @exception KTX_INVALID_VALUE @p outputFormat is invalid.
* @exception KTX_TRANSCODE_FAILED
* Something went wrong during transcoding. The
* texture object will be corrupted.
* @exception KTX_UNSUPPORTED_FEATURE
* KTX_TF_PVRTC_DECODE_TO_NEXT_POW2 was requested
* or the specified transcode target has not been
* included in the library being used.
* @exception KTX_OUT_OF_MEMORY Not enough memory to carry out transcoding.
*/
KTX_error_code
ktxTexture2_transcodeLzEtc1s(ktxTexture2* This,
alpha_content_e alphaContent,
ktxTexture2* prototype,
ktx_transcode_fmt_e outputFormat,
ktx_transcode_flags transcodeFlags)
{
DECLARE_PRIVATE(priv, This);
DECLARE_PRIVATE(protoPriv, prototype);
KTX_error_code result = KTX_SUCCESS;
assert(This->supercompressionScheme == KTX_SS_BASIS_LZ);
uint8_t* bgd = priv._supercompressionGlobalData;
ktxBasisLzGlobalHeader& bgdh = *reinterpret_cast<ktxBasisLzGlobalHeader*>(bgd);
if (!(bgdh.endpointsByteLength && bgdh.selectorsByteLength && bgdh.tablesByteLength)) {
debug_printf("ktxTexture_TranscodeBasis: missing endpoints, selectors or tables");
return KTX_FILE_DATA_ERROR;
}
// Compute some helpful numbers.
//
// firstImages contains the indices of the first images for each level to
// ease finding the correct slice description when iterating from smallest
// level to largest or when randomly accessing them (t.b.c). The last array
// entry contains the total number of images, for calculating the offsets
// of the endpoints, etc.
uint32_t* firstImages = new uint32_t[This->numLevels+1];
// Temporary invariant value
uint32_t layersFaces = This->numLayers * This->numFaces;
firstImages[0] = 0;
for (uint32_t level = 1; level <= This->numLevels; level++) {
// NOTA BENE: numFaces * depth is only reasonable because they can't
// both be > 1. I.e there are no 3d cubemaps.
firstImages[level] = firstImages[level - 1]
+ layersFaces * MAX(This->baseDepth >> (level - 1), 1);
}
uint32_t& imageCount = firstImages[This->numLevels];
if (BGD_TABLES_ADDR(0, bgdh, imageCount) + bgdh.tablesByteLength > priv._sgdByteLength) {
return KTX_FILE_DATA_ERROR;
}
// FIXME: Do more validation.
// Prepare low-level transcoder for transcoding slices.
basist::basisu_lowlevel_etc1s_transcoder bit;
// basisu_transcoder_state is used to find the previous frame when
// decoding a video P-Frame. It tracks the previous frame for each mip
// level. For cube map array textures we need to find the previous frame
// for each face so we a state per face. Although providing this is only
// needed for video, it is easier to always pass our own.
std::vector<basisu_transcoder_state> xcoderStates;
xcoderStates.resize(This->isVideo ? This->numFaces : 1);
bit.decode_palettes(bgdh.endpointCount, BGD_ENDPOINTS_ADDR(bgd, imageCount),
bgdh.endpointsByteLength,
bgdh.selectorCount, BGD_SELECTORS_ADDR(bgd, bgdh, imageCount),
bgdh.selectorsByteLength);
bit.decode_tables(BGD_TABLES_ADDR(bgd, bgdh, imageCount),
bgdh.tablesByteLength);
// Find matching VkFormat and calculate output sizes.
const bool isVideo = This->isVideo;
ktx_uint8_t* pXcodedData = prototype->pData;
// Inconveniently, the output buffer size parameter of transcode_image
// has to be in pixels for uncompressed output and in blocks for
// compressed output. The only reason for humouring the API is so
// its buffer size tests provide a real check. An alternative is to
// always provide the size in bytes which will always pass.
ktx_uint32_t outputBlockByteLength
= prototype->_protected->_formatSize.blockSizeInBits / 8;
ktx_size_t xcodedDataLength
= prototype->dataSize / outputBlockByteLength;
ktxLevelIndexEntry* protoLevelIndex;
uint64_t levelOffsetWrite;
const ktxBasisLzEtc1sImageDesc* imageDescs = BGD_ETC1S_IMAGE_DESCS(bgd);
// Finally we're ready to transcode the slices.
// FIXME: Iframe flag needs to be queryable by the application. In Basis
// the app can query file_info and image_info from the transcoder which
// returns a structure with lots of info about the image.
protoLevelIndex = protoPriv._levelIndex;
levelOffsetWrite = 0;
for (int32_t level = This->numLevels - 1; level >= 0; level--) {
uint64_t levelOffset = ktxTexture2_levelDataOffset(This, level);
uint64_t writeOffset = levelOffsetWrite;
uint64_t writeOffsetBlocks = levelOffsetWrite / outputBlockByteLength;
uint32_t levelWidth = MAX(1, This->baseWidth >> level);
uint32_t levelHeight = MAX(1, This->baseHeight >> level);
// ETC1S texel block dimensions
const uint32_t bw = 4, bh = 4;
uint32_t levelBlocksX = (levelWidth + (bw - 1)) / bw;
uint32_t levelBlocksY = (levelHeight + (bh - 1)) / bh;
uint32_t depth = MAX(1, This->baseDepth >> level);
//uint32_t faceSlices = This->numFaces == 1 ? depth : This->numFaces;
uint32_t faceSlices = This->numFaces * depth;
uint32_t numImages = This->numLayers * faceSlices;
uint32_t image = firstImages[level];
uint32_t endImage = image + numImages;
ktx_size_t levelImageSizeOut, levelSizeOut;
uint32_t stateIndex = 0;
levelSizeOut = 0;
// FIXME: Figure out a way to get the size out of the transcoder.
levelImageSizeOut = ktxTexture2_GetImageSize(prototype, level);
for (; image < endImage; image++) {
const ktxBasisLzEtc1sImageDesc& imageDesc = imageDescs[image];
basisu_transcoder_state& xcoderState = xcoderStates[stateIndex];
// We have face0 [face1 ...] within each layer. Use `stateIndex`
// rather than a double loop of layers and faceSlices as this
// works for 3d texture and non-array cube maps as well as
// cube map arrays without special casing.
if (++stateIndex == xcoderStates.size())
stateIndex = 0;
if (alphaContent != eNone)
{
// The slice descriptions should have alpha information.
if (imageDesc.alphaSliceByteOffset == 0
|| imageDesc.alphaSliceByteLength == 0)
return KTX_FILE_DATA_ERROR;
}
bool status;
status = bit.transcode_image(
(transcoder_texture_format)outputFormat,
pXcodedData + writeOffset,
(uint32_t)(xcodedDataLength - writeOffsetBlocks),
This->pData,
(uint32_t)This->dataSize,
levelBlocksX,
levelBlocksY,
levelWidth,
levelHeight,
level,
(uint32_t)(levelOffset + imageDesc.rgbSliceByteOffset),
imageDesc.rgbSliceByteLength,
(uint32_t)(levelOffset + imageDesc.alphaSliceByteOffset),
imageDesc.alphaSliceByteLength,
transcodeFlags,
alphaContent != eNone,
isVideo,
// Our P-Frame flag is in the same bit as
// cSliceDescFlagsFrameIsIFrame. We have to
// invert it to make it an I-Frame flag.
//
// API currently doesn't have any way to pass
// the I-Frame flag.
//imageDesc.imageFlags ^ cSliceDescFlagsFrameIsIFrame,
0, // output_row_pitch_in_blocks_or_pixels
&xcoderState,
0 // output_rows_in_pixels
);
if (!status) {
result = KTX_TRANSCODE_FAILED;
goto cleanup;
}
writeOffset += levelImageSizeOut;
levelSizeOut += levelImageSizeOut;
} // end images loop
protoLevelIndex[level].byteOffset = levelOffsetWrite;
protoLevelIndex[level].byteLength = levelSizeOut;
protoLevelIndex[level].uncompressedByteLength = levelSizeOut;
levelOffsetWrite += levelSizeOut;
assert(levelOffsetWrite == writeOffset);
// In case of transcoding to uncompressed.
levelOffsetWrite = _KTX_PADN(protoPriv._requiredLevelAlignment,
levelOffsetWrite);
} // level loop
result = KTX_SUCCESS;
cleanup:
delete[] firstImages;
return result;
}
KTX_error_code
ktxTexture2_transcodeUastc(ktxTexture2* This,
alpha_content_e alphaContent,
ktxTexture2* prototype,
ktx_transcode_fmt_e outputFormat,
ktx_transcode_flags transcodeFlags)
{
assert(This->supercompressionScheme != KTX_SS_BASIS_LZ);
ktx_uint8_t* pXcodedData = prototype->pData;
ktx_uint32_t outputBlockByteLength
= prototype->_protected->_formatSize.blockSizeInBits / 8;
ktx_size_t xcodedDataLength
= prototype->dataSize / outputBlockByteLength;
DECLARE_PRIVATE(protoPriv, prototype);
ktxLevelIndexEntry* protoLevelIndex = protoPriv._levelIndex;
ktx_size_t levelOffsetWrite = 0;
basisu_lowlevel_uastc_transcoder uit;
// See comment on same declaration in transcodeEtc1s.
std::vector<basisu_transcoder_state> xcoderStates;
xcoderStates.resize(This->isVideo ? This->numFaces : 1);
for (ktx_int32_t level = This->numLevels - 1; level >= 0; level--)
{
ktx_uint32_t depth;
uint64_t writeOffset = levelOffsetWrite;
uint64_t writeOffsetBlocks = levelOffsetWrite / outputBlockByteLength;
ktx_size_t levelImageSizeIn, levelImageOffsetIn;
ktx_size_t levelImageSizeOut, levelSizeOut;
ktx_uint32_t levelImageCount;
uint32_t levelWidth = MAX(1, This->baseWidth >> level);
uint32_t levelHeight = MAX(1, This->baseHeight >> level);
// UASTC texel block dimensions
const uint32_t bw = 4, bh = 4;
uint32_t levelBlocksX = (levelWidth + (bw - 1)) / bw;
uint32_t levelBlocksY = (levelHeight + (bh - 1)) / bh;
uint32_t stateIndex = 0;
depth = MAX(1, This->baseDepth >> level);
levelImageCount = This->numLayers * This->numFaces * depth;
levelImageSizeIn = ktxTexture_calcImageSize(ktxTexture(This), level,
KTX_FORMAT_VERSION_TWO);
levelImageSizeOut = ktxTexture_calcImageSize(ktxTexture(prototype),
level,
KTX_FORMAT_VERSION_TWO);
levelImageOffsetIn = ktxTexture2_levelDataOffset(This, level);
levelSizeOut = 0;
bool status;
for (uint32_t image = 0; image < levelImageCount; image++) {
basisu_transcoder_state& xcoderState = xcoderStates[stateIndex];
// See comment before same lines in transcodeEtc1s.
if (++stateIndex == xcoderStates.size())
stateIndex = 0;
status = uit.transcode_image(
(transcoder_texture_format)outputFormat,
pXcodedData + writeOffset,
(uint32_t)(xcodedDataLength - writeOffsetBlocks),
This->pData,
(uint32_t)This->dataSize,
levelBlocksX,
levelBlocksY,
levelWidth,
levelHeight,
level,
(uint32_t)levelImageOffsetIn,
(uint32_t)levelImageSizeIn,
transcodeFlags,
alphaContent != eNone,
This->isVideo, // is_video
//imageDesc.imageFlags ^ cSliceDescFlagsFrameIsIFrame,
0, // output_row_pitch_in_blocks_or_pixels
&xcoderState, // pState
0, // output_rows_in_pixels,
-1, // channel0
-1 // channel1
);
if (!status)
return KTX_TRANSCODE_FAILED;
writeOffset += levelImageSizeOut;
levelSizeOut += levelImageSizeOut;
levelImageOffsetIn += levelImageSizeIn;
}
protoLevelIndex[level].byteOffset = levelOffsetWrite;
// writeOffset will be equal to total size of the images in the level.
protoLevelIndex[level].byteLength = levelSizeOut;
protoLevelIndex[level].uncompressedByteLength = levelSizeOut;
levelOffsetWrite += levelSizeOut;
}
// In case of transcoding to uncompressed.
levelOffsetWrite = _KTX_PADN(protoPriv._requiredLevelAlignment,
levelOffsetWrite);
return KTX_SUCCESS;
}

259
thirdparty/libktx/lib/checkheader.c vendored Normal file
View File

@ -0,0 +1,259 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* $Id: ee6f7be4d43390de78e1815ed158012c78ddeff1 $ */
/*
* Copyright 2010-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file checkheader.c
* @~English
*
* @brief Function to verify a KTX file header
*
* @author Mark Callow, HI Corporation
*/
/*
* Author: Georg Kolling, Imagination Technology with modifications
* by Mark Callow, HI Corporation.
*/
#include <assert.h>
#include <string.h>
#include "ktx.h"
#include "ktxint.h"
/**
* @internal
* @~English
* @brief Check a KTX file header.
*
* As well as checking that the header identifies a KTX file, the function
* sanity checks the values and returns information about the texture in a
* struct KTX_supplementary_info.
*
* @param pHeader pointer to the KTX header to check
* @param pSuppInfo pointer to a KTX_supplementary_info structure in which to
* return information about the texture.
*
* @author Georg Kolling, Imagination Technology
* @author Mark Callow, HI Corporation
*/
KTX_error_code ktxCheckHeader1_(KTX_header* pHeader,
KTX_supplemental_info* pSuppInfo)
{
ktx_uint8_t identifier_reference[12] = KTX_IDENTIFIER_REF;
ktx_uint32_t max_dim;
assert(pHeader != NULL && pSuppInfo != NULL);
/* Compare identifier, is this a KTX file? */
if (memcmp(pHeader->identifier, identifier_reference, 12) != 0)
{
return KTX_UNKNOWN_FILE_FORMAT;
}
if (pHeader->endianness == KTX_ENDIAN_REF_REV)
{
/* Convert endianness of pHeader fields. */
_ktxSwapEndian32(&pHeader->glType, 12);
if (pHeader->glTypeSize != 1 &&
pHeader->glTypeSize != 2 &&
pHeader->glTypeSize != 4)
{
/* Only 8-, 16-, and 32-bit types supported so far. */
return KTX_FILE_DATA_ERROR;
}
}
else if (pHeader->endianness != KTX_ENDIAN_REF)
{
return KTX_FILE_DATA_ERROR;
}
/* Check glType and glFormat */
pSuppInfo->compressed = 0;
if (pHeader->glType == 0 || pHeader->glFormat == 0)
{
if (pHeader->glType + pHeader->glFormat != 0)
{
/* either both or none of glType, glFormat must be zero */
return KTX_FILE_DATA_ERROR;
}
pSuppInfo->compressed = 1;
}
if (pHeader->glFormat == pHeader->glInternalformat) {
// glInternalFormat is either unsized (which is no longer and should
// never have been supported by libktx) or glFormat is sized.
return KTX_FILE_DATA_ERROR;
}
/* Check texture dimensions. KTX files can store 8 types of textures:
1D, 2D, 3D, cube, and array variants of these. There is currently
no GL extension for 3D array textures. */
if ((pHeader->pixelWidth == 0) ||
(pHeader->pixelDepth > 0 && pHeader->pixelHeight == 0))
{
/* texture must have width */
/* texture must have height if it has depth */
return KTX_FILE_DATA_ERROR;
}
if (pHeader->pixelDepth > 0)
{
if (pHeader->numberOfArrayElements > 0)
{
/* No 3D array textures yet. */
return KTX_UNSUPPORTED_TEXTURE_TYPE;
}
pSuppInfo->textureDimension = 3;
}
else if (pHeader->pixelHeight > 0)
{
pSuppInfo->textureDimension = 2;
}
else
{
pSuppInfo->textureDimension = 1;
}
if (pHeader->numberOfFaces == 6)
{
if (pSuppInfo->textureDimension != 2)
{
/* cube map needs 2D faces */
return KTX_FILE_DATA_ERROR;
}
}
else if (pHeader->numberOfFaces != 1)
{
/* numberOfFaces must be either 1 or 6 */
return KTX_FILE_DATA_ERROR;
}
/* Check number of mipmap levels */
if (pHeader->numberOfMipLevels == 0)
{
pSuppInfo->generateMipmaps = 1;
pHeader->numberOfMipLevels = 1;
}
else
{
pSuppInfo->generateMipmaps = 0;
}
/* This test works for arrays too because height or depth will be 0. */
max_dim = MAX(MAX(pHeader->pixelWidth, pHeader->pixelHeight), pHeader->pixelDepth);
if (max_dim < ((ktx_uint32_t)1 << (pHeader->numberOfMipLevels - 1)))
{
/* Can't have more mip levels than 1 + log2(max(width, height, depth)) */
return KTX_FILE_DATA_ERROR;
}
return KTX_SUCCESS;
}
/**
* @internal
* @~English
* @brief Check a KTX2 file header.
*
* As well as checking that the header identifies a KTX 2 file, the function
* sanity checks the values and returns information about the texture in a
* struct KTX_supplementary_info.
*
* @param pHeader pointer to the KTX header to check
* @param pSuppInfo pointer to a KTX_supplementary_info structure in which to
* return information about the texture.
*
* @author Mark Callow, HI Corporation
*/
KTX_error_code ktxCheckHeader2_(KTX_header2* pHeader,
KTX_supplemental_info* pSuppInfo)
{
// supp info is compressed, generateMipmaps and num dimensions. Don't need
// compressed as formatSize gives us that. I think the other 2 aren't needed.
ktx_uint8_t identifier_reference[12] = KTX2_IDENTIFIER_REF;
assert(pHeader != NULL && pSuppInfo != NULL);
ktx_uint32_t max_dim;
/* Compare identifier, is this a KTX file? */
if (memcmp(pHeader->identifier, identifier_reference, 12) != 0)
{
return KTX_UNKNOWN_FILE_FORMAT;
}
/* Check texture dimensions. KTX files can store 8 types of textures:
1D, 2D, 3D, cube, and array variants of these. There is currently
no extension for 3D array textures in any 3D API. */
if ((pHeader->pixelWidth == 0) ||
(pHeader->pixelDepth > 0 && pHeader->pixelHeight == 0))
{
/* texture must have width */
/* texture must have height if it has depth */
return KTX_FILE_DATA_ERROR;
}
if (pHeader->pixelDepth > 0)
{
if (pHeader->layerCount > 0)
{
/* No 3D array textures yet. */
return KTX_UNSUPPORTED_TEXTURE_TYPE;
}
pSuppInfo->textureDimension = 3;
}
else if (pHeader->pixelHeight > 0)
{
pSuppInfo->textureDimension = 2;
}
else
{
pSuppInfo->textureDimension = 1;
}
if (pHeader->faceCount == 6)
{
if (pSuppInfo->textureDimension != 2)
{
/* cube map needs 2D faces */
return KTX_FILE_DATA_ERROR;
}
}
else if (pHeader->faceCount != 1)
{
/* numberOfFaces must be either 1 or 6 */
return KTX_FILE_DATA_ERROR;
}
// Check number of mipmap levels
if (pHeader->levelCount == 0)
{
pSuppInfo->generateMipmaps = 1;
pHeader->levelCount = 1;
}
else
{
pSuppInfo->generateMipmaps = 0;
}
// This test works for arrays too because height or depth will be 0.
max_dim = MAX(MAX(pHeader->pixelWidth, pHeader->pixelHeight), pHeader->pixelDepth);
if (max_dim < ((ktx_uint32_t)1 << (pHeader->levelCount - 1)))
{
// Can't have more mip levels than 1 + log2(max(width, height, depth))
return KTX_FILE_DATA_ERROR;
}
return KTX_SUCCESS;
}

View File

@ -0,0 +1,619 @@
/* The Khronos Data Format Specification (version 1.3) */
/*
** Copyright 2015-2020 The Khronos Group Inc.
** SPDX-License-Identifier: Apache-2.0
*/
/* This header defines a structure that can describe the layout of image
formats in memory. This means that the data format is transparent to
the application, and the expectation is that this should be used when
the layout is defined external to the API. Many Khronos APIs deliberately
keep the internal layout of images opaque, to allow proprietary layouts
and optimisations. This structure is not appropriate for describing
opaque layouts. */
/* We stick to standard C89 constructs for simplicity and portability. */
#ifndef _KHR_DATA_FORMAT_H_
#define _KHR_DATA_FORMAT_H_
/* Accessors */
typedef enum _khr_word_e {
KHR_DF_WORD_VENDORID = 0U,
KHR_DF_WORD_DESCRIPTORTYPE = 0U,
KHR_DF_WORD_VERSIONNUMBER = 1U,
KHR_DF_WORD_DESCRIPTORBLOCKSIZE = 1U,
KHR_DF_WORD_MODEL = 2U,
KHR_DF_WORD_PRIMARIES = 2U,
KHR_DF_WORD_TRANSFER = 2U,
KHR_DF_WORD_FLAGS = 2U,
KHR_DF_WORD_TEXELBLOCKDIMENSION0 = 3U,
KHR_DF_WORD_TEXELBLOCKDIMENSION1 = 3U,
KHR_DF_WORD_TEXELBLOCKDIMENSION2 = 3U,
KHR_DF_WORD_TEXELBLOCKDIMENSION3 = 3U,
KHR_DF_WORD_BYTESPLANE0 = 4U,
KHR_DF_WORD_BYTESPLANE1 = 4U,
KHR_DF_WORD_BYTESPLANE2 = 4U,
KHR_DF_WORD_BYTESPLANE3 = 4U,
KHR_DF_WORD_BYTESPLANE4 = 5U,
KHR_DF_WORD_BYTESPLANE5 = 5U,
KHR_DF_WORD_BYTESPLANE6 = 5U,
KHR_DF_WORD_BYTESPLANE7 = 5U,
KHR_DF_WORD_SAMPLESTART = 6U,
KHR_DF_WORD_SAMPLEWORDS = 4U
} khr_df_word_e;
typedef enum _khr_df_shift_e {
KHR_DF_SHIFT_VENDORID = 0U,
KHR_DF_SHIFT_DESCRIPTORTYPE = 17U,
KHR_DF_SHIFT_VERSIONNUMBER = 0U,
KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE = 16U,
KHR_DF_SHIFT_MODEL = 0U,
KHR_DF_SHIFT_PRIMARIES = 8U,
KHR_DF_SHIFT_TRANSFER = 16U,
KHR_DF_SHIFT_FLAGS = 24U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION0 = 0U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION1 = 8U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION2 = 16U,
KHR_DF_SHIFT_TEXELBLOCKDIMENSION3 = 24U,
KHR_DF_SHIFT_BYTESPLANE0 = 0U,
KHR_DF_SHIFT_BYTESPLANE1 = 8U,
KHR_DF_SHIFT_BYTESPLANE2 = 16U,
KHR_DF_SHIFT_BYTESPLANE3 = 24U,
KHR_DF_SHIFT_BYTESPLANE4 = 0U,
KHR_DF_SHIFT_BYTESPLANE5 = 8U,
KHR_DF_SHIFT_BYTESPLANE6 = 16U,
KHR_DF_SHIFT_BYTESPLANE7 = 24U
} khr_df_shift_e;
typedef enum _khr_df_mask_e {
KHR_DF_MASK_VENDORID = 0x1FFFFU,
KHR_DF_MASK_DESCRIPTORTYPE = 0x7FFFU,
KHR_DF_MASK_VERSIONNUMBER = 0xFFFFU,
KHR_DF_MASK_DESCRIPTORBLOCKSIZE = 0xFFFFU,
KHR_DF_MASK_MODEL = 0xFFU,
KHR_DF_MASK_PRIMARIES = 0xFFU,
KHR_DF_MASK_TRANSFER = 0xFFU,
KHR_DF_MASK_FLAGS = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION0 = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION1 = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION2 = 0xFFU,
KHR_DF_MASK_TEXELBLOCKDIMENSION3 = 0xFFU,
KHR_DF_MASK_BYTESPLANE0 = 0xFFU,
KHR_DF_MASK_BYTESPLANE1 = 0xFFU,
KHR_DF_MASK_BYTESPLANE2 = 0xFFU,
KHR_DF_MASK_BYTESPLANE3 = 0xFFU,
KHR_DF_MASK_BYTESPLANE4 = 0xFFU,
KHR_DF_MASK_BYTESPLANE5 = 0xFFU,
KHR_DF_MASK_BYTESPLANE6 = 0xFFU,
KHR_DF_MASK_BYTESPLANE7 = 0xFFU
} khr_df_mask_e;
/* Helper macro:
Extract field X from basic descriptor block BDB */
#define KHR_DFDVAL(BDB, X) \
(((BDB)[KHR_DF_WORD_ ## X] >> (KHR_DF_SHIFT_ ## X)) \
& (KHR_DF_MASK_ ## X))
/* Helper macro:
Set field X of basic descriptor block BDB */
#define KHR_DFDSETVAL(BDB, X, val) \
((BDB)[KHR_DF_WORD_ ## X] = \
((BDB)[KHR_DF_WORD_ ## X] & \
~((KHR_DF_MASK_ ## X) << (KHR_DF_SHIFT_ ## X))) | \
(((val) & (KHR_DF_MASK_ ## X)) << (KHR_DF_SHIFT_ ## X)))
/* Offsets relative to the start of a sample */
typedef enum _khr_df_sampleword_e {
KHR_DF_SAMPLEWORD_BITOFFSET = 0U,
KHR_DF_SAMPLEWORD_BITLENGTH = 0U,
KHR_DF_SAMPLEWORD_CHANNELID = 0U,
KHR_DF_SAMPLEWORD_QUALIFIERS = 0U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION0 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION1 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION2 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION3 = 1U,
KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL = 1U,
KHR_DF_SAMPLEWORD_SAMPLELOWER = 2U,
KHR_DF_SAMPLEWORD_SAMPLEUPPER = 3U
} khr_df_sampleword_e;
typedef enum _khr_df_sampleshift_e {
KHR_DF_SAMPLESHIFT_BITOFFSET = 0U,
KHR_DF_SAMPLESHIFT_BITLENGTH = 16U,
KHR_DF_SAMPLESHIFT_CHANNELID = 24U,
/* N.B. Qualifiers are defined as an offset into a byte */
KHR_DF_SAMPLESHIFT_QUALIFIERS = 24U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION0 = 0U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION1 = 8U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION2 = 16U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION3 = 24U,
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION_ALL = 0U,
KHR_DF_SAMPLESHIFT_SAMPLELOWER = 0U,
KHR_DF_SAMPLESHIFT_SAMPLEUPPER = 0U
} khr_df_sampleshift_e;
typedef enum _khr_df_samplemask_e {
KHR_DF_SAMPLEMASK_BITOFFSET = 0xFFFFU,
KHR_DF_SAMPLEMASK_BITLENGTH = 0xFF,
KHR_DF_SAMPLEMASK_CHANNELID = 0xF,
/* N.B. Qualifiers are defined as an offset into a byte */
KHR_DF_SAMPLEMASK_QUALIFIERS = 0xF0,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION0 = 0xFF,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION1 = 0xFF,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION2 = 0xFF,
KHR_DF_SAMPLEMASK_SAMPLEPOSITION3 = 0xFF,
/* ISO C restricts enum values to range of int hence the
cast. We do it verbosely instead of using -1 to ensure
it is a 32-bit value even if int is 64 bits. */
KHR_DF_SAMPLEMASK_SAMPLEPOSITION_ALL = (int) 0xFFFFFFFFU,
KHR_DF_SAMPLEMASK_SAMPLELOWER = (int) 0xFFFFFFFFU,
KHR_DF_SAMPLEMASK_SAMPLEUPPER = (int) 0xFFFFFFFFU
} khr_df_samplemask_e;
/* Helper macro:
Extract field X of sample S from basic descriptor block BDB */
#define KHR_DFDSVAL(BDB, S, X) \
(((BDB)[KHR_DF_WORD_SAMPLESTART + \
((S) * KHR_DF_WORD_SAMPLEWORDS) + \
KHR_DF_SAMPLEWORD_ ## X] >> (KHR_DF_SAMPLESHIFT_ ## X)) \
& (KHR_DF_SAMPLEMASK_ ## X))
/* Helper macro:
Set field X of sample S of basic descriptor block BDB */
#define KHR_DFDSETSVAL(BDB, S, X, val) \
((BDB)[KHR_DF_WORD_SAMPLESTART + \
((S) * KHR_DF_WORD_SAMPLEWORDS) + \
KHR_DF_SAMPLEWORD_ ## X] = \
((BDB)[KHR_DF_WORD_SAMPLESTART + \
((S) * KHR_DF_WORD_SAMPLEWORDS) + \
KHR_DF_SAMPLEWORD_ ## X] & \
~((uint32_t)(KHR_DF_SAMPLEMASK_ ## X) << (KHR_DF_SAMPLESHIFT_ ## X))) | \
(((val) & (uint32_t)(KHR_DF_SAMPLEMASK_ ## X)) << (KHR_DF_SAMPLESHIFT_ ## X)))
/* Helper macro:
Number of samples in basic descriptor block BDB */
#define KHR_DFDSAMPLECOUNT(BDB) \
(((KHR_DFDVAL(BDB, DESCRIPTORBLOCKSIZE) >> 2) - \
KHR_DF_WORD_SAMPLESTART) \
/ KHR_DF_WORD_SAMPLEWORDS)
/* Helper macro:
Size in words of basic descriptor block for S samples */
#define KHR_DFDSIZEWORDS(S) \
(KHR_DF_WORD_SAMPLESTART + \
(S) * KHR_DF_WORD_SAMPLEWORDS)
/* Vendor ids */
typedef enum _khr_df_vendorid_e {
/* Standard Khronos descriptor */
KHR_DF_VENDORID_KHRONOS = 0U,
KHR_DF_VENDORID_MAX = 0x1FFFFU
} khr_df_vendorid_e;
/* Descriptor types */
typedef enum _khr_df_khr_descriptortype_e {
/* Default Khronos basic descriptor block */
KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT = 0U,
/* Extension descriptor block for additional planes */
KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_PLANES = 0x6001U,
/* Extension descriptor block for additional dimensions */
KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS = 0x6002U,
/* Bit indicates modifying requires understanding this extension */
KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_WRITE_BIT = 0x2000U,
/* Bit indicates processing requires understanding this extension */
KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_DECODE_BIT = 0x4000U,
KHR_DF_KHR_DESCRIPTORTYPE_MAX = 0x7FFFU
} khr_df_khr_descriptortype_e;
/* Descriptor block version */
typedef enum _khr_df_versionnumber_e {
/* Standard Khronos descriptor */
KHR_DF_VERSIONNUMBER_1_0 = 0U, /* Version 1.0 of the specification */
KHR_DF_VERSIONNUMBER_1_1 = 0U, /* Version 1.1 did not bump the version number */
KHR_DF_VERSIONNUMBER_1_2 = 1U, /* Version 1.2 increased the version number */
KHR_DF_VERSIONNUMBER_1_3 = 2U, /* Version 1.3 increased the version number */
KHR_DF_VERSIONNUMBER_LATEST = KHR_DF_VERSIONNUMBER_1_3,
KHR_DF_VERSIONNUMBER_MAX = 0xFFFFU
} khr_df_versionnumber_e;
/* Model in which the color coordinate space is defined.
There is no requirement that a color format use all the
channel types that are defined in the color model. */
typedef enum _khr_df_model_e {
/* No interpretation of color channels defined */
KHR_DF_MODEL_UNSPECIFIED = 0U,
/* Color primaries (red, green, blue) + alpha, depth and stencil */
KHR_DF_MODEL_RGBSDA = 1U,
/* Color differences (Y', Cb, Cr) + alpha, depth and stencil */
KHR_DF_MODEL_YUVSDA = 2U,
/* Color differences (Y', I, Q) + alpha, depth and stencil */
KHR_DF_MODEL_YIQSDA = 3U,
/* Perceptual color (CIE L*a*b*) + alpha, depth and stencil */
KHR_DF_MODEL_LABSDA = 4U,
/* Subtractive colors (cyan, magenta, yellow, black) + alpha */
KHR_DF_MODEL_CMYKA = 5U,
/* Non-color coordinate data (X, Y, Z, W) */
KHR_DF_MODEL_XYZW = 6U,
/* Hue, saturation, value, hue angle on color circle, plus alpha */
KHR_DF_MODEL_HSVA_ANG = 7U,
/* Hue, saturation, lightness, hue angle on color circle, plus alpha */
KHR_DF_MODEL_HSLA_ANG = 8U,
/* Hue, saturation, value, hue on color hexagon, plus alpha */
KHR_DF_MODEL_HSVA_HEX = 9U,
/* Hue, saturation, lightness, hue on color hexagon, plus alpha */
KHR_DF_MODEL_HSLA_HEX = 10U,
/* Lightweight approximate color difference (luma, orange, green) */
KHR_DF_MODEL_YCGCOA = 11U,
/* ITU BT.2020 constant luminance YcCbcCrc */
KHR_DF_MODEL_YCCBCCRC = 12U,
/* ITU BT.2100 constant intensity ICtCp */
KHR_DF_MODEL_ICTCP = 13U,
/* CIE 1931 XYZ color coordinates (X, Y, Z) */
KHR_DF_MODEL_CIEXYZ = 14U,
/* CIE 1931 xyY color coordinates (X, Y, Y) */
KHR_DF_MODEL_CIEXYY = 15U,
/* Compressed formats start at 128. */
/* These compressed formats should generally have a single sample,
sited at the 0,0 position of the texel block. Where multiple
channels are used to distinguish formats, these should be cosited. */
/* Direct3D (and S3) compressed formats */
/* Note that premultiplied status is recorded separately */
/* DXT1 "channels" are RGB (0), Alpha (1) */
/* DXT1/BC1 with one channel is opaque */
/* DXT1/BC1 with a cosited alpha sample is transparent */
KHR_DF_MODEL_DXT1A = 128U,
KHR_DF_MODEL_BC1A = 128U,
/* DXT2/DXT3/BC2, with explicit 4-bit alpha */
KHR_DF_MODEL_DXT2 = 129U,
KHR_DF_MODEL_DXT3 = 129U,
KHR_DF_MODEL_BC2 = 129U,
/* DXT4/DXT5/BC3, with interpolated alpha */
KHR_DF_MODEL_DXT4 = 130U,
KHR_DF_MODEL_DXT5 = 130U,
KHR_DF_MODEL_BC3 = 130U,
/* BC4 - single channel interpolated 8-bit data */
/* (The UNORM/SNORM variation is recorded in the channel data) */
KHR_DF_MODEL_BC4 = 131U,
/* BC5 - two channel interpolated 8-bit data */
/* (The UNORM/SNORM variation is recorded in the channel data) */
KHR_DF_MODEL_BC5 = 132U,
/* BC6H - DX11 format for 16-bit float channels */
KHR_DF_MODEL_BC6H = 133U,
/* BC7 - DX11 format */
KHR_DF_MODEL_BC7 = 134U,
/* Gap left for future desktop expansion */
/* Mobile compressed formats follow */
/* A format of ETC1 indicates that the format shall be decodable
by an ETC1-compliant decoder and not rely on ETC2 features */
KHR_DF_MODEL_ETC1 = 160U,
/* A format of ETC2 is permitted to use ETC2 encodings on top of
the baseline ETC1 specification */
/* The ETC2 format has channels "red", "green", "RGB" and "alpha",
which should be cosited samples */
/* Punch-through alpha can be distinguished from full alpha by
the plane size in bytes required for the texel block */
KHR_DF_MODEL_ETC2 = 161U,
/* Adaptive Scalable Texture Compression */
/* ASTC HDR vs LDR is determined by the float flag in the channel */
/* ASTC block size can be distinguished by texel block size */
KHR_DF_MODEL_ASTC = 162U,
/* ETC1S is a simplified subset of ETC1 */
KHR_DF_MODEL_ETC1S = 163U,
/* PowerVR Texture Compression */
KHR_DF_MODEL_PVRTC = 164U,
KHR_DF_MODEL_PVRTC2 = 165U,
KHR_DF_MODEL_UASTC = 166U,
/* Proprietary formats (ATITC, etc.) should follow */
KHR_DF_MODEL_MAX = 0xFFU
} khr_df_model_e;
/* Definition of channel names for each color model */
typedef enum _khr_df_model_channels_e {
/* Unspecified format with nominal channel numbering */
KHR_DF_CHANNEL_UNSPECIFIED_0 = 0U,
KHR_DF_CHANNEL_UNSPECIFIED_1 = 1U,
KHR_DF_CHANNEL_UNSPECIFIED_2 = 2U,
KHR_DF_CHANNEL_UNSPECIFIED_3 = 3U,
KHR_DF_CHANNEL_UNSPECIFIED_4 = 4U,
KHR_DF_CHANNEL_UNSPECIFIED_5 = 5U,
KHR_DF_CHANNEL_UNSPECIFIED_6 = 6U,
KHR_DF_CHANNEL_UNSPECIFIED_7 = 7U,
KHR_DF_CHANNEL_UNSPECIFIED_8 = 8U,
KHR_DF_CHANNEL_UNSPECIFIED_9 = 9U,
KHR_DF_CHANNEL_UNSPECIFIED_10 = 10U,
KHR_DF_CHANNEL_UNSPECIFIED_11 = 11U,
KHR_DF_CHANNEL_UNSPECIFIED_12 = 12U,
KHR_DF_CHANNEL_UNSPECIFIED_13 = 13U,
KHR_DF_CHANNEL_UNSPECIFIED_14 = 14U,
KHR_DF_CHANNEL_UNSPECIFIED_15 = 15U,
/* MODEL_RGBSDA - red, green, blue, stencil, depth, alpha */
KHR_DF_CHANNEL_RGBSDA_RED = 0U,
KHR_DF_CHANNEL_RGBSDA_R = 0U,
KHR_DF_CHANNEL_RGBSDA_GREEN = 1U,
KHR_DF_CHANNEL_RGBSDA_G = 1U,
KHR_DF_CHANNEL_RGBSDA_BLUE = 2U,
KHR_DF_CHANNEL_RGBSDA_B = 2U,
KHR_DF_CHANNEL_RGBSDA_STENCIL = 13U,
KHR_DF_CHANNEL_RGBSDA_S = 13U,
KHR_DF_CHANNEL_RGBSDA_DEPTH = 14U,
KHR_DF_CHANNEL_RGBSDA_D = 14U,
KHR_DF_CHANNEL_RGBSDA_ALPHA = 15U,
KHR_DF_CHANNEL_RGBSDA_A = 15U,
/* MODEL_YUVSDA - luma, Cb, Cr, stencil, depth, alpha */
KHR_DF_CHANNEL_YUVSDA_Y = 0U,
KHR_DF_CHANNEL_YUVSDA_CB = 1U,
KHR_DF_CHANNEL_YUVSDA_U = 1U,
KHR_DF_CHANNEL_YUVSDA_CR = 2U,
KHR_DF_CHANNEL_YUVSDA_V = 2U,
KHR_DF_CHANNEL_YUVSDA_STENCIL = 13U,
KHR_DF_CHANNEL_YUVSDA_S = 13U,
KHR_DF_CHANNEL_YUVSDA_DEPTH = 14U,
KHR_DF_CHANNEL_YUVSDA_D = 14U,
KHR_DF_CHANNEL_YUVSDA_ALPHA = 15U,
KHR_DF_CHANNEL_YUVSDA_A = 15U,
/* MODEL_YIQSDA - luma, in-phase, quadrature, stencil, depth, alpha */
KHR_DF_CHANNEL_YIQSDA_Y = 0U,
KHR_DF_CHANNEL_YIQSDA_I = 1U,
KHR_DF_CHANNEL_YIQSDA_Q = 2U,
KHR_DF_CHANNEL_YIQSDA_STENCIL = 13U,
KHR_DF_CHANNEL_YIQSDA_S = 13U,
KHR_DF_CHANNEL_YIQSDA_DEPTH = 14U,
KHR_DF_CHANNEL_YIQSDA_D = 14U,
KHR_DF_CHANNEL_YIQSDA_ALPHA = 15U,
KHR_DF_CHANNEL_YIQSDA_A = 15U,
/* MODEL_LABSDA - CIELAB/L*a*b* luma, red-green, blue-yellow, stencil, depth, alpha */
KHR_DF_CHANNEL_LABSDA_L = 0U,
KHR_DF_CHANNEL_LABSDA_A = 1U,
KHR_DF_CHANNEL_LABSDA_B = 2U,
KHR_DF_CHANNEL_LABSDA_STENCIL = 13U,
KHR_DF_CHANNEL_LABSDA_S = 13U,
KHR_DF_CHANNEL_LABSDA_DEPTH = 14U,
KHR_DF_CHANNEL_LABSDA_D = 14U,
KHR_DF_CHANNEL_LABSDA_ALPHA = 15U,
/* NOTE: KHR_DF_CHANNEL_LABSDA_A is not a synonym for alpha! */
/* MODEL_CMYKA - cyan, magenta, yellow, key/blacK, alpha */
KHR_DF_CHANNEL_CMYKSDA_CYAN = 0U,
KHR_DF_CHANNEL_CMYKSDA_C = 0U,
KHR_DF_CHANNEL_CMYKSDA_MAGENTA = 1U,
KHR_DF_CHANNEL_CMYKSDA_M = 1U,
KHR_DF_CHANNEL_CMYKSDA_YELLOW = 2U,
KHR_DF_CHANNEL_CMYKSDA_Y = 2U,
KHR_DF_CHANNEL_CMYKSDA_KEY = 3U,
KHR_DF_CHANNEL_CMYKSDA_BLACK = 3U,
KHR_DF_CHANNEL_CMYKSDA_K = 3U,
KHR_DF_CHANNEL_CMYKSDA_ALPHA = 15U,
KHR_DF_CHANNEL_CMYKSDA_A = 15U,
/* MODEL_XYZW - coordinates x, y, z, w */
KHR_DF_CHANNEL_XYZW_X = 0U,
KHR_DF_CHANNEL_XYZW_Y = 1U,
KHR_DF_CHANNEL_XYZW_Z = 2U,
KHR_DF_CHANNEL_XYZW_W = 3U,
/* MODEL_HSVA_ANG - value (luma), saturation, hue, alpha, angular projection, conical space */
KHR_DF_CHANNEL_HSVA_ANG_VALUE = 0U,
KHR_DF_CHANNEL_HSVA_ANG_V = 0U,
KHR_DF_CHANNEL_HSVA_ANG_SATURATION = 1U,
KHR_DF_CHANNEL_HSVA_ANG_S = 1U,
KHR_DF_CHANNEL_HSVA_ANG_HUE = 2U,
KHR_DF_CHANNEL_HSVA_ANG_H = 2U,
KHR_DF_CHANNEL_HSVA_ANG_ALPHA = 15U,
KHR_DF_CHANNEL_HSVA_ANG_A = 15U,
/* MODEL_HSLA_ANG - lightness (luma), saturation, hue, alpha, angular projection, double conical space */
KHR_DF_CHANNEL_HSLA_ANG_LIGHTNESS = 0U,
KHR_DF_CHANNEL_HSLA_ANG_L = 0U,
KHR_DF_CHANNEL_HSLA_ANG_SATURATION = 1U,
KHR_DF_CHANNEL_HSLA_ANG_S = 1U,
KHR_DF_CHANNEL_HSLA_ANG_HUE = 2U,
KHR_DF_CHANNEL_HSLA_ANG_H = 2U,
KHR_DF_CHANNEL_HSLA_ANG_ALPHA = 15U,
KHR_DF_CHANNEL_HSLA_ANG_A = 15U,
/* MODEL_HSVA_HEX - value (luma), saturation, hue, alpha, hexagonal projection, conical space */
KHR_DF_CHANNEL_HSVA_HEX_VALUE = 0U,
KHR_DF_CHANNEL_HSVA_HEX_V = 0U,
KHR_DF_CHANNEL_HSVA_HEX_SATURATION = 1U,
KHR_DF_CHANNEL_HSVA_HEX_S = 1U,
KHR_DF_CHANNEL_HSVA_HEX_HUE = 2U,
KHR_DF_CHANNEL_HSVA_HEX_H = 2U,
KHR_DF_CHANNEL_HSVA_HEX_ALPHA = 15U,
KHR_DF_CHANNEL_HSVA_HEX_A = 15U,
/* MODEL_HSLA_HEX - lightness (luma), saturation, hue, alpha, hexagonal projection, double conical space */
KHR_DF_CHANNEL_HSLA_HEX_LIGHTNESS = 0U,
KHR_DF_CHANNEL_HSLA_HEX_L = 0U,
KHR_DF_CHANNEL_HSLA_HEX_SATURATION = 1U,
KHR_DF_CHANNEL_HSLA_HEX_S = 1U,
KHR_DF_CHANNEL_HSLA_HEX_HUE = 2U,
KHR_DF_CHANNEL_HSLA_HEX_H = 2U,
KHR_DF_CHANNEL_HSLA_HEX_ALPHA = 15U,
KHR_DF_CHANNEL_HSLA_HEX_A = 15U,
/* MODEL_YCGCOA - luma, green delta, orange delta, alpha */
KHR_DF_CHANNEL_YCGCOA_Y = 0U,
KHR_DF_CHANNEL_YCGCOA_CG = 1U,
KHR_DF_CHANNEL_YCGCOA_CO = 2U,
KHR_DF_CHANNEL_YCGCOA_ALPHA = 15U,
KHR_DF_CHANNEL_YCGCOA_A = 15U,
/* MODEL_CIEXYZ - CIE 1931 X, Y, Z */
KHR_DF_CHANNEL_CIEXYZ_X = 0U,
KHR_DF_CHANNEL_CIEXYZ_Y = 1U,
KHR_DF_CHANNEL_CIEXYZ_Z = 2U,
/* MODEL_CIEXYY - CIE 1931 x, y, Y */
KHR_DF_CHANNEL_CIEXYY_X = 0U,
KHR_DF_CHANNEL_CIEXYY_YCHROMA = 1U,
KHR_DF_CHANNEL_CIEXYY_YLUMA = 2U,
/* Compressed formats */
/* MODEL_DXT1A/MODEL_BC1A */
KHR_DF_CHANNEL_DXT1A_COLOR = 0U,
KHR_DF_CHANNEL_BC1A_COLOR = 0U,
KHR_DF_CHANNEL_DXT1A_ALPHAPRESENT = 1U,
KHR_DF_CHANNEL_DXT1A_ALPHA = 1U,
KHR_DF_CHANNEL_BC1A_ALPHAPRESENT = 1U,
KHR_DF_CHANNEL_BC1A_ALPHA = 1U,
/* MODEL_DXT2/3/MODEL_BC2 */
KHR_DF_CHANNEL_DXT2_COLOR = 0U,
KHR_DF_CHANNEL_DXT3_COLOR = 0U,
KHR_DF_CHANNEL_BC2_COLOR = 0U,
KHR_DF_CHANNEL_DXT2_ALPHA = 15U,
KHR_DF_CHANNEL_DXT3_ALPHA = 15U,
KHR_DF_CHANNEL_BC2_ALPHA = 15U,
/* MODEL_DXT4/5/MODEL_BC3 */
KHR_DF_CHANNEL_DXT4_COLOR = 0U,
KHR_DF_CHANNEL_DXT5_COLOR = 0U,
KHR_DF_CHANNEL_BC3_COLOR = 0U,
KHR_DF_CHANNEL_DXT4_ALPHA = 15U,
KHR_DF_CHANNEL_DXT5_ALPHA = 15U,
KHR_DF_CHANNEL_BC3_ALPHA = 15U,
/* MODEL_BC4 */
KHR_DF_CHANNEL_BC4_DATA = 0U,
/* MODEL_BC5 */
KHR_DF_CHANNEL_BC5_RED = 0U,
KHR_DF_CHANNEL_BC5_R = 0U,
KHR_DF_CHANNEL_BC5_GREEN = 1U,
KHR_DF_CHANNEL_BC5_G = 1U,
/* MODEL_BC6H */
KHR_DF_CHANNEL_BC6H_COLOR = 0U,
KHR_DF_CHANNEL_BC6H_DATA = 0U,
/* MODEL_BC7 */
KHR_DF_CHANNEL_BC7_DATA = 0U,
KHR_DF_CHANNEL_BC7_COLOR = 0U,
/* MODEL_ETC1 */
KHR_DF_CHANNEL_ETC1_DATA = 0U,
KHR_DF_CHANNEL_ETC1_COLOR = 0U,
/* MODEL_ETC2 */
KHR_DF_CHANNEL_ETC2_RED = 0U,
KHR_DF_CHANNEL_ETC2_R = 0U,
KHR_DF_CHANNEL_ETC2_GREEN = 1U,
KHR_DF_CHANNEL_ETC2_G = 1U,
KHR_DF_CHANNEL_ETC2_COLOR = 2U,
KHR_DF_CHANNEL_ETC2_ALPHA = 15U,
KHR_DF_CHANNEL_ETC2_A = 15U,
/* MODEL_ASTC */
KHR_DF_CHANNEL_ASTC_DATA = 0U,
/* MODEL_ETC1S */
KHR_DF_CHANNEL_ETC1S_RGB = 0U,
KHR_DF_CHANNEL_ETC1S_RRR = 3U,
KHR_DF_CHANNEL_ETC1S_GGG = 4U,
KHR_DF_CHANNEL_ETC1S_AAA = 15U,
/* MODEL_PVRTC */
KHR_DF_CHANNEL_PVRTC_DATA = 0U,
KHR_DF_CHANNEL_PVRTC_COLOR = 0U,
/* MODEL_PVRTC2 */
KHR_DF_CHANNEL_PVRTC2_DATA = 0U,
KHR_DF_CHANNEL_PVRTC2_COLOR = 0U,
/* MODEL UASTC */
KHR_DF_CHANNEL_UASTC_DATA = 0U,
KHR_DF_CHANNEL_UASTC_RGB = 0U,
KHR_DF_CHANNEL_UASTC_RGBA = 3U,
KHR_DF_CHANNEL_UASTC_RRR = 4U,
KHR_DF_CHANNEL_UASTC_RRRG = 5U,
KHR_DF_CHANNEL_UASTC_RG = 6U,
/* Common channel names shared by multiple formats */
KHR_DF_CHANNEL_COMMON_LUMA = 0U,
KHR_DF_CHANNEL_COMMON_L = 0U,
KHR_DF_CHANNEL_COMMON_STENCIL = 13U,
KHR_DF_CHANNEL_COMMON_S = 13U,
KHR_DF_CHANNEL_COMMON_DEPTH = 14U,
KHR_DF_CHANNEL_COMMON_D = 14U,
KHR_DF_CHANNEL_COMMON_ALPHA = 15U,
KHR_DF_CHANNEL_COMMON_A = 15U
} khr_df_model_channels_e;
/* Definition of the primary colors in color coordinates.
This is implicitly responsible for defining the conversion
between RGB an YUV color spaces.
LAB and related absolute color models should use
KHR_DF_PRIMARIES_CIEXYZ. */
typedef enum _khr_df_primaries_e {
/* No color primaries defined */
KHR_DF_PRIMARIES_UNSPECIFIED = 0U,
/* Color primaries of ITU-R BT.709 and sRGB */
KHR_DF_PRIMARIES_BT709 = 1U,
/* Synonym for KHR_DF_PRIMARIES_BT709 */
KHR_DF_PRIMARIES_SRGB = 1U,
/* Color primaries of ITU-R BT.601 (625-line EBU variant) */
KHR_DF_PRIMARIES_BT601_EBU = 2U,
/* Color primaries of ITU-R BT.601 (525-line SMPTE C variant) */
KHR_DF_PRIMARIES_BT601_SMPTE = 3U,
/* Color primaries of ITU-R BT.2020 */
KHR_DF_PRIMARIES_BT2020 = 4U,
/* CIE theoretical color coordinate space */
KHR_DF_PRIMARIES_CIEXYZ = 5U,
/* Academy Color Encoding System primaries */
KHR_DF_PRIMARIES_ACES = 6U,
/* Color primaries of ACEScc */
KHR_DF_PRIMARIES_ACESCC = 7U,
/* Legacy NTSC 1953 primaries */
KHR_DF_PRIMARIES_NTSC1953 = 8U,
/* Legacy PAL 525-line primaries */
KHR_DF_PRIMARIES_PAL525 = 9U,
/* Color primaries of Display P3 */
KHR_DF_PRIMARIES_DISPLAYP3 = 10U,
/* Color primaries of Adobe RGB (1998) */
KHR_DF_PRIMARIES_ADOBERGB = 11U,
KHR_DF_PRIMARIES_MAX = 0xFFU
} khr_df_primaries_e;
/* Definition of the optical to digital transfer function
("gamma correction"). Most transfer functions are not a pure
power function and also include a linear element.
LAB and related absolute color representations should use
KHR_DF_TRANSFER_UNSPECIFIED. */
typedef enum _khr_df_transfer_e {
/* No transfer function defined */
KHR_DF_TRANSFER_UNSPECIFIED = 0U,
/* Linear transfer function (value proportional to intensity) */
KHR_DF_TRANSFER_LINEAR = 1U,
/* Perceptually-linear transfer function of sRGH (~2.4) */
KHR_DF_TRANSFER_SRGB = 2U,
/* Perceptually-linear transfer function of ITU BT.601, BT.709 and BT.2020 (~1/.45) */
KHR_DF_TRANSFER_ITU = 3U,
/* SMTPE170M (digital NTSC) defines an alias for the ITU transfer function (~1/.45) */
KHR_DF_TRANSFER_SMTPE170M = 3U,
/* Perceptually-linear gamma function of original NTSC (simple 2.2 gamma) */
KHR_DF_TRANSFER_NTSC = 4U,
/* Sony S-log used by Sony video cameras */
KHR_DF_TRANSFER_SLOG = 5U,
/* Sony S-log 2 used by Sony video cameras */
KHR_DF_TRANSFER_SLOG2 = 6U,
/* ITU BT.1886 EOTF */
KHR_DF_TRANSFER_BT1886 = 7U,
/* ITU BT.2100 HLG OETF */
KHR_DF_TRANSFER_HLG_OETF = 8U,
/* ITU BT.2100 HLG EOTF */
KHR_DF_TRANSFER_HLG_EOTF = 9U,
/* ITU BT.2100 PQ EOTF */
KHR_DF_TRANSFER_PQ_EOTF = 10U,
/* ITU BT.2100 PQ OETF */
KHR_DF_TRANSFER_PQ_OETF = 11U,
/* DCI P3 transfer function */
KHR_DF_TRANSFER_DCIP3 = 12U,
/* Legacy PAL OETF */
KHR_DF_TRANSFER_PAL_OETF = 13U,
/* Legacy PAL 625-line EOTF */
KHR_DF_TRANSFER_PAL625_EOTF = 14U,
/* Legacy ST240 transfer function */
KHR_DF_TRANSFER_ST240 = 15U,
/* ACEScc transfer function */
KHR_DF_TRANSFER_ACESCC = 16U,
/* ACEScct transfer function */
KHR_DF_TRANSFER_ACESCCT = 17U,
/* Adobe RGB (1998) transfer function */
KHR_DF_TRANSFER_ADOBERGB = 18U,
KHR_DF_TRANSFER_MAX = 0xFFU
} khr_df_transfer_e;
typedef enum _khr_df_flags_e {
KHR_DF_FLAG_ALPHA_STRAIGHT = 0U,
KHR_DF_FLAG_ALPHA_PREMULTIPLIED = 1U
} khr_df_flags_e;
typedef enum _khr_df_sample_datatype_qualifiers_e {
KHR_DF_SAMPLE_DATATYPE_LINEAR = 1U << 4U,
KHR_DF_SAMPLE_DATATYPE_EXPONENT = 1U << 5U,
KHR_DF_SAMPLE_DATATYPE_SIGNED = 1U << 6U,
KHR_DF_SAMPLE_DATATYPE_FLOAT = 1U << 7U
} khr_df_sample_datatype_qualifiers_e;
#endif

View File

@ -0,0 +1,51 @@
/* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @~English
* @brief Helper functions for colourspaces.
*/
#include <KHR/khr_df.h>
#include "dfd.h"
typedef struct s_PrimaryMapping {
khr_df_primaries_e dfPrimaryEnum;
Primaries primaries;
} sPrimaryMapping;
sPrimaryMapping primaryMap[] = {
{ KHR_DF_PRIMARIES_BT709, { 0.640f,0.330f, 0.300f,0.600f, 0.150f,0.060f, 0.3127f,0.3290f}},
{ KHR_DF_PRIMARIES_BT601_EBU, { 0.640f,0.330f, 0.290f,0.600f, 0.150f,0.060f, 0.3127f,0.3290f}},
{ KHR_DF_PRIMARIES_BT601_SMPTE, { 0.630f,0.340f, 0.310f,0.595f, 0.155f,0.070f, 0.3127f,0.3290f}},
{ KHR_DF_PRIMARIES_BT2020, { 0.708f,0.292f, 0.170f,0.797f, 0.131f,0.046f, 0.3127f,0.3290f}},
{ KHR_DF_PRIMARIES_CIEXYZ, { 1.0f,0.0f, 0.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f}},
{ KHR_DF_PRIMARIES_ACES, { 0.7347f,0.2653f, 0.0f,1.0f, 0.0001f,-0.077f, 0.32168f,0.33767f}},
{ KHR_DF_PRIMARIES_ACESCC, { 0.713f,0.293f, 0.165f,0.830f, 0.128f,0.044f, 0.32168f,0.33767f}},
{ KHR_DF_PRIMARIES_NTSC1953, { 0.67f,0.33f, 0.21f,0.71f, 0.14f,0.08f, 0.310f,0.316f}},
{ KHR_DF_PRIMARIES_PAL525, { 0.630f,0.340f, 0.310f,0.595f, 0.155f,0.070f, 0.3101f,0.3162f}},
{ KHR_DF_PRIMARIES_DISPLAYP3, { 0.6800f,0.3200f, 0.2650f,0.69f, 0.1500f,0.0600f, 0.3127f,0.3290f}},
{ KHR_DF_PRIMARIES_ADOBERGB, { 0.6400f,0.3300f, 0.2100f,0.71f, 0.1500f,0.0600f, 0.3127f,0.3290f}}};
/**
* @brief Map a set of primaries to a KDFS primaries enum.
*
* @param[in] p pointer to a Primaries struct filled in with the primary values.
* @param[in] latitude tolerance to use while matching. A suitable value might be 0.002
* but it depends on the application.
*/
khr_df_primaries_e findMapping(Primaries *p, float latitude) {
unsigned int i;
for (i = 0; i < sizeof(primaryMap)/sizeof(sPrimaryMapping); ++i) {
if (primaryMap[i].primaries.Rx - p->Rx <= latitude && p->Rx - primaryMap[i].primaries.Rx <= latitude &&
primaryMap[i].primaries.Gx - p->Gx <= latitude && p->Gx - primaryMap[i].primaries.Gx <= latitude &&
primaryMap[i].primaries.Bx - p->Bx <= latitude && p->Bx - primaryMap[i].primaries.Bx <= latitude &&
primaryMap[i].primaries.Wx - p->Wx <= latitude && p->Wx - primaryMap[i].primaries.Wx <= latitude) {
return primaryMap[i].dfPrimaryEnum;
}
}
/* No match */
return KHR_DF_PRIMARIES_UNSPECIFIED;
}

View File

@ -0,0 +1,659 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @~English
* @brief Utilities for creating data format descriptors.
*/
/*
* Author: Andrew Garrard
*/
#include <stdlib.h>
#include <KHR/khr_df.h>
#include "dfd.h"
typedef enum { i_COLOR, i_NON_COLOR } channels_infotype;
static uint32_t *writeHeader(int numSamples, int bytes, int suffix,
channels_infotype infotype)
{
uint32_t *DFD = (uint32_t *) malloc(sizeof(uint32_t) *
(1 + KHR_DF_WORD_SAMPLESTART +
numSamples * KHR_DF_WORD_SAMPLEWORDS));
uint32_t* BDFD = DFD+1;
DFD[0] = sizeof(uint32_t) *
(1 + KHR_DF_WORD_SAMPLESTART +
numSamples * KHR_DF_WORD_SAMPLEWORDS);
BDFD[KHR_DF_WORD_VENDORID] =
(KHR_DF_VENDORID_KHRONOS << KHR_DF_SHIFT_VENDORID) |
(KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT << KHR_DF_SHIFT_DESCRIPTORTYPE);
BDFD[KHR_DF_WORD_VERSIONNUMBER] =
(KHR_DF_VERSIONNUMBER_LATEST << KHR_DF_SHIFT_VERSIONNUMBER) |
(((uint32_t)sizeof(uint32_t) *
(KHR_DF_WORD_SAMPLESTART +
numSamples * KHR_DF_WORD_SAMPLEWORDS)
<< KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE));
BDFD[KHR_DF_WORD_MODEL] =
((KHR_DF_MODEL_RGBSDA << KHR_DF_SHIFT_MODEL) | /* Only supported model */
(KHR_DF_FLAG_ALPHA_STRAIGHT << KHR_DF_SHIFT_FLAGS));
if (infotype == i_COLOR) {
BDFD[KHR_DF_WORD_PRIMARIES] |= KHR_DF_PRIMARIES_BT709 << KHR_DF_SHIFT_PRIMARIES; /* Assumed */
} else {
BDFD[KHR_DF_WORD_PRIMARIES] |= KHR_DF_PRIMARIES_UNSPECIFIED << KHR_DF_SHIFT_PRIMARIES;
}
if (suffix == s_SRGB) {
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_SRGB << KHR_DF_SHIFT_TRANSFER;
} else {
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_LINEAR << KHR_DF_SHIFT_TRANSFER;
}
BDFD[KHR_DF_WORD_TEXELBLOCKDIMENSION0] = 0; /* Only 1x1x1x1 texel blocks supported */
BDFD[KHR_DF_WORD_BYTESPLANE0] = bytes; /* bytesPlane0 = bytes, bytesPlane3..1 = 0 */
BDFD[KHR_DF_WORD_BYTESPLANE4] = 0; /* bytesPlane7..5 = 0 */
return DFD;
}
static uint32_t setChannelFlags(uint32_t channel, enum VkSuffix suffix)
{
switch (suffix) {
case s_UNORM: break;
case s_SNORM:
channel |=
KHR_DF_SAMPLE_DATATYPE_SIGNED;
break;
case s_USCALED: break;
case s_SSCALED:
channel |=
KHR_DF_SAMPLE_DATATYPE_SIGNED;
break;
case s_UINT: break;
case s_SINT:
channel |=
KHR_DF_SAMPLE_DATATYPE_SIGNED;
break;
case s_SFLOAT:
channel |=
KHR_DF_SAMPLE_DATATYPE_FLOAT |
KHR_DF_SAMPLE_DATATYPE_SIGNED;
break;
case s_UFLOAT:
channel |=
KHR_DF_SAMPLE_DATATYPE_FLOAT;
break;
case s_SRGB:
if (channel == KHR_DF_CHANNEL_RGBSDA_ALPHA) {
channel |= KHR_DF_SAMPLE_DATATYPE_LINEAR;
}
break;
}
return channel;
}
static void writeSample(uint32_t *DFD, int sampleNo, int channel,
int bits, int offset,
int topSample, int bottomSample, enum VkSuffix suffix)
{
// Use this to avoid type-punning complaints from the gcc optimizer
// with -Wall.
union {
uint32_t i;
float f;
} lower, upper;
uint32_t *sample = DFD + 1 + KHR_DF_WORD_SAMPLESTART + sampleNo * KHR_DF_WORD_SAMPLEWORDS;
if (channel == 3) channel = KHR_DF_CHANNEL_RGBSDA_ALPHA;
if (channel == 3) channel = KHR_DF_CHANNEL_RGBSDA_ALPHA;
channel = setChannelFlags(channel, suffix);
sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
(offset << KHR_DF_SAMPLESHIFT_BITOFFSET) |
((bits - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
(channel << KHR_DF_SAMPLESHIFT_CHANNELID);
sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
switch (suffix) {
case s_UNORM:
case s_SRGB:
default:
if (bits > 32) {
upper.i = 0xFFFFFFFFU;
} else {
upper.i = (uint32_t)((1U << bits) - 1U);
}
lower.i = 0U;
break;
case s_SNORM:
if (bits > 32) {
upper.i = 0x7FFFFFFF;
} else {
upper.i = topSample ? (1U << (bits - 1)) - 1 : (1U << bits) - 1;
}
lower.i = ~upper.i;
if (bottomSample) lower.i += 1;
break;
case s_USCALED:
case s_UINT:
upper.i = bottomSample ? 1U : 0U;
lower.i = 0U;
break;
case s_SSCALED:
case s_SINT:
upper.i = bottomSample ? 1U : 0U;
lower.i = ~0U;
break;
case s_SFLOAT:
upper.f = 1.0f;
lower.f = -1.0f;
break;
case s_UFLOAT:
upper.f = 1.0f;
lower.f = 0.0f;
break;
}
sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
}
/**
* @~English
* @brief Create a Data Format Descriptor for an unpacked format.
*
* @param bigEndian Set to 1 for big-endian byte ordering and
0 for little-endian byte ordering.
* @param numChannels The number of color channels.
* @param bytes The number of bytes per channel.
* @param redBlueSwap Normally channels appear in consecutive R, G, B, A order
* in memory; redBlueSwap inverts red and blue, allowing
* B, G, R, A.
* @param suffix Indicates the format suffix for the type.
*
* @return A data format descriptor in malloc'd data. The caller is responsible
* for freeing the descriptor.
**/
uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes,
int redBlueSwap, enum VkSuffix suffix)
{
uint32_t *DFD;
if (bigEndian) {
int channelCounter, channelByte;
/* Number of samples = number of channels * bytes per channel */
DFD = writeHeader(numChannels * bytes, numChannels * bytes, suffix, i_COLOR);
/* First loop over the channels */
for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
int channel = channelCounter;
if (redBlueSwap && (channel == 0 || channel == 2)) {
channel ^= 2;
}
/* Loop over the bytes that constitute a channel */
for (channelByte = 0; channelByte < bytes; ++channelByte) {
writeSample(DFD, channelCounter * bytes + channelByte, channel,
8, 8 * (channelCounter * bytes + bytes - channelByte - 1),
channelByte == bytes-1, channelByte == 0, suffix);
}
}
} else { /* Little-endian */
int sampleCounter;
/* One sample per channel */
DFD = writeHeader(numChannels, numChannels * bytes, suffix, i_COLOR);
for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
int channel = sampleCounter;
if (redBlueSwap && (channel == 0 || channel == 2)) {
channel ^= 2;
}
writeSample(DFD, sampleCounter, channel,
8 * bytes, 8 * sampleCounter * bytes,
1, 1, suffix);
}
}
return DFD;
}
/**
* @~English
* @brief Create a Data Format Descriptor for a packed format.
*
* @param bigEndian Big-endian flag: Set to 1 for big-endian byte ordering and
* 0 for little-endian byte ordering.
* @param numChannels The number of color channels.
* @param bits[] An array of length numChannels.
* Each entry is the number of bits composing the channel, in
* order starting at bit 0 of the packed type.
* @param channels[] An array of length numChannels.
* Each entry enumerates the channel type: 0 = red, 1 = green,
* 2 = blue, 15 = alpha, in order starting at bit 0 of the
* packed type. These values match channel IDs for RGBSDA in
* the Khronos Data Format header. To simplify iteration
* through channels, channel id 3 is a synonym for alpha.
* @param suffix Indicates the format suffix for the type.
*
* @return A data format descriptor in malloc'd data. The caller is responsible
* for freeing the descriptor.
**/
uint32_t *createDFDPacked(int bigEndian, int numChannels,
int bits[], int channels[],
enum VkSuffix suffix)
{
uint32_t *DFD = 0;
if (numChannels == 6) {
/* Special case E5B9G9R9 */
DFD = writeHeader(numChannels, 4, s_UFLOAT, i_COLOR);
writeSample(DFD, 0, 0,
9, 0,
1, 1, s_UNORM);
KHR_DFDSETSVAL((DFD+1), 0, SAMPLEUPPER, 8448);
writeSample(DFD, 1, 0 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
5, 27,
1, 1, s_UNORM);
KHR_DFDSETSVAL((DFD+1), 1, SAMPLELOWER, 15);
KHR_DFDSETSVAL((DFD+1), 1, SAMPLEUPPER, 31);
writeSample(DFD, 2, 1,
9, 9,
1, 1, s_UNORM);
KHR_DFDSETSVAL((DFD+1), 2, SAMPLEUPPER, 8448);
writeSample(DFD, 3, 1 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
5, 27,
1, 1, s_UNORM);
KHR_DFDSETSVAL((DFD+1), 3, SAMPLELOWER, 15);
KHR_DFDSETSVAL((DFD+1), 3, SAMPLEUPPER, 31);
writeSample(DFD, 4, 2,
9, 18,
1, 1, s_UNORM);
KHR_DFDSETSVAL((DFD+1), 4, SAMPLEUPPER, 8448);
writeSample(DFD, 5, 2 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
5, 27,
1, 1, s_UNORM);
KHR_DFDSETSVAL((DFD+1), 5, SAMPLELOWER, 15);
KHR_DFDSETSVAL((DFD+1), 5, SAMPLEUPPER, 31);
} else if (bigEndian) {
/* No packed format is larger than 32 bits. */
/* No packed channel crosses more than two bytes. */
int totalBits = 0;
int bitChannel[32];
int beChannelStart[4];
int channelCounter;
int bitOffset = 0;
int BEMask;
int numSamples = numChannels;
int sampleCounter;
for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
beChannelStart[channelCounter] = totalBits;
totalBits += bits[channelCounter];
}
BEMask = (totalBits - 1) & 0x18;
for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
bitChannel[bitOffset ^ BEMask] = channelCounter;
if (((bitOffset + bits[channelCounter] - 1) & ~7) != (bitOffset & ~7)) {
/* Continuation sample */
bitChannel[((bitOffset + bits[channelCounter] - 1) & ~7) ^ BEMask] = channelCounter;
numSamples++;
}
bitOffset += bits[channelCounter];
}
DFD = writeHeader(numSamples, totalBits >> 3, suffix, i_COLOR);
sampleCounter = 0;
for (bitOffset = 0; bitOffset < totalBits;) {
if (bitChannel[bitOffset] == -1) {
/* Done this bit, so this is the lower half of something. */
/* We must therefore jump to the end of the byte and continue. */
bitOffset = (bitOffset + 8) & ~7;
} else {
/* Start of a channel? */
int thisChannel = bitChannel[bitOffset];
if ((beChannelStart[thisChannel] ^ BEMask) == bitOffset) {
/* Must be just one sample if we hit it first. */
writeSample(DFD, sampleCounter++, channels[thisChannel],
bits[thisChannel], bitOffset,
1, 1, suffix);
bitOffset += bits[thisChannel];
} else {
/* Two samples. Move to the end of the first one we hit when we're done. */
int firstSampleBits = 8 - (beChannelStart[thisChannel] & 0x7); /* Rest of the byte */
int secondSampleBits = bits[thisChannel] - firstSampleBits; /* Rest of the bits */
writeSample(DFD, sampleCounter++, channels[thisChannel],
firstSampleBits, beChannelStart[thisChannel] ^ BEMask,
0, 1, suffix);
/* Mark that we've already handled this sample */
bitChannel[beChannelStart[thisChannel] ^ BEMask] = -1;
writeSample(DFD, sampleCounter++, channels[thisChannel],
secondSampleBits, bitOffset,
1, 0, suffix);
bitOffset += secondSampleBits;
}
}
}
} else { /* Little-endian */
int sampleCounter;
int totalBits = 0;
int bitOffset = 0;
for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
totalBits += bits[sampleCounter];
}
/* One sample per channel */
DFD = writeHeader(numChannels, totalBits >> 3, suffix, i_COLOR);
for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
writeSample(DFD, sampleCounter, channels[sampleCounter],
bits[sampleCounter], bitOffset,
1, 1, suffix);
bitOffset += bits[sampleCounter];
}
}
return DFD;
}
static khr_df_model_e compModelMapping[] = {
KHR_DF_MODEL_BC1A, /*!< BC1, aka DXT1, no alpha. */
KHR_DF_MODEL_BC1A, /*!< BC1, aka DXT1, punch-through alpha. */
KHR_DF_MODEL_BC2, /*!< BC2, aka DXT2 and DXT3. */
KHR_DF_MODEL_BC3, /*!< BC3, aka DXT4 and DXT5. */
KHR_DF_MODEL_BC4, /*!< BC4. */
KHR_DF_MODEL_BC5, /*!< BC5. */
KHR_DF_MODEL_BC6H, /*!< BC6h HDR format. */
KHR_DF_MODEL_BC7, /*!< BC7. */
KHR_DF_MODEL_ETC2, /*!< ETC2 no alpha. */
KHR_DF_MODEL_ETC2, /*!< ETC2 punch-through alpha. */
KHR_DF_MODEL_ETC2, /*!< ETC2 independent alpha. */
KHR_DF_MODEL_ETC2, /*!< R11 ETC2 single-channel. */
KHR_DF_MODEL_ETC2, /*!< R11G11 ETC2 dual-channel. */
KHR_DF_MODEL_ASTC, /*!< ASTC. */
KHR_DF_MODEL_ETC1S, /*!< ETC1S. */
KHR_DF_MODEL_PVRTC, /*!< PVRTC(1). */
KHR_DF_MODEL_PVRTC2 /*!< PVRTC2. */
};
static uint32_t compSampleCount[] = {
1U, /*!< BC1, aka DXT1, no alpha. */
1U, /*!< BC1, aka DXT1, punch-through alpha. */
2U, /*!< BC2, aka DXT2 and DXT3. */
2U, /*!< BC3, aka DXT4 and DXT5. */
1U, /*!< BC4. */
2U, /*!< BC5. */
1U, /*!< BC6h HDR format. */
1U, /*!< BC7. */
1U, /*!< ETC2 no alpha. */
2U, /*!< ETC2 punch-through alpha. */
2U, /*!< ETC2 independent alpha. */
1U, /*!< R11 ETC2 single-channel. */
2U, /*!< R11G11 ETC2 dual-channel. */
1U, /*!< ASTC. */
1U, /*!< ETC1S. */
1U, /*!< PVRTC. */
1U /*!< PVRTC2. */
};
static khr_df_model_channels_e compFirstChannel[] = {
KHR_DF_CHANNEL_BC1A_COLOR, /*!< BC1, aka DXT1, no alpha. */
KHR_DF_CHANNEL_BC1A_ALPHAPRESENT, /*!< BC1, aka DXT1, punch-through alpha. */
KHR_DF_CHANNEL_BC2_ALPHA, /*!< BC2, aka DXT2 and DXT3. */
KHR_DF_CHANNEL_BC3_ALPHA, /*!< BC3, aka DXT4 and DXT5. */
KHR_DF_CHANNEL_BC4_DATA, /*!< BC4. */
KHR_DF_CHANNEL_BC5_RED, /*!< BC5. */
KHR_DF_CHANNEL_BC6H_COLOR, /*!< BC6h HDR format. */
KHR_DF_CHANNEL_BC7_COLOR, /*!< BC7. */
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 no alpha. */
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 punch-through alpha. */
KHR_DF_CHANNEL_ETC2_ALPHA, /*!< ETC2 independent alpha. */
KHR_DF_CHANNEL_ETC2_RED, /*!< R11 ETC2 single-channel. */
KHR_DF_CHANNEL_ETC2_RED, /*!< R11G11 ETC2 dual-channel. */
KHR_DF_CHANNEL_ASTC_DATA, /*!< ASTC. */
KHR_DF_CHANNEL_ETC1S_RGB, /*!< ETC1S. */
KHR_DF_CHANNEL_PVRTC_COLOR, /*!< PVRTC. */
KHR_DF_CHANNEL_PVRTC2_COLOR /*!< PVRTC2. */
};
static khr_df_model_channels_e compSecondChannel[] = {
KHR_DF_CHANNEL_BC1A_COLOR, /*!< BC1, aka DXT1, no alpha. */
KHR_DF_CHANNEL_BC1A_ALPHAPRESENT, /*!< BC1, aka DXT1, punch-through alpha. */
KHR_DF_CHANNEL_BC2_COLOR, /*!< BC2, aka DXT2 and DXT3. */
KHR_DF_CHANNEL_BC3_COLOR, /*!< BC3, aka DXT4 and DXT5. */
KHR_DF_CHANNEL_BC4_DATA, /*!< BC4. */
KHR_DF_CHANNEL_BC5_GREEN, /*!< BC5. */
KHR_DF_CHANNEL_BC6H_COLOR, /*!< BC6h HDR format. */
KHR_DF_CHANNEL_BC7_COLOR, /*!< BC7. */
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 no alpha. */
KHR_DF_CHANNEL_ETC2_ALPHA, /*!< ETC2 punch-through alpha. */
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 independent alpha. */
KHR_DF_CHANNEL_ETC2_RED, /*!< R11 ETC2 single-channel. */
KHR_DF_CHANNEL_ETC2_GREEN, /*!< R11G11 ETC2 dual-channel. */
KHR_DF_CHANNEL_ASTC_DATA, /*!< ASTC. */
KHR_DF_CHANNEL_ETC1S_RGB, /*!< ETC1S. */
KHR_DF_CHANNEL_PVRTC_COLOR, /*!< PVRTC. */
KHR_DF_CHANNEL_PVRTC2_COLOR /*!< PVRTC2. */
};
static uint32_t compSecondChannelOffset[] = {
0U, /*!< BC1, aka DXT1, no alpha. */
0U, /*!< BC1, aka DXT1, punch-through alpha. */
64U, /*!< BC2, aka DXT2 and DXT3. */
64U, /*!< BC3, aka DXT4 and DXT5. */
0U, /*!< BC4. */
64U, /*!< BC5. */
0U, /*!< BC6h HDR format. */
0U, /*!< BC7. */
0U, /*!< ETC2 no alpha. */
0U, /*!< ETC2 punch-through alpha. */
64U, /*!< ETC2 independent alpha. */
0U, /*!< R11 ETC2 single-channel. */
64U, /*!< R11G11 ETC2 dual-channel. */
0U, /*!< ASTC. */
0U, /*!< ETC1S. */
0U, /*!< PVRTC. */
0U /*!< PVRTC2. */
};
static uint32_t compChannelBits[] = {
64U, /*!< BC1, aka DXT1, no alpha. */
64U, /*!< BC1, aka DXT1, punch-through alpha. */
64U, /*!< BC2, aka DXT2 and DXT3. */
64U, /*!< BC3, aka DXT4 and DXT5. */
64U, /*!< BC4. */
64U, /*!< BC5. */
128U, /*!< BC6h HDR format. */
128U, /*!< BC7. */
64U, /*!< ETC2 no alpha. */
64U, /*!< ETC2 punch-through alpha. */
64U, /*!< ETC2 independent alpha. */
64U, /*!< R11 ETC2 single-channel. */
64U, /*!< R11G11 ETC2 dual-channel. */
128U, /*!< ASTC. */
64U, /*!< ETC1S. */
64U, /*!< PVRTC. */
64U /*!< PVRTC2. */
};
static uint32_t compBytes[] = {
8U, /*!< BC1, aka DXT1, no alpha. */
8U, /*!< BC1, aka DXT1, punch-through alpha. */
16U, /*!< BC2, aka DXT2 and DXT3. */
16U, /*!< BC3, aka DXT4 and DXT5. */
8U, /*!< BC4. */
16U, /*!< BC5. */
16U, /*!< BC6h HDR format. */
16U, /*!< BC7. */
8U, /*!< ETC2 no alpha. */
8U, /*!< ETC2 punch-through alpha. */
16U, /*!< ETC2 independent alpha. */
8U, /*!< R11 ETC2 single-channel. */
16U, /*!< R11G11 ETC2 dual-channel. */
16U, /*!< ASTC. */
8U, /*!< ETC1S. */
8U, /*!< PVRTC. */
8U /*!< PVRTC2. */
};
/**
* @~English
* @brief Create a Data Format Descriptor for a compressed format.
*
* @param compScheme Vulkan-style compression scheme enumeration.
* @param bwidth Block width in texel coordinates.
* @param bheight Block height in texel coordinates.
* @param bdepth Block depth in texel coordinates.
* @author Mark Callow, Edgewise Consulting.
* @param suffix Indicates the format suffix for the type.
*
* @return A data format descriptor in malloc'd data. The caller is responsible
* for freeing the descriptor.
**/
uint32_t *createDFDCompressed(enum VkCompScheme compScheme, int bwidth, int bheight, int bdepth,
enum VkSuffix suffix)
{
uint32_t *DFD = 0;
uint32_t numSamples = compSampleCount[compScheme];
uint32_t* BDFD;
uint32_t *sample;
uint32_t channel;
// Use union to avoid type-punning complaints from gcc optimizer
// with -Wall.
union {
uint32_t i;
float f;
} lower, upper;
DFD = (uint32_t *) malloc(sizeof(uint32_t) *
(1 + KHR_DF_WORD_SAMPLESTART +
numSamples * KHR_DF_WORD_SAMPLEWORDS));
BDFD = DFD+1;
DFD[0] = sizeof(uint32_t) *
(1 + KHR_DF_WORD_SAMPLESTART +
numSamples * KHR_DF_WORD_SAMPLEWORDS);
BDFD[KHR_DF_WORD_VENDORID] =
(KHR_DF_VENDORID_KHRONOS << KHR_DF_SHIFT_VENDORID) |
(KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT << KHR_DF_SHIFT_DESCRIPTORTYPE);
BDFD[KHR_DF_WORD_VERSIONNUMBER] =
(KHR_DF_VERSIONNUMBER_LATEST << KHR_DF_SHIFT_VERSIONNUMBER) |
(((uint32_t)sizeof(uint32_t) *
(KHR_DF_WORD_SAMPLESTART +
numSamples * KHR_DF_WORD_SAMPLEWORDS)
<< KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE));
BDFD[KHR_DF_WORD_MODEL] =
((compModelMapping[compScheme] << KHR_DF_SHIFT_MODEL) |
(KHR_DF_PRIMARIES_BT709 << KHR_DF_SHIFT_PRIMARIES) | /* Assumed */
(KHR_DF_FLAG_ALPHA_STRAIGHT << KHR_DF_SHIFT_FLAGS));
if (suffix == s_SRGB) {
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_SRGB << KHR_DF_SHIFT_TRANSFER;
} else {
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_LINEAR << KHR_DF_SHIFT_TRANSFER;
}
BDFD[KHR_DF_WORD_TEXELBLOCKDIMENSION0] =
(bwidth - 1) | ((bheight - 1) << KHR_DF_SHIFT_TEXELBLOCKDIMENSION1) | ((bdepth - 1) << KHR_DF_SHIFT_TEXELBLOCKDIMENSION2);
/* bytesPlane0 = bytes, bytesPlane3..1 = 0 */
BDFD[KHR_DF_WORD_BYTESPLANE0] = compBytes[compScheme];
BDFD[KHR_DF_WORD_BYTESPLANE4] = 0; /* bytesPlane7..5 = 0 */
sample = BDFD + KHR_DF_WORD_SAMPLESTART;
channel = compFirstChannel[compScheme];
channel = setChannelFlags(channel, suffix);
sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
(0 << KHR_DF_SAMPLESHIFT_BITOFFSET) |
((compChannelBits[compScheme] - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
(channel << KHR_DF_SAMPLESHIFT_CHANNELID);
sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
switch (suffix) {
case s_UNORM:
case s_SRGB:
default:
upper.i = 0xFFFFFFFFU;
lower.i = 0U;
break;
case s_SNORM:
upper.i = 0x7FFFFFFF;
lower.i = ~upper.i;
break;
case s_USCALED:
case s_UINT:
upper.i = 1U;
lower.i = 0U;
break;
case s_SSCALED:
case s_SINT:
upper.i = 1U;
lower.i = ~0U;
break;
case s_SFLOAT:
upper.f = 1.0f;
lower.f = -1.0f;
break;
case s_UFLOAT:
upper.f = 1.0f;
lower.f = 0.0f;
break;
}
sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
if (compSampleCount[compScheme] > 1) {
sample += KHR_DF_WORD_SAMPLEWORDS;
channel = compSecondChannel[compScheme];
channel = setChannelFlags(channel, suffix);
sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
(compSecondChannelOffset[compScheme] << KHR_DF_SAMPLESHIFT_BITOFFSET) |
((compChannelBits[compScheme] - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
(channel << KHR_DF_SAMPLESHIFT_CHANNELID);
sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
}
return DFD;
}
/**
* @~English
* @brief Create a Data Format Descriptor for a depth-stencil format.
*
* @param depthBits The numeber of bits in the depth channel.
* @param stencilBits The numeber of bits in the stencil channel.
* @param sizeBytes The total byte size of the texel.
*
* @return A data format descriptor in malloc'd data. The caller is responsible
* for freeing the descriptor.
**/
uint32_t *createDFDDepthStencil(int depthBits,
int stencilBits,
int sizeBytes)
{
/* N.B. Little-endian is assumed. */
uint32_t *DFD = 0;
DFD = writeHeader((depthBits > 0) + (stencilBits > 0),
sizeBytes, s_UNORM, i_NON_COLOR);
if (depthBits == 32) {
writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_DEPTH,
32, 0,
1, 1, s_SFLOAT);
} else if (depthBits > 0) {
writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_DEPTH,
depthBits, 0,
1, 1, s_UNORM);
}
if (stencilBits > 0) {
if (depthBits > 0) {
writeSample(DFD, 1, KHR_DF_CHANNEL_RGBSDA_STENCIL,
stencilBits, depthBits,
1, 1, s_UINT);
} else {
writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_STENCIL,
stencilBits, 0,
1, 1, s_UINT);
}
}
return DFD;
}

170
thirdparty/libktx/lib/dfdutils/dfd.h vendored Normal file
View File

@ -0,0 +1,170 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @~English
* @brief Header file defining the data format descriptor utilities API.
*/
/*
* Author: Andrew Garrard
*/
#ifndef _DFD_H_
#define _DFD_H_
#include <KHR/khr_df.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Qualifier suffix to the format, in Vulkan terms. */
enum VkSuffix {
s_UNORM, /*!< Unsigned normalized format. */
s_SNORM, /*!< Signed normalized format. */
s_USCALED, /*!< Unsigned scaled format. */
s_SSCALED, /*!< Signed scaled format. */
s_UINT, /*!< Unsigned integer format. */
s_SINT, /*!< Signed integer format. */
s_SFLOAT, /*!< Signed float format. */
s_UFLOAT, /*!< Unsigned float format. */
s_SRGB /*!< sRGB normalized format. */
};
/** Compression scheme, in Vulkan terms. */
enum VkCompScheme {
c_BC1_RGB, /*!< BC1, aka DXT1, no alpha. */
c_BC1_RGBA, /*!< BC1, aka DXT1, punch-through alpha. */
c_BC2, /*!< BC2, aka DXT2 and DXT3. */
c_BC3, /*!< BC3, aka DXT4 and DXT5. */
c_BC4, /*!< BC4. */
c_BC5, /*!< BC5. */
c_BC6H, /*!< BC6h HDR format. */
c_BC7, /*!< BC7. */
c_ETC2_R8G8B8, /*!< ETC2 no alpha. */
c_ETC2_R8G8B8A1, /*!< ETC2 punch-through alpha. */
c_ETC2_R8G8B8A8, /*!< ETC2 independent alpha. */
c_EAC_R11, /*!< R11 ETC2 single-channel. */
c_EAC_R11G11, /*!< R11G11 ETC2 dual-channel. */
c_ASTC, /*!< ASTC. */
c_ETC1S, /*!< ETC1S. */
c_PVRTC, /*!< PVRTC(1). */
c_PVRTC2 /*!< PVRTC2. */
};
typedef unsigned int uint32_t;
#if !defined(LIBKTX)
#include <vulkan/vulkan_core.h>
#else
#include "../vkformat_enum.h"
#endif
uint32_t* vk2dfd(enum VkFormat format);
/* Create a Data Format Descriptor for an unpacked format. */
uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes,
int redBlueSwap, enum VkSuffix suffix);
/* Create a Data Format Descriptor for a packed format. */
uint32_t *createDFDPacked(int bigEndian, int numChannels,
int bits[], int channels[],
enum VkSuffix suffix);
/* Create a Data Format Descriptor for a compressed format. */
uint32_t *createDFDCompressed(enum VkCompScheme compScheme,
int bwidth, int bheight, int bdepth,
enum VkSuffix suffix);
/* Create a Data Format Descriptor for a depth/stencil format. */
uint32_t *createDFDDepthStencil(int depthBits,
int stencilBits,
int sizeBytes);
/** @brief Result of interpreting the data format descriptor. */
enum InterpretDFDResult {
i_LITTLE_ENDIAN_FORMAT_BIT = 0, /*!< Confirmed little-endian (default for 8bpc). */
i_BIG_ENDIAN_FORMAT_BIT = 1, /*!< Confirmed big-endian. */
i_PACKED_FORMAT_BIT = 2, /*!< Packed format. */
i_SRGB_FORMAT_BIT = 4, /*!< sRGB transfer function. */
i_NORMALIZED_FORMAT_BIT = 8, /*!< Normalized (UNORM or SNORM). */
i_SIGNED_FORMAT_BIT = 16, /*!< Format is signed. */
i_FLOAT_FORMAT_BIT = 32, /*!< Format is floating point. */
i_UNSUPPORTED_ERROR_BIT = 64, /*!< Format not successfully interpreted. */
/** "NONTRIVIAL_ENDIANNESS" means not big-endian, not little-endian
* (a channel has bits that are not consecutive in either order). **/
i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS = i_UNSUPPORTED_ERROR_BIT,
/** "MULTIPLE_SAMPLE_LOCATIONS" is an error because only single-sample
* texel blocks (with coordinates 0,0,0,0 for all samples) are supported. **/
i_UNSUPPORTED_MULTIPLE_SAMPLE_LOCATIONS = i_UNSUPPORTED_ERROR_BIT + 1,
/** "MULTIPLE_PLANES" is an error because only contiguous data is supported. */
i_UNSUPPORTED_MULTIPLE_PLANES = i_UNSUPPORTED_ERROR_BIT + 2,
/** Only channels R, G, B and A are supported. */
i_UNSUPPORTED_CHANNEL_TYPES = i_UNSUPPORTED_ERROR_BIT + 3,
/** Only channels with the same flags are supported
* (e.g. we don't support float red with integer green). */
i_UNSUPPORTED_MIXED_CHANNELS = i_UNSUPPORTED_ERROR_BIT + 4
};
/** @brief Interpretation of a channel from the data format descriptor. */
typedef struct _InterpretedDFDChannel {
uint32_t offset; /*!< Offset in bits for packed, bytes for unpacked. */
uint32_t size; /*!< Size in bits for packed, bytes for unpacked. */
} InterpretedDFDChannel;
/* Interpret a Data Format Descriptor. */
enum InterpretDFDResult interpretDFD(const uint32_t *DFD,
InterpretedDFDChannel *R,
InterpretedDFDChannel *G,
InterpretedDFDChannel *B,
InterpretedDFDChannel *A,
uint32_t *wordBytes);
/* Print a human-readable interpretation of a data format descriptor. */
void printDFD(uint32_t *DFD);
/* Get the number of components & component size from a DFD for an
* unpacked format.
*/
void
getDFDComponentInfoUnpacked(const uint32_t* DFD, uint32_t* numComponents,
uint32_t* componentByteLength);
/* Return the number of components described by a DFD. */
uint32_t getDFDNumComponents(const uint32_t* DFD);
/* Recreate and return the value of bytesPlane0 as it should be for the data
* post-inflation from variable-rate compression.
*/
void
recreateBytesPlane0FromSampleInfo(const uint32_t* DFD, uint32_t* bytesPlane0);
/** @brief Colourspace primaries information.
*
* Structure to store the 1931 CIE x,y chromaticities of the red, green, and blue
* display primaries and the reference white point of a colourspace.
*/
typedef struct _Primaries {
float Rx; /*!< Red x. */
float Ry; /*!< Red y. */
float Gx; /*!< Green x. */
float Gy; /*!< Green y. */
float Bx; /*!< Blue x. */
float By; /*!< Blue y. */
float Wx; /*!< White x. */
float Wy; /*!< White y. */
} Primaries;
khr_df_primaries_e findMapping(Primaries *p, float latitude);
#ifdef __cplusplus
}
#endif
#endif /* _DFD_H_ */

View File

@ -0,0 +1,599 @@
/* Copyright 2019-2020 The Khronos Group Inc. */
/* SPDX-License-Identifier: Apache-2.0 */
/***************************** Do not edit. *****************************
Automatically generated by makedfd2vk.pl.
*************************************************************************/
if (KHR_DFDVAL(dfd + 1, MODEL) == KHR_DF_MODEL_RGBSDA) {
enum InterpretDFDResult r;
InterpretedDFDChannel R = {0,0};
InterpretedDFDChannel G = {0,0};
InterpretedDFDChannel B = {0,0};
InterpretedDFDChannel A = {0,0};
uint32_t wordBytes;
/* Special case exponent format */
if (KHR_DFDSAMPLECOUNT(dfd + 1) == 6 &&
((KHR_DFDSVAL((dfd + 1), 1, QUALIFIERS) & KHR_DF_SAMPLE_DATATYPE_EXPONENT) > 0)) {
/* The only format we expect to be encoded like this. */
return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32;
}
/* Special case depth formats (assumed little-endian) */
if (KHR_DFDSVAL((dfd + 1), 0, CHANNELID) == KHR_DF_CHANNEL_RGBSDA_DEPTH) {
if (KHR_DFDSAMPLECOUNT((dfd + 1)) == 1) {
if (KHR_DFDSVAL((dfd + 1), 0, BITLENGTH) == 16-1) return VK_FORMAT_D16_UNORM;
if (KHR_DFDSVAL((dfd + 1), 0, BITLENGTH) == 24-1) return VK_FORMAT_X8_D24_UNORM_PACK32;
return VK_FORMAT_D32_SFLOAT;
} else {
if (KHR_DFDSVAL((dfd + 1), 0, BITLENGTH) == 16-1) return VK_FORMAT_D16_UNORM_S8_UINT;
if (KHR_DFDSVAL((dfd + 1), 0, BITLENGTH) == 24-1) return VK_FORMAT_D24_UNORM_S8_UINT;
return VK_FORMAT_D32_SFLOAT_S8_UINT;
}
}
if (KHR_DFDSVAL((dfd + 1), 0, CHANNELID) == KHR_DF_CHANNEL_RGBSDA_STENCIL) {
return VK_FORMAT_S8_UINT;
}
r = interpretDFD(dfd, &R, &G, &B, &A, &wordBytes);
if (r & i_UNSUPPORTED_ERROR_BIT) return VK_FORMAT_UNDEFINED;
if (r & i_PACKED_FORMAT_BIT) {
if (wordBytes == 1) return VK_FORMAT_R4G4_UNORM_PACK8;
else if (wordBytes == 2) { /* PACK16 */
if (A.size == 4) {
if (R.offset == 12) return VK_FORMAT_R4G4B4A4_UNORM_PACK16;
else return VK_FORMAT_B4G4R4A4_UNORM_PACK16;
} else if (A.size == 0) { /* Three channels */
if (B.offset == 0) return VK_FORMAT_R5G6B5_UNORM_PACK16;
else return VK_FORMAT_B5G6R5_UNORM_PACK16;
} else { /* Four channels, one-bit alpha */
if (B.offset == 0) return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
if (B.offset == 1) return VK_FORMAT_R5G5B5A1_UNORM_PACK16;
return VK_FORMAT_B5G5R5A1_UNORM_PACK16;
}
} else if (wordBytes == 4) { /* PACK32 */
if (A.size == 8) {
if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_A8B8G8R8_SRGB_PACK32;
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A8B8G8R8_SNORM_PACK32;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A8B8G8R8_UINT_PACK32;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A8B8G8R8_SINT_PACK32;
} else if (A.size == 2 && B.offset == 0) {
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A2R10G10B10_UNORM_PACK32;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A2R10G10B10_SNORM_PACK32;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A2R10G10B10_UINT_PACK32;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A2R10G10B10_SINT_PACK32;
} else if (A.size == 2 && R.offset == 0) {
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A2B10G10R10_SNORM_PACK32;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A2B10G10R10_UINT_PACK32;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A2B10G10R10_SINT_PACK32;
} else if (R.size == 11) return VK_FORMAT_B10G11R11_UFLOAT_PACK32;
}
} else { /* Not a packed format */
if (wordBytes == 1) {
if (A.size > 0) { /* 4 channels */
if (R.offset == 0) { /* RGBA */
if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_SRGB;
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_UNORM;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_SNORM;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_SINT;
} else { /* BGRA */
if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_SRGB;
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_UNORM;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_SNORM;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_SINT;
}
} else if (B.size > 0) { /* 3 channels */
if (R.offset == 0) { /* RGB */
if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_R8G8B8_SRGB;
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_UNORM;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_SNORM;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_SINT;
} else { /* BGR */
if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_B8G8R8_SRGB;
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_UNORM;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_SNORM;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_SINT;
}
} else if (G.size > 0) { /* 2 channels */
if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_R8G8_SRGB;
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8_UNORM;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8_SNORM;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8_SINT;
} else { /* 1 channel */
if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_R8_SRGB;
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8_UNORM;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8_SNORM;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8_SINT;
}
} else if (wordBytes == 2) {
if (A.size > 0) { /* 4 channels */
if (R.offset == 0) { /* RGBA */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_SFLOAT;
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_UNORM;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_SNORM;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_SINT;
} else { /* BGRA */
}
} else if (B.size > 0) { /* 3 channels */
if (R.offset == 0) { /* RGB */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R16G16B16_SFLOAT;
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_UNORM;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_SNORM;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_SINT;
} else { /* BGR */
}
} else if (G.size > 0) { /* 2 channels */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R16G16_SFLOAT;
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16_UNORM;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16_SNORM;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16_SINT;
} else { /* 1 channel */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R16_SFLOAT;
if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16_UNORM;
if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16_SNORM;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16_SINT;
}
} else if (wordBytes == 4) {
if (A.size > 0) { /* 4 channels */
if (R.offset == 0) { /* RGBA */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R32G32B32A32_SFLOAT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32A32_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32A32_SINT;
} else { /* BGRA */
}
} else if (B.size > 0) { /* 3 channels */
if (R.offset == 0) { /* RGB */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R32G32B32_SFLOAT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32_SINT;
} else { /* BGR */
}
} else if (G.size > 0) { /* 2 channels */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R32G32_SFLOAT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32_SINT;
} else { /* 1 channel */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R32_SFLOAT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32_SINT;
}
} else if (wordBytes == 8) {
if (A.size > 0) { /* 4 channels */
if (R.offset == 0) { /* RGBA */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R64G64B64A64_SFLOAT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64A64_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64A64_SINT;
} else { /* BGRA */
}
} else if (B.size > 0) { /* 3 channels */
if (R.offset == 0) { /* RGB */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R64G64B64_SFLOAT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64_SINT;
} else { /* BGR */
}
} else if (G.size > 0) { /* 2 channels */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R64G64_SFLOAT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64_SINT;
} else { /* 1 channel */
if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R64_SFLOAT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64_UINT;
if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64_SINT;
}
}
}
} else if (KHR_DFDVAL((dfd + 1), MODEL) >= 128) {
const uint32_t *bdb = dfd + 1;
switch (KHR_DFDVAL(bdb, MODEL)) {
case KHR_DF_MODEL_BC1A:
if (KHR_DFDSVAL(bdb, 0, CHANNELID) == KHR_DF_CHANNEL_BC1A_COLOR) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_BC1_RGB_UNORM_BLOCK;
} else {
return VK_FORMAT_BC1_RGB_SRGB_BLOCK;
}
} else {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
} else {
return VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
}
}
case KHR_DF_MODEL_BC2:
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_BC2_UNORM_BLOCK;
} else {
return VK_FORMAT_BC2_SRGB_BLOCK;
}
case KHR_DF_MODEL_BC3:
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_BC3_UNORM_BLOCK;
} else {
return VK_FORMAT_BC3_SRGB_BLOCK;
}
case KHR_DF_MODEL_BC4:
if (!(KHR_DFDSVAL(bdb, 0, QUALIFIERS) & KHR_DF_SAMPLE_DATATYPE_SIGNED)) {
return VK_FORMAT_BC4_UNORM_BLOCK;
} else {
return VK_FORMAT_BC4_SNORM_BLOCK;
}
case KHR_DF_MODEL_BC5:
if (!(KHR_DFDSVAL(bdb, 0, QUALIFIERS) & KHR_DF_SAMPLE_DATATYPE_SIGNED)) {
return VK_FORMAT_BC5_UNORM_BLOCK;
} else {
return VK_FORMAT_BC5_SNORM_BLOCK;
}
case KHR_DF_MODEL_BC6H:
if (!(KHR_DFDSVAL(bdb, 0, QUALIFIERS) & KHR_DF_SAMPLE_DATATYPE_SIGNED)) {
return VK_FORMAT_BC6H_UFLOAT_BLOCK;
} else {
return VK_FORMAT_BC6H_SFLOAT_BLOCK;
}
case KHR_DF_MODEL_BC7:
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_BC7_UNORM_BLOCK;
} else {
return VK_FORMAT_BC7_SRGB_BLOCK;
}
case KHR_DF_MODEL_ETC2:
if (KHR_DFDSVAL(bdb, 0, CHANNELID) == KHR_DF_CHANNEL_ETC2_COLOR) {
if (KHR_DFDVAL(bdb, DESCRIPTORBLOCKSIZE) == 40) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
} else {
return VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK;
}
} else {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
} else {
return VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK;
}
}
} else if (KHR_DFDSVAL(bdb, 0, CHANNELID) == KHR_DF_CHANNEL_ETC2_ALPHA) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
} else {
return VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
}
} else if (KHR_DFDVAL(bdb, DESCRIPTORBLOCKSIZE) == 40) {
if (!(KHR_DFDSVAL(bdb, 0, QUALIFIERS) & KHR_DF_SAMPLE_DATATYPE_SIGNED)) {
return VK_FORMAT_EAC_R11_UNORM_BLOCK;
} else {
return VK_FORMAT_EAC_R11_SNORM_BLOCK;
}
} else {
if (!(KHR_DFDSVAL(bdb, 0, QUALIFIERS) & KHR_DF_SAMPLE_DATATYPE_SIGNED)) {
return VK_FORMAT_EAC_R11G11_UNORM_BLOCK;
} else {
return VK_FORMAT_EAC_R11G11_SNORM_BLOCK;
}
}
case KHR_DF_MODEL_ASTC:
if (!(KHR_DFDSVAL(bdb, 0, QUALIFIERS) & KHR_DF_SAMPLE_DATATYPE_FLOAT)) {
if (KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 0) {
if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 3)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_4x4_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 3)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_5x4_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_5x5_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_6x5_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 5)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_6x6_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 7) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_8x5_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 7) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 5)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_8x6_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 7) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 7)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_8x8_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 9) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_10x5_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 9) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 5)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_10x6_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 9) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 7)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_10x8_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 9) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 9)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_10x10_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 11) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 9)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_12x10_SRGB_BLOCK;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 11) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 11)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
} else {
return VK_FORMAT_ASTC_12x12_SRGB_BLOCK;
}
}
} else {
if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 2) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 2) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 2)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT;
} else {
return VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 2) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 2)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_4x3x3_UNORM_BLOCK_EXT;
} else {
return VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 2)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_4x4x3_UNORM_BLOCK_EXT;
} else {
return VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 3)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_4x4x4_UNORM_BLOCK_EXT;
} else {
return VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT;
}
}
if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 3)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_5x4x4_UNORM_BLOCK_EXT;
} else {
return VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 3)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_5x5x4_UNORM_BLOCK_EXT;
} else {
return VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 4)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_5x5x5_UNORM_BLOCK_EXT;
} else {
return VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 4)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_6x5x5_UNORM_BLOCK_EXT;
} else {
return VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 4)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_6x6x5_UNORM_BLOCK_EXT;
} else {
return VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT;
}
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 5)) {
if (KHR_DFDVAL(bdb, TRANSFER) != KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT;
} else {
return VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT;
}
}
}
} else {
if (KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 0) {
if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 3)) {
return VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 3)) {
return VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4)) {
return VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4)) {
return VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 5)) {
return VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 7) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4)) {
return VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 7) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 5)) {
return VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 7) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 7)) {
return VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 9) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4)) {
return VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 9) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 5)) {
return VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 9) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 7)) {
return VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 9) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 9)) {
return VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 11) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 9)) {
return VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 11) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 11)) {
return VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT;
}
} else {
if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 2) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 2) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 2)) {
return VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 2) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 2)) {
return VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 2) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 2)) {
return VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 2)) {
return VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 3)) {
return VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 3) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 3)) {
return VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 3)) {
return VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 4)) {
return VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 4) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 4)) {
return VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 4)) {
return VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT;
} else if ((KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION1) == 5) &&
(KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION2) == 5)) {
return VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT;
}
}
}
break;
case KHR_DF_MODEL_PVRTC:
if (KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 3) {
if (KHR_DFDVAL(bdb, TRANSFER) == KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG;
} else {
return VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
}
} else {
if (KHR_DFDVAL(bdb, TRANSFER) == KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
} else {
return VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
}
}
case KHR_DF_MODEL_PVRTC2:
if (KHR_DFDVAL(bdb, TEXELBLOCKDIMENSION0) == 3) {
if (KHR_DFDVAL(bdb, TRANSFER) == KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG;
} else {
return VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG;
}
} else {
if (KHR_DFDVAL(bdb, TRANSFER) == KHR_DF_TRANSFER_SRGB) {
return VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG;
} else {
return VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG;
}
}
default:
;
}
}
return VK_FORMAT_UNDEFINED; /* Drop-through for unmatched formats. */

View File

@ -0,0 +1,345 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @~English
* @brief Utility for interpreting a data format descriptor.
* @author Andrew Garrard
*/
#include <stdint.h>
#include <stdio.h>
#include <KHR/khr_df.h>
#include "dfd.h"
/**
* @~English
* @brief Interpret a Data Format Descriptor for a simple format.
*
* @param DFD Pointer to a Data Format Descriptor to interpret,
described as 32-bit words in native endianness.
Note that this is the whole descriptor, not just
the basic descriptor block.
* @param R Information about the decoded red channel, if any.
* @param G Information about the decoded green channel, if any.
* @param B Information about the decoded blue channel, if any.
* @param A Information about the decoded alpha channel, if any.
* @param wordBytes Byte size of the channels (unpacked) or total size (packed).
*
* @return An enumerant describing the decoded value,
* or an error code in case of failure.
**/
enum InterpretDFDResult interpretDFD(const uint32_t *DFD,
InterpretedDFDChannel *R,
InterpretedDFDChannel *G,
InterpretedDFDChannel *B,
InterpretedDFDChannel *A,
uint32_t *wordBytes)
{
/* We specifically handle "simple" cases that can be translated */
/* to things a GPU can access. For simplicity, we also ignore */
/* the compressed formats, which are generally a single sample */
/* (and I believe are all defined to be little-endian in their */
/* in-memory layout, even if some documentation confuses this). */
/* We also just worry about layout and ignore sRGB, since that's */
/* trivial to extract anyway. */
/* DFD points to the whole descriptor, not the basic descriptor block. */
/* Make everything else relative to the basic descriptor block. */
const uint32_t *BDFDB = DFD+1;
uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
uint32_t sampleCounter;
int determinedEndianness = 0;
int determinedNormalizedness = 0;
int determinedSignedness = 0;
int determinedFloatness = 0;
enum InterpretDFDResult result = 0; /* Build this up incrementally. */
/* Clear these so following code doesn't get confused. */
R->offset = R->size = 0;
G->offset = G->size = 0;
B->offset = B->size = 0;
A->offset = A->size = 0;
/* First rule out the multiple planes case (trivially) */
/* - that is, we check that only bytesPlane0 is non-zero. */
/* This means we don't handle YUV even if the API could. */
/* (We rely on KHR_DF_WORD_BYTESPLANE0..3 being the same and */
/* KHR_DF_WORD_BYTESPLANE4..7 being the same as a short cut.) */
if ((BDFDB[KHR_DF_WORD_BYTESPLANE0] & ~KHR_DF_MASK_BYTESPLANE0)
|| BDFDB[KHR_DF_WORD_BYTESPLANE4]) return i_UNSUPPORTED_MULTIPLE_PLANES;
/* Only support the RGB color model. */
/* We could expand this to allow "UNSPECIFIED" as well. */
if (KHR_DFDVAL(BDFDB, MODEL) != KHR_DF_MODEL_RGBSDA) return i_UNSUPPORTED_CHANNEL_TYPES;
/* We only pay attention to sRGB. */
if (KHR_DFDVAL(BDFDB, TRANSFER) == KHR_DF_TRANSFER_SRGB) result |= i_SRGB_FORMAT_BIT;
/* We only support samples at coordinate 0,0,0,0. */
/* (We could confirm this from texel_block_dimensions in 1.2, but */
/* the interpretation might change in later versions.) */
for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
if (KHR_DFDSVAL(BDFDB, sampleCounter, SAMPLEPOSITION_ALL))
return i_UNSUPPORTED_MULTIPLE_SAMPLE_LOCATIONS;
}
/* Set flags and check for consistency. */
for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
/* Note: We're ignoring 9995, which is weird and worth special-casing */
/* rather than trying to generalise to all float formats. */
if (!determinedFloatness) {
if (KHR_DFDSVAL(BDFDB, sampleCounter, QUALIFIERS)
& KHR_DF_SAMPLE_DATATYPE_FLOAT) {
result |= i_FLOAT_FORMAT_BIT;
determinedFloatness = 1;
}
} else {
/* Check whether we disagree with our predetermined floatness. */
/* Note that this could justifiably happen with (say) D24S8. */
if (KHR_DFDSVAL(BDFDB, sampleCounter, QUALIFIERS)
& KHR_DF_SAMPLE_DATATYPE_FLOAT) {
if (!(result & i_FLOAT_FORMAT_BIT)) return i_UNSUPPORTED_MIXED_CHANNELS;
} else {
if ((result & i_FLOAT_FORMAT_BIT)) return i_UNSUPPORTED_MIXED_CHANNELS;
}
}
if (!determinedSignedness) {
if (KHR_DFDSVAL(BDFDB, sampleCounter, QUALIFIERS)
& KHR_DF_SAMPLE_DATATYPE_SIGNED) {
result |= i_SIGNED_FORMAT_BIT;
determinedSignedness = 1;
}
} else {
/* Check whether we disagree with our predetermined signedness. */
if (KHR_DFDSVAL(BDFDB, sampleCounter, QUALIFIERS)
& KHR_DF_SAMPLE_DATATYPE_SIGNED) {
if (!(result & i_SIGNED_FORMAT_BIT)) return i_UNSUPPORTED_MIXED_CHANNELS;
} else {
if ((result & i_SIGNED_FORMAT_BIT)) return i_UNSUPPORTED_MIXED_CHANNELS;
}
}
/* We define "unnormalized" as "sample_upper = 1". */
/* We don't check whether any non-1 normalization value is correct */
/* (i.e. set to the maximum bit value, and check min value) on */
/* the assumption that we're looking at a format which *came* from */
/* an API we can support. */
if (!determinedNormalizedness) {
/* The ambiguity here is if the bottom bit is a single-bit value, */
/* as in RGBA 5:5:5:1, so we defer the decision if the channel only has one bit. */
if (KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) > 0) {
if ((result & i_FLOAT_FORMAT_BIT)) {
if (*(float *)(void *)&BDFDB[KHR_DF_WORD_SAMPLESTART +
KHR_DF_WORD_SAMPLEWORDS * sampleCounter +
KHR_DF_SAMPLEWORD_SAMPLEUPPER] != 1.0f) {
result |= i_NORMALIZED_FORMAT_BIT;
}
} else {
if (KHR_DFDSVAL(BDFDB, sampleCounter, SAMPLEUPPER) != 1U) {
result |= i_NORMALIZED_FORMAT_BIT;
}
}
determinedNormalizedness = 1;
}
}
/* Note: We don't check for inconsistent normalization, because */
/* channels composed of multiple samples will have 0 in the */
/* lower/upper range. */
/* This heuristic should handle 64-bit integers, too. */
}
/* If this is a packed format, we work out our offsets differently. */
/* We assume a packed format has channels that aren't byte-aligned. */
/* If we have a format in which every channel is byte-aligned *and* packed, */
/* we have the RGBA/ABGR ambiguity; we *probably* don't want the packed */
/* version in this case, and if hardware has to pack it and swizzle, */
/* that's up to the hardware to special-case. */
for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
if (KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET) & 0x7U) {
result |= i_PACKED_FORMAT_BIT;
/* Once we're packed, we're packed, no need to keep checking. */
break;
}
}
/* Remember: the canonical ordering of samples is to start with */
/* the lowest bit of the channel/location which touches bit 0 of */
/* the data, when the latter is concatenated in little-endian order, */
/* and then progress until all the bits of that channel/location */
/* have been processed. Multiple channels sharing the same source */
/* bits are processed in channel ID order. (I should clarify this */
/* for partially-shared data, but it doesn't really matter so long */
/* as everything is consecutive, except to make things canonical.) */
/* Note: For standard formats we could determine big/little-endianness */
/* simply from whether the first sample starts in bit 0; technically */
/* it's possible to have a format with unaligned channels wherein the */
/* first channel starts at bit 0 and is one byte, yet other channels */
/* take more bytes or aren't aligned (e.g. D24S8), but this should be */
/* irrelevant for the formats that we support. */
if ((result & i_PACKED_FORMAT_BIT)) {
/* A packed format. */
uint32_t currentChannel = ~0U; /* Don't start matched. */
uint32_t currentBitOffset = 0;
uint32_t currentByteOffset = 0;
uint32_t currentBitLength = 0;
*wordBytes = (BDFDB[KHR_DF_WORD_BYTESPLANE0] & 0xFFU);
for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
uint32_t sampleBitOffset = KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET);
uint32_t sampleByteOffset = sampleBitOffset >> 3U;
/* The sample bitLength field stores the bit length - 1. */
uint32_t sampleBitLength = KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1;
uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID);
InterpretedDFDChannel *sampleChannelPtr;
switch (sampleChannel) {
case KHR_DF_CHANNEL_RGBSDA_RED:
sampleChannelPtr = R;
break;
case KHR_DF_CHANNEL_RGBSDA_GREEN:
sampleChannelPtr = G;
break;
case KHR_DF_CHANNEL_RGBSDA_BLUE:
sampleChannelPtr = B;
break;
case KHR_DF_CHANNEL_RGBSDA_ALPHA:
sampleChannelPtr = A;
break;
default:
return i_UNSUPPORTED_CHANNEL_TYPES;
}
if (sampleChannel == currentChannel) {
/* Continuation of the same channel. */
/* Since a big (>32-bit) channel isn't "packed", */
/* this should only happen in big-endian, or if */
/* we have a wacky format that we won't support. */
if (sampleByteOffset == currentByteOffset - 1U && /* One byte earlier */
((currentBitOffset + currentBitLength) & 7U) == 0 && /* Already at the end of a byte */
(sampleBitOffset & 7U) == 0) { /* Start at the beginning of the byte */
/* All is good, continue big-endian. */
/* N.B. We shouldn't be here if we decided we were little-endian, */
/* so we don't bother to check that disagreement. */
result |= i_BIG_ENDIAN_FORMAT_BIT;
determinedEndianness = 1;
} else {
/* Oh dear. */
/* We could be little-endian, but not with any standard format. */
/* More likely we've got something weird that we can't support. */
return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS;
}
/* Remember where we are. */
currentBitOffset = sampleBitOffset;
currentByteOffset = sampleByteOffset;
currentBitLength = sampleBitLength;
/* Accumulate the bit length. */
sampleChannelPtr->size += sampleBitLength;
} else {
/* Everything is new. Hopefully. */
currentChannel = sampleChannel;
currentBitOffset = sampleBitOffset;
currentByteOffset = sampleByteOffset;
currentBitLength = sampleBitLength;
if (sampleChannelPtr->size) {
/* Uh-oh, we've seen this channel before. */
return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS;
}
/* For now, record the bit offset in little-endian terms, */
/* because we may not know to reverse it yet. */
sampleChannelPtr->offset = sampleBitOffset;
sampleChannelPtr->size = sampleBitLength;
}
}
if ((result & i_BIG_ENDIAN_FORMAT_BIT)) {
/* Our bit offsets to bit 0 of each channel are in little-endian terms. */
/* We need to do a byte swap to work out where they should be. */
/* We assume, for sanity, that byte sizes are a power of two for this. */
uint32_t offsetMask = (*wordBytes - 1U) << 3U;
R->offset ^= offsetMask;
G->offset ^= offsetMask;
B->offset ^= offsetMask;
A->offset ^= offsetMask;
}
} else {
/* Not a packed format. */
/* Everything is byte-aligned. */
/* Question is whether there multiple samples per channel. */
uint32_t currentChannel = ~0U; /* Don't start matched. */
uint32_t currentByteOffset = 0;
uint32_t currentByteLength = 0;
for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
uint32_t sampleByteOffset = KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET) >> 3U;
uint32_t sampleByteLength = (KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1) >> 3U;
uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID);
InterpretedDFDChannel *sampleChannelPtr;
switch (sampleChannel) {
case KHR_DF_CHANNEL_RGBSDA_RED:
sampleChannelPtr = R;
break;
case KHR_DF_CHANNEL_RGBSDA_GREEN:
sampleChannelPtr = G;
break;
case KHR_DF_CHANNEL_RGBSDA_BLUE:
sampleChannelPtr = B;
break;
case KHR_DF_CHANNEL_RGBSDA_ALPHA:
sampleChannelPtr = A;
break;
default:
return i_UNSUPPORTED_CHANNEL_TYPES;
}
if (sampleChannel == currentChannel) {
/* Continuation of the same channel. */
/* Either big-endian, or little-endian with a very large channel. */
if (sampleByteOffset == currentByteOffset - 1) { /* One byte earlier */
if (determinedEndianness && !(result & i_BIG_ENDIAN_FORMAT_BIT)) {
return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS;
}
/* All is good, continue big-endian. */
result |= i_BIG_ENDIAN_FORMAT_BIT;
determinedEndianness = 1;
/* Update the start */
sampleChannelPtr->offset = sampleByteOffset;
} else if (sampleByteOffset == currentByteOffset + currentByteLength) {
if (determinedEndianness && (result & i_BIG_ENDIAN_FORMAT_BIT)) {
return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS;
}
/* All is good, continue little-endian. */
determinedEndianness = 1;
} else {
/* Oh dear. */
/* We could be little-endian, but not with any standard format. */
/* More likely we've got something weird that we can't support. */
return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS;
}
/* Remember where we are. */
currentByteOffset = sampleByteOffset;
currentByteLength = sampleByteLength;
/* Accumulate the byte length. */
sampleChannelPtr->size += sampleByteLength;
/* Assume these are all the same. */
*wordBytes = sampleChannelPtr->size;
} else {
/* Everything is new. Hopefully. */
currentChannel = sampleChannel;
currentByteOffset = sampleByteOffset;
currentByteLength = sampleByteLength;
if (sampleChannelPtr->size) {
/* Uh-oh, we've seen this channel before. */
return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS;
}
/* For now, record the byte offset in little-endian terms, */
/* because we may not know to reverse it yet. */
sampleChannelPtr->offset = sampleByteOffset;
sampleChannelPtr->size = sampleByteLength;
/* Assume these are all the same. */
*wordBytes = sampleByteLength;
}
}
}
return result;
}

View File

@ -0,0 +1,97 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @~English
* @brief Utilities for printing data format descriptors.
*/
/*
* Author: Andrew Garrard
*/
#include <stdio.h>
#include <KHR/khr_df.h>
#include "dfd.h"
/**
* @~English
* @brief Print a human-readable interpretation of a data format descriptor.
*
* @param DFD Pointer to a data format descriptor.
**/
void printDFD(uint32_t *DFD)
{
uint32_t *BDB = DFD+1;
int samples = (KHR_DFDVAL(BDB, DESCRIPTORBLOCKSIZE) - 4 * KHR_DF_WORD_SAMPLESTART) / (4 * KHR_DF_WORD_SAMPLEWORDS);
int sample;
int model = KHR_DFDVAL(BDB, MODEL);
printf("DFD total bytes: %d\n", DFD[0]);
printf("BDB descriptor type 0x%04x vendor id = 0x%05x\n",
KHR_DFDVAL(BDB, DESCRIPTORTYPE),
KHR_DFDVAL(BDB, VENDORID));
printf("Descriptor block size %d (%d samples) versionNumber = 0x%04x\n",
KHR_DFDVAL(BDB, DESCRIPTORBLOCKSIZE),
samples,
KHR_DFDVAL(BDB, VERSIONNUMBER));
printf("Flags 0x%02x Xfer %02d Primaries %02d Model %03d\n",
KHR_DFDVAL(BDB, FLAGS),
KHR_DFDVAL(BDB, TRANSFER),
KHR_DFDVAL(BDB, PRIMARIES),
model);
printf("Dimensions: %d,%d,%d,%d\n",
KHR_DFDVAL(BDB, TEXELBLOCKDIMENSION0) + 1,
KHR_DFDVAL(BDB, TEXELBLOCKDIMENSION1) + 1,
KHR_DFDVAL(BDB, TEXELBLOCKDIMENSION2) + 1,
KHR_DFDVAL(BDB, TEXELBLOCKDIMENSION3) + 1);
printf("Plane bytes: %d,%d,%d,%d,%d,%d,%d,%d\n",
KHR_DFDVAL(BDB, BYTESPLANE0),
KHR_DFDVAL(BDB, BYTESPLANE1),
KHR_DFDVAL(BDB, BYTESPLANE2),
KHR_DFDVAL(BDB, BYTESPLANE3),
KHR_DFDVAL(BDB, BYTESPLANE4),
KHR_DFDVAL(BDB, BYTESPLANE5),
KHR_DFDVAL(BDB, BYTESPLANE6),
KHR_DFDVAL(BDB, BYTESPLANE7));
for (sample = 0; sample < samples; ++sample) {
int channelId = KHR_DFDSVAL(BDB, sample, CHANNELID);
printf(" Sample %d\n", sample);
printf("Qualifiers %x", KHR_DFDSVAL(BDB, sample, QUALIFIERS) >> 4);
printf(" Channel 0x%x", channelId);
if (model == KHR_DF_MODEL_UASTC) {
printf(" (%s)",
channelId == KHR_DF_CHANNEL_UASTC_RRRG ? "RRRG"
: channelId == KHR_DF_CHANNEL_UASTC_RGBA ? "RGBA"
: channelId == KHR_DF_CHANNEL_UASTC_RRR ? "RRR"
: channelId == KHR_DF_CHANNEL_UASTC_RGB ? "RGB"
: channelId == KHR_DF_CHANNEL_UASTC_RG ? "RG"
: "unknown");
} else if (model == KHR_DF_MODEL_ETC1S) {
printf(" (%s)",
channelId == KHR_DF_CHANNEL_ETC1S_AAA ? "AAA"
: channelId == KHR_DF_CHANNEL_ETC1S_GGG ? "GGG"
: channelId == KHR_DF_CHANNEL_ETC1S_RRR ? "RRR"
: channelId == KHR_DF_CHANNEL_ETC1S_RGB ? "RGB"
: "unknown");
} else {
printf(" (%c)",
"RGB3456789abcdeA"[channelId]);
}
printf(" Length %d bits Offset %d\n",
KHR_DFDSVAL(BDB, sample, BITLENGTH) + 1,
KHR_DFDSVAL(BDB, sample, BITOFFSET));
printf("Position: %d,%d,%d,%d\n",
KHR_DFDSVAL(BDB, sample, SAMPLEPOSITION0),
KHR_DFDSVAL(BDB, sample, SAMPLEPOSITION1),
KHR_DFDSVAL(BDB, sample, SAMPLEPOSITION2),
KHR_DFDSVAL(BDB, sample, SAMPLEPOSITION3));
printf("Lower 0x%08x\nUpper 0x%08x\n",
KHR_DFDSVAL(BDB, sample, SAMPLELOWER),
KHR_DFDSVAL(BDB, sample, SAMPLEUPPER));
}
}

146
thirdparty/libktx/lib/dfdutils/queries.c vendored Normal file
View File

@ -0,0 +1,146 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @~English
* @brief Utilities for querying info from a data format descriptor.
* @author Mark Callow
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <KHR/khr_df.h>
#include "dfd.h"
/**
* @~English
* @brief Get the number and size of the image components from a DFD.
*
* This simplified function is for use only with the DFDs for unpacked
* formats which means all components have the same size.
*
* @param DFD Pointer to a Data Format Descriptor to interpret,
described as 32-bit words in native endianness.
Note that this is the whole descriptor, not just
the basic descriptor block.
* @param numComponents pointer to a 32-bit word in which the number of
components will be written.
* @param componentByteLength pointer to a 32-bit word in which the size of
a component in bytes will be written.
*/
void
getDFDComponentInfoUnpacked(const uint32_t* DFD, uint32_t* numComponents,
uint32_t* componentByteLength)
{
const uint32_t *BDFDB = DFD+1;
uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
uint32_t sampleCounter;
uint32_t currentChannel = ~0U; /* Don't start matched. */
/* This is specifically for unpacked formats which means the size of */
/* each component is the same. */
*numComponents = 0;
for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
uint32_t sampleByteLength = (KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1) >> 3U;
uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID);
if (sampleChannel == currentChannel) {
/* Continuation of the same channel. */
/* Accumulate the byte length. */
*componentByteLength += sampleByteLength;
} else {
/* Everything is new. Hopefully. */
currentChannel = sampleChannel;
(*numComponents)++;
*componentByteLength = sampleByteLength;
}
}
}
/**
* @~English
* @brief Return the number of "components" in the data.
*
* Calculates the number of uniques samples in the DFD by combining
* multiple samples for the same channel. For uncompressed colorModels
* this is the same as the number of components in the image data. For
* block-compressed color models this is the number of samples in
* the color model, typically 1 and in a few cases 2.
*
* @param DFD Pointer to a Data Format Descriptor for which,
* described as 32-bit words in native endianness.
* Note that this is the whole descriptor, not just
* the basic descriptor block.
*/
uint32_t getDFDNumComponents(const uint32_t* DFD)
{
const uint32_t *BDFDB = DFD+1;
uint32_t currentChannel = ~0U; /* Don't start matched. */
uint32_t numComponents = 0;
uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
uint32_t sampleCounter;
for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID);
if (sampleChannel != currentChannel) {
numComponents++;
currentChannel = sampleChannel;
}
}
return numComponents;
}
/**
* @~English
* @brief Recreate the value of bytesPlane0 from sample info.
*
* This can be use to recreate the value of bytesPlane0 for data that
* has been variable-rate compressed so has bytesPlane0 = 0. For DFDs
* that are valid for KTX files. Little-endian data only and no multi-plane
* formats.
*
* @param DFD Pointer to a Data Format Descriptor for which,
* described as 32-bit words in native endianness.
* Note that this is the whole descriptor, not just
* the basic descriptor block.
* @param bytesPlane0 pointer to a 32-bit word in which the recreated
* value of bytesPlane0 will be written.
*/
void
recreateBytesPlane0FromSampleInfo(const uint32_t* DFD, uint32_t* bytesPlane0)
{
const uint32_t *BDFDB = DFD+1;
uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
uint32_t sampleCounter;
uint32_t bitsPlane0 = 0;
uint32_t* bitOffsets = malloc(sizeof(uint32_t) * numSamples);
memset(bitOffsets, -1, sizeof(uint32_t) * numSamples);
for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
uint32_t sampleBitOffset = KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET);
/* The sample bitLength field stores the bit length - 1. */
uint32_t sampleBitLength = KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1;
uint32_t i;
for (i = 0; i < numSamples; i++) {
if (sampleBitOffset == bitOffsets[i]) {
// This sample is being repeated as in e.g. RGB9E5.
break;
}
}
if (i == numSamples) {
// Previously unseen bitOffset. Bump size.
bitsPlane0 += sampleBitLength;
bitOffsets[sampleCounter] = sampleBitOffset;
}
}
free(bitOffsets);
*bytesPlane0 = bitsPlane0 >> 3U;
}

34
thirdparty/libktx/lib/dfdutils/vk2dfd.c vendored Normal file
View File

@ -0,0 +1,34 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* Copyright 2019-2020 Mark Callow
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @~English
* @brief Create a DFD for a VkFormat.
*/
#include "dfd.h"
/**
* @~English
* @brief Create a DFD matching a VkFormat.
*
* @param[in] format VkFormat for which to create a DFD.
*
* @return pointer to the created DFD or 0 if format not supported or
* unrecognized. Caller is responsible for freeing the created
* DFD.
*/
uint32_t*
vk2dfd(enum VkFormat format)
{
switch (format) {
#include "vk2dfd.inl"
default: return 0;
}
}

View File

@ -0,0 +1,340 @@
/* Copyright 2019-2020 The Khronos Group Inc. */
/* SPDX-License-Identifier: Apache-2.0 */
/***************************** Do not edit. *****************************
Automatically generated by makevk2dfd.pl.
*************************************************************************/
/* Vulkan combined depth & stencil formats are not included here
* because they do not exist outside a Vulkan device.
*/
case VK_FORMAT_R4G4_UNORM_PACK8: {
int channels[] = {1,0}; int bits[] = {4,4};
return createDFDPacked(0, 2, bits, channels, s_UNORM);
}
case VK_FORMAT_R4G4B4A4_UNORM_PACK16: {
int channels[] = {3,2,1,0}; int bits[] = {4,4,4,4};
return createDFDPacked(0, 4, bits, channels, s_UNORM);
}
case VK_FORMAT_B4G4R4A4_UNORM_PACK16: {
int channels[] = {3,0,1,2}; int bits[] = {4,4,4,4};
return createDFDPacked(0, 4, bits, channels, s_UNORM);
}
case VK_FORMAT_R5G6B5_UNORM_PACK16: {
int channels[] = {2,1,0}; int bits[] = {5,6,5};
return createDFDPacked(0, 3, bits, channels, s_UNORM);
}
case VK_FORMAT_B5G6R5_UNORM_PACK16: {
int channels[] = {0,1,2}; int bits[] = {5,6,5};
return createDFDPacked(0, 3, bits, channels, s_UNORM);
}
case VK_FORMAT_R5G5B5A1_UNORM_PACK16: {
int channels[] = {3,2,1,0}; int bits[] = {1,5,5,5};
return createDFDPacked(0, 4, bits, channels, s_UNORM);
}
case VK_FORMAT_B5G5R5A1_UNORM_PACK16: {
int channels[] = {3,0,1,2}; int bits[] = {1,5,5,5};
return createDFDPacked(0, 4, bits, channels, s_UNORM);
}
case VK_FORMAT_A1R5G5B5_UNORM_PACK16: {
int channels[] = {2,1,0,3}; int bits[] = {5,5,5,1};
return createDFDPacked(0, 4, bits, channels, s_UNORM);
}
case VK_FORMAT_R8_UNORM: return createDFDUnpacked(0, 1, 1, 0, s_UNORM);
case VK_FORMAT_R8_SNORM: return createDFDUnpacked(0, 1, 1, 0, s_SNORM);
case VK_FORMAT_R8_USCALED: return createDFDUnpacked(0, 1, 1, 0, s_USCALED);
case VK_FORMAT_R8_SSCALED: return createDFDUnpacked(0, 1, 1, 0, s_SSCALED);
case VK_FORMAT_R8_UINT: return createDFDUnpacked(0, 1, 1, 0, s_UINT);
case VK_FORMAT_R8_SINT: return createDFDUnpacked(0, 1, 1, 0, s_SINT);
case VK_FORMAT_R8_SRGB: return createDFDUnpacked(0, 1, 1, 0, s_SRGB);
case VK_FORMAT_R8G8_UNORM: return createDFDUnpacked(0, 2, 1, 0, s_UNORM);
case VK_FORMAT_R8G8_SNORM: return createDFDUnpacked(0, 2, 1, 0, s_SNORM);
case VK_FORMAT_R8G8_USCALED: return createDFDUnpacked(0, 2, 1, 0, s_USCALED);
case VK_FORMAT_R8G8_SSCALED: return createDFDUnpacked(0, 2, 1, 0, s_SSCALED);
case VK_FORMAT_R8G8_UINT: return createDFDUnpacked(0, 2, 1, 0, s_UINT);
case VK_FORMAT_R8G8_SINT: return createDFDUnpacked(0, 2, 1, 0, s_SINT);
case VK_FORMAT_R8G8_SRGB: return createDFDUnpacked(0, 2, 1, 0, s_SRGB);
case VK_FORMAT_R8G8B8_UNORM: return createDFDUnpacked(0, 3, 1, 0, s_UNORM);
case VK_FORMAT_R8G8B8_SNORM: return createDFDUnpacked(0, 3, 1, 0, s_SNORM);
case VK_FORMAT_R8G8B8_USCALED: return createDFDUnpacked(0, 3, 1, 0, s_USCALED);
case VK_FORMAT_R8G8B8_SSCALED: return createDFDUnpacked(0, 3, 1, 0, s_SSCALED);
case VK_FORMAT_R8G8B8_UINT: return createDFDUnpacked(0, 3, 1, 0, s_UINT);
case VK_FORMAT_R8G8B8_SINT: return createDFDUnpacked(0, 3, 1, 0, s_SINT);
case VK_FORMAT_R8G8B8_SRGB: return createDFDUnpacked(0, 3, 1, 0, s_SRGB);
case VK_FORMAT_B8G8R8_UNORM: return createDFDUnpacked(0, 3, 1, 1, s_UNORM);
case VK_FORMAT_B8G8R8_SNORM: return createDFDUnpacked(0, 3, 1, 1, s_SNORM);
case VK_FORMAT_B8G8R8_USCALED: return createDFDUnpacked(0, 3, 1, 1, s_USCALED);
case VK_FORMAT_B8G8R8_SSCALED: return createDFDUnpacked(0, 3, 1, 1, s_SSCALED);
case VK_FORMAT_B8G8R8_UINT: return createDFDUnpacked(0, 3, 1, 1, s_UINT);
case VK_FORMAT_B8G8R8_SINT: return createDFDUnpacked(0, 3, 1, 1, s_SINT);
case VK_FORMAT_B8G8R8_SRGB: return createDFDUnpacked(0, 3, 1, 1, s_SRGB);
case VK_FORMAT_R8G8B8A8_UNORM: return createDFDUnpacked(0, 4, 1, 0, s_UNORM);
case VK_FORMAT_R8G8B8A8_SNORM: return createDFDUnpacked(0, 4, 1, 0, s_SNORM);
case VK_FORMAT_R8G8B8A8_USCALED: return createDFDUnpacked(0, 4, 1, 0, s_USCALED);
case VK_FORMAT_R8G8B8A8_SSCALED: return createDFDUnpacked(0, 4, 1, 0, s_SSCALED);
case VK_FORMAT_R8G8B8A8_UINT: return createDFDUnpacked(0, 4, 1, 0, s_UINT);
case VK_FORMAT_R8G8B8A8_SINT: return createDFDUnpacked(0, 4, 1, 0, s_SINT);
case VK_FORMAT_R8G8B8A8_SRGB: return createDFDUnpacked(0, 4, 1, 0, s_SRGB);
case VK_FORMAT_B8G8R8A8_UNORM: return createDFDUnpacked(0, 4, 1, 1, s_UNORM);
case VK_FORMAT_B8G8R8A8_SNORM: return createDFDUnpacked(0, 4, 1, 1, s_SNORM);
case VK_FORMAT_B8G8R8A8_USCALED: return createDFDUnpacked(0, 4, 1, 1, s_USCALED);
case VK_FORMAT_B8G8R8A8_SSCALED: return createDFDUnpacked(0, 4, 1, 1, s_SSCALED);
case VK_FORMAT_B8G8R8A8_UINT: return createDFDUnpacked(0, 4, 1, 1, s_UINT);
case VK_FORMAT_B8G8R8A8_SINT: return createDFDUnpacked(0, 4, 1, 1, s_SINT);
case VK_FORMAT_B8G8R8A8_SRGB: return createDFDUnpacked(0, 4, 1, 1, s_SRGB);
case VK_FORMAT_A8B8G8R8_UNORM_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
return createDFDPacked(0, 4, bits, channels, s_UNORM);
}
case VK_FORMAT_A8B8G8R8_SNORM_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
return createDFDPacked(0, 4, bits, channels, s_SNORM);
}
case VK_FORMAT_A8B8G8R8_USCALED_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
return createDFDPacked(0, 4, bits, channels, s_USCALED);
}
case VK_FORMAT_A8B8G8R8_SSCALED_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
return createDFDPacked(0, 4, bits, channels, s_SSCALED);
}
case VK_FORMAT_A8B8G8R8_UINT_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
return createDFDPacked(0, 4, bits, channels, s_UINT);
}
case VK_FORMAT_A8B8G8R8_SINT_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
return createDFDPacked(0, 4, bits, channels, s_SINT);
}
case VK_FORMAT_A8B8G8R8_SRGB_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
return createDFDPacked(0, 4, bits, channels, s_SRGB);
}
case VK_FORMAT_A2R10G10B10_UNORM_PACK32: {
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_UNORM);
}
case VK_FORMAT_A2R10G10B10_SNORM_PACK32: {
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_SNORM);
}
case VK_FORMAT_A2R10G10B10_USCALED_PACK32: {
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_USCALED);
}
case VK_FORMAT_A2R10G10B10_SSCALED_PACK32: {
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_SSCALED);
}
case VK_FORMAT_A2R10G10B10_UINT_PACK32: {
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_UINT);
}
case VK_FORMAT_A2R10G10B10_SINT_PACK32: {
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_SINT);
}
case VK_FORMAT_A2B10G10R10_UNORM_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_UNORM);
}
case VK_FORMAT_A2B10G10R10_SNORM_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_SNORM);
}
case VK_FORMAT_A2B10G10R10_USCALED_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_USCALED);
}
case VK_FORMAT_A2B10G10R10_SSCALED_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_SSCALED);
}
case VK_FORMAT_A2B10G10R10_UINT_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_UINT);
}
case VK_FORMAT_A2B10G10R10_SINT_PACK32: {
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
return createDFDPacked(0, 4, bits, channels, s_SINT);
}
case VK_FORMAT_R16_UNORM: return createDFDUnpacked(0, 1, 2, 0, s_UNORM);
case VK_FORMAT_R16_SNORM: return createDFDUnpacked(0, 1, 2, 0, s_SNORM);
case VK_FORMAT_R16_USCALED: return createDFDUnpacked(0, 1, 2, 0, s_USCALED);
case VK_FORMAT_R16_SSCALED: return createDFDUnpacked(0, 1, 2, 0, s_SSCALED);
case VK_FORMAT_R16_UINT: return createDFDUnpacked(0, 1, 2, 0, s_UINT);
case VK_FORMAT_R16_SINT: return createDFDUnpacked(0, 1, 2, 0, s_SINT);
case VK_FORMAT_R16_SFLOAT: return createDFDUnpacked(0, 1, 2, 0, s_SFLOAT);
case VK_FORMAT_R16G16_UNORM: return createDFDUnpacked(0, 2, 2, 0, s_UNORM);
case VK_FORMAT_R16G16_SNORM: return createDFDUnpacked(0, 2, 2, 0, s_SNORM);
case VK_FORMAT_R16G16_USCALED: return createDFDUnpacked(0, 2, 2, 0, s_USCALED);
case VK_FORMAT_R16G16_SSCALED: return createDFDUnpacked(0, 2, 2, 0, s_SSCALED);
case VK_FORMAT_R16G16_UINT: return createDFDUnpacked(0, 2, 2, 0, s_UINT);
case VK_FORMAT_R16G16_SINT: return createDFDUnpacked(0, 2, 2, 0, s_SINT);
case VK_FORMAT_R16G16_SFLOAT: return createDFDUnpacked(0, 2, 2, 0, s_SFLOAT);
case VK_FORMAT_R16G16B16_UNORM: return createDFDUnpacked(0, 3, 2, 0, s_UNORM);
case VK_FORMAT_R16G16B16_SNORM: return createDFDUnpacked(0, 3, 2, 0, s_SNORM);
case VK_FORMAT_R16G16B16_USCALED: return createDFDUnpacked(0, 3, 2, 0, s_USCALED);
case VK_FORMAT_R16G16B16_SSCALED: return createDFDUnpacked(0, 3, 2, 0, s_SSCALED);
case VK_FORMAT_R16G16B16_UINT: return createDFDUnpacked(0, 3, 2, 0, s_UINT);
case VK_FORMAT_R16G16B16_SINT: return createDFDUnpacked(0, 3, 2, 0, s_SINT);
case VK_FORMAT_R16G16B16_SFLOAT: return createDFDUnpacked(0, 3, 2, 0, s_SFLOAT);
case VK_FORMAT_R16G16B16A16_UNORM: return createDFDUnpacked(0, 4, 2, 0, s_UNORM);
case VK_FORMAT_R16G16B16A16_SNORM: return createDFDUnpacked(0, 4, 2, 0, s_SNORM);
case VK_FORMAT_R16G16B16A16_USCALED: return createDFDUnpacked(0, 4, 2, 0, s_USCALED);
case VK_FORMAT_R16G16B16A16_SSCALED: return createDFDUnpacked(0, 4, 2, 0, s_SSCALED);
case VK_FORMAT_R16G16B16A16_UINT: return createDFDUnpacked(0, 4, 2, 0, s_UINT);
case VK_FORMAT_R16G16B16A16_SINT: return createDFDUnpacked(0, 4, 2, 0, s_SINT);
case VK_FORMAT_R16G16B16A16_SFLOAT: return createDFDUnpacked(0, 4, 2, 0, s_SFLOAT);
case VK_FORMAT_R32_UINT: return createDFDUnpacked(0, 1, 4, 0, s_UINT);
case VK_FORMAT_R32_SINT: return createDFDUnpacked(0, 1, 4, 0, s_SINT);
case VK_FORMAT_R32_SFLOAT: return createDFDUnpacked(0, 1, 4, 0, s_SFLOAT);
case VK_FORMAT_R32G32_UINT: return createDFDUnpacked(0, 2, 4, 0, s_UINT);
case VK_FORMAT_R32G32_SINT: return createDFDUnpacked(0, 2, 4, 0, s_SINT);
case VK_FORMAT_R32G32_SFLOAT: return createDFDUnpacked(0, 2, 4, 0, s_SFLOAT);
case VK_FORMAT_R32G32B32_UINT: return createDFDUnpacked(0, 3, 4, 0, s_UINT);
case VK_FORMAT_R32G32B32_SINT: return createDFDUnpacked(0, 3, 4, 0, s_SINT);
case VK_FORMAT_R32G32B32_SFLOAT: return createDFDUnpacked(0, 3, 4, 0, s_SFLOAT);
case VK_FORMAT_R32G32B32A32_UINT: return createDFDUnpacked(0, 4, 4, 0, s_UINT);
case VK_FORMAT_R32G32B32A32_SINT: return createDFDUnpacked(0, 4, 4, 0, s_SINT);
case VK_FORMAT_R32G32B32A32_SFLOAT: return createDFDUnpacked(0, 4, 4, 0, s_SFLOAT);
case VK_FORMAT_R64_UINT: return createDFDUnpacked(0, 1, 8, 0, s_UINT);
case VK_FORMAT_R64_SINT: return createDFDUnpacked(0, 1, 8, 0, s_SINT);
case VK_FORMAT_R64_SFLOAT: return createDFDUnpacked(0, 1, 8, 0, s_SFLOAT);
case VK_FORMAT_R64G64_UINT: return createDFDUnpacked(0, 2, 8, 0, s_UINT);
case VK_FORMAT_R64G64_SINT: return createDFDUnpacked(0, 2, 8, 0, s_SINT);
case VK_FORMAT_R64G64_SFLOAT: return createDFDUnpacked(0, 2, 8, 0, s_SFLOAT);
case VK_FORMAT_R64G64B64_UINT: return createDFDUnpacked(0, 3, 8, 0, s_UINT);
case VK_FORMAT_R64G64B64_SINT: return createDFDUnpacked(0, 3, 8, 0, s_SINT);
case VK_FORMAT_R64G64B64_SFLOAT: return createDFDUnpacked(0, 3, 8, 0, s_SFLOAT);
case VK_FORMAT_R64G64B64A64_UINT: return createDFDUnpacked(0, 4, 8, 0, s_UINT);
case VK_FORMAT_R64G64B64A64_SINT: return createDFDUnpacked(0, 4, 8, 0, s_SINT);
case VK_FORMAT_R64G64B64A64_SFLOAT: return createDFDUnpacked(0, 4, 8, 0, s_SFLOAT);
case VK_FORMAT_B10G11R11_UFLOAT_PACK32: {
int channels[] = {0,1,2}; int bits[] = {11,11,10};
return createDFDPacked(0, 3, bits, channels, s_UFLOAT);
}
case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: {
int bits[] = {0}; int channels[] = {0};
return createDFDPacked(0, 6, bits, channels, s_UFLOAT);
}
case VK_FORMAT_D16_UNORM: return createDFDDepthStencil(16,0,2);
case VK_FORMAT_X8_D24_UNORM_PACK32: return createDFDDepthStencil(24,0,4);
case VK_FORMAT_D32_SFLOAT: return createDFDDepthStencil(32,0,4);
case VK_FORMAT_S8_UINT: return createDFDDepthStencil(0,8,1);
case VK_FORMAT_BC1_RGB_UNORM_BLOCK: return createDFDCompressed(c_BC1_RGB, 4, 4, 1, s_UNORM);
case VK_FORMAT_BC1_RGB_SRGB_BLOCK: return createDFDCompressed(c_BC1_RGB, 4, 4, 1, s_SRGB);
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return createDFDCompressed(c_BC1_RGBA, 4, 4, 1, s_UNORM);
case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: return createDFDCompressed(c_BC1_RGBA, 4, 4, 1, s_SRGB);
case VK_FORMAT_BC2_UNORM_BLOCK: return createDFDCompressed(c_BC2, 4, 4, 1, s_UNORM);
case VK_FORMAT_BC2_SRGB_BLOCK: return createDFDCompressed(c_BC2, 4, 4, 1, s_SRGB);
case VK_FORMAT_BC3_UNORM_BLOCK: return createDFDCompressed(c_BC3, 4, 4, 1, s_UNORM);
case VK_FORMAT_BC3_SRGB_BLOCK: return createDFDCompressed(c_BC3, 4, 4, 1, s_SRGB);
case VK_FORMAT_BC4_UNORM_BLOCK: return createDFDCompressed(c_BC4, 4, 4, 1, s_UNORM);
case VK_FORMAT_BC4_SNORM_BLOCK: return createDFDCompressed(c_BC4, 4, 4, 1, s_SNORM);
case VK_FORMAT_BC5_UNORM_BLOCK: return createDFDCompressed(c_BC5, 4, 4, 1, s_UNORM);
case VK_FORMAT_BC5_SNORM_BLOCK: return createDFDCompressed(c_BC5, 4, 4, 1, s_SNORM);
case VK_FORMAT_BC6H_UFLOAT_BLOCK: return createDFDCompressed(c_BC6H, 4, 4, 1, s_UFLOAT);
case VK_FORMAT_BC6H_SFLOAT_BLOCK: return createDFDCompressed(c_BC6H, 4, 4, 1, s_SFLOAT);
case VK_FORMAT_BC7_UNORM_BLOCK: return createDFDCompressed(c_BC7, 4, 4, 1, s_UNORM);
case VK_FORMAT_BC7_SRGB_BLOCK: return createDFDCompressed(c_BC7, 4, 4, 1, s_SRGB);
case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8, 4, 4, 1, s_UNORM);
case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8, 4, 4, 1, s_SRGB);
case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8A1, 4, 4, 1, s_UNORM);
case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8A1, 4, 4, 1, s_SRGB);
case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8A8, 4, 4, 1, s_UNORM);
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8A8, 4, 4, 1, s_SRGB);
case VK_FORMAT_EAC_R11_UNORM_BLOCK: return createDFDCompressed(c_EAC_R11, 4, 4, 1, s_UNORM);
case VK_FORMAT_EAC_R11_SNORM_BLOCK: return createDFDCompressed(c_EAC_R11, 4, 4, 1, s_SNORM);
case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: return createDFDCompressed(c_EAC_R11G11, 4, 4, 1, s_UNORM);
case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: return createDFDCompressed(c_EAC_R11G11, 4, 4, 1, s_SNORM);
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 4, 4, 1, s_UNORM);
case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 4, 4, 1, s_SRGB);
case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 5, 4, 1, s_UNORM);
case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 5, 4, 1, s_SRGB);
case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 5, 5, 1, s_UNORM);
case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 5, 5, 1, s_SRGB);
case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 6, 5, 1, s_UNORM);
case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 6, 5, 1, s_SRGB);
case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 6, 6, 1, s_UNORM);
case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 6, 6, 1, s_SRGB);
case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 8, 5, 1, s_UNORM);
case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 8, 5, 1, s_SRGB);
case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 8, 6, 1, s_UNORM);
case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 8, 6, 1, s_SRGB);
case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 8, 8, 1, s_UNORM);
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 8, 8, 1, s_SRGB);
case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 10, 5, 1, s_UNORM);
case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 10, 5, 1, s_SRGB);
case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 10, 6, 1, s_UNORM);
case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 10, 6, 1, s_SRGB);
case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 10, 8, 1, s_UNORM);
case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 10, 8, 1, s_SRGB);
case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 10, 10, 1, s_UNORM);
case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 10, 10, 1, s_SRGB);
case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 12, 10, 1, s_UNORM);
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 12, 10, 1, s_SRGB);
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 12, 12, 1, s_UNORM);
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 12, 12, 1, s_SRGB);
case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: return createDFDCompressed(c_PVRTC, 8, 4, 1, s_UNORM);
case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: return createDFDCompressed(c_PVRTC, 4, 4, 1, s_UNORM);
case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: return createDFDCompressed(c_PVRTC2, 8, 4, 1, s_UNORM);
case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: return createDFDCompressed(c_PVRTC2, 4, 4, 1, s_UNORM);
case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: return createDFDCompressed(c_PVRTC, 8, 4, 1, s_SRGB);
case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: return createDFDCompressed(c_PVRTC, 4, 4, 1, s_SRGB);
case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: return createDFDCompressed(c_PVRTC2, 8, 4, 1, s_SRGB);
case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: return createDFDCompressed(c_PVRTC2, 4, 4, 1, s_SRGB);
case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 4, 4, 1, s_SFLOAT);
case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 5, 4, 1, s_SFLOAT);
case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 5, 5, 1, s_SFLOAT);
case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 5, 1, s_SFLOAT);
case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 1, s_SFLOAT);
case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 8, 5, 1, s_SFLOAT);
case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 8, 6, 1, s_SFLOAT);
case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 8, 8, 1, s_SFLOAT);
case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 10, 5, 1, s_SFLOAT);
case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 10, 6, 1, s_SFLOAT);
case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 10, 8, 1, s_SFLOAT);
case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 10, 10, 1, s_SFLOAT);
case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 12, 10, 1, s_SFLOAT);
case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 12, 12, 1, s_SFLOAT);
#if 0
case VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 3, 3, 3, s_UNORM);
case VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 3, 3, 3, s_SRGB);
case VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 3, 3, 3, s_SFLOAT);
case VK_FORMAT_ASTC_4x3x3_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 4, 3, 3, s_UNORM);
case VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 4, 3, 3, s_SRGB);
case VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 4, 3, 3, s_SFLOAT);
case VK_FORMAT_ASTC_4x4x3_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 4, 4, 3, s_UNORM);
case VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 4, 4, 3, s_SRGB);
case VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 4, 4, 3, s_SFLOAT);
case VK_FORMAT_ASTC_4x4x4_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 4, 4, 4, s_UNORM);
case VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 4, 4, 4, s_SRGB);
case VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 4, 4, 4, s_SFLOAT);
case VK_FORMAT_ASTC_5x4x4_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 5, 4, 4, s_UNORM);
case VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 5, 4, 4, s_SRGB);
case VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 5, 4, 4, s_SFLOAT);
case VK_FORMAT_ASTC_5x5x4_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 5, 5, 4, s_UNORM);
case VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 5, 5, 4, s_SRGB);
case VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 5, 5, 4, s_SFLOAT);
case VK_FORMAT_ASTC_5x5x5_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 5, 5, 5, s_UNORM);
case VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 5, 5, 5, s_SRGB);
case VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 5, 5, 5, s_SFLOAT);
case VK_FORMAT_ASTC_6x5x5_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 5, 5, s_UNORM);
case VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 5, 5, s_SRGB);
case VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 5, 5, s_SFLOAT);
case VK_FORMAT_ASTC_6x6x5_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 5, s_UNORM);
case VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 5, s_SRGB);
case VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 5, s_SFLOAT);
case VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 6, s_UNORM);
case VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 6, s_SRGB);
case VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 6, s_SFLOAT);
#endif
case VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT: {
int channels[] = {2,1,0,3}; int bits[] = {4,4,4,4};
return createDFDPacked(0, 4, bits, channels, s_UNORM);
}
case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT: {
int channels[] = {0,1,2,3}; int bits[] = {4,4,4,4};
return createDFDPacked(0, 4, bits, channels, s_UNORM);
}

393
thirdparty/libktx/lib/filestream.c vendored Normal file
View File

@ -0,0 +1,393 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2010-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @~English
*
* @brief Implementation of ktxStream for FILE.
*
* @author Maksim Kolesin, Under Development
* @author Georg Kolling, Imagination Technology
* @author Mark Callow, HI Corporation
*/
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <string.h>
/* I need these on Linux. Why? */
#define __USE_LARGEFILE 1 // For declaration of ftello, etc.
#define __USE_POSIX 1 // For declaration of fileno.
#define _POSIX_SOURCE 1 // For both the above in Emscripten.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> // For stat.h on Windows
#define __USE_MISC 1 // For declaration of S_IF...
#include <sys/stat.h>
#include "ktx.h"
#include "ktxint.h"
#include "filestream.h"
// Gotta love Windows :-(
#if defined(_MSC_VER)
#if defined(_WIN64)
#define ftello _ftelli64
#define fseeko _fseeki64
#else
#define ftello ftell
#define fseeko fseek
#endif
#define fileno _fileno
#define fstat _fstat
#define stat _stat
#define S_IFIFO _S_IFIFO
#define S_IFSOCK 0xC000
typedef unsigned short mode_t;
#endif
#if defined(__MINGW32__)
#define S_IFSOCK 0xC000
#endif
#define KTX_FILE_STREAM_MAX (1 << (sizeof(ktx_off_t) - 1) - 1)
/**
* @~English
* @brief Read bytes from a ktxFileStream.
*
* @param [in] str pointer to the ktxStream from which to read.
* @param [out] dst pointer to a block of memory with a size
* of at least @p size bytes, converted to a void*.
* @param [in,out] count pointer to total count of bytes to be read.
* On completion set to number of bytes read.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_INVALID_VALUE @p dst is @c NULL or @p src is @c NULL.
* @exception KTX_FILE_READ_ERROR an error occurred while reading the file.
* @exception KTX_FILE_UNEXPECTED_EOF not enough data to satisfy the request.
*/
static
KTX_error_code ktxFileStream_read(ktxStream* str, void* dst, const ktx_size_t count)
{
ktx_size_t nread;
if (!str || !dst)
return KTX_INVALID_VALUE;
assert(str->type == eStreamTypeFile);
if ((nread = fread(dst, 1, count, str->data.file)) != count) {
if (feof(str->data.file)) {
return KTX_FILE_UNEXPECTED_EOF;
} else {
return KTX_FILE_READ_ERROR;
}
}
str->readpos += count;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Skip bytes in a ktxFileStream.
*
* @param [in] str pointer to a ktxStream object.
* @param [in] count number of bytes to be skipped.
*
* In order to support applications reading from stdin, read characters
* rather than using seek functions.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_INVALID_VALUE @p str is @c NULL or @p count is less than zero.
* @exception KTX_INVALID_OPERATION skipping @p count bytes would go beyond EOF.
* @exception KTX_FILE_READ_ERROR an error occurred while reading the file.
* @exception KTX_FILE_UNEXPECTED_EOF not enough data to satisfy the request.
* @p count is set to the number of bytes
* skipped.
*/
static
KTX_error_code ktxFileStream_skip(ktxStream* str, const ktx_size_t count)
{
if (!str)
return KTX_INVALID_VALUE;
assert(str->type == eStreamTypeFile);
for (ktx_uint32_t i = 0; i < count; i++) {
int ret = getc(str->data.file);
if (ret == EOF) {
if (feof(str->data.file)) {
return KTX_FILE_UNEXPECTED_EOF;
} else {
return KTX_FILE_READ_ERROR;
}
}
}
str->readpos += count;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Write bytes to a ktxFileStream.
*
* @param [in] str pointer to the ktxStream that is the destination of the
* write.
* @param [in] src pointer to the array of elements to be written,
* converted to a const void*.
* @param [in] size size in bytes of each element to be written.
* @param [in] count number of elements, each one with a @p size of size
* bytes.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_INVALID_VALUE @p str is @c NULL or @p src is @c NULL.
* @exception KTX_FILE_OVERFLOW the requested write would caused the file to
* exceed the maximum supported file size.
* @exception KTX_FILE_WRITE_ERROR a system error occurred while writing the
* file.
*/
static
KTX_error_code ktxFileStream_write(ktxStream* str, const void *src,
const ktx_size_t size,
const ktx_size_t count)
{
if (!str || !src)
return KTX_INVALID_VALUE;
assert(str->type == eStreamTypeFile);
if (fwrite(src, size, count, str->data.file) != count) {
if (errno == EFBIG || errno == EOVERFLOW)
return KTX_FILE_OVERFLOW;
else
return KTX_FILE_WRITE_ERROR;
}
return KTX_SUCCESS;
}
/**
* @~English
* @brief Get the current read/write position in a ktxFileStream.
*
* @param [in] str pointer to the ktxStream to query.
* @param [in,out] off pointer to variable to receive the offset value.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_FILE_ISPIPE file descriptor underlying stream is associated
* with a pipe or FIFO so does not have a
* file-position indicator.
* @exception KTX_INVALID_VALUE @p str or @p pos is @c NULL.
*/
static
KTX_error_code ktxFileStream_getpos(ktxStream* str, ktx_off_t* pos)
{
ktx_off_t ftellval;
if (!str || !pos)
return KTX_INVALID_VALUE;
assert(str->type == eStreamTypeFile);
if (str->data.file == stdin) {
*pos = str->readpos;
} else {
/* The cast quiets an Xcode warning when building for "Generic iOS Device".
* I'm not sure why.
*/
ftellval = (ktx_off_t)ftello(str->data.file);
if (ftellval < 0) {
switch (errno) {
case ESPIPE: return KTX_FILE_ISPIPE;
case EOVERFLOW: return KTX_FILE_OVERFLOW;
}
}
*pos = ftellval;
}
return KTX_SUCCESS;
}
/**
* @~English
* @brief Set the current read/write position in a ktxFileStream.
*
* Offset of 0 is the start of the file. This function operates
* like Linux > 3.1's @c lseek() when it is passed a @c whence
* of @c SEEK_DATA as it returns an error if the seek would
* go beyond the end of the file.
*
* @param [in] str pointer to the ktxStream whose r/w position is to be set.
* @param [in] off pointer to the offset value to set.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* Throws the same exceptions as ktxFileStream_getsize() for the reasons given
* there plus the following:
*
* @exception KTX_INVALID_VALUE @p str is @c NULL.
* @exception KTX_INVALID_OPERATION @p pos is > the size of the file or an
* fseek error occurred.
*/
static
KTX_error_code ktxFileStream_setpos(ktxStream* str, ktx_off_t pos)
{
ktx_size_t fileSize;
KTX_error_code result;
if (!str)
return KTX_INVALID_VALUE;
assert(str->type == eStreamTypeFile);
if (str->data.file == stdin) {
if (pos > str->readpos)
return str->skip(str, pos - str->readpos);
else
return KTX_FILE_ISPIPE;
}
result = str->getsize(str, &fileSize);
if (result != KTX_SUCCESS) {
// Device is likely not seekable.
return result;
}
if (pos > (ktx_off_t)fileSize)
return KTX_INVALID_OPERATION;
if (fseeko(str->data.file, pos, SEEK_SET) < 0)
return KTX_FILE_SEEK_ERROR;
else
return KTX_SUCCESS;
}
/**
* @~English
* @brief Get the size of a ktxFileStream in bytes.
*
* @param [in] str pointer to the ktxStream whose size is to be queried.
* @param [in,out] size pointer to a variable in which size will be written.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_FILE_OVERFLOW size is too large to be returned in a
* @c ktx_size_t.
* @exception KTX_FILE_ISPIPE file descriptor underlying stream is associated
* with a pipe or FIFO so does not have a
* file-position indicator.
* @exception KTX_FILE_READ_ERROR a system error occurred while getting the
* size.
* @exception KTX_INVALID_VALUE @p str or @p size is @c NULL.
* @exception KTX_INVALID_OPERATION stream is a tty.
*/
static
KTX_error_code ktxFileStream_getsize(ktxStream* str, ktx_size_t* size)
{
struct stat statbuf;
int statret;
if (!str || !size)
return KTX_INVALID_VALUE;
assert(str->type == eStreamTypeFile);
// Need to flush so that fstat will return the current size.
// Can ignore return value. The only error that can happen is to tell you
// it was a NOP because the file is read only.
#if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(__MINGW64__) && !defined(_UCRT)
// Bug in VS2013 msvcrt. fflush on FILE open for READ changes file offset
// to 4096.
if (str->data.file->_flag & _IOWRT)
#endif
(void)fflush(str->data.file);
statret = fstat(fileno(str->data.file), &statbuf);
if (statret < 0) {
switch (errno) {
case EOVERFLOW: return KTX_FILE_OVERFLOW;
case EIO:
default:
return KTX_FILE_READ_ERROR;
}
}
mode_t ftype = statbuf.st_mode & S_IFMT;
if (ftype == S_IFIFO || ftype == S_IFSOCK)
return KTX_FILE_ISPIPE;
if (statbuf.st_mode & S_IFCHR)
return KTX_INVALID_OPERATION;
*size = (ktx_size_t)statbuf.st_size; /* See _getpos for why this cast. */
return KTX_SUCCESS;
}
/**
* @~English
* @brief Initialize a ktxFileStream.
*
* @param [in] str pointer to the ktxStream to initialize.
* @param [in] file pointer to the underlying FILE object.
* @param [in] closeFileOnDestruct if not false, stdio file pointer will be closed when ktxStream
* is destructed.
*
* @return KTX_SUCCESS on success, KTX_INVALID_VALUE on error.
*
* @exception KTX_INVALID_VALUE @p stream is @c NULL or @p file is @c NULL.
*/
KTX_error_code ktxFileStream_construct(ktxStream* str, FILE* file,
ktx_bool_t closeFileOnDestruct)
{
if (!str || !file)
return KTX_INVALID_VALUE;
str->data.file = file;
str->readpos = 0;
str->type = eStreamTypeFile;
str->read = ktxFileStream_read;
str->skip = ktxFileStream_skip;
str->write = ktxFileStream_write;
str->getpos = ktxFileStream_getpos;
str->setpos = ktxFileStream_setpos;
str->getsize = ktxFileStream_getsize;
str->destruct = ktxFileStream_destruct;
str->closeOnDestruct = closeFileOnDestruct;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Destruct the stream, potentially closing the underlying FILE.
*
* This only closes the underyling FILE if the @c closeOnDestruct parameter to
* ktxFileStream_construct() was not @c KTX_FALSE.
*
* @param [in] str pointer to the ktxStream whose FILE is to potentially
* be closed.
*/
void
ktxFileStream_destruct(ktxStream* str)
{
assert(str && str->type == eStreamTypeFile);
if (str->closeOnDestruct)
fclose(str->data.file);
str->data.file = 0;
}

27
thirdparty/libktx/lib/filestream.h vendored Normal file
View File

@ -0,0 +1,27 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2010-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Author: Maksim Kolesin from original code
* by Mark Callow and Georg Kolling
*/
#ifndef FILESTREAM_H
#define FILESTREAM_H
#include "ktx.h"
/*
* ktxFileInit: Initialize a ktxStream to a ktxFileStream with a FILE object
*/
KTX_error_code ktxFileStream_construct(ktxStream* str, FILE* file,
ktx_bool_t closeFileOnDestruct);
void ktxFileStream_destruct(ktxStream* str);
#endif /* FILESTREAM_H */

58
thirdparty/libktx/lib/formatsize.h vendored Normal file
View File

@ -0,0 +1,58 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file
* @~English
*
* @brief Struct for returning size information about an image format.
*
* @author Mark Callow, www.edgewise-consulting.com
*/
#ifndef _FORMATSIZE_H_
#define _FORMATSIZE_H_
#include "ktx.h"
typedef enum ktxFormatSizeFlagBits {
KTX_FORMAT_SIZE_PACKED_BIT = 0x00000001,
KTX_FORMAT_SIZE_COMPRESSED_BIT = 0x00000002,
KTX_FORMAT_SIZE_PALETTIZED_BIT = 0x00000004,
KTX_FORMAT_SIZE_DEPTH_BIT = 0x00000008,
KTX_FORMAT_SIZE_STENCIL_BIT = 0x00000010,
} ktxFormatSizeFlagBits;
typedef ktx_uint32_t ktxFormatSizeFlags;
/**
* @brief Structure for holding size information for a texture format.
*/
typedef struct ktxFormatSize {
ktxFormatSizeFlags flags;
unsigned int paletteSizeInBits; // For KTX1.
unsigned int blockSizeInBits;
unsigned int blockWidth; // in texels
unsigned int blockHeight; // in texels
unsigned int blockDepth; // in texels
unsigned int minBlocksX; // Minimum required number of blocks
unsigned int minBlocksY;
} ktxFormatSize;
#ifdef __cplusplus
extern "C" {
#endif
bool ktxFormatSize_initFromDfd(ktxFormatSize* This, ktx_uint32_t* pDfd);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* _FORMATSIZE_H_ */

2654
thirdparty/libktx/lib/gl_format.h vendored Normal file

File diff suppressed because it is too large Load Diff

604
thirdparty/libktx/lib/hashlist.c vendored Normal file
View File

@ -0,0 +1,604 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2010-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file hashlist.c
* @~English
*
* @brief Functions for creating and using a hash list of key-value
* pairs.
*
* @author Mark Callow, HI Corporation
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
// This is to avoid compile warnings. strlen is defined as returning
// size_t and is used by the uthash macros. This avoids having to
// make changes to uthash and a bunch of casts in this file. The
// casts would be required because the key and value lengths in KTX
// are specified as 4 byte quantities so we can't change _keyAndValue
// below to use size_t.
#define strlen(x) ((unsigned int)strlen(x))
#include "uthash.h"
#include "ktx.h"
#include "ktxint.h"
/**
* @internal
* @struct ktxKVListEntry
* @brief Hash list entry structure
*/
typedef struct ktxKVListEntry {
unsigned int keyLen; /*!< Length of the key */
char* key; /*!< Pointer to key string */
unsigned int valueLen; /*!< Length of the value */
void* value; /*!< Pointer to the value */
UT_hash_handle hh; /*!< handle used by UT hash */
} ktxKVListEntry;
/**
* @memberof ktxHashList @public
* @~English
* @brief Construct an empty hash list for storing key-value pairs.
*
* @param [in] pHead pointer to the location to write the list head.
*/
void
ktxHashList_Construct(ktxHashList* pHead)
{
*pHead = NULL;
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Construct a hash list by copying another.
*
* @param [in] pHead pointer to head of the list.
* @param [in] orig head of the original hash list.
*/
void
ktxHashList_ConstructCopy(ktxHashList* pHead, ktxHashList orig)
{
ktxHashListEntry* entry = orig;
*pHead = NULL;
for (; entry != NULL; entry = ktxHashList_Next(entry)) {
(void)ktxHashList_AddKVPair(pHead,
entry->key, entry->valueLen, entry->value);
}
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Destruct a hash list.
*
* All memory associated with the hash list's keys and values
* is freed.
*
* @param [in] pHead pointer to the hash list to be destroyed.
*/
void
ktxHashList_Destruct(ktxHashList* pHead)
{
ktxKVListEntry* kv;
ktxKVListEntry* head = *pHead;
for(kv = head; kv != NULL;) {
ktxKVListEntry* tmp = (ktxKVListEntry*)kv->hh.next;
HASH_DELETE(hh, head, kv);
free(kv);
kv = tmp;
}
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Create an empty hash list for storing key-value pairs.
*
* @param [in,out] ppHl address of a variable in which to set a pointer to
* the newly created hash list.
*
* @return KTX_SUCCESS or one of the following error codes.
* @exception KTX_OUT_OF_MEMORY if not enough memory.
*/
KTX_error_code
ktxHashList_Create(ktxHashList** ppHl)
{
ktxHashList* hl = (ktxHashList*)malloc(sizeof (ktxKVListEntry*));
if (hl == NULL)
return KTX_OUT_OF_MEMORY;
ktxHashList_Construct(hl);
*ppHl = hl;
return KTX_SUCCESS;
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Create a copy of a hash list.
*
* @param [in,out] ppHl address of a variable in which to set a pointer to
* the newly created hash list.
* @param [in] orig head of the ktxHashList to copy.
*
* @return KTX_SUCCESS or one of the following error codes.
* @exception KTX_OUT_OF_MEMORY if not enough memory.
*/
KTX_error_code
ktxHashList_CreateCopy(ktxHashList** ppHl, ktxHashList orig)
{
ktxHashList* hl = (ktxHashList*)malloc(sizeof (ktxKVListEntry*));
if (hl == NULL)
return KTX_OUT_OF_MEMORY;
ktxHashList_ConstructCopy(hl, orig);
*ppHl = hl;
return KTX_SUCCESS;
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Destroy a hash list.
*
* All memory associated with the hash list's keys and values
* is freed. The hash list is also freed.
*
* @param [in] pHead pointer to the hash list to be destroyed.
*/
void
ktxHashList_Destroy(ktxHashList* pHead)
{
ktxHashList_Destruct(pHead);
free(pHead);
}
#if !__clang__ && __GNUC__ // Grumble clang grumble
// These are in uthash.h macros. I don't want to change that file.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
/**
* @memberof ktxHashList @public
* @~English
* @brief Add a key value pair to a hash list.
*
* The value can be empty, i.e, its length can be 0.
*
* @param [in] pHead pointer to the head of the target hash list.
* @param [in] key pointer to the UTF8 NUL-terminated string to be used as the key.
* @param [in] valueLen the number of bytes of data in @p value.
* @param [in] value pointer to the bytes of data constituting the value.
*
* @return KTX_SUCCESS or one of the following error codes.
* @exception KTX_INVALID_VALUE if @p pHead, @p key or @p value are NULL, @p key is an
* empty string or @p valueLen == 0.
*/
KTX_error_code
ktxHashList_AddKVPair(ktxHashList* pHead, const char* key, unsigned int valueLen, const void* value)
{
if (pHead && key && (valueLen == 0 || value)) {
unsigned int keyLen = (unsigned int)strlen(key) + 1;
ktxKVListEntry* kv;
if (keyLen == 1)
return KTX_INVALID_VALUE; /* Empty string */
/* Allocate all the memory as a block */
kv = (ktxKVListEntry*)malloc(sizeof(ktxKVListEntry) + keyLen + valueLen);
/* Put key first */
kv->key = (char *)kv + sizeof(ktxKVListEntry);
kv->keyLen = keyLen;
memcpy(kv->key, key, keyLen);
/* then value */
kv->valueLen = valueLen;
if (valueLen > 0) {
kv->value = kv->key + keyLen;
memcpy(kv->value, value, valueLen);
} else {
kv->value = 0;
}
HASH_ADD_KEYPTR( hh, *pHead, kv->key, kv->keyLen-1, kv);
return KTX_SUCCESS;
} else
return KTX_INVALID_VALUE;
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Delete a key value pair in a hash list.
*
* Is a nop if the key is not in the hash.
*
* @param [in] pHead pointer to the head of the target hash list.
* @param [in] key pointer to the UTF8 NUL-terminated string to be used as the key.
*
* @return KTX_SUCCESS or one of the following error codes.
* @exception KTX_INVALID_VALUE if @p pHead is NULL or @p key is an empty
* string.
*/
KTX_error_code
ktxHashList_DeleteKVPair(ktxHashList* pHead, const char* key)
{
if (pHead && key) {
ktxKVListEntry* kv;
HASH_FIND_STR( *pHead, key, kv ); /* kv: pointer to target entry. */
if (kv != NULL)
HASH_DEL(*pHead, kv);
return KTX_SUCCESS;
} else
return KTX_INVALID_VALUE;
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Delete an entry from a hash list.
*
* @param [in] pHead pointer to the head of the target hash list.
* @param [in] pEntry pointer to the ktxHashListEntry to delete.
*
* @return KTX_SUCCESS or one of the following error codes.
* @exception KTX_INVALID_VALUE if @p pHead is NULL or @p key is an empty
* string.
*/
KTX_error_code
ktxHashList_DeleteEntry(ktxHashList* pHead, ktxHashListEntry* pEntry)
{
if (pHead && pEntry) {
HASH_DEL(*pHead, pEntry);
return KTX_SUCCESS;
} else
return KTX_INVALID_VALUE;
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Looks up a key in a hash list and returns the entry.
*
* @param [in] pHead pointer to the head of the target hash list.
* @param [in] key pointer to a UTF8 NUL-terminated string to find.
* @param [in,out] ppEntry @p *ppEntry is set to the point at the
* ktxHashListEntry.
*
* @return KTX_SUCCESS or one of the following error codes.
*
* @exception KTX_INVALID_VALUE if @p This, @p key or @p pValueLen or @p ppValue
* is NULL.
* @exception KTX_NOT_FOUND an entry matching @p key was not found.
*/
KTX_error_code
ktxHashList_FindEntry(ktxHashList* pHead, const char* key,
ktxHashListEntry** ppEntry)
{
if (pHead && key) {
ktxKVListEntry* kv;
HASH_FIND_STR( *pHead, key, kv ); /* kv: output pointer */
if (kv) {
*ppEntry = kv;
return KTX_SUCCESS;
} else
return KTX_NOT_FOUND;
} else
return KTX_INVALID_VALUE;
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Looks up a key in a hash list and returns the value.
*
* @param [in] pHead pointer to the head of the target hash list.
* @param [in] key pointer to a UTF8 NUL-terminated string to find.
* @param [in,out] pValueLen @p *pValueLen is set to the number of bytes of
* data in the returned value.
* @param [in,out] ppValue @p *ppValue is set to the point to the value for
* @p key.
*
* @return KTX_SUCCESS or one of the following error codes.
*
* @exception KTX_INVALID_VALUE if @p This, @p key or @p pValueLen or @p ppValue
* is NULL.
* @exception KTX_NOT_FOUND an entry matching @p key was not found.
*/
KTX_error_code
ktxHashList_FindValue(ktxHashList *pHead, const char* key, unsigned int* pValueLen, void** ppValue)
{
if (pValueLen && ppValue) {
ktxHashListEntry* pEntry;
KTX_error_code result;
result = ktxHashList_FindEntry(pHead, key, &pEntry);
if (result == KTX_SUCCESS) {
ktxHashListEntry_GetValue(pEntry, pValueLen, ppValue);
return KTX_SUCCESS;
} else
return result;
} else
return KTX_INVALID_VALUE;
}
#if !__clang__ && __GNUC__
#pragma GCC diagnostic pop
#endif
/**
* @memberof ktxHashList @public
* @~English
* @brief Returns the next entry in a ktxHashList.
*
* Use for iterating through the list:
* @code
* ktxHashListEntry* entry;
* for (entry = listHead; entry != NULL; entry = ktxHashList_Next(entry)) {
* ...
* };
* @endcode
*
* Note
*
* @param [in] entry pointer to a hash list entry. Note that a ktxHashList*,
* i.e. the list head, is also a pointer to an entry so
* can be passed to this function.
*
* @return a pointer to the next entry or NULL.
*
*/
ktxHashListEntry*
ktxHashList_Next(ktxHashListEntry* entry)
{
if (entry) {
return ((ktxKVListEntry*)entry)->hh.next;
} else
return NULL;
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Serialize a hash list to a block of data suitable for writing
* to a file.
*
* The caller is responsible for freeing the data block returned by this
* function.
*
* @param [in] pHead pointer to the head of the target hash list.
* @param [in,out] pKvdLen @p *pKvdLen is set to the number of bytes of
* data in the returned data block.
* @param [in,out] ppKvd @p *ppKvd is set to the point to the block of
* memory containing the serialized data or
* NULL. if the hash list is empty.
*
* @return KTX_SUCCESS or one of the following error codes.
*
* @exception KTX_INVALID_VALUE if @p This, @p pKvdLen or @p ppKvd is NULL.
* @exception KTX_OUT_OF_MEMORY there was not enough memory to serialize the
* data.
*/
KTX_error_code
ktxHashList_Serialize(ktxHashList* pHead,
unsigned int* pKvdLen, unsigned char** ppKvd)
{
if (pHead && pKvdLen && ppKvd) {
ktxKVListEntry* kv;
unsigned int bytesOfKeyValueData = 0;
unsigned int keyValueLen;
unsigned char* sd;
char padding[4] = {0, 0, 0, 0};
for (kv = *pHead; kv != NULL; kv = kv->hh.next) {
/* sizeof(sd) is to make space to write keyAndValueByteSize */
keyValueLen = kv->keyLen + kv->valueLen + sizeof(ktx_uint32_t);
/* Add valuePadding */
keyValueLen = _KTX_PAD4(keyValueLen);
bytesOfKeyValueData += keyValueLen;
}
if (bytesOfKeyValueData == 0) {
*pKvdLen = 0;
*ppKvd = NULL;
} else {
sd = malloc(bytesOfKeyValueData);
if (!sd)
return KTX_OUT_OF_MEMORY;
*pKvdLen = bytesOfKeyValueData;
*ppKvd = sd;
for (kv = *pHead; kv != NULL; kv = kv->hh.next) {
int padLen;
keyValueLen = kv->keyLen + kv->valueLen;
*(ktx_uint32_t*)sd = keyValueLen;
sd += sizeof(ktx_uint32_t);
memcpy(sd, kv->key, kv->keyLen);
sd += kv->keyLen;
if (kv->valueLen > 0)
memcpy(sd, kv->value, kv->valueLen);
sd += kv->valueLen;
padLen = _KTX_PAD4_LEN(keyValueLen);
memcpy(sd, padding, padLen);
sd += padLen;
}
}
return KTX_SUCCESS;
} else
return KTX_INVALID_VALUE;
}
int sort_by_key_codepoint(ktxKVListEntry* a, ktxKVListEntry* b) {
return strcmp(a->key, b->key);
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Sort a hash list in order of the UTF8 codepoints.
*
* @param [in] pHead pointer to the head of the target hash list.
*
* @return KTX_SUCCESS or one of the following error codes.
*
* @exception KTX_INVALID_VALUE if @p This is NULL.
*/
KTX_error_code
ktxHashList_Sort(ktxHashList* pHead)
{
if (pHead) {
//ktxKVListEntry* kv = (ktxKVListEntry*)pHead;
HASH_SORT(*pHead, sort_by_key_codepoint);
return KTX_SUCCESS;
} else {
return KTX_INVALID_VALUE;
}
}
/**
* @memberof ktxHashList @public
* @~English
* @brief Construct a hash list from a block of serialized key-value
* data read from a file.
* @note The bytes of the 32-bit key-value lengths within the serialized data
* are expected to be in native endianness.
*
* @param [in] pHead pointer to the head of the target hash list.
* @param [in] kvdLen the length of the serialized key-value data.
* @param [in] pKvd pointer to the serialized key-value data.
* table.
*
* @return KTX_SUCCESS or one of the following error codes.
*
* @exception KTX_INVALID_OPERATION if @p pHead does not point to an empty list.
* @exception KTX_INVALID_VALUE if @p pKvd or @p pHt is NULL or kvdLen == 0.
* @exception KTX_OUT_OF_MEMORY there was not enough memory to create the hash
* table.
*/
KTX_error_code
ktxHashList_Deserialize(ktxHashList* pHead, unsigned int kvdLen, void* pKvd)
{
char* src = pKvd;
KTX_error_code result;
if (kvdLen == 0 || pKvd == NULL || pHead == NULL)
return KTX_INVALID_VALUE;
if (*pHead != NULL)
return KTX_INVALID_OPERATION;
result = KTX_SUCCESS;
while (result == KTX_SUCCESS && src < (char *)pKvd + kvdLen) {
char* key;
unsigned int keyLen, valueLen;
void* value;
ktx_uint32_t keyAndValueByteSize = *((ktx_uint32_t*)src);
src += sizeof(keyAndValueByteSize);
key = src;
keyLen = (unsigned int)strlen(key) + 1;
value = key + keyLen;
valueLen = keyAndValueByteSize - keyLen;
result = ktxHashList_AddKVPair(pHead, key, valueLen,
valueLen > 0 ? value : NULL);
if (result == KTX_SUCCESS) {
src += _KTX_PAD4(keyAndValueByteSize);
}
}
return result;
}
/**
* @memberof ktxHashListEntry @public
* @~English
* @brief Return the key of a ktxHashListEntry
*
* @param [in] This The target hash list entry.
* @param [in,out] pKeyLen @p *pKeyLen is set to the byte length of
* the returned key.
* @param [in,out] ppKey @p *ppKey is set to the point to the value of
* @p the key.
*
* @return KTX_SUCCESS or one of the following error codes.
*
* @exception KTX_INVALID_VALUE if @p pKvd or @p pHt is NULL or kvdLen == 0.
*/
KTX_error_code
ktxHashListEntry_GetKey(ktxHashListEntry* This,
unsigned int* pKeyLen, char** ppKey)
{
if (pKeyLen && ppKey) {
ktxKVListEntry* kv = (ktxKVListEntry*)This;
*pKeyLen = kv->keyLen;
*ppKey = kv->key;
return KTX_SUCCESS;
} else
return KTX_INVALID_VALUE;
}
/**
* @memberof ktxHashListEntry @public
* @~English
* @brief Return the value from a ktxHashListEntry
*
* @param [in] This The target hash list entry.
* @param [in,out] pValueLen @p *pValueLen is set to the number of bytes of
* data in the returned value.
* @param [in,out] ppValue @p *ppValue is set to point to the value of
* of the target entry.
*
* @return KTX_SUCCESS or one of the following error codes.
*
* @exception KTX_INVALID_VALUE if @p pKvd or @p pHt is NULL or kvdLen == 0.
*/
KTX_error_code
ktxHashListEntry_GetValue(ktxHashListEntry* This,
unsigned int* pValueLen, void** ppValue)
{
if (pValueLen && ppValue) {
ktxKVListEntry* kv = (ktxKVListEntry*)This;
*pValueLen = kv->valueLen;
*ppValue = kv->valueLen > 0 ? kv->value : NULL;
return KTX_SUCCESS;
} else
return KTX_INVALID_VALUE;
}

266
thirdparty/libktx/lib/ktxint.h vendored Normal file
View File

@ -0,0 +1,266 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* $Id: e36ad79b5eac8ea237d6a05602c71aadab575519 $ */
/*
* Copyright 2010-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Author: Mark Callow from original code by Georg Kolling
*/
#ifndef KTXINT_H
#define KTXINT_H
#include <math.h>
/* Define this to include the ETC unpack software in the library. */
#ifndef SUPPORT_SOFTWARE_ETC_UNPACK
/* Include for all GL versions because have seen OpenGL ES 3
* implementaions that do not support ETC1 (ARM Mali emulator v1.0)!
*/
#define SUPPORT_SOFTWARE_ETC_UNPACK 1
#endif
#ifndef MAX
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#endif
#define QUOTE(x) #x
#define STR(x) QUOTE(x)
#define KTX2_IDENTIFIER_REF { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x32, 0x30, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }
#define KTX2_HEADER_SIZE (80)
#ifdef __cplusplus
extern "C" {
#endif
/**
* @internal
* @brief used to pass GL context capabilites to subroutines.
*/
#define _KTX_NO_R16_FORMATS 0x0
#define _KTX_R16_FORMATS_NORM 0x1
#define _KTX_R16_FORMATS_SNORM 0x2
#define _KTX_ALL_R16_FORMATS (_KTX_R16_FORMATS_NORM | _KTX_R16_FORMATS_SNORM)
extern GLint _ktxR16Formats;
extern GLboolean _ktxSupportsSRGB;
/**
* @internal
* @~English
* @brief KTX file header.
*
* See the KTX specification for descriptions.
*/
typedef struct KTX_header {
ktx_uint8_t identifier[12];
ktx_uint32_t endianness;
ktx_uint32_t glType;
ktx_uint32_t glTypeSize;
ktx_uint32_t glFormat;
ktx_uint32_t glInternalformat;
ktx_uint32_t glBaseInternalformat;
ktx_uint32_t pixelWidth;
ktx_uint32_t pixelHeight;
ktx_uint32_t pixelDepth;
ktx_uint32_t numberOfArrayElements;
ktx_uint32_t numberOfFaces;
ktx_uint32_t numberOfMipLevels;
ktx_uint32_t bytesOfKeyValueData;
} KTX_header;
/* This will cause compilation to fail if the struct size doesn't match */
typedef int KTX_header_SIZE_ASSERT [sizeof(KTX_header) == KTX_HEADER_SIZE];
/**
* @internal
* @~English
* @brief 32-bit KTX 2 index entry.
*/
typedef struct ktxIndexEntry32 {
ktx_uint32_t byteOffset; /*!< Offset of item from start of file. */
ktx_uint32_t byteLength; /*!< Number of bytes of data in the item. */
} ktxIndexEntry32;
/**
* @internal
* @~English
* @brief 64-bit KTX 2 index entry.
*/
typedef struct ktxIndexEntry64 {
ktx_uint64_t byteOffset; /*!< Offset of item from start of file. */
ktx_uint64_t byteLength; /*!< Number of bytes of data in the item. */
} ktxIndexEntry64;
/**
* @internal
* @~English
* @brief KTX 2 file header.
*
* See the KTX 2 specification for descriptions.
*/
typedef struct KTX_header2 {
ktx_uint8_t identifier[12];
ktx_uint32_t vkFormat;
ktx_uint32_t typeSize;
ktx_uint32_t pixelWidth;
ktx_uint32_t pixelHeight;
ktx_uint32_t pixelDepth;
ktx_uint32_t layerCount;
ktx_uint32_t faceCount;
ktx_uint32_t levelCount;
ktx_uint32_t supercompressionScheme;
ktxIndexEntry32 dataFormatDescriptor;
ktxIndexEntry32 keyValueData;
ktxIndexEntry64 supercompressionGlobalData;
} KTX_header2;
/* This will cause compilation to fail if the struct size doesn't match */
typedef int KTX_header2_SIZE_ASSERT [sizeof(KTX_header2) == KTX2_HEADER_SIZE];
/**
* @internal
* @~English
* @brief KTX 2 level index entry.
*/
typedef struct ktxLevelIndexEntry {
ktx_uint64_t byteOffset; /*!< Offset of level from start of file. */
ktx_uint64_t byteLength;
/*!< Number of bytes of compressed image data in the level. */
ktx_uint64_t uncompressedByteLength;
/*!< Number of bytes of uncompressed image data in the level. */
} ktxLevelIndexEntry;
/**
* @internal
* @~English
* @brief Structure for supplemental information about the texture.
*
* _ktxCheckHeader returns supplemental information about the texture in this
* structure that is derived during checking of the file header.
*/
typedef struct KTX_supplemental_info
{
ktx_uint8_t compressed;
ktx_uint8_t generateMipmaps;
ktx_uint16_t textureDimension;
} KTX_supplemental_info;
/**
* @internal
* @var ktx_uint8_t KTX_supplemental_info::compressed
* @~English
* @brief KTX_TRUE, if this a compressed texture, KTX_FALSE otherwise?
*/
/**
* @internal
* @var ktx_uint8_t KTX_supplemental_info::generateMipmaps
* @~English
* @brief KTX_TRUE, if mipmap generation is required, KTX_FALSE otherwise.
*/
/**
* @internal
* @var ktx_uint16_t KTX_supplemental_info::textureDimension
* @~English
* @brief The number of dimensions, 1, 2 or 3, of data in the texture image.
*/
/*
* @internal
* CheckHeader1
*
* Reads the KTX file header and performs some sanity checking on the values
*/
KTX_error_code ktxCheckHeader1_(KTX_header* pHeader,
KTX_supplemental_info* pSuppInfo);
/*
* @internal
* CheckHeader2
*
* Reads the KTX 2 file header and performs some sanity checking on the values
*/
KTX_error_code ktxCheckHeader2_(KTX_header2* pHeader,
KTX_supplemental_info* pSuppInfo);
/*
* SwapEndian16: Swaps endianness in an array of 16-bit values
*/
void _ktxSwapEndian16(ktx_uint16_t* pData16, ktx_size_t count);
/*
* SwapEndian32: Swaps endianness in an array of 32-bit values
*/
void _ktxSwapEndian32(ktx_uint32_t* pData32, ktx_size_t count);
/*
* SwapEndian32: Swaps endianness in an array of 64-bit values
*/
void _ktxSwapEndian64(ktx_uint64_t* pData64, ktx_size_t count);
/*
* UnpackETC: uncompresses an ETC compressed texture image
*/
KTX_error_code _ktxUnpackETC(const GLubyte* srcETC, const GLenum srcFormat,
ktx_uint32_t active_width, ktx_uint32_t active_height,
GLubyte** dstImage,
GLenum* format, GLenum* internalFormat, GLenum* type,
GLint R16Formats, GLboolean supportsSRGB);
/*
* Pad nbytes to next multiple of n
*/
#define _KTX_PADN(n, nbytes) (ktx_uint32_t)(n * ceilf((float)(nbytes) / n))
/*
* Calculate bytes of of padding needed to reach next multiple of n.
*/
/* Equivalent to (n * ceil(nbytes / n)) - nbytes */
#define _KTX_PADN_LEN(n, nbytes) \
(ktx_uint32_t)((n * ceilf((float)(nbytes) / n)) - (nbytes))
/*
* Pad nbytes to next multiple of 4
*/
#define _KTX_PAD4(nbytes) _KTX_PADN(4, nbytes)
/*
* Calculate bytes of of padding needed to reach next multiple of 4.
*/
#define _KTX_PAD4_LEN(nbytes) _KTX_PADN_LEN(4, nbytes)
/*
* Pad nbytes to next multiple of 8
*/
#define _KTX_PAD8(nbytes) _KTX_PADN(8, nbytes)
/*
* Calculate bytes of of padding needed to reach next multiple of 8.
*/
#define _KTX_PAD8_LEN(nbytes) _KTX_PADN_LEN(8, nbytes)
/*
* Pad nbytes to KTX_GL_UNPACK_ALIGNMENT
*/
#define _KTX_PAD_UNPACK_ALIGN(nbytes) \
_KTX_PADN(KTX_GL_UNPACK_ALIGNMENT, nbytes)
/*
* Calculate bytes of of padding needed to reach KTX_GL_UNPACK_ALIGNMENT.
*/
#define _KTX_PAD_UNPACK_ALIGN_LEN(nbytes) \
_KTX_PADN_LEN(KTX_GL_UNPACK_ALIGNMENT, nbytes)
/*
======================================
Internal utility functions
======================================
*/
void printKTX2Info2(ktxStream* src, KTX_header2* header);
#ifdef __cplusplus
}
#endif
#endif /* KTXINT_H */

561
thirdparty/libktx/lib/memstream.c vendored Normal file
View File

@ -0,0 +1,561 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2010-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @~English
*
* @brief Implementation of ktxStream for memory.
*
* @author Maksim Kolesin, Under Development
* @author Georg Kolling, Imagination Technology
* @author Mark Callow, HI Corporation
*/
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "ktx.h"
#include "ktxint.h"
#include "memstream.h"
/**
* @brief Default allocation size for a ktxMemStream.
*/
#define KTX_MEM_DEFAULT_ALLOCATED_SIZE 256
/**
* @brief Structure to store information about data allocated for ktxMemStream.
*/
struct ktxMem
{
const ktx_uint8_t* robytes;/*!< pointer to read-only data */
ktx_uint8_t* bytes; /*!< pointer to rw data. */
ktx_size_t alloc_size; /*!< allocated size of the memory block. */
ktx_size_t used_size; /*!< bytes used. Effectively the write position. */
ktx_off_t pos; /*!< read/write position. */
};
static KTX_error_code ktxMem_expand(ktxMem* pMem, const ktx_size_t size);
/**
* @brief Initialize a ktxMem struct for read-write.
*
* Memory for the stream data is allocated internally but the
* caller is responsible for freeing the memory. A pointer to
* the memory can be obtained with ktxMem_getdata().
*
* @sa ktxMem_getdata.
*
* @param [in] pMem pointer to the @c ktxMem to initialize.
*/
static KTX_error_code
ktxMem_construct(ktxMem* pMem)
{
pMem->pos = 0;
pMem->alloc_size = 0;
pMem->robytes = 0;
pMem->bytes = 0;
pMem->used_size = 0;
return ktxMem_expand(pMem, KTX_MEM_DEFAULT_ALLOCATED_SIZE);
}
/**
* @brief Create & initialize a ktxMem struct for read-write.
*
* @sa ktxMem_construct.
*
* @param [in,out] ppMem pointer to the location in which to return
* a pointer to the newly created @c ktxMem.
*
* @return KTX_SUCCESS on success, KTX_OUT_OF_MEMORY on error.
*
* @exception KTX_OUT_OF_MEMORY System failed to allocate sufficient pMemory.
*/
static KTX_error_code
ktxMem_create(ktxMem** ppMem)
{
ktxMem* pNewMem = (ktxMem*)malloc(sizeof(ktxMem));
if (pNewMem) {
KTX_error_code result = ktxMem_construct(pNewMem);
if (result == KTX_SUCCESS)
*ppMem = pNewMem;
return result;
}
else {
return KTX_OUT_OF_MEMORY;
}
}
/**
* @brief Initialize a ktxMem struct for read-only.
*
* @param [in] pMem pointer to the @c ktxMem to initialize.
* @param [in] bytes pointer to the data to be read.
* @param [in] numBytes number of bytes of data.
*/
static void
ktxMem_construct_ro(ktxMem* pMem, const void* bytes, ktx_size_t numBytes)
{
pMem->pos = 0;
pMem->robytes = bytes;
pMem->bytes = 0;
pMem->used_size = numBytes;
pMem->alloc_size = numBytes;
}
/**
* @brief Create & initialize a ktxMem struct for read-only.
*
* @sa ktxMem_construct.
*
* @param [in,out] ppMem pointer to the location in which to return
* a pointer to the newly created @c ktxMem.
* @param [in] bytes pointer to the data to be read.
* @param [in] numBytes number of bytes of data.
*
* @return KTX_SUCCESS on success, KTX_OUT_OF_MEMORY on error.
*
* @exception KTX_OUT_OF_MEMORY System failed to allocate sufficient pMemory.
*/
static KTX_error_code
ktxMem_create_ro(ktxMem** ppMem, const void* bytes, ktx_size_t numBytes)
{
ktxMem* pNewMem = (ktxMem*)malloc(sizeof(ktxMem));
if (pNewMem) {
ktxMem_construct_ro(pNewMem, bytes, numBytes);
*ppMem = pNewMem;
return KTX_SUCCESS;
}
else {
return KTX_OUT_OF_MEMORY;
}
}
/*
* ktxMem_destruct not needed as ktxMem_construct caller is reponsible
* for freeing the data written.
*/
/**
* @brief Free the memory of a struct ktxMem.
*
* @param pMem pointer to ktxMem to free.
*/
static void
ktxMem_destroy(ktxMem* pMem, ktx_bool_t freeData)
{
assert(pMem != NULL);
if (freeData) {
free(pMem->bytes);
}
free(pMem);
}
#ifdef KTXMEM_CLEAR_USED
/**
* @brief Clear the data of a memory stream.
*
* @param pMem pointer to ktxMem to clear.
*/
static void
ktxMem_clear(ktxMem* pMem)
{
assert(pMem != NULL);
memset(pMem, 0, sizeof(ktxMem));
}
#endif
/**
* @~English
* @brief Expand a ktxMem to fit to a new size.
*
* @param [in] pMem pointer to ktxMem struct to expand.
* @param [in] newsize minimum new size required.
*
* @return KTX_SUCCESS on success, KTX_OUT_OF_MEMORY on error.
*
* @exception KTX_OUT_OF_MEMORY System failed to allocate sufficient pMemory.
*/
static KTX_error_code
ktxMem_expand(ktxMem *pMem, const ktx_size_t newsize)
{
ktx_size_t new_alloc_size;
assert(pMem != NULL && newsize != 0);
new_alloc_size = pMem->alloc_size == 0 ?
KTX_MEM_DEFAULT_ALLOCATED_SIZE : pMem->alloc_size;
while (new_alloc_size < newsize) {
ktx_size_t alloc_size = new_alloc_size;
new_alloc_size <<= 1;
if (new_alloc_size < alloc_size) {
/* Overflow. Set to maximum size. newsize can't be larger. */
new_alloc_size = (ktx_size_t)-1L;
}
}
if (new_alloc_size == pMem->alloc_size)
return KTX_SUCCESS;
if (!pMem->bytes)
pMem->bytes = (ktx_uint8_t*)malloc(new_alloc_size);
else
pMem->bytes = (ktx_uint8_t*)realloc(pMem->bytes, new_alloc_size);
if (!pMem->bytes)
{
pMem->alloc_size = 0;
pMem->used_size = 0;
return KTX_OUT_OF_MEMORY;
}
pMem->alloc_size = new_alloc_size;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Read bytes from a ktxMemStream.
*
* @param [in] str pointer to ktxMem struct, converted to a void*, that
* specifies an input stream.
* @param [in,out] dst pointer to memory where to copy read bytes.
* @param [in,out] count pointer to number of bytes to read.
*
* @return KTX_SUCCESS on success, KTX_INVALID_VALUE on error.
*
* @exception KTX_INVALID_VALUE @p str or @p dst is @c NULL or @p str->data is
* @c NULL.
* @exception KTX_FILE_UNEXPECTED_EOF not enough data to satisfy the request.
*/
static
KTX_error_code ktxMemStream_read(ktxStream* str, void* dst, const ktx_size_t count)
{
ktxMem* mem;
ktx_off_t newpos;
const ktx_uint8_t* bytes;
if (!str || (mem = str->data.mem)== 0)
return KTX_INVALID_VALUE;
newpos = mem->pos + count;
/* The first clause checks for overflow. */
if (newpos < mem->pos || (ktx_uint32_t)newpos > mem->used_size)
return KTX_FILE_UNEXPECTED_EOF;
bytes = mem->robytes ? mem->robytes : mem->bytes;
memcpy(dst, bytes + mem->pos, count);
mem->pos = newpos;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Skip bytes in a ktxMemStream.
*
* @param [in] str pointer to the ktxStream on which to operate.
* @param [in] count number of bytes to skip.
*
* @return KTX_SUCCESS on success, KTX_INVALID_VALUE on error.
*
* @exception KTX_INVALID_VALUE @p str or @p mem is @c NULL or sufficient
* data is not available in ktxMem.
* @exception KTX_FILE_UNEXPECTED_EOF not enough data to satisfy the request.
*/
static
KTX_error_code ktxMemStream_skip(ktxStream* str, const ktx_size_t count)
{
ktxMem* mem;
ktx_off_t newpos;
if (!str || (mem = str->data.mem) == 0)
return KTX_INVALID_VALUE;
newpos = mem->pos + count;
/* The first clause checks for overflow. */
if (newpos < mem->pos || (ktx_uint32_t)newpos > mem->used_size)
return KTX_FILE_UNEXPECTED_EOF;
mem->pos = newpos;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Write bytes to a ktxMemStream.
*
* @param [out] str pointer to the ktxStream that specifies the destination.
* @param [in] src pointer to the array of elements to be written,
* converted to a const void*.
* @param [in] size size in bytes of each element to be written.
* @param [in] count number of elements, each one with a @p size of size
* bytes.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_FILE_OVERFLOW write would result in file exceeding the
* maximum permissible size.
* @exception KTX_INVALID_OPERATION @p str is a read-only stream.
* @exception KTX_INVALID_VALUE @p dst is @c NULL or @p mem is @c NULL.
* @exception KTX_OUT_OF_MEMORY See ktxMem_expand() for causes.
*/
static
KTX_error_code ktxMemStream_write(ktxStream* str, const void* src,
const ktx_size_t size, const ktx_size_t count)
{
ktxMem* mem;
KTX_error_code rc = KTX_SUCCESS;
ktx_size_t new_size;
if (!str || (mem = str->data.mem) == 0)
return KTX_INVALID_VALUE;
if (mem->robytes)
return KTX_INVALID_OPERATION; /* read-only */
new_size = mem->pos + (size*count);
//if (new_size < mem->used_size)
if ((ktx_off_t)new_size < mem->pos)
return KTX_FILE_OVERFLOW;
if (mem->alloc_size < new_size) {
rc = ktxMem_expand(mem, new_size);
if (rc != KTX_SUCCESS)
return rc;
}
memcpy(mem->bytes + mem->pos, src, size*count);
mem->pos += size*count;
if (mem->pos > (ktx_off_t)mem->used_size)
mem->used_size = mem->pos;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Get the current read/write position in a ktxMemStream.
*
* @param [in] str pointer to the ktxStream to query.
* @param [in,out] off pointer to variable to receive the offset value.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_INVALID_VALUE @p str or @p pos is @c NULL.
*/
static
KTX_error_code ktxMemStream_getpos(ktxStream* str, ktx_off_t* const pos)
{
if (!str || !pos)
return KTX_INVALID_VALUE;
assert(str->type == eStreamTypeMemory);
*pos = str->data.mem->pos;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Set the current read/write position in a ktxMemStream.
*
* Offset of 0 is the start of the file.
*
* @param [in] str pointer to the ktxStream whose r/w position is to be set.
* @param [in] off pointer to the offset value to set.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_INVALID_VALUE @p str is @c NULL.
* @exception KTX_INVALID_OPERATION @p pos > size of the allocated memory.
*/
static
KTX_error_code ktxMemStream_setpos(ktxStream* str, ktx_off_t pos)
{
if (!str)
return KTX_INVALID_VALUE;
assert(str->type == eStreamTypeMemory);
if (pos > (ktx_off_t)str->data.mem->alloc_size)
return KTX_INVALID_OPERATION;
str->data.mem->pos = pos;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Get a pointer to a ktxMemStream's data.
*
* Gets a pointer to data that has been written to the stream. Returned
* pointer will be 0 if stream is read-only.
*
* @param [in] str pointer to the ktxStream whose data pointer is to
* be queried.
* @param [in,out] ppBytes pointer to a variable in which the data pointer
* will be written.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_INVALID_VALUE @p str or @p ppBytes is @c NULL.
*/
KTX_error_code ktxMemStream_getdata(ktxStream* str, ktx_uint8_t** ppBytes)
{
if (!str || !ppBytes)
return KTX_INVALID_VALUE;
assert(str->type == eStreamTypeMemory);
*ppBytes = str->data.mem->bytes;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Get the size of a ktxMemStream in bytes.
*
* @param [in] str pointer to the ktxStream whose size is to be queried.
* @param [in,out] size pointer to a variable in which size will be written.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_INVALID_VALUE @p str or @p pSize is @c NULL.
*/
static
KTX_error_code ktxMemStream_getsize(ktxStream* str, ktx_size_t* pSize)
{
if (!str || !pSize)
return KTX_INVALID_VALUE;
assert(str->type == eStreamTypeMemory);
*pSize = str->data.mem->used_size;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Setup ktxMemStream function pointers.
*/
void
ktxMemStream_setup(ktxStream* str)
{
str->type = eStreamTypeMemory;
str->read = ktxMemStream_read;
str->skip = ktxMemStream_skip;
str->write = ktxMemStream_write;
str->getpos = ktxMemStream_getpos;
str->setpos = ktxMemStream_setpos;
str->getsize = ktxMemStream_getsize;
str->destruct = ktxMemStream_destruct;
}
/**
* @~English
* @brief Initialize a read-write ktxMemStream.
*
* Memory is allocated as data is written. The caller of this is
* responsible for freeing this memory unless @a freeOnDestruct
* is not KTX_FALSE.
*
* @param [in] str pointer to a ktxStream struct to initialize.
* @param [in] freeOnDestruct If not KTX_FALSE memory holding the data will
* be freed by the destructor.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_INVALID_VALUE @p str is @c NULL.
* @exception KTX_OUT_OF_MEMORY system failed to allocate sufficient memory.
*/
KTX_error_code ktxMemStream_construct(ktxStream* str,
ktx_bool_t freeOnDestruct)
{
ktxMem* mem;
KTX_error_code result = KTX_SUCCESS;
if (!str)
return KTX_INVALID_VALUE;
result = ktxMem_create(&mem);
if (KTX_SUCCESS == result) {
str->data.mem = mem;
ktxMemStream_setup(str);
str->closeOnDestruct = freeOnDestruct;
}
return result;
}
/**
* @~English
* @brief Initialize a read-only ktxMemStream.
*
* @param [in] str pointer to a ktxStream struct to initialize.
* @param [in] bytes pointer to an array of bytes containing the data.
* @param [in] numBytes size of array of data for ktxMemStream.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_INVALID_VALUE @p str or @p mem is @c NULL or @p numBytes
* is 0.
* or @p size is less than 0.
* @exception KTX_OUT_OF_MEMORY system failed to allocate sufficient memory.
*/
KTX_error_code ktxMemStream_construct_ro(ktxStream* str,
const ktx_uint8_t* bytes,
const ktx_size_t numBytes)
{
ktxMem* mem;
KTX_error_code result = KTX_SUCCESS;
if (!str || !bytes || numBytes == 0)
return KTX_INVALID_VALUE;
result = ktxMem_create_ro(&mem, bytes, numBytes);
if (KTX_SUCCESS == result) {
str->data.mem = mem;
ktxMemStream_setup(str);
str->closeOnDestruct = KTX_FALSE;
}
return result;
}
/**
* @~English
* @brief Free the memory used by a ktxMemStream.
*
* This only frees the memory used to store the data written to the stream,
* if the @c freeOnDestruct parameter to ktxMemStream_construct() was not
* @c KTX_FALSE. Otherwise it is the responsibility of the caller of
* ktxMemStream_construct() and a pointer to this memory should be retrieved
* using ktxMemStream_getdata() before calling this function.
*
* @sa ktxMemStream_construct, ktxMemStream_getdata.
*
* @param [in] str pointer to the ktxStream whose memory is
* to be freed.
*/
void
ktxMemStream_destruct(ktxStream* str)
{
assert(str && str->type == eStreamTypeMemory);
ktxMem_destroy(str->data.mem, str->closeOnDestruct);
str->data.mem = NULL;
}

43
thirdparty/libktx/lib/memstream.h vendored Normal file
View File

@ -0,0 +1,43 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2010-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file
* @~English
*
* @brief Interface of ktxStream for memory.
*
* @author Maksim Kolesin
* @author Georg Kolling, Imagination Technology
* @author Mark Callow, HI Corporation
*/
#ifndef MEMSTREAM_H
#define MEMSTREAM_H
#include "ktx.h"
/*
* Initialize a ktxStream to a ktxMemStream with internally
* allocated memory. Can be read or written.
*/
KTX_error_code ktxMemStream_construct(ktxStream* str,
ktx_bool_t freeOnDestruct);
/*
* Initialize a ktxStream to a read-only ktxMemStream reading
* from an array of bytes.
*/
KTX_error_code ktxMemStream_construct_ro(ktxStream* str,
const ktx_uint8_t* pBytes,
const ktx_size_t size);
void ktxMemStream_destruct(ktxStream* str);
KTX_error_code ktxMemStream_getdata(ktxStream* str, ktx_uint8_t** ppBytes);
#endif /* MEMSTREAM_H */

57
thirdparty/libktx/lib/swap.c vendored Normal file
View File

@ -0,0 +1,57 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* $Id: 02ea6de2d8db512ca3af08f48b98ab5f6c35e7e5 $ */
/*
* Copyright 2010-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
#include <KHR/khrplatform.h>
#include "ktx.h"
/*
* SwapEndian16: Swaps endianness in an array of 16-bit values
*/
void
_ktxSwapEndian16(khronos_uint16_t* pData16, ktx_size_t count)
{
for (ktx_size_t i = 0; i < count; ++i)
{
khronos_uint16_t x = *pData16;
*pData16++ = (x << 8) | (x >> 8);
}
}
/*
* SwapEndian32: Swaps endianness in an array of 32-bit values
*/
void
_ktxSwapEndian32(khronos_uint32_t* pData32, ktx_size_t count)
{
for (ktx_size_t i = 0; i < count; ++i)
{
khronos_uint32_t x = *pData32;
*pData32++ = (x << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | (x >> 24);
}
}
/*
* SwapEndian364: Swaps endianness in an array of 32-bit values
*/
void
_ktxSwapEndian64(khronos_uint64_t* pData64, ktx_size_t count)
{
for (ktx_size_t i = 0; i < count; ++i)
{
khronos_uint64_t x = *pData64;
*pData64++ = (x << 56) | ((x & 0xFF00) << 40) | ((x & 0xFF0000) << 24)
| ((x & 0xFF000000) << 8 ) | ((x & 0xFF00000000) >> 8)
| ((x & 0xFF0000000000) >> 24)
| ((x & 0xFF000000000000) << 40) | (x >> 56);
}
}

911
thirdparty/libktx/lib/texture.c vendored Normal file
View File

@ -0,0 +1,911 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2018-2020 Mark Callow.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file writer.c
* @~English
*
* @brief ktxTexture implementation.
*
* @author Mark Callow, www.edgewise-consulting.com
*/
#if defined(_WIN32)
#define _CRT_SECURE_NO_WARNINGS
#ifndef __cplusplus
#undef inline
#define inline __inline
#endif // __cplusplus
#endif
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "ktx.h"
#include "ktxint.h"
#include "formatsize.h"
#include "filestream.h"
#include "memstream.h"
#include "texture1.h"
#include "texture2.h"
#include "unused.h"
ktx_size_t ktxTexture_GetDataSize(ktxTexture* This);
static ktx_uint32_t padRow(ktx_uint32_t* rowBytes);
/**
* @memberof ktxTexture @private
* @~English
* @brief Construct (initialize) a ktxTexture base class instance.
*
* @param[in] This pointer to a ktxTexture-sized block of memory to
* initialize.
* @param[in] createInfo pointer to a ktxTextureCreateInfo struct with
* information describing the texture.
* @param[in] formatSize pointer to a ktxFormatSize giving size information
* about the texture's elements.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_INVALID_VALUE @c glInternalFormat in @p createInfo is not a
* valid OpenGL internal format value.
* @exception KTX_INVALID_VALUE @c numDimensions in @p createInfo is not 1, 2
* or 3.
* @exception KTX_INVALID_VALUE One of <tt>base{Width,Height,Depth}</tt> in
* @p createInfo is 0.
* @exception KTX_INVALID_VALUE @c numFaces in @p createInfo is not 1 or 6.
* @exception KTX_INVALID_VALUE @c numLevels in @p createInfo is 0.
* @exception KTX_INVALID_OPERATION
* The <tt>base{Width,Height,Depth}</tt> specified
* in @p createInfo are inconsistent with
* @c numDimensions.
* @exception KTX_INVALID_OPERATION
* @p createInfo is requesting a 3D array or
* 3D cubemap texture.
* @exception KTX_INVALID_OPERATION
* @p createInfo is requesting a cubemap with
* non-square or non-2D images.
* @exception KTX_INVALID_OPERATION
* @p createInfo is requesting more mip levels
* than needed for the specified
* <tt>base{Width,Height,Depth}</tt>.
* @exception KTX_OUT_OF_MEMORY Not enough memory for the texture.
*/
KTX_error_code
ktxTexture_construct(ktxTexture* This, ktxTextureCreateInfo* createInfo,
ktxFormatSize* formatSize)
{
DECLARE_PROTECTED(ktxTexture);
memset(This, 0, sizeof(*This));
This->_protected = (struct ktxTexture_protected*)malloc(sizeof(*prtctd));
if (!This->_protected)
return KTX_OUT_OF_MEMORY;
prtctd = This->_protected;
memset(prtctd, 0, sizeof(*prtctd));
memcpy(&prtctd->_formatSize, formatSize, sizeof(prtctd->_formatSize));
This->isCompressed = (formatSize->flags & KTX_FORMAT_SIZE_COMPRESSED_BIT);
This->orientation.x = KTX_ORIENT_X_RIGHT;
This->orientation.y = KTX_ORIENT_Y_DOWN;
This->orientation.z = KTX_ORIENT_Z_OUT;
/* Check texture dimensions. KTX files can store 8 types of textures:
* 1D, 2D, 3D, cube, and array variants of these.
*/
if (createInfo->numDimensions < 1 || createInfo->numDimensions > 3)
return KTX_INVALID_VALUE;
if (createInfo->baseWidth == 0 || createInfo->baseHeight == 0
|| createInfo->baseDepth == 0)
return KTX_INVALID_VALUE;
switch (createInfo->numDimensions) {
case 1:
if (createInfo->baseHeight > 1 || createInfo->baseDepth > 1)
return KTX_INVALID_OPERATION;
break;
case 2:
if (createInfo->baseDepth > 1)
return KTX_INVALID_OPERATION;
break;
case 3:
/* 3D array textures and 3D cubemaps are not supported by either
* OpenGL or Vulkan.
*/
if (createInfo->isArray || createInfo->numFaces != 1
|| createInfo->numLayers != 1)
return KTX_INVALID_OPERATION;
break;
}
This->numDimensions = createInfo->numDimensions;
This->baseWidth = createInfo->baseWidth;
This->baseDepth = createInfo->baseDepth;
This->baseHeight = createInfo->baseHeight;
if (createInfo->numLayers == 0)
return KTX_INVALID_VALUE;
This->numLayers = createInfo->numLayers;
This->isArray = createInfo->isArray;
if (createInfo->numFaces == 6) {
if (This->numDimensions != 2) {
/* cube map needs 2D faces */
return KTX_INVALID_OPERATION;
}
if (createInfo->baseWidth != createInfo->baseHeight) {
/* cube maps require square images */
return KTX_INVALID_OPERATION;
}
This->isCubemap = KTX_TRUE;
} else if (createInfo->numFaces != 1) {
/* numFaces must be either 1 or 6 */
return KTX_INVALID_VALUE;
}
This->numFaces = createInfo->numFaces;
/* Check number of mipmap levels */
if (createInfo->numLevels == 0)
return KTX_INVALID_VALUE;
This->numLevels = createInfo->numLevels;
This->generateMipmaps = createInfo->generateMipmaps;
if (createInfo->numLevels > 1) {
GLuint max_dim = MAX(MAX(createInfo->baseWidth, createInfo->baseHeight),
createInfo->baseDepth);
if (max_dim < ((GLuint)1 << (This->numLevels - 1)))
{
/* Can't have more mip levels than 1 + log2(max(width, height, depth)) */
return KTX_INVALID_OPERATION;
}
}
ktxHashList_Construct(&This->kvDataHead);
return KTX_SUCCESS;
}
/**
* @memberof ktxTexture @private
* @~English
* @brief Construct (initialize) the part of a ktxTexture base class that is
* not related to the stream contents.
*
* @param[in] This pointer to a ktxTexture-sized block of memory to
* initialize.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*/
KTX_error_code
ktxTexture_constructFromStream(ktxTexture* This, ktxStream* pStream,
ktxTextureCreateFlags createFlags)
{
ktxStream* stream;
UNUSED(createFlags); // Reference to keep compiler happy.
assert(This != NULL);
assert(pStream->data.mem != NULL);
assert(pStream->type == eStreamTypeFile
|| pStream->type == eStreamTypeMemory
|| pStream->type == eStreamTypeCustom);
This->_protected = (struct ktxTexture_protected *)
malloc(sizeof(struct ktxTexture_protected));
stream = ktxTexture_getStream(This);
// Copy stream info into struct for later use.
*stream = *pStream;
This->orientation.x = KTX_ORIENT_X_RIGHT;
This->orientation.y = KTX_ORIENT_Y_DOWN;
This->orientation.z = KTX_ORIENT_Z_OUT;
return KTX_SUCCESS;
}
/**
* @memberof ktxTexture @private
* @~English
* @brief Free the memory associated with the texture contents
*
* @param[in] This pointer to the ktxTextureInt whose texture contents are
* to be freed.
*/
void
ktxTexture_destruct(ktxTexture* This)
{
ktxStream stream = *(ktxTexture_getStream(This));
if (stream.data.file != NULL)
stream.destruct(&stream);
if (This->kvDataHead != NULL)
ktxHashList_Destruct(&This->kvDataHead);
if (This->kvData != NULL)
free(This->kvData);
if (This->pData != NULL)
free(This->pData);
free(This->_protected);
}
/**
* @defgroup reader Reader
* @brief Read KTX-formatted data.
* @{
*/
typedef enum { KTX1, KTX2 } ktxFileType_;
typedef union {
KTX_header ktx;
KTX_header2 ktx2;
} ktxHeaderUnion_;
/**
* @memberof ktxTexture @private
* @~English
* @brief Determine if stream data is KTX1 or KTX2.
*
* @param pStream pointer to the ktxStream to examine.
* @param pFileType pointer to a ktxFileType enum where the type of the data
* will be written.
* @param pHeader pointer to a ktxHeaderUnion where the header info. will be
* written.
*/
static KTX_error_code
ktxDetermineFileType_(ktxStream* pStream, ktxFileType_* pFileType,
ktxHeaderUnion_* pHeader)
{
ktx_uint8_t ktx_ident_ref[12] = KTX_IDENTIFIER_REF;
ktx_uint8_t ktx2_ident_ref[12] = KTX2_IDENTIFIER_REF;
KTX_error_code result;
assert(pStream != NULL && pFileType != NULL);
assert(pStream->data.mem != NULL);
assert(pStream->type == eStreamTypeFile
|| pStream->type == eStreamTypeMemory
|| pStream->type == eStreamTypeCustom);
result = pStream->read(pStream, pHeader, sizeof(ktx2_ident_ref));
if (result == KTX_SUCCESS) {
#if BIG_ENDIAN
// byte swap the heaader fields
#endif
// Compare identifier, is this a KTX or KTX2 file?
if (!memcmp(pHeader->ktx.identifier, ktx_ident_ref, 12)) {
*pFileType = KTX1;
} else if (!memcmp(pHeader->ktx2.identifier, ktx2_ident_ref, 12)) {
*pFileType = KTX2;
} else {
return KTX_UNKNOWN_FILE_FORMAT;
}
// Read rest of header.
if (*pFileType == KTX1) {
// Read rest of header.
result = pStream->read(pStream, &pHeader->ktx.endianness,
KTX_HEADER_SIZE - sizeof(ktx_ident_ref));
} else {
result = pStream->read(pStream, &pHeader->ktx2.vkFormat,
KTX2_HEADER_SIZE - sizeof(ktx2_ident_ref));
}
}
return result;
}
/**
* @memberof ktxTexture
* @~English
* @brief Construct (initialize) a ktx1 or ktx2 texture according to the stream
* data.
*
* @copydetails ktxTexture_CreateFromStdioStream
*/
KTX_error_code
ktxTexture_CreateFromStream(ktxStream* pStream,
ktxTextureCreateFlags createFlags,
ktxTexture** newTex)
{
ktxHeaderUnion_ header;
ktxFileType_ fileType;
KTX_error_code result;
ktxTexture* tex;
result = ktxDetermineFileType_(pStream, &fileType, &header);
if (result != KTX_SUCCESS)
return result;
if (fileType == KTX1) {
ktxTexture1* tex1 = (ktxTexture1*)malloc(sizeof(ktxTexture1));
if (tex1 == NULL)
return KTX_OUT_OF_MEMORY;
memset(tex1, 0, sizeof(ktxTexture1));
result = ktxTexture1_constructFromStreamAndHeader(tex1, pStream,
&header.ktx,
createFlags);
tex = ktxTexture(tex1);
} else {
ktxTexture2* tex2 = (ktxTexture2*)malloc(sizeof(ktxTexture2));
if (tex2 == NULL)
return KTX_OUT_OF_MEMORY;
memset(tex2, 0, sizeof(ktxTexture2));
result = ktxTexture2_constructFromStreamAndHeader(tex2, pStream,
&header.ktx2,
createFlags);
tex = ktxTexture(tex2);
}
if (result == KTX_SUCCESS)
*newTex = (ktxTexture*)tex;
else {
free(tex);
*newTex = NULL;
}
return result;
}
/**
* @memberof ktxTexture
* @~English
* @brief Create a ktxTexture1 or ktxTexture2 from a stdio stream according
* to the stream data.
*
* @copydetails ktxTexture1_CreateFromStdioStream()
*/
KTX_error_code
ktxTexture_CreateFromStdioStream(FILE* stdioStream,
ktxTextureCreateFlags createFlags,
ktxTexture** newTex)
{
ktxStream stream;
KTX_error_code result;
if (stdioStream == NULL || newTex == NULL)
return KTX_INVALID_VALUE;
result = ktxFileStream_construct(&stream, stdioStream, KTX_FALSE);
if (result == KTX_SUCCESS) {
result = ktxTexture_CreateFromStream(&stream, createFlags, newTex);
}
return result;
}
/**
* @memberof ktxTexture
* @~English
* @brief Create a ktxTexture1 or ktxTexture2 from a named KTX file according
* to the file contents.
*
* The address of a newly created ktxTexture reflecting the contents of the
* file is written to the location pointed at by @p newTex.
*
* The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
* if the ktxTexture is ultimately to be uploaded to OpenGL or Vulkan. This
* will minimize memory usage by allowing, for example, loading the images
* directly from the source into a Vulkan staging buffer.
*
* The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is
* provided solely to enable implementation of the @e libktx v1 API on top of
* ktxTexture.
*
* @param[in] filename pointer to a char array containing the file name.
* @param[in] createFlags bitmask requesting specific actions during creation.
* @param[in,out] newTex pointer to a location in which store the address of
* the newly created texture.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
* @exception KTX_FILE_OPEN_FAILED The file could not be opened.
* @exception KTX_INVALID_VALUE @p filename is @c NULL.
*
* For other exceptions, see ktxTexture_CreateFromStdioStream().
*/
KTX_error_code
ktxTexture_CreateFromNamedFile(const char* const filename,
ktxTextureCreateFlags createFlags,
ktxTexture** newTex)
{
KTX_error_code result;
ktxStream stream;
FILE* file;
if (filename == NULL || newTex == NULL)
return KTX_INVALID_VALUE;
file = fopen(filename, "rb");
if (!file)
return KTX_FILE_OPEN_FAILED;
result = ktxFileStream_construct(&stream, file, KTX_TRUE);
if (result == KTX_SUCCESS) {
result = ktxTexture_CreateFromStream(&stream, createFlags, newTex);
}
return result;
}
/**
* @memberof ktxTexture
* @~English
* @brief Create a ktxTexture1 or ktxTexture2 from KTX-formatted data in memory
* according to the data contents.
*
* The address of a newly created ktxTexture reflecting the contents of the
* serialized KTX data is written to the location pointed at by @p newTex.
*
* The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
* if the ktxTexture is ultimately to be uploaded to OpenGL or Vulkan. This
* will minimize memory usage by allowing, for example, loading the images
* directly from the source into a Vulkan staging buffer.
*
* The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is
* provided solely to enable implementation of the @e libktx v1 API on top of
* ktxTexture.
*
* @param[in] bytes pointer to the memory containing the serialized KTX data.
* @param[in] size length of the KTX data in bytes.
* @param[in] createFlags bitmask requesting specific actions during creation.
* @param[in,out] newTex pointer to a location in which store the address of
* the newly created texture.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error.
*
* @exception KTX_INVALID_VALUE Either @p bytes is NULL or @p size is 0.
*
* For other exceptions, see ktxTexture_CreateFromStdioStream().
*/
KTX_error_code
ktxTexture_CreateFromMemory(const ktx_uint8_t* bytes, ktx_size_t size,
ktxTextureCreateFlags createFlags,
ktxTexture** newTex)
{
KTX_error_code result;
ktxStream stream;
if (bytes == NULL || newTex == NULL || size == 0)
return KTX_INVALID_VALUE;
result = ktxMemStream_construct_ro(&stream, bytes, size);
if (result == KTX_SUCCESS) {
result = ktxTexture_CreateFromStream(&stream, createFlags, newTex);
}
return result;}
/**
* @memberof ktxTexture
* @~English
* @brief Return a pointer to the texture image data.
*
* @param[in] This pointer to the ktxTexture object of interest.
*/
ktx_uint8_t*
ktxTexture_GetData(ktxTexture* This)
{
return This->pData;
}
/**
* @memberof ktxTexture
* @~English
* @brief Return the total size of the texture image data in bytes.
*
* For a ktxTexture2 with supercompressionScheme != KTX_SS_NONE this will
* return the deflated size of the data.
*
* @param[in] This pointer to the ktxTexture object of interest.
*/
ktx_size_t
ktxTexture_GetDataSize(ktxTexture* This)
{
assert(This != NULL);
return This->dataSize;
}
/**
* @memberof ktxTexture
* @~English
* @brief Return the size in bytes of an elements of a texture's
* images.
*
* For uncompressed textures an element is one texel. For compressed
* textures it is one block.
*
* @param[in] This pointer to the ktxTexture object of interest.
*/
ktx_uint32_t
ktxTexture_GetElementSize(ktxTexture* This)
{
assert (This != NULL);
return (This->_protected->_formatSize.blockSizeInBits / 8);
}
/**
* @memberof ktxTexture @private
* @~English
* @brief Calculate & return the size in bytes of an image at the specified
* mip level.
*
* For arrays, this is the size of layer, for cubemaps, the size of a face
* and for 3D textures, the size of a depth slice.
*
* The size reflects the padding of each row to KTX_GL_UNPACK_ALIGNMENT.
*
* @param[in] This pointer to the ktxTexture object of interest.
* @param[in] level level of interest.
* @param[in] fv enum specifying format version for which to calculate
* image size.
*/
ktx_size_t
ktxTexture_calcImageSize(ktxTexture* This, ktx_uint32_t level,
ktxFormatVersionEnum fv)
{
DECLARE_PROTECTED(ktxTexture);
struct blockCount {
ktx_uint32_t x, y;
} blockCount;
ktx_uint32_t blockSizeInBytes;
ktx_uint32_t rowBytes;
assert (This != NULL);
float levelWidth = (float)(This->baseWidth >> level);
float levelHeight = (float)(This->baseHeight >> level);
// Round up to next whole block. We can't use KTX_PADN because some of
// the block sizes are not powers of 2.
blockCount.x
= (ktx_uint32_t)ceilf(levelWidth / prtctd->_formatSize.blockWidth);
blockCount.y
= (ktx_uint32_t)ceilf(levelHeight / prtctd->_formatSize.blockHeight);
blockCount.x = MAX(prtctd->_formatSize.minBlocksX, blockCount.x);
blockCount.y = MAX(prtctd->_formatSize.minBlocksX, blockCount.y);
blockSizeInBytes = prtctd->_formatSize.blockSizeInBits / 8;
if (prtctd->_formatSize.flags & KTX_FORMAT_SIZE_COMPRESSED_BIT) {
assert(This->isCompressed);
return blockCount.x * blockCount.y * blockSizeInBytes;
} else {
assert(prtctd->_formatSize.blockWidth == 1U
&& prtctd->_formatSize.blockHeight == 1U
&& prtctd->_formatSize.blockDepth == 1U);
rowBytes = blockCount.x * blockSizeInBytes;
if (fv == KTX_FORMAT_VERSION_ONE)
(void)padRow(&rowBytes);
return rowBytes * blockCount.y;
}
}
/**
* @memberof ktxTexture
* @~English
* @brief Iterate over the levels or faces in a ktxTexture object.
*
* Blocks of image data are passed to an application-supplied callback
* function. This is not a strict per-image iteration. Rather it reflects how
* OpenGL needs the images. For most textures the block of data includes all
* images of a mip level which implies all layers of an array. However, for
* non-array cube map textures the block is a single face of the mip level,
* i.e the callback is called once for each face.
*
* This function works even if @p This->pData == 0 so it can be used to
* obtain offsets and sizes for each level by callers who have loaded the data
* externally.
*
* @param[in] This pointer to the ktxTexture object of interest.
* @param[in,out] iterCb the address of a callback function which is called
* with the data for each image block.
* @param[in,out] userdata the address of application-specific data which is
* passed to the callback along with the image data.
*
* @return KTX_SUCCESS on success, other KTX_* enum values on error. The
* following are returned directly by this function. @p iterCb may
* return these for other causes or may return additional errors.
*
* @exception KTX_FILE_DATA_ERROR Mip level sizes are increasing not
* decreasing
* @exception KTX_INVALID_VALUE @p This is @c NULL or @p iterCb is @c NULL.
*
*/
KTX_error_code
ktxTexture_IterateLevelFaces(ktxTexture* This, PFNKTXITERCB iterCb,
void* userdata)
{
ktx_uint32_t miplevel;
KTX_error_code result = KTX_SUCCESS;
if (This == NULL)
return KTX_INVALID_VALUE;
if (iterCb == NULL)
return KTX_INVALID_VALUE;
for (miplevel = 0; miplevel < This->numLevels; ++miplevel)
{
ktx_uint32_t faceLodSize;
ktx_uint32_t face;
ktx_uint32_t innerIterations;
GLsizei width, height, depth;
/* Array textures have the same number of layers at each mip level. */
width = MAX(1, This->baseWidth >> miplevel);
height = MAX(1, This->baseHeight >> miplevel);
depth = MAX(1, This->baseDepth >> miplevel);
faceLodSize = (ktx_uint32_t)ktxTexture_calcFaceLodSize(
This, miplevel);
/* All array layers are passed in a group because that is how
* GL & Vulkan need them. Hence no
* for (layer = 0; layer < This->numLayers)
*/
if (This->isCubemap && !This->isArray)
innerIterations = This->numFaces;
else
innerIterations = 1;
for (face = 0; face < innerIterations; ++face)
{
/* And all z_slices are also passed as a group hence no
* for (slice = 0; slice < This->depth)
*/
ktx_size_t offset;
ktxTexture_GetImageOffset(This, miplevel, 0, face, &offset);
result = iterCb(miplevel, face,
width, height, depth,
faceLodSize, This->pData + offset, userdata);
if (result != KTX_SUCCESS)
break;
}
}
return result;
}
/**
* @internal
* @brief Calculate and apply the padding needed to comply with
* KTX_GL_UNPACK_ALIGNMENT.
*
* For uncompressed textures, KTX format specifies KTX_GL_UNPACK_ALIGNMENT = 4.
*
* @param[in,out] rowBytes pointer to variable containing the packed no. of
* bytes in a row. The no. of bytes after padding
* is written into this location.
* @return the no. of bytes of padding.
*/
static ktx_uint32_t
padRow(ktx_uint32_t* rowBytes)
{
ktx_uint32_t rowPadding;
assert (rowBytes != NULL);
rowPadding = _KTX_PAD_UNPACK_ALIGN_LEN(*rowBytes);
*rowBytes += rowPadding;
return rowPadding;
}
/**
* @memberof ktxTexture @private
* @~English
* @brief Calculate the size of an array layer at the specified mip level.
*
* The size of a layer is the size of an image * either the number of faces
* or the number of depth slices. This is the size of a layer as needed to
* find the offset within the array of images of a level and layer so the size
* reflects any @c cubePadding.
*
* @param[in] This pointer to the ktxTexture object of interest.
* @param[in] level level whose layer size to return.
*
* @return the layer size in bytes.
*/
ktx_size_t
ktxTexture_layerSize(ktxTexture* This, ktx_uint32_t level,
ktxFormatVersionEnum fv)
{
/*
* As there are no 3D cubemaps, the image's z block count will always be
* 1 for cubemaps and numFaces will always be 1 for 3D textures so the
* multiply is safe. 3D cubemaps, if they existed, would require
* imageSize * (blockCount.z + This->numFaces);
*/
DECLARE_PROTECTED(ktxTexture);
ktx_uint32_t blockCountZ;
ktx_size_t imageSize, layerSize;
assert (This != NULL);
blockCountZ = MAX(1, (This->baseDepth / prtctd->_formatSize.blockDepth) >> level);
imageSize = ktxTexture_calcImageSize(This, level, fv);
layerSize = imageSize * blockCountZ;
if (fv == KTX_FORMAT_VERSION_ONE && KTX_GL_UNPACK_ALIGNMENT != 4) {
if (This->isCubemap && !This->isArray) {
/* cubePadding. NOTE: this adds padding after the last face too. */
layerSize += _KTX_PAD4(layerSize);
}
}
return layerSize * This->numFaces;
}
/**
* @memberof ktxTexture @private
* @~English
* @brief Calculate the size of the specified mip level.
*
* The size of a level is the size of a layer * the number of layers.
*
* @param[in] This pointer to the ktxTexture object of interest.
* @param[in] level level whose layer size to return.
*
* @return the level size in bytes.
*/
ktx_size_t
ktxTexture_calcLevelSize(ktxTexture* This, ktx_uint32_t level,
ktxFormatVersionEnum fv)
{
assert (This != NULL);
assert (level < This->numLevels);
return ktxTexture_layerSize(This, level, fv) * This->numLayers;
}
/**
* @memberof ktxTexture @private
* @~English
* @brief Calculate the faceLodSize of the specified mip level.
*
* The faceLodSize of a level for most textures is the size of a level. For
* non-array cube map textures is the size of a face. This is the size that
* must be provided to OpenGL when uploading textures. Faces get uploaded 1
* at a time while all layers of an array or all slices of a 3D texture are
* uploaded together.
*
* @param[in] This pointer to the ktxTexture object of interest.
* @param[in] level level whose layer size to return.
*
* @return the faceLodSize size in bytes.
*/
ktx_size_t
ktxTexture_doCalcFaceLodSize(ktxTexture* This, ktx_uint32_t level,
ktxFormatVersionEnum fv)
{
/*
* For non-array cubemaps this is the size of a face. For everything
* else it is the size of the level.
*/
if (This->isCubemap && !This->isArray)
return ktxTexture_calcImageSize(This, level, fv);
else
return ktxTexture_calcLevelSize(This, level, fv);
}
/**
* @memberof ktxTexture @private
* @~English
* @brief Return the number of bytes needed to store all the image data for
* a ktxTexture.
*
* The caclulated size does not include space for storing the @c imageSize
* fields of each mip level.
*
* @param[in] This pointer to the ktxTexture object of interest.
* @param[in] fv enum specifying format version for which to calculate
* image size.
*
* @return the data size in bytes.
*/
ktx_size_t
ktxTexture_calcDataSizeTexture(ktxTexture* This)
{
assert (This != NULL);
return ktxTexture_calcDataSizeLevels(This, This->numLevels);
}
/**
* @memberof ktxTexture @private
* @~English
* @brief Get information about rows of an uncompresssed texture image at a
* specified level.
*
* For an image at @p level of a ktxTexture provide the number of rows, the
* packed (unpadded) number of bytes in a row and the padding necessary to
* comply with KTX_GL_UNPACK_ALIGNMENT.
*
* @param[in] This pointer to the ktxTexture object of interest.
* @param[in] level level of interest.
* @param[in,out] numRows pointer to location to store the number of rows.
* @param[in,out] pRowLengthBytes pointer to location to store number of bytes
* in a row.
* @param[in.out] pRowPadding pointer to location to store the number of bytes
* of padding.
*/
void
ktxTexture_rowInfo(ktxTexture* This, ktx_uint32_t level,
ktx_uint32_t* numRows, ktx_uint32_t* pRowLengthBytes,
ktx_uint32_t* pRowPadding)
{
DECLARE_PROTECTED(ktxTexture);
struct blockCount {
ktx_uint32_t x;
} blockCount;
assert (This != NULL);
assert(!This->isCompressed);
assert(prtctd->_formatSize.blockWidth == 1U
&& prtctd->_formatSize.blockHeight == 1U
&& prtctd->_formatSize.blockDepth == 1U);
blockCount.x = MAX(1, (This->baseWidth / prtctd->_formatSize.blockWidth) >> level);
*numRows = MAX(1, (This->baseHeight / prtctd->_formatSize.blockHeight) >> level);
*pRowLengthBytes = blockCount.x * prtctd->_formatSize.blockSizeInBits / 8;
*pRowPadding = padRow(pRowLengthBytes);
}
/**
* @memberof ktxTexture
* @~English
* @brief Return pitch betweeb rows of a texture image level in bytes.
*
* For uncompressed textures the pitch is the number of bytes between
* rows of texels. For compressed textures it is the number of bytes
* between rows of blocks. The value is padded to GL_UNPACK_ALIGNMENT,
* if necessary. For all currently known compressed formats padding
* will not be necessary.
*
* @param[in] This pointer to the ktxTexture object of interest.
* @param[in] level level of interest.
*
* @return the row pitch in bytes.
*/
ktx_uint32_t
ktxTexture_GetRowPitch(ktxTexture* This, ktx_uint32_t level)
{
DECLARE_PROTECTED(ktxTexture)
struct blockCount {
ktx_uint32_t x;
} blockCount;
ktx_uint32_t pitch;
blockCount.x = MAX(1, (This->baseWidth / prtctd->_formatSize.blockWidth) >> level);
pitch = blockCount.x * prtctd->_formatSize.blockSizeInBits / 8;
(void)padRow(&pitch);
return pitch;
}
/**
* @memberof ktxTexture @private
* @~English
* @brief Query if a ktxTexture has an active stream.
*
* Tests if a ktxTexture has unread image data. The internal stream is closed
* once all the images have been read.
*
* @param[in] This pointer to the ktxTexture object of interest.
*
* @return KTX_TRUE if there is an active stream, KTX_FALSE otherwise.
*/
ktx_bool_t
ktxTexture_isActiveStream(ktxTexture* This)
{
assert(This != NULL);
ktxStream* stream = ktxTexture_getStream(This);
return stream->data.file != NULL;
}
/** @} */

107
thirdparty/libktx/lib/texture.h vendored Normal file
View File

@ -0,0 +1,107 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab textwidth=70: */
/*
* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file texture.h
* @~English
*
* @brief Declare internal ktxTexture functions for sharing between
* compilation units.
*
* These functions are private and should not be used outside the library.
*/
#ifndef _TEXTURE_H_
#define _TEXTURE_H_
#include "ktx.h"
#include "formatsize.h"
#define DECLARE_PRIVATE(class) class ## _private* private = This->_private
#define DECLARE_PROTECTED(class) class ## _protected* prtctd = This->_protected;
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
KTX_FORMAT_VERSION_ONE = 1,
KTX_FORMAT_VERSION_TWO = 2
} ktxFormatVersionEnum;
typedef ktx_size_t (* PFNCALCDATASIZELEVELS)(ktxTexture* This,
ktx_uint32_t levels);
typedef ktx_size_t (* PFNCALCFACELODSIZE)(ktxTexture* This, ktx_uint32_t level);
typedef ktx_size_t (* PFNCALCLEVELOFFSET)(ktxTexture* This, ktx_uint32_t level);
typedef struct ktxTexture_vtblInt {
PFNCALCDATASIZELEVELS calcDataSizeLevels;
PFNCALCFACELODSIZE calcFaceLodSize;
PFNCALCLEVELOFFSET calcLevelOffset;
} ktxTexture_vtblInt;
#define ktxTexture_calcDataSizeLevels(This, levels) \
This->_protected->_vtbl.calcDataSizeLevels(This, levels);
#define ktxTexture_calcFaceLodSize(This, level) \
This->_protected->_vtbl.calcFaceLodSize(This, level);
#define ktxTexture_calcLevelOffset(This, level) \
This->_protected->_vtbl.calcLevelOffset(This, level);
/**
* @memberof ktxTexture
* @~English
*
* @brief protected members of ktxTexture.
*/
typedef struct ktxTexture_protected {
ktxTexture_vtblInt _vtbl;
ktxFormatSize _formatSize;
ktx_uint32_t _typeSize;
ktxStream _stream;
} ktxTexture_protected;
#define ktxTexture_getStream(t) ((ktxStream*)(&(t)->_protected->_stream))
#define ktxTexture1_getStream(t1) ktxTexture_getStream((ktxTexture*)t1)
#define ktxTexture2_getStream(t2) ktxTexture_getStream((ktxTexture*)t2)
KTX_error_code
ktxTexture_iterateLoadedImages(ktxTexture* This, PFNKTXITERCB iterCb,
void* userdata);
KTX_error_code
ktxTexture_iterateSourceImages(ktxTexture* This, PFNKTXITERCB iterCb,
void* userdata);
ktx_size_t ktxTexture_calcDataSizeTexture(ktxTexture* This);
ktx_size_t ktxTexture_calcImageSize(ktxTexture* This, ktx_uint32_t level,
ktxFormatVersionEnum fv);
ktx_bool_t ktxTexture_isActiveStream(ktxTexture* This);
ktx_size_t ktxTexture_calcLevelSize(ktxTexture* This, ktx_uint32_t level,
ktxFormatVersionEnum fv);
ktx_size_t ktxTexture_doCalcFaceLodSize(ktxTexture* This, ktx_uint32_t level,
ktxFormatVersionEnum fv);
ktx_size_t ktxTexture_layerSize(ktxTexture* This, ktx_uint32_t level,
ktxFormatVersionEnum fv);
void ktxTexture_rowInfo(ktxTexture* This, ktx_uint32_t level,
ktx_uint32_t* numRows, ktx_uint32_t* rowBytes,
ktx_uint32_t* rowPadding);
KTX_error_code
ktxTexture_construct(ktxTexture* This, ktxTextureCreateInfo* createInfo,
ktxFormatSize* formatSize);
KTX_error_code
ktxTexture_constructFromStream(ktxTexture* This, ktxStream* pStream,
ktxTextureCreateFlags createFlags);
void
ktxTexture_destruct(ktxTexture* This);
#ifdef __cplusplus
}
#endif
#endif /* _TEXTURE_H_ */

1459
thirdparty/libktx/lib/texture1.c vendored Normal file

File diff suppressed because it is too large Load Diff

46
thirdparty/libktx/lib/texture1.h vendored Normal file
View File

@ -0,0 +1,46 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab textwidth=70: */
/*
* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file texture1.h
* @~English
*
* @brief Declare internal ktxTexture1 functions for sharing between
* compilation units.
*
* These functions are private and should not be used outside the library.
*/
#ifndef _TEXTURE1_H_
#define _TEXTURE1_H_
#include "texture.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CLASS ktxTexture1
#include "texture_funcs.inl"
#undef CLASS
KTX_error_code
ktxTexture1_constructFromStreamAndHeader(ktxTexture1* This, ktxStream* pStream,
KTX_header* pHeader,
ktxTextureCreateFlags createFlags);
ktx_uint64_t ktxTexture1_calcDataSizeTexture(ktxTexture1* This);
ktx_size_t ktxTexture1_calcLevelOffset(ktxTexture1* This, ktx_uint32_t level);
ktx_uint32_t ktxTexture1_glTypeSize(ktxTexture1* This);
#ifdef __cplusplus
}
#endif
#endif /* _TEXTURE1_H_ */

2524
thirdparty/libktx/lib/texture2.c vendored Normal file

File diff suppressed because it is too large Load Diff

68
thirdparty/libktx/lib/texture2.h vendored Normal file
View File

@ -0,0 +1,68 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab textwidth=70: */
/*
* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file texture2.h
* @~English
*
* @brief Declare internal ktxTexture2 functions for sharing between
* compilation units.
*
* These functions are private and should not be used outside the library.
*/
#ifndef _TEXTURE2_H_
#define _TEXTURE2_H_
#include "texture.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CLASS ktxTexture2
#include "texture_funcs.inl"
#undef CLASS
typedef struct ktxTexture2_private {
ktx_uint8_t* _supercompressionGlobalData;
ktx_uint32_t _requiredLevelAlignment;
ktx_uint64_t _sgdByteLength;
ktx_uint64_t _firstLevelFileOffset; /*!< Always 0, unless the texture was
created from a stream and the image
data is not yet loaded. */
// Must be last so it can grow.
ktxLevelIndexEntry _levelIndex[1]; /*!< Offsets in this index are from the
start of the image data. Use
ktxTexture_levelStreamOffset() and
ktxTexture_levelDataOffset(). The former
will add the above file offset to the
index offset. */
} ktxTexture2_private;
KTX_error_code
ktxTexture2_LoadImageData(ktxTexture2* This,
ktx_uint8_t* pBuffer, ktx_size_t bufSize);
KTX_error_code
ktxTexture2_constructFromStreamAndHeader(ktxTexture2* This, ktxStream* pStream,
KTX_header2* pHeader,
ktxTextureCreateFlags createFlags);
ktx_uint64_t ktxTexture2_calcDataSizeTexture(ktxTexture2* This);
ktx_size_t ktxTexture2_calcLevelOffset(ktxTexture2* This, ktx_uint32_t level);
ktx_uint32_t ktxTexture2_calcRequiredLevelAlignment(ktxTexture2* This);
ktx_uint64_t ktxTexture2_levelFileOffset(ktxTexture2* This, ktx_uint32_t level);
ktx_uint64_t ktxTexture2_levelDataOffset(ktxTexture2* This, ktx_uint32_t level);
#ifdef __cplusplus
}
#endif
#endif /* _TEXTURE2_H_ */

76
thirdparty/libktx/lib/texture_funcs.inl vendored Normal file
View File

@ -0,0 +1,76 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab textwidth=70: */
/*
* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file texture_funcs.h
* @~English
*
* @brief Templates for functions common to base & derived ktxTexture classes.
*
* Define CLASS before including this file.
*/
#define CAT(c, n) PRIMITIVE_CAT(c, n)
#define PRIMITIVE_CAT(c, n) c ## _ ## n
#define CLASS_FUNC(name) CAT(CLASS, name)
/*
======================================
Virtual ktxTexture functions
======================================
*/
void CLASS_FUNC(Destroy)(CLASS* This);
KTX_error_code CLASS_FUNC(GetImageOffset)(CLASS* This, ktx_uint32_t level,
ktx_uint32_t layer,
ktx_uint32_t faceSlice,
ktx_size_t* pOffset);
ktx_size_t CLASS_FUNC(GetImageSize)(CLASS* This, ktx_uint32_t level);
KTX_error_code CLASS_FUNC(GLUpload)(CLASS* This, GLuint* pTexture,
GLenum* pTarget, GLenum* pGlerror);
KTX_error_code CLASS_FUNC(IterateLevels)(CLASS* This,
PFNKTXITERCB iterCb,
void* userdata);
KTX_error_code CLASS_FUNC(IterateLevelFaces)(CLASS* This,
PFNKTXITERCB iterCb,
void* userdata);
KTX_error_code CLASS_FUNC(IterateLoadLevelFaces)(CLASS* This,
PFNKTXITERCB iterCb,
void* userdata);
KTX_error_code CLASS_FUNC(LoadImageData)(CLASS* This,
ktx_uint8_t* pBuffer,
ktx_size_t bufSize);
KTX_error_code CLASS_FUNC(SetImageFromStdioStream)(CLASS* This,
ktx_uint32_t level,ktx_uint32_t layer,
ktx_uint32_t faceSlice,
FILE* src, ktx_size_t srcSize);
KTX_error_code CLASS_FUNC(SetImageFromMemory)(CLASS* This,
ktx_uint32_t level, ktx_uint32_t layer,
ktx_uint32_t faceSlice,
const ktx_uint8_t* src, ktx_size_t srcSize);
KTX_error_code CLASS_FUNC(WriteToStdioStream)(CLASS* This, FILE* dstsstr);
KTX_error_code CLASS_FUNC(WriteToNamedFile)(CLASS* This,
const char* const dstname);
KTX_error_code CLASS_FUNC(WriteToMemory)(CLASS* This,
ktx_uint8_t** ppDstBytes, ktx_size_t* pSize);
KTX_error_code CLASS_FUNC(WriteToStream)(CLASS* This,
ktxStream* dststr);
/*
======================================
Internal ktxTexture functions
======================================
*/
void CLASS_FUNC(destruct)(CLASS* This);

942
thirdparty/libktx/lib/uthash.h vendored Normal file
View File

@ -0,0 +1,942 @@
/*
Copyright (c) 2003-2010, Troy D. Hanson http://uthash.sourceforge.net All rights reserved.
SPDX-License-Identifier: BSD-1-Clause
*/
#ifndef UTHASH_H
#define UTHASH_H
#include <string.h> /* memcmp,strlen */
#include <stddef.h> /* ptrdiff_t */
/* These macros use decltype or the earlier __typeof GNU extension.
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
when compiling c++ source) this code uses whatever method is needed
or, for VS2008 where neither is available, uses casting workarounds. */
#ifdef _MSC_VER /* MS compiler */
#if _MSC_VER >= 1600 && __cplusplus /* VS2010 or newer in C++ mode */
#define DECLTYPE(x) (decltype(x))
#else /* VS2008 or older (or VS2010 in C mode) */
#define NO_DECLTYPE
#define DECLTYPE(x)
#endif
#else /* GNU, Sun and other compilers */
#define DECLTYPE(x) (__typeof(x))
#endif
#ifdef NO_DECLTYPE
#define DECLTYPE_ASSIGN(dst,src) \
do { \
char **_da_dst = (char**)(&(dst)); \
*_da_dst = (char*)(src); \
} while(0)
#else
#define DECLTYPE_ASSIGN(dst,src) \
do { \
(dst) = DECLTYPE(dst)(src); \
} while(0)
#endif
/* a number of the hash function use uint32_t which isn't defined on win32 */
#ifdef _MSC_VER
typedef unsigned int uint32_t;
#else
#include <inttypes.h> /* uint32_t */
#endif
#define UTHASH_VERSION 1.9.1
#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
#define uthash_free(ptr) free(ptr) /* free fcn */
#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
/* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
/* calculate the element whose hash handle address is hhe */
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
#define HASH_FIND(hh,head,keyptr,keylen,out) \
do { \
unsigned _hf_bkt,_hf_hashv; \
out=NULL; \
if (head) { \
HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
keyptr,keylen,out); \
} \
} \
} while (0)
#ifdef HASH_BLOOM
#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
#define HASH_BLOOM_MAKE(tbl) \
do { \
(tbl)->bloom_nbits = HASH_BLOOM; \
(tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
} while (0);
#define HASH_BLOOM_FREE(tbl) \
do { \
uthash_free((tbl)->bloom_bv); \
} while (0);
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
#define HASH_BLOOM_ADD(tbl,hashv) \
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#define HASH_BLOOM_TEST(tbl,hashv) \
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#else
#define HASH_BLOOM_MAKE(tbl)
#define HASH_BLOOM_FREE(tbl)
#define HASH_BLOOM_ADD(tbl,hashv)
#define HASH_BLOOM_TEST(tbl,hashv) (1)
#endif
#define HASH_MAKE_TABLE(hh,head) \
do { \
(head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
sizeof(UT_hash_table)); \
if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
(head)->hh.tbl->tail = &((head)->hh); \
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
(head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
(head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
memset((head)->hh.tbl->buckets, 0, \
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
HASH_BLOOM_MAKE((head)->hh.tbl); \
(head)->hh.tbl->signature = HASH_SIGNATURE; \
} while(0)
#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add)
#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
do { \
unsigned _ha_bkt; \
(add)->hh.next = NULL; \
(add)->hh.key = (char*)keyptr; \
(add)->hh.keylen = keylen_in; \
if (!(head)) { \
head = (add); \
(head)->hh.prev = NULL; \
HASH_MAKE_TABLE(hh,head); \
} else { \
(head)->hh.tbl->tail->next = (add); \
(add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
(head)->hh.tbl->tail = &((add)->hh); \
} \
(head)->hh.tbl->num_items++; \
(add)->hh.tbl = (head)->hh.tbl; \
HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
(add)->hh.hashv, _ha_bkt); \
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
HASH_FSCK(hh,head); \
} while(0)
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
do { \
bkt = ((hashv) & ((num_bkts) - 1)); \
} while(0)
/* delete "delptr" from the hash table.
* "the usual" patch-up process for the app-order doubly-linked-list.
* The use of _hd_hh_del below deserves special explanation.
* These used to be expressed using (delptr) but that led to a bug
* if someone used the same symbol for the head and deletee, like
* HASH_DELETE(hh,users,users);
* We want that to work, but by changing the head (users) below
* we were forfeiting our ability to further refer to the deletee (users)
* in the patch-up process. Solution: use scratch space to
* copy the deletee pointer, then the latter references are via that
* scratch pointer rather than through the repointed (users) symbol.
*/
#define HASH_DELETE(hh,head,delptr) \
do { \
unsigned _hd_bkt; \
struct UT_hash_handle *_hd_hh_del; \
if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
uthash_free((head)->hh.tbl->buckets ); \
HASH_BLOOM_FREE((head)->hh.tbl); \
uthash_free((head)->hh.tbl); \
head = NULL; \
} else { \
_hd_hh_del = &((delptr)->hh); \
if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
(head)->hh.tbl->tail = \
(UT_hash_handle*)((char*)((delptr)->hh.prev) + \
(head)->hh.tbl->hho); \
} \
if ((delptr)->hh.prev) { \
((UT_hash_handle*)((char*)((delptr)->hh.prev) + \
(head)->hh.tbl->hho))->next = (delptr)->hh.next; \
} else { \
DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
} \
if (_hd_hh_del->next) { \
((UT_hash_handle*)((char*)_hd_hh_del->next + \
(head)->hh.tbl->hho))->prev = \
_hd_hh_del->prev; \
} \
HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
(head)->hh.tbl->num_items--; \
} \
HASH_FSCK(hh,head); \
} while (0)
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
#define HASH_FIND_STR(head,findstr,out) \
HASH_FIND(hh,head,findstr,strlen(findstr),out)
#define HASH_ADD_STR(head,strfield,add) \
HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
#define HASH_FIND_INT(head,findint,out) \
HASH_FIND(hh,head,findint,sizeof(int),out)
#define HASH_ADD_INT(head,intfield,add) \
HASH_ADD(hh,head,intfield,sizeof(int),add)
#define HASH_FIND_PTR(head,findptr,out) \
HASH_FIND(hh,head,findptr,sizeof(void *),out)
#define HASH_ADD_PTR(head,ptrfield,add) \
HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
#define HASH_DEL(head,delptr) \
HASH_DELETE(hh,head,delptr)
/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
*/
#ifdef HASH_DEBUG
#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
#define HASH_FSCK(hh,head) \
do { \
unsigned _bkt_i; \
unsigned _count, _bkt_count; \
char *_prev; \
struct UT_hash_handle *_thh; \
if (head) { \
_count = 0; \
for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
_bkt_count = 0; \
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
_prev = NULL; \
while (_thh) { \
if (_prev != (char*)(_thh->hh_prev)) { \
HASH_OOPS("invalid hh_prev %p, actual %p\n", \
_thh->hh_prev, _prev ); \
} \
_bkt_count++; \
_prev = (char*)(_thh); \
_thh = _thh->hh_next; \
} \
_count += _bkt_count; \
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
HASH_OOPS("invalid bucket count %d, actual %d\n", \
(head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
} \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid hh item count %d, actual %d\n", \
(head)->hh.tbl->num_items, _count ); \
} \
/* traverse hh in app order; check next/prev integrity, count */ \
_count = 0; \
_prev = NULL; \
_thh = &(head)->hh; \
while (_thh) { \
_count++; \
if (_prev !=(char*)(_thh->prev)) { \
HASH_OOPS("invalid prev %p, actual %p\n", \
_thh->prev, _prev ); \
} \
_prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
_thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
(head)->hh.tbl->hho) : NULL ); \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid app item count %d, actual %d\n", \
(head)->hh.tbl->num_items, _count ); \
} \
} \
} while (0)
#else
#define HASH_FSCK(hh,head)
#endif
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
* the descriptor to which this macro is defined for tuning the hash function.
* The app can #include <unistd.h> to get the prototype for write(2). */
#ifdef HASH_EMIT_KEYS
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
do { \
unsigned _klen = fieldlen; \
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
write(HASH_EMIT_KEYS, keyptr, fieldlen); \
} while (0)
#else
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
#endif
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
#ifdef HASH_FUNCTION
#define HASH_FCN HASH_FUNCTION
#else
#define HASH_FCN HASH_JEN
#endif
/* The Bernstein hash function, used in Perl prior to v5.6 */
#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _hb_keylen=keylen; \
char *_hb_key=(char*)key; \
(hashv) = 0; \
while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
bkt = (hashv) & (num_bkts-1); \
} while (0)
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _sx_i; \
char *_hs_key=(char*)key; \
hashv = 0; \
for(_sx_i=0; _sx_i < keylen; _sx_i++) \
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
bkt = hashv & (num_bkts-1); \
} while (0)
#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _fn_i; \
char *_hf_key=(char*)key; \
hashv = 2166136261UL; \
for(_fn_i=0; _fn_i < keylen; _fn_i++) \
hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
bkt = hashv & (num_bkts-1); \
} while(0);
#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _ho_i; \
char *_ho_key=(char*)key; \
hashv = 0; \
for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
hashv += _ho_key[_ho_i]; \
hashv += (hashv << 10); \
hashv ^= (hashv >> 6); \
} \
hashv += (hashv << 3); \
hashv ^= (hashv >> 11); \
hashv += (hashv << 15); \
bkt = hashv & (num_bkts-1); \
} while(0)
#define HASH_JEN_MIX(a,b,c) \
do { \
a -= b; a -= c; a ^= ( c >> 13 ); \
b -= c; b -= a; b ^= ( a << 8 ); \
c -= a; c -= b; c ^= ( b >> 13 ); \
a -= b; a -= c; a ^= ( c >> 12 ); \
b -= c; b -= a; b ^= ( a << 16 ); \
c -= a; c -= b; c ^= ( b >> 5 ); \
a -= b; a -= c; a ^= ( c >> 3 ); \
b -= c; b -= a; b ^= ( a << 10 ); \
c -= a; c -= b; c ^= ( b >> 15 ); \
} while (0)
#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _hj_i,_hj_j,_hj_k; \
char *_hj_key=(char*)key; \
hashv = 0xfeedbeef; \
_hj_i = _hj_j = 0x9e3779b9; \
_hj_k = keylen; \
while (_hj_k >= 12) { \
_hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
+ ( (unsigned)_hj_key[2] << 16 ) \
+ ( (unsigned)_hj_key[3] << 24 ) ); \
_hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
+ ( (unsigned)_hj_key[6] << 16 ) \
+ ( (unsigned)_hj_key[7] << 24 ) ); \
hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
+ ( (unsigned)_hj_key[10] << 16 ) \
+ ( (unsigned)_hj_key[11] << 24 ) ); \
\
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
\
_hj_key += 12; \
_hj_k -= 12; \
} \
hashv += keylen; \
switch ( _hj_k ) { \
case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
case 5: _hj_j += _hj_key[4]; \
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
case 1: _hj_i += _hj_key[0]; \
} \
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
bkt = hashv & (num_bkts-1); \
} while(0)
/* The Paul Hsieh hash function */
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
#define get16bits(d) (*((const uint16_t *) (d)))
#endif
#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
do { \
char *_sfh_key=(char*)key; \
uint32_t _sfh_tmp, _sfh_len = keylen; \
\
int _sfh_rem = _sfh_len & 3; \
_sfh_len >>= 2; \
hashv = 0xcafebabe; \
\
/* Main loop */ \
for (;_sfh_len > 0; _sfh_len--) { \
hashv += get16bits (_sfh_key); \
_sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \
hashv = (hashv << 16) ^ _sfh_tmp; \
_sfh_key += 2*sizeof (uint16_t); \
hashv += hashv >> 11; \
} \
\
/* Handle end cases */ \
switch (_sfh_rem) { \
case 3: hashv += get16bits (_sfh_key); \
hashv ^= hashv << 16; \
hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \
hashv += hashv >> 11; \
break; \
case 2: hashv += get16bits (_sfh_key); \
hashv ^= hashv << 11; \
hashv += hashv >> 17; \
break; \
case 1: hashv += *_sfh_key; \
hashv ^= hashv << 10; \
hashv += hashv >> 1; \
} \
\
/* Force "avalanching" of final 127 bits */ \
hashv ^= hashv << 3; \
hashv += hashv >> 5; \
hashv ^= hashv << 4; \
hashv += hashv >> 17; \
hashv ^= hashv << 25; \
hashv += hashv >> 6; \
bkt = hashv & (num_bkts-1); \
} while(0);
#ifdef HASH_USING_NO_STRICT_ALIASING
/* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads.
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
* So MurmurHash comes in two versions, the faster unaligned one and the slower
* aligned one. We only use the faster one on CPU's where we know it's safe.
*
* Note the preprocessor built-in defines can be emitted using:
*
* gcc -m64 -dM -E - < /dev/null (on gcc)
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
*/
#if (defined(__i386__) || defined(__x86_64__))
#define HASH_MUR HASH_MUR_UNALIGNED
#else
#define HASH_MUR HASH_MUR_ALIGNED
#endif
/* Appleby's MurmurHash fast version for unaligned-tolerant archs like i386 */
#define HASH_MUR_UNALIGNED(key,keylen,num_bkts,hashv,bkt) \
do { \
const unsigned int _mur_m = 0x5bd1e995; \
const int _mur_r = 24; \
hashv = 0xcafebabe ^ keylen; \
char *_mur_key = (char *)key; \
uint32_t _mur_tmp, _mur_len = keylen; \
\
for (;_mur_len >= 4; _mur_len-=4) { \
_mur_tmp = *(uint32_t *)_mur_key; \
_mur_tmp *= _mur_m; \
_mur_tmp ^= _mur_tmp >> _mur_r; \
_mur_tmp *= _mur_m; \
hashv *= _mur_m; \
hashv ^= _mur_tmp; \
_mur_key += 4; \
} \
\
switch(_mur_len) \
{ \
case 3: hashv ^= _mur_key[2] << 16; \
case 2: hashv ^= _mur_key[1] << 8; \
case 1: hashv ^= _mur_key[0]; \
hashv *= _mur_m; \
}; \
\
hashv ^= hashv >> 13; \
hashv *= _mur_m; \
hashv ^= hashv >> 15; \
\
bkt = hashv & (num_bkts-1); \
} while(0)
/* Appleby's MurmurHash version for alignment-sensitive archs like Sparc */
#define HASH_MUR_ALIGNED(key,keylen,num_bkts,hashv,bkt) \
do { \
const unsigned int _mur_m = 0x5bd1e995; \
const int _mur_r = 24; \
hashv = 0xcafebabe ^ keylen; \
char *_mur_key = (char *)key; \
uint32_t _mur_len = keylen; \
int _mur_align = (int)_mur_key & 3; \
\
if (_mur_align && (_mur_len >= 4)) { \
unsigned _mur_t = 0, _mur_d = 0; \
switch(_mur_align) { \
case 1: _mur_t |= _mur_key[2] << 16; \
case 2: _mur_t |= _mur_key[1] << 8; \
case 3: _mur_t |= _mur_key[0]; \
} \
_mur_t <<= (8 * _mur_align); \
_mur_key += 4-_mur_align; \
_mur_len -= 4-_mur_align; \
int _mur_sl = 8 * (4-_mur_align); \
int _mur_sr = 8 * _mur_align; \
\
for (;_mur_len >= 4; _mur_len-=4) { \
_mur_d = *(unsigned *)_mur_key; \
_mur_t = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
unsigned _mur_k = _mur_t; \
_mur_k *= _mur_m; \
_mur_k ^= _mur_k >> _mur_r; \
_mur_k *= _mur_m; \
hashv *= _mur_m; \
hashv ^= _mur_k; \
_mur_t = _mur_d; \
_mur_key += 4; \
} \
_mur_d = 0; \
if(_mur_len >= _mur_align) { \
switch(_mur_align) { \
case 3: _mur_d |= _mur_key[2] << 16; \
case 2: _mur_d |= _mur_key[1] << 8; \
case 1: _mur_d |= _mur_key[0]; \
} \
unsigned _mur_k = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
_mur_k *= _mur_m; \
_mur_k ^= _mur_k >> _mur_r; \
_mur_k *= _mur_m; \
hashv *= _mur_m; \
hashv ^= _mur_k; \
_mur_k += _mur_align; \
_mur_len -= _mur_align; \
\
switch(_mur_len) \
{ \
case 3: hashv ^= _mur_key[2] << 16; \
case 2: hashv ^= _mur_key[1] << 8; \
case 1: hashv ^= _mur_key[0]; \
hashv *= _mur_m; \
} \
} else { \
switch(_mur_len) \
{ \
case 3: _mur_d ^= _mur_key[2] << 16; \
case 2: _mur_d ^= _mur_key[1] << 8; \
case 1: _mur_d ^= _mur_key[0]; \
case 0: hashv ^= (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
hashv *= _mur_m; \
} \
} \
\
hashv ^= hashv >> 13; \
hashv *= _mur_m; \
hashv ^= hashv >> 15; \
} else { \
for (;_mur_len >= 4; _mur_len-=4) { \
unsigned _mur_k = *(unsigned*)_mur_key; \
_mur_k *= _mur_m; \
_mur_k ^= _mur_k >> _mur_r; \
_mur_k *= _mur_m; \
hashv *= _mur_m; \
hashv ^= _mur_k; \
_mur_key += 4; \
} \
switch(_mur_len) \
{ \
case 3: hashv ^= _mur_key[2] << 16; \
case 2: hashv ^= _mur_key[1] << 8; \
case 1: hashv ^= _mur_key[0]; \
hashv *= _mur_m; \
} \
\
hashv ^= hashv >> 13; \
hashv *= _mur_m; \
hashv ^= hashv >> 15; \
} \
bkt = hashv & (num_bkts-1); \
} while(0)
#endif /* HASH_USING_NO_STRICT_ALIASING */
/* key comparison function; return 0 if keys equal */
#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
/* iterate over items in a known bucket to find desired item */
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
do { \
if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
else out=NULL; \
while (out) { \
if (out->hh.keylen == keylen_in) { \
if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \
} \
if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \
else out = NULL; \
} \
} while(0)
/* add an item to a bucket */
#define HASH_ADD_TO_BKT(head,addhh) \
do { \
head.count++; \
(addhh)->hh_next = head.hh_head; \
(addhh)->hh_prev = NULL; \
if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
(head).hh_head=addhh; \
if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
&& (addhh)->tbl->noexpand != 1) { \
HASH_EXPAND_BUCKETS((addhh)->tbl); \
} \
} while(0)
/* remove an item from a given bucket */
#define HASH_DEL_IN_BKT(hh,head,hh_del) \
(head).count--; \
if ((head).hh_head == hh_del) { \
(head).hh_head = hh_del->hh_next; \
} \
if (hh_del->hh_prev) { \
hh_del->hh_prev->hh_next = hh_del->hh_next; \
} \
if (hh_del->hh_next) { \
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
}
/* Bucket expansion has the effect of doubling the number of buckets
* and redistributing the items into the new buckets. Ideally the
* items will distribute more or less evenly into the new buckets
* (the extent to which this is true is a measure of the quality of
* the hash function as it applies to the key domain).
*
* With the items distributed into more buckets, the chain length
* (item count) in each bucket is reduced. Thus by expanding buckets
* the hash keeps a bound on the chain length. This bounded chain
* length is the essence of how a hash provides constant time lookup.
*
* The calculation of tbl->ideal_chain_maxlen below deserves some
* explanation. First, keep in mind that we're calculating the ideal
* maximum chain length based on the *new* (doubled) bucket count.
* In fractions this is just n/b (n=number of items,b=new num buckets).
* Since the ideal chain length is an integer, we want to calculate
* ceil(n/b). We don't depend on floating point arithmetic in this
* hash, so to calculate ceil(n/b) with integers we could write
*
* ceil(n/b) = (n/b) + ((n%b)?1:0)
*
* and in fact a previous version of this hash did just that.
* But now we have improved things a bit by recognizing that b is
* always a power of two. We keep its base 2 log handy (call it lb),
* so now we can write this with a bit shift and logical AND:
*
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
*
*/
#define HASH_EXPAND_BUCKETS(tbl) \
do { \
unsigned _he_bkt; \
unsigned _he_bkt_i; \
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
memset(_he_new_buckets, 0, \
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
tbl->ideal_chain_maxlen = \
(tbl->num_items >> (tbl->log2_num_buckets+1)) + \
((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
tbl->nonideal_items = 0; \
for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
{ \
_he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
while (_he_thh) { \
_he_hh_nxt = _he_thh->hh_next; \
HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
_he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
tbl->nonideal_items++; \
_he_newbkt->expand_mult = _he_newbkt->count / \
tbl->ideal_chain_maxlen; \
} \
_he_thh->hh_prev = NULL; \
_he_thh->hh_next = _he_newbkt->hh_head; \
if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
_he_thh; \
_he_newbkt->hh_head = _he_thh; \
_he_thh = _he_hh_nxt; \
} \
} \
tbl->num_buckets *= 2; \
tbl->log2_num_buckets++; \
uthash_free( tbl->buckets ); \
tbl->buckets = _he_new_buckets; \
tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
(tbl->ineff_expands+1) : 0; \
if (tbl->ineff_expands > 1) { \
tbl->noexpand=1; \
uthash_noexpand_fyi(tbl); \
} \
uthash_expand_fyi(tbl); \
} while(0)
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
/* Note that HASH_SORT assumes the hash handle name to be hh.
* HASH_SRT was added to allow the hash handle name to be passed in. */
#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
#define HASH_SRT(hh,head,cmpfcn) \
do { \
unsigned _hs_i; \
unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
if (head) { \
_hs_insize = 1; \
_hs_looping = 1; \
_hs_list = &((head)->hh); \
while (_hs_looping) { \
_hs_p = _hs_list; \
_hs_list = NULL; \
_hs_tail = NULL; \
_hs_nmerges = 0; \
while (_hs_p) { \
_hs_nmerges++; \
_hs_q = _hs_p; \
_hs_psize = 0; \
for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
_hs_psize++; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
if (! (_hs_q) ) break; \
} \
_hs_qsize = _hs_insize; \
while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
if (_hs_psize == 0) { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
_hs_e = _hs_p; \
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
((void*)((char*)(_hs_p->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_psize--; \
} else if (( \
cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
) <= 0) { \
_hs_e = _hs_p; \
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
((void*)((char*)(_hs_p->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_psize--; \
} else { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} \
if ( _hs_tail ) { \
_hs_tail->next = ((_hs_e) ? \
ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
} else { \
_hs_list = _hs_e; \
} \
_hs_e->prev = ((_hs_tail) ? \
ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
_hs_tail = _hs_e; \
} \
_hs_p = _hs_q; \
} \
_hs_tail->next = NULL; \
if ( _hs_nmerges <= 1 ) { \
_hs_looping=0; \
(head)->hh.tbl->tail = _hs_tail; \
DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
} \
_hs_insize *= 2; \
} \
HASH_FSCK(hh,head); \
} \
} while (0)
/* This function selects items from one hash into another hash.
* The end result is that the selected items have dual presence
* in both hashes. There is no copy of the items made; rather
* they are added into the new hash through a secondary hash
* hash handle that must be present in the structure. */
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
do { \
unsigned _src_bkt, _dst_bkt; \
void *_last_elt=NULL, *_elt; \
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
if (src) { \
for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
_src_hh; \
_src_hh = _src_hh->hh_next) { \
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
if (cond(_elt)) { \
_dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
_dst_hh->key = _src_hh->key; \
_dst_hh->keylen = _src_hh->keylen; \
_dst_hh->hashv = _src_hh->hashv; \
_dst_hh->prev = _last_elt; \
_dst_hh->next = NULL; \
if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
if (!dst) { \
DECLTYPE_ASSIGN(dst,_elt); \
HASH_MAKE_TABLE(hh_dst,dst); \
} else { \
_dst_hh->tbl = (dst)->hh_dst.tbl; \
} \
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
(dst)->hh_dst.tbl->num_items++; \
_last_elt = _elt; \
_last_elt_hh = _dst_hh; \
} \
} \
} \
} \
HASH_FSCK(hh_dst,dst); \
} while (0)
#define HASH_CLEAR(hh,head) \
do { \
if (head) { \
uthash_free((head)->hh.tbl->buckets ); \
uthash_free((head)->hh.tbl); \
(head)=NULL; \
} \
} while(0)
/* obtain a count of items in the hash */
#define HASH_COUNT(head) HASH_CNT(hh,head)
#define HASH_CNT(hh,head) (head?(head->hh.tbl->num_items):0)
typedef struct UT_hash_bucket {
struct UT_hash_handle *hh_head;
unsigned count;
/* expand_mult is normally set to 0. In this situation, the max chain length
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
* the bucket's chain exceeds this length, bucket expansion is triggered).
* However, setting expand_mult to a non-zero value delays bucket expansion
* (that would be triggered by additions to this particular bucket)
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
* (The multiplier is simply expand_mult+1). The whole idea of this
* multiplier is to reduce bucket expansions, since they are expensive, in
* situations where we know that a particular bucket tends to be overused.
* It is better to let its chain length grow to a longer yet-still-bounded
* value, than to do an O(n) bucket expansion too often.
*/
unsigned expand_mult;
} UT_hash_bucket;
/* random signature used only to find hash tables in external analysis */
#define HASH_SIGNATURE 0xa0111fe1
#define HASH_BLOOM_SIGNATURE 0xb12220f2
typedef struct UT_hash_table {
UT_hash_bucket *buckets;
unsigned num_buckets, log2_num_buckets;
unsigned num_items;
struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
/* in an ideal situation (all buckets used equally), no bucket would have
* more than ceil(#items/#buckets) items. that's the ideal chain length. */
unsigned ideal_chain_maxlen;
/* nonideal_items is the number of items in the hash whose chain position
* exceeds the ideal chain maxlen. these items pay the penalty for an uneven
* hash distribution; reaching them in a chain traversal takes >ideal steps */
unsigned nonideal_items;
/* ineffective expands occur when a bucket doubling was performed, but
* afterward, more than half the items in the hash had nonideal chain
* positions. If this happens on two consecutive expansions we inhibit any
* further expansion, as it's not helping; this happens when the hash
* function isn't a good fit for the key domain. When expansion is inhibited
* the hash will still work, albeit no longer in constant time. */
unsigned ineff_expands, noexpand;
uint32_t signature; /* used only to find hash tables in external analysis */
#ifdef HASH_BLOOM
uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
uint8_t *bloom_bv;
char bloom_nbits;
#endif
} UT_hash_table;
typedef struct UT_hash_handle {
struct UT_hash_table *tbl;
void *prev; /* prev element in app order */
void *next; /* next element in app order */
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
struct UT_hash_handle *hh_next; /* next hh in bucket order */
void *key; /* ptr to enclosing struct's key */
unsigned keylen; /* enclosing struct's key len */
unsigned hashv; /* result of hash-fcn(key) */
} UT_hash_handle;
#endif /* UTHASH_H */

1388
thirdparty/libktx/lib/vk_format.h vendored Normal file

File diff suppressed because it is too large Load Diff

300
thirdparty/libktx/lib/vkformat_enum.h vendored Normal file
View File

@ -0,0 +1,300 @@
#if !defined(_VKFORMAT_ENUM_H_) && !defined(VULKAN_CORE_H_)
#define _VKFORMAT_ENUM_H_
/***************************** Do not edit. *****************************
Automatically generated from vulkan_core.h version 151 by mkvkformatfiles.
*************************************************************************/
/*
** Copyright (c) 2015-2020 The Khronos Group Inc.
**
** SPDX-License-Identifier: Apache-2.0
*/
#if defined(_MSC_VER) && _MSC_VER < 1900 // Older than VS 2015.
typedef unsigned __int32 VkFlags;
#else
#include <stdint.h>
typedef uint32_t VkFlags;
#endif
typedef enum VkFormat {
VK_FORMAT_UNDEFINED = 0,
VK_FORMAT_R4G4_UNORM_PACK8 = 1,
VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2,
VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3,
VK_FORMAT_R5G6B5_UNORM_PACK16 = 4,
VK_FORMAT_B5G6R5_UNORM_PACK16 = 5,
VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6,
VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7,
VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8,
VK_FORMAT_R8_UNORM = 9,
VK_FORMAT_R8_SNORM = 10,
VK_FORMAT_R8_USCALED = 11,
VK_FORMAT_R8_SSCALED = 12,
VK_FORMAT_R8_UINT = 13,
VK_FORMAT_R8_SINT = 14,
VK_FORMAT_R8_SRGB = 15,
VK_FORMAT_R8G8_UNORM = 16,
VK_FORMAT_R8G8_SNORM = 17,
VK_FORMAT_R8G8_USCALED = 18,
VK_FORMAT_R8G8_SSCALED = 19,
VK_FORMAT_R8G8_UINT = 20,
VK_FORMAT_R8G8_SINT = 21,
VK_FORMAT_R8G8_SRGB = 22,
VK_FORMAT_R8G8B8_UNORM = 23,
VK_FORMAT_R8G8B8_SNORM = 24,
VK_FORMAT_R8G8B8_USCALED = 25,
VK_FORMAT_R8G8B8_SSCALED = 26,
VK_FORMAT_R8G8B8_UINT = 27,
VK_FORMAT_R8G8B8_SINT = 28,
VK_FORMAT_R8G8B8_SRGB = 29,
VK_FORMAT_B8G8R8_UNORM = 30,
VK_FORMAT_B8G8R8_SNORM = 31,
VK_FORMAT_B8G8R8_USCALED = 32,
VK_FORMAT_B8G8R8_SSCALED = 33,
VK_FORMAT_B8G8R8_UINT = 34,
VK_FORMAT_B8G8R8_SINT = 35,
VK_FORMAT_B8G8R8_SRGB = 36,
VK_FORMAT_R8G8B8A8_UNORM = 37,
VK_FORMAT_R8G8B8A8_SNORM = 38,
VK_FORMAT_R8G8B8A8_USCALED = 39,
VK_FORMAT_R8G8B8A8_SSCALED = 40,
VK_FORMAT_R8G8B8A8_UINT = 41,
VK_FORMAT_R8G8B8A8_SINT = 42,
VK_FORMAT_R8G8B8A8_SRGB = 43,
VK_FORMAT_B8G8R8A8_UNORM = 44,
VK_FORMAT_B8G8R8A8_SNORM = 45,
VK_FORMAT_B8G8R8A8_USCALED = 46,
VK_FORMAT_B8G8R8A8_SSCALED = 47,
VK_FORMAT_B8G8R8A8_UINT = 48,
VK_FORMAT_B8G8R8A8_SINT = 49,
VK_FORMAT_B8G8R8A8_SRGB = 50,
VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51,
VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52,
VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53,
VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54,
VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55,
VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56,
VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57,
VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58,
VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59,
VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60,
VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61,
VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62,
VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63,
VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64,
VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65,
VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66,
VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67,
VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68,
VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69,
VK_FORMAT_R16_UNORM = 70,
VK_FORMAT_R16_SNORM = 71,
VK_FORMAT_R16_USCALED = 72,
VK_FORMAT_R16_SSCALED = 73,
VK_FORMAT_R16_UINT = 74,
VK_FORMAT_R16_SINT = 75,
VK_FORMAT_R16_SFLOAT = 76,
VK_FORMAT_R16G16_UNORM = 77,
VK_FORMAT_R16G16_SNORM = 78,
VK_FORMAT_R16G16_USCALED = 79,
VK_FORMAT_R16G16_SSCALED = 80,
VK_FORMAT_R16G16_UINT = 81,
VK_FORMAT_R16G16_SINT = 82,
VK_FORMAT_R16G16_SFLOAT = 83,
VK_FORMAT_R16G16B16_UNORM = 84,
VK_FORMAT_R16G16B16_SNORM = 85,
VK_FORMAT_R16G16B16_USCALED = 86,
VK_FORMAT_R16G16B16_SSCALED = 87,
VK_FORMAT_R16G16B16_UINT = 88,
VK_FORMAT_R16G16B16_SINT = 89,
VK_FORMAT_R16G16B16_SFLOAT = 90,
VK_FORMAT_R16G16B16A16_UNORM = 91,
VK_FORMAT_R16G16B16A16_SNORM = 92,
VK_FORMAT_R16G16B16A16_USCALED = 93,
VK_FORMAT_R16G16B16A16_SSCALED = 94,
VK_FORMAT_R16G16B16A16_UINT = 95,
VK_FORMAT_R16G16B16A16_SINT = 96,
VK_FORMAT_R16G16B16A16_SFLOAT = 97,
VK_FORMAT_R32_UINT = 98,
VK_FORMAT_R32_SINT = 99,
VK_FORMAT_R32_SFLOAT = 100,
VK_FORMAT_R32G32_UINT = 101,
VK_FORMAT_R32G32_SINT = 102,
VK_FORMAT_R32G32_SFLOAT = 103,
VK_FORMAT_R32G32B32_UINT = 104,
VK_FORMAT_R32G32B32_SINT = 105,
VK_FORMAT_R32G32B32_SFLOAT = 106,
VK_FORMAT_R32G32B32A32_UINT = 107,
VK_FORMAT_R32G32B32A32_SINT = 108,
VK_FORMAT_R32G32B32A32_SFLOAT = 109,
VK_FORMAT_R64_UINT = 110,
VK_FORMAT_R64_SINT = 111,
VK_FORMAT_R64_SFLOAT = 112,
VK_FORMAT_R64G64_UINT = 113,
VK_FORMAT_R64G64_SINT = 114,
VK_FORMAT_R64G64_SFLOAT = 115,
VK_FORMAT_R64G64B64_UINT = 116,
VK_FORMAT_R64G64B64_SINT = 117,
VK_FORMAT_R64G64B64_SFLOAT = 118,
VK_FORMAT_R64G64B64A64_UINT = 119,
VK_FORMAT_R64G64B64A64_SINT = 120,
VK_FORMAT_R64G64B64A64_SFLOAT = 121,
VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122,
VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123,
VK_FORMAT_D16_UNORM = 124,
VK_FORMAT_X8_D24_UNORM_PACK32 = 125,
VK_FORMAT_D32_SFLOAT = 126,
VK_FORMAT_S8_UINT = 127,
VK_FORMAT_D16_UNORM_S8_UINT = 128,
VK_FORMAT_D24_UNORM_S8_UINT = 129,
VK_FORMAT_D32_SFLOAT_S8_UINT = 130,
VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131,
VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132,
VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133,
VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134,
VK_FORMAT_BC2_UNORM_BLOCK = 135,
VK_FORMAT_BC2_SRGB_BLOCK = 136,
VK_FORMAT_BC3_UNORM_BLOCK = 137,
VK_FORMAT_BC3_SRGB_BLOCK = 138,
VK_FORMAT_BC4_UNORM_BLOCK = 139,
VK_FORMAT_BC4_SNORM_BLOCK = 140,
VK_FORMAT_BC5_UNORM_BLOCK = 141,
VK_FORMAT_BC5_SNORM_BLOCK = 142,
VK_FORMAT_BC6H_UFLOAT_BLOCK = 143,
VK_FORMAT_BC6H_SFLOAT_BLOCK = 144,
VK_FORMAT_BC7_UNORM_BLOCK = 145,
VK_FORMAT_BC7_SRGB_BLOCK = 146,
VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147,
VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148,
VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149,
VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150,
VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151,
VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152,
VK_FORMAT_EAC_R11_UNORM_BLOCK = 153,
VK_FORMAT_EAC_R11_SNORM_BLOCK = 154,
VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155,
VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156,
VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157,
VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158,
VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159,
VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160,
VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161,
VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162,
VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163,
VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164,
VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165,
VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166,
VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167,
VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168,
VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169,
VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170,
VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171,
VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172,
VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173,
VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174,
VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175,
VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176,
VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177,
VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178,
VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179,
VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180,
VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181,
VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182,
VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183,
VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184,
VK_FORMAT_G8B8G8R8_422_UNORM = 1000156000,
VK_FORMAT_B8G8R8G8_422_UNORM = 1000156001,
VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM = 1000156002,
VK_FORMAT_G8_B8R8_2PLANE_420_UNORM = 1000156003,
VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM = 1000156004,
VK_FORMAT_G8_B8R8_2PLANE_422_UNORM = 1000156005,
VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM = 1000156006,
VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007,
VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008,
VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009,
VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010,
VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011,
VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 = 1000156012,
VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 = 1000156013,
VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 = 1000156014,
VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 = 1000156015,
VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 = 1000156016,
VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017,
VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018,
VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019,
VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020,
VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021,
VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 = 1000156022,
VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 = 1000156023,
VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 = 1000156024,
VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 = 1000156025,
VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 = 1000156026,
VK_FORMAT_G16B16G16R16_422_UNORM = 1000156027,
VK_FORMAT_B16G16R16G16_422_UNORM = 1000156028,
VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM = 1000156029,
VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030,
VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031,
VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032,
VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033,
VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000,
VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001,
VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002,
VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003,
VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004,
VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005,
VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006,
VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007,
VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT = 1000066000,
VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT = 1000066001,
VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT = 1000066002,
VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT = 1000066003,
VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT = 1000066004,
VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT = 1000066005,
VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT = 1000066006,
VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT = 1000066007,
VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT = 1000066008,
VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT = 1000066009,
VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT = 1000066010,
VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT = 1000066011,
VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT = 1000066012,
VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT = 1000066013,
VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT = 1000288000,
VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT = 1000288001,
VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT = 1000288002,
VK_FORMAT_ASTC_4x3x3_UNORM_BLOCK_EXT = 1000288003,
VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT = 1000288004,
VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT = 1000288005,
VK_FORMAT_ASTC_4x4x3_UNORM_BLOCK_EXT = 1000288006,
VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT = 1000288007,
VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT = 1000288008,
VK_FORMAT_ASTC_4x4x4_UNORM_BLOCK_EXT = 1000288009,
VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT = 1000288010,
VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT = 1000288011,
VK_FORMAT_ASTC_5x4x4_UNORM_BLOCK_EXT = 1000288012,
VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT = 1000288013,
VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT = 1000288014,
VK_FORMAT_ASTC_5x5x4_UNORM_BLOCK_EXT = 1000288015,
VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT = 1000288016,
VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT = 1000288017,
VK_FORMAT_ASTC_5x5x5_UNORM_BLOCK_EXT = 1000288018,
VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT = 1000288019,
VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT = 1000288020,
VK_FORMAT_ASTC_6x5x5_UNORM_BLOCK_EXT = 1000288021,
VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT = 1000288022,
VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT = 1000288023,
VK_FORMAT_ASTC_6x6x5_UNORM_BLOCK_EXT = 1000288024,
VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT = 1000288025,
VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT = 1000288026,
VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT = 1000288027,
VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT = 1000288028,
VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT = 1000288029,
VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT = 1000340000,
VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT = 1000340001,
VK_FORMAT_MAX_ENUM = 0x7FFFFFFF
} VkFormat;
#define VK_FORMAT_MAX_STANDARD_ENUM 184
#endif /* _VKFORMAT_ENUM_H_ */

View File

@ -0,0 +1,290 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
/*
** Copyright (c) 2008-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
# define KHRONOS_STATIC 1
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(KHRONOS_STATIC)
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
* header compatible with static linking. */
# define KHRONOS_APICALL
#elif defined(_WIN32)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(KHRONOS_STATIC)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef _WIN64
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */

37
thirdparty/libktx/utils/unused.h vendored Normal file
View File

@ -0,0 +1,37 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* Copyright 2019-2018 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/* I'm extending this beyond the purpose implied by its name rather than creating
* a new file to hold the FALLTHROUGH declaration as this
* file is already included in most places FALLTHROUGH
* is needed.
*/
#ifndef _UNUSED_H
#define _UNUSED_H
#if (__cplusplus >= 201703L)
#define MAYBE_UNUSED [[maybe_unused]]
#elif __GNUC__ || __clang__
#define MAYBE_UNUSED __attribute__((unused))
#else
// Boohoo. VC++ has no equivalent
#define MAYBE_UNUSED
#endif
#define U_ASSERT_ONLY MAYBE_UNUSED
// For unused parameters of c functions. Portable.
#define UNUSED(x) (void)(x)
#if !__clang__ && __GNUC__ // grumble ... clang ... grumble
#define FALLTHROUGH __attribute__((fallthrough))
#else
#define FALLTHROUGH
#endif
#endif /* UNUSED_H */