mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 07:12:40 +02:00
Starting to work on the writer side
This commit is contained in:
parent
4ac87c6851
commit
7343c2f90b
4 changed files with 84 additions and 37 deletions
|
@ -15,6 +15,11 @@
|
|||
|
||||
using namespace ktx;
|
||||
|
||||
uint32_t evalPadding(size_t byteSize) {
|
||||
auto padding = byteSize % PACKING_SIZE;
|
||||
return (padding ? PACKING_SIZE - padding : 0);
|
||||
}
|
||||
|
||||
const Header::Identifier ktx::Header::IDENTIFIER {{
|
||||
0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
|
||||
}};
|
||||
|
@ -49,8 +54,8 @@ size_t Header::evalRowSize(uint32_t level) const {
|
|||
auto pixelWidth = evalPixelWidth(level);
|
||||
auto pixSize = evalPixelSize();
|
||||
auto netSize = pixelWidth * pixSize;
|
||||
auto packing = netSize % PACKING_SIZE;
|
||||
return netSize + (packing ? PACKING_SIZE - packing : 0);
|
||||
auto padding = evalPadding(netSize);
|
||||
return netSize + padding;
|
||||
}
|
||||
size_t Header::evalFaceSize(uint32_t level) const {
|
||||
auto pixelHeight = evalPixelHeight(level);
|
||||
|
@ -115,3 +120,4 @@ const Byte* KTX::getTexelsData() const {
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ end
|
|||
|
||||
namespace ktx {
|
||||
const uint32_t PACKING_SIZE { sizeof(uint32_t) };
|
||||
using Byte = uint8_t;
|
||||
uint32_t evalPadding(size_t byteSize);
|
||||
|
||||
enum GLType : uint32_t {
|
||||
COMPRESSED_TYPE = 0,
|
||||
|
@ -289,7 +291,6 @@ namespace ktx {
|
|||
NUM_CUBEMAPFACES = 6,
|
||||
};
|
||||
|
||||
using Byte = uint8_t;
|
||||
|
||||
// Chunk of data
|
||||
struct Storage {
|
||||
|
@ -375,31 +376,37 @@ namespace ktx {
|
|||
using KeyValues = std::list<KeyValue>;
|
||||
|
||||
|
||||
struct Mip {
|
||||
struct Image {
|
||||
uint32_t _imageSize;
|
||||
uint32_t _padding;
|
||||
const Byte* _bytes;
|
||||
|
||||
Mip(uint32_t imageSize, uint32_t padding, const Byte* bytes) :
|
||||
Image(uint32_t imageSize, uint32_t padding, const Byte* bytes) :
|
||||
_imageSize(imageSize),
|
||||
_padding(padding),
|
||||
_bytes(bytes) {}
|
||||
};
|
||||
using Mips = std::vector<Mip>;
|
||||
using Images = std::vector<Image>;
|
||||
|
||||
|
||||
class KTX {
|
||||
void resetStorage(Storage* src);
|
||||
|
||||
KTX();
|
||||
public:
|
||||
|
||||
KTX();
|
||||
~KTX();
|
||||
|
||||
// parse a block of memory and create a KTX object from it
|
||||
// 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
|
||||
static std::unique_ptr<KTX> create(const Header& header, const KeyValues& keyValues, const Images& images);
|
||||
|
||||
// Parse a block of memory and create a KTX object from it
|
||||
static std::unique_ptr<KTX> create(const Storage& src);
|
||||
static std::unique_ptr<KTX> create(std::unique_ptr<Storage>& src);
|
||||
|
||||
static bool checkStorageHeader(const Storage& storage);
|
||||
static bool checkHeaderFromStorage(const Storage& storage);
|
||||
|
||||
// Access raw pointers to the main sections of the KTX
|
||||
const Header* getHeader() const;
|
||||
|
@ -412,7 +419,7 @@ namespace ktx {
|
|||
|
||||
std::unique_ptr<Storage> _storage;
|
||||
KeyValues _keyValues;
|
||||
Mips _mips;
|
||||
Images _images;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
#include <QtGlobal>
|
||||
|
||||
namespace ktx {
|
||||
class Exception: public std::exception {
|
||||
class ReaderException: public std::exception {
|
||||
public:
|
||||
Exception(std::string explanation) : _explanation(explanation) {}
|
||||
ReaderException(std::string explanation) : _explanation(explanation) {}
|
||||
const char* what() const override {
|
||||
return ("KTX deserialization error: " + _explanation).c_str();
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ namespace ktx {
|
|||
uint32_t keyValueByteSize;
|
||||
memcpy(&keyValueByteSize, src, sizeof(uint32_t));
|
||||
if (keyValueByteSize > length - offset) {
|
||||
throw Exception("invalid key-value size");
|
||||
throw ReaderException("invalid key-value size");
|
||||
}
|
||||
|
||||
// find the first null character \0
|
||||
|
@ -63,7 +63,7 @@ namespace ktx {
|
|||
while (reinterpret_cast<const char*>(src[++keyLength]) != '\0') {
|
||||
if (keyLength == keyValueByteSize) {
|
||||
// key must be null-terminated, and there must be space for the value
|
||||
throw Exception("invalid key-value " + std::string(reinterpret_cast<const char*>(src), keyLength));
|
||||
throw ReaderException("invalid key-value " + std::string(reinterpret_cast<const char*>(src), keyLength));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,8 +81,8 @@ namespace ktx {
|
|||
return keyValues;
|
||||
}
|
||||
|
||||
Mips getMipsTable(const Header& header, size_t mipsDataSize, const Byte* mipsData) {
|
||||
Mips mips;
|
||||
Images getImagesTable(const Header& header, size_t mipsDataSize, const Byte* mipsData) {
|
||||
Images images;
|
||||
auto currentPtr = mipsData;
|
||||
auto numMips = header.numberOfMipmapLevels + 1;
|
||||
|
||||
|
@ -95,10 +95,9 @@ namespace ktx {
|
|||
|
||||
// If enough data ahead then capture the pointer
|
||||
if ((currentPtr - mipsData) + imageSize <= (mipsDataSize)) {
|
||||
auto padding = imageSize % PACKING_SIZE;
|
||||
padding = (padding ? 4 - padding : 0);
|
||||
auto padding = evalPadding(imageSize);
|
||||
|
||||
mips.emplace_back(Mip(imageSize, padding, currentPtr));
|
||||
images.emplace_back(Image(imageSize, padding, currentPtr));
|
||||
|
||||
currentPtr += imageSize + padding;
|
||||
} else {
|
||||
|
@ -106,28 +105,28 @@ namespace ktx {
|
|||
}
|
||||
}
|
||||
|
||||
return mips;
|
||||
return images;
|
||||
}
|
||||
|
||||
|
||||
bool KTX::checkStorageHeader(const Storage& src) {
|
||||
bool KTX::checkHeaderFromStorage(const Storage& src) {
|
||||
try {
|
||||
auto srcSize = src.size();
|
||||
auto srcBytes = src.data();
|
||||
|
||||
// validation
|
||||
if (srcSize < sizeof(Header)) {
|
||||
throw Exception("length is too short for header");
|
||||
throw ReaderException("length is too short for header");
|
||||
}
|
||||
const Header* header = reinterpret_cast<const Header*>(srcBytes);
|
||||
|
||||
if (!checkIdentifier(header->identifier)) {
|
||||
throw Exception("identifier field invalid");
|
||||
throw ReaderException("identifier field invalid");
|
||||
}
|
||||
|
||||
bool endianMatch { true };
|
||||
if (!checkEndianness(header->endianness, endianMatch)) {
|
||||
throw Exception("endianness field has invalid value");
|
||||
throw ReaderException("endianness field has invalid value");
|
||||
}
|
||||
|
||||
// TODO: endian conversion if !endianMatch - for now, this is for local use and is unnecessary
|
||||
|
@ -135,17 +134,18 @@ namespace ktx {
|
|||
|
||||
// TODO: calculated bytesOfTexData
|
||||
if (srcSize < (sizeof(Header) + header->bytesOfKeyValueData)) {
|
||||
throw Exception("length is too short for metadata");
|
||||
throw ReaderException("length is too short for metadata");
|
||||
}
|
||||
|
||||
size_t bytesOfTexData = 0;
|
||||
if (srcSize < (sizeof(Header) + header->bytesOfKeyValueData + bytesOfTexData)) {
|
||||
|
||||
throw Exception("length is too short for data");
|
||||
throw ReaderException("length is too short for data");
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception& e) {
|
||||
}
|
||||
catch (ReaderException& e) {
|
||||
qWarning(e.what());
|
||||
return false;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ namespace ktx {
|
|||
}
|
||||
|
||||
try {
|
||||
if (!checkStorageHeader(*src)) {
|
||||
if (!checkHeaderFromStorage(*src)) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -173,12 +173,12 @@ namespace ktx {
|
|||
// read metadata
|
||||
result->_keyValues = getKeyValues(result->getHeader()->bytesOfKeyValueData, result->getKeyValueData());
|
||||
|
||||
// populate mip table
|
||||
result->_mips = getMipsTable(*result->getHeader(), result->getTexelsDataSize(), result->getTexelsData());
|
||||
// populate image table
|
||||
result->_images = getImagesTable(*result->getHeader(), result->getTexelsDataSize(), result->getTexelsData());
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception& e) {
|
||||
catch (ReaderException& e) {
|
||||
qWarning(e.what());
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -12,10 +12,44 @@
|
|||
|
||||
|
||||
namespace ktx {
|
||||
/* size_t serialize(const gpu::Texture& texture, uint8_t* data) {
|
||||
return 0;
|
||||
}*/
|
||||
/* KTX serialize(const gpu::Texture& texture) {
|
||||
return KTX(0, nullptr);
|
||||
}*/
|
||||
|
||||
class WriterException : public std::exception {
|
||||
public:
|
||||
WriterException(std::string explanation) : _explanation(explanation) {}
|
||||
const char* what() const override {
|
||||
return ("KTX serialization error: " + _explanation).c_str();
|
||||
}
|
||||
private:
|
||||
std::string _explanation;
|
||||
};
|
||||
|
||||
std::unique_ptr<Storage> generateStorage(const Header& header, const KeyValues& keyValues, const Images& images) {
|
||||
size_t storageSize = sizeof(Header);
|
||||
auto numMips = header.numberOfMipmapLevels + 1;
|
||||
|
||||
for (uint32_t l = 0; l < numMips; l++) {
|
||||
if (images.size() > l) {
|
||||
|
||||
storageSize += images[l]._imageSize;
|
||||
storageSize += images[l]._imageSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<KTX> KTX::create(const Header& header, const KeyValues& keyValues, const Images& images) {
|
||||
|
||||
std::unique_ptr<KTX> result(new KTX());
|
||||
result->resetStorage(generateStorage(header, keyValues, images).release());
|
||||
|
||||
// read metadata
|
||||
result->_keyValues = keyValues;
|
||||
|
||||
// populate image table
|
||||
result->_images = images;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue