initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

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

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

View File

@@ -0,0 +1,744 @@
/* -*- 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 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;
// Free SGD data
This->_private->_sgdByteLength = 0;
if (This->_private->_supercompressionGlobalData) {
free(This->_private->_supercompressionGlobalData);
This->_private->_supercompressionGlobalData = NULL;
}
}
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) {
// Compiler will not allow `goto cleanup;` because "jump bypasses variable initialization."
// The static initializations below this and before the loop are presumably the issue
// as the compiler is,presumably, inserting code to destruct those at the end of the
// function.
delete[] firstImages;
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_ldr_4x4_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;
}

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

@@ -0,0 +1,299 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* $Id$ */
/*
* Copyright 2010-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file
* @~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"
#include "vkformat_enum.h"
bool isProhibitedFormat(VkFormat format);
bool isValidFormat(VkFormat format);
/**
* @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_FEATURE;
}
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 format */
if (isProhibitedFormat(pHeader->vkFormat))
{
return KTX_FILE_DATA_ERROR;
}
if (!isValidFormat(pHeader->vkFormat))
{
return KTX_UNSUPPORTED_FEATURE;
}
if (pHeader->supercompressionScheme == KTX_SS_BASIS_LZ && pHeader->vkFormat != VK_FORMAT_UNDEFINED)
{
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 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_FEATURE;
}
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;
}
if (pHeader->pixelDepth != 0)
{
/* cube map cannot have depth */
return KTX_FILE_DATA_ERROR;
}
if (pHeader->pixelWidth != pHeader->pixelHeight)
{
/* cube map needs square 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;
}
// Check supercompression
switch (pHeader->supercompressionScheme) {
case KTX_SS_NONE:
case KTX_SS_BASIS_LZ:
case KTX_SS_ZSTD:
case KTX_SS_ZLIB:
break;
default:
// Unsupported supercompression
return KTX_UNSUPPORTED_FEATURE;
}
// 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;
}

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

@@ -0,0 +1,395 @@
/* -*- 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)
(void)fflush(str->data.file);
#else
(void)fflush(str->data.file);
#endif
statret = fstat(fileno(str->data.file), &statbuf);
if (statret < 0) {
switch (errno) {
case EOVERFLOW: return KTX_FILE_OVERFLOW;
case EIO:
default:
return KTX_FILE_READ_ERROR;
}
}
mode_t ftype = statbuf.st_mode & S_IFMT;
if (ftype == S_IFIFO || ftype == S_IFSOCK)
return KTX_FILE_ISPIPE;
if (statbuf.st_mode & S_IFCHR)
return KTX_INVALID_OPERATION;
*size = (ktx_size_t)statbuf.st_size; /* See _getpos for why this cast. */
return KTX_SUCCESS;
}
/**
* @~English
* @brief Initialize a ktxFileStream.
*
* @param [in] str pointer to the ktxStream to initialize.
* @param [in] file pointer to the underlying FILE object.
* @param [in] closeFileOnDestruct if not false, stdio file pointer will be closed when ktxStream
* is destructed.
*
* @return KTX_SUCCESS on success, KTX_INVALID_VALUE on error.
*
* @exception KTX_INVALID_VALUE @p stream is @c NULL or @p file is @c NULL.
*/
KTX_error_code ktxFileStream_construct(ktxStream* str, FILE* file,
ktx_bool_t closeFileOnDestruct)
{
if (!str || !file)
return KTX_INVALID_VALUE;
str->data.file = file;
str->readpos = 0;
str->type = eStreamTypeFile;
str->read = ktxFileStream_read;
str->skip = ktxFileStream_skip;
str->write = ktxFileStream_write;
str->getpos = ktxFileStream_getpos;
str->setpos = ktxFileStream_setpos;
str->getsize = ktxFileStream_getsize;
str->destruct = ktxFileStream_destruct;
str->closeOnDestruct = closeFileOnDestruct;
return KTX_SUCCESS;
}
/**
* @~English
* @brief Destruct the stream, potentially closing the underlying FILE.
*
* This only closes the underyling FILE if the @c closeOnDestruct parameter to
* ktxFileStream_construct() was not @c KTX_FALSE.
*
* @param [in] str pointer to the ktxStream whose FILE is to potentially
* be closed.
*/
void
ktxFileStream_destruct(ktxStream* str)
{
assert(str && str->type == eStreamTypeFile);
if (str->closeOnDestruct)
fclose(str->data.file);
str->data.file = 0;
}

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

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

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

