blob: 351b3be1d2722bcad89b45800334726d426dbb48 [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
msaretteed039b2015-03-18 11:11:19 -070047static SkSwizzler::ResultAlpha swizzle_small_index_to_565(
48 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
49 int bitsPerPixel, int y, const SkPMColor ctable[]) {
50
51 uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow;
52 const uint32_t pixelsPerByte = 8 / bitsPerPixel;
53 const size_t rowBytes = compute_row_bytes_ppb(width, pixelsPerByte);
54 const uint8_t mask = (1 << bitsPerPixel) - 1;
55 int x = 0;
56 for (uint32_t byte = 0; byte < rowBytes; byte++) {
57 uint8_t pixelData = src[byte];
58 for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) {
59 uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask;
60 uint16_t c = SkPixel32ToPixel16(ctable[index]);
61 dst[x] = c;
62 pixelData <<= bitsPerPixel;
63 x++;
64 }
65 }
66 return SkSwizzler::kOpaque_ResultAlpha;
67}
68
msarett74114382015-03-16 11:55:18 -070069// kIndex
70
71static SkSwizzler::ResultAlpha swizzle_index_to_n32(
72 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
73 int bytesPerPixel, int y, const SkPMColor ctable[]) {
msarett36758742015-03-16 08:27:53 -070074
75 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
msarett74114382015-03-16 11:55:18 -070076 INIT_RESULT_ALPHA;
msarett36758742015-03-16 08:27:53 -070077 for (int x = 0; x < width; x++) {
78 SkPMColor c = ctable[*src];
msarett74114382015-03-16 11:55:18 -070079 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
80 dst[x] = c;
81 src++;
82 }
83 return COMPUTE_RESULT_ALPHA;
84}
85
86static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ(
87 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
88 int bytesPerPixel, int y, const SkPMColor ctable[]) {
89
90 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
91 INIT_RESULT_ALPHA;
92 for (int x = 0; x < width; x++) {
93 SkPMColor c = ctable[*src];
94 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
scroggof24f2242015-03-03 08:59:20 -080095 if (c != 0) {
96 dst[x] = c;
97 }
msarett74114382015-03-16 11:55:18 -070098 src++;
scroggof24f2242015-03-03 08:59:20 -080099 }
msarett74114382015-03-16 11:55:18 -0700100 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800101}
102
msaretteed039b2015-03-18 11:11:19 -0700103static SkSwizzler::ResultAlpha swizzle_index_to_565(
104 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
105 int bytesPerPixel, int y, const SkPMColor ctable[]) {
106
107 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
108 for (int x = 0; x < width; x++) {
109 uint16_t c = SkPixel32ToPixel16(ctable[*src]);
110 dst[x] = c;
111 src++;
112 }
113 return SkSwizzler::kOpaque_ResultAlpha;
114}
115
scroggof24f2242015-03-03 08:59:20 -0800116#undef A32_MASK_IN_PLACE
117
msarett74114382015-03-16 11:55:18 -0700118static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32(
119 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
120 int bytesPerPixel, int y, const SkPMColor ctable[]) {
121
122 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
123 for (int x = 0; x < width; x++) {
124 dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]);
125 src += bytesPerPixel;
126 }
127 return SkSwizzler::kOpaque_ResultAlpha;
128}
129
msaretteed039b2015-03-18 11:11:19 -0700130static SkSwizzler::ResultAlpha swizzle_bgrx_to_565(
131 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
132 int bytesPerPixel, int y, const SkPMColor ctable[]) {
133
134 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
135 for (int x = 0; x < width; x++) {
136 dst[x] = SkPack888ToRGB16(src[2], src[1], src[0]);
137 src += bytesPerPixel;
138 }
139 return SkSwizzler::kOpaque_ResultAlpha;
140}
141
msarett74114382015-03-16 11:55:18 -0700142// kBGRA
143
msaretteed039b2015-03-18 11:11:19 -0700144static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_unpremul(
msarett74114382015-03-16 11:55:18 -0700145 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
146 int bytesPerPixel, int y, const SkPMColor ctable[]) {
147
148 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
149 INIT_RESULT_ALPHA;
150 for (int x = 0; x < width; x++) {
151 uint8_t alpha = src[3];
152 UPDATE_RESULT_ALPHA(alpha);
153 dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]);
154 src += bytesPerPixel;
155 }
156 return COMPUTE_RESULT_ALPHA;
157}
158
msaretteed039b2015-03-18 11:11:19 -0700159static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_premul(
160 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
161 int bytesPerPixel, int y, const SkPMColor ctable[]) {
162
163 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
164 INIT_RESULT_ALPHA;
165 for (int x = 0; x < width; x++) {
166 uint8_t alpha = src[3];
167 UPDATE_RESULT_ALPHA(alpha);
168 dst[x] = SkPreMultiplyARGB(alpha, src[2], src[1], src[0]);
169 src += bytesPerPixel;
170 }
171 return COMPUTE_RESULT_ALPHA;
172}
173
scroggof24f2242015-03-03 08:59:20 -0800174// n32
msarett74114382015-03-16 11:55:18 -0700175static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32(
176 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
177 int bytesPerPixel, int y, const SkPMColor ctable[]) {
178
scroggof24f2242015-03-03 08:59:20 -0800179 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
180 for (int x = 0; x < width; x++) {
181 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
msarett74114382015-03-16 11:55:18 -0700182 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800183 }
msarett74114382015-03-16 11:55:18 -0700184 return SkSwizzler::kOpaque_ResultAlpha;
scroggof24f2242015-03-03 08:59:20 -0800185}
186
msarett74114382015-03-16 11:55:18 -0700187static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul(
188 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
189 int bytesPerPixel, int y, const SkPMColor ctable[]) {
190
scroggof24f2242015-03-03 08:59:20 -0800191 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
msarett74114382015-03-16 11:55:18 -0700192 INIT_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800193 for (int x = 0; x < width; x++) {
194 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700195 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800196 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
msarett74114382015-03-16 11:55:18 -0700197 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800198 }
msarett74114382015-03-16 11:55:18 -0700199 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800200}
201
msarett74114382015-03-16 11:55:18 -0700202static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_unpremul(
203 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
204 int bytesPerPixel, int y, const SkPMColor ctable[]) {
205
scroggof24f2242015-03-03 08:59:20 -0800206 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
msarett74114382015-03-16 11:55:18 -0700207 INIT_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800208 for (int x = 0; x < width; x++) {
209 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700210 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800211 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
msarett74114382015-03-16 11:55:18 -0700212 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800213 }
msarett74114382015-03-16 11:55:18 -0700214 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800215}
216
msarett74114382015-03-16 11:55:18 -0700217static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ(
218 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
219 int bytesPerPixel, int y, const SkPMColor ctable[]) {
220
scroggof24f2242015-03-03 08:59:20 -0800221 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
msarett74114382015-03-16 11:55:18 -0700222 INIT_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800223 for (int x = 0; x < width; x++) {
224 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700225 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800226 if (0 != alpha) {
227 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
228 }
msarett74114382015-03-16 11:55:18 -0700229 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800230 }
msarett74114382015-03-16 11:55:18 -0700231 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800232}
233
234/**
235 FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes.
236 This would be fine for drawing normally, but not for drawing with transfer modes. Being
237 honest means we can draw correctly with transfer modes, with the cost of not being able
238 to take advantage of Android's free unwritten pages. Something to keep in mind when we
239 decide whether to switch to unpremul default.
240static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow,
241 const uint8_t* SK_RESTRICT src,
msarett74114382015-03-16 11:55:18 -0700242 int width, int bitsPerPixel,
scroggof24f2242015-03-03 08:59:20 -0800243 const SkPMColor[]) {
244 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
245 unsigned alphaMask = 0xFF;
246 for (int x = 0; x < width; x++) {
247 unsigned alpha = src[3];
248 // NOTE: We cheat here. The caller requested unpremul and skip zeroes. It's possible
249 // the color components are not zero, but we skip them anyway, meaning they'll remain
250 // zero (implied by the request to skip zeroes).
251 if (0 != alpha) {
252 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
253 }
254 src += deltaSrc;
255 alphaMask &= alpha;
256 }
257 return alphaMask != 0xFF;
258}
259*/
260
msarett74114382015-03-16 11:55:18 -0700261SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
262 const SkPMColor* ctable,
scroggof24f2242015-03-03 08:59:20 -0800263 const SkImageInfo& info, void* dst,
scroggo95526622015-03-17 05:02:17 -0700264 size_t dstRowBytes,
265 SkImageGenerator::ZeroInitialized zeroInit) {
msarett74114382015-03-16 11:55:18 -0700266 if (kUnknown_SkColorType == info.colorType()) {
scroggof24f2242015-03-03 08:59:20 -0800267 return NULL;
268 }
269 if (info.minRowBytes() > dstRowBytes) {
270 return NULL;
271 }
msarett74114382015-03-16 11:55:18 -0700272 if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc)
273 && NULL == ctable) {
scroggof24f2242015-03-03 08:59:20 -0800274 return NULL;
275 }
276 RowProc proc = NULL;
277 switch (sc) {
msarett74114382015-03-16 11:55:18 -0700278 case kIndex1:
279 case kIndex2:
280 case kIndex4:
281 switch (info.colorType()) {
282 case kN32_SkColorType:
283 proc = &swizzle_small_index_to_n32;
284 break;
msaretteed039b2015-03-18 11:11:19 -0700285 case kRGB_565_SkColorType:
286 proc = &swizzle_small_index_to_565;
287 break;
msarett74114382015-03-16 11:55:18 -0700288 default:
289 break;
290 }
291 break;
scroggof24f2242015-03-03 08:59:20 -0800292 case kIndex:
293 switch (info.colorType()) {
294 case kN32_SkColorType:
scroggo95526622015-03-17 05:02:17 -0700295 // We assume the color premultiplied ctable (or not) as desired.
296 if (SkImageGenerator::kYes_ZeroInitialized == zeroInit) {
scroggof24f2242015-03-03 08:59:20 -0800297 proc = &swizzle_index_to_n32_skipZ;
msaretteed039b2015-03-18 11:11:19 -0700298 break;
scroggof24f2242015-03-03 08:59:20 -0800299 } else {
300 proc = &swizzle_index_to_n32;
msaretteed039b2015-03-18 11:11:19 -0700301 break;
scroggof24f2242015-03-03 08:59:20 -0800302 }
303 break;
msaretteed039b2015-03-18 11:11:19 -0700304 case kRGB_565_SkColorType:
305 proc = &swizzle_index_to_565;
306 break;
msarett74114382015-03-16 11:55:18 -0700307 default:
308 break;
309 }
310 break;
311 case kBGR:
312 case kBGRX:
313 switch (info.colorType()) {
314 case kN32_SkColorType:
315 proc = &swizzle_bgrx_to_n32;
316 break;
msaretteed039b2015-03-18 11:11:19 -0700317 case kRGB_565_SkColorType:
318 proc = &swizzle_bgrx_to_565;
319 break;
msarett74114382015-03-16 11:55:18 -0700320 default:
321 break;
322 }
323 break;
324 case kBGRA:
325 switch (info.colorType()) {
326 case kN32_SkColorType:
msaretteed039b2015-03-18 11:11:19 -0700327 switch (info.alphaType()) {
328 case kUnpremul_SkAlphaType:
329 proc = &swizzle_bgra_to_n32_unpremul;
330 break;
331 case kPremul_SkAlphaType:
332 proc = &swizzle_bgra_to_n32_premul;
333 break;
334 default:
335 break;
336 }
msarett74114382015-03-16 11:55:18 -0700337 break;
scroggof24f2242015-03-03 08:59:20 -0800338 default:
339 break;
340 }
341 break;
342 case kRGBX:
343 // TODO: Support other swizzles.
344 switch (info.colorType()) {
345 case kN32_SkColorType:
346 proc = &swizzle_rgbx_to_n32;
347 break;
348 default:
349 break;
350 }
351 break;
352 case kRGBA:
353 switch (info.colorType()) {
354 case kN32_SkColorType:
355 if (info.alphaType() == kUnpremul_SkAlphaType) {
scroggo95526622015-03-17 05:02:17 -0700356 // Respect zeroInit?
scroggof24f2242015-03-03 08:59:20 -0800357 proc = &swizzle_rgba_to_n32_unpremul;
358 } else {
scroggo95526622015-03-17 05:02:17 -0700359 if (SkImageGenerator::kYes_ZeroInitialized == zeroInit) {
scroggof24f2242015-03-03 08:59:20 -0800360 proc = &swizzle_rgba_to_n32_premul_skipZ;
361 } else {
362 proc = &swizzle_rgba_to_n32_premul;
363 }
364 }
365 break;
366 default:
367 break;
368 }
369 break;
msarett74114382015-03-16 11:55:18 -0700370 case kRGB:
371 switch (info.colorType()) {
372 case kN32_SkColorType:
373 proc = &swizzle_rgbx_to_n32;
374 break;
375 default:
376 break;
377 }
378 break;
scroggof24f2242015-03-03 08:59:20 -0800379 default:
380 break;
381 }
382 if (NULL == proc) {
383 return NULL;
384 }
msarett74114382015-03-16 11:55:18 -0700385
386 // Store deltaSrc in bytes if it is an even multiple, otherwise use bits
387 int deltaSrc = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) :
388 BitsPerPixel(sc);
389 return SkNEW_ARGS(SkSwizzler, (proc, ctable, deltaSrc, info, dst,
390 dstRowBytes));
scroggof24f2242015-03-03 08:59:20 -0800391}
392
msarett74114382015-03-16 11:55:18 -0700393SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable,
394 int deltaSrc, const SkImageInfo& info, void* dst,
395 size_t rowBytes)
scroggof24f2242015-03-03 08:59:20 -0800396 : fRowProc(proc)
397 , fColorTable(ctable)
msarett74114382015-03-16 11:55:18 -0700398 , fDeltaSrc(deltaSrc)
scroggof24f2242015-03-03 08:59:20 -0800399 , fDstInfo(info)
400 , fDstRow(dst)
401 , fDstRowBytes(rowBytes)
402 , fCurrY(0)
403{
msarett74114382015-03-16 11:55:18 -0700404 SkDEBUGCODE(fNextMode = kUninitialized_NextMode);
scroggof24f2242015-03-03 08:59:20 -0800405}
406
msarett74114382015-03-16 11:55:18 -0700407SkSwizzler::ResultAlpha SkSwizzler::next(const uint8_t* SK_RESTRICT src) {
408 SkASSERT(0 <= fCurrY && fCurrY < fDstInfo.height());
409 SkASSERT(kDesignateRow_NextMode != fNextMode);
410 SkDEBUGCODE(fNextMode = kConsecutive_NextMode);
411
412 // Decode a row
413 const ResultAlpha result = fRowProc(fDstRow, src, fDstInfo.width(),
414 fDeltaSrc, fCurrY, fColorTable);
415
416 // Move to the next row and return the result
scroggof24f2242015-03-03 08:59:20 -0800417 fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes);
msarett74114382015-03-16 11:55:18 -0700418 return result;
419}
420
421SkSwizzler::ResultAlpha SkSwizzler::next(const uint8_t* SK_RESTRICT src,
422 int y) {
423 SkASSERT(0 <= y && y < fDstInfo.height());
424 SkASSERT(kConsecutive_NextMode != fNextMode);
425 SkDEBUGCODE(fNextMode = kDesignateRow_NextMode);
426
427 // Choose the row
428 void* row = SkTAddOffset<void>(fDstRow, y*fDstRowBytes);
429
430 // Decode the row
431 return fRowProc(row, src, fDstInfo.width(), fDeltaSrc, fCurrY,
432 fColorTable);
scroggof24f2242015-03-03 08:59:20 -0800433}