195b1b3d82d227141647777d83324aa570b530096krajcevski/* 295b1b3d82d227141647777d83324aa570b530096krajcevski * Copyright 2014 Google Inc. 395b1b3d82d227141647777d83324aa570b530096krajcevski * 495b1b3d82d227141647777d83324aa570b530096krajcevski * Use of this source code is governed by a BSD-style license that can be 595b1b3d82d227141647777d83324aa570b530096krajcevski * found in the LICENSE file. 695b1b3d82d227141647777d83324aa570b530096krajcevski */ 795b1b3d82d227141647777d83324aa570b530096krajcevski 895b1b3d82d227141647777d83324aa570b530096krajcevski#include "SkEndian.h" 995b1b3d82d227141647777d83324aa570b530096krajcevski#include "SkColorPriv.h" 1095b1b3d82d227141647777d83324aa570b530096krajcevski#include "SkImageDecoder.h" 1195b1b3d82d227141647777d83324aa570b530096krajcevski#include "SkScaledBitmapSampler.h" 1295b1b3d82d227141647777d83324aa570b530096krajcevski#include "SkStream.h" 1395b1b3d82d227141647777d83324aa570b530096krajcevski#include "SkStreamPriv.h" 1495b1b3d82d227141647777d83324aa570b530096krajcevski#include "SkTypes.h" 1595b1b3d82d227141647777d83324aa570b530096krajcevski 1695b1b3d82d227141647777d83324aa570b530096krajcevski#include "SkTextureCompressor.h" 1795b1b3d82d227141647777d83324aa570b530096krajcevski 1895b1b3d82d227141647777d83324aa570b530096krajcevskiclass SkASTCImageDecoder : public SkImageDecoder { 1995b1b3d82d227141647777d83324aa570b530096krajcevskipublic: 2095b1b3d82d227141647777d83324aa570b530096krajcevski SkASTCImageDecoder() { } 2195b1b3d82d227141647777d83324aa570b530096krajcevski 2295b1b3d82d227141647777d83324aa570b530096krajcevski virtual Format getFormat() const SK_OVERRIDE { 2395b1b3d82d227141647777d83324aa570b530096krajcevski return kASTC_Format; 2495b1b3d82d227141647777d83324aa570b530096krajcevski } 2595b1b3d82d227141647777d83324aa570b530096krajcevski 2695b1b3d82d227141647777d83324aa570b530096krajcevskiprotected: 2795b1b3d82d227141647777d83324aa570b530096krajcevski virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; 2895b1b3d82d227141647777d83324aa570b530096krajcevski 2995b1b3d82d227141647777d83324aa570b530096krajcevskiprivate: 3095b1b3d82d227141647777d83324aa570b530096krajcevski typedef SkImageDecoder INHERITED; 3195b1b3d82d227141647777d83324aa570b530096krajcevski}; 3295b1b3d82d227141647777d83324aa570b530096krajcevski 3395b1b3d82d227141647777d83324aa570b530096krajcevski///////////////////////////////////////////////////////////////////////////////////////// 3495b1b3d82d227141647777d83324aa570b530096krajcevski 3595b1b3d82d227141647777d83324aa570b530096krajcevskistatic const uint32_t kASTCMagicNumber = 0x5CA1AB13; 3695b1b3d82d227141647777d83324aa570b530096krajcevski 3795b1b3d82d227141647777d83324aa570b530096krajcevskistatic inline int read_24bit(const uint8_t* buf) { 3895b1b3d82d227141647777d83324aa570b530096krajcevski // Assume everything is little endian... 3995b1b3d82d227141647777d83324aa570b530096krajcevski return 4095b1b3d82d227141647777d83324aa570b530096krajcevski static_cast<int>(buf[0]) | 4195b1b3d82d227141647777d83324aa570b530096krajcevski (static_cast<int>(buf[1]) << 8) | 4295b1b3d82d227141647777d83324aa570b530096krajcevski (static_cast<int>(buf[2]) << 16); 4395b1b3d82d227141647777d83324aa570b530096krajcevski} 4495b1b3d82d227141647777d83324aa570b530096krajcevski 4595b1b3d82d227141647777d83324aa570b530096krajcevskibool SkASTCImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 4695b1b3d82d227141647777d83324aa570b530096krajcevski SkAutoMalloc autoMal; 4795b1b3d82d227141647777d83324aa570b530096krajcevski const size_t length = SkCopyStreamToStorage(&autoMal, stream); 4895b1b3d82d227141647777d83324aa570b530096krajcevski if (0 == length) { 4995b1b3d82d227141647777d83324aa570b530096krajcevski return false; 5095b1b3d82d227141647777d83324aa570b530096krajcevski } 5195b1b3d82d227141647777d83324aa570b530096krajcevski 5295b1b3d82d227141647777d83324aa570b530096krajcevski unsigned char* buf = (unsigned char*)autoMal.get(); 5395b1b3d82d227141647777d83324aa570b530096krajcevski 5495b1b3d82d227141647777d83324aa570b530096krajcevski // Make sure that the magic header is there... 5595b1b3d82d227141647777d83324aa570b530096krajcevski SkASSERT(SkEndian_SwapLE32(*(reinterpret_cast<uint32_t*>(buf))) == kASTCMagicNumber); 5695b1b3d82d227141647777d83324aa570b530096krajcevski 5795b1b3d82d227141647777d83324aa570b530096krajcevski // Advance past the magic header 5895b1b3d82d227141647777d83324aa570b530096krajcevski buf += 4; 5995b1b3d82d227141647777d83324aa570b530096krajcevski 6095b1b3d82d227141647777d83324aa570b530096krajcevski const int blockDimX = buf[0]; 6195b1b3d82d227141647777d83324aa570b530096krajcevski const int blockDimY = buf[1]; 6295b1b3d82d227141647777d83324aa570b530096krajcevski const int blockDimZ = buf[2]; 6395b1b3d82d227141647777d83324aa570b530096krajcevski 6495b1b3d82d227141647777d83324aa570b530096krajcevski if (1 != blockDimZ) { 6595b1b3d82d227141647777d83324aa570b530096krajcevski // We don't support decoding 3D 6695b1b3d82d227141647777d83324aa570b530096krajcevski return false; 6795b1b3d82d227141647777d83324aa570b530096krajcevski } 6895b1b3d82d227141647777d83324aa570b530096krajcevski 6995b1b3d82d227141647777d83324aa570b530096krajcevski // Choose the proper ASTC format 7095b1b3d82d227141647777d83324aa570b530096krajcevski SkTextureCompressor::Format astcFormat; 7195b1b3d82d227141647777d83324aa570b530096krajcevski if (4 == blockDimX && 4 == blockDimY) { 7295b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_4x4_Format; 7395b1b3d82d227141647777d83324aa570b530096krajcevski } else if (5 == blockDimX && 4 == blockDimY) { 7495b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_5x4_Format; 7595b1b3d82d227141647777d83324aa570b530096krajcevski } else if (5 == blockDimX && 5 == blockDimY) { 7695b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_5x5_Format; 7795b1b3d82d227141647777d83324aa570b530096krajcevski } else if (6 == blockDimX && 5 == blockDimY) { 7895b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_6x5_Format; 7995b1b3d82d227141647777d83324aa570b530096krajcevski } else if (6 == blockDimX && 6 == blockDimY) { 8095b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_6x6_Format; 8195b1b3d82d227141647777d83324aa570b530096krajcevski } else if (8 == blockDimX && 5 == blockDimY) { 8295b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_8x5_Format; 8395b1b3d82d227141647777d83324aa570b530096krajcevski } else if (8 == blockDimX && 6 == blockDimY) { 8495b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_8x6_Format; 8595b1b3d82d227141647777d83324aa570b530096krajcevski } else if (8 == blockDimX && 8 == blockDimY) { 8695b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_8x8_Format; 8795b1b3d82d227141647777d83324aa570b530096krajcevski } else if (10 == blockDimX && 5 == blockDimY) { 8895b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_10x5_Format; 8995b1b3d82d227141647777d83324aa570b530096krajcevski } else if (10 == blockDimX && 6 == blockDimY) { 9095b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_10x6_Format; 9195b1b3d82d227141647777d83324aa570b530096krajcevski } else if (10 == blockDimX && 8 == blockDimY) { 9295b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_10x8_Format; 9395b1b3d82d227141647777d83324aa570b530096krajcevski } else if (10 == blockDimX && 10 == blockDimY) { 9495b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_10x10_Format; 9595b1b3d82d227141647777d83324aa570b530096krajcevski } else if (12 == blockDimX && 10 == blockDimY) { 9695b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_12x10_Format; 9795b1b3d82d227141647777d83324aa570b530096krajcevski } else if (12 == blockDimX && 12 == blockDimY) { 9895b1b3d82d227141647777d83324aa570b530096krajcevski astcFormat = SkTextureCompressor::kASTC_12x12_Format; 9995b1b3d82d227141647777d83324aa570b530096krajcevski } else { 10095b1b3d82d227141647777d83324aa570b530096krajcevski // We don't support any other block dimensions.. 10195b1b3d82d227141647777d83324aa570b530096krajcevski return false; 10295b1b3d82d227141647777d83324aa570b530096krajcevski } 10395b1b3d82d227141647777d83324aa570b530096krajcevski 10495b1b3d82d227141647777d83324aa570b530096krajcevski // Advance buf past the block dimensions 10595b1b3d82d227141647777d83324aa570b530096krajcevski buf += 3; 10695b1b3d82d227141647777d83324aa570b530096krajcevski 10795b1b3d82d227141647777d83324aa570b530096krajcevski // Read the width/height/depth from the buffer... 10895b1b3d82d227141647777d83324aa570b530096krajcevski const int width = read_24bit(buf); 10995b1b3d82d227141647777d83324aa570b530096krajcevski const int height = read_24bit(buf + 3); 11095b1b3d82d227141647777d83324aa570b530096krajcevski const int depth = read_24bit(buf + 6); 11195b1b3d82d227141647777d83324aa570b530096krajcevski 11295b1b3d82d227141647777d83324aa570b530096krajcevski if (1 != depth) { 11395b1b3d82d227141647777d83324aa570b530096krajcevski // We don't support decoding 3D. 11495b1b3d82d227141647777d83324aa570b530096krajcevski return false; 11595b1b3d82d227141647777d83324aa570b530096krajcevski } 11695b1b3d82d227141647777d83324aa570b530096krajcevski 11795b1b3d82d227141647777d83324aa570b530096krajcevski // Advance the buffer past the image dimensions 11895b1b3d82d227141647777d83324aa570b530096krajcevski buf += 9; 11995b1b3d82d227141647777d83324aa570b530096krajcevski 12095b1b3d82d227141647777d83324aa570b530096krajcevski#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 12195b1b3d82d227141647777d83324aa570b530096krajcevski // should we allow the Chooser (if present) to pick a config for us??? 12295b1b3d82d227141647777d83324aa570b530096krajcevski if (!this->chooseFromOneChoice(kN32_SkColorType, width, height)) { 12395b1b3d82d227141647777d83324aa570b530096krajcevski return false; 12495b1b3d82d227141647777d83324aa570b530096krajcevski } 12595b1b3d82d227141647777d83324aa570b530096krajcevski#endif 12695b1b3d82d227141647777d83324aa570b530096krajcevski 12795b1b3d82d227141647777d83324aa570b530096krajcevski // Setup the sampler... 12895b1b3d82d227141647777d83324aa570b530096krajcevski SkScaledBitmapSampler sampler(width, height, this->getSampleSize()); 12995b1b3d82d227141647777d83324aa570b530096krajcevski 13095b1b3d82d227141647777d83324aa570b530096krajcevski // Determine the alpha of the bitmap... 13195b1b3d82d227141647777d83324aa570b530096krajcevski SkAlphaType alphaType = kOpaque_SkAlphaType; 13295b1b3d82d227141647777d83324aa570b530096krajcevski if (this->getRequireUnpremultipliedColors()) { 13395b1b3d82d227141647777d83324aa570b530096krajcevski alphaType = kUnpremul_SkAlphaType; 13495b1b3d82d227141647777d83324aa570b530096krajcevski } else { 13595b1b3d82d227141647777d83324aa570b530096krajcevski alphaType = kPremul_SkAlphaType; 13695b1b3d82d227141647777d83324aa570b530096krajcevski } 13795b1b3d82d227141647777d83324aa570b530096krajcevski 13895b1b3d82d227141647777d83324aa570b530096krajcevski // Set the config... 13995b1b3d82d227141647777d83324aa570b530096krajcevski bm->setInfo(SkImageInfo::MakeN32(sampler.scaledWidth(), sampler.scaledHeight(), alphaType)); 14095b1b3d82d227141647777d83324aa570b530096krajcevski 14195b1b3d82d227141647777d83324aa570b530096krajcevski if (SkImageDecoder::kDecodeBounds_Mode == mode) { 14295b1b3d82d227141647777d83324aa570b530096krajcevski return true; 14395b1b3d82d227141647777d83324aa570b530096krajcevski } 14495b1b3d82d227141647777d83324aa570b530096krajcevski 14595b1b3d82d227141647777d83324aa570b530096krajcevski if (!this->allocPixelRef(bm, NULL)) { 14695b1b3d82d227141647777d83324aa570b530096krajcevski return false; 14795b1b3d82d227141647777d83324aa570b530096krajcevski } 14895b1b3d82d227141647777d83324aa570b530096krajcevski 14995b1b3d82d227141647777d83324aa570b530096krajcevski // Lock the pixels, since we're about to write to them... 15095b1b3d82d227141647777d83324aa570b530096krajcevski SkAutoLockPixels alp(*bm); 15195b1b3d82d227141647777d83324aa570b530096krajcevski 15295b1b3d82d227141647777d83324aa570b530096krajcevski if (!sampler.begin(bm, SkScaledBitmapSampler::kRGBA, *this)) { 15395b1b3d82d227141647777d83324aa570b530096krajcevski return false; 15495b1b3d82d227141647777d83324aa570b530096krajcevski } 15595b1b3d82d227141647777d83324aa570b530096krajcevski 15695b1b3d82d227141647777d83324aa570b530096krajcevski // ASTC Data is encoded as RGBA pixels, so we should extract it as such 15795b1b3d82d227141647777d83324aa570b530096krajcevski int nPixels = width * height; 15895b1b3d82d227141647777d83324aa570b530096krajcevski SkAutoMalloc outRGBAData(nPixels * 4); 15995b1b3d82d227141647777d83324aa570b530096krajcevski uint8_t *outRGBADataPtr = reinterpret_cast<uint8_t *>(outRGBAData.get()); 16095b1b3d82d227141647777d83324aa570b530096krajcevski 16195b1b3d82d227141647777d83324aa570b530096krajcevski // Decode ASTC 16295b1b3d82d227141647777d83324aa570b530096krajcevski if (!SkTextureCompressor::DecompressBufferFromFormat( 16395b1b3d82d227141647777d83324aa570b530096krajcevski outRGBADataPtr, width*4, buf, width, height, astcFormat)) { 16495b1b3d82d227141647777d83324aa570b530096krajcevski } 16595b1b3d82d227141647777d83324aa570b530096krajcevski 16695b1b3d82d227141647777d83324aa570b530096krajcevski // Set each of the pixels... 16795b1b3d82d227141647777d83324aa570b530096krajcevski const int srcRowBytes = width * 4; 16895b1b3d82d227141647777d83324aa570b530096krajcevski const int dstHeight = sampler.scaledHeight(); 16995b1b3d82d227141647777d83324aa570b530096krajcevski const uint8_t *srcRow = reinterpret_cast<uint8_t *>(outRGBADataPtr); 17095b1b3d82d227141647777d83324aa570b530096krajcevski srcRow += sampler.srcY0() * srcRowBytes; 17195b1b3d82d227141647777d83324aa570b530096krajcevski for (int y = 0; y < dstHeight; ++y) { 17295b1b3d82d227141647777d83324aa570b530096krajcevski sampler.next(srcRow); 17395b1b3d82d227141647777d83324aa570b530096krajcevski srcRow += sampler.srcDY() * srcRowBytes; 17495b1b3d82d227141647777d83324aa570b530096krajcevski } 17595b1b3d82d227141647777d83324aa570b530096krajcevski 17695b1b3d82d227141647777d83324aa570b530096krajcevski return true; 17795b1b3d82d227141647777d83324aa570b530096krajcevski} 17895b1b3d82d227141647777d83324aa570b530096krajcevski 17995b1b3d82d227141647777d83324aa570b530096krajcevski///////////////////////////////////////////////////////////////////////////////////////// 18095b1b3d82d227141647777d83324aa570b530096krajcevskiDEFINE_DECODER_CREATOR(ASTCImageDecoder); 18195b1b3d82d227141647777d83324aa570b530096krajcevski///////////////////////////////////////////////////////////////////////////////////////// 18295b1b3d82d227141647777d83324aa570b530096krajcevski 18395b1b3d82d227141647777d83324aa570b530096krajcevskistatic bool is_astc(SkStreamRewindable* stream) { 18495b1b3d82d227141647777d83324aa570b530096krajcevski // Read the ASTC header and make sure it's valid. 18595b1b3d82d227141647777d83324aa570b530096krajcevski uint32_t magic; 18695b1b3d82d227141647777d83324aa570b530096krajcevski if (stream->read((void*)&magic, 4) != 4) { 18795b1b3d82d227141647777d83324aa570b530096krajcevski return false; 18895b1b3d82d227141647777d83324aa570b530096krajcevski } 18995b1b3d82d227141647777d83324aa570b530096krajcevski 19095b1b3d82d227141647777d83324aa570b530096krajcevski return kASTCMagicNumber == SkEndian_SwapLE32(magic); 19195b1b3d82d227141647777d83324aa570b530096krajcevski} 19295b1b3d82d227141647777d83324aa570b530096krajcevski 19395b1b3d82d227141647777d83324aa570b530096krajcevskistatic SkImageDecoder* sk_libastc_dfactory(SkStreamRewindable* stream) { 19495b1b3d82d227141647777d83324aa570b530096krajcevski if (is_astc(stream)) { 19595b1b3d82d227141647777d83324aa570b530096krajcevski return SkNEW(SkASTCImageDecoder); 19695b1b3d82d227141647777d83324aa570b530096krajcevski } 19795b1b3d82d227141647777d83324aa570b530096krajcevski return NULL; 19895b1b3d82d227141647777d83324aa570b530096krajcevski} 19995b1b3d82d227141647777d83324aa570b530096krajcevski 20095b1b3d82d227141647777d83324aa570b530096krajcevskistatic SkImageDecoder_DecodeReg gReg(sk_libastc_dfactory); 20195b1b3d82d227141647777d83324aa570b530096krajcevski 20295b1b3d82d227141647777d83324aa570b530096krajcevskistatic SkImageDecoder::Format get_format_astc(SkStreamRewindable* stream) { 20395b1b3d82d227141647777d83324aa570b530096krajcevski if (is_astc(stream)) { 20495b1b3d82d227141647777d83324aa570b530096krajcevski return SkImageDecoder::kASTC_Format; 20595b1b3d82d227141647777d83324aa570b530096krajcevski } 20695b1b3d82d227141647777d83324aa570b530096krajcevski return SkImageDecoder::kUnknown_Format; 20795b1b3d82d227141647777d83324aa570b530096krajcevski} 20895b1b3d82d227141647777d83324aa570b530096krajcevski 20995b1b3d82d227141647777d83324aa570b530096krajcevskistatic SkImageDecoder_FormatReg gFormatReg(get_format_astc); 210