199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski/* 399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski * Copyright 2014 Google Inc. 499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski * 599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski * Use of this source code is governed by a BSD-style license that can be 699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski * found in the LICENSE file. 799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski */ 899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 1099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski#ifndef SkKTXFile_DEFINED 1199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski#define SkKTXFile_DEFINED 1299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 1399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski#include "SkData.h" 1440a1e11ebebe81586f3fec96408fdfd4b51123d2krajcevski#include "SkTextureCompressor.h" 1599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski#include "SkTypes.h" 1699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski#include "SkTDArray.h" 1799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski#include "SkString.h" 1899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski#include "SkRefCnt.h" 1999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 20c250d2e4abdbe8193357696518592af8a0b4555akrajcevskiclass SkBitmap; 2199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevskiclass SkStreamRewindable; 22c250d2e4abdbe8193357696518592af8a0b4555akrajcevskiclass SkWStream; 2399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 2499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski// KTX Image File 2599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski// --- 2699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski// KTX is a general texture data storage file format ratified by the Khronos Group. As an 2799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski// overview, a KTX file contains all of the appropriate values needed to fully specify a 2899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski// texture in an OpenGL application, including the use of compressed data. 2999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski// 3099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski// A full format specification can be found here: 3199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski// http://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ 3299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 3399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevskiclass SkKTXFile { 3499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevskipublic: 3599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // The ownership of the data remains with the caller. This class is intended 3699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // to be used as a logical wrapper around the data in order to properly 3799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // access the pixels. 3899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski SkKTXFile(SkData* data) 3999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski : fData(data), fSwapBytes(false) 4099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski { 4199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski data->ref(); 4299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski fValid = this->readKTXFile(fData->bytes(), fData->size()); 4399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski } 4499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 4599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski bool valid() const { return fValid; } 4699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 4799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski int width() const { return static_cast<int>(fHeader.fPixelWidth); } 4899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski int height() const { return static_cast<int>(fHeader.fPixelHeight); } 4999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 5099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski const uint8_t *pixelData(int mipmap = 0) const { 5199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski SkASSERT(!this->valid() || mipmap < fPixelData.count()); 5299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski return this->valid() ? fPixelData[mipmap].data() : NULL; 5399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski } 5499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 55c250d2e4abdbe8193357696518592af8a0b4555akrajcevski // If the decoded KTX file has the following key, then it will 56c250d2e4abdbe8193357696518592af8a0b4555akrajcevski // return the associated value. If not found, the empty string 57c250d2e4abdbe8193357696518592af8a0b4555akrajcevski // is returned. 58c250d2e4abdbe8193357696518592af8a0b4555akrajcevski SkString getValueForKey(const SkString& key) const; 59c250d2e4abdbe8193357696518592af8a0b4555akrajcevski 6099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski int numMipmaps() const { return static_cast<int>(fHeader.fNumberOfMipmapLevels); } 6199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 6240a1e11ebebe81586f3fec96408fdfd4b51123d2krajcevski bool isCompressedFormat(SkTextureCompressor::Format fmt) const; 6399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski bool isRGBA8() const; 6499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski bool isRGB8() const; 6599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 6699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski static bool is_ktx(const uint8_t *data); 6799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski static bool is_ktx(SkStreamRewindable* stream); 6899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 69c250d2e4abdbe8193357696518592af8a0b4555akrajcevski static bool WriteETC1ToKTX(SkWStream* stream, const uint8_t *etc1Data, 70c250d2e4abdbe8193357696518592af8a0b4555akrajcevski uint32_t width, uint32_t height); 71c250d2e4abdbe8193357696518592af8a0b4555akrajcevski static bool WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap); 7299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevskiprivate: 7399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 7499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // The blob holding the file data. 7599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski SkAutoTUnref<SkData> fData; 7699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 7799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // This header captures all of the data that describes the format 7899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // of the image data in a KTX file. 7999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski struct Header { 8099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fGLType; 8199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fGLTypeSize; 8299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fGLFormat; 8399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fGLInternalFormat; 8499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fGLBaseInternalFormat; 8599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fPixelWidth; 8699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fPixelHeight; 8799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fPixelDepth; 8899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fNumberOfArrayElements; 8999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fNumberOfFaces; 9099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fNumberOfMipmapLevels; 9199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t fBytesOfKeyValueData; 9299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 9399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski Header() { memset(this, 0, sizeof(*this)); } 9499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski } fHeader; 9599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 9699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // A Key Value pair stored in the KTX file. There may be 9799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // arbitrarily many of these. 9899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski class KeyValue { 9999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski public: 10099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski KeyValue(size_t size) : fDataSz(size) { } 10199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski bool readKeyAndValue(const uint8_t *data); 102c250d2e4abdbe8193357696518592af8a0b4555akrajcevski size_t size() const { return fDataSz; } 103c250d2e4abdbe8193357696518592af8a0b4555akrajcevski const SkString& key() const { return fKey; } 104c250d2e4abdbe8193357696518592af8a0b4555akrajcevski const SkString& value() const { return fValue; } 105c250d2e4abdbe8193357696518592af8a0b4555akrajcevski bool writeKeyAndValueForKTX(SkWStream* strm); 10699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski private: 10799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski const size_t fDataSz; 108c250d2e4abdbe8193357696518592af8a0b4555akrajcevski SkString fKey; 109c250d2e4abdbe8193357696518592af8a0b4555akrajcevski SkString fValue; 11099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski }; 11199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 112c250d2e4abdbe8193357696518592af8a0b4555akrajcevski static KeyValue CreateKeyValue(const char *key, const char *value); 113c250d2e4abdbe8193357696518592af8a0b4555akrajcevski 11499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // The pixel data for a single mipmap level in an image. Based on how 11599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // the rest of the data is stored, this may be compressed, a cubemap, etc. 11699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // The header will describe the format of this data. 11799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski class PixelData { 11899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski public: 11999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski PixelData(const uint8_t *ptr, size_t sz) : fDataSz(sz), fDataPtr(ptr) { } 12099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski const uint8_t *data() const { return fDataPtr; } 12199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski size_t dataSize() const { return fDataSz; } 12299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski private: 12399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski const size_t fDataSz; 12499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski const uint8_t *fDataPtr; 12599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski }; 12699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 12799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // This function is only called once from the constructor. It loads the data 12899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // and populates the appropriate fields of this class 12999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // (fKeyValuePairs, fPixelData, fSwapBytes) 13099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski bool readKTXFile(const uint8_t *data, size_t dataLen); 13199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 13299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski SkTArray<KeyValue> fKeyValuePairs; 13399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski SkTDArray<PixelData> fPixelData; 13499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski bool fValid; 13599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 13699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // If the endianness of the platform is different than the file, 13799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // then we need to do proper byte swapping. 13899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski bool fSwapBytes; 13999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 14099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // Read an integer from a buffer, advance the buffer, and swap 14199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski // bytes if fSwapBytes is set 14299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski uint32_t readInt(const uint8_t** buf, size_t* bytesLeft) const; 14399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski}; 14499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski 14599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski#endif // SkKTXFile_DEFINED 146