Address review comments

This commit is contained in:
samcake 2017-02-16 13:27:16 -08:00
parent 7d9ad838c7
commit 2f7181fb32
6 changed files with 156 additions and 66 deletions

View file

@ -1002,27 +1002,3 @@ Texture::ExternalUpdates Texture::getUpdates() const {
return result;
}
#include <ktx/KTX.h>
ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
ktx::Header header;
header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 4, ktx::GLFormat::BGRA, ktx::GLInternalFormat_Uncompressed::RGBA8, ktx::GLBaseInternalFormat::RGBA);
header.pixelWidth = texture.getWidth();
header.pixelHeight = texture.getHeight();
header.numberOfMipmapLevels = texture.mipLevels();
ktx::Images images;
for (int level = 0; level < header.numberOfMipmapLevels; level++) {
auto mip = texture.accessStoredMipFace(level);
if (mip) {
images.emplace_back(ktx::Image(mip->getSize(), 0, mip->readData()));
}
}
auto ktxBuffer = ktx::KTX::create(header, ktx::KeyValues(), images);
return ktxBuffer;
}
TexturePointer Texture::unserialize(const ktx::KTXUniquePointer& srcData) {
return nullptr;
}

View file

@ -0,0 +1,42 @@
//
// Texture_ktx.cpp
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 2/16/2017.
// Copyright 2014 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 "Texture.h"
#include <ktx/KTX.h>
using namespace gpu;
ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
ktx::Header header;
header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 4, ktx::GLFormat::BGRA, ktx::GLInternalFormat_Uncompressed::RGBA8, ktx::GLBaseInternalFormat::RGBA);
header.pixelWidth = texture.getWidth();
header.pixelHeight = texture.getHeight();
header.numberOfMipmapLevels = texture.mipLevels();
ktx::Images images;
for (int level = 0; level < header.numberOfMipmapLevels; level++) {
auto mip = texture.accessStoredMipFace(level);
if (mip) {
images.emplace_back(ktx::Image(mip->getSize(), 0, mip->readData()));
}
}
auto ktxBuffer = ktx::KTX::create(header, images);
return ktxBuffer;
}
TexturePointer Texture::unserialize(const ktx::KTXUniquePointer& srcData) {
const auto& header = *srcData->getHeader();
return nullptr;
}

View file

