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