| Index: src/images/SkImageDecoder_ktx.cpp | 
| diff --git a/src/images/SkImageDecoder_ktx.cpp b/src/images/SkImageDecoder_ktx.cpp | 
| index 156674565c0dff6c91adfed7331a02d16d558797..79f0293c2a0de42d9842173b46d61c1507657076 100644 | 
| --- a/src/images/SkImageDecoder_ktx.cpp | 
| +++ b/src/images/SkImageDecoder_ktx.cpp | 
| @@ -6,10 +6,9 @@ | 
| */ | 
|  | 
| #include "SkColorPriv.h" | 
| -#include "SkImageDecoder.h" | 
| +#include "SkImageEncoder.h" | 
| #include "SkImageGenerator.h" | 
| #include "SkPixelRef.h" | 
| -#include "SkScaledBitmapSampler.h" | 
| #include "SkStream.h" | 
| #include "SkStreamPriv.h" | 
| #include "SkTypes.h" | 
| @@ -17,230 +16,14 @@ | 
| #include "ktx.h" | 
| #include "etc1.h" | 
|  | 
| -///////////////////////////////////////////////////////////////////////////////////////// | 
| - | 
| - | 
| -///////////////////////////////////////////////////////////////////////////////////////// | 
| +/////////////////////////////////////////////////////////////////////////////// | 
|  | 
| -// KTX Image decoder | 
| -// --- | 
| +// KTX Image Encoder | 
| +// | 
| // 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. | 
| // | 
| -// This decoder is meant to be used with an SkDiscardablePixelRef so that GPU backends | 
| -// can sniff the data before creating a texture. If they encounter a compressed format | 
| -// that they understand, they can then upload the data directly to the GPU. Otherwise, | 
| -// they will decode the data into a format that Skia supports. | 
| - | 
| -class SkKTXImageDecoder : public SkImageDecoder { | 
| -public: | 
| -    SkKTXImageDecoder() { } | 
| - | 
| -    Format getFormat() const override { | 
| -        return kKTX_Format; | 
| -    } | 
| - | 
| -protected: | 
| -    Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override; | 
| - | 
| -private: | 
| -    typedef SkImageDecoder INHERITED; | 
| -}; | 
| - | 
| -SkImageDecoder::Result SkKTXImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { | 
| -    // TODO: Implement SkStream::copyToData() that's cheap for memory and file streams | 
| -    auto data = SkCopyStreamToData(stream); | 
| -    if (nullptr == data) { | 
| -        return kFailure; | 
| -    } | 
| - | 
| -    SkKTXFile ktxFile(data.get()); | 
| -    if (!ktxFile.valid()) { | 
| -        return kFailure; | 
| -    } | 
| - | 
| -    const unsigned short width = ktxFile.width(); | 
| -    const unsigned short height = ktxFile.height(); | 
| - | 
| -    // Set a flag if our source is premultiplied alpha | 
| -    const SkString premulKey("KTXPremultipliedAlpha"); | 
| -    const bool bSrcIsPremul = ktxFile.getValueForKey(premulKey) == SkString("True"); | 
| - | 
| -    // Setup the sampler... | 
| -    SkScaledBitmapSampler sampler(width, height, this->getSampleSize()); | 
| - | 
| -    // Determine the alpha of the bitmap... | 
| -    SkAlphaType alphaType = kOpaque_SkAlphaType; | 
| -    if (ktxFile.isRGBA8()) { | 
| -        if (this->getRequireUnpremultipliedColors()) { | 
| -            alphaType = kUnpremul_SkAlphaType; | 
| -            // If the client wants unpremul colors and we only have | 
| -            // premul, then we cannot honor their wish. | 
| -            if (bSrcIsPremul) { | 
| -                return kFailure; | 
| -            } | 
| -        } else { | 
| -            alphaType = kPremul_SkAlphaType; | 
| -        } | 
| -    } | 
| - | 
| -    // Search through the compressed formats to see if the KTX file is holding | 
| -    // compressed data | 
| -    bool ktxIsCompressed = false; | 
| -    SkTextureCompressor::Format ktxCompressedFormat; | 
| -    for (int i = 0; i < SkTextureCompressor::kFormatCnt; ++i) { | 
| -        SkTextureCompressor::Format fmt = static_cast<SkTextureCompressor::Format>(i); | 
| -        if (ktxFile.isCompressedFormat(fmt)) { | 
| -            ktxIsCompressed = true; | 
| -            ktxCompressedFormat = fmt; | 
| -            break; | 
| -        } | 
| -    } | 
| - | 
| -    // If the compressed format is a grayscale image, then setup the bitmap properly... | 
| -    bool isCompressedAlpha = ktxIsCompressed && | 
| -        ((SkTextureCompressor::kLATC_Format == ktxCompressedFormat) || | 
| -         (SkTextureCompressor::kR11_EAC_Format == ktxCompressedFormat)); | 
| - | 
| -    // Set the image dimensions and underlying pixel type. | 
| -    if (isCompressedAlpha) { | 
| -        const int w = sampler.scaledWidth(); | 
| -        const int h = sampler.scaledHeight(); | 
| -        bm->setInfo(SkImageInfo::MakeA8(w, h)); | 
| -    } else { | 
| -        const int w = sampler.scaledWidth(); | 
| -        const int h = sampler.scaledHeight(); | 
| -        bm->setInfo(SkImageInfo::MakeN32(w, h, alphaType)); | 
| -    } | 
| - | 
| -    if (SkImageDecoder::kDecodeBounds_Mode == mode) { | 
| -        return kSuccess; | 
| -    } | 
| - | 
| -    // If we've made it this far, then we know how to grok the data. | 
| -    if (!this->allocPixelRef(bm, nullptr)) { | 
| -        return kFailure; | 
| -    } | 
| - | 
| -    // Lock the pixels, since we're about to write to them... | 
| -    SkAutoLockPixels alp(*bm); | 
| - | 
| -    if (isCompressedAlpha) { | 
| -        if (!sampler.begin(bm, SkScaledBitmapSampler::kGray, *this)) { | 
| -            return kFailure; | 
| -        } | 
| - | 
| -        // Alpha data is only a single byte per pixel. | 
| -        int nPixels = width * height; | 
| -        SkAutoMalloc outRGBData(nPixels); | 
| -        uint8_t *outRGBDataPtr = reinterpret_cast<uint8_t *>(outRGBData.get()); | 
| - | 
| -        // Decode the compressed format | 
| -        const uint8_t *buf = reinterpret_cast<const uint8_t *>(ktxFile.pixelData()); | 
| -        if (!SkTextureCompressor::DecompressBufferFromFormat( | 
| -                outRGBDataPtr, width, buf, width, height, ktxCompressedFormat)) { | 
| -            return kFailure; | 
| -        } | 
| - | 
| -        // Set each of the pixels... | 
| -        const int srcRowBytes = width; | 
| -        const int dstHeight = sampler.scaledHeight(); | 
| -        const uint8_t *srcRow = reinterpret_cast<uint8_t *>(outRGBDataPtr); | 
| -        srcRow += sampler.srcY0() * srcRowBytes; | 
| -        for (int y = 0; y < dstHeight; ++y) { | 
| -            sampler.next(srcRow); | 
| -            srcRow += sampler.srcDY() * srcRowBytes; | 
| -        } | 
| - | 
| -        return kSuccess; | 
| - | 
| -    } else if (ktxFile.isCompressedFormat(SkTextureCompressor::kETC1_Format)) { | 
| -        if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) { | 
| -            return kFailure; | 
| -        } | 
| - | 
| -        // ETC1 Data is encoded as RGB pixels, so we should extract it as such | 
| -        int nPixels = width * height; | 
| -        SkAutoMalloc outRGBData(nPixels * 3); | 
| -        uint8_t *outRGBDataPtr = reinterpret_cast<uint8_t *>(outRGBData.get()); | 
| - | 
| -        // Decode ETC1 | 
| -        const uint8_t *buf = reinterpret_cast<const uint8_t *>(ktxFile.pixelData()); | 
| -        if (!SkTextureCompressor::DecompressBufferFromFormat( | 
| -                outRGBDataPtr, width*3, buf, width, height, SkTextureCompressor::kETC1_Format)) { | 
| -            return kFailure; | 
| -        } | 
| - | 
| -        // Set each of the pixels... | 
| -        const int srcRowBytes = width * 3; | 
| -        const int dstHeight = sampler.scaledHeight(); | 
| -        const uint8_t *srcRow = reinterpret_cast<uint8_t *>(outRGBDataPtr); | 
| -        srcRow += sampler.srcY0() * srcRowBytes; | 
| -        for (int y = 0; y < dstHeight; ++y) { | 
| -            sampler.next(srcRow); | 
| -            srcRow += sampler.srcDY() * srcRowBytes; | 
| -        } | 
| - | 
| -        return kSuccess; | 
| - | 
| -    } else if (ktxFile.isRGB8()) { | 
| - | 
| -        // Uncompressed RGB data (without alpha) | 
| -        if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) { | 
| -            return kFailure; | 
| -        } | 
| - | 
| -        // Just need to read RGB pixels | 
| -        const int srcRowBytes = width * 3; | 
| -        const int dstHeight = sampler.scaledHeight(); | 
| -        const uint8_t *srcRow = reinterpret_cast<const uint8_t *>(ktxFile.pixelData()); | 
| -        srcRow += sampler.srcY0() * srcRowBytes; | 
| -        for (int y = 0; y < dstHeight; ++y) { | 
| -            sampler.next(srcRow); | 
| -            srcRow += sampler.srcDY() * srcRowBytes; | 
| -        } | 
| - | 
| -        return kSuccess; | 
| - | 
| -    } else if (ktxFile.isRGBA8()) { | 
| - | 
| -        // Uncompressed RGBA data | 
| - | 
| -        // If we know that the image contains premultiplied alpha, then | 
| -        // we need to turn off the premultiplier | 
| -        SkScaledBitmapSampler::Options opts (*this); | 
| -        if (bSrcIsPremul) { | 
| -            SkASSERT(bm->alphaType() == kPremul_SkAlphaType); | 
| -            SkASSERT(!this->getRequireUnpremultipliedColors()); | 
| - | 
| -            opts.fPremultiplyAlpha = false; | 
| -        } | 
| - | 
| -        if (!sampler.begin(bm, SkScaledBitmapSampler::kRGBA, opts)) { | 
| -            return kFailure; | 
| -        } | 
| - | 
| -        // Just need to read RGBA pixels | 
| -        const int srcRowBytes = width * 4; | 
| -        const int dstHeight = sampler.scaledHeight(); | 
| -        const uint8_t *srcRow = reinterpret_cast<const uint8_t *>(ktxFile.pixelData()); | 
| -        srcRow += sampler.srcY0() * srcRowBytes; | 
| -        for (int y = 0; y < dstHeight; ++y) { | 
| -            sampler.next(srcRow); | 
| -            srcRow += sampler.srcDY() * srcRowBytes; | 
| -        } | 
| - | 
| -        return kSuccess; | 
| -    } | 
| - | 
| -    return kFailure; | 
| -} | 
| - | 
| -/////////////////////////////////////////////////////////////////////////////// | 
| - | 
| -// KTX Image Encoder | 
| -// | 
| // This encoder takes a best guess at how to encode the bitmap passed to it. If | 
| // there is an installed discardable pixel ref with existing PKM data, then we | 
| // will repurpose the existing ETC1 data into a KTX file. If the data contains | 
| @@ -304,28 +87,11 @@ bool SkKTXImageEncoder::encodePKM(SkWStream* stream, const SkData *data) { | 
| } | 
|  | 
| ///////////////////////////////////////////////////////////////////////////////////////// | 
| -DEFINE_DECODER_CREATOR(KTXImageDecoder); | 
| DEFINE_ENCODER_CREATOR(KTXImageEncoder); | 
| ///////////////////////////////////////////////////////////////////////////////////////// | 
|  | 
| -static SkImageDecoder* sk_libktx_dfactory(SkStreamRewindable* stream) { | 
| -    if (SkKTXFile::is_ktx(stream)) { | 
| -        return new SkKTXImageDecoder; | 
| -    } | 
| -    return nullptr; | 
| -} | 
| - | 
| -static SkImageDecoder::Format get_format_ktx(SkStreamRewindable* stream) { | 
| -    if (SkKTXFile::is_ktx(stream)) { | 
| -        return SkImageDecoder::kKTX_Format; | 
| -    } | 
| -    return SkImageDecoder::kUnknown_Format; | 
| -} | 
| - | 
| SkImageEncoder* sk_libktx_efactory(SkImageEncoder::Type t) { | 
| return (SkImageEncoder::kKTX_Type == t) ? new SkKTXImageEncoder : nullptr; | 
| } | 
|  | 
| -static SkImageDecoder_DecodeReg gReg(sk_libktx_dfactory); | 
| -static SkImageDecoder_FormatReg gFormatReg(get_format_ktx); | 
| static SkImageEncoder_EncodeReg gEReg(sk_libktx_efactory); | 
|  |