2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkTextureCompressor.h"
9 #include "SkTextureCompressor_ASTC.h"
10 #include "SkTextureCompressor_LATC.h"
11 #include "SkTextureCompressor_R11EAC.h"
14 #include "SkBitmapProcShader.h"
18 #include "SkTextureCompression_opts.h"
20 #ifndef SK_IGNORE_ETC1_SUPPORT
24 // Convert ETC1 functions to our function signatures
25 static bool compress_etc1_565(uint8_t* dst, const uint8_t* src,
26 int width, int height, int rowBytes) {
27 #ifndef SK_IGNORE_ETC1_SUPPORT
28 return 0 == etc1_encode_image(src, width, height, 2, rowBytes, dst);
34 ////////////////////////////////////////////////////////////////////////////////
36 namespace SkTextureCompressor {
38 void GetBlockDimensions(Format format, int* dimX, int* dimY, bool matchSpec) {
39 if (NULL == dimX || NULL == dimY) {
43 if (!matchSpec && SkTextureCompressorGetPlatformDims(format, dimX, dimY)) {
47 // No specialized arguments, return the dimensions as they are in the spec.
48 static const struct FormatDimensions {
49 const int fBlockSizeX;
50 const int fBlockSizeY;
51 } kFormatDimensions[kFormatCnt] = {
52 { 4, 4 }, // kLATC_Format
53 { 4, 4 }, // kR11_EAC_Format
54 { 4, 4 }, // kETC1_Format
55 { 4, 4 }, // kASTC_4x4_Format
56 { 5, 4 }, // kASTC_5x4_Format
57 { 5, 5 }, // kASTC_5x5_Format
58 { 6, 5 }, // kASTC_6x5_Format
59 { 6, 6 }, // kASTC_6x6_Format
60 { 8, 5 }, // kASTC_8x5_Format
61 { 8, 6 }, // kASTC_8x6_Format
62 { 8, 8 }, // kASTC_8x8_Format
63 { 10, 5 }, // kASTC_10x5_Format
64 { 10, 6 }, // kASTC_10x6_Format
65 { 10, 8 }, // kASTC_10x8_Format
66 { 10, 10 }, // kASTC_10x10_Format
67 { 12, 10 }, // kASTC_12x10_Format
68 { 12, 12 }, // kASTC_12x12_Format
71 *dimX = kFormatDimensions[format].fBlockSizeX;
72 *dimY = kFormatDimensions[format].fBlockSizeY;
75 int GetCompressedDataSize(Format fmt, int width, int height) {
77 GetBlockDimensions(fmt, &dimX, &dimY, true);
79 int encodedBlockSize = 0;
82 // These formats are 64 bits per 4x4 block.
89 // This format is 128 bits.
90 case kASTC_4x4_Format:
91 case kASTC_5x4_Format:
92 case kASTC_5x5_Format:
93 case kASTC_6x5_Format:
94 case kASTC_6x6_Format:
95 case kASTC_8x5_Format:
96 case kASTC_8x6_Format:
97 case kASTC_8x8_Format:
98 case kASTC_10x5_Format:
99 case kASTC_10x6_Format:
100 case kASTC_10x8_Format:
101 case kASTC_10x10_Format:
102 case kASTC_12x10_Format:
103 case kASTC_12x12_Format:
104 encodedBlockSize = 16;
108 SkFAIL("Unknown compressed format!");
112 if(((width % dimX) == 0) && ((height % dimY) == 0)) {
113 const int blocksX = width / dimX;
114 const int blocksY = height / dimY;
116 return blocksX * blocksY * encodedBlockSize;
122 bool CompressBufferToFormat(uint8_t* dst, const uint8_t* src, SkColorType srcColorType,
123 int width, int height, int rowBytes, Format format, bool opt) {
124 CompressionProc proc = NULL;
126 proc = SkTextureCompressorGetPlatformProc(srcColorType, format);
130 switch (srcColorType) {
131 case kAlpha_8_SkColorType:
135 proc = CompressA8ToLATC;
137 case kR11_EAC_Format:
138 proc = CompressA8ToR11EAC;
140 case kASTC_12x12_Format:
141 proc = CompressA8To12x12ASTC;
150 case kRGB_565_SkColorType:
154 proc = compress_etc1_565;
170 return proc(dst, src, width, height, rowBytes);
176 SkData* CompressBitmapToFormat(const SkBitmap &bitmap, Format format) {
177 SkAutoLockPixels alp(bitmap);
179 int compressedDataSize = GetCompressedDataSize(format, bitmap.width(), bitmap.height());
180 if (compressedDataSize < 0) {
184 const uint8_t* src = reinterpret_cast<const uint8_t*>(bitmap.getPixels());
185 SkData* dst = SkData::NewUninitialized(compressedDataSize);
187 if (!CompressBufferToFormat((uint8_t*)dst->writable_data(), src, bitmap.colorType(),
188 bitmap.width(), bitmap.height(), bitmap.rowBytes(), format)) {
195 SkBlitter* CreateBlitterForFormat(int width, int height, void* compressedBuffer,
196 SkTBlitterAllocator *allocator, Format format) {
199 return CreateLATCBlitter(width, height, compressedBuffer, allocator);
201 case kR11_EAC_Format:
202 return CreateR11EACBlitter(width, height, compressedBuffer, allocator);
204 case kASTC_12x12_Format:
205 return CreateASTCBlitter(width, height, compressedBuffer, allocator);
214 bool DecompressBufferFromFormat(uint8_t* dst, int dstRowBytes, const uint8_t* src,
215 int width, int height, Format format) {
217 GetBlockDimensions(format, &dimX, &dimY, true);
219 if (width < 0 || ((width % dimX) != 0) || height < 0 || ((height % dimY) != 0)) {
225 DecompressLATC(dst, dstRowBytes, src, width, height);
228 case kR11_EAC_Format:
229 DecompressR11EAC(dst, dstRowBytes, src, width, height);
232 #ifndef SK_IGNORE_ETC1_SUPPORT
234 return 0 == etc1_decode_image(src, dst, width, height, 3, dstRowBytes);
237 case kASTC_4x4_Format:
238 case kASTC_5x4_Format:
239 case kASTC_5x5_Format:
240 case kASTC_6x5_Format:
241 case kASTC_6x6_Format:
242 case kASTC_8x5_Format:
243 case kASTC_8x6_Format:
244 case kASTC_8x8_Format:
245 case kASTC_10x5_Format:
246 case kASTC_10x6_Format:
247 case kASTC_10x8_Format:
248 case kASTC_10x10_Format:
249 case kASTC_12x10_Format:
250 case kASTC_12x12_Format:
251 DecompressASTC(dst, dstRowBytes, src, width, height, dimX, dimY);
262 } // namespace SkTextureCompressor