@@ -0,0 +1,59 @@
/* -*- 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,
KTX_FORMAT_SIZE_YUVSDA_BIT = 0x00000020,
} 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_ */

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

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,628 @@
/* -*- 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 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) {
if (src + 6 > (char *)pKvd + kvdLen) {
// Not enough space for another entry
return KTX_FILE_DATA_ERROR;
}
char* key;
unsigned int keyLen, valueLen;
void* value;
ktx_uint32_t keyAndValueByteSize = *((ktx_uint32_t*)src);
if (src + 4 + keyAndValueByteSize > (char *)pKvd + kvdLen) {
// Not enough space for this entry
return KTX_FILE_DATA_ERROR;
}
src += sizeof(keyAndValueByteSize);
key = src;
keyLen = 0;
while (keyLen < keyAndValueByteSize && key[keyLen] != '\0') keyLen++;
if (keyLen == keyAndValueByteSize || key[keyLen] != '\0') {
// Missing NULL terminator or no value
return KTX_FILE_DATA_ERROR;
}
if (keyLen >= 3 && key[0] == '\xEF' && key[1] == '\xBB' && key[2] == '\xBF') {
// Forbidden BOM
return KTX_FILE_DATA_ERROR;
}
keyLen += 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;
}

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

@@ -0,0 +1,348 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* $Id$ */
/*
* 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
#ifndef MIN
#define MIN(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);
/*
* @internal
* ktxCompressZLIBBounds
*
* Returns upper bound for compresses data using miniz (ZLIB)
*/
ktx_size_t ktxCompressZLIBBounds(ktx_size_t srcLength);
/*
* @internal
* ktxCompressZLIBInt
*
* Compresses data using miniz (ZLIB)
*/
KTX_error_code ktxCompressZLIBInt(unsigned char* pDest,
ktx_size_t* pDestLength,
const unsigned char* pSrc,
ktx_size_t srcLength,
ktx_uint32_t level);
/*
* @internal
* ktxUncompressZLIBInt
*
* Uncompresses data using miniz (ZLIB)
*/
KTX_error_code ktxUncompressZLIBInt(unsigned char* pDest,
ktx_size_t* pDestLength,
const unsigned char* pSrc,
ktx_size_t srcLength);
/*
* 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
======================================
*/
KTX_error_code printKTX2Info2(ktxStream* src, KTX_header2* header);
/*
* fopen a file identified by a UTF-8 path.
*/
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <assert.h>
#include <windows.h>
#include <shellapi.h>
#include <stdlib.h>
// For Windows, we convert the UTF-8 path and mode to UTF-16 path and use
// _wfopen which correctly handles unicode characters.
static inline FILE* ktxFOpenUTF8(char const* path, char const* mode) {
int wpLen = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
int wmLen = MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
FILE* fp = NULL;
if (wpLen > 0 && wmLen > 0)
{
wchar_t* wpath = (wchar_t*)malloc(wpLen * sizeof(wchar_t));
wchar_t* wmode = (wchar_t*)malloc(wmLen * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, wpLen);
MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, wmLen);
// Returned errno_t value is also set in the global errno.
// Apps use that for error detail as libktx only returns
// KTX_FILE_OPEN_FAILED.
(void)_wfopen_s(&fp, wpath, wmode);
free(wpath);
free(wmode);
return fp;
} else {
assert(KTX_FALSE
&& "ktxFOpenUTF8 called with zero length path or mode.");
return NULL;
}
}
#else
// For other platforms there is no need for any conversion, they
// support UTF-8 natively.
static inline FILE* ktxFOpenUTF8(char const* path, char const* mode) {
return fopen(path, mode);
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* KTXINT_H */

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

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

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

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

149
thirdparty/libktx/lib/miniz_wrapper.cpp vendored Normal file
View File

@@ -0,0 +1,149 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2023-2023 The Khronos Group Inc.
* Copyright 2023-2023 RasterGrid Kft.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file
* @~English
*
* @brief Wrapper functions for ZLIB compression/decompression using miniz.
*
* @author Daniel Rakos, RasterGrid
*/
#include "ktx.h"
#include "ktxint.h"
#include <assert.h>
#if !KTX_FEATURE_WRITE
// The reader does not link with the basisu components that already include a
// definition of miniz so we include it here explicitly.
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wmisleading-indentation"
#endif
#include "encoder/basisu_miniz.h"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#else
// Otherwise we only declare the interfaces and link with the basisu version.
// This is needed because while miniz is defined as a header in basisu it's
// not declaring the functions as static or inline, hence causing multiple
// conflicting definitions at link-time.
namespace buminiz {
typedef unsigned long mz_ulong;
enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 };
mz_ulong mz_compressBound(mz_ulong source_len);
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
}
#endif
using namespace buminiz;
extern "C" {
/**
* @internal
* @~English
* @brief Returns upper bound for compresses data using miniz (ZLIB).
*
* @param srcLength source data length
*
* @author Daniel Rakos, RasterGrid
*/
ktx_size_t ktxCompressZLIBBounds(ktx_size_t srcLength) {
return mz_compressBound((mz_ulong)srcLength);
}
/**
* @internal
* @~English
* @brief Compresses data using miniz (ZLIB)
*
* @param pDest destination data buffer
* @param pDestLength destination data buffer size
* (filled with written byte count on success)
* @param pSrc source data buffer
* @param srcLength source data size
* @param level compression level (between 1 and 9)
*
* @author Daniel Rakos, RasterGrid
*/
KTX_error_code ktxCompressZLIBInt(unsigned char* pDest,
ktx_size_t* pDestLength,
const unsigned char* pSrc,
ktx_size_t srcLength,
ktx_uint32_t level) {
if ((srcLength | *pDestLength) > 0xFFFFFFFFU) return KTX_INVALID_VALUE;
mz_ulong mzCompressedSize = (mz_ulong)*pDestLength;
int status = mz_compress2(pDest, &mzCompressedSize, pSrc, (mz_ulong)srcLength, level);
switch (status) {
case MZ_OK:
*pDestLength = mzCompressedSize;
return KTX_SUCCESS;
case MZ_PARAM_ERROR:
return KTX_INVALID_VALUE;
case MZ_BUF_ERROR:
#ifdef DEBUG
assert(false && "Deflate dstSize too small.");
#endif
return KTX_OUT_OF_MEMORY;
case MZ_MEM_ERROR:
#ifdef DEBUG
assert(false && "Deflate workspace too small.");
#endif
return KTX_OUT_OF_MEMORY;
default:
// The remaining errors look like they should only
// occur during decompression but just in case.
#ifdef DEBUG
assert(true);
#endif
return KTX_INVALID_OPERATION;
}
}
/**
* @internal
* @~English
* @brief Uncompresses data using miniz (ZLIB)
*
* @param pDest destination data buffer
* @param pDestLength destination data buffer size
* (filled with written byte count on success)
* @param pSrc source data buffer
* @param srcLength source data size
*
* @author Daniel Rakos, RasterGrid
*/
KTX_error_code ktxUncompressZLIBInt(unsigned char* pDest,
ktx_size_t* pDestLength,
const unsigned char* pSrc,
ktx_size_t srcLength) {
if ((srcLength | *pDestLength) > 0xFFFFFFFFU) return KTX_INVALID_VALUE;
mz_ulong mzUncompressedSize = (mz_ulong)*pDestLength;
int status = mz_uncompress(pDest, &mzUncompressedSize, pSrc, (mz_ulong)srcLength);
switch (status) {
case MZ_OK:
*pDestLength = mzUncompressedSize;
return KTX_SUCCESS;
case MZ_BUF_ERROR:
return KTX_DECOMPRESS_LENGTH_ERROR; // buffer too small
case MZ_MEM_ERROR:
return KTX_OUT_OF_MEMORY;
default:
return KTX_FILE_DATA_ERROR;
}
}
}

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

