Path: blob/master/thirdparty/libktx/lib/checkheader.c
9902 views
/* -*- tab-width: 4; -*- */1/* vi: set sw=2 ts=4 expandtab: */23/* $Id$ */45/*6* Copyright 2010-2020 The Khronos Group Inc.7* SPDX-License-Identifier: Apache-2.08*/910/**11* @internal12* @file13* @~English14*15* @brief Function to verify a KTX file header16*17* @author Mark Callow, HI Corporation18*/1920/*21* Author: Georg Kolling, Imagination Technology with modifications22* by Mark Callow, HI Corporation.23*/24#include <assert.h>25#include <string.h>2627#include "ktx.h"28#include "ktxint.h"29#include "vkformat_enum.h"3031bool isProhibitedFormat(VkFormat format);32bool isValidFormat(VkFormat format);3334/**35* @internal36* @~English37* @brief Check a KTX file header.38*39* As well as checking that the header identifies a KTX file, the function40* sanity checks the values and returns information about the texture in a41* struct KTX_supplementary_info.42*43* @param pHeader pointer to the KTX header to check44* @param pSuppInfo pointer to a KTX_supplementary_info structure in which to45* return information about the texture.46*47* @author Georg Kolling, Imagination Technology48* @author Mark Callow, HI Corporation49*/5051KTX_error_code ktxCheckHeader1_(KTX_header* pHeader,52KTX_supplemental_info* pSuppInfo)53{54ktx_uint8_t identifier_reference[12] = KTX_IDENTIFIER_REF;55ktx_uint32_t max_dim;5657assert(pHeader != NULL && pSuppInfo != NULL);5859/* Compare identifier, is this a KTX file? */60if (memcmp(pHeader->identifier, identifier_reference, 12) != 0)61{62return KTX_UNKNOWN_FILE_FORMAT;63}6465if (pHeader->endianness == KTX_ENDIAN_REF_REV)66{67/* Convert endianness of pHeader fields. */68_ktxSwapEndian32(&pHeader->glType, 12);6970if (pHeader->glTypeSize != 1 &&71pHeader->glTypeSize != 2 &&72pHeader->glTypeSize != 4)73{74/* Only 8-, 16-, and 32-bit types supported so far. */75return KTX_FILE_DATA_ERROR;76}77}78else if (pHeader->endianness != KTX_ENDIAN_REF)79{80return KTX_FILE_DATA_ERROR;81}8283/* Check glType and glFormat */84pSuppInfo->compressed = 0;85if (pHeader->glType == 0 || pHeader->glFormat == 0)86{87if (pHeader->glType + pHeader->glFormat != 0)88{89/* either both or none of glType, glFormat must be zero */90return KTX_FILE_DATA_ERROR;91}92pSuppInfo->compressed = 1;93}9495if (pHeader->glFormat == pHeader->glInternalformat) {96// glInternalFormat is either unsized (which is no longer and should97// never have been supported by libktx) or glFormat is sized.98return KTX_FILE_DATA_ERROR;99}100101/* Check texture dimensions. KTX files can store 8 types of textures:1021D, 2D, 3D, cube, and array variants of these. There is currently103no GL extension for 3D array textures. */104if ((pHeader->pixelWidth == 0) ||105(pHeader->pixelDepth > 0 && pHeader->pixelHeight == 0))106{107/* texture must have width */108/* texture must have height if it has depth */109return KTX_FILE_DATA_ERROR;110}111112113if (pHeader->pixelDepth > 0)114{115if (pHeader->numberOfArrayElements > 0)116{117/* No 3D array textures yet. */118return KTX_UNSUPPORTED_FEATURE;119}120pSuppInfo->textureDimension = 3;121}122else if (pHeader->pixelHeight > 0)123{124pSuppInfo->textureDimension = 2;125}126else127{128pSuppInfo->textureDimension = 1;129}130131if (pHeader->numberOfFaces == 6)132{133if (pSuppInfo->textureDimension != 2)134{135/* cube map needs 2D faces */136return KTX_FILE_DATA_ERROR;137}138}139else if (pHeader->numberOfFaces != 1)140{141/* numberOfFaces must be either 1 or 6 */142return KTX_FILE_DATA_ERROR;143}144145/* Check number of mipmap levels */146if (pHeader->numberOfMipLevels == 0)147{148pSuppInfo->generateMipmaps = 1;149pHeader->numberOfMipLevels = 1;150}151else152{153pSuppInfo->generateMipmaps = 0;154}155156/* This test works for arrays too because height or depth will be 0. */157max_dim = MAX(MAX(pHeader->pixelWidth, pHeader->pixelHeight), pHeader->pixelDepth);158if (max_dim < ((ktx_uint32_t)1 << (pHeader->numberOfMipLevels - 1)))159{160/* Can't have more mip levels than 1 + log2(max(width, height, depth)) */161return KTX_FILE_DATA_ERROR;162}163164return KTX_SUCCESS;165}166167/**168* @internal169* @~English170* @brief Check a KTX2 file header.171*172* As well as checking that the header identifies a KTX 2 file, the function173* sanity checks the values and returns information about the texture in a174* struct KTX_supplementary_info.175*176* @param pHeader pointer to the KTX header to check177* @param pSuppInfo pointer to a KTX_supplementary_info structure in which to178* return information about the texture.179*180* @author Mark Callow, HI Corporation181*/182KTX_error_code ktxCheckHeader2_(KTX_header2* pHeader,183KTX_supplemental_info* pSuppInfo)184{185// supp info is compressed, generateMipmaps and num dimensions. Don't need186// compressed as formatSize gives us that. I think the other 2 aren't needed.187ktx_uint8_t identifier_reference[12] = KTX2_IDENTIFIER_REF;188189assert(pHeader != NULL && pSuppInfo != NULL);190ktx_uint32_t max_dim;191192/* Compare identifier, is this a KTX file? */193if (memcmp(pHeader->identifier, identifier_reference, 12) != 0)194{195return KTX_UNKNOWN_FILE_FORMAT;196}197198/* Check format */199if (isProhibitedFormat(pHeader->vkFormat))200{201return KTX_FILE_DATA_ERROR;202}203if (!isValidFormat(pHeader->vkFormat))204{205return KTX_UNSUPPORTED_FEATURE;206}207if (pHeader->supercompressionScheme == KTX_SS_BASIS_LZ && pHeader->vkFormat != VK_FORMAT_UNDEFINED)208{209return KTX_FILE_DATA_ERROR;210}211212/* Check texture dimensions. KTX files can store 8 types of textures:2131D, 2D, 3D, cube, and array variants of these. There is currently214no extension for 3D array textures in any 3D API. */215if ((pHeader->pixelWidth == 0) ||216(pHeader->pixelDepth > 0 && pHeader->pixelHeight == 0))217{218/* texture must have width */219/* texture must have height if it has depth */220return KTX_FILE_DATA_ERROR;221}222223if (pHeader->pixelDepth > 0)224{225if (pHeader->layerCount > 0)226{227/* No 3D array textures yet. */228return KTX_UNSUPPORTED_FEATURE;229}230pSuppInfo->textureDimension = 3;231}232else if (pHeader->pixelHeight > 0)233{234pSuppInfo->textureDimension = 2;235}236else237{238pSuppInfo->textureDimension = 1;239}240241if (pHeader->faceCount == 6)242{243if (pSuppInfo->textureDimension != 2)244{245/* cube map needs 2D faces */246return KTX_FILE_DATA_ERROR;247}248if (pHeader->pixelDepth != 0)249{250/* cube map cannot have depth */251return KTX_FILE_DATA_ERROR;252}253if (pHeader->pixelWidth != pHeader->pixelHeight)254{255/* cube map needs square faces */256return KTX_FILE_DATA_ERROR;257}258}259else if (pHeader->faceCount != 1)260{261/* numberOfFaces must be either 1 or 6 */262return KTX_FILE_DATA_ERROR;263}264265// Check number of mipmap levels266if (pHeader->levelCount == 0)267{268pSuppInfo->generateMipmaps = 1;269pHeader->levelCount = 1;270}271else272{273pSuppInfo->generateMipmaps = 0;274}275276// Check supercompression277switch (pHeader->supercompressionScheme) {278case KTX_SS_NONE:279case KTX_SS_BASIS_LZ:280case KTX_SS_ZSTD:281case KTX_SS_ZLIB:282break;283default:284// Unsupported supercompression285return KTX_UNSUPPORTED_FEATURE;286}287288// This test works for arrays too because height or depth will be 0.289max_dim = MAX(MAX(pHeader->pixelWidth, pHeader->pixelHeight), pHeader->pixelDepth);290if (max_dim < ((ktx_uint32_t)1 << (pHeader->levelCount - 1)))291{292// Can't have more mip levels than 1 + log2(max(width, height, depth))293return KTX_FILE_DATA_ERROR;294}295296return KTX_SUCCESS;297298}299300301