130 lines
3.9 KiB
C
130 lines
3.9 KiB
C
|
|
||
|
/*
|
||
|
* Copyright 2014 Google Inc.
|
||
|
*
|
||
|
* Use of this source code is governed by a BSD-style license that can be
|
||
|
* found in the LICENSE file.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#ifndef SkKTXFile_DEFINED
|
||
|
#define SkKTXFile_DEFINED
|
||
|
|
||
|
#include "SkData.h"
|
||
|
#include "SkTypes.h"
|
||
|
#include "SkTDArray.h"
|
||
|
#include "SkString.h"
|
||
|
#include "SkRefCnt.h"
|
||
|
|
||
|
class SkStreamRewindable;
|
||
|
|
||
|
// KTX Image File
|
||
|
// ---
|
||
|
// KTX is a general texture data storage file format ratified by the Khronos Group. As an
|
||
|
// overview, a KTX file contains all of the appropriate values needed to fully specify a
|
||
|
// texture in an OpenGL application, including the use of compressed data.
|
||
|
//
|
||
|
// A full format specification can be found here:
|
||
|
// http://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
|
||
|
|
||
|
class SkKTXFile {
|
||
|
public:
|
||
|
// The ownership of the data remains with the caller. This class is intended
|
||
|
// to be used as a logical wrapper around the data in order to properly
|
||
|
// access the pixels.
|
||
|
SkKTXFile(SkData* data)
|
||
|
: fData(data), fSwapBytes(false)
|
||
|
{
|
||
|
data->ref();
|
||
|
fValid = this->readKTXFile(fData->bytes(), fData->size());
|
||
|
}
|
||
|
|
||
|
bool valid() const { return fValid; }
|
||
|
|
||
|
int width() const { return static_cast<int>(fHeader.fPixelWidth); }
|
||
|
int height() const { return static_cast<int>(fHeader.fPixelHeight); }
|
||
|
|
||
|
const uint8_t *pixelData(int mipmap = 0) const {
|
||
|
SkASSERT(!this->valid() || mipmap < fPixelData.count());
|
||
|
return this->valid() ? fPixelData[mipmap].data() : NULL;
|
||
|
}
|
||
|
|
||
|
int numMipmaps() const { return static_cast<int>(fHeader.fNumberOfMipmapLevels); }
|
||
|
|
||
|
bool isETC1() const;
|
||
|
bool isRGBA8() const;
|
||
|
bool isRGB8() const;
|
||
|
|
||
|
static bool is_ktx(const uint8_t *data);
|
||
|
static bool is_ktx(SkStreamRewindable* stream);
|
||
|
|
||
|
private:
|
||
|
|
||
|
// The blob holding the file data.
|
||
|
SkAutoTUnref<SkData> fData;
|
||
|
|
||
|
// This header captures all of the data that describes the format
|
||
|
// of the image data in a KTX file.
|
||
|
struct Header {
|
||
|
uint32_t fGLType;
|
||
|
uint32_t fGLTypeSize;
|
||
|
uint32_t fGLFormat;
|
||
|
uint32_t fGLInternalFormat;
|
||
|
uint32_t fGLBaseInternalFormat;
|
||
|
uint32_t fPixelWidth;
|
||
|
uint32_t fPixelHeight;
|
||
|
uint32_t fPixelDepth;
|
||
|
uint32_t fNumberOfArrayElements;
|
||
|
uint32_t fNumberOfFaces;
|
||
|
uint32_t fNumberOfMipmapLevels;
|
||
|
uint32_t fBytesOfKeyValueData;
|
||
|
|
||
|
Header() { memset(this, 0, sizeof(*this)); }
|
||
|
} fHeader;
|
||
|
|
||
|
// A Key Value pair stored in the KTX file. There may be
|
||
|
// arbitrarily many of these.
|
||
|
class KeyValue {
|
||
|
public:
|
||
|
KeyValue(size_t size) : fDataSz(size) { }
|
||
|
bool readKeyAndValue(const uint8_t *data);
|
||
|
|
||
|
private:
|
||
|
const size_t fDataSz;
|
||
|
SkString fKey;
|
||
|
SkString fValue;
|
||
|
};
|
||
|
|
||
|
// The pixel data for a single mipmap level in an image. Based on how
|
||
|
// the rest of the data is stored, this may be compressed, a cubemap, etc.
|
||
|
// The header will describe the format of this data.
|
||
|
class PixelData {
|
||
|
public:
|
||
|
PixelData(const uint8_t *ptr, size_t sz) : fDataSz(sz), fDataPtr(ptr) { }
|
||
|
const uint8_t *data() const { return fDataPtr; }
|
||
|
size_t dataSize() const { return fDataSz; }
|
||
|
private:
|
||
|
const size_t fDataSz;
|
||
|
const uint8_t *fDataPtr;
|
||
|
};
|
||
|
|
||
|
// This function is only called once from the constructor. It loads the data
|
||
|
// and populates the appropriate fields of this class
|
||
|
// (fKeyValuePairs, fPixelData, fSwapBytes)
|
||
|
bool readKTXFile(const uint8_t *data, size_t dataLen);
|
||
|
|
||
|
SkTArray<KeyValue> fKeyValuePairs;
|
||
|
SkTDArray<PixelData> fPixelData;
|
||
|
bool fValid;
|
||
|
|
||
|
// If the endianness of the platform is different than the file,
|
||
|
// then we need to do proper byte swapping.
|
||
|
bool fSwapBytes;
|
||
|
|
||
|
// Read an integer from a buffer, advance the buffer, and swap
|
||
|
// bytes if fSwapBytes is set
|
||
|
uint32_t readInt(const uint8_t** buf, size_t* bytesLeft) const;
|
||
|
};
|
||
|
|
||
|
#endif // SkKTXFile_DEFINED
|