12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460 |
- /* -*- 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 ktxTexture1 implementation. Support for KTX format.
- *
- * @author Mark Callow, www.edgewise-consulting.com
- */
- #if defined(_WIN32)
- #define _CRT_SECURE_NO_WARNINGS
- #endif
- #include <stdlib.h>
- #include <string.h>
- #include "dfdutils/dfd.h"
- #include "ktx.h"
- #include "ktxint.h"
- #include "filestream.h"
- #include "memstream.h"
- #include "texture1.h"
- #include "unused.h"
- #include "gl_format.h"
- typedef struct ktxTexture1_private {
- ktx_bool_t _needSwap;
- } ktxTexture1_private;
- struct ktxTexture_vtbl ktxTexture1_vtbl;
- struct ktxTexture_vtblInt ktxTexture1_vtblInt;
- static KTX_error_code
- ktxTexture1_constructCommon(ktxTexture1* This)
- {
- assert(This != NULL);
- This->classId = ktxTexture1_c;
- This->vtbl = &ktxTexture1_vtbl;
- This->_protected->_vtbl = ktxTexture1_vtblInt;
- This->_private = (ktxTexture1_private*)malloc(sizeof(ktxTexture1_private));
- if (This->_private == NULL) {
- return KTX_OUT_OF_MEMORY;
- }
- memset(This->_private, 0, sizeof(*This->_private));
- return KTX_SUCCESS;
- }
- /**
- * @memberof ktxTexture1 @private
- * @copydoc ktxTexture2_construct
- */
- static KTX_error_code
- ktxTexture1_construct(ktxTexture1* This, ktxTextureCreateInfo* createInfo,
- ktxTextureCreateStorageEnum storageAllocation)
- {
- ktxTexture_protected* prtctd;
- ktxFormatSize formatSize;
- GLuint typeSize;
- GLenum glFormat;
- KTX_error_code result;
- memset(This, 0, sizeof(*This));
- This->glInternalformat = createInfo->glInternalformat;
- glGetFormatSize(This->glInternalformat, &formatSize);
- if (formatSize.blockSizeInBits == 0) {
- // Most likely a deprecated legacy format.
- return KTX_UNSUPPORTED_TEXTURE_TYPE;
- }
- glFormat= glGetFormatFromInternalFormat(createInfo->glInternalformat);
- if (glFormat == GL_INVALID_VALUE) {
- return KTX_INVALID_VALUE;
- }
- result = ktxTexture_construct(ktxTexture(This), createInfo, &formatSize);
- if (result != KTX_SUCCESS)
- return result;
- result = ktxTexture1_constructCommon(This);
- if (result != KTX_SUCCESS)
- return result;
- prtctd = This->_protected;
- This->isCompressed
- = (formatSize.flags & KTX_FORMAT_SIZE_COMPRESSED_BIT);
- if (This->isCompressed) {
- This->glFormat = 0;
- This->glBaseInternalformat = glFormat;
- This->glType = 0;
- prtctd->_typeSize = 1;
- } else {
- This->glBaseInternalformat = This->glFormat = glFormat;
- This->glType
- = glGetTypeFromInternalFormat(createInfo->glInternalformat);
- if (This->glType == GL_INVALID_VALUE) {
- result = KTX_INVALID_VALUE;
- goto cleanup;
- }
- typeSize = glGetTypeSizeFromType(This->glType);
- assert(typeSize != GL_INVALID_VALUE);
- /* Do some sanity checking */
- if (typeSize != 1 &&
- typeSize != 2 &&
- typeSize != 4)
- {
- /* Only 8, 16, and 32-bit types are supported for byte-swapping.
- * See UNPACK_SWAP_BYTES & table 8.4 in the OpenGL 4.4 spec.
- */
- result = KTX_INVALID_VALUE;
- goto cleanup;
- }
- prtctd->_typeSize = typeSize;
- }
- if (storageAllocation == KTX_TEXTURE_CREATE_ALLOC_STORAGE) {
- This->dataSize
- = ktxTexture_calcDataSizeTexture(ktxTexture(This));
- This->pData = malloc(This->dataSize);
- if (This->pData == NULL) {
- result = KTX_OUT_OF_MEMORY;
- goto cleanup;
- }
- }
- return result;
- cleanup:
- ktxTexture1_destruct(This);
- ktxTexture_destruct(ktxTexture(This));
- return result;
- }
- /**
- * @memberof ktxTexture1 @private
- * @brief Construct a ktxTexture1 from a ktxStream reading from a KTX source.
- *
- * The KTX header, that must have been read prior to calling this, is passed
- * to the function.
- *
- * The stream object is copied into the constructed ktxTexture1.
- *
- * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
- * if the ktxTexture1 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
- * ktxTexture1.
- *
- * @param[in] This pointer to a ktxTexture1-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
- ktxTexture1_constructFromStreamAndHeader(ktxTexture1* This, ktxStream* pStream,
- KTX_header* pHeader,
- ktxTextureCreateFlags createFlags)
- {
- ktxTexture1_private* private;
- KTX_error_code result;
- KTX_supplemental_info suppInfo;
- ktxStream* stream;
- ktx_off_t pos;
- ktx_size_t size;
- ktxFormatSize formatSize;
- assert(pHeader != NULL && pStream != NULL);
- memset(This, 0, sizeof(*This));
- result = ktxTexture_constructFromStream(ktxTexture(This), pStream, createFlags);
- if (result != KTX_SUCCESS)
- return result;
- result = ktxTexture1_constructCommon(This);
- if (result != KTX_SUCCESS) {
- ktxTexture_destruct(ktxTexture(This));
- return result;
- }
- private = This->_private;
- stream = ktxTexture1_getStream(This);
- result = ktxCheckHeader1_(pHeader, &suppInfo);
- if (result != KTX_SUCCESS)
- goto cleanup;
- /*
- * Initialize from pHeader info.
- */
- This->glFormat = pHeader->glFormat;
- This->glInternalformat = pHeader->glInternalformat;
- This->glType = pHeader->glType;
- glGetFormatSize(This->glInternalformat, &formatSize);
- if (formatSize.blockSizeInBits == 0) {
- // Most likely a deprecated legacy format.
- result = KTX_UNSUPPORTED_TEXTURE_TYPE;
- goto cleanup;
- }
- This->_protected->_formatSize = formatSize;
- This->glBaseInternalformat = pHeader->glBaseInternalformat;
- // Can these be done by a ktxTexture_constructFromStream?
- This->numDimensions = suppInfo.textureDimension;
- This->baseWidth = pHeader->pixelWidth;
- assert(suppInfo.textureDimension > 0 && suppInfo.textureDimension < 4);
- switch (suppInfo.textureDimension) {
- case 1:
- This->baseHeight = This->baseDepth = 1;
- break;
- case 2:
- This->baseHeight = pHeader->pixelHeight;
- This->baseDepth = 1;
- break;
- case 3:
- This->baseHeight = pHeader->pixelHeight;
- This->baseDepth = pHeader->pixelDepth;
- break;
- }
- if (pHeader->numberOfArrayElements > 0) {
- This->numLayers = pHeader->numberOfArrayElements;
- This->isArray = KTX_TRUE;
- } else {
- This->numLayers = 1;
- This->isArray = KTX_FALSE;
- }
- This->numFaces = pHeader->numberOfFaces;
- if (pHeader->numberOfFaces == 6)
- This->isCubemap = KTX_TRUE;
- else
- This->isCubemap = KTX_FALSE;
- This->numLevels = pHeader->numberOfMipLevels;
- This->isCompressed = suppInfo.compressed;
- This->generateMipmaps = suppInfo.generateMipmaps;
- if (pHeader->endianness == KTX_ENDIAN_REF_REV)
- private->_needSwap = KTX_TRUE;
- This->_protected->_typeSize = pHeader->glTypeSize;
- /*
- * Make an empty hash list.
- */
- ktxHashList_Construct(&This->kvDataHead);
- /*
- * Load KVData.
- */
- if (pHeader->bytesOfKeyValueData > 0) {
- if (!(createFlags & KTX_TEXTURE_CREATE_SKIP_KVDATA_BIT)) {
- ktx_uint32_t kvdLen = pHeader->bytesOfKeyValueData;
- ktx_uint8_t* pKvd;
- pKvd = malloc(kvdLen);
- if (pKvd == NULL) {
- result = KTX_OUT_OF_MEMORY;
- goto cleanup;
- }
- result = stream->read(stream, pKvd, kvdLen);
- if (result != KTX_SUCCESS)
- goto cleanup;
- if (private->_needSwap) {
- /* Swap the counts inside the key & value data. */
- ktx_uint8_t* src = pKvd;
- ktx_uint8_t* end = pKvd + kvdLen;
- while (src < end) {
- ktx_uint32_t* pKeyAndValueByteSize = (ktx_uint32_t*)src;
- _ktxSwapEndian32(pKeyAndValueByteSize, 1);
- src += _KTX_PAD4(*pKeyAndValueByteSize);
- }
- }
- if (!(createFlags & KTX_TEXTURE_CREATE_RAW_KVDATA_BIT)) {
- char* orientation;
- ktx_uint32_t orientationLen;
- result = ktxHashList_Deserialize(&This->kvDataHead,
- kvdLen, pKvd);
- free(pKvd);
- if (result != KTX_SUCCESS) {
- goto cleanup;
- }
- result = ktxHashList_FindValue(&This->kvDataHead,
- KTX_ORIENTATION_KEY,
- &orientationLen,
- (void**)&orientation);
- assert(result != KTX_INVALID_VALUE);
- if (result == KTX_SUCCESS) {
- ktx_uint32_t count;
- char orient[4] = {0, 0, 0, 0};
- count = sscanf(orientation, KTX_ORIENTATION3_FMT,
- &orient[0],
- &orient[1],
- &orient[2]);
- if (count > This->numDimensions) {
- // KTX 1 is less strict than KTX2 so there is a chance
- // of having more dimensions than needed.
- count = This->numDimensions;
- }
- switch (This->numDimensions) {
- case 3:
- This->orientation.z = orient[2];
- FALLTHROUGH;
- case 2:
- This->orientation.y = orient[1];
- FALLTHROUGH;
- case 1:
- This->orientation.x = orient[0];
- }
- }
- } else {
- This->kvDataLen = kvdLen;
- This->kvData = pKvd;
- }
- } else {
- stream->skip(stream, pHeader->bytesOfKeyValueData);
- }
- }
- /*
- * Get the size of the image data.
- */
- result = stream->getsize(stream, &size);
- if (result != KTX_SUCCESS)
- goto cleanup;
- result = stream->getpos(stream, &pos);
- if (result != KTX_SUCCESS)
- goto cleanup;
- /* Remove space for faceLodSize fields */
- This->dataSize = size - pos - This->numLevels * sizeof(ktx_uint32_t);
- /*
- * Load the images, if requested.
- */
- if (createFlags & KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT) {
- result = ktxTexture1_LoadImageData(This, NULL, 0);
- }
- if (result == KTX_SUCCESS)
- return result;
- cleanup:
- ktxTexture1_destruct(This);
- return result;
- }
- /**
- * @memberof ktxTexture1 @private
- * @brief Construct a ktxTexture1 from a ktxStream reading from a KTX source.
- *
- * The stream object is copied into the constructed ktxTexture1.
- *
- * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
- * if the ktxTexture1 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
- * ktxTexture1.
- *
- * @param[in] This pointer to a ktxTexture1-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 ktxTexture1_constructFromStreamAndHeader().
- */
- static KTX_error_code
- ktxTexture1_constructFromStream(ktxTexture1* This, ktxStream* pStream,
- ktxTextureCreateFlags createFlags)
- {
- KTX_header header;
- KTX_error_code result;
- // Read header.
- result = pStream->read(pStream, &header, KTX_HEADER_SIZE);
- if (result != KTX_SUCCESS)
- return result;
- return ktxTexture1_constructFromStreamAndHeader(This, pStream,
- &header, createFlags);
- }
- /**
- * @memberof ktxTexture1 @private
- * @brief Construct a ktxTexture1 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
- ktxTexture1_constructFromStdioStream(ktxTexture1* This, FILE* stdioStream,
- ktxTextureCreateFlags createFlags)
- {
- ktxStream stream;
- KTX_error_code result;
- if (stdioStream == NULL || This == NULL)
- return KTX_INVALID_VALUE;
- result = ktxFileStream_construct(&stream, stdioStream, KTX_FALSE);
- if (result == KTX_SUCCESS)
- result = ktxTexture1_constructFromStream(This, &stream, createFlags);
- return result;
- }
- /**
- * @memberof ktxTexture1 @private
- * @brief Construct a ktxTexture1 from a named KTX file.
- *
- * 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
- ktxTexture1_constructFromNamedFile(ktxTexture1* This,
- const char* const filename,
- ktxTextureCreateFlags createFlags)
- {
- FILE* file;
- ktxStream stream;
- KTX_error_code result;
- if (This == NULL || filename == NULL)
- return KTX_INVALID_VALUE;
- file = fopen(filename, "rb");
- if (!file)
- return KTX_FILE_OPEN_FAILED;
- result = ktxFileStream_construct(&stream, file, KTX_TRUE);
- if (result == KTX_SUCCESS)
- result = ktxTexture1_constructFromStream(This, &stream, createFlags);
- return result;
- }
- /**
- * @memberof ktxTexture1 @private
- * @brief Construct a ktxTexture1 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
- ktxTexture1_constructFromMemory(ktxTexture1* This,
- const ktx_uint8_t* bytes, ktx_size_t size,
- ktxTextureCreateFlags createFlags)
- {
- ktxStream stream;
- KTX_error_code result;
- if (bytes == NULL || size == 0)
- return KTX_INVALID_VALUE;
- result = ktxMemStream_construct_ro(&stream, bytes, size);
- if (result == KTX_SUCCESS)
- result = ktxTexture1_constructFromStream(This, &stream, createFlags);
- return result;
- }
- void
- ktxTexture1_destruct(ktxTexture1* This)
- {
- if (This->_private) free(This->_private);
- ktxTexture_destruct(ktxTexture(This));
- }
- /**
- * @defgroup reader Reader
- * @brief Read KTX-formatted data.
- * @{
- */
- /**
- * @memberof ktxTexture1
- * @ingroup writer
- * @brief Create a new empty ktxTexture1.
- *
- * The address of the newly created ktxTexture1 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
- ktxTexture1_Create(ktxTextureCreateInfo* createInfo,
- ktxTextureCreateStorageEnum storageAllocation,
- ktxTexture1** newTex)
- {
- KTX_error_code result;
- if (newTex == NULL)
- return KTX_INVALID_VALUE;
- ktxTexture1* tex = (ktxTexture1*)malloc(sizeof(ktxTexture1));
- if (tex == NULL)
- return KTX_OUT_OF_MEMORY;
- result = ktxTexture1_construct(tex, createInfo, storageAllocation);
- if (result != KTX_SUCCESS) {
- free(tex);
- } else {
- *newTex = tex;
- }
- return result;
- }
- /**
- * @memberof ktxTexture1
- * @~English
- * @brief Create a ktxTexture1 from a stdio stream reading from a KTX source.
- *
- * The address of a newly created ktxTexture1 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 ktxTexture1 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
- * ktxTexture1.
- *
- * @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
- ktxTexture1_CreateFromStdioStream(FILE* stdioStream,
- ktxTextureCreateFlags createFlags,
- ktxTexture1** newTex)
- {
- KTX_error_code result;
- if (newTex == NULL)
- return KTX_INVALID_VALUE;
- ktxTexture1* tex = (ktxTexture1*)malloc(sizeof(ktxTexture1));
- if (tex == NULL)
- return KTX_OUT_OF_MEMORY;
- result = ktxTexture1_constructFromStdioStream(tex, stdioStream,
- createFlags);
- if (result == KTX_SUCCESS)
- *newTex = (ktxTexture1*)tex;
- else {
- free(tex);
- *newTex = NULL;
- }
- return result;
- }
- /*
- * @memberof ktxTexture1
- * @~English
- * @brief Create a ktxTexture1 from a named KTX file.
- *
- * The address of a newly created ktxTexture1 reflecting the contents of the
- * file is written to the location pointed at by @p newTex.
- *
- * The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
- * if the ktxTexture1 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
- * ktxTexture1.
- *
- * @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
- ktxTexture1_CreateFromNamedFile(const char* const filename,
- ktxTextureCreateFlags createFlags,
- ktxTexture1** newTex)
- {
- KTX_error_code result;
- if (newTex == NULL)
- return KTX_INVALID_VALUE;
- ktxTexture1* tex = (ktxTexture1*)malloc(sizeof(ktxTexture1));
- if (tex == NULL)
- return KTX_OUT_OF_MEMORY;
- result = ktxTexture1_constructFromNamedFile(tex, filename, createFlags);
- if (result == KTX_SUCCESS)
- *newTex = (ktxTexture1*)tex;
- else {
- free(tex);
- *newTex = NULL;
- }
- return result;
- }
- /**
- * @memberof ktxTexture1
- * @~English
- * @brief Create a ktxTexture1 from KTX-formatted data in memory.
- *
- * The address of a newly created ktxTexture1 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 ktxTexture1 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
- * ktxTexture1.
- *
- * @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
- ktxTexture1_CreateFromMemory(const ktx_uint8_t* bytes, ktx_size_t size,
- ktxTextureCreateFlags createFlags,
- ktxTexture1** newTex)
- {
- KTX_error_code result;
- if (newTex == NULL)
- return KTX_INVALID_VALUE;
- ktxTexture1* tex = (ktxTexture1*)malloc(sizeof(ktxTexture1));
- if (tex == NULL)
- return KTX_OUT_OF_MEMORY;
- result = ktxTexture1_constructFromMemory(tex, bytes, size,
- createFlags);
- if (result == KTX_SUCCESS)
- *newTex = (ktxTexture1*)tex;
- else {
- free(tex);
- *newTex = NULL;
- }
- return result;
- }
- /**
- * @memberof ktxTexture1
- * @~English
- * @brief Create a ktxTexture1 from KTX-formatted data from a `ktxStream`.
- *
- * The address of a newly created ktxTexture1 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 ktxTexture1 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
- * ktxTexture1.
- *
- * @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
- ktxTexture1_CreateFromStream(ktxStream* stream,
- ktxTextureCreateFlags createFlags,
- ktxTexture1** newTex)
- {
- KTX_error_code result;
- if (newTex == NULL)
- return KTX_INVALID_VALUE;
- ktxTexture1* tex = (ktxTexture1*)malloc(sizeof(ktxTexture1));
- if (tex == NULL)
- return KTX_OUT_OF_MEMORY;
- result = ktxTexture1_constructFromStream(tex, stream, createFlags);
- if (result == KTX_SUCCESS)
- *newTex = (ktxTexture1*)tex;
- else {
- free(tex);
- *newTex = NULL;
- }
- return result;
- }
- /**
- * @memberof ktxTexture1
- * @~English
- * @brief Destroy a ktxTexture1 object.
- *
- * This frees the memory associated with the texture contents and the memory
- * of the ktxTexture1 object. This does @e not delete any OpenGL or Vulkan
- * texture objects created by ktxTexture1_GLUpload or ktxTexture1_VkUpload.
- *
- * @param[in] This pointer to the ktxTexture1 object to destroy
- */
- void
- ktxTexture1_Destroy(ktxTexture1* This)
- {
- ktxTexture1_destruct(This);
- free(This);
- }
- /**
- * @memberof ktxTexture @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.
- *
- * @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
- ktxTexture1_calcDataSizeLevels(ktxTexture1* This, ktx_uint32_t levels)
- {
- ktx_uint32_t i;
- ktx_size_t dataSize = 0;
- assert(This != NULL);
- assert(levels <= This->numLevels);
- for (i = 0; i < levels; i++) {
- ktx_size_t levelSize = ktxTexture_calcLevelSize(ktxTexture(This), i,
- KTX_FORMAT_VERSION_ONE);
- /* mipPadding. NOTE: this adds padding after the last level too. */
- #if KTX_GL_UNPACK_ALIGNMENT != 4
- dataSize += _KTX_PAD4(levelSize);
- #else
- dataSize += levelSize;
- #endif
- }
- return dataSize;
- }
- /**
- * @memberof ktxTexture1 @private
- * @~English
- *
- * @copydoc ktxTexture::ktxTexture_doCalcFaceLodSize
- */
- ktx_size_t
- ktxTexture1_calcFaceLodSize(ktxTexture1* This, ktx_uint32_t level)
- {
- return ktxTexture_doCalcFaceLodSize(ktxTexture(This), level,
- KTX_FORMAT_VERSION_ONE);
- }
- /**
- * @memberof ktxTexture @private
- * @~English
- * @brief Return the offset of a level in bytes from the start of the image
- * data in 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] level level whose offset to return.
- * @param[in] fv enum specifying format version for which to calculate
- * image size.
- *
- * @return the data size in bytes.
- */
- ktx_size_t
- ktxTexture1_calcLevelOffset(ktxTexture1* This, ktx_uint32_t level)
- {
- assert (This != NULL);
- assert (level < This->numLevels);
- return ktxTexture1_calcDataSizeLevels(This, level);
- }
- /**
- * @memberof ktxTexture1
- * @~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.
- *
- * @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_VALID @p This is NULL.
- */
- KTX_error_code
- ktxTexture1_GetImageOffset(ktxTexture1* This, ktx_uint32_t level,
- ktx_uint32_t layer, ktx_uint32_t faceSlice,
- ktx_size_t* pOffset)
- {
- if (This == NULL)
- return KTX_INVALID_VALUE;
- if (level >= This->numLevels || layer >= This->numLayers)
- return KTX_INVALID_OPERATION;
- if (This->isCubemap) {
- if (faceSlice >= This->numFaces)
- return KTX_INVALID_OPERATION;
- } else {
- ktx_uint32_t maxSlice = MAX(1, This->baseDepth >> level);
- if (faceSlice >= maxSlice)
- return KTX_INVALID_OPERATION;
- }
- // Get the size of the data up to the start of the indexed level.
- *pOffset = ktxTexture_calcDataSizeLevels(ktxTexture(This), level);
- // All layers, faces & slices within a level are the same size.
- if (layer != 0) {
- ktx_size_t layerSize;
- layerSize = ktxTexture_layerSize(ktxTexture(This), level,
- KTX_FORMAT_VERSION_ONE);
- *pOffset += layer * layerSize;
- }
- if (faceSlice != 0) {
- ktx_size_t imageSize;
- imageSize = ktxTexture_GetImageSize(ktxTexture(This), level);
- #if (KTX_GL_UNPACK_ALIGNMENT != 4)
- if (This->isCubemap)
- _KTX_PAD4(imageSize); // Account for cubePadding.
- #endif
- *pOffset += faceSlice * imageSize;
- }
- return KTX_SUCCESS;
- }
- /**
- * @memberof ktxTexture1
- * @~English
- * @brief Return the total size in bytes of the uncompressed data of a ktxTexture1.
- *
- * This always returns the value of @c This->dataSize. The function is provided for
- * symmetry with ktxTexture2.
- *
- * @param[in] This pointer to the ktxTexture1 object of interest.
- * @return The size of the data in the texture.
- */
- ktx_size_t
- ktxTexture1_GetDataSizeUncompressed(ktxTexture1* This)
- {
- return This->dataSize;
- }
- /**
- * @memberof ktxTexture1
- * @~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 ktxTexture1 object of interest.
- * @param[in] level level of interest.
- */
- ktx_size_t
- ktxTexture1_GetImageSize(ktxTexture1* This, ktx_uint32_t level)
- {
- return ktxTexture_calcImageSize(ktxTexture(This), level,
- KTX_FORMAT_VERSION_ONE);
- }
- /**
- * @memberof ktxTexture1 @private
- * @~English
- * @brief Return the size of the primitive type of a single color component
- *
- * @param[in] This pointer to the ktxTexture1 object of interest.
- *
- * @return the type size in bytes.
- */
- ktx_uint32_t
- ktxTexture1_glTypeSize(ktxTexture1* This)
- {
- assert(This != NULL);
- return This->_protected->_typeSize;
- }
- /**
- * @memberof ktxTexture1
- * @~English
- * @brief Iterate over the mip levels in a ktxTexture1 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.
- *
- * @param[in] This handle of the 1 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_VALUE @p This is @c NULL or @p iterCb is @c NULL.
- *
- */
- KTX_error_code
- ktxTexture1_IterateLevels(ktxTexture1* 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)
- {
- GLsizei width, height, depth;
- ktx_uint32_t levelSize;
- ktx_size_t offset;
- /* 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);
- levelSize = (ktx_uint32_t)ktxTexture_calcLevelSize(ktxTexture(This),
- miplevel,
- KTX_FORMAT_VERSION_ONE);
- /* All array layers are passed in a group because that is how
- * GL & Vulkan need them. Hence no
- * for (layer = 0; layer < This->numLayers)
- */
- ktxTexture_GetImageOffset(ktxTexture(This), miplevel, 0, 0, &offset);
- result = iterCb(miplevel, 0, width, height, depth,
- levelSize, This->pData + offset, userdata);
- if (result != KTX_SUCCESS)
- break;
- }
- return result;
- }
- /**
- * @memberof ktxTexture1
- * @~English
- * @brief Iterate over the images in a ktxTexture1 object while loading the
- * image data.
- *
- * This operates similarly to ktxTexture_IterateLevelFaces() except that it
- * loads the images from the ktxTexture1's source to a temporary buffer
- * while iterating. 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.
- *
- * @param[in] This pointer to the ktxTexture1 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 ktxTexture1 was not created from a
- * stream, i.e there is no data to load, or
- * this ktxTexture1's images have already
- * been loaded.
- * @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
- ktxTexture1_IterateLoadLevelFaces(ktxTexture1* This, PFNKTXITERCB iterCb,
- void* userdata)
- {
- DECLARE_PRIVATE(ktxTexture1);
- struct ktxTexture_protected* prtctd = This->_protected;
- ktxStream* stream = (ktxStream *)&prtctd->_stream;
- ktx_uint32_t dataSize = 0;
- ktx_uint32_t miplevel;
- KTX_error_code result = KTX_SUCCESS;
- void* data = NULL;
- if (This == NULL)
- return KTX_INVALID_VALUE;
- if (This->classId != ktxTexture1_c)
- return KTX_INVALID_OPERATION;
- if (iterCb == NULL)
- return KTX_INVALID_VALUE;
- if (prtctd->_stream.data.file == NULL)
- // This Texture not created from a stream or images are already loaded.
- return KTX_INVALID_OPERATION;
- for (miplevel = 0; miplevel < This->numLevels; ++miplevel)
- {
- ktx_uint32_t faceLodSize;
- ktx_uint32_t faceLodSizePadded;
- 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);
- result = stream->read(stream, &faceLodSize, sizeof(ktx_uint32_t));
- if (result != KTX_SUCCESS) {
- goto cleanup;
- }
- if (private->_needSwap) {
- _ktxSwapEndian32(&faceLodSize, 1);
- }
- #if (KTX_GL_UNPACK_ALIGNMENT != 4)
- faceLodSizePadded = _KTX_PAD4(faceLodSize);
- #else
- faceLodSizePadded = faceLodSize;
- #endif
- if (!data) {
- /* allocate memory sufficient for the base miplevel */
- data = malloc(faceLodSizePadded);
- if (!data) {
- result = KTX_OUT_OF_MEMORY;
- goto cleanup;
- }
- dataSize = faceLodSizePadded;
- }
- else if (dataSize < faceLodSizePadded) {
- /* subsequent miplevels cannot be larger than the base miplevel */
- result = KTX_FILE_DATA_ERROR;
- goto cleanup;
- }
- /* 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 (z_slice = 0; z_slice < This->depth)
- */
- result = stream->read(stream, data, faceLodSizePadded);
- if (result != KTX_SUCCESS) {
- goto cleanup;
- }
- /* Perform endianness conversion on texture data */
- if (private->_needSwap) {
- if (prtctd->_typeSize == 2)
- _ktxSwapEndian16((ktx_uint16_t*)data, faceLodSize / 2);
- else if (prtctd->_typeSize == 4)
- _ktxSwapEndian32((ktx_uint32_t*)data, faceLodSize / 4);
- }
- result = iterCb(miplevel, face,
- width, height, depth,
- faceLodSize, data, userdata);
- }
- }
- cleanup:
- free(data);
- // No further need for this.
- stream->destruct(stream);
- return result;
- }
- /**
- * @memberof ktxTexture1
- * @~English
- * @brief Load all the image data from the ktxTexture1's source.
- *
- * The data is loaded into the provided buffer or to an internally allocated
- * buffer, if @p pBuffer is @c NULL.
- *
- * @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
- ktxTexture1_LoadImageData(ktxTexture1* This,
- ktx_uint8_t* pBuffer, ktx_size_t bufSize)
- {
- DECLARE_PROTECTED(ktxTexture);
- DECLARE_PRIVATE(ktxTexture1);
- ktx_uint32_t miplevel;
- ktx_uint8_t* pDest;
- KTX_error_code result = KTX_SUCCESS;
- if (This == NULL)
- return KTX_INVALID_VALUE;
- if (prtctd->_stream.data.file == NULL)
- // This Texture not created from a stream or images already loaded;
- return KTX_INVALID_OPERATION;
- if (pBuffer == NULL) {
- This->pData = malloc(This->dataSize);
- if (This->pData == NULL)
- return KTX_OUT_OF_MEMORY;
- pDest = This->pData;
- } else if (bufSize < This->dataSize) {
- return KTX_INVALID_VALUE;
- } else {
- pDest = pBuffer;
- }
- // Need to loop through for correct byte swapping
- for (miplevel = 0; miplevel < This->numLevels; ++miplevel)
- {
- ktx_uint32_t faceLodSize;
- ktx_uint32_t faceLodSizePadded;
- ktx_uint32_t face;
- ktx_uint32_t innerIterations;
- result = prtctd->_stream.read(&prtctd->_stream, &faceLodSize,
- sizeof(ktx_uint32_t));
- if (result != KTX_SUCCESS) {
- goto cleanup;
- }
- if (private->_needSwap) {
- _ktxSwapEndian32(&faceLodSize, 1);
- }
- #if (KTX_GL_UNPACK_ALIGNMENT != 4)
- faceLodSizePadded = _KTX_PAD4(faceLodSize);
- #else
- faceLodSizePadded = faceLodSize;
- #endif
- if (This->isCubemap && !This->isArray)
- innerIterations = This->numFaces;
- else
- innerIterations = 1;
- for (face = 0; face < innerIterations; ++face)
- {
- result = prtctd->_stream.read(&prtctd->_stream, pDest,
- faceLodSizePadded);
- if (result != KTX_SUCCESS) {
- goto cleanup;
- }
- /* Perform endianness conversion on texture data */
- if (private->_needSwap) {
- if (prtctd->_typeSize == 2)
- _ktxSwapEndian16((ktx_uint16_t*)pDest, faceLodSize / 2);
- else if (prtctd->_typeSize == 4)
- _ktxSwapEndian32((ktx_uint32_t*)pDest, faceLodSize / 4);
- }
- pDest += faceLodSizePadded;
- }
- }
- cleanup:
- // No further need for This->
- prtctd->_stream.destruct(&prtctd->_stream);
- return result;
- }
- ktx_bool_t
- ktxTexture1_NeedsTranscoding(ktxTexture1* This)
- {
- UNUSED(This);
- return KTX_FALSE;
- }
- #if !KTX_FEATURE_WRITE
- /*
- * Stubs for writer functions that return a proper error code
- */
- KTX_error_code
- ktxTexture1_SetImageFromMemory(ktxTexture1* This, ktx_uint32_t level,
- ktx_uint32_t layer, ktx_uint32_t faceSlice,
- const ktx_uint8_t* src, ktx_size_t srcSize)
- {
- UNUSED(This);
- UNUSED(level);
- UNUSED(layer);
- UNUSED(faceSlice);
- UNUSED(src);
- UNUSED(srcSize);
- return KTX_INVALID_OPERATION;
- }
- KTX_error_code
- ktxTexture1_SetImageFromStdioStream(ktxTexture1* This, ktx_uint32_t level,
- ktx_uint32_t layer, ktx_uint32_t faceSlice,
- FILE* src, ktx_size_t srcSize)
- {
- UNUSED(This);
- UNUSED(level);
- UNUSED(layer);
- UNUSED(faceSlice);
- UNUSED(src);
- UNUSED(srcSize);
- return KTX_INVALID_OPERATION;
- }
- KTX_error_code
- ktxTexture1_WriteToStdioStream(ktxTexture1* This, FILE* dstsstr)
- {
- UNUSED(This);
- UNUSED(dstsstr);
- return KTX_INVALID_OPERATION;
- }
- KTX_error_code
- ktxTexture1_WriteToNamedFile(ktxTexture1* This, const char* const dstname)
- {
- UNUSED(This);
- UNUSED(dstname);
- return KTX_INVALID_OPERATION;
- }
- KTX_error_code
- ktxTexture1_WriteToMemory(ktxTexture1* This,
- ktx_uint8_t** ppDstBytes, ktx_size_t* pSize)
- {
- UNUSED(This);
- UNUSED(ppDstBytes);
- UNUSED(pSize);
- return KTX_INVALID_OPERATION;
- }
- KTX_error_code
- ktxTexture1_WriteToStream(ktxTexture1* This,
- ktxStream* dststr)
- {
- UNUSED(This);
- UNUSED(dststr);
- return KTX_INVALID_OPERATION;
- }
- #endif
- /*
- * Initialized here at the end to avoid the need for multiple declarations of
- * these functions.
- */
- struct ktxTexture_vtblInt ktxTexture1_vtblInt = {
- (PFNCALCDATASIZELEVELS)ktxTexture1_calcDataSizeLevels,
- (PFNCALCFACELODSIZE)ktxTexture1_calcFaceLodSize,
- (PFNCALCLEVELOFFSET)ktxTexture1_calcLevelOffset
- };
- struct ktxTexture_vtbl ktxTexture1_vtbl = {
- (PFNKTEXDESTROY)ktxTexture1_Destroy,
- (PFNKTEXGETIMAGEOFFSET)ktxTexture1_GetImageOffset,
- (PFNKTEXGETDATASIZEUNCOMPRESSED)ktxTexture1_GetDataSizeUncompressed,
- (PFNKTEXGETIMAGESIZE)ktxTexture1_GetImageSize,
- (PFNKTEXITERATELEVELS)ktxTexture1_IterateLevels,
- (PFNKTEXITERATELOADLEVELFACES)ktxTexture1_IterateLoadLevelFaces,
- (PFNKTEXNEEDSTRANSCODING)ktxTexture1_NeedsTranscoding,
- (PFNKTEXLOADIMAGEDATA)ktxTexture1_LoadImageData,
- (PFNKTEXSETIMAGEFROMMEMORY)ktxTexture1_SetImageFromMemory,
- (PFNKTEXSETIMAGEFROMSTDIOSTREAM)ktxTexture1_SetImageFromStdioStream,
- (PFNKTEXWRITETOSTDIOSTREAM)ktxTexture1_WriteToStdioStream,
- (PFNKTEXWRITETONAMEDFILE)ktxTexture1_WriteToNamedFile,
- (PFNKTEXWRITETOMEMORY)ktxTexture1_WriteToMemory,
- (PFNKTEXWRITETOSTREAM)ktxTexture1_WriteToStream,
- };
- /** @} */
|