overte-HifiExperiments/libraries/ktx/src/ktx/KTX.cpp

212 lines
No EOL
6.1 KiB
C++

//
// KTX.cpp
// ktx/src/ktx
//
// Created by Zach Pomerantz on 2/08/2017.
// 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 <algorithm> //min max and more
using namespace ktx;
uint32_t Header::evalPadding(size_t byteSize) {
//auto padding = byteSize % PACKING_SIZE;
// return (uint32_t) (padding ? PACKING_SIZE - padding : 0);
return (uint32_t) (3 - (byteSize + 3) % PACKING_SIZE);// padding ? PACKING_SIZE - padding : 0);
}
const Header::Identifier ktx::Header::IDENTIFIER {{
0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
}};
Header::Header() {
memcpy(identifier, IDENTIFIER.data(), IDENTIFIER_LENGTH);
}
uint32_t Header::evalMaxDimension() const {
return std::max(getPixelWidth(), std::max(getPixelHeight(), getPixelDepth()));
}
uint32_t Header::evalPixelWidth(uint32_t level) const {
return std::max(getPixelWidth() >> level, 1U);
}
uint32_t Header::evalPixelHeight(uint32_t level) const {
return std::max(getPixelHeight() >> level, 1U);
}
uint32_t Header::evalPixelDepth(uint32_t level) const {
return std::max(getPixelDepth() >> level, 1U);
}
size_t Header::evalPixelSize() const {
return glTypeSize; // Really we should generate the size from the FOrmat etc
}
size_t Header::evalRowSize(uint32_t level) const {
auto pixWidth = evalPixelWidth(level);
auto pixSize = evalPixelSize();
auto netSize = pixWidth * pixSize;
auto padding = evalPadding(netSize);
return netSize + padding;
}
size_t Header::evalFaceSize(uint32_t level) const {
auto pixHeight = evalPixelHeight(level);
auto pixDepth = evalPixelDepth(level);
auto rowSize = evalRowSize(level);
return pixDepth * pixHeight * rowSize;
}
size_t Header::evalImageSize(uint32_t level) const {
auto faceSize = evalFaceSize(level);
if (numberOfFaces == NUM_CUBEMAPFACES && numberOfArrayElements == 0) {
return faceSize;
} else {
return (getNumberOfSlices() * numberOfFaces * faceSize);
}
}
KeyValue::KeyValue(const std::string& key, uint32_t valueByteSize, const Byte* value) :
_byteSize((uint32_t) key.size() + 1 + valueByteSize), // keyString size + '\0' ending char + the value size
_key(key),
_value(valueByteSize)
{
if (_value.size() && value) {
memcpy(_value.data(), value, valueByteSize);
}
}
KeyValue::KeyValue(const std::string& key, const std::string& value) :
KeyValue(key, (uint32_t) value.size(), (const Byte*) value.data())
{
}
uint32_t KeyValue::serializedByteSize() const {
return (uint32_t) (sizeof(uint32_t) + _byteSize + Header::evalPadding(_byteSize));
}
uint32_t KeyValue::serializedKeyValuesByteSize(const KeyValues& keyValues) {
uint32_t keyValuesSize = 0;
for (auto& keyval : keyValues) {
keyValuesSize += keyval.serializedByteSize();
}
return (keyValuesSize + Header::evalPadding(keyValuesSize));
}
KTX::KTX() {
}
KTX::~KTX() {
}
void KTX::resetStorage(const StoragePointer& storage) {
_storage = storage;
if (_storage->size() >= sizeof(Header)) {
memcpy(&_header, _storage->data(), sizeof(Header));
}
}
const Header& KTX::getHeader() const {
return _header;
}
size_t KTX::getKeyValueDataSize() const {
return _header.bytesOfKeyValueData;
}
size_t KTX::getTexelsDataSize() const {
if (!_storage) {
return 0;
}
return (_storage->data() + _storage->size()) - getTexelsData();
}
const Byte* KTX::getKeyValueData() const {
if (!_storage) {
return nullptr;
}
return (_storage->data() + sizeof(Header));
}
const Byte* KTX::getTexelsData() const {
if (!_storage) {
return nullptr;
}
return (_storage->data() + sizeof(Header) + getKeyValueDataSize());
}
storage::StoragePointer KTX::getMipFaceTexelsData(uint16_t mip, uint8_t face) const {
storage::StoragePointer result;
if (mip < _images.size()) {
const auto& faces = _images[mip];
if (face < faces._numFaces) {
auto faceOffset = faces._faceBytes[face] - _storage->data();
auto faceSize = faces._faceSize;
result = _storage->createView(faceSize, faceOffset);
}
}
return result;
}
size_t KTXDescriptor::getMipFaceTexelsSize(uint16_t mip, uint8_t face) const {
size_t result { 0 };
if (mip < images.size()) {
const auto& faces = images[mip];
if (face < faces._numFaces) {
result = faces._faceSize;
}
}
return result;
}
size_t KTXDescriptor::getMipFaceTexelsOffset(uint16_t mip, uint8_t face) const {
size_t result { 0 };
if (mip < images.size()) {
const auto& faces = images[mip];
if (face < faces._numFaces) {
result = faces._faceOffsets[face];
}
}
return result;
}
ImageDescriptor Image::toImageDescriptor(const Byte* baseAddress) const {
FaceOffsets offsets;
offsets.resize(_faceBytes.size());
for (size_t face = 0; face < _numFaces; ++face) {
offsets[face] = _faceBytes[face] - baseAddress;
}
// Note, implicit cast of *this to const ImageHeader&
return ImageDescriptor(*this, offsets);
}
Image ImageDescriptor::toImage(const ktx::StoragePointer& storage) const {
FaceBytes faces;
faces.resize(_faceOffsets.size());
for (size_t face = 0; face < _numFaces; ++face) {
faces[face] = storage->data() + _faceOffsets[face];
}
// Note, implicit cast of *this to const ImageHeader&
return Image(*this, faces);
}
KTXDescriptor KTX::toDescriptor() const {
ImageDescriptors newDescriptors;
auto storageStart = _storage ? _storage->data() : nullptr;
for (size_t i = 0; i < _images.size(); ++i) {
newDescriptors.emplace_back(_images[i].toImageDescriptor(storageStart));
}
return { this->_header, this->_keyValues, newDescriptors };
}
KTX::KTX(const StoragePointer& storage, const Header& header, const KeyValues& keyValues, const Images& images)
: _header(header), _storage(storage), _keyValues(keyValues), _images(images) {
}