1ae614409e4cff083c070face78cc349153d0b932krajcevski/*
2ae614409e4cff083c070face78cc349153d0b932krajcevski * Copyright 2014 Google Inc.
3ae614409e4cff083c070face78cc349153d0b932krajcevski *
4ae614409e4cff083c070face78cc349153d0b932krajcevski * Use of this source code is governed by a BSD-style license that can be
5ae614409e4cff083c070face78cc349153d0b932krajcevski * found in the LICENSE file.
6ae614409e4cff083c070face78cc349153d0b932krajcevski */
7ae614409e4cff083c070face78cc349153d0b932krajcevski
8ae614409e4cff083c070face78cc349153d0b932krajcevski#ifndef SkTextureCompressor_DEFINED
9ae614409e4cff083c070face78cc349153d0b932krajcevski#define SkTextureCompressor_DEFINED
10ae614409e4cff083c070face78cc349153d0b932krajcevski
11b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski#include "SkBitmapProcShader.h"
12eecc35f988662f4fa82693ad36e908d637a7d3c1krajcevski#include "SkImageInfo.h"
13eecc35f988662f4fa82693ad36e908d637a7d3c1krajcevski
14ae614409e4cff083c070face78cc349153d0b932krajcevskiclass SkBitmap;
1540a1e11ebebe81586f3fec96408fdfd4b51123d2krajcevskiclass SkBlitter;
16ae614409e4cff083c070face78cc349153d0b932krajcevskiclass SkData;
17ae614409e4cff083c070face78cc349153d0b932krajcevski
18ae614409e4cff083c070face78cc349153d0b932krajcevskinamespace SkTextureCompressor {
19ae614409e4cff083c070face78cc349153d0b932krajcevski    // Various texture compression formats that we support.
20ae614409e4cff083c070face78cc349153d0b932krajcevski    enum Format {
21f3d15dc13abb825946ccad514412699828d5d709krajcevski        // Alpha only formats.
22e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski        kLATC_Format,       // 4x4 blocks, (de)compresses A8
23e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski        kR11_EAC_Format,    // 4x4 blocks, (de)compresses A8
24e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski
25e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski        // RGB only formats
26e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski        kETC1_Format,       // 4x4 blocks, compresses RGB 565, decompresses 8-bit RGB
27e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski                            //    NOTE: ETC1 supports 8-bit RGB compression, but we
28e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski                            //    currently don't have any RGB8 SkColorTypes. We could
29e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski                            //    support 8-bit RGBA but we would have to preprocess the
30e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski                            //    bitmap to insert alphas.
31e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski
32e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski        // Multi-purpose formats
3395b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_4x4_Format,   // 4x4 blocks, no compression, decompresses RGBA
3495b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_5x4_Format,   // 5x4 blocks, no compression, decompresses RGBA
3595b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_5x5_Format,   // 5x5 blocks, no compression, decompresses RGBA
3695b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_6x5_Format,   // 6x5 blocks, no compression, decompresses RGBA
3795b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_6x6_Format,   // 6x6 blocks, no compression, decompresses RGBA
3895b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_8x5_Format,   // 8x5 blocks, no compression, decompresses RGBA
3995b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_8x6_Format,   // 8x6 blocks, no compression, decompresses RGBA
4095b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_8x8_Format,   // 8x8 blocks, no compression, decompresses RGBA
4195b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_10x5_Format,  // 10x5 blocks, no compression, decompresses RGBA
4295b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_10x6_Format,  // 10x6 blocks, no compression, decompresses RGBA
4395b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_10x8_Format,  // 10x8 blocks, no compression, decompresses RGBA
4495b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_10x10_Format, // 10x10 blocks, no compression, decompresses RGBA
4595b1b3d82d227141647777d83324aa570b530096krajcevski        kASTC_12x10_Format, // 12x10 blocks, no compression, decompresses RGBA
46e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski        kASTC_12x12_Format, // 12x12 blocks, compresses A8, decompresses RGBA
47ae614409e4cff083c070face78cc349153d0b932krajcevski
48b2ef181ed614d1a5772367a8cd7ab77aa015ae29krajcevski        kLast_Format = kASTC_12x12_Format
49ae614409e4cff083c070face78cc349153d0b932krajcevski    };
50ae614409e4cff083c070face78cc349153d0b932krajcevski    static const int kFormatCnt = kLast_Format + 1;
51ae614409e4cff083c070face78cc349153d0b932krajcevski
526c354881b63935626a0700366937530d38b8b1e8krajcevski    // Returns the size of the compressed data given the width, height, and
536c354881b63935626a0700366937530d38b8b1e8krajcevski    // desired compression format. If the width and height are not an appropriate
546c354881b63935626a0700366937530d38b8b1e8krajcevski    // multiple of the block size, then this function returns an error (-1).
556c354881b63935626a0700366937530d38b8b1e8krajcevski    int GetCompressedDataSize(Format fmt, int width, int height);
566c354881b63935626a0700366937530d38b8b1e8krajcevski
57ae614409e4cff083c070face78cc349153d0b932krajcevski    // Returns an SkData holding a blob of compressed data that corresponds
58ae614409e4cff083c070face78cc349153d0b932krajcevski    // to the bitmap. If the bitmap colorType cannot be compressed using the
59ae614409e4cff083c070face78cc349153d0b932krajcevski    // associated format, then we return NULL. The caller is responsible for
60ae614409e4cff083c070face78cc349153d0b932krajcevski    // calling unref() on the returned data.
61ae614409e4cff083c070face78cc349153d0b932krajcevski    SkData* CompressBitmapToFormat(const SkBitmap& bitmap, Format format);
62eecc35f988662f4fa82693ad36e908d637a7d3c1krajcevski
63eecc35f988662f4fa82693ad36e908d637a7d3c1krajcevski    // Compresses the given src data into dst. The src data is assumed to be
64eecc35f988662f4fa82693ad36e908d637a7d3c1krajcevski    // large enough to hold width*height pixels. The dst data is expected to
65eecc35f988662f4fa82693ad36e908d637a7d3c1krajcevski    // be large enough to hold the compressed data according to the format.
66eecc35f988662f4fa82693ad36e908d637a7d3c1krajcevski    bool CompressBufferToFormat(uint8_t* dst, const uint8_t* src, SkColorType srcColorType,
67630598cbb87edda47aa26bc7b7f93865b34cd8dekrajcevski                                int width, int height, int rowBytes, Format format,
68630598cbb87edda47aa26bc7b7f93865b34cd8dekrajcevski                                bool opt = true /* Use optimization if available */);
69630598cbb87edda47aa26bc7b7f93865b34cd8dekrajcevski
704ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // Decompresses the given src data from the format specified into the
714ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // destination buffer. The width and height of the data passed corresponds
724ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // to the width and height of the uncompressed image. The destination buffer (dst)
734ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // is assumed to be large enough to hold the entire decompressed image. The
74e90c900ed7b2be3d0f9c7134d7fcd5f820b0464ckrajcevski    // decompressed image colors are determined based on the passed format.
754ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    //
764ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // Note, CompressBufferToFormat compresses A8 data into ASTC. However,
774ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // general ASTC data encodes RGBA data, so that is what the decompressor
784ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // operates on.
794ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    //
804ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // Returns true if successfully decompresses the src data.
814ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    bool DecompressBufferFromFormat(uint8_t* dst, int dstRowBytes, const uint8_t* src,
824ad76e35111585f4da662d54943f23792dd1e0aekrajcevski                                    int width, int height, Format format);
834ad76e35111585f4da662d54943f23792dd1e0aekrajcevski
84630598cbb87edda47aa26bc7b7f93865b34cd8dekrajcevski    // This typedef defines what the nominal aspects of a compression function
85630598cbb87edda47aa26bc7b7f93865b34cd8dekrajcevski    // are. The typedef is not meant to be used by clients of the API, but rather
86630598cbb87edda47aa26bc7b7f93865b34cd8dekrajcevski    // allows SIMD optimized compression functions to be implemented.
87630598cbb87edda47aa26bc7b7f93865b34cd8dekrajcevski    typedef bool (*CompressionProc)(uint8_t* dst, const uint8_t* src,
88630598cbb87edda47aa26bc7b7f93865b34cd8dekrajcevski                                    int width, int height, int rowBytes);
89ad1df153a16b7723d2d4afd13627919fc3ee87cekrajcevski
90b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski    // Returns true if there exists a blitter for the specified format.
91b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski    inline bool ExistsBlitterForFormat(Format format) {
92b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski        switch (format) {
93b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski            case kLATC_Format:
94b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski            case kR11_EAC_Format:
95b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski            case kASTC_12x12_Format:
96b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski                return true;
97b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski
98b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski            default:
99b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski                return false;
100b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski        }
101b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski    }
102b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski
1036c354881b63935626a0700366937530d38b8b1e8krajcevski    // Returns the blitter for the given compression format. Note, the blitter
1046c354881b63935626a0700366937530d38b8b1e8krajcevski    // is intended to be used with the proper input. I.e. if you try to blit
1056c354881b63935626a0700366937530d38b8b1e8krajcevski    // RGB source data into an R11 EAC texture, you're gonna have a bad time.
1066c354881b63935626a0700366937530d38b8b1e8krajcevski    SkBlitter* CreateBlitterForFormat(int width, int height, void* compressedBuffer,
107b8ccc2f6d258a8466f79fc418e9e0a55aeaf58cekrajcevski                                      SkTBlitterAllocator *allocator, Format format);
10825a67bcb7ac70d3077e91126c4b8924a53557a38krajcevski
10925a67bcb7ac70d3077e91126c4b8924a53557a38krajcevski    // Returns the desired dimensions of the block size for the given format. These dimensions
1104ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // don't necessarily correspond to the specification's dimensions, since there may
1114ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // be specialized algorithms that operate on multiple blocks at once. If the
1124ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // flag 'matchSpec' is true, then the actual dimensions from the specification are
1134ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // returned. If the flag is false, then these dimensions reflect the appropriate operable
1144ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    // dimensions of the compression functions.
1154ad76e35111585f4da662d54943f23792dd1e0aekrajcevski    void GetBlockDimensions(Format format, int* dimX, int* dimY, bool matchSpec = false);
116ae614409e4cff083c070face78cc349153d0b932krajcevski}
117ae614409e4cff083c070face78cc349153d0b932krajcevski
118ae614409e4cff083c070face78cc349153d0b932krajcevski#endif
119