blob: 1aa3793f156cd94f0761690280ccdaff2eefe9e3 [file] [log] [blame]
scroggof24f2242015-03-03 08:59:20 -08001/*
2 * Copyright 2015 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
msarett74114382015-03-16 11:55:18 -07008#include "SkCodecPriv.h"
scroggof24f2242015-03-03 08:59:20 -08009#include "SkColorPriv.h"
10#include "SkSwizzler.h"
11#include "SkTemplates.h"
12
msarett74114382015-03-16 11:55:18 -070013SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha,
14 uint8_t maxAlpha) {
15 // In the transparent case, this returns 0x0000
16 // In the opaque case, this returns 0xFFFF
17 // If the row is neither transparent nor opaque, returns something else
18 return (((uint16_t) maxAlpha) << 8) | zeroAlpha;
msarett36758742015-03-16 08:27:53 -070019}
20
msarett74114382015-03-16 11:55:18 -070021// kIndex1, kIndex2, kIndex4
22
23static SkSwizzler::ResultAlpha swizzle_small_index_to_n32(
24 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
25 int bitsPerPixel, int y, const SkPMColor ctable[]) {
26
27 SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow;
28 INIT_RESULT_ALPHA;
29 const uint32_t pixelsPerByte = 8 / bitsPerPixel;
30 const size_t rowBytes = compute_row_bytes_ppb(width, pixelsPerByte);
31 const uint8_t mask = (1 << bitsPerPixel) - 1;
32 int x = 0;
33 for (uint32_t byte = 0; byte < rowBytes; byte++) {
34 uint8_t pixelData = src[byte];
35 for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) {
36 uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask;
37 SkPMColor c = ctable[index];
38 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
39 dst[x] = c;
40 pixelData <<= bitsPerPixel;
41 x++;
42 }
43 }
44 return COMPUTE_RESULT_ALPHA;
45}
46
47// kIndex
48
49static SkSwizzler::ResultAlpha swizzle_index_to_n32(
50 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
51 int bytesPerPixel, int y, const SkPMColor ctable[]) {
msarett36758742015-03-16 08:27:53 -070052
53 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
msarett74114382015-03-16 11:55:18 -070054 INIT_RESULT_ALPHA;
msarett36758742015-03-16 08:27:53 -070055 for (int x = 0; x < width; x++) {
56 SkPMColor c = ctable[*src];
msarett74114382015-03-16 11:55:18 -070057 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
58 dst[x] = c;
59 src++;
60 }
61 return COMPUTE_RESULT_ALPHA;
62}
63
64static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ(
65 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
66 int bytesPerPixel, int y, const SkPMColor ctable[]) {
67
68 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
69 INIT_RESULT_ALPHA;
70 for (int x = 0; x < width; x++) {
71 SkPMColor c = ctable[*src];
72 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
scroggof24f2242015-03-03 08:59:20 -080073 if (c != 0) {
74 dst[x] = c;
75 }
msarett74114382015-03-16 11:55:18 -070076 src++;
scroggof24f2242015-03-03 08:59:20 -080077 }
msarett74114382015-03-16 11:55:18 -070078 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -080079}
80
81#undef A32_MASK_IN_PLACE
82
msarett74114382015-03-16 11:55:18 -070083static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32(
84 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
85 int bytesPerPixel, int y, const SkPMColor ctable[]) {
86
87 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
88 for (int x = 0; x < width; x++) {
89 dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]);
90 src += bytesPerPixel;
91 }
92 return SkSwizzler::kOpaque_ResultAlpha;
93}
94
95// kBGRA
96
97static SkSwizzler::ResultAlpha swizzle_bgra_to_n32(
98 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
99 int bytesPerPixel, int y, const SkPMColor ctable[]) {
100
101 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
102 INIT_RESULT_ALPHA;
103 for (int x = 0; x < width; x++) {
104 uint8_t alpha = src[3];
105 UPDATE_RESULT_ALPHA(alpha);
106 dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]);
107 src += bytesPerPixel;
108 }
109 return COMPUTE_RESULT_ALPHA;
110}
111
scroggof24f2242015-03-03 08:59:20 -0800112// n32
msarett74114382015-03-16 11:55:18 -0700113static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32(
114 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
115 int bytesPerPixel, int y, const SkPMColor ctable[]) {
116
scroggof24f2242015-03-03 08:59:20 -0800117 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
118 for (int x = 0; x < width; x++) {
119 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
msarett74114382015-03-16 11:55:18 -0700120 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800121 }
msarett74114382015-03-16 11:55:18 -0700122 return SkSwizzler::kOpaque_ResultAlpha;
scroggof24f2242015-03-03 08:59:20 -0800123}
124
msarett74114382015-03-16 11:55:18 -0700125static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul(
126 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
127 int bytesPerPixel, int y, const SkPMColor ctable[]) {
128
scroggof24f2242015-03-03 08:59:20 -0800129 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
msarett74114382015-03-16 11:55:18 -0700130 INIT_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800131 for (int x = 0; x < width; x++) {
132 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700133 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800134 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
msarett74114382015-03-16 11:55:18 -0700135 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800136 }
msarett74114382015-03-16 11:55:18 -0700137 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800138}
139
msarett74114382015-03-16 11:55:18 -0700140static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_unpremul(
141 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
142 int bytesPerPixel, int y, const SkPMColor ctable[]) {
143
scroggof24f2242015-03-03 08:59:20 -0800144 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
msarett74114382015-03-16 11:55:18 -0700145 INIT_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800146 for (int x = 0; x < width; x++) {
147 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700148 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800149 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
msarett74114382015-03-16 11:55:18 -0700150 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800151 }
msarett74114382015-03-16 11:55:18 -0700152 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800153}
154
msarett74114382015-03-16 11:55:18 -0700155static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ(
156 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
157 int bytesPerPixel, int y, const SkPMColor ctable[]) {
158
scroggof24f2242015-03-03 08:59:20 -0800159 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
msarett74114382015-03-16 11:55:18 -0700160 INIT_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800161 for (int x = 0; x < width; x++) {
162 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700163 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800164 if (0 != alpha) {
165 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
166 }
msarett74114382015-03-16 11:55:18 -0700167 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800168 }
msarett74114382015-03-16 11:55:18 -0700169 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800170}
171
172/**
173 FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes.
174 This would be fine for drawing normally, but not for drawing with transfer modes. Being
175 honest means we can draw correctly with transfer modes, with the cost of not being able
176 to take advantage of Android's free unwritten pages. Something to keep in mind when we
177 decide whether to switch to unpremul default.
178static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow,
179 const uint8_t* SK_RESTRICT src,
msarett74114382015-03-16 11:55:18 -0700180 int width, int bitsPerPixel,
scroggof24f2242015-03-03 08:59:20 -0800181 const SkPMColor[]) {
182 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
183 unsigned alphaMask = 0xFF;
184 for (int x = 0; x < width; x++) {
185 unsigned alpha = src[3];
186 // NOTE: We cheat here. The caller requested unpremul and skip zeroes. It's possible
187 // the color components are not zero, but we skip them anyway, meaning they'll remain
188 // zero (implied by the request to skip zeroes).
189 if (0 != alpha) {
190 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
191 }
192 src += deltaSrc;
193 alphaMask &= alpha;
194 }
195 return alphaMask != 0xFF;
196}
197*/
198
msarett74114382015-03-16 11:55:18 -0700199SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
200 const SkPMColor* ctable,
scroggof24f2242015-03-03 08:59:20 -0800201 const SkImageInfo& info, void* dst,
scroggo95526622015-03-17 05:02:17 -0700202 size_t dstRowBytes,
203 SkImageGenerator::ZeroInitialized zeroInit) {
msarett74114382015-03-16 11:55:18 -0700204 if (kUnknown_SkColorType == info.colorType()) {
scroggof24f2242015-03-03 08:59:20 -0800205 return NULL;
206 }
207 if (info.minRowBytes() > dstRowBytes) {
208 return NULL;
209 }
msarett74114382015-03-16 11:55:18 -0700210 if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc)
211 && NULL == ctable) {
scroggof24f2242015-03-03 08:59:20 -0800212 return NULL;
213 }
214 RowProc proc = NULL;
215 switch (sc) {
msarett74114382015-03-16 11:55:18 -0700216 case kIndex1:
217 case kIndex2:
218 case kIndex4:
219 switch (info.colorType()) {
220 case kN32_SkColorType:
221 proc = &swizzle_small_index_to_n32;
222 break;
223 default:
224 break;
225 }
226 break;
scroggof24f2242015-03-03 08:59:20 -0800227 case kIndex:
228 switch (info.colorType()) {
229 case kN32_SkColorType:
scroggo95526622015-03-17 05:02:17 -0700230 // We assume the color premultiplied ctable (or not) as desired.
231 if (SkImageGenerator::kYes_ZeroInitialized == zeroInit) {
scroggof24f2242015-03-03 08:59:20 -0800232 proc = &swizzle_index_to_n32_skipZ;
233 } else {
234 proc = &swizzle_index_to_n32;
235 }
236 break;
msarett74114382015-03-16 11:55:18 -0700237 default:
238 break;
239 }
240 break;
241 case kBGR:
242 case kBGRX:
243 switch (info.colorType()) {
244 case kN32_SkColorType:
245 proc = &swizzle_bgrx_to_n32;
246 break;
247 default:
248 break;
249 }
250 break;
251 case kBGRA:
252 switch (info.colorType()) {
253 case kN32_SkColorType:
254 proc = &swizzle_bgra_to_n32;
255 break;
scroggof24f2242015-03-03 08:59:20 -0800256 default:
257 break;
258 }
259 break;
260 case kRGBX:
261 // TODO: Support other swizzles.
262 switch (info.colorType()) {
263 case kN32_SkColorType:
264 proc = &swizzle_rgbx_to_n32;
265 break;
266 default:
267 break;
268 }
269 break;
270 case kRGBA:
271 switch (info.colorType()) {
272 case kN32_SkColorType:
273 if (info.alphaType() == kUnpremul_SkAlphaType) {
scroggo95526622015-03-17 05:02:17 -0700274 // Respect zeroInit?
scroggof24f2242015-03-03 08:59:20 -0800275 proc = &swizzle_rgba_to_n32_unpremul;
276 } else {
scroggo95526622015-03-17 05:02:17 -0700277 if (SkImageGenerator::kYes_ZeroInitialized == zeroInit) {
scroggof24f2242015-03-03 08:59:20 -0800278 proc = &swizzle_rgba_to_n32_premul_skipZ;
279 } else {
280 proc = &swizzle_rgba_to_n32_premul;
281 }
282 }
283 break;
284 default:
285 break;
286 }
287 break;
msarett74114382015-03-16 11:55:18 -0700288 case kRGB:
289 switch (info.colorType()) {
290 case kN32_SkColorType:
291 proc = &swizzle_rgbx_to_n32;
292 break;
293 default:
294 break;
295 }
296 break;
scroggof24f2242015-03-03 08:59:20 -0800297 default:
298 break;
299 }
300 if (NULL == proc) {
301 return NULL;
302 }
msarett74114382015-03-16 11:55:18 -0700303
304 // Store deltaSrc in bytes if it is an even multiple, otherwise use bits
305 int deltaSrc = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) :
306 BitsPerPixel(sc);
307 return SkNEW_ARGS(SkSwizzler, (proc, ctable, deltaSrc, info, dst,
308 dstRowBytes));
scroggof24f2242015-03-03 08:59:20 -0800309}
310
msarett74114382015-03-16 11:55:18 -0700311SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable,
312 int deltaSrc, const SkImageInfo& info, void* dst,
313 size_t rowBytes)
scroggof24f2242015-03-03 08:59:20 -0800314 : fRowProc(proc)
315 , fColorTable(ctable)
msarett74114382015-03-16 11:55:18 -0700316 , fDeltaSrc(deltaSrc)
scroggof24f2242015-03-03 08:59:20 -0800317 , fDstInfo(info)
318 , fDstRow(dst)
319 , fDstRowBytes(rowBytes)
320 , fCurrY(0)
321{
msarett74114382015-03-16 11:55:18 -0700322 SkDEBUGCODE(fNextMode = kUninitialized_NextMode);
scroggof24f2242015-03-03 08:59:20 -0800323}
324
msarett74114382015-03-16 11:55:18 -0700325SkSwizzler::ResultAlpha SkSwizzler::next(const uint8_t* SK_RESTRICT src) {
326 SkASSERT(0 <= fCurrY && fCurrY < fDstInfo.height());
327 SkASSERT(kDesignateRow_NextMode != fNextMode);
328 SkDEBUGCODE(fNextMode = kConsecutive_NextMode);
329
330 // Decode a row
331 const ResultAlpha result = fRowProc(fDstRow, src, fDstInfo.width(),
332 fDeltaSrc, fCurrY, fColorTable);
333
334 // Move to the next row and return the result
scroggof24f2242015-03-03 08:59:20 -0800335 fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes);
msarett74114382015-03-16 11:55:18 -0700336 return result;
337}
338
339SkSwizzler::ResultAlpha SkSwizzler::next(const uint8_t* SK_RESTRICT src,
340 int y) {
341 SkASSERT(0 <= y && y < fDstInfo.height());
342 SkASSERT(kConsecutive_NextMode != fNextMode);
343 SkDEBUGCODE(fNextMode = kDesignateRow_NextMode);
344
345 // Choose the row
346 void* row = SkTAddOffset<void>(fDstRow, y*fDstRowBytes);
347
348 // Decode the row
349 return fRowProc(row, src, fDstInfo.width(), fDeltaSrc, fCurrY,
350 fColorTable);
scroggof24f2242015-03-03 08:59:20 -0800351}