1 2 /* 3 * Copyright 2014 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #ifndef SkKTXFile_DEFINED 11 #define SkKTXFile_DEFINED 12 13 #include "SkData.h" 14 #include "SkTextureCompressor.h" 15 #include "SkTypes.h" 16 #include "SkTDArray.h" 17 #include "SkString.h" 18 #include "SkRefCnt.h" 19 20 class SkBitmap; 21 class SkStreamRewindable; 22 class SkWStream; 23 24 // KTX Image File 25 // --- 26 // KTX is a general texture data storage file format ratified by the Khronos Group. As an 27 // overview, a KTX file contains all of the appropriate values needed to fully specify a 28 // texture in an OpenGL application, including the use of compressed data. 29 // 30 // A full format specification can be found here: 31 // http://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ 32 33 class SkKTXFile { 34 public: 35 // The ownership of the data remains with the caller. This class is intended 36 // to be used as a logical wrapper around the data in order to properly 37 // access the pixels. SkKTXFile(SkData * data)38 SkKTXFile(SkData* data) 39 : fData(data), fSwapBytes(false) 40 { 41 data->ref(); 42 fValid = this->readKTXFile(fData->bytes(), fData->size()); 43 } 44 valid()45 bool valid() const { return fValid; } 46 width()47 int width() const { return static_cast<int>(fHeader.fPixelWidth); } height()48 int height() const { return static_cast<int>(fHeader.fPixelHeight); } 49 50 const uint8_t *pixelData(int mipmap = 0) const { 51 SkASSERT(!this->valid() || mipmap < fPixelData.count()); 52 return this->valid() ? fPixelData[mipmap].data() : NULL; 53 } 54 55 // If the decoded KTX file has the following key, then it will 56 // return the associated value. If not found, the empty string 57 // is returned. 58 SkString getValueForKey(const SkString& key) const; 59 numMipmaps()60 int numMipmaps() const { return static_cast<int>(fHeader.fNumberOfMipmapLevels); } 61 62 bool isCompressedFormat(SkTextureCompressor::Format fmt) const; 63 bool isRGBA8() const; 64 bool isRGB8() const; 65 66 static bool is_ktx(const uint8_t *data); 67 static bool is_ktx(SkStreamRewindable* stream); 68 69 static bool WriteETC1ToKTX(SkWStream* stream, const uint8_t *etc1Data, 70 uint32_t width, uint32_t height); 71 static bool WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap); 72 private: 73 74 // The blob holding the file data. 75 SkAutoTUnref<SkData> fData; 76 77 // This header captures all of the data that describes the format 78 // of the image data in a KTX file. 79 struct Header { 80 uint32_t fGLType; 81 uint32_t fGLTypeSize; 82 uint32_t fGLFormat; 83 uint32_t fGLInternalFormat; 84 uint32_t fGLBaseInternalFormat; 85 uint32_t fPixelWidth; 86 uint32_t fPixelHeight; 87 uint32_t fPixelDepth; 88 uint32_t fNumberOfArrayElements; 89 uint32_t fNumberOfFaces; 90 uint32_t fNumberOfMipmapLevels; 91 uint32_t fBytesOfKeyValueData; 92 HeaderHeader93 Header() { memset(this, 0, sizeof(*this)); } 94 } fHeader; 95 96 // A Key Value pair stored in the KTX file. There may be 97 // arbitrarily many of these. 98 class KeyValue { 99 public: KeyValue(size_t size)100 KeyValue(size_t size) : fDataSz(size) { } 101 bool readKeyAndValue(const uint8_t *data); size()102 size_t size() const { return fDataSz; } key()103 const SkString& key() const { return fKey; } value()104 const SkString& value() const { return fValue; } 105 bool writeKeyAndValueForKTX(SkWStream* strm); 106 private: 107 const size_t fDataSz; 108 SkString fKey; 109 SkString fValue; 110 }; 111 112 static KeyValue CreateKeyValue(const char *key, const char *value); 113 114 // The pixel data for a single mipmap level in an image. Based on how 115 // the rest of the data is stored, this may be compressed, a cubemap, etc. 116 // The header will describe the format of this data. 117 class PixelData { 118 public: PixelData(const uint8_t * ptr,size_t sz)119 PixelData(const uint8_t *ptr, size_t sz) : fDataSz(sz), fDataPtr(ptr) { } data()120 const uint8_t *data() const { return fDataPtr; } dataSize()121 size_t dataSize() const { return fDataSz; } 122 private: 123 const size_t fDataSz; 124 const uint8_t *fDataPtr; 125 }; 126 127 // This function is only called once from the constructor. It loads the data 128 // and populates the appropriate fields of this class 129 // (fKeyValuePairs, fPixelData, fSwapBytes) 130 bool readKTXFile(const uint8_t *data, size_t dataLen); 131 132 SkTArray<KeyValue> fKeyValuePairs; 133 SkTDArray<PixelData> fPixelData; 134 bool fValid; 135 136 // If the endianness of the platform is different than the file, 137 // then we need to do proper byte swapping. 138 bool fSwapBytes; 139 140 // Read an integer from a buffer, advance the buffer, and swap 141 // bytes if fSwapBytes is set 142 uint32_t readInt(const uint8_t** buf, size_t* bytesLeft) const; 143 }; 144 145 #endif // SkKTXFile_DEFINED 146