aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/astcbitmap.cpp104
-rw-r--r--gyp/gmslides.gypi1
-rw-r--r--gyp/images.gyp1
-rw-r--r--include/core/SkImageDecoder.h2
-rw-r--r--src/gpu/GrSWMaskHelper.cpp38
-rw-r--r--src/images/SkForceLinking.cpp1
-rw-r--r--src/images/SkImageDecoder.cpp2
-rw-r--r--src/images/SkImageDecoder_astc.cpp209
-rw-r--r--src/utils/SkTextureCompressor.cpp76
-rw-r--r--src/utils/SkTextureCompressor.h13
-rw-r--r--src/utils/SkTextureCompressor_ASTC.cpp15
-rw-r--r--tests/ImageDecodingTest.cpp5
-rw-r--r--tests/TextureCompressionTest.cpp37
-rw-r--r--third_party/ktx/ktx.cpp32
14 files changed, 491 insertions, 45 deletions
diff --git a/gm/astcbitmap.cpp b/gm/astcbitmap.cpp
new file mode 100644
index 0000000000..3c9079cfa8
--- /dev/null
+++ b/gm/astcbitmap.cpp
@@ -0,0 +1,104 @@
+/*
+ * 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 "gm.h"
+
+#include "Resources.h"
+#include "SkCanvas.h"
+#include "SkData.h"
+#include "SkDecodingImageGenerator.h"
+#include "SkImageDecoder.h"
+#include "SkOSFile.h"
+#include "SkTextureCompressor.h"
+
+static const char *kASTCFilenames[] = {
+ "mandrill_128x128_4x4.astc", // kASTC_4x4_Format
+ "mandrill_130x128_5x4.astc", // kASTC_5x4_Format
+ "mandrill_130x130_5x5.astc", // kASTC_5x5_Format
+ "mandrill_132x130_6x5.astc", // kASTC_6x5_Format
+ "mandrill_132x132_6x6.astc", // kASTC_6x6_Format
+ "mandrill_128x130_8x5.astc", // kASTC_8x5_Format
+ "mandrill_128x132_8x6.astc", // kASTC_8x6_Format
+ "mandrill_128x128_8x8.astc", // kASTC_8x8_Format
+ "mandrill_130x130_10x5.astc", // kASTC_10x5_Format
+ "mandrill_130x132_10x6.astc", // kASTC_10x6_Format
+ "mandrill_130x128_10x8.astc", // kASTC_10x8_Format
+ "mandrill_130x130_10x10.astc", // kASTC_10x10_Format
+ "mandrill_132x130_12x10.astc", // kASTC_12x10_Format
+ "mandrill_132x132_12x12.astc", // kASTC_12x12_Format
+};
+
+static const int kNumASTCFilenames = SK_ARRAY_COUNT(kASTCFilenames);
+
+static inline const char *get_astc_filename(int idx) {
+ if (idx < 0 || kNumASTCFilenames <= idx) {
+ return "";
+ }
+
+ return kASTCFilenames[idx];
+}
+
+namespace skiagm {
+
+/**
+ * Test decoding an image from an ASTC file and then from compressed ASTC data.
+ */
+class ASTCBitmapGM : public GM {
+public:
+ ASTCBitmapGM() { }
+ virtual ~ASTCBitmapGM() { }
+
+protected:
+ virtual SkString onShortName() SK_OVERRIDE {
+ return SkString("astcbitmap");
+ }
+
+ virtual SkISize onISize() SK_OVERRIDE {
+ return SkISize::Make(kGMDimension, kGMDimension);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+ for (int j = 0; j < 4; ++j) {
+ for (int i = 0; i < 4; ++i) {
+ SkString filename = GetResourcePath(get_astc_filename(j*4+i));
+ if (filename == GetResourcePath("")) {
+ continue;
+ }
+
+ SkAutoTUnref<SkData> fileData(SkData::NewFromFileName(filename.c_str()));
+ if (NULL == fileData) {
+ SkDebugf("Could not open the file. Did you forget to set the resourcePath?\n");
+ return;
+ }
+
+ SkBitmap bm;
+ if (!SkInstallDiscardablePixelRef(
+ SkDecodingImageGenerator::Create(
+ fileData, SkDecodingImageGenerator::Options()), &bm)) {
+ SkDebugf("Could not install discardable pixel ref.\n");
+ return;
+ }
+
+ const SkScalar bmX = static_cast<SkScalar>(i*kBitmapDimension);
+ const SkScalar bmY = static_cast<SkScalar>(j*kBitmapDimension);
+ canvas->drawBitmap(bm, bmX, bmY);
+ }
+ }
+ }
+
+private:
+ static const int kGMDimension = 600;
+ static const int kBitmapDimension = kGMDimension/4;
+
+ typedef GM INHERITED;
+};
+
+} // namespace skiagm
+
+//////////////////////////////////////////////////////////////////////////////
+
+DEF_GM( return SkNEW(skiagm::ASTCBitmapGM); )
diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi
index d9c18722b1..c55da892f8 100644
--- a/gyp/gmslides.gypi
+++ b/gyp/gmslides.gypi
@@ -18,6 +18,7 @@
'../gm/alphagradients.cpp',
'../gm/arcofzorro.cpp',
'../gm/arithmode.cpp',
+ '../gm/astcbitmap.cpp',
'../gm/beziereffects.cpp',
'../gm/bigblurs.cpp',
'../gm/bigmatrix.cpp',
diff --git a/gyp/images.gyp b/gyp/images.gyp
index ee1840bd3f..3cc66a0adb 100644
--- a/gyp/images.gyp
+++ b/gyp/images.gyp
@@ -59,6 +59,7 @@
'../src/images/SkImageDecoder_wbmp.cpp',
'../src/images/SkImageDecoder_pkm.cpp',
'../src/images/SkImageDecoder_ktx.cpp',
+ '../src/images/SkImageDecoder_astc.cpp',
'../src/images/SkImageDecoder_libbmp.cpp',
'../src/images/SkImageDecoder_libgif.cpp',
'../src/images/SkImageDecoder_libico.cpp',
diff --git a/include/core/SkImageDecoder.h b/include/core/SkImageDecoder.h
index b258afedce..2b9108025e 100644
--- a/include/core/SkImageDecoder.h
+++ b/include/core/SkImageDecoder.h
@@ -37,6 +37,7 @@ public:
kWEBP_Format,
kPKM_Format,
kKTX_Format,
+ kASTC_Format,
kLastKnownFormat = kKTX_Format,
};
@@ -525,6 +526,7 @@ DECLARE_DECODER_CREATOR(WBMPImageDecoder);
DECLARE_DECODER_CREATOR(WEBPImageDecoder);
DECLARE_DECODER_CREATOR(PKMImageDecoder);
DECLARE_DECODER_CREATOR(KTXImageDecoder);
+DECLARE_DECODER_CREATOR(ASTCImageDecoder);
// Typedefs to make registering decoder and formatter callbacks easier.
// These have to be defined outside SkImageDecoder. :(
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index 2863739161..69dc0b5319 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -37,19 +37,33 @@ SkXfermode::Mode op_to_mode(SkRegion::Op op) {
}
static inline GrPixelConfig fmt_to_config(SkTextureCompressor::Format fmt) {
- static const GrPixelConfig configMap[] = {
- kLATC_GrPixelConfig, // kLATC_Format,
- kR11_EAC_GrPixelConfig, // kR11_EAC_Format,
- kETC1_GrPixelConfig, // kETC1_Format,
- kASTC_12x12_GrPixelConfig // kASTC_12x12_Format,
- };
- GR_STATIC_ASSERT(0 == SkTextureCompressor::kLATC_Format);
- GR_STATIC_ASSERT(1 == SkTextureCompressor::kR11_EAC_Format);
- GR_STATIC_ASSERT(2 == SkTextureCompressor::kETC1_Format);
- GR_STATIC_ASSERT(3 == SkTextureCompressor::kASTC_12x12_Format);
- GR_STATIC_ASSERT(SK_ARRAY_COUNT(configMap) == SkTextureCompressor::kFormatCnt);
- return configMap[fmt];
+ GrPixelConfig config;
+ switch (fmt) {
+ case SkTextureCompressor::kLATC_Format:
+ config = kLATC_GrPixelConfig;
+ break;
+
+ case SkTextureCompressor::kR11_EAC_Format:
+ config = kR11_EAC_GrPixelConfig;
+ break;
+
+ case SkTextureCompressor::kASTC_12x12_Format:
+ config = kASTC_12x12_GrPixelConfig;
+ break;
+
+ case SkTextureCompressor::kETC1_Format:
+ config = kETC1_GrPixelConfig;
+ break;
+
+ default:
+ SkDEBUGFAIL("No GrPixelConfig for compression format!");
+ // Best guess
+ config = kAlpha_8_GrPixelConfig;
+ break;
+ }
+
+ return config;
}
#if GR_COMPRESS_ALPHA_MASK
diff --git a/src/images/SkForceLinking.cpp b/src/images/SkForceLinking.cpp
index 442f0f77c0..6cc0704e83 100644
--- a/src/images/SkForceLinking.cpp
+++ b/src/images/SkForceLinking.cpp
@@ -20,6 +20,7 @@ int SkForceLinking(bool doNotPassTrue) {
CreateICOImageDecoder();
CreatePKMImageDecoder();
CreateKTXImageDecoder();
+ CreateASTCImageDecoder();
CreateWBMPImageDecoder();
// Only link GIF and PNG on platforms that build them. See images.gyp
#if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_WIN) && !defined(SK_BUILD_FOR_NACL) \
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp
index fcba91069a..0e2018c117 100644
--- a/src/images/SkImageDecoder.cpp
+++ b/src/images/SkImageDecoder.cpp
@@ -86,6 +86,8 @@ const char* SkImageDecoder::GetFormatName(Format format) {
return "PKM";
case kKTX_Format:
return "KTX";
+ case kASTC_Format:
+ return "ASTC";
case kJPEG_Format:
return "JPEG";
case kPNG_Format:
diff --git a/src/images/SkImageDecoder_astc.cpp b/src/images/SkImageDecoder_astc.cpp
new file mode 100644
index 0000000000..79e98047d6
--- /dev/null
+++ b/src/images/SkImageDecoder_astc.cpp
@@ -0,0 +1,209 @@
+/*
+ * 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 "SkEndian.h"
+#include "SkColorPriv.h"
+#include "SkImageDecoder.h"
+#include "SkScaledBitmapSampler.h"
+#include "SkStream.h"
+#include "SkStreamPriv.h"
+#include "SkTypes.h"
+
+#include "SkTextureCompressor.h"
+
+class SkASTCImageDecoder : public SkImageDecoder {
+public:
+ SkASTCImageDecoder() { }
+
+ virtual Format getFormat() const SK_OVERRIDE {
+ return kASTC_Format;
+ }
+
+protected:
+ virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
+
+private:
+ typedef SkImageDecoder INHERITED;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static const uint32_t kASTCMagicNumber = 0x5CA1AB13;
+
+static inline int read_24bit(const uint8_t* buf) {
+ // Assume everything is little endian...
+ return
+ static_cast<int>(buf[0]) |
+ (static_cast<int>(buf[1]) << 8) |
+ (static_cast<int>(buf[2]) << 16);
+}
+
+bool SkASTCImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
+ SkAutoMalloc autoMal;
+ const size_t length = SkCopyStreamToStorage(&autoMal, stream);
+ if (0 == length) {
+ return false;
+ }
+
+ unsigned char* buf = (unsigned char*)autoMal.get();
+
+ // Make sure that the magic header is there...
+ SkASSERT(SkEndian_SwapLE32(*(reinterpret_cast<uint32_t*>(buf))) == kASTCMagicNumber);
+
+ // Advance past the magic header
+ buf += 4;
+
+ const int blockDimX = buf[0];
+ const int blockDimY = buf[1];
+ const int blockDimZ = buf[2];
+
+ if (1 != blockDimZ) {
+ // We don't support decoding 3D
+ return false;
+ }
+
+ // Choose the proper ASTC format
+ SkTextureCompressor::Format astcFormat;
+ if (4 == blockDimX && 4 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_4x4_Format;
+ } else if (5 == blockDimX && 4 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_5x4_Format;
+ } else if (5 == blockDimX && 5 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_5x5_Format;
+ } else if (6 == blockDimX && 5 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_6x5_Format;
+ } else if (6 == blockDimX && 6 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_6x6_Format;
+ } else if (8 == blockDimX && 5 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_8x5_Format;
+ } else if (8 == blockDimX && 6 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_8x6_Format;
+ } else if (8 == blockDimX && 8 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_8x8_Format;
+ } else if (10 == blockDimX && 5 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_10x5_Format;
+ } else if (10 == blockDimX && 6 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_10x6_Format;
+ } else if (10 == blockDimX && 8 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_10x8_Format;
+ } else if (10 == blockDimX && 10 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_10x10_Format;
+ } else if (12 == blockDimX && 10 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_12x10_Format;
+ } else if (12 == blockDimX && 12 == blockDimY) {
+ astcFormat = SkTextureCompressor::kASTC_12x12_Format;
+ } else {
+ // We don't support any other block dimensions..
+ return false;
+ }
+
+ // Advance buf past the block dimensions
+ buf += 3;
+
+ // Read the width/height/depth from the buffer...
+ const int width = read_24bit(buf);
+ const int height = read_24bit(buf + 3);
+ const int depth = read_24bit(buf + 6);
+
+ if (1 != depth) {
+ // We don't support decoding 3D.
+ return false;
+ }
+
+ // Advance the buffer past the image dimensions
+ buf += 9;
+
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
+ // should we allow the Chooser (if present) to pick a config for us???
+ if (!this->chooseFromOneChoice(kN32_SkColorType, width, height)) {
+ return false;
+ }
+#endif
+
+ // Setup the sampler...
+ SkScaledBitmapSampler sampler(width, height, this->getSampleSize());
+
+ // Determine the alpha of the bitmap...
+ SkAlphaType alphaType = kOpaque_SkAlphaType;
+ if (this->getRequireUnpremultipliedColors()) {
+ alphaType = kUnpremul_SkAlphaType;
+ } else {
+ alphaType = kPremul_SkAlphaType;
+ }
+
+ // Set the config...
+ bm->setInfo(SkImageInfo::MakeN32(sampler.scaledWidth(), sampler.scaledHeight(), alphaType));
+
+ if (SkImageDecoder::kDecodeBounds_Mode == mode) {
+ return true;
+ }
+
+ if (!this->allocPixelRef(bm, NULL)) {
+ return false;
+ }
+
+ // Lock the pixels, since we're about to write to them...
+ SkAutoLockPixels alp(*bm);
+
+ if (!sampler.begin(bm, SkScaledBitmapSampler::kRGBA, *this)) {
+ return false;
+ }
+
+ // ASTC Data is encoded as RGBA pixels, so we should extract it as such
+ int nPixels = width * height;
+ SkAutoMalloc outRGBAData(nPixels * 4);
+ uint8_t *outRGBADataPtr = reinterpret_cast<uint8_t *>(outRGBAData.get());
+
+ // Decode ASTC
+ if (!SkTextureCompressor::DecompressBufferFromFormat(
+ outRGBADataPtr, width*4, buf, width, height, astcFormat)) {
+ }
+
+ // Set each of the pixels...
+ const int srcRowBytes = width * 4;
+ const int dstHeight = sampler.scaledHeight();
+ const uint8_t *srcRow = reinterpret_cast<uint8_t *>(outRGBADataPtr);
+ srcRow += sampler.srcY0() * srcRowBytes;
+ for (int y = 0; y < dstHeight; ++y) {
+ sampler.next(srcRow);
+ srcRow += sampler.srcDY() * srcRowBytes;
+ }
+
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+DEFINE_DECODER_CREATOR(ASTCImageDecoder);
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static bool is_astc(SkStreamRewindable* stream) {
+ // Read the ASTC header and make sure it's valid.
+ uint32_t magic;
+ if (stream->read((void*)&magic, 4) != 4) {
+ return false;
+ }
+
+ return kASTCMagicNumber == SkEndian_SwapLE32(magic);
+}
+
+static SkImageDecoder* sk_libastc_dfactory(SkStreamRewindable* stream) {
+ if (is_astc(stream)) {
+ return SkNEW(SkASTCImageDecoder);
+ }
+ return NULL;
+}
+
+static SkImageDecoder_DecodeReg gReg(sk_libastc_dfactory);
+
+static SkImageDecoder::Format get_format_astc(SkStreamRewindable* stream) {
+ if (is_astc(stream)) {
+ return SkImageDecoder::kASTC_Format;
+ }
+ return SkImageDecoder::kUnknown_Format;
+}
+
+static SkImageDecoder_FormatReg gFormatReg(get_format_astc);
diff --git a/src/utils/SkTextureCompressor.cpp b/src/utils/SkTextureCompressor.cpp
index 4ced9a0b57..0dfc229193 100644
--- a/src/utils/SkTextureCompressor.cpp
+++ b/src/utils/SkTextureCompressor.cpp
@@ -45,24 +45,31 @@ void GetBlockDimensions(Format format, int* dimX, int* dimY, bool matchSpec) {
}
// No specialized arguments, return the dimensions as they are in the spec.
- switch(format) {
- // These formats are 64 bits per 4x4 block.
- default:
- SkDEBUGFAIL("Unknown compression format!");
- // fall through
- case kLATC_Format:
- case kR11_EAC_Format:
- case kETC1_Format:
- *dimX = 4;
- *dimY = 4;
- break;
-
- // This format is 12x12 blocks to 128 bits.
- case kASTC_12x12_Format:
- *dimX = 12;
- *dimY = 12;
- break;
- }
+ static const struct FormatDimensions {
+ const int fBlockSizeX;
+ const int fBlockSizeY;
+ } kFormatDimensions[kFormatCnt] = {
+ { 4, 4 }, // kLATC_Format
+ { 4, 4 }, // kR11_EAC_Format
+ { 4, 4 }, // kETC1_Format
+ { 4, 4 }, // kASTC_4x4_Format
+ { 5, 4 }, // kASTC_5x4_Format
+ { 5, 5 }, // kASTC_5x5_Format
+ { 6, 5 }, // kASTC_6x5_Format
+ { 6, 6 }, // kASTC_6x6_Format
+ { 8, 5 }, // kASTC_8x5_Format
+ { 8, 6 }, // kASTC_8x6_Format
+ { 8, 8 }, // kASTC_8x8_Format
+ { 10, 5 }, // kASTC_10x5_Format
+ { 10, 6 }, // kASTC_10x6_Format
+ { 10, 8 }, // kASTC_10x8_Format
+ { 10, 10 }, // kASTC_10x10_Format
+ { 12, 10 }, // kASTC_12x10_Format
+ { 12, 12 }, // kASTC_12x12_Format
+ };
+
+ *dimX = kFormatDimensions[format].fBlockSizeX;
+ *dimY = kFormatDimensions[format].fBlockSizeY;
}
int GetCompressedDataSize(Format fmt, int width, int height) {
@@ -79,7 +86,20 @@ int GetCompressedDataSize(Format fmt, int width, int height) {
encodedBlockSize = 8;
break;
- // This format is 12x12 blocks to 128 bits.
+ // This format is 128 bits.
+ case kASTC_4x4_Format:
+ case kASTC_5x4_Format:
+ case kASTC_5x5_Format:
+ case kASTC_6x5_Format:
+ case kASTC_6x6_Format:
+ case kASTC_8x5_Format:
+ case kASTC_8x6_Format:
+ case kASTC_8x8_Format:
+ case kASTC_10x5_Format:
+ case kASTC_10x6_Format:
+ case kASTC_10x8_Format:
+ case kASTC_10x10_Format:
+ case kASTC_12x10_Format:
case kASTC_12x12_Format:
encodedBlockSize = 16;
break;
@@ -214,9 +234,23 @@ bool DecompressBufferFromFormat(uint8_t* dst, int dstRowBytes, const uint8_t* sr
case kETC1_Format:
return 0 == etc1_decode_image(src, dst, width, height, 3, dstRowBytes);
#endif
+
+ case kASTC_4x4_Format:
+ case kASTC_5x4_Format:
+ case kASTC_5x5_Format:
+ case kASTC_6x5_Format:
+ case kASTC_6x6_Format:
+ case kASTC_8x5_Format:
+ case kASTC_8x6_Format:
+ case kASTC_8x8_Format:
+ case kASTC_10x5_Format:
+ case kASTC_10x6_Format:
+ case kASTC_10x8_Format:
+ case kASTC_10x10_Format:
+ case kASTC_12x10_Format:
case kASTC_12x12_Format:
- // TODO(krajcevski) .. right now just fall through and return false.
- return false;
+ DecompressASTC(dst, dstRowBytes, src, width, height, dimX, dimY);
+ return true;
default:
// Do nothing...
diff --git a/src/utils/SkTextureCompressor.h b/src/utils/SkTextureCompressor.h
index d82bf07a1e..d5c1d2557e 100644
--- a/src/utils/SkTextureCompressor.h
+++ b/src/utils/SkTextureCompressor.h
@@ -30,6 +30,19 @@ namespace SkTextureCompressor {
// 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
diff --git a/src/utils/SkTextureCompressor_ASTC.cpp b/src/utils/SkTextureCompressor_ASTC.cpp
index 25d87fd28e..029f7f2426 100644
--- a/src/utils/SkTextureCompressor_ASTC.cpp
+++ b/src/utils/SkTextureCompressor_ASTC.cpp
@@ -793,7 +793,11 @@ static bool decode_integer_sequence(
endBlockBit = endBit;
}
- decode_trit_block(dst, nBits, read_astc_bits(src, startBit, endBlockBit));
+ // Trit blocks are three values large.
+ int trits[5];
+ decode_trit_block(trits, nBits, read_astc_bits(src, startBit, endBlockBit));
+ memcpy(dst, trits, SkMin32(nVals, 5)*sizeof(int));
+
dst += 5;
nVals -= 5;
startBit = endBlockBit;
@@ -806,7 +810,11 @@ static bool decode_integer_sequence(
endBlockBit = endBit;
}
- decode_quint_block(dst, nBits, read_astc_bits(src, startBit, endBlockBit));
+ // Quint blocks are three values large
+ int quints[3];
+ decode_quint_block(quints, nBits, read_astc_bits(src, startBit, endBlockBit));
+ memcpy(dst, quints, SkMin32(nVals, 3)*sizeof(int));
+
dst += 3;
nVals -= 3;
startBit = endBlockBit;
@@ -1708,7 +1716,8 @@ struct ASTCDecompressionData {
// The rest of the CEM config will be between the dual plane bit selector
// and the texel weight grid.
const int lowCEM = static_cast<int>(read_astc_bits(fBlock, 23, 29));
- SkASSERT(lastWeight - dualPlaneBitLoc > 31);
+ SkASSERT(lastWeight >= dualPlaneBitLoc);
+ SkASSERT(lastWeight - dualPlaneBitLoc < 31);
int fullCEM = static_cast<int>(read_astc_bits(fBlock, dualPlaneBitLoc, lastWeight));
// Attach the config at the end of the weight grid to the CEM values
diff --git a/tests/ImageDecodingTest.cpp b/tests/ImageDecodingTest.cpp
index 5e63611348..8838e75566 100644
--- a/tests/ImageDecodingTest.cpp
+++ b/tests/ImageDecodingTest.cpp
@@ -55,9 +55,10 @@ static bool skip_image_format(SkImageDecoder::Format format) {
// decoders do not, so skip them as well.
case SkImageDecoder::kICO_Format:
case SkImageDecoder::kBMP_Format:
- // KTX is a Texture format so it's not particularly clear how to
- // decode the alpha from it.
+ // KTX and ASTC are texture formats so it's not particularly clear how to
+ // decode the alpha from them.
case SkImageDecoder::kKTX_Format:
+ case SkImageDecoder::kASTC_Format:
// The rest of these are opaque.
case SkImageDecoder::kPKM_Format:
case SkImageDecoder::kWBMP_Format:
diff --git a/tests/TextureCompressionTest.cpp b/tests/TextureCompressionTest.cpp
index 8694389fe7..da7a87bd41 100644
--- a/tests/TextureCompressionTest.cpp
+++ b/tests/TextureCompressionTest.cpp
@@ -12,6 +12,32 @@
#include "SkTextureCompressor.h"
#include "Test.h"
+// TODO: Create separate tests for RGB and RGBA data once
+// ASTC and ETC1 decompression is implemented.
+
+static bool decompresses_a8(SkTextureCompressor::Format fmt) {
+ switch (fmt) {
+ case SkTextureCompressor::kLATC_Format:
+ case SkTextureCompressor::kR11_EAC_Format:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool compresses_a8(SkTextureCompressor::Format fmt) {
+ switch (fmt) {
+ case SkTextureCompressor::kLATC_Format:
+ case SkTextureCompressor::kR11_EAC_Format:
+ case SkTextureCompressor::kASTC_12x12_Format:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
/**
* Make sure that we properly fail when we don't have multiple of four image dimensions.
*/
@@ -38,6 +64,9 @@ DEF_TEST(CompressAlphaFailDimensions, reporter) {
for (int i = 0; i < SkTextureCompressor::kFormatCnt; ++i) {
const SkTextureCompressor::Format fmt = static_cast<SkTextureCompressor::Format>(i);
+ if (!compresses_a8(fmt)) {
+ continue;
+ }
SkAutoDataUnref data(SkTextureCompressor::CompressBitmapToFormat(bitmap, fmt));
REPORTER_ASSERT(reporter, NULL == data);
}
@@ -69,6 +98,9 @@ DEF_TEST(CompressAlphaFailColorType, reporter) {
for (int i = 0; i < SkTextureCompressor::kFormatCnt; ++i) {
const SkTextureCompressor::Format fmt = static_cast<SkTextureCompressor::Format>(i);
+ if (!compresses_a8(fmt)) {
+ continue;
+ }
SkAutoDataUnref data(SkTextureCompressor::CompressBitmapToFormat(bitmap, fmt));
REPORTER_ASSERT(reporter, NULL == data);
}
@@ -134,10 +166,7 @@ DEF_TEST(CompressCheckerboard, reporter) {
// Ignore formats for RGBA data, since the decompressed buffer
// won't match the size and contents of the original.
- // TODO: Create separate tests for RGB and RGBA data once
- // ASTC and ETC1 decompression is implemented.
- if (SkTextureCompressor::kASTC_12x12_Format == fmt ||
- SkTextureCompressor::kETC1_Format == fmt) {
+ if (!decompresses_a8(fmt) || !compresses_a8(fmt)) {
continue;
}
diff --git a/third_party/ktx/ktx.cpp b/third_party/ktx/ktx.cpp
index ebcc5eb187..d62833fac4 100644
--- a/third_party/ktx/ktx.cpp
+++ b/third_party/ktx/ktx.cpp
@@ -19,15 +19,41 @@
static inline uint32_t compressed_fmt_to_gl_define(SkTextureCompressor::Format fmt) {
static const uint32_t kGLDefineMap[SkTextureCompressor::kFormatCnt] = {
GR_GL_COMPRESSED_LUMINANCE_LATC1, // kLATC_Format
- GR_GL_COMPRESSED_R11, // kR11_EAC_Format
- GR_GL_COMPRESSED_RGB8_ETC1, // kETC1_Format
+ GR_GL_COMPRESSED_R11, // kR11_EAC_Format
+ GR_GL_COMPRESSED_RGB8_ETC1, // 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 == SkTextureCompressor::kLATC_Format);
GR_STATIC_ASSERT(1 == SkTextureCompressor::kR11_EAC_Format);
GR_STATIC_ASSERT(2 == SkTextureCompressor::kETC1_Format);
- GR_STATIC_ASSERT(3 == SkTextureCompressor::kASTC_12x12_Format);
+ GR_STATIC_ASSERT(3 == SkTextureCompressor::kASTC_4x4_Format);
+ GR_STATIC_ASSERT(4 == SkTextureCompressor::kASTC_5x4_Format);
+ GR_STATIC_ASSERT(5 == SkTextureCompressor::kASTC_5x5_Format);
+ GR_STATIC_ASSERT(6 == SkTextureCompressor::kASTC_6x5_Format);
+ GR_STATIC_ASSERT(7 == SkTextureCompressor::kASTC_6x6_Format);
+ GR_STATIC_ASSERT(8 == SkTextureCompressor::kASTC_8x5_Format);
+ GR_STATIC_ASSERT(9 == SkTextureCompressor::kASTC_8x6_Format);
+ GR_STATIC_ASSERT(10 == SkTextureCompressor::kASTC_8x8_Format);
+ GR_STATIC_ASSERT(11 == SkTextureCompressor::kASTC_10x5_Format);
+ GR_STATIC_ASSERT(12 == SkTextureCompressor::kASTC_10x6_Format);
+ GR_STATIC_ASSERT(13 == SkTextureCompressor::kASTC_10x8_Format);
+ GR_STATIC_ASSERT(14 == SkTextureCompressor::kASTC_10x10_Format);
+ GR_STATIC_ASSERT(15 == SkTextureCompressor::kASTC_12x10_Format);
+ GR_STATIC_ASSERT(16 == SkTextureCompressor::kASTC_12x12_Format);
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kGLDefineMap) == SkTextureCompressor::kFormatCnt);
return kGLDefineMap[fmt];