Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / utils / SkTextureCompressor.cpp
1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkTextureCompressor.h"
9 #include "SkTextureCompressor_ASTC.h"
10 #include "SkTextureCompressor_LATC.h"
11 #include "SkTextureCompressor_R11EAC.h"
12
13 #include "SkBitmap.h"
14 #include "SkBitmapProcShader.h"
15 #include "SkData.h"
16 #include "SkEndian.h"
17
18 #include "SkTextureCompression_opts.h"
19
20 #ifndef SK_IGNORE_ETC1_SUPPORT
21 #  include "etc1.h"
22 #endif
23
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);
29 #else
30     return false;
31 #endif
32 }
33
34 ////////////////////////////////////////////////////////////////////////////////
35
36 namespace SkTextureCompressor {
37
38 void GetBlockDimensions(Format format, int* dimX, int* dimY, bool matchSpec) {
39     if (NULL == dimX || NULL == dimY) {
40         return;
41     }
42
43     if (!matchSpec && SkTextureCompressorGetPlatformDims(format, dimX, dimY)) {
44         return;
45     }
46
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
69     };
70
71     *dimX = kFormatDimensions[format].fBlockSizeX;
72     *dimY = kFormatDimensions[format].fBlockSizeY;
73 }
74
75 int GetCompressedDataSize(Format fmt, int width, int height) {
76     int dimX, dimY;
77     GetBlockDimensions(fmt, &dimX, &dimY, true);
78
79     int encodedBlockSize = 0;
80             
81     switch (fmt) {
82         // These formats are 64 bits per 4x4 block.
83         case kLATC_Format:
84         case kR11_EAC_Format:
85         case kETC1_Format:
86             encodedBlockSize = 8;
87             break;
88
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;
105             break;
106
107         default:
108             SkFAIL("Unknown compressed format!");
109             return -1;
110     }
111
112     if(((width % dimX) == 0) && ((height % dimY) == 0)) {
113         const int blocksX = width / dimX;
114         const int blocksY = height / dimY;
115
116         return blocksX * blocksY * encodedBlockSize;
117     }
118
119     return -1;
120 }
121
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;
125     if (opt) {
126         proc = SkTextureCompressorGetPlatformProc(srcColorType, format);
127     }
128
129     if (NULL == proc) {
130         switch (srcColorType) {
131             case kAlpha_8_SkColorType:
132             {
133                 switch (format) {
134                     case kLATC_Format:
135                         proc = CompressA8ToLATC;
136                         break;
137                     case kR11_EAC_Format:
138                         proc = CompressA8ToR11EAC;
139                         break;
140                     case kASTC_12x12_Format:
141                         proc = CompressA8To12x12ASTC;
142                         break;
143                     default:
144                         // Do nothing...
145                         break;
146                 }
147             }
148             break;
149
150             case kRGB_565_SkColorType:
151             {
152                 switch (format) {
153                     case kETC1_Format:
154                         proc = compress_etc1_565;
155                         break;
156                     default:
157                         // Do nothing...
158                         break;
159                 }
160             }
161             break;
162
163             default:
164                 // Do nothing...
165                 break;
166         }
167     }
168
169     if (proc) {
170         return proc(dst, src, width, height, rowBytes);
171     }
172
173     return false;
174 }
175
176 SkData* CompressBitmapToFormat(const SkBitmap &bitmap, Format format) {
177     SkAutoLockPixels alp(bitmap);
178
179     int compressedDataSize = GetCompressedDataSize(format, bitmap.width(), bitmap.height());
180     if (compressedDataSize < 0) {
181         return NULL;
182     }
183
184     const uint8_t* src = reinterpret_cast<const uint8_t*>(bitmap.getPixels());
185     SkData* dst = SkData::NewUninitialized(compressedDataSize);
186
187     if (!CompressBufferToFormat((uint8_t*)dst->writable_data(), src, bitmap.colorType(),
188                                 bitmap.width(), bitmap.height(), bitmap.rowBytes(), format)) {
189         dst->unref();
190         dst = NULL;
191     }
192     return dst;
193 }
194
195 SkBlitter* CreateBlitterForFormat(int width, int height, void* compressedBuffer,
196                                   SkTBlitterAllocator *allocator, Format format) {
197     switch(format) {
198         case kLATC_Format:
199             return CreateLATCBlitter(width, height, compressedBuffer, allocator);
200
201         case kR11_EAC_Format:
202             return CreateR11EACBlitter(width, height, compressedBuffer, allocator);
203
204         case kASTC_12x12_Format:
205             return CreateASTCBlitter(width, height, compressedBuffer, allocator);
206
207         default:
208             return NULL;
209     }
210
211     return NULL;
212 }
213
214 bool DecompressBufferFromFormat(uint8_t* dst, int dstRowBytes, const uint8_t* src,
215                                 int width, int height, Format format) {
216     int dimX, dimY;
217     GetBlockDimensions(format, &dimX, &dimY, true);
218
219     if (width < 0 || ((width % dimX) != 0) || height < 0 || ((height % dimY) != 0)) {
220         return false;
221     }
222
223     switch(format) {
224         case kLATC_Format:
225             DecompressLATC(dst, dstRowBytes, src, width, height);
226             return true;
227
228         case kR11_EAC_Format:
229             DecompressR11EAC(dst, dstRowBytes, src, width, height);
230             return true;
231
232 #ifndef SK_IGNORE_ETC1_SUPPORT
233         case kETC1_Format:
234             return 0 == etc1_decode_image(src, dst, width, height, 3, dstRowBytes);
235 #endif
236
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);
252             return true;
253
254         default:
255             // Do nothing...
256             break;
257     }
258
259     return false;
260 }
261
262 }  // namespace SkTextureCompressor