diff options
author | Herb Derby <herb@google.com> | 2017-02-10 11:15:17 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-02-16 20:03:46 +0000 |
commit | 3bf12c60e265b09f282c9cc0fea1219b0b1b1088 (patch) | |
tree | 6ccf9d1183837ec9c7aa8b6b240a0be5e102e648 | |
parent | d519d484949161df6d4b2ecadc282427cab532cf (diff) |
Remove third_party/ktx from Skia.
Change-Id: I3a1f68b0528f8789af5ccc0704b0a68fe14f52d3
Reviewed-on: https://skia-review.googlesource.com/8319
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
-rw-r--r-- | BUILD.gn | 2 | ||||
-rw-r--r-- | public.bzl | 3 | ||||
-rw-r--r-- | third_party/ktx/ktx.cpp | 567 | ||||
-rw-r--r-- | third_party/ktx/ktx.h | 177 |
4 files changed, 0 insertions, 749 deletions
@@ -114,7 +114,6 @@ config("skia_private") { "src/xml", "third_party/etc1", "third_party/gif", - "third_party/ktx", ] defines = [ @@ -613,7 +612,6 @@ component("skia") { "src/utils/mac/SkStream_mac.cpp", "third_party/etc1/etc1.cpp", "third_party/gif/SkGifImageReader.cpp", - "third_party/ktx/ktx.cpp", ] libs = [] diff --git a/public.bzl b/public.bzl index 839bf661d1..a69b760a35 100644 --- a/public.bzl +++ b/public.bzl @@ -86,8 +86,6 @@ BASE_SRCS_ALL = struct( "third_party/etc1/*.h", "third_party/gif/*.cpp", "third_party/gif/*.h", - "third_party/ktx/*.cpp", - "third_party/ktx/*.h", ], # Note: PRIVATE_HDRS_INCLUDE_LIST is excluded from BASE_SRCS_ALL here # because they are required to appear in srcs for some rules but hdrs for @@ -392,7 +390,6 @@ INCLUDES = [ "src/utils", "third_party/etc1", "third_party/gif", - "third_party/ktx", ] ################################################################################ diff --git a/third_party/ktx/ktx.cpp b/third_party/ktx/ktx.cpp deleted file mode 100644 index c96a3081fa..0000000000 --- a/third_party/ktx/ktx.cpp +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "ktx.h" - -#include "SkAutoMalloc.h" -#include "SkBitmap.h" -#include "SkEndian.h" -#include "SkStream.h" - -#include "gl/GrGLDefines.h" -#include "GrConfig.h" - -#include "etc1.h" - -static inline uint32_t compressed_fmt_to_gl_define(SkKTXFile::Format fmt) { - static const uint32_t kGLDefineMap[SkKTXFile::kFormatCnt] = { - GR_GL_COMPRESSED_LUMINANCE_LATC1, // kLATC_Format - GR_GL_COMPRESSED_R11_EAC, // kR11_EAC_Format - GR_GL_COMPRESSED_ETC1_RGB8, // kETC1_Format - GR_GL_COMPRESSED_RGBA_ASTC_4x4, // kASTC_4x4_Format - GR_GL_COMPRESSED_RGBA_ASTC_5x4, // kASTC_5x4_Format - GR_GL_COMPRESSED_RGBA_ASTC_5x5, // kASTC_5x5_Format - GR_GL_COMPRESSED_RGBA_ASTC_6x5, // kASTC_6x5_Format - GR_GL_COMPRESSED_RGBA_ASTC_6x6, // kASTC_6x6_Format - GR_GL_COMPRESSED_RGBA_ASTC_8x5, // kASTC_8x5_Format - GR_GL_COMPRESSED_RGBA_ASTC_8x6, // kASTC_8x6_Format - GR_GL_COMPRESSED_RGBA_ASTC_8x8, // kASTC_8x8_Format - GR_GL_COMPRESSED_RGBA_ASTC_10x5, // kASTC_10x5_Format - GR_GL_COMPRESSED_RGBA_ASTC_10x6, // kASTC_10x6_Format - GR_GL_COMPRESSED_RGBA_ASTC_10x8, // kASTC_10x8_Format - GR_GL_COMPRESSED_RGBA_ASTC_10x10, // kASTC_10x10_Format - GR_GL_COMPRESSED_RGBA_ASTC_12x10, // kASTC_12x10_Format - GR_GL_COMPRESSED_RGBA_ASTC_12x12, // kASTC_12x12_Format - }; - - GR_STATIC_ASSERT(0 == SkKTXFile::kLATC_Format); - GR_STATIC_ASSERT(1 == SkKTXFile::kR11_EAC_Format); - GR_STATIC_ASSERT(2 == SkKTXFile::kETC1_Format); - GR_STATIC_ASSERT(3 == SkKTXFile::kASTC_4x4_Format); - GR_STATIC_ASSERT(4 == SkKTXFile::kASTC_5x4_Format); - GR_STATIC_ASSERT(5 == SkKTXFile::kASTC_5x5_Format); - GR_STATIC_ASSERT(6 == SkKTXFile::kASTC_6x5_Format); - GR_STATIC_ASSERT(7 == SkKTXFile::kASTC_6x6_Format); - GR_STATIC_ASSERT(8 == SkKTXFile::kASTC_8x5_Format); - GR_STATIC_ASSERT(9 == SkKTXFile::kASTC_8x6_Format); - GR_STATIC_ASSERT(10 == SkKTXFile::kASTC_8x8_Format); - GR_STATIC_ASSERT(11 == SkKTXFile::kASTC_10x5_Format); - GR_STATIC_ASSERT(12 == SkKTXFile::kASTC_10x6_Format); - GR_STATIC_ASSERT(13 == SkKTXFile::kASTC_10x8_Format); - GR_STATIC_ASSERT(14 == SkKTXFile::kASTC_10x10_Format); - GR_STATIC_ASSERT(15 == SkKTXFile::kASTC_12x10_Format); - GR_STATIC_ASSERT(16 == SkKTXFile::kASTC_12x12_Format); - GR_STATIC_ASSERT(SK_ARRAY_COUNT(kGLDefineMap) == SkKTXFile::kFormatCnt); - - return kGLDefineMap[fmt]; -} - -#define KTX_FILE_IDENTIFIER_SIZE 12 -static const uint8_t KTX_FILE_IDENTIFIER[KTX_FILE_IDENTIFIER_SIZE] = { - 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A -}; - -static const uint32_t kKTX_ENDIANNESS_CODE = 0x04030201; - -bool SkKTXFile::KeyValue::readKeyAndValue(const uint8_t* data) { - const char *key = reinterpret_cast<const char *>(data); - const char *value = key; - - size_t bytesRead = 0; - while (*value != '\0' && bytesRead < this->fDataSz) { - ++bytesRead; - ++value; - } - - // Error of some sort.. - if (bytesRead >= this->fDataSz) { - return false; - } - - // Read the zero terminator - ++bytesRead; - ++value; - - size_t bytesLeft = this->fDataSz - bytesRead; - - // We ignore the null terminator when setting the string value. - this->fKey.set(key, bytesRead - 1); - if (bytesLeft > 0) { - this->fValue.set(value, bytesLeft - 1); - } else { - return false; - } - - return true; -} - -bool SkKTXFile::KeyValue::writeKeyAndValueForKTX(SkWStream* strm) { - size_t bytesWritten = 0; - if (!strm->write(&(this->fDataSz), 4)) { - return false; - } - - bytesWritten += 4; - - // Here we know that C-strings must end with a null terminating - // character, so when we get a c_str(), it will have as many - // bytes of data as size() returns plus a zero, so we just - // write size() + 1 bytes into the stream. - - size_t keySize = this->fKey.size() + 1; - if (!strm->write(this->fKey.c_str(), keySize)) { - return false; - } - - bytesWritten += keySize; - - size_t valueSize = this->fValue.size() + 1; - if (!strm->write(this->fValue.c_str(), valueSize)) { - return false; - } - - bytesWritten += valueSize; - - size_t bytesWrittenPadFour = (bytesWritten + 3) & ~3; - uint8_t nullBuf[4] = { 0, 0, 0, 0 }; - - size_t padding = bytesWrittenPadFour - bytesWritten; - SkASSERT(padding < 4); - - return strm->write(nullBuf, padding); -} - -uint32_t SkKTXFile::readInt(const uint8_t** buf, size_t* bytesLeft) const { - SkASSERT(buf && bytesLeft); - - uint32_t result; - - if (*bytesLeft < 4) { - SkASSERT(false); - return 0; - } - - memcpy(&result, *buf, 4); - *buf += 4; - - if (fSwapBytes) { - SkEndianSwap32(result); - } - - *bytesLeft -= 4; - - return result; -} - -SkString SkKTXFile::getValueForKey(const SkString& key) const { - const KeyValue *begin = this->fKeyValuePairs.begin(); - const KeyValue *end = this->fKeyValuePairs.end(); - for (const KeyValue *kv = begin; kv != end; ++kv) { - if (kv->key() == key) { - return kv->value(); - } - } - return SkString(); -} - -bool SkKTXFile::isCompressedFormat(Format fmt) const { - if (!this->valid()) { - return false; - } - - // This has many aliases - bool isFmt = false; - if (fmt == kLATC_Format) { - isFmt = GR_GL_COMPRESSED_RED_RGTC1 == fHeader.fGLInternalFormat || - GR_GL_COMPRESSED_3DC_X == fHeader.fGLInternalFormat; - } - - return isFmt || compressed_fmt_to_gl_define(fmt) == fHeader.fGLInternalFormat; -} - -bool SkKTXFile::isRGBA8() const { - return this->valid() && GR_GL_RGBA8 == fHeader.fGLInternalFormat; -} - -bool SkKTXFile::isRGB8() const { - return this->valid() && GR_GL_RGB8 == fHeader.fGLInternalFormat; -} - -bool SkKTXFile::readKTXFile(const uint8_t* data, size_t dataLen) { - const uint8_t *buf = data; - size_t bytesLeft = dataLen; - - // Make sure original KTX header is there... this should have been checked - // already by a call to is_ktx() - SkASSERT(bytesLeft > KTX_FILE_IDENTIFIER_SIZE); - SkASSERT(0 == memcmp(KTX_FILE_IDENTIFIER, buf, KTX_FILE_IDENTIFIER_SIZE)); - buf += KTX_FILE_IDENTIFIER_SIZE; - bytesLeft -= KTX_FILE_IDENTIFIER_SIZE; - - // Read header, but first make sure that we have the proper space: we need - // two 32-bit ints: 1 for endianness, and another for the mandatory image - // size after the header. - if (bytesLeft < 8 + sizeof(Header)) { - return false; - } - - uint32_t endianness = this->readInt(&buf, &bytesLeft); - fSwapBytes = kKTX_ENDIANNESS_CODE != endianness; - - // Read header values - fHeader.fGLType = this->readInt(&buf, &bytesLeft); - fHeader.fGLTypeSize = this->readInt(&buf, &bytesLeft); - fHeader.fGLFormat = this->readInt(&buf, &bytesLeft); - fHeader.fGLInternalFormat = this->readInt(&buf, &bytesLeft); - fHeader.fGLBaseInternalFormat = this->readInt(&buf, &bytesLeft); - fHeader.fPixelWidth = this->readInt(&buf, &bytesLeft); - fHeader.fPixelHeight = this->readInt(&buf, &bytesLeft); - fHeader.fPixelDepth = this->readInt(&buf, &bytesLeft); - fHeader.fNumberOfArrayElements = this->readInt(&buf, &bytesLeft); - fHeader.fNumberOfFaces = this->readInt(&buf, &bytesLeft); - fHeader.fNumberOfMipmapLevels = this->readInt(&buf, &bytesLeft); - fHeader.fBytesOfKeyValueData = this->readInt(&buf, &bytesLeft); - - // Check for things that we understand... - { - // First, we only support compressed formats and single byte - // representations at the moment. If the internal format is - // compressed, the the GLType field in the header must be zero. - // In the future, we may support additional data types (such - // as GL_UNSIGNED_SHORT_5_6_5) - if (fHeader.fGLType != 0 && fHeader.fGLType != GR_GL_UNSIGNED_BYTE) { - return false; - } - - // This means that for well-formatted KTX files, the glTypeSize - // field must be one... - if (fHeader.fGLTypeSize != 1) { - return false; - } - - // We don't support 3D textures. - if (fHeader.fPixelDepth > 1) { - return false; - } - - // We don't support texture arrays - if (fHeader.fNumberOfArrayElements > 1) { - return false; - } - - // We don't support cube maps - if (fHeader.fNumberOfFaces > 1) { - return false; - } - - // We don't support width and/or height <= 0 - if (fHeader.fPixelWidth <= 0 || fHeader.fPixelHeight <= 0) { - return false; - } - } - - // Make sure that we have enough bytes left for the key/value - // data according to what was said in the header. - if (bytesLeft < fHeader.fBytesOfKeyValueData) { - return false; - } - - // Next read the key value pairs - size_t keyValueBytesRead = 0; - while (keyValueBytesRead < fHeader.fBytesOfKeyValueData) { - uint32_t keyValueBytes = this->readInt(&buf, &bytesLeft); - keyValueBytesRead += 4; - - if (keyValueBytes > bytesLeft) { - return false; - } - - KeyValue kv(keyValueBytes); - if (!kv.readKeyAndValue(buf)) { - return false; - } - - fKeyValuePairs.push_back(kv); - - uint32_t keyValueBytesPadded = (keyValueBytes + 3) & ~3; - buf += keyValueBytesPadded; - keyValueBytesRead += keyValueBytesPadded; - bytesLeft -= keyValueBytesPadded; - } - - // Read the pixel data... - int mipmaps = SkMax32(fHeader.fNumberOfMipmapLevels, 1); - SkASSERT(mipmaps == 1); - - int arrayElements = SkMax32(fHeader.fNumberOfArrayElements, 1); - SkASSERT(arrayElements == 1); - - int faces = SkMax32(fHeader.fNumberOfFaces, 1); - SkASSERT(faces == 1); - - int depth = SkMax32(fHeader.fPixelDepth, 1); - SkASSERT(depth == 1); - - for (int mipmap = 0; mipmap < mipmaps; ++mipmap) { - // Make sure that we have at least 4 more bytes for the first image size - if (bytesLeft < 4) { - return false; - } - - uint32_t imgSize = this->readInt(&buf, &bytesLeft); - - // Truncated file. - if (bytesLeft < imgSize) { - return false; - } - - // !FIXME! If support is ever added for cube maps then the padding - // needs to be taken into account here. - for (int arrayElement = 0; arrayElement < arrayElements; ++arrayElement) { - for (int face = 0; face < faces; ++face) { - for (int z = 0; z < depth; ++z) { - PixelData pd(buf, imgSize); - fPixelData.append(1, &pd); - } - } - } - - uint32_t imgSizePadded = (imgSize + 3) & ~3; - buf += imgSizePadded; - bytesLeft -= imgSizePadded; - } - - return bytesLeft == 0; -} - -bool SkKTXFile::is_ktx(const uint8_t data[], size_t size) { - return size >= KTX_FILE_IDENTIFIER_SIZE && - 0 == memcmp(KTX_FILE_IDENTIFIER, data, KTX_FILE_IDENTIFIER_SIZE); -} - -bool SkKTXFile::is_ktx(SkStreamRewindable* stream) { - // Read the KTX header and make sure it's valid. - unsigned char buf[KTX_FILE_IDENTIFIER_SIZE]; - bool largeEnough = - stream->read((void*)buf, KTX_FILE_IDENTIFIER_SIZE) == KTX_FILE_IDENTIFIER_SIZE; - stream->rewind(); - if (!largeEnough) { - return false; - } - return is_ktx(buf, KTX_FILE_IDENTIFIER_SIZE); -} - -SkKTXFile::KeyValue SkKTXFile::CreateKeyValue(const char *cstrKey, const char *cstrValue) { - SkString key(cstrKey); - SkString value(cstrValue); - - // Size of buffer is length of string plus the null terminators... - size_t size = key.size() + 1 + value.size() + 1; - - SkAutoSMalloc<256> buf(size); - uint8_t* kvBuf = reinterpret_cast<uint8_t*>(buf.get()); - memcpy(kvBuf, key.c_str(), key.size() + 1); - memcpy(kvBuf + key.size() + 1, value.c_str(), value.size() + 1); - - KeyValue kv(size); - SkAssertResult(kv.readKeyAndValue(kvBuf)); - return kv; -} - -bool SkKTXFile::WriteETC1ToKTX(SkWStream* stream, const uint8_t *etc1Data, - uint32_t width, uint32_t height) { - // First thing's first, write out the magic identifier and endianness... - if (!stream->write(KTX_FILE_IDENTIFIER, KTX_FILE_IDENTIFIER_SIZE)) { - return false; - } - - if (!stream->write(&kKTX_ENDIANNESS_CODE, 4)) { - return false; - } - - Header hdr; - hdr.fGLType = 0; - hdr.fGLTypeSize = 1; - hdr.fGLFormat = 0; - hdr.fGLInternalFormat = GR_GL_COMPRESSED_ETC1_RGB8; - hdr.fGLBaseInternalFormat = GR_GL_RGB; - hdr.fPixelWidth = width; - hdr.fPixelHeight = height; - hdr.fNumberOfArrayElements = 0; - hdr.fNumberOfFaces = 1; - hdr.fNumberOfMipmapLevels = 1; - - // !FIXME! The spec suggests that we put KTXOrientation as a - // key value pair in the header, but that means that we'd have to - // pipe through the pixmap's orientation to properly do that. - hdr.fBytesOfKeyValueData = 0; - - // Write the header - if (!stream->write(&hdr, sizeof(hdr))) { - return false; - } - - // Write the size of the image data - etc1_uint32 dataSize = etc1_get_encoded_data_size(width, height); - if (!stream->write(&dataSize, 4)) { - return false; - } - - // Write the actual image data - if (!stream->write(etc1Data, dataSize)) { - return false; - } - - return true; -} - -bool SkKTXFile::WritePixmapToKTX(SkWStream* stream, const SkPixmap& pixmap) { - const SkColorType ct = pixmap.colorType(); - - const int width = pixmap.width(); - const int height = pixmap.height(); - const uint8_t* src = reinterpret_cast<const uint8_t*>(pixmap.addr()); - if (!src) { - return false; - } - const size_t rowBytes = pixmap.rowBytes(); - const int bytesPerPixel = pixmap.info().bytesPerPixel(); - - // First thing's first, write out the magic identifier and endianness... - if (!stream->write(KTX_FILE_IDENTIFIER, KTX_FILE_IDENTIFIER_SIZE) || - !stream->write(&kKTX_ENDIANNESS_CODE, 4)) { - return false; - } - - // Collect our key/value pairs... - SkTArray<KeyValue> kvPairs; - - // Next, write the header based on the pixmap's config. - Header hdr; - switch (ct) { - case kIndex_8_SkColorType: - // There is a compressed format for this, but we don't support it yet. - SkDebugf("Writing indexed pixmap to KTX unsupported.\n"); - // VVV fall through VVV - default: - case kUnknown_SkColorType: - // Pixmap hasn't been configured. - return false; - - case kAlpha_8_SkColorType: - hdr.fGLType = GR_GL_UNSIGNED_BYTE; - hdr.fGLTypeSize = 1; - hdr.fGLFormat = GR_GL_RED; - hdr.fGLInternalFormat = GR_GL_R8; - hdr.fGLBaseInternalFormat = GR_GL_RED; - break; - - case kRGB_565_SkColorType: - hdr.fGLType = GR_GL_UNSIGNED_SHORT_5_6_5; - hdr.fGLTypeSize = 2; - hdr.fGLFormat = GR_GL_RGB; - hdr.fGLInternalFormat = GR_GL_RGB; - hdr.fGLBaseInternalFormat = GR_GL_RGB; - break; - - case kARGB_4444_SkColorType: - hdr.fGLType = GR_GL_UNSIGNED_SHORT_4_4_4_4; - hdr.fGLTypeSize = 2; - hdr.fGLFormat = GR_GL_RGBA; - hdr.fGLInternalFormat = GR_GL_RGBA4; - hdr.fGLBaseInternalFormat = GR_GL_RGBA; - kvPairs.push_back(CreateKeyValue("KTXPremultipliedAlpha", "True")); - break; - - case kN32_SkColorType: - hdr.fGLType = GR_GL_UNSIGNED_BYTE; - hdr.fGLTypeSize = 1; - hdr.fGLFormat = GR_GL_RGBA; - hdr.fGLInternalFormat = GR_GL_RGBA8; - hdr.fGLBaseInternalFormat = GR_GL_RGBA; - kvPairs.push_back(CreateKeyValue("KTXPremultipliedAlpha", "True")); - break; - } - - // Everything else in the header is shared. - hdr.fPixelWidth = width; - hdr.fPixelHeight = height; - hdr.fNumberOfArrayElements = 0; - hdr.fNumberOfFaces = 1; - hdr.fNumberOfMipmapLevels = 1; - - // Calculate the key value data size - hdr.fBytesOfKeyValueData = 0; - for (KeyValue *kv = kvPairs.begin(); kv != kvPairs.end(); ++kv) { - // Key value size is the size of the key value data, - // four bytes for saying how big the key value size is - // and then additional bytes for padding to four byte boundary - size_t kvsize = kv->size(); - kvsize += 4; - kvsize = (kvsize + 3) & ~3; - hdr.fBytesOfKeyValueData = SkToU32(hdr.fBytesOfKeyValueData + kvsize); - } - - // Write the header - if (!stream->write(&hdr, sizeof(hdr))) { - return false; - } - - // Write out each key value pair - for (KeyValue *kv = kvPairs.begin(); kv != kvPairs.end(); ++kv) { - if (!kv->writeKeyAndValueForKTX(stream)) { - return false; - } - } - - // Calculate the size of the data - uint32_t dataSz = bytesPerPixel * width * height; - - if (0 >= bytesPerPixel) { - return false; - } - - // Write it into the buffer - if (!stream->write(&dataSz, 4)) { - return false; - } - - // Write the pixel data... - const uint8_t* rowPtr = src; - if (kN32_SkColorType == ct) { - for (int j = 0; j < height; ++j) { - const uint32_t* pixelsPtr = reinterpret_cast<const uint32_t*>(rowPtr); - for (int i = 0; i < width; ++i) { - uint32_t pixel = pixelsPtr[i]; - uint8_t dstPixel[4]; - dstPixel[0] = pixel >> SK_R32_SHIFT; - dstPixel[1] = pixel >> SK_G32_SHIFT; - dstPixel[2] = pixel >> SK_B32_SHIFT; - dstPixel[3] = pixel >> SK_A32_SHIFT; - if (!stream->write(dstPixel, 4)) { - return false; - } - } - rowPtr += rowBytes; - } - } else { - for (int i = 0; i < height; ++i) { - if (!stream->write(rowPtr, bytesPerPixel * width)) { - return false; - } - rowPtr += rowBytes; - } - } - - return true; -} - -bool SkKTXFile::WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap) { - SkAutoLockPixels autoLockPixels(bitmap); - SkPixmap pixmap; - return bitmap.peekPixels(&pixmap) && SkKTXFile::WritePixmapToKTX(stream, pixmap); -} diff --git a/third_party/ktx/ktx.h b/third_party/ktx/ktx.h deleted file mode 100644 index 22872ab540..0000000000 --- a/third_party/ktx/ktx.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - - -#ifndef SkKTXFile_DEFINED -#define SkKTXFile_DEFINED - -#include "SkData.h" -#include "SkTypes.h" -#include "SkTDArray.h" -#include "SkString.h" -#include "SkRefCnt.h" - -class SkBitmap; -class SkPixmap; -class SkStreamRewindable; -class SkWStream; - -// KTX Image File -// --- -// KTX is a general texture data storage file format ratified by the Khronos Group. As an -// overview, a KTX file contains all of the appropriate values needed to fully specify a -// texture in an OpenGL application, including the use of compressed data. -// -// A full format specification can be found here: -// http://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ - -class SkKTXFile { -public: - // Various texture compression formats that we support. - enum Format { - // Alpha only formats. - kLATC_Format, // 4x4 blocks, (de)compresses A8 - kR11_EAC_Format, // 4x4 blocks, (de)compresses A8 - - // RGB only formats - kETC1_Format, // 4x4 blocks, compresses RGB 565, decompresses 8-bit RGB - // NOTE: ETC1 supports 8-bit RGB compression, but we - // currently don't have any RGB8 SkColorTypes. We could - // support 8-bit RGBA but we would have to preprocess the - // bitmap to insert alphas. - - // Multi-purpose formats - kASTC_4x4_Format, // 4x4 blocks, no compression, decompresses RGBA - kASTC_5x4_Format, // 5x4 blocks, no compression, decompresses RGBA - kASTC_5x5_Format, // 5x5 blocks, no compression, decompresses RGBA - kASTC_6x5_Format, // 6x5 blocks, no compression, decompresses RGBA - kASTC_6x6_Format, // 6x6 blocks, no compression, decompresses RGBA - kASTC_8x5_Format, // 8x5 blocks, no compression, decompresses RGBA - kASTC_8x6_Format, // 8x6 blocks, no compression, decompresses RGBA - kASTC_8x8_Format, // 8x8 blocks, no compression, decompresses RGBA - kASTC_10x5_Format, // 10x5 blocks, no compression, decompresses RGBA - kASTC_10x6_Format, // 10x6 blocks, no compression, decompresses RGBA - kASTC_10x8_Format, // 10x8 blocks, no compression, decompresses RGBA - kASTC_10x10_Format, // 10x10 blocks, no compression, decompresses RGBA - kASTC_12x10_Format, // 12x10 blocks, no compression, decompresses RGBA - kASTC_12x12_Format, // 12x12 blocks, compresses A8, decompresses RGBA - - kLast_Format = kASTC_12x12_Format - }; - static const int kFormatCnt = kLast_Format + 1; - - // The ownership of the data remains with the caller. This class is intended - // to be used as a logical wrapper around the data in order to properly - // access the pixels. - SkKTXFile(SkData* data) : fData(data), fSwapBytes(false) { - data->ref(); - fValid = this->readKTXFile(fData->bytes(), fData->size()); - } - - bool valid() const { return fValid; } - - int width() const { return static_cast<int>(fHeader.fPixelWidth); } - int height() const { return static_cast<int>(fHeader.fPixelHeight); } - - const uint8_t *pixelData(int mipmap = 0) const { - SkASSERT(!this->valid() || mipmap < fPixelData.count()); - return this->valid() ? fPixelData[mipmap].data() : NULL; - } - - // If the decoded KTX file has the following key, then it will - // return the associated value. If not found, the empty string - // is returned. - SkString getValueForKey(const SkString& key) const; - - int numMipmaps() const { return static_cast<int>(fHeader.fNumberOfMipmapLevels); } - - bool isCompressedFormat(Format fmt) const; - bool isRGBA8() const; - bool isRGB8() const; - - static bool is_ktx(const uint8_t data[], size_t size); - static bool is_ktx(SkStreamRewindable* stream); - - static bool WriteETC1ToKTX(SkWStream* stream, const uint8_t *etc1Data, - uint32_t width, uint32_t height); - static bool WritePixmapToKTX(SkWStream* stream, const SkPixmap& pixmap); - static bool WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap); - -private: - - // The blob holding the file data. - sk_sp<SkData> fData; - - // This header captures all of the data that describes the format - // of the image data in a KTX file. - struct Header { - uint32_t fGLType; - uint32_t fGLTypeSize; - uint32_t fGLFormat; - uint32_t fGLInternalFormat; - uint32_t fGLBaseInternalFormat; - uint32_t fPixelWidth; - uint32_t fPixelHeight; - uint32_t fPixelDepth; - uint32_t fNumberOfArrayElements; - uint32_t fNumberOfFaces; - uint32_t fNumberOfMipmapLevels; - uint32_t fBytesOfKeyValueData; - - Header() { memset(this, 0, sizeof(*this)); } - } fHeader; - - // A Key Value pair stored in the KTX file. There may be - // arbitrarily many of these. - class KeyValue { - public: - KeyValue(size_t size) : fDataSz(size) { } - bool readKeyAndValue(const uint8_t *data); - size_t size() const { return fDataSz; } - const SkString& key() const { return fKey; } - const SkString& value() const { return fValue; } - bool writeKeyAndValueForKTX(SkWStream* strm); - private: - const size_t fDataSz; - SkString fKey; - SkString fValue; - }; - - static KeyValue CreateKeyValue(const char *key, const char *value); - - // The pixel data for a single mipmap level in an image. Based on how - // the rest of the data is stored, this may be compressed, a cubemap, etc. - // The header will describe the format of this data. - class PixelData { - public: - PixelData(const uint8_t *ptr, size_t sz) : fDataSz(sz), fDataPtr(ptr) { } - const uint8_t *data() const { return fDataPtr; } - size_t dataSize() const { return fDataSz; } - private: - const size_t fDataSz; - const uint8_t *fDataPtr; - }; - - // This function is only called once from the constructor. It loads the data - // and populates the appropriate fields of this class - // (fKeyValuePairs, fPixelData, fSwapBytes) - bool readKTXFile(const uint8_t *data, size_t dataLen); - - SkTArray<KeyValue> fKeyValuePairs; - SkTDArray<PixelData> fPixelData; - bool fValid; - - // If the endianness of the platform is different than the file, - // then we need to do proper byte swapping. - bool fSwapBytes; - - // Read an integer from a buffer, advance the buffer, and swap - // bytes if fSwapBytes is set - uint32_t readInt(const uint8_t** buf, size_t* bytesLeft) const; -}; - -#endif // SkKTXFile_DEFINED |