Add support for KTX & KTX2 image format
Add support glTF KHR_texture_basisu extension
This commit is contained in:
parent
ff5c884153
commit
a00cf02241
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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) {
|
||||||
|
|
|
@ -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)
|
|
@ -0,0 +1,6 @@
|
||||||
|
def can_build(env, platform):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def configure(env):
|
||||||
|
pass
|
|
@ -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();
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
|
@ -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
|
|
@ -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.
|
|
@ -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);
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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_ */
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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_ */
|
|
@ -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. */
|
|
@ -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;
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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 */
|
|
@ -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_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||||
|
}
|
|
@ -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 */
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
|
@ -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_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -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_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -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_ */
|
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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 */
|
Loading…
Reference in New Issue