/* -*- 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 texture2.c * @~English * * @brief ktxTexture2 implementation. Support for KTX2 format. * * @author Mark Callow, www.edgewise-consulting.com */ #if defined(_WIN32) #define _CRT_SECURE_NO_WARNINGS #endif #include <assert.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <zstd.h> #include <zstd_errors.h> #include <KHR/khr_df.h> #include "dfdutils/dfd.h" #include "ktx.h" #include "ktxint.h" #include "filestream.h" #include "memstream.h" #include "texture2.h" #include "unused.h" // FIXME: Test this #define and put it in a header somewhere. //#define IS_BIG_ENDIAN (1 == *(unsigned char *)&(const int){0x01000000ul}) #define IS_BIG_ENDIAN … extern uint32_t vkFormatTypeSize(VkFormat format); struct ktxTexture_vtbl ktxTexture2_vtbl; struct ktxTexture_vtblInt ktxTexture2_vtblInt; #if !defined(BITFIELD_ORDER_FROM_MSB) // Most compilers, including all those tested so far, including clang, gcc // and msvc, order bitfields from the lsb so these struct declarations work. // Could this be because I've only tested on little-endian machines? // These are preferred as they are much easier to manually initialize // and verify. struct sampleType { … }; struct BDFD { … }; struct BDFD e5b9g9r9_ufloat_comparator = …; #else // For compilers which order bitfields from the msb rather than lsb. #define shift … #define sampleshift … #define e5b9g9r9_bdbwordcount … ktx_uint32_t e5b9g9r9_ufloat_comparator[e5b9g9r9_bdbwordcount] = { 0, // descriptorType & vendorId shift(DESCRIPTORBLOCKSIZE, e5b9g9r9_bdbwordcount * sizeof(ktx_uint32_t)) | shift(VERSIONNUMBER, 2), // N.B. Allow various values of primaries, transfer & flags shift(FLAGS, KHR_DF_FLAG_ALPHA_STRAIGHT) | shift(TRANSFER, KHR_DF_TRANSFER_LINEAR) | shift(PRIMARIES, KHR_DF_PRIMARIES_BT709) | shift(MODEL, KHR_DF_MODEL_RGBSDA), 0, // texelBlockDimension3~0 shift(BYTESPLANE0, 4), // All other bytesPlane fields are 0. 0, // bytesPlane7~4 sampleshift(CHANNELID, KHR_DF_CHANNEL_RGBSDA_RED) | sampleshift(BITLENGTH, 8) | sampleshift(BITOFFSET, 0), 0, // samplePosition3~0 0, // sampleLower 8448, // sampleUpper sampleshift(CHANNELID, KHR_DF_CHANNEL_RGBSDA_RED | KHR_DF_SAMPLE_DATATYPE_EXPONENT) | sampleshift(BITLENGTH, 4) | sampleshift(BITOFFSET, 27), 0, // samplePosition3~0 15, // sampleLower 31, // sampleUpper sampleshift(CHANNELID, KHR_DF_CHANNEL_RGBSDA_GREEN) | sampleshift(BITLENGTH, 8) | sampleshift(BITOFFSET, 9), 0, // samplePosition3~0 0, // sampleLower 8448, // sampleUpper sampleshift(CHANNELID, KHR_DF_CHANNEL_RGBSDA_GREEN | KHR_DF_SAMPLE_DATATYPE_EXPONENT) | sampleshift(BITLENGTH, 4) | sampleshift(BITOFFSET, 27), 0, // samplePosition3~0 15, // sampleLower 31, // sampleUpper sampleshift(CHANNELID, KHR_DF_CHANNEL_RGBSDA_BLUE) | sampleshift(BITLENGTH, 8) | sampleshift(BITOFFSET, 18), 0, // samplePosition3~0 0, // sampleLower 8448, // sampleUpper sampleshift(CHANNELID, KHR_DF_CHANNEL_RGBSDA_BLUE | KHR_DF_SAMPLE_DATATYPE_EXPONENT) | sampleshift(BITLENGTH, 4) | sampleshift(BITOFFSET, 27), 0, // samplePosition3~0 15, // sampleLower 31, // sampleUpper }; #endif /** * @private * @~English * @brief Initialize a ktxFormatSize object from the info in a DFD. * * This is used instead of referring to the DFD directly so code dealing * with format info can be common to KTX 1 & 2. * * @param[in] This pointer the ktxFormatSize to initialize. * @param[in] pDFD pointer to the DFD whose data to use. * * @return KTX_TRUE on success, otherwise KTX_FALSE. */ bool ktxFormatSize_initFromDfd(ktxFormatSize* This, ktx_uint32_t* pDfd) { … } /** * @private * @~English * @brief Create a DFD for a VkFormat. * * This KTX-specific function adds support for combined depth stencil formats * which are not supported by @e dfdutils' @c vk2dfd function because they * are not seen outside a Vulkan device. KTX has its own definitions for * these that enable uploading, with some effort. * * @param[in] vkFormat the format for which to create a DFD. */ static uint32_t* ktxVk2dfd(ktx_uint32_t vkFormat) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Do the part of ktxTexture2 construction that is common to * new textures and those constructed from a stream. * * @param[in] This pointer to a ktxTexture2-sized block of memory to * initialize. * @param[in] numLevels the number of levels the texture must have. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * @exception KTX_OUT_OF_MEMORY Not enough memory for the texture data. */ static KTX_error_code ktxTexture2_constructCommon(ktxTexture2* This, ktx_uint32_t numLevels) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Construct a new, empty, ktxTexture2. * * @param[in] This pointer to a ktxTexture2-sized block of memory to * initialize. * @param[in] createInfo pointer to a ktxTextureCreateInfo struct with * information describing the texture. * @param[in] storageAllocation * enum indicating whether or not to allocate storage * for the texture images. * @return KTX_SUCCESS on success, other KTX_* enum values on error. * @exception KTX_OUT_OF_MEMORY Not enough memory for the texture or image data. * @exception KTX_UNSUPPORTED_TEXTURE_TYPE * The request VkFormat is one of the * prohibited formats. */ static KTX_error_code ktxTexture2_construct(ktxTexture2* This, ktxTextureCreateInfo* createInfo, ktxTextureCreateStorageEnum storageAllocation) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Construct a ktxTexture by copying a source ktxTexture. * * @param[in] This pointer to a ktxTexture2-sized block of memory to * initialize. * @param[in] orig pointer to the source texture to copy. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_OUT_OF_MEMORY Not enough memory for the texture data. */ KTX_error_code ktxTexture2_constructCopy(ktxTexture2* This, ktxTexture2* orig) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Construct a ktxTexture from a ktxStream reading from a KTX source. * * The KTX header, which must have been read prior to calling this, is passed * to the function. * * The stream object is copied into the constructed ktxTexture2. * * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set, * if the ktxTexture is ultimately to be uploaded to OpenGL or Vulkan. This * will minimize memory usage by allowing, for example, loading the images * directly from the source into a Vulkan staging buffer. * * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is * provided solely to enable implementation of the @e libktx v1 API on top of * ktxTexture. * * If either KTX_TEXTURE_CREATE_SKIP_KVDATA_BIT or * KTX_TEXTURE_CREATE_RAW_KVDATA_BIT is set then the ktxTexture's orientation * fields will be set to defaults even if the KTX source contains * KTXorientation metadata. * * @param[in] This pointer to a ktxTexture2-sized block of memory to * initialize. * @param[in] pStream pointer to the stream to read. * @param[in] pHeader pointer to a KTX header that has already been read from * the stream. * @param[in] createFlags bitmask requesting specific actions during creation. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_FILE_DATA_ERROR * Source data is inconsistent with the KTX * specification. * @exception KTX_FILE_READ_ERROR * An error occurred while reading the source. * @exception KTX_FILE_UNEXPECTED_EOF * Not enough data in the source. * @exception KTX_OUT_OF_MEMORY Not enough memory to load either the images or * the key-value data. * @exception KTX_UNKNOWN_FILE_FORMAT * The source is not in KTX format. * @exception KTX_UNSUPPORTED_TEXTURE_TYPE * The source describes a texture type not * supported by OpenGL or Vulkan, e.g, a 3D array. */ KTX_error_code ktxTexture2_constructFromStreamAndHeader(ktxTexture2* This, ktxStream* pStream, KTX_header2* pHeader, ktxTextureCreateFlags createFlags) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Construct a ktxTexture from a ktxStream reading from a KTX source. * * The stream object is copied into the constructed ktxTexture2. * * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set, * if the ktxTexture is ultimately to be uploaded to OpenGL or Vulkan. This * will minimize memory usage by allowing, for example, loading the images * directly from the source into a Vulkan staging buffer. * * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is * provided solely to enable implementation of the @e libktx v1 API on top of * ktxTexture. * * @param[in] This pointer to a ktxTexture2-sized block of memory to * initialize. * @param[in] pStream pointer to the stream to read. * @param[in] createFlags bitmask requesting specific actions during creation. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_FILE_READ_ERROR * An error occurred while reading the source. * * For other exceptions see ktxTexture2_constructFromStreamAndHeader(). */ static KTX_error_code ktxTexture2_constructFromStream(ktxTexture2* This, ktxStream* pStream, ktxTextureCreateFlags createFlags) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Construct a ktxTexture from a stdio stream reading from a KTX source. * * See ktxTextureInt_constructFromStream for details. * * @note Do not close the stdio stream until you are finished with the texture * object. * * @param[in] This pointer to a ktxTextureInt-sized block of memory to * initialize. * @param[in] stdioStream a stdio FILE pointer opened on the source. * @param[in] createFlags bitmask requesting specific actions during creation. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_INVALID_VALUE Either @p stdiostream or @p This is null. * * For other exceptions, see ktxTexture_constructFromStream(). */ static KTX_error_code ktxTexture2_constructFromStdioStream(ktxTexture2* This, FILE* stdioStream, ktxTextureCreateFlags createFlags) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Construct a ktxTexture from a named KTX file. * * The file name must be encoded in utf-8. On Windows convert unicode names * to utf-8 with @c WideCharToMultiByte(CP_UTF8, ...) before calling. * * See ktxTextureInt_constructFromStream for details. * * @param[in] This pointer to a ktxTextureInt-sized block of memory to * initialize. * @param[in] filename pointer to a char array containing the file name. * @param[in] createFlags bitmask requesting specific actions during creation. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_FILE_OPEN_FAILED The file could not be opened. * @exception KTX_INVALID_VALUE @p filename is @c NULL. * * For other exceptions, see ktxTexture_constructFromStream(). */ static KTX_error_code ktxTexture2_constructFromNamedFile(ktxTexture2* This, const char* const filename, ktxTextureCreateFlags createFlags) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Construct a ktxTexture from KTX-formatted data in memory. * * See ktxTextureInt_constructFromStream for details. * * @param[in] This pointer to a ktxTextureInt-sized block of memory to * initialize. * @param[in] bytes pointer to the memory containing the serialized KTX data. * @param[in] size length of the KTX data in bytes. * @param[in] createFlags bitmask requesting specific actions during creation. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_INVALID_VALUE Either @p bytes is NULL or @p size is 0. * * For other exceptions, see ktxTexture_constructFromStream(). */ static KTX_error_code ktxTexture2_constructFromMemory(ktxTexture2* This, const ktx_uint8_t* bytes, ktx_size_t size, ktxTextureCreateFlags createFlags) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Destruct a ktxTexture2, freeing and internal memory. * * @param[in] This pointer to a ktxTexture2-sized block of memory to * initialize. */ void ktxTexture2_destruct(ktxTexture2* This) { … } /** * @memberof ktxTexture2 * @ingroup writer * @~English * @brief Create a new empty ktxTexture2. * * The address of the newly created ktxTexture2 is written to the location * pointed at by @p newTex. * * @param[in] createInfo pointer to a ktxTextureCreateInfo struct with * information describing the texture. * @param[in] storageAllocation * enum indicating whether or not to allocate storage * for the texture images. * @param[in,out] newTex pointer to a location in which store the address of * the newly created texture. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_INVALID_VALUE @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's images. */ KTX_error_code ktxTexture2_Create(ktxTextureCreateInfo* createInfo, ktxTextureCreateStorageEnum storageAllocation, ktxTexture2** newTex) { … } /** * @memberof ktxTexture2 * @ingroup writer * @~English * @brief Create a ktxTexture2 by making a copy of a ktxTexture2. * * The address of the newly created ktxTexture2 is written to the location * pointed at by @p newTex. * * @param[in] orig pointer to the texture to copy. * @param[in,out] newTex pointer to a location in which store the address of * the newly created texture. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_OUT_OF_MEMORY Not enough memory for the texture data. */ KTX_error_code ktxTexture2_CreateCopy(ktxTexture2* orig, ktxTexture2** newTex) { … } /** * @defgroup reader Reader * @brief Read KTX-formatted data. * @{ */ /** * @memberof ktxTexture2 * @~English * @brief Create a ktxTexture2 from a stdio stream reading from a KTX source. * * The address of a newly created ktxTexture2 reflecting the contents of the * stdio stream is written to the location pointed at by @p newTex. * * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set, * if the ktxTexture is ultimately to be uploaded to OpenGL or Vulkan. This * will minimize memory usage by allowing, for example, loading the images * directly from the source into a Vulkan staging buffer. * * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is * provided solely to enable implementation of the @e libktx v1 API on top of * ktxTexture. * * @param[in] stdioStream stdio FILE pointer created from the desired file. * @param[in] createFlags bitmask requesting specific actions during creation. * @param[in,out] newTex pointer to a location in which store the address of * the newly created texture. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_INVALID_VALUE @p newTex is @c NULL. * @exception KTX_FILE_DATA_ERROR * Source data is inconsistent with the KTX * specification. * @exception KTX_FILE_READ_ERROR * An error occurred while reading the source. * @exception KTX_FILE_UNEXPECTED_EOF * Not enough data in the source. * @exception KTX_OUT_OF_MEMORY Not enough memory to create the texture object, * load the images or load the key-value data. * @exception KTX_UNKNOWN_FILE_FORMAT * The source is not in KTX format. * @exception KTX_UNSUPPORTED_TEXTURE_TYPE * The source describes a texture type not * supported by OpenGL or Vulkan, e.g, a 3D array. */ KTX_error_code ktxTexture2_CreateFromStdioStream(FILE* stdioStream, ktxTextureCreateFlags createFlags, ktxTexture2** newTex) { … } /** * @memberof ktxTexture2 * @~English * @brief Create a ktxTexture2 from a named KTX file. * * The address of a newly created ktxTexture2 reflecting the contents of the * file is written to the location pointed at by @p newTex. * * The file name must be encoded in utf-8. On Windows convert unicode names * to utf-8 with @c WideCharToMultiByte(CP_UTF8, ...) before calling. * * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set, * if the ktxTexture is ultimately to be uploaded to OpenGL or Vulkan. This * will minimize memory usage by allowing, for example, loading the images * directly from the source into a Vulkan staging buffer. * * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is * provided solely to enable implementation of the @e libktx v1 API on top of * ktxTexture. * * @param[in] filename pointer to a char array containing the file name. * @param[in] createFlags bitmask requesting specific actions during creation. * @param[in,out] newTex pointer to a location in which store the address of * the newly created texture. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * @exception KTX_FILE_OPEN_FAILED The file could not be opened. * @exception KTX_INVALID_VALUE @p filename is @c NULL. * * For other exceptions, see ktxTexture_CreateFromStdioStream(). */ KTX_error_code ktxTexture2_CreateFromNamedFile(const char* const filename, ktxTextureCreateFlags createFlags, ktxTexture2** newTex) { … } /** * @memberof ktxTexture2 * @~English * @brief Create a ktxTexture2 from KTX-formatted data in memory. * * The address of a newly created ktxTexture2 reflecting the contents of the * serialized KTX data is written to the location pointed at by @p newTex. * * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set, * if the ktxTexture is ultimately to be uploaded to OpenGL or Vulkan. This * will minimize memory usage by allowing, for example, loading the images * directly from the source into a Vulkan staging buffer. * * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is * provided solely to enable implementation of the @e libktx v1 API on top of * ktxTexture. * * @param[in] bytes pointer to the memory containing the serialized KTX data. * @param[in] size length of the KTX data in bytes. * @param[in] createFlags bitmask requesting specific actions during creation. * @param[in,out] newTex pointer to a location in which store the address of * the newly created texture. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_INVALID_VALUE Either @p bytes is NULL or @p size is 0. * * For other exceptions, see ktxTexture_CreateFromStdioStream(). */ KTX_error_code ktxTexture2_CreateFromMemory(const ktx_uint8_t* bytes, ktx_size_t size, ktxTextureCreateFlags createFlags, ktxTexture2** newTex) { … } /** * @memberof ktxTexture2 * @~English * @brief Create a ktxTexture2 from KTX-formatted data from a stream. * * The address of a newly created ktxTexture2 reflecting the contents of the * serialized KTX data is written to the location pointed at by @p newTex. * * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set, * if the ktxTexture is ultimately to be uploaded to OpenGL or Vulkan. This * will minimize memory usage by allowing, for example, loading the images * directly from the source into a Vulkan staging buffer. * * The create flag KTX_TEXTURE_CREATE_RAW_KVDATA_BIT should not be used. It is * provided solely to enable implementation of the @e libktx v1 API on top of * ktxTexture. * * @param[in] stream pointer to the stream to read KTX data from. * @param[in] createFlags bitmask requesting specific actions during creation. * @param[in,out] newTex pointer to a location in which store the address of * the newly created texture. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_INVALID_VALUE Either @p bytes is NULL or @p size is 0. * * For other exceptions, see ktxTexture_CreateFromStdioStream(). */ KTX_error_code ktxTexture2_CreateFromStream(ktxStream* stream, ktxTextureCreateFlags createFlags, ktxTexture2** newTex) { … } /** * @memberof ktxTexture2 * @~English * @brief Destroy a ktxTexture2 object. * * This frees the memory associated with the texture contents and the memory * of the ktxTexture2 object. This does @e not delete any OpenGL or Vulkan * texture objects created by ktxTexture2_GLUpload or ktxTexture2_VkUpload. * * @param[in] This pointer to the ktxTexture2 object to destroy */ void ktxTexture2_Destroy(ktxTexture2* This) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Calculate the size of the image data for the specified number * of levels. * * The data size is the sum of the sizes of each level up to the number * specified and includes any @c mipPadding between levels. It does * not include initial @c mipPadding required in the file. * * @param[in] This pointer to the ktxTexture object of interest. * @param[in] levels number of levels whose data size to return. * * @return the data size in bytes. */ ktx_size_t ktxTexture2_calcDataSizeLevels(ktxTexture2* This, ktx_uint32_t levels) { … } /** * @memberof ktxTexture2 @private * @~English * * @copydoc ktxTexture::ktxTexture_doCalcFaceLodSize */ ktx_size_t ktxTexture2_calcFaceLodSize(ktxTexture2* This, ktx_uint32_t level) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Return the offset of a level in bytes from the start of the image * data in a ktxTexture. * * Since the offset is from the start of the image data, it does not include the initial * @c mipPadding required in the file. * * @param[in] This pointer to the ktxTexture object of interest. * @param[in] level level whose offset to return. * * @return the data size in bytes. */ ktx_size_t ktxTexture2_calcLevelOffset(ktxTexture2* This, ktx_uint32_t level) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Retrieve the offset of a level's first image within the KTX2 file. * * @param[in] This pointer to the ktxTexture object of interest. */ ktx_uint64_t ktxTexture2_levelFileOffset(ktxTexture2* This, ktx_uint32_t level) { … } // Recursive function to return the greatest common divisor of a and b. static uint32_t gcd(uint32_t a, uint32_t b) { … } // Function to return the least common multiple of a & 4. uint32_t lcm4(uint32_t a) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Return the required alignment for levels of this texture. * * @param[in] This pointer to the ktxTexture2 object of interest. * * @return The required alignment for levels. */ ktx_uint32_t ktxTexture2_calcRequiredLevelAlignment(ktxTexture2* This) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Return what the required alignment for levels of this texture will be after inflation. * * @param[in] This pointer to the ktxTexture2 object of interest. * * @return The required alignment for levels. */ ktx_uint32_t ktxTexture2_calcPostInflationLevelAlignment(ktxTexture2* This) { … } /** * @memberof ktxTexture2 * @~English * @brief Return information about the components of an image in a texture. * * @param[in] This pointer to the ktxTexture object of interest. * @param[in,out] pNumComponents pointer to location in which to write the * number of components in the textures images. * @param[in,out] pComponentByteLength * pointer to the location in which to write * byte length of a component. */ void ktxTexture2_GetComponentInfo(ktxTexture2* This, uint32_t* pNumComponents, uint32_t* pComponentByteLength) { … } /** * @memberof ktxTexture2 * @~English * @brief Return the number of components in an image of the texture. * * Returns the number of components indicated by the DFD's sample information * in accordance with the color model. For uncompressed formats it will be the actual * number of components in the image. For block-compressed formats, it will be 1 or 2 * according to the format's DFD color model. For Basis compressed textures, the * function examines the ids of the channels indicated by the DFD and uses that * information to determine and return the number of components in the image * @e before encoding and deflation so it can be used to help choose a suitable * transcode target format. * * @param[in] This pointer to the ktxTexture object of interest. * * @return the number of components. */ ktx_uint32_t ktxTexture2_GetNumComponents(ktxTexture2* This) { … } /** * @memberof ktxTexture2 * @~English * @brief Find the offset of an image within a ktxTexture's image data. * * As there is no such thing as a 3D cubemap we make the 3rd location parameter * do double duty. Only works for non-supercompressed textures as * there is no way to tell where an image is for a supercompressed one. * * @param[in] This pointer to the ktxTexture object of interest. * @param[in] level mip level of the image. * @param[in] layer array layer of the image. * @param[in] faceSlice cube map face or depth slice of the image. * @param[in,out] pOffset pointer to location to store the offset. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_INVALID_OPERATION * @p level, @p layer or @p faceSlice exceed the * dimensions of the texture. * @exception KTX_INVALID_OPERATION Texture is supercompressed. * @exception KTX_INVALID_VALID @p This is NULL. */ KTX_error_code ktxTexture2_GetImageOffset(ktxTexture2* This, ktx_uint32_t level, ktx_uint32_t layer, ktx_uint32_t faceSlice, ktx_size_t* pOffset) { … } /** * @memberof ktxTexture2 * @~English * @brief Retrieve the opto-electrical transfer function of the images. * * @param[in] This pointer to the ktxTexture2 object of interest. * * @return A @c khr_df_transfer enum value specifying the OETF. */ khr_df_transfer_e ktxTexture2_GetOETF_e(ktxTexture2* This) { … } /** * @memberof ktxTexture2 * @~English * @brief Retrieve the opto-electrical transfer function of the images. * @deprecated Retained for backward compatibility. Use ktxTexture2\_GetOETF\_e() * * @param[in] This pointer to the ktxTexture2 object of interest. * * @return A @c khr_df_transfer enum value specifying the OETF, returned as * @c ktx_uint32_t. */ ktx_uint32_t ktxTexture2_GetOETF(ktxTexture2* This) { … } /** * @memberof ktxTexture2 * @~English * @brief Retrieve the DFD color model of the images. * * @param[in] This pointer to the ktxTexture2 object of interest. * * @return A @c khr_df_transfer enum value specifying the color model. */ khr_df_model_e ktxTexture2_GetColorModel_e(ktxTexture2* This) { … } /** * @memberof ktxTexture2 * @~English * @brief Retrieve whether the RGB components have been premultiplied by the alpha component. * * @param[in] This pointer to the ktxTexture2 object of interest. * * @return KTX\_TRUE if the components are premultiplied, KTX_FALSE otherwise. */ ktx_bool_t ktxTexture2_GetPremultipliedAlpha(ktxTexture2* This) { … } /** * @memberof ktxTexture2 * @~English * @brief Query if the images are in a transcodable format. * * @param[in] This pointer to the ktxTexture2 object of interest. */ ktx_bool_t ktxTexture2_NeedsTranscoding(ktxTexture2* This) { … } /** * @memberof ktxTexture2 * @~English * @brief Return the total size in bytes of the uncompressed data of a * ktxTexture2. * * If supercompressionScheme == @c KTX_SS_NONE or * @c KTX_SS_BASIS_LZ, returns the value of @c This->dataSize * else if supercompressionScheme == @c KTX_SS_ZSTD or @c KTX_SS_ZLIB, it * returns the sum of the uncompressed sizes of each mip level plus space for * the level padding. With no supercompression the data size and uncompressed * data size are the same. For Basis supercompression the uncompressed size * cannot be known until the data is transcoded so the compressed size is * returned. * * @param[in] This pointer to the ktxTexture1 object of interest. */ ktx_size_t ktxTexture2_GetDataSizeUncompressed(ktxTexture2* This) { … } /** * @memberof ktxTexture2 * @~English * @brief Calculate & return the size in bytes of an image at the specified * mip level. * * For arrays, this is the size of a 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 ktxTexture2 object of interest. * @param[in] level level of interest. * */ ktx_size_t ktxTexture2_GetImageSize(ktxTexture2* This, ktx_uint32_t level) { … } /** * @memberof ktxTexture2 * @~English * @brief Iterate over the mip levels in a ktxTexture2 object. * * This is almost identical to ktxTexture_IterateLevelFaces(). The difference is * that the blocks of image data for non-array cube maps include all faces of * a mip level. * * 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. * * Intended for use only when supercompressionScheme == SUPERCOMPRESSION_NONE. * * @param[in] This handle of the ktxTexture opened on the data. * @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_OPERATION supercompressionScheme != SUPERCOMPRESSION_NONE. * @exception KTX_INVALID_VALUE @p This is @c NULL or @p iterCb is @c NULL. * */ KTX_error_code ktxTexture2_IterateLevels(ktxTexture2* This, PFNKTXITERCB iterCb, void* userdata) { … } /** * @memberof ktxTexture2 * @~English * @brief Iterate over the images in a ktxTexture2 object while loading the * image data. * * This operates similarly to ktxTexture_IterateLevelFaces() except that it * loads the images from the ktxTexture2's source to a temporary buffer * while iterating. If supercompressionScheme == KTX_SS_ZSTD or KTX_SS_ZLIB, * it will inflate the data before passing it to the callback. The callback function * must copy the image data if it wishes to preserve it as the temporary buffer * is reused for each level and is freed when this function exits. * * This function is helpful for reducing memory usage when uploading the data * to a graphics API. * * Intended for use only when supercompressionScheme == KTX_SS_NONE, * KTX_SS_ZSTD or KTX_SS_ZLIB. As there is no access to the ktxTexture's data on * conclusion of this function, destroying the texture on completion is recommended. * * @param[in] This pointer to the ktxTexture2 object of interest. * @param[in,out] iterCb the address of a callback function which is called * with the data for each image. * @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_OPERATION the ktxTexture2 was not created from a * stream, i.e there is no data to load, or * this ktxTexture2's images have already * been loaded. * @exception KTX_INVALID_OPERATION * supercompressionScheme != KTX_SS_NONE, * supercompressionScheme != KTX_SS_ZSTD, and * supercompressionScheme != KTX_SS_ZLIB. * @exception KTX_INVALID_VALUE @p This is @c NULL or @p iterCb is @c NULL. * @exception KTX_OUT_OF_MEMORY not enough memory to allocate a block to * hold the base level image. */ KTX_error_code ktxTexture2_IterateLoadLevelFaces(ktxTexture2* This, PFNKTXITERCB iterCb, void* userdata) { … } KTX_error_code ktxTexture2_inflateZstdInt(ktxTexture2* This, ktx_uint8_t* pDeflatedData, ktx_uint8_t* pInflatedData, ktx_size_t inflatedDataCapacity); KTX_error_code ktxTexture2_inflateZLIBInt(ktxTexture2* This, ktx_uint8_t* pDeflatedData, ktx_uint8_t* pInflatedData, ktx_size_t inflatedDataCapacity); /** * @memberof ktxTexture2 * @~English * @brief Load all the image data from the ktxTexture2's source. * * The data will be inflated if supercompressionScheme == @c KTX_SS_ZSTD or * @c KTX_SS_ZLIB. * The data is loaded into the provided buffer or to an internally allocated * buffer, if @p pBuffer is @c NULL. Callers providing their own buffer must * ensure the buffer large enough to hold the inflated data for files deflated * with Zstd or ZLIB. See ktxTexture2\_GetDataSizeUncompressed(). * * The texture's levelIndex, dataSize, DFD and supercompressionScheme will * all be updated after successful inflation to reflect the inflated data. * * @param[in] This pointer to the ktxTexture object of interest. * @param[in] pBuffer pointer to the buffer in which to load the image data. * @param[in] bufSize size of the buffer pointed at by @p pBuffer. * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_INVALID_VALUE @p This is NULL. * @exception KTX_INVALID_VALUE @p bufSize is less than the the image data size. * @exception KTX_INVALID_OPERATION * The data has already been loaded or the * ktxTexture was not created from a KTX source. * @exception KTX_OUT_OF_MEMORY Insufficient memory for the image data. */ KTX_error_code ktxTexture2_LoadImageData(ktxTexture2* This, ktx_uint8_t* pBuffer, ktx_size_t bufSize) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Retrieve the offset of a level's first image within the ktxTexture2's * image data. * * @param[in] This pointer to the ktxTexture2 object of interest. */ ktx_uint64_t ktxTexture2_levelDataOffset(ktxTexture2* This, ktx_uint32_t level) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Inflate the data in a ktxTexture2 object using Zstandard. * * The texture's levelIndex, dataSize, DFD and supercompressionScheme will * all be updated after successful inflation to reflect the inflated data. * * @param[in] This pointer to the ktxTexture2 object of interest. * @param[in] pDeflatedData pointer to a buffer containing the deflated data * of the entire texture. * @param[in,out] pInflatedData pointer to a buffer in which to write the inflated * data. * @param[in] inflatedDataCapacity capacity of the buffer pointed at by * @p pInflatedData. */ KTX_error_code ktxTexture2_inflateZstdInt(ktxTexture2* This, ktx_uint8_t* pDeflatedData, ktx_uint8_t* pInflatedData, ktx_size_t inflatedDataCapacity) { … } /** * @memberof ktxTexture2 @private * @~English * @brief Inflate the data in a ktxTexture2 object using miniz (ZLIB). * * The texture's levelIndex, dataSize, DFD and supercompressionScheme will * all be updated after successful inflation to reflect the inflated data. * * @param[in] This pointer to the ktxTexture2 object of interest. * @param[in] pDeflatedData pointer to a buffer containing the deflated * data of the entire texture. * @param[in,out] pInflatedData pointer to a buffer in which to write the * inflated data. * @param[in] inflatedDataCapacity capacity of the buffer pointed at by * @p pInflatedData. */ KTX_error_code ktxTexture2_inflateZLIBInt(ktxTexture2* This, ktx_uint8_t* pDeflatedData, ktx_uint8_t* pInflatedData, ktx_size_t inflatedDataCapacity) { … } #if !KTX_FEATURE_WRITE /* * Stubs for writer functions that return a proper error code */ KTX_error_code ktxTexture2_SetImageFromMemory(ktxTexture2* This, ktx_uint32_t level, ktx_uint32_t layer, ktx_uint32_t faceSlice, const ktx_uint8_t* src, ktx_size_t srcSize) { … } KTX_error_code ktxTexture2_SetImageFromStdioStream(ktxTexture2* This, ktx_uint32_t level, ktx_uint32_t layer, ktx_uint32_t faceSlice, FILE* src, ktx_size_t srcSize) { … } KTX_error_code ktxTexture2_WriteToStdioStream(ktxTexture2* This, FILE* dstsstr) { … } KTX_error_code ktxTexture2_WriteToNamedFile(ktxTexture2* This, const char* const dstname) { … } KTX_error_code ktxTexture2_WriteToMemory(ktxTexture2* This, ktx_uint8_t** ppDstBytes, ktx_size_t* pSize) { … } KTX_error_code ktxTexture2_WriteToStream(ktxTexture2* This, ktxStream* dststr) { … } #endif /* * Initialized here at the end to avoid the need for multiple declarations of * the virtual functions. */ struct ktxTexture_vtblInt ktxTexture2_vtblInt = …; struct ktxTexture_vtbl ktxTexture2_vtbl = …; /** @} */