Home | History | Annotate | Download | only in ktx
      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.
     38     SkKTXFile(SkData* data)
     39         : fData(data), fSwapBytes(false)
     40     {
     41         data->ref();
     42         fValid = this->readKTXFile(fData->bytes(), fData->size());
     43     }
     44 
     45     bool valid() const { return fValid; }
     46 
     47     int width() const { return static_cast<int>(fHeader.fPixelWidth); }
     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 
     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 
     93         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:
    100         KeyValue(size_t size) : fDataSz(size) { }
    101         bool readKeyAndValue(const uint8_t *data);
    102         size_t size() const { return fDataSz; }
    103         const SkString& key() const { return fKey; }
    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:
    119         PixelData(const uint8_t *ptr, size_t sz) : fDataSz(sz), fDataPtr(ptr) { }
    120         const uint8_t *data() const { return fDataPtr; }
    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