@@ -0,0 +1,57 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* $Id$ */
/*
* 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);
}
}

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

@@ -0,0 +1,882 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2018-2020 Mark Callow.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file
* @~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,
const ktxTextureCreateInfo* const 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 Create a ktx1 or ktx2 texture according to the stream
* data.
*
* See @ref ktxTexture1::ktxTexture1_CreateFromStream
* "ktxTexture1_CreateFromStream" or
* @ref ktxTexture2::ktxTexture2_CreateFromStream
* "ktxTexture2_CreateFromStream" for details.
*/
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.
*
* See @ref ktxTexture1::ktxTexture1_CreateFromStdioStream
* "ktxTexture1_CreateFromStdioStream" or
* @ref ktxTexture2::ktxTexture2_CreateFromStdioStream
* "ktxTexture2_CreateFromStdioStream" for details.
*/
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.
*
* See @ref ktxTexture1::ktxTexture1_CreateFromNamedFile
* "ktxTexture1_CreateFromNamedFile" or
* @ref ktxTexture2::ktxTexture2_CreateFromNamedFile
* "ktxTexture2_CreateFromNamedFile" for details.
*/
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 = ktxFOpenUTF8(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.
*
* See @ref ktxTexture1::ktxTexture1_CreateFromMemory
* "ktxTexture1_CreateFromMemory" or
* @ref ktxTexture2::ktxTexture2_CreateFromMemory
* "ktxTexture2_CreateFromMemory" for details.
*/
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.minBlocksY, 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);
assert (prtctd->_formatSize.blockDepth != 0);
blockCountZ = ((This->baseDepth >> level) + prtctd->_formatSize.blockDepth - 1) / prtctd->_formatSize.blockDepth;
blockCountZ = MAX(1, blockCountZ);
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 between 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;
}
/** @} */

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

