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