12 #ifndef hifi_ktx_KTX_h
13 #define hifi_ktx_KTX_h
23 #include <shared/Storage.h>
25 #include "../khronos/KHR.h"
83 static const uint32_t ALIGNMENT {
sizeof(uint32_t) };
84 static const uint32_t ALIGNMENT_REMAINDER { ALIGNMENT - 1 };
85 static const uint32_t NUM_CUBEMAPFACES = khronos::gl::texture::cubemap::NUM_CUBEMAPFACES;
88 const std::string HIFI_MIN_POPULATED_MIP_KEY {
"hifi.minMip" };
93 using GLType = khronos::gl::Type;
94 using GLFormat = khronos::gl::texture::Format;
95 using GLInternalFormat = khronos::gl::texture::InternalFormat;
96 using GLBaseInternalFormat = khronos::gl::texture::BaseInternalFormat;
98 using Storage = storage::Storage;
99 using StoragePointer = std::shared_ptr<const Storage>;
101 struct ImageDescriptor;
102 using ImageDescriptors = std::vector<ImageDescriptor>;
104 bool checkIdentifier(
const Byte* identifier);
107 template <
typename T>
108 inline uint8_t evalPadding(T value) {
109 return ALIGNMENT_REMAINDER - ((value + ALIGNMENT_REMAINDER) % ALIGNMENT);
113 template <
typename T>
114 inline T evalPaddedSize(T value) {
115 return (value + ALIGNMENT_REMAINDER) & ~(T)ALIGNMENT_REMAINDER;
118 template <
typename T>
119 inline T evalAlignedCount(T value) {
120 return (value + ALIGNMENT_REMAINDER) / ALIGNMENT;
123 template <
typename T>
124 inline bool checkAlignment(T value) {
125 return ((value & ALIGNMENT_REMAINDER) == 0);
131 static const uint32_t COMPRESSED_FORMAT { 0 };
132 static const uint32_t COMPRESSED_TYPE { 0 };
133 static const uint32_t COMPRESSED_TYPE_SIZE { 1 };
134 static const size_t IDENTIFIER_LENGTH { 12 };
135 using Identifier = std::array<uint8_t, IDENTIFIER_LENGTH>;
136 static const Identifier IDENTIFIER;
138 static const uint32_t ENDIAN_TEST = 0x04030201;
139 static const uint32_t REVERSE_ENDIAN_TEST = 0x01020304;
143 Byte identifier[IDENTIFIER_LENGTH];
144 uint32_t endianness { ENDIAN_TEST };
146 uint32_t glType {
static_cast<uint32_t
>(GLType::UNSIGNED_BYTE) };
147 uint32_t glTypeSize { 0 };
148 uint32_t glFormat {
static_cast<uint32_t
>(GLFormat::RGBA) };
149 uint32_t glInternalFormat {
static_cast<uint32_t
>(GLInternalFormat::RGBA8) };
150 uint32_t glBaseInternalFormat {
static_cast<uint32_t
>(GLBaseInternalFormat::RGBA) };
152 uint32_t pixelWidth { 1 };
153 uint32_t pixelHeight { 1 };
154 uint32_t pixelDepth { 0 };
155 uint32_t numberOfArrayElements { 0 };
156 uint32_t numberOfFaces { 1 };
157 uint32_t numberOfMipmapLevels { 1 };
159 uint32_t bytesOfKeyValueData { 0 };
161 uint32_t getPixelWidth()
const {
return (pixelWidth ? pixelWidth : 1); }
162 uint32_t getPixelHeight()
const {
return (pixelHeight ? pixelHeight : 1); }
163 uint32_t getPixelDepth()
const {
return (pixelDepth ? pixelDepth : 1); }
164 uint32_t getNumberOfSlices()
const {
return (numberOfArrayElements ? numberOfArrayElements : 1); }
165 uint32_t getNumberOfLevels()
const {
return (numberOfMipmapLevels ? numberOfMipmapLevels : 1); }
166 bool isArray()
const {
return numberOfArrayElements > 0; }
167 bool isCompressed()
const {
return glFormat == COMPRESSED_FORMAT; }
169 uint32_t evalMaxDimension()
const;
170 uint32_t evalPixelOrBlockWidth(uint32_t level)
const;
171 uint32_t evalPixelOrBlockHeight(uint32_t level)
const;
172 uint32_t evalPixelOrBlockDepth(uint32_t level)
const;
174 size_t evalPixelOrBlockBitSize()
const;
175 size_t evalRowSize(uint32_t level)
const;
176 size_t evalFaceSize(uint32_t level)
const;
177 size_t evalImageSize(uint32_t level)
const;
181 void setUncompressed(GLType type, uint32_t typeSize, GLFormat format, GLInternalFormat internalFormat, GLBaseInternalFormat baseInternalFormat) {
182 glType = (uint32_t) type;
183 glTypeSize = typeSize;
184 glFormat = (uint32_t) format;
185 glInternalFormat = (uint32_t) internalFormat;
186 glBaseInternalFormat = (uint32_t) baseInternalFormat;
190 void setCompressed(GLInternalFormat internalFormat, GLBaseInternalFormat baseInternalFormat) {
191 glType = COMPRESSED_TYPE;
192 glFormat = COMPRESSED_FORMAT;
193 glTypeSize = COMPRESSED_TYPE_SIZE;
194 glInternalFormat = (uint32_t) internalFormat;
195 glBaseInternalFormat = (uint32_t) baseInternalFormat;
198 GLType getGLType()
const {
return (GLType)glType; }
199 uint32_t getTypeSize()
const {
return glTypeSize; }
200 GLFormat getGLFormat()
const {
return (GLFormat)glFormat; }
201 GLInternalFormat getGLInternaFormat()
const {
return (GLInternalFormat)glInternalFormat; }
202 GLBaseInternalFormat getGLBaseInternalFormat()
const {
return (GLBaseInternalFormat)glBaseInternalFormat; }
204 void set1D(uint32_t width) { setDimensions(width); }
205 void set1DArray(uint32_t width, uint32_t numSlices) { setDimensions(width, 0, 0, (numSlices > 0 ? numSlices : 1)); }
206 void set2D(uint32_t width, uint32_t height) { setDimensions(width, height); }
207 void set2DArray(uint32_t width, uint32_t height, uint32_t numSlices) { setDimensions(width, height, 0, (numSlices > 0 ? numSlices : 1)); }
208 void set3D(uint32_t width, uint32_t height, uint32_t depth) { setDimensions(width, height, depth); }
209 void set3DArray(uint32_t width, uint32_t height, uint32_t depth, uint32_t numSlices) { setDimensions(width, height, depth, (numSlices > 0 ? numSlices : 1)); }
210 void setCube(uint32_t width, uint32_t height) { setDimensions(width, height, 0, 0, NUM_CUBEMAPFACES); }
211 void setCubeArray(uint32_t width, uint32_t height, uint32_t numSlices) { setDimensions(width, height, 0, (numSlices > 0 ? numSlices : 1), NUM_CUBEMAPFACES); }
213 bool isValid()
const;
216 ImageDescriptors generateImageDescriptors()
const;
219 uint32_t evalPixelOrBlockDimension(uint32_t pixelDimension)
const;
220 uint32_t evalMipPixelOrBlockDimension(uint32_t level, uint32_t pixelDimension)
const;
222 static inline uint32_t evalMipDimension(uint32_t mipLevel, uint32_t pixelDimension) {
223 return std::max(pixelDimension >> mipLevel, 1U);
226 void setDimensions(uint32_t width, uint32_t height = 0, uint32_t depth = 0, uint32_t numSlices = 0, uint32_t numFaces = 1) {
227 pixelWidth = (width > 0 ? width : 1);
228 pixelHeight = height;
230 numberOfArrayElements = numSlices;
231 numberOfFaces = numFaces;
236 static const size_t KTX_HEADER_SIZE { 64 };
237 static_assert(
sizeof(Header) == KTX_HEADER_SIZE,
"KTX Header size is static and should not change from the spec");
238 static const size_t KV_SIZE_WIDTH { ALIGNMENT };
239 static const size_t IMAGE_SIZE_WIDTH { ALIGNMENT };
243 uint32_t _byteSize { 0 };
245 std::vector<Byte> _value;
248 KeyValue(
const std::string& key, uint32_t valueByteSize,
const Byte* value);
250 KeyValue(
const std::string& key,
const std::string& value);
252 uint32_t serializedByteSize()
const;
254 static KeyValue parseSerializedKeyAndValue(uint32_t srcSize,
const Byte* srcBytes);
255 static uint32_t writeSerializedKeyAndValue(Byte* destBytes, uint32_t destByteSize,
const KeyValue& keyval);
257 using KeyValues = std::list<KeyValue>;
258 static uint32_t serializedKeyValuesByteSize(
const KeyValues& keyValues);
261 using KeyValues = KeyValue::KeyValues;
264 using FaceOffsets = std::vector<size_t>;
265 using FaceBytes = std::vector<const Byte*>;
267 const uint32_t _numFaces;
270 const size_t _imageOffset;
271 const uint32_t _imageSize;
272 const uint32_t _faceSize;
273 const uint32_t _padding;
275 ImageHeader(
bool cube,
size_t imageOffset, uint32_t imageSize, uint32_t padding) :
276 _numFaces(cube ? NUM_CUBEMAPFACES : 1),
277 _imageOffset(imageOffset),
278 _imageSize(imageSize * _numFaces),
279 _faceSize(imageSize),
287 struct ImageDescriptor :
public ImageHeader {
288 const FaceOffsets _faceOffsets;
289 ImageDescriptor(
const ImageHeader& header,
const FaceOffsets& offsets) : ImageHeader(header), _faceOffsets(offsets) {}
290 Image toImage(
const ktx::StoragePointer& storage)
const;
294 struct Image :
public ImageHeader {
295 FaceBytes _faceBytes;
296 Image(
const ImageHeader& header,
const FaceBytes& faces) : ImageHeader(header), _faceBytes(faces) {}
297 Image(
size_t imageOffset, uint32_t imageSize, uint32_t padding,
const Byte* bytes) :
298 ImageHeader(false, imageOffset, imageSize, padding),
299 _faceBytes(1, bytes) {}
300 Image(
size_t imageOffset, uint32_t pageSize, uint32_t padding,
const FaceBytes& cubeFaceBytes) :
301 ImageHeader(true, imageOffset, pageSize, padding)
303 if (cubeFaceBytes.size() == NUM_CUBEMAPFACES) {
304 _faceBytes = cubeFaceBytes;
308 ImageDescriptor toImageDescriptor(
const Byte* baseAddress)
const;
311 using Images = std::vector<Image>;
317 struct KTXDescriptor {
318 KTXDescriptor(
const Header& header,
const KeyValues& keyValues,
const ImageDescriptors& imageDescriptors) : header(header), keyValues(keyValues), images(imageDescriptors) {}
320 const KeyValues keyValues;
321 const ImageDescriptors images;
322 size_t getMipFaceTexelsSize(uint16_t mip = 0, uint8_t face = 0)
const;
323 size_t getMipFaceTexelsOffset(uint16_t mip = 0, uint8_t face = 0)
const;
324 size_t getValueOffsetForKey(
const std::string& key)
const;
328 void resetStorage(
const StoragePointer& src);
331 KTX(
const StoragePointer& storage,
const Header& header,
const KeyValues& keyValues,
const Images& images);
333 static bool validate(
const StoragePointer& src);
338 static std::unique_ptr<KTX> create(
const Header& header,
const Images& images,
const KeyValues& keyValues = KeyValues());
339 static std::unique_ptr<KTX> createBare(
const Header& header,
const KeyValues& keyValues = KeyValues());
352 static size_t evalStorageSize(
const Header& header,
const Images& images,
const KeyValues& keyValues = KeyValues());
353 static size_t evalStorageSize(
const Header& header,
const ImageDescriptors& images,
const KeyValues& keyValues = KeyValues());
354 static size_t write(Byte* destBytes,
size_t destByteSize,
const Header& header,
const Images& images,
const KeyValues& keyValues = KeyValues());
355 static size_t writeWithoutImages(Byte* destBytes,
size_t destByteSize,
const Header& header,
const ImageDescriptors& descriptors,
const KeyValues& keyValues = KeyValues());
356 static size_t writeKeyValues(Byte* destBytes,
size_t destByteSize,
const KeyValues& keyValues);
357 static Images writeImages(Byte* destBytes,
size_t destByteSize,
const Images& images);
359 void writeMipData(uint16_t level,
const Byte* sourceBytes,
size_t source_size);
362 static std::unique_ptr<KTX> create(
const StoragePointer& src);
364 static bool checkHeaderFromStorage(
size_t srcSize,
const Byte* srcBytes);
365 static KeyValues parseKeyValues(
size_t srcSize,
const Byte* srcBytes);
366 static Images parseImages(
const Header& header,
size_t srcSize,
const Byte* srcBytes);
369 const Header& getHeader()
const;
371 const Byte* getKeyValueData()
const;
372 const Byte* getTexelsData()
const;
373 storage::StoragePointer getMipFaceTexelsData(uint16_t mip = 0, uint8_t face = 0)
const;
374 const StoragePointer& getStorage()
const {
return _storage; }
376 KTXDescriptor toDescriptor()
const;
377 size_t getKeyValueDataSize()
const;
378 size_t getTexelsDataSize()
const;
379 bool isValid()
const;
382 StoragePointer _storage;
383 KeyValues _keyValues;
386 friend struct KTXDescriptor;
391 Q_DECLARE_METATYPE(ktx::KTXDescriptor*);