@@ -0,0 +1,108 @@
/* -*- 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
* @~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,
const ktxTextureCreateInfo* const 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_ */

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

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,46 @@
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab textwidth=70: */
/*
* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file
* @~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_ */

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

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,67 @@
/* -*- 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
* @~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_constructCopy(ktxTexture2* This, ktxTexture2* orig);
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_ */

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

@@ -0,0 +1,61 @@
/* -*- 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
* @~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
======================================
*/
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(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);
/*
======================================
Internal ktxTexture functions
======================================
*/
void CLASS_FUNC(destruct)(CLASS* This);

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

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

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

File diff suppressed because it is too large Load Diff

215
thirdparty/libktx/lib/vkformat_check.c vendored Normal file
View File

@@ -0,0 +1,215 @@
/***************************** Do not edit. *****************************
Automatically generated from vulkan_core.h version 287 by mkvkformatfiles.
*************************************************************************/
/*
** Copyright 2015-2024 The Khronos Group Inc.
**
** SPDX-License-Identifier: Apache-2.0
*/
// clang-format off: CI is complicated if formatting checks on generated files are enforced.
#include <stdint.h>
#include <stdbool.h>
#include "vkformat_enum.h"
bool
isProhibitedFormat(VkFormat format)
{
switch (format) {
case VK_FORMAT_R8_USCALED:
case VK_FORMAT_R8_SSCALED:
case VK_FORMAT_R8G8_USCALED:
case VK_FORMAT_R8G8_SSCALED:
case VK_FORMAT_R8G8B8_USCALED:
case VK_FORMAT_R8G8B8_SSCALED:
case VK_FORMAT_B8G8R8_USCALED:
case VK_FORMAT_B8G8R8_SSCALED:
case VK_FORMAT_R8G8B8A8_USCALED:
case VK_FORMAT_R8G8B8A8_SSCALED:
case VK_FORMAT_B8G8R8A8_USCALED:
case VK_FORMAT_B8G8R8A8_SSCALED:
case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
case VK_FORMAT_R16_USCALED:
case VK_FORMAT_R16_SSCALED:
case VK_FORMAT_R16G16_USCALED:
case VK_FORMAT_R16G16_SSCALED:
case VK_FORMAT_R16G16B16_USCALED:
case VK_FORMAT_R16G16B16_SSCALED:
case VK_FORMAT_R16G16B16A16_USCALED:
case VK_FORMAT_R16G16B16A16_SSCALED:
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM:
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16:
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16:
case VK_FORMAT_G16_B16R16_2PLANE_444_UNORM:
return true;
default:
return false;
}
}
bool
isSrgbFormat(VkFormat format)
{
switch(format) {
case VK_FORMAT_R8_SRGB:
case VK_FORMAT_R8G8_SRGB:
case VK_FORMAT_R8G8B8_SRGB:
case VK_FORMAT_B8G8R8_SRGB:
case VK_FORMAT_R8G8B8A8_SRGB:
case VK_FORMAT_B8G8R8A8_SRGB:
case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
case VK_FORMAT_BC2_SRGB_BLOCK:
case VK_FORMAT_BC3_SRGB_BLOCK:
case VK_FORMAT_BC7_SRGB_BLOCK:
case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG:
case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG:
case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG:
case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG:
case VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT:
return true;
default:
return false;
}
}
bool
isValidFormat(VkFormat format)
{
// On MSVC VkFormat can be a signed integer
if ((uint32_t) format <= VK_FORMAT_MAX_STANDARD_ENUM)
return true;
else switch(format) {
case VK_FORMAT_G8B8G8R8_422_UNORM:
case VK_FORMAT_B8G8R8G8_422_UNORM:
case VK_FORMAT_R10X6_UNORM_PACK16:
case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
case VK_FORMAT_R12X4_UNORM_PACK16:
case VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
case VK_FORMAT_G16B16G16R16_422_UNORM:
case VK_FORMAT_B16G16R16G16_422_UNORM:
case VK_FORMAT_A4R4G4B4_UNORM_PACK16:
case VK_FORMAT_A4B4G4R4_UNORM_PACK16:
case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK:
case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK:
case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG:
case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG:
case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG:
case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG:
case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG:
case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG:
case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG:
case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG:
case VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT:
case VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_4x3x3_UNORM_BLOCK_EXT:
case VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_4x4x3_UNORM_BLOCK_EXT:
case VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_4x4x4_UNORM_BLOCK_EXT:
case VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_5x4x4_UNORM_BLOCK_EXT:
case VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_5x5x4_UNORM_BLOCK_EXT:
case VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_5x5x5_UNORM_BLOCK_EXT:
case VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_6x5x5_UNORM_BLOCK_EXT:
case VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_6x6x5_UNORM_BLOCK_EXT:
case VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT:
case VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT:
case VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT:
case VK_FORMAT_R16G16_SFIXED5_NV:
case VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR:
case VK_FORMAT_A8_UNORM_KHR:
return true;
default:
return false;
}
}
// clang-format on