@ -427,7 +427,22 @@ namespace ktx {
// 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);
static std::unique_ptr<KTX> create(const Header& header, const Images& images, const KeyValues& keyValues = KeyValues());
// Instead of creating a full Copy of the src data in a KTX object, the write serialization can be performed with the
// following two functions
// size_t sizeNeeded = KTX::evalStorageSize(header, images);
//
// //allocate a buffer of size "sizeNeeded" or map a file with enough capacity
// Byte* destBytes = new Byte[sizeNeeded];
//
// // THen perform the writing of the src data to the destinnation buffer
// write(destBytes, sizeNeeded, header, images);
//
// This is exactly what is done in the create function
static size_t evalStorageSize(const Header& header, const Images& images, const KeyValues& keyValues = KeyValues());
static size_t write(Byte* destBytes, size_t destByteSize, const Header& header, const Images& images, const KeyValues& keyValues = KeyValues());
static Images writeImages(Byte* destBytes, size_t destByteSize, const Images& images);
// Parse a block of memory and create a KTX object from it
static std::unique_ptr<KTX> create(const Storage& src);

View file

@ -16,12 +16,12 @@
namespace ktx {
class ReaderException: public std::exception {
public:
ReaderException(std::string explanation) : _explanation(explanation) {}
ReaderException(const std::string& explanation) : _explanation("KTX deserialization error: " + explanation) {}
const char* what() const override {
return ("KTX deserialization error: " + _explanation).c_str();
return _explanation.c_str();
}
private:
std::string _explanation;
const std::string _explanation;
};
bool checkEndianness(uint32_t endianness, bool& matching) {

View file

@ -15,30 +15,14 @@ namespace ktx {
class WriterException : public std::exception {
public:
WriterException(std::string explanation) : _explanation(explanation) {}
WriterException(const std::string& explanation) : _explanation("KTX serialization error: " + explanation) {}
const char* what() const override {
return ("KTX serialization error: " + _explanation).c_str();
return _explanation.c_str();
}
private:
std::string _explanation;
const 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.getNumberOfLevels();
for (uint32_t l = 0; l < numMips; l++) {
if (images.size() > l) {
storageSize += sizeof(uint32_t);
storageSize += images[l]._imageSize;
storageSize += Header::evalPadding(images[l]._imageSize);
}
}
std::unique_ptr<Storage> storage(new Storage(storageSize));
return storage;
}
void KTX::resetHeader(const Header& header) {
if (!_storage) {
@ -52,10 +36,84 @@ namespace ktx {
return;
}
auto allocatedImagesDataSize = getTexelsDataSize();
// Just copy in our storage
_images = writeImages(imagesDataPtr, allocatedImagesDataSize, srcImages);
}
std::unique_ptr<KTX> KTX::create(const Header& header, const Images& images, const KeyValues& keyValues) {
auto storageSize = evalStorageSize(header, images, keyValues);
std::unique_ptr<KTX> result(new KTX());
result->resetStorage(new Storage(storageSize));
result->resetHeader(header);
// read metadata
result->_keyValues = keyValues;
// populate image table
result->resetImages(images);
return result;
}
size_t KTX::evalStorageSize(const Header& header, const Images& images, const KeyValues& keyValues) {
size_t storageSize = sizeof(Header);
if (header.bytesOfKeyValueData && !keyValues.empty()) {
}
auto numMips = header.getNumberOfLevels();
for (uint32_t l = 0; l < numMips; l++) {
if (images.size() > l) {
storageSize += sizeof(uint32_t);
storageSize += images[l]._imageSize;
storageSize += Header::evalPadding(images[l]._imageSize);
}
}
return storageSize;
}
size_t KTX::write(Byte* destBytes, size_t destByteSize, const Header& header, const Images& srcImages, const KeyValues& keyValues) {
// Check again that we have enough destination capacity
if (!destBytes || (destByteSize < evalStorageSize(header, srcImages, keyValues))) {
return 0;
}
auto currentDestPtr = destBytes;
// Header
auto destHeader = reinterpret_cast<Header*>(currentDestPtr);
memcpy(currentDestPtr, &header, sizeof(Header));
currentDestPtr += sizeof(Header);
// KeyValues
// Skip for now
if (header.bytesOfKeyValueData && !keyValues.empty()) {
}
destHeader->bytesOfKeyValueData = 0;
currentDestPtr += destHeader->bytesOfKeyValueData;
// Images
auto destImages = writeImages(currentDestPtr, destByteSize - sizeof(Header) - destHeader->bytesOfKeyValueData, srcImages);
// We chould check here that the amoutn of dest IMages generated is the same as the source
return destByteSize;
}
Images KTX::writeImages(Byte* destBytes, size_t destByteSize, const Images& srcImages) {
Images destImages;
auto imagesDataPtr = destBytes;
if (!imagesDataPtr) {
return destImages;
}
auto allocatedImagesDataSize = destByteSize;
size_t currentDataSize = 0;
auto currentPtr = imagesDataPtr;
_images.clear();
for (uint32_t l = 0; l < srcImages.size(); l++) {
@ -72,29 +130,15 @@ namespace ktx {
auto padding = Header::evalPadding(imageSize);
_images.emplace_back(Image(imageSize, padding, currentPtr));
destImages.emplace_back(Image(imageSize, padding, currentPtr));
currentPtr += imageSize + padding;
currentDataSize += imageSize + padding;
}
}
}
}
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());
result->resetHeader(header);
// read metadata
result->_keyValues = keyValues;
// populate image table
result->resetImages(images);
return result;
return destImages;
}
}

View file

@ -15,6 +15,9 @@
#include <QImage>
#include <QPainter>
#include <QDebug>
#include <QStandardPaths>
#include <QFileInfo>
#include <QDir>
#include <Profile.h>
@ -269,7 +272,17 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag
auto theKTX = Texture::serialize(*theTexture);
if (theKTX) {
// save that!
std::string filename("C://temp//ktxCache//texmex");
QString path("hifi_ktx/");
QFileInfo originalFileInfo(path);
QString docsLocation = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
path = docsLocation + "/" + path;
QFileInfo info(path);
if (!info.absoluteDir().exists()) {
QString originalRelativePath = originalFileInfo.path();
QDir(docsLocation).mkpath(originalRelativePath);
}
std::string filename(path.toStdString());
filename += std::to_string((size_t) theTexture);
filename += ".ktx";