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