View File

@@ -0,0 +1,171 @@
/*
** Copyright 2025 The Khronos Group Inc.
**
** SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include "vkformat_enum.h"
bool
isNotSrgbFormatButHasSrgbVariant(VkFormat format)
{
switch (format) {
// VK_FORMAT_R8_SRGB
case VK_FORMAT_R8_UNORM:
case VK_FORMAT_R8_SNORM:
case VK_FORMAT_R8_UINT:
case VK_FORMAT_R8_SINT:
// VK_FORMAT_R8G8_SRGB
case VK_FORMAT_R8G8_UNORM:
case VK_FORMAT_R8G8_SNORM:
case VK_FORMAT_R8G8_UINT:
case VK_FORMAT_R8G8_SINT:
// VK_FORMAT_R8G8B8_SRGB
case VK_FORMAT_R8G8B8_UNORM:
case VK_FORMAT_R8G8B8_SNORM:
case VK_FORMAT_R8G8B8_UINT:
case VK_FORMAT_R8G8B8_SINT:
// VK_FORMAT_B8G8R8_SRGB
case VK_FORMAT_B8G8R8_UNORM:
case VK_FORMAT_B8G8R8_SNORM:
case VK_FORMAT_B8G8R8_UINT:
case VK_FORMAT_B8G8R8_SINT:
// VK_FORMAT_R8G8B8A8_SRGB
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_R8G8B8A8_SNORM:
case VK_FORMAT_R8G8B8A8_UINT:
case VK_FORMAT_R8G8B8A8_SINT:
// VK_FORMAT_B8G8R8A8_SRGB
case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_B8G8R8A8_SNORM:
case VK_FORMAT_B8G8R8A8_UINT:
case VK_FORMAT_B8G8R8A8_SINT:
// VK_FORMAT_A8B8G8R8_SRGB_PACK32
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
case VK_FORMAT_A8B8G8R8_UINT_PACK32:
case VK_FORMAT_A8B8G8R8_SINT_PACK32:
// VK_FORMAT_BC1_RGB_SRGB_BLOCK
case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
// VK_FORMAT_BC1_RGBA_SRGB_BLOCK
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
// VK_FORMAT_BC2_SRGB_BLOCK
case VK_FORMAT_BC2_UNORM_BLOCK:
// VK_FORMAT_BC3_SRGB_BLOCK
case VK_FORMAT_BC3_UNORM_BLOCK:
// VK_FORMAT_BC7_SRGB_BLOCK
case VK_FORMAT_BC7_UNORM_BLOCK:
// VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK
case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
// VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK
case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
// VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK
case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
// VK_FORMAT_ASTC_4x4_SRGB_BLOCK
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
// VK_FORMAT_ASTC_5x4_SRGB_BLOCK
case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
// VK_FORMAT_ASTC_5x5_SRGB_BLOCK
case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
// VK_FORMAT_ASTC_6x5_SRGB_BLOCK
case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
// VK_FORMAT_ASTC_6x6_SRGB_BLOCK
case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
// VK_FORMAT_ASTC_8x5_SRGB_BLOCK
case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
// VK_FORMAT_ASTC_8x6_SRGB_BLOCK
case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
// VK_FORMAT_ASTC_8x8_SRGB_BLOCK
case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
// VK_FORMAT_ASTC_10x5_SRGB_BLOCK
case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
// VK_FORMAT_ASTC_10x6_SRGB_BLOCK
case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
// VK_FORMAT_ASTC_10x8_SRGB_BLOCK
case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
// VK_FORMAT_ASTC_10x10_SRGB_BLOCK
case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
// VK_FORMAT_ASTC_12x10_SRGB_BLOCK
case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
// VK_FORMAT_ASTC_12x12_SRGB_BLOCK
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
// VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG
case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG:
// VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG
case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG:
// VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG
case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG:
// VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG
case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG:
// VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT
case VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT:
// VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT
case VK_FORMAT_ASTC_4x3x3_UNORM_BLOCK_EXT:
// VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT
case VK_FORMAT_ASTC_4x4x3_UNORM_BLOCK_EXT:
// VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT
case VK_FORMAT_ASTC_4x4x4_UNORM_BLOCK_EXT:
// VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT
case VK_FORMAT_ASTC_5x4x4_UNORM_BLOCK_EXT:
// VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT
case VK_FORMAT_ASTC_5x5x4_UNORM_BLOCK_EXT:
// VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT
case VK_FORMAT_ASTC_5x5x5_UNORM_BLOCK_EXT:
// VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT
case VK_FORMAT_ASTC_6x5x5_UNORM_BLOCK_EXT:
// VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT
case VK_FORMAT_ASTC_6x6x5_UNORM_BLOCK_EXT:
// VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT
case VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT:
return true;
default:
return false;
}
}

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

@@ -0,0 +1,316 @@
// clang-format off: CI is complicated if formatting checks on generated files are enforced.
#if !defined(_VKFORMAT_ENUM_H_) && !defined(VULKAN_CORE_H_)
#define _VKFORMAT_ENUM_H_
/***************************** Do not edit. *****************************
Automatically generated from vulkan_core.h version 287 by mkvkformatfiles.
*************************************************************************/
/*
** Copyright 2015-2024 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_G8_B8R8_2PLANE_444_UNORM = 1000330000,
VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16 = 1000330001,
VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16 = 1000330002,
VK_FORMAT_G16_B16R16_2PLANE_444_UNORM = 1000330003,
VK_FORMAT_A4R4G4B4_UNORM_PACK16 = 1000340000,
VK_FORMAT_A4B4G4R4_UNORM_PACK16 = 1000340001,
VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK = 1000066000,
VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK = 1000066001,
VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK = 1000066002,
VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK = 1000066003,
VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK = 1000066004,
VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK = 1000066005,
VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK = 1000066006,
VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK = 1000066007,
VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK = 1000066008,
VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK = 1000066009,
VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK = 1000066010,
VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK = 1000066011,
VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK = 1000066012,
VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK = 1000066013,
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_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_R16G16_SFIXED5_NV = 1000464000,
VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR = 1000470000,
VK_FORMAT_A8_UNORM_KHR = 1000470001,
VK_FORMAT_MAX_ENUM = 0x7FFFFFFF
} VkFormat;
#if defined(_MSC_VER) && _MSC_VER < 1900 // Older than VS 2015.
typedef unsigned __int32 VkFlags;
#else
#include <stdint.h>
typedef uint64_t VkFlags64;
#endif
#define VK_FORMAT_MAX_STANDARD_ENUM 184
#endif /* _VKFORMAT_ENUM_H_ */
// clang-format on

