mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-07 12:12:39 +02:00
Add KTX validation routines
This commit is contained in:
parent
499897e271
commit
077e56a96f
3 changed files with 522 additions and 83 deletions
|
@ -180,105 +180,107 @@ namespace ktx {
|
|||
RGB16F = 0x881B,
|
||||
RGBA16F = 0x881A,
|
||||
|
||||
R32F = 0x822E,
|
||||
RG32F = 0x8230,
|
||||
RGB32F = 0x8815,
|
||||
RGBA32F = 0x8814,
|
||||
R32F = 0x822E,
|
||||
RG32F = 0x8230,
|
||||
RGB32F = 0x8815,
|
||||
RGBA32F = 0x8814,
|
||||
|
||||
R11F_G11F_B10F = 0x8C3A,
|
||||
RGB9_E5 = 0x8C3D,
|
||||
R11F_G11F_B10F = 0x8C3A,
|
||||
RGB9_E5 = 0x8C3D,
|
||||
|
||||
|
||||
R8I = 0x8231,
|
||||
R8UI = 0x8232,
|
||||
R16I = 0x8233,
|
||||
R16UI = 0x8234,
|
||||
R32I = 0x8235,
|
||||
R32UI = 0x8236,
|
||||
RG8I = 0x8237,
|
||||
RG8UI = 0x8238,
|
||||
RG16I = 0x8239,
|
||||
RG16UI = 0x823A,
|
||||
RG32I = 0x823B,
|
||||
RG32UI = 0x823C,
|
||||
R8I = 0x8231,
|
||||
R8UI = 0x8232,
|
||||
R16I = 0x8233,
|
||||
R16UI = 0x8234,
|
||||
R32I = 0x8235,
|
||||
R32UI = 0x8236,
|
||||
RG8I = 0x8237,
|
||||
RG8UI = 0x8238,
|
||||
RG16I = 0x8239,
|
||||
RG16UI = 0x823A,
|
||||
RG32I = 0x823B,
|
||||
RG32UI = 0x823C,
|
||||
|
||||
RGB8I = 0x8D8F,
|
||||
RGB8UI = 0x8D7D,
|
||||
RGB16I = 0x8D89,
|
||||
RGB16UI = 0x8D77,
|
||||
RGB8I = 0x8D8F,
|
||||
RGB8UI = 0x8D7D,
|
||||
RGB16I = 0x8D89,
|
||||
RGB16UI = 0x8D77,
|
||||
|
||||
RGB32I = 0x8D83,
|
||||
RGB32UI = 0x8D71,
|
||||
RGBA8I = 0x8D8E,
|
||||
RGBA8UI = 0x8D7C,
|
||||
RGBA16I = 0x8D88,
|
||||
RGBA16UI = 0x8D76,
|
||||
RGBA32I = 0x8D82,
|
||||
RGB32I = 0x8D83,
|
||||
RGB32UI = 0x8D71,
|
||||
RGBA8I = 0x8D8E,
|
||||
RGBA8UI = 0x8D7C,
|
||||
RGBA16I = 0x8D88,
|
||||
RGBA16UI = 0x8D76,
|
||||
RGBA32I = 0x8D82,
|
||||
|
||||
RGBA32UI = 0x8D70,
|
||||
RGBA32UI = 0x8D70,
|
||||
|
||||
// GL 4.4 Table 8.13
|
||||
DEPTH_COMPONENT16 = 0x81A5,
|
||||
DEPTH_COMPONENT24 = 0x81A6,
|
||||
DEPTH_COMPONENT32 = 0x81A7,
|
||||
DEPTH_COMPONENT16 = 0x81A5,
|
||||
DEPTH_COMPONENT24 = 0x81A6,
|
||||
DEPTH_COMPONENT32 = 0x81A7,
|
||||
|
||||
DEPTH_COMPONENT32F = 0x8CAC,
|
||||
DEPTH24_STENCIL8 = 0x88F0,
|
||||
DEPTH32F_STENCIL8 = 0x8CAD,
|
||||
DEPTH_COMPONENT32F = 0x8CAC,
|
||||
DEPTH24_STENCIL8 = 0x88F0,
|
||||
DEPTH32F_STENCIL8 = 0x8CAD,
|
||||
|
||||
STENCIL_INDEX1 = 0x8D46,
|
||||
STENCIL_INDEX4 = 0x8D47,
|
||||
STENCIL_INDEX8 = 0x8D48,
|
||||
STENCIL_INDEX16 = 0x8D49,
|
||||
STENCIL_INDEX1 = 0x8D46,
|
||||
STENCIL_INDEX4 = 0x8D47,
|
||||
STENCIL_INDEX8 = 0x8D48,
|
||||
STENCIL_INDEX16 = 0x8D49,
|
||||
};
|
||||
|
||||
enum class GLInternalFormat_Compressed : uint32_t {
|
||||
// GL 4.4 Table 8.14
|
||||
COMPRESSED_RED = 0x8225,
|
||||
COMPRESSED_RG = 0x8226,
|
||||
COMPRESSED_RGB = 0x84ED,
|
||||
COMPRESSED_RGBA = 0x84EE,
|
||||
COMPRESSED_RED = 0x8225,
|
||||
COMPRESSED_RG = 0x8226,
|
||||
COMPRESSED_RGB = 0x84ED,
|
||||
COMPRESSED_RGBA = 0x84EE,
|
||||
|
||||
COMPRESSED_SRGB = 0x8C48,
|
||||
COMPRESSED_SRGB_ALPHA = 0x8C49,
|
||||
COMPRESSED_SRGB = 0x8C48,
|
||||
COMPRESSED_SRGB_ALPHA = 0x8C49,
|
||||
|
||||
COMPRESSED_SRGB_S3TC_DXT1_EXT = 0x8C4C,
|
||||
COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT = 0x8C4D,
|
||||
COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT = 0x8C4E,
|
||||
COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT = 0x8C4F,
|
||||
COMPRESSED_ETC1_RGB8_OES = 0x8D64,
|
||||
|
||||
COMPRESSED_RED_RGTC1 = 0x8DBB,
|
||||
COMPRESSED_SIGNED_RED_RGTC1 = 0x8DBC,
|
||||
COMPRESSED_RG_RGTC2 = 0x8DBD,
|
||||
COMPRESSED_SIGNED_RG_RGTC2 = 0x8DBE,
|
||||
COMPRESSED_SRGB_S3TC_DXT1_EXT = 0x8C4C,
|
||||
COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT = 0x8C4D,
|
||||
COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT = 0x8C4E,
|
||||
COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT = 0x8C4F,
|
||||
|
||||
COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C,
|
||||
COMPRESSED_SRGB_ALPHA_BPTC_UNORM = 0x8E8D,
|
||||
COMPRESSED_RGB_BPTC_SIGNED_FLOAT = 0x8E8E,
|
||||
COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F,
|
||||
COMPRESSED_RED_RGTC1 = 0x8DBB,
|
||||
COMPRESSED_SIGNED_RED_RGTC1 = 0x8DBC,
|
||||
COMPRESSED_RG_RGTC2 = 0x8DBD,
|
||||
COMPRESSED_SIGNED_RG_RGTC2 = 0x8DBE,
|
||||
|
||||
COMPRESSED_RGB8_ETC2 = 0x9274,
|
||||
COMPRESSED_SRGB8_ETC2 = 0x9275,
|
||||
COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276,
|
||||
COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277,
|
||||
COMPRESSED_RGBA8_ETC2_EAC = 0x9278,
|
||||
COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279,
|
||||
COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C,
|
||||
COMPRESSED_SRGB_ALPHA_BPTC_UNORM = 0x8E8D,
|
||||
COMPRESSED_RGB_BPTC_SIGNED_FLOAT = 0x8E8E,
|
||||
COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F,
|
||||
|
||||
COMPRESSED_R11_EAC = 0x9270,
|
||||
COMPRESSED_SIGNED_R11_EAC = 0x9271,
|
||||
COMPRESSED_RG11_EAC = 0x9272,
|
||||
COMPRESSED_SIGNED_RG11_EAC = 0x9273,
|
||||
COMPRESSED_RGB8_ETC2 = 0x9274,
|
||||
COMPRESSED_SRGB8_ETC2 = 0x9275,
|
||||
COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276,
|
||||
COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277,
|
||||
COMPRESSED_RGBA8_ETC2_EAC = 0x9278,
|
||||
COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279,
|
||||
|
||||
COMPRESSED_R11_EAC = 0x9270,
|
||||
COMPRESSED_SIGNED_R11_EAC = 0x9271,
|
||||
COMPRESSED_RG11_EAC = 0x9272,
|
||||
COMPRESSED_SIGNED_RG11_EAC = 0x9273,
|
||||
};
|
||||
|
||||
enum class GLBaseInternalFormat : uint32_t {
|
||||
// GL 4.4 Table 8.11
|
||||
DEPTH_COMPONENT = 0x1902,
|
||||
DEPTH_STENCIL = 0x84F9,
|
||||
RED = 0x1903,
|
||||
RG = 0x8227,
|
||||
RGB = 0x1907,
|
||||
RGBA = 0x1908,
|
||||
STENCIL_INDEX = 0x1901,
|
||||
DEPTH_COMPONENT = 0x1902,
|
||||
DEPTH_STENCIL = 0x84F9,
|
||||
RED = 0x1903,
|
||||
RG = 0x8227,
|
||||
RGB = 0x1907,
|
||||
RGBA = 0x1908,
|
||||
STENCIL_INDEX = 0x1901,
|
||||
};
|
||||
|
||||
enum CubeMapFace {
|
||||
|
@ -316,14 +318,14 @@ namespace ktx {
|
|||
Byte identifier[IDENTIFIER_LENGTH];
|
||||
uint32_t endianness { ENDIAN_TEST };
|
||||
|
||||
uint32_t glType;
|
||||
uint32_t glType { static_cast<uint32_t>(GLType::UNSIGNED_BYTE) };
|
||||
uint32_t glTypeSize { 0 };
|
||||
uint32_t glFormat;
|
||||
uint32_t glInternalFormat;
|
||||
uint32_t glBaseInternalFormat;
|
||||
uint32_t glFormat { static_cast<uint32_t>(GLFormat::RGBA) };
|
||||
uint32_t glInternalFormat { static_cast<uint32_t>(GLInternalFormat_Uncompressed::RGBA8) };
|
||||
uint32_t glBaseInternalFormat { static_cast<uint32_t>(GLBaseInternalFormat::RGBA) };
|
||||
|
||||
uint32_t pixelWidth { 1 };
|
||||
uint32_t pixelHeight { 0 };
|
||||
uint32_t pixelHeight { 1 };
|
||||
uint32_t pixelDepth { 0 };
|
||||
uint32_t numberOfArrayElements { 0 };
|
||||
uint32_t numberOfFaces { 1 };
|
||||
|
@ -386,8 +388,12 @@ namespace ktx {
|
|||
void setCube(uint32_t width, uint32_t height) { setDimensions(width, height, 0, 0, NUM_CUBEMAPFACES); }
|
||||
void setCubeArray(uint32_t width, uint32_t height, uint32_t numSlices) { setDimensions(width, height, 0, (numSlices > 0 ? numSlices : 1), NUM_CUBEMAPFACES); }
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
// Generate a set of image descriptors based on the assumption that the full mip pyramid is populated
|
||||
ImageDescriptors generateImageDescriptors() const;
|
||||
};
|
||||
|
||||
static const size_t KTX_HEADER_SIZE = 64;
|
||||
static_assert(sizeof(Header) == KTX_HEADER_SIZE, "KTX Header size is static and should not change from the spec");
|
||||
static const size_t KV_SIZE_WIDTH = 4; // Number of bytes for keyAndValueByteSize
|
||||
|
@ -426,6 +432,7 @@ namespace ktx {
|
|||
const uint32_t _imageSize;
|
||||
const uint32_t _faceSize;
|
||||
const uint32_t _padding;
|
||||
|
||||
ImageHeader(bool cube, size_t imageOffset, uint32_t imageSize, uint32_t padding) :
|
||||
_numFaces(cube ? NUM_CUBEMAPFACES : 1),
|
||||
_imageOffset(imageOffset),
|
||||
|
@ -486,6 +493,8 @@ namespace ktx {
|
|||
public:
|
||||
~KTX();
|
||||
|
||||
static bool validate(const StoragePointer& src);
|
||||
|
||||
// Define a KTX object manually to write it somewhere (in a file on disk?)
|
||||
// This path allocate the Storage where to store header, keyvalues and copy mips
|
||||
// Then COPY all the data
|
||||
|
|
376
libraries/ktx/src/ktx/Validation.cpp
Normal file
376
libraries/ktx/src/ktx/Validation.cpp
Normal file
|
@ -0,0 +1,376 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2017/05/13
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "KTX.h"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace ktx;
|
||||
|
||||
static const std::unordered_set<uint32_t> VALID_GL_TYPES {
|
||||
(uint32_t)GLType::UNSIGNED_BYTE,
|
||||
(uint32_t)GLType::BYTE,
|
||||
(uint32_t)GLType::UNSIGNED_SHORT,
|
||||
(uint32_t)GLType::SHORT,
|
||||
(uint32_t)GLType::UNSIGNED_INT,
|
||||
(uint32_t)GLType::INT,
|
||||
(uint32_t)GLType::HALF_FLOAT,
|
||||
(uint32_t)GLType::FLOAT,
|
||||
(uint32_t)GLType::UNSIGNED_BYTE_3_3_2,
|
||||
(uint32_t)GLType::UNSIGNED_BYTE_2_3_3_REV,
|
||||
(uint32_t)GLType::UNSIGNED_SHORT_5_6_5,
|
||||
(uint32_t)GLType::UNSIGNED_SHORT_5_6_5_REV,
|
||||
(uint32_t)GLType::UNSIGNED_SHORT_4_4_4_4,
|
||||
(uint32_t)GLType::UNSIGNED_SHORT_4_4_4_4_REV,
|
||||
(uint32_t)GLType::UNSIGNED_SHORT_5_5_5_1,
|
||||
(uint32_t)GLType::UNSIGNED_SHORT_1_5_5_5_REV,
|
||||
(uint32_t)GLType::UNSIGNED_INT_8_8_8_8,
|
||||
(uint32_t)GLType::UNSIGNED_INT_8_8_8_8_REV,
|
||||
(uint32_t)GLType::UNSIGNED_INT_10_10_10_2,
|
||||
(uint32_t)GLType::UNSIGNED_INT_2_10_10_10_REV,
|
||||
(uint32_t)GLType::UNSIGNED_INT_24_8,
|
||||
(uint32_t)GLType::UNSIGNED_INT_10F_11F_11F_REV,
|
||||
(uint32_t)GLType::UNSIGNED_INT_5_9_9_9_REV,
|
||||
(uint32_t)GLType::FLOAT_32_UNSIGNED_INT_24_8_REV,
|
||||
};
|
||||
|
||||
static const std::unordered_set<uint32_t> VALID_GL_FORMATS {
|
||||
(uint32_t)GLFormat::STENCIL_INDEX,
|
||||
(uint32_t)GLFormat::DEPTH_COMPONENT,
|
||||
(uint32_t)GLFormat::DEPTH_STENCIL,
|
||||
(uint32_t)GLFormat::RED,
|
||||
(uint32_t)GLFormat::GREEN,
|
||||
(uint32_t)GLFormat::BLUE,
|
||||
(uint32_t)GLFormat::RG,
|
||||
(uint32_t)GLFormat::RGB,
|
||||
(uint32_t)GLFormat::RGBA,
|
||||
(uint32_t)GLFormat::BGR,
|
||||
(uint32_t)GLFormat::BGRA,
|
||||
(uint32_t)GLFormat::RG_INTEGER,
|
||||
(uint32_t)GLFormat::RED_INTEGER,
|
||||
(uint32_t)GLFormat::GREEN_INTEGER,
|
||||
(uint32_t)GLFormat::BLUE_INTEGER,
|
||||
(uint32_t)GLFormat::RGB_INTEGER,
|
||||
(uint32_t)GLFormat::RGBA_INTEGER,
|
||||
(uint32_t)GLFormat::BGR_INTEGER,
|
||||
(uint32_t)GLFormat::BGRA_INTEGER,
|
||||
};
|
||||
|
||||
static const std::unordered_set<uint32_t> VALID_GL_INTERNAL_FORMATS {
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R8,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R8_SNORM,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R16,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R16_SNORM,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG8,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG8_SNORM,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG16,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG16_SNORM,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R3_G3_B2,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB4,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB5,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB565,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB8,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB8_SNORM,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB10,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB12,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB16,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB16_SNORM,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA2,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA4,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB5_A1,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA8,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA8_SNORM,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB10_A2,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB10_A2UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA12,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA16,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA16_SNORM,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::SRGB8,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::SRGB8_ALPHA8,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R16F,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG16F,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB16F,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA16F,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R32F,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG32F,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA32F,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R11F_G11F_B10F,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB9_E5,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R8I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R8UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R16I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R16UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R32I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::R32UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG8I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG8UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG16I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG16UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG32I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RG32UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB8I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB8UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB16I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB16UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB32I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGB32UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA8I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA8UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA16I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA16UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA32I,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::RGBA32UI,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT16,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT24,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT32,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT32F,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::DEPTH24_STENCIL8,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::DEPTH32F_STENCIL8,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX1,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX4,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX8,
|
||||
(uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX16,
|
||||
};
|
||||
|
||||
static const std::unordered_set<uint32_t> VALID_GL_INTERNAL_COMPRESSED_FORMATS {
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RED,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RG,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGBA,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_ETC1_RGB8_OES,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_S3TC_DXT1_EXT,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RED_RGTC1,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_RED_RGTC1,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RG_RGTC2,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_RG_RGTC2,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGBA_BPTC_UNORM,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB_BPTC_SIGNED_FLOAT,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB8_ETC2,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB8_ETC2,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGBA8_ETC2_EAC,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_R11_EAC,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_R11_EAC,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_RG11_EAC,
|
||||
(uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_RG11_EAC,
|
||||
};
|
||||
|
||||
static const std::unordered_set<uint32_t> VALID_GL_BASE_INTERNAL_FORMATS {
|
||||
(uint32_t)GLBaseInternalFormat::DEPTH_COMPONENT,
|
||||
(uint32_t)GLBaseInternalFormat::DEPTH_STENCIL,
|
||||
(uint32_t)GLBaseInternalFormat::RED,
|
||||
(uint32_t)GLBaseInternalFormat::RG,
|
||||
(uint32_t)GLBaseInternalFormat::RGB,
|
||||
(uint32_t)GLBaseInternalFormat::RGBA,
|
||||
(uint32_t)GLBaseInternalFormat::STENCIL_INDEX,
|
||||
};
|
||||
|
||||
bool Header::isValid() const {
|
||||
if (0 != memcmp(identifier, IDENTIFIER.data(), IDENTIFIER_LENGTH)) {
|
||||
qDebug() << "Invalid header identifier";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (endianness != ENDIAN_TEST && endianness != REVERSE_ENDIAN_TEST) {
|
||||
qDebug("Invalid endian marker 0x%x", endianness);
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// GL enum validity
|
||||
//
|
||||
if (VALID_GL_BASE_INTERNAL_FORMATS.count(glBaseInternalFormat) != 1) {
|
||||
qDebug("Invalid base internal format 0x%x", glBaseInternalFormat);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (glFormat == (uint32_t)GLFormat::COMPRESSED_FORMAT && glType == (uint32_t)GLType::COMPRESSED_TYPE) {
|
||||
if (VALID_GL_INTERNAL_COMPRESSED_FORMATS.count(glInternalFormat) != 1) {
|
||||
qDebug("Invalid compressed internal format 0x%x", glInternalFormat);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (VALID_GL_TYPES.count(glType) != 1) {
|
||||
qDebug("Invalid type 0x%x", glType);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (VALID_GL_FORMATS.count(glFormat) != 1) {
|
||||
qDebug("Invalid format 0x%x", glFormat);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (VALID_GL_INTERNAL_FORMATS.count(glInternalFormat) != 1) {
|
||||
qDebug("Invalid internal format 0x%x", glInternalFormat);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Dimensions validity
|
||||
//
|
||||
|
||||
// Textures must at least have a width
|
||||
// If they have a depth, they must have a height
|
||||
if ((pixelWidth == 0) || (pixelDepth != 0 && pixelHeight == 0)) {
|
||||
qDebug() << "Invalid dimensions " << pixelWidth << "x" << pixelHeight << "x" << pixelDepth;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (numberOfFaces != 1 && numberOfFaces != NUM_CUBEMAPFACES) {
|
||||
qDebug() << "Invalid number of faces " << numberOfFaces;
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME validate numberOfMipmapLevels based on the dimensions?
|
||||
|
||||
if ((bytesOfKeyValueData % 4) != 0) {
|
||||
qDebug() << "Invalid keyvalue data size " << numberOfFaces;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct AlignedStreamBuffer {
|
||||
AlignedStreamBuffer(size_t size, const uint8_t* data)
|
||||
: _size(size), _data(data) { }
|
||||
|
||||
AlignedStreamBuffer(const StoragePointer& storage)
|
||||
: AlignedStreamBuffer(storage->size(), storage->data()) { }
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool read(T& t) {
|
||||
// Ensure we don't read more than we have
|
||||
if (sizeof(T) > _size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab the data
|
||||
memcpy(&t, _data, sizeof(T));
|
||||
|
||||
// Advance the pointer
|
||||
return skip(sizeof(T));
|
||||
}
|
||||
|
||||
bool skip(size_t skipSize) {
|
||||
if ((skipSize % 4) != 0) {
|
||||
skipSize += (3 - ((skipSize + 3) % 4));
|
||||
}
|
||||
if (skipSize > _size) {
|
||||
return false;
|
||||
}
|
||||
_data += skipSize;
|
||||
_size -= skipSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
AlignedStreamBuffer front(size_t size) const {
|
||||
return AlignedStreamBuffer { std::min(size, _size), _data };
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return _size == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t _size;
|
||||
const uint8_t* _data;
|
||||
};
|
||||
|
||||
bool validateKeyValueData(AlignedStreamBuffer kvbuffer) {
|
||||
while (!kvbuffer.empty()) {
|
||||
uint32_t keyValueSize;
|
||||
// Try to fetch the size of the next key value block
|
||||
if (!kvbuffer.read(keyValueSize)) {
|
||||
qDebug() << "Unable to read past key value size";
|
||||
return false;
|
||||
}
|
||||
if (!kvbuffer.skip(keyValueSize)) {
|
||||
qDebug() << "Unable to skip past key value data";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KTX::validate(const StoragePointer& src) {
|
||||
if ((src->size() % 4) != 0) {
|
||||
// All KTX data is 4-byte aligned
|
||||
qDebug() << "Invalid size, not 4 byte aligned";
|
||||
return false;
|
||||
}
|
||||
|
||||
Header header;
|
||||
AlignedStreamBuffer buffer { src };
|
||||
if (!buffer.read(header)) {
|
||||
qDebug() << "Unable to read header";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Basic header validation, are the enums and size valid?
|
||||
if (!header.isValid()) {
|
||||
qDebug() << "Invalid header";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate the key value pairs
|
||||
if (!validateKeyValueData(buffer.front(header.bytesOfKeyValueData))) {
|
||||
qDebug() << "Invalid key value data";
|
||||
return false;
|
||||
}
|
||||
|
||||
// now skip the KV data
|
||||
if (!buffer.skip(header.bytesOfKeyValueData)) {
|
||||
qDebug() << "Unable to read past key value data";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Validate the images
|
||||
for (uint32_t mip = 0; mip < header.numberOfMipmapLevels; ++mip) {
|
||||
uint32_t imageSize;
|
||||
if (!buffer.read(imageSize)) {
|
||||
qDebug() << "Unable to read image size";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header.numberOfArrayElements == 0 && header.numberOfFaces == 6) {
|
||||
for (uint8_t face = 0; face < NUM_CUBEMAPFACES; ++face) {
|
||||
if (!buffer.skip(imageSize)) {
|
||||
qDebug() << "Unable to skip past cubemap data";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!buffer.skip(imageSize)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The buffer should be empty afer we've skipped all of the KTX data
|
||||
if (!buffer.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -38,14 +38,12 @@
|
|||
#include <StatTracker.h>
|
||||
#include <LogHandler.h>
|
||||
|
||||
|
||||
#include <gpu/Texture.h>
|
||||
#include <gl/Config.h>
|
||||
#include <model/TextureMap.h>
|
||||
#include <ktx/KTX.h>
|
||||
#include <image/Image.h>
|
||||
|
||||
|
||||
QSharedPointer<FileLogger> logger;
|
||||
|
||||
gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bool write = true, bool read = true);
|
||||
|
@ -59,7 +57,9 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt
|
|||
OutputDebugStringA(logMessage.toLocal8Bit().constData());
|
||||
OutputDebugStringA("\n");
|
||||
#endif
|
||||
logger->addMessage(qPrintable(logMessage + "\n"));
|
||||
if (logger) {
|
||||
logger->addMessage(qPrintable(logMessage + "\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,5 +149,59 @@ int main(int argc, char** argv) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const QString TEST_FOLDER { "H:/ktx_cacheold" };
|
||||
//static const QString TEST_FOLDER { "C:/Users/bdavis/Git/KTX/testimages" };
|
||||
|
||||
//static const QString EXTENSIONS { "4bbdf8f786470e4ab3e672d44b8e8df2.ktx" };
|
||||
static const QString EXTENSIONS { "*.ktx" };
|
||||
|
||||
int mainTemp(int, char**) {
|
||||
qInstallMessageHandler(messageHandler);
|
||||
auto fileInfoList = QDir { TEST_FOLDER }.entryInfoList(QStringList { EXTENSIONS });
|
||||
for (auto fileInfo : fileInfoList) {
|
||||
qDebug() << fileInfo.filePath();
|
||||
std::shared_ptr<storage::Storage> storage { new storage::FileStorage { fileInfo.filePath() } };
|
||||
|
||||
if (!ktx::KTX::validate(storage)) {
|
||||
qDebug() << "KTX invalid";
|
||||
}
|
||||
|
||||
auto ktxFile = ktx::KTX::create(storage);
|
||||
ktx::KTXDescriptor ktxDescriptor = ktxFile->toDescriptor();
|
||||
assert(ktxFile->_keyValues == ktxDescriptor.keyValues);
|
||||
|
||||
qDebug() << "Contains " << ktxDescriptor.keyValues.size() << " key value pairs";
|
||||
for (const auto& kv : ktxDescriptor.keyValues) {
|
||||
qDebug() << "\t" << kv._key.c_str();
|
||||
}
|
||||
|
||||
auto offsetToMinMipKV = ktxDescriptor.getValueOffsetForKey(ktx::HIFI_MIN_POPULATED_MIP_KEY);
|
||||
if (offsetToMinMipKV) {
|
||||
auto data = storage->data() + ktx::KTX_HEADER_SIZE + offsetToMinMipKV;
|
||||
auto minMipLevelAvailable = *data;
|
||||
qDebug() << "\tMin mip available " << minMipLevelAvailable;
|
||||
assert(minMipLevelAvailable < ktxDescriptor.header.numberOfMipmapLevels);
|
||||
}
|
||||
auto storageSize = storage->size();
|
||||
for (const auto& faceImageDesc : ktxDescriptor.images) {
|
||||
//assert(0 == (faceImageDesc._faceSize % 4));
|
||||
for (const auto& faceOffset : faceImageDesc._faceOffsets) {
|
||||
assert(0 == (faceOffset % 4));
|
||||
auto faceEndOffset = faceOffset + faceImageDesc._faceSize;
|
||||
assert(faceEndOffset <= storageSize);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& faceImage : ktxFile->_images) {
|
||||
for (const ktx::Byte* faceBytes : faceImage._faceBytes) {
|
||||
assert(0 == (reinterpret_cast<size_t>(faceBytes) % 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "main.moc"
|
||||
|
||||
|
|
Loading…
Reference in a new issue