View File

@@ -0,0 +1,586 @@
/***************************** Do not edit. *****************************
Automatically generated from vulkan_core.h version 287 by mkvkformatfiles.
*************************************************************************/
/*
** Copyright 2015-2024 The Khronos Group Inc.
**
** SPDX-License-Identifier: Apache-2.0
*/
// clang-format off: CI is complicated if formatting checks on generated files are enforced.
#include <stdint.h>
#include "vkformat_enum.h"
uint32_t
vkFormatTypeSize(VkFormat format)
{
switch (format) {
case VK_FORMAT_UNDEFINED:
return 1;
case VK_FORMAT_R4G4_UNORM_PACK8:
return 1;
case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
return 2;
case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
return 2;
case VK_FORMAT_R5G6B5_UNORM_PACK16:
return 2;
case VK_FORMAT_B5G6R5_UNORM_PACK16:
return 2;
case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
return 2;
case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
return 2;
case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
return 2;
case VK_FORMAT_R8_UNORM:
return 1;
case VK_FORMAT_R8_SNORM:
return 1;
case VK_FORMAT_R8_USCALED:
return 1;
case VK_FORMAT_R8_SSCALED:
return 1;
case VK_FORMAT_R8_UINT:
return 1;
case VK_FORMAT_R8_SINT:
return 1;
case VK_FORMAT_R8_SRGB:
return 1;
case VK_FORMAT_R8G8_UNORM:
return 1;
case VK_FORMAT_R8G8_SNORM:
return 1;
case VK_FORMAT_R8G8_USCALED:
return 1;
case VK_FORMAT_R8G8_SSCALED:
return 1;
case VK_FORMAT_R8G8_UINT:
return 1;
case VK_FORMAT_R8G8_SINT:
return 1;
case VK_FORMAT_R8G8_SRGB:
return 1;
case VK_FORMAT_R8G8B8_UNORM:
return 1;
case VK_FORMAT_R8G8B8_SNORM:
return 1;
case VK_FORMAT_R8G8B8_USCALED:
return 1;
case VK_FORMAT_R8G8B8_SSCALED:
return 1;
case VK_FORMAT_R8G8B8_UINT:
return 1;
case VK_FORMAT_R8G8B8_SINT:
return 1;
case VK_FORMAT_R8G8B8_SRGB:
return 1;
case VK_FORMAT_B8G8R8_UNORM:
return 1;
case VK_FORMAT_B8G8R8_SNORM:
return 1;
case VK_FORMAT_B8G8R8_USCALED:
return 1;
case VK_FORMAT_B8G8R8_SSCALED:
return 1;
case VK_FORMAT_B8G8R8_UINT:
return 1;
case VK_FORMAT_B8G8R8_SINT:
return 1;
case VK_FORMAT_B8G8R8_SRGB:
return 1;
case VK_FORMAT_R8G8B8A8_UNORM:
return 1;
case VK_FORMAT_R8G8B8A8_SNORM:
return 1;
case VK_FORMAT_R8G8B8A8_USCALED:
return 1;
case VK_FORMAT_R8G8B8A8_SSCALED:
return 1;
case VK_FORMAT_R8G8B8A8_UINT:
return 1;
case VK_FORMAT_R8G8B8A8_SINT:
return 1;
case VK_FORMAT_R8G8B8A8_SRGB:
return 1;
case VK_FORMAT_B8G8R8A8_UNORM:
return 1;
case VK_FORMAT_B8G8R8A8_SNORM:
return 1;
case VK_FORMAT_B8G8R8A8_USCALED:
return 1;
case VK_FORMAT_B8G8R8A8_SSCALED:
return 1;
case VK_FORMAT_B8G8R8A8_UINT:
return 1;
case VK_FORMAT_B8G8R8A8_SINT:
return 1;
case VK_FORMAT_B8G8R8A8_SRGB:
return 1;
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
return 4;
case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
return 4;
case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
return 4;
case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
return 4;
case VK_FORMAT_A8B8G8R8_UINT_PACK32:
return 4;
case VK_FORMAT_A8B8G8R8_SINT_PACK32:
return 4;
case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
return 4;
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
return 4;
case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
return 4;
case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
return 4;
case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
return 4;
case VK_FORMAT_A2R10G10B10_UINT_PACK32:
return 4;
case VK_FORMAT_A2R10G10B10_SINT_PACK32:
return 4;
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
return 4;
case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
return 4;
case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
return 4;
case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
return 4;
case VK_FORMAT_A2B10G10R10_UINT_PACK32:
return 4;
case VK_FORMAT_A2B10G10R10_SINT_PACK32:
return 4;
case VK_FORMAT_R16_UNORM:
return 2;
case VK_FORMAT_R16_SNORM:
return 2;
case VK_FORMAT_R16_USCALED:
return 2;
case VK_FORMAT_R16_SSCALED:
return 2;
case VK_FORMAT_R16_UINT:
return 2;
case VK_FORMAT_R16_SINT:
return 2;
case VK_FORMAT_R16_SFLOAT:
return 2;
case VK_FORMAT_R16G16_UNORM:
return 2;
case VK_FORMAT_R16G16_SNORM:
return 2;
case VK_FORMAT_R16G16_USCALED:
return 2;
case VK_FORMAT_R16G16_SSCALED:
return 2;
case VK_FORMAT_R16G16_UINT:
return 2;
case VK_FORMAT_R16G16_SINT:
return 2;
case VK_FORMAT_R16G16_SFLOAT:
return 2;
case VK_FORMAT_R16G16B16_UNORM:
return 2;
case VK_FORMAT_R16G16B16_SNORM:
return 2;
case VK_FORMAT_R16G16B16_USCALED:
return 2;
case VK_FORMAT_R16G16B16_SSCALED:
return 2;
case VK_FORMAT_R16G16B16_UINT:
return 2;
case VK_FORMAT_R16G16B16_SINT:
return 2;
case VK_FORMAT_R16G16B16_SFLOAT:
return 2;
case VK_FORMAT_R16G16B16A16_UNORM:
return 2;
case VK_FORMAT_R16G16B16A16_SNORM:
return 2;
case VK_FORMAT_R16G16B16A16_USCALED:
return 2;
case VK_FORMAT_R16G16B16A16_SSCALED:
return 2;
case VK_FORMAT_R16G16B16A16_UINT:
return 2;
case VK_FORMAT_R16G16B16A16_SINT:
return 2;
case VK_FORMAT_R16G16B16A16_SFLOAT:
return 2;
case VK_FORMAT_R32_UINT:
return 4;
case VK_FORMAT_R32_SINT:
return 4;
case VK_FORMAT_R32_SFLOAT:
return 4;
case VK_FORMAT_R32G32_UINT:
return 4;
case VK_FORMAT_R32G32_SINT:
return 4;
case VK_FORMAT_R32G32_SFLOAT:
return 4;
case VK_FORMAT_R32G32B32_UINT:
return 4;
case VK_FORMAT_R32G32B32_SINT:
return 4;
case VK_FORMAT_R32G32B32_SFLOAT:
return 4;
case VK_FORMAT_R32G32B32A32_UINT:
return 4;
case VK_FORMAT_R32G32B32A32_SINT:
return 4;
case VK_FORMAT_R32G32B32A32_SFLOAT:
return 4;
case VK_FORMAT_R64_UINT:
return 8;
case VK_FORMAT_R64_SINT:
return 8;
case VK_FORMAT_R64_SFLOAT:
return 8;
case VK_FORMAT_R64G64_UINT:
return 8;
case VK_FORMAT_R64G64_SINT:
return 8;
case VK_FORMAT_R64G64_SFLOAT:
return 8;
case VK_FORMAT_R64G64B64_UINT:
return 8;
case VK_FORMAT_R64G64B64_SINT:
return 8;
case VK_FORMAT_R64G64B64_SFLOAT:
return 8;
case VK_FORMAT_R64G64B64A64_UINT:
return 8;
case VK_FORMAT_R64G64B64A64_SINT:
return 8;
case VK_FORMAT_R64G64B64A64_SFLOAT:
return 8;
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
return 4;
case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
return 4;
case VK_FORMAT_D16_UNORM:
return 2;
case VK_FORMAT_X8_D24_UNORM_PACK32:
return 4;
case VK_FORMAT_D32_SFLOAT:
return 4;
case VK_FORMAT_S8_UINT:
return 1;
case VK_FORMAT_D16_UNORM_S8_UINT:
return 2;
case VK_FORMAT_D24_UNORM_S8_UINT:
return 4;
case VK_FORMAT_D32_SFLOAT_S8_UINT:
return 4;
case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
return 1;
case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
return 1;
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
return 1;
case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
return 1;
case VK_FORMAT_BC2_UNORM_BLOCK:
return 1;
case VK_FORMAT_BC2_SRGB_BLOCK:
return 1;
case VK_FORMAT_BC3_UNORM_BLOCK:
return 1;
case VK_FORMAT_BC3_SRGB_BLOCK:
return 1;
case VK_FORMAT_BC4_UNORM_BLOCK:
return 1;
case VK_FORMAT_BC4_SNORM_BLOCK:
return 1;
case VK_FORMAT_BC5_UNORM_BLOCK:
return 1;
case VK_FORMAT_BC5_SNORM_BLOCK:
return 1;
case VK_FORMAT_BC6H_UFLOAT_BLOCK:
return 1;
case VK_FORMAT_BC6H_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_BC7_UNORM_BLOCK:
return 1;
case VK_FORMAT_BC7_SRGB_BLOCK:
return 1;
case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
return 1;
case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
return 1;
case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
return 1;
case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
return 1;
case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
return 1;
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
return 1;
case VK_FORMAT_EAC_R11_UNORM_BLOCK:
return 1;
case VK_FORMAT_EAC_R11_SNORM_BLOCK:
return 1;
case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
return 1;
case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
return 1;
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
return 1;
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
return 1;
case VK_FORMAT_G8B8G8R8_422_UNORM:
return 1;
case VK_FORMAT_B8G8R8G8_422_UNORM:
return 1;
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
return 1;
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
return 1;
case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
return 1;
case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
return 1;
case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
return 1;
case VK_FORMAT_R10X6_UNORM_PACK16:
return 2;
case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
return 2;
case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
return 2;
case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
return 2;
case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
return 2;
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
return 2;
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
return 2;
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
return 2;
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
return 2;
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
return 2;
case VK_FORMAT_R12X4_UNORM_PACK16:
return 2;
case VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
return 2;
case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
return 2;
case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
return 2;
case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
return 2;
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
return 2;
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
return 2;
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
return 2;
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
return 2;
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
return 2;
case VK_FORMAT_G16B16G16R16_422_UNORM:
return 2;
case VK_FORMAT_B16G16R16G16_422_UNORM:
return 2;
case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
return 2;
case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
return 2;
case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
return 2;
case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
return 2;
case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
return 2;
case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM:
return 1;
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16:
return 2;
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16:
return 2;
case VK_FORMAT_G16_B16R16_2PLANE_444_UNORM:
return 2;
case VK_FORMAT_A4R4G4B4_UNORM_PACK16:
return 2;
case VK_FORMAT_A4B4G4R4_UNORM_PACK16:
return 2;
case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK:
return 1;
case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG:
return 1;
case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG:
return 1;
case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG:
return 1;
case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG:
return 1;
case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG:
return 1;
case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG:
return 1;
case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG:
return 1;
case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG:
return 1;
case VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_4x3x3_UNORM_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_4x4x3_UNORM_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_4x4x4_UNORM_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_5x4x4_UNORM_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_5x5x4_UNORM_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_5x5x5_UNORM_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_6x5x5_UNORM_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_6x6x5_UNORM_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT:
return 1;
case VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT:
return 1;
case VK_FORMAT_R16G16_SFIXED5_NV:
return 2;
case VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR:
return 2;
case VK_FORMAT_A8_UNORM_KHR:
return 1;
default:
return 0;
}
}
// clang-format on