blob: 8d13e56bd25a44e221c7f4bc290e51cf4922449f [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"
emmaleer8f4ba762015-08-14 07:44:46 -070010#include "SkScaledCodec.h"
scroggof24f2242015-03-03 08:59:20 -080011#include "SkSwizzler.h"
12#include "SkTemplates.h"
13
msarett74114382015-03-16 11:55:18 -070014SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha,
15 uint8_t maxAlpha) {
16 // In the transparent case, this returns 0x0000
17 // In the opaque case, this returns 0xFFFF
18 // If the row is neither transparent nor opaque, returns something else
19 return (((uint16_t) maxAlpha) << 8) | zeroAlpha;
msarett36758742015-03-16 08:27:53 -070020}
21
emmaleer8f4ba762015-08-14 07:44:46 -070022// samples the row. Does not do anything else but sampling
23static SkSwizzler::ResultAlpha sample565(void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src,
msarett5406d6f2015-08-31 06:55:13 -070024 int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[]){
emmaleer8f4ba762015-08-14 07:44:46 -070025
26 src += offset;
27 uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow;
28 for (int x = 0; x < width; x++) {
29 dst[x] = src[1] << 8 | src[0];
30 src += deltaSrc;
31 }
32 // 565 is always opaque
33 return SkSwizzler::kOpaque_ResultAlpha;
34}
35
msarett5406d6f2015-08-31 06:55:13 -070036// TODO (msarett): Investigate SIMD optimizations for swizzle routines.
37
msarett99f567e2015-08-05 12:58:26 -070038// kBit
39// These routines exclusively choose between white and black
40
41#define GRAYSCALE_BLACK 0
42#define GRAYSCALE_WHITE 0xFF
43
emmaleer8f4ba762015-08-14 07:44:46 -070044
45// same as swizzle_bit_to_index and swizzle_bit_to_n32 except for value assigned to dst[x]
msarett99f567e2015-08-05 12:58:26 -070046static SkSwizzler::ResultAlpha swizzle_bit_to_grayscale(
emmaleer8f4ba762015-08-14 07:44:46 -070047 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -070048 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
emmaleer8f4ba762015-08-14 07:44:46 -070049
msarett99f567e2015-08-05 12:58:26 -070050 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
51
emmaleer8f4ba762015-08-14 07:44:46 -070052 // increment src by byte offset and bitIndex by bit offset
53 src += offset / 8;
54 int bitIndex = offset % 8;
55 uint8_t currByte = *src;
56
57 dst[0] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
58
59 for (int x = 1; x < dstWidth; x++) {
60 int bitOffset = bitIndex + deltaSrc;
61 bitIndex = bitOffset % 8;
62 currByte = *(src += bitOffset / 8);
63 dst[x] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
msarett99f567e2015-08-05 12:58:26 -070064 }
65
msarett99f567e2015-08-05 12:58:26 -070066 return SkSwizzler::kOpaque_ResultAlpha;
67}
68
69#undef GRAYSCALE_BLACK
70#undef GRAYSCALE_WHITE
71
emmaleer8f4ba762015-08-14 07:44:46 -070072// same as swizzle_bit_to_grayscale and swizzle_bit_to_n32 except for value assigned to dst[x]
msarett99f567e2015-08-05 12:58:26 -070073static SkSwizzler::ResultAlpha swizzle_bit_to_index(
emmaleer8f4ba762015-08-14 07:44:46 -070074 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -070075 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
msarett99f567e2015-08-05 12:58:26 -070076 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
77
emmaleer8f4ba762015-08-14 07:44:46 -070078 // increment src by byte offset and bitIndex by bit offset
79 src += offset / 8;
80 int bitIndex = offset % 8;
81 uint8_t currByte = *src;
82
83 dst[0] = ((currByte >> (7-bitIndex)) & 1);
84
85 for (int x = 1; x < dstWidth; x++) {
86 int bitOffset = bitIndex + deltaSrc;
87 bitIndex = bitOffset % 8;
88 currByte = *(src += bitOffset / 8);
89 dst[x] = ((currByte >> (7-bitIndex)) & 1);
msarett99f567e2015-08-05 12:58:26 -070090 }
91
msarett99f567e2015-08-05 12:58:26 -070092 return SkSwizzler::kOpaque_ResultAlpha;
93}
94
emmaleer8f4ba762015-08-14 07:44:46 -070095// same as swizzle_bit_to_grayscale and swizzle_bit_to_index except for value assigned to dst[x]
msarett99f567e2015-08-05 12:58:26 -070096static SkSwizzler::ResultAlpha swizzle_bit_to_n32(
emmaleer8f4ba762015-08-14 07:44:46 -070097 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -070098 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
msarett99f567e2015-08-05 12:58:26 -070099 SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow;
100
emmaleer8f4ba762015-08-14 07:44:46 -0700101 // increment src by byte offset and bitIndex by bit offset
102 src += offset / 8;
103 int bitIndex = offset % 8;
104 uint8_t currByte = *src;
105
106 dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
107
108 for (int x = 1; x < dstWidth; x++) {
109 int bitOffset = bitIndex + deltaSrc;
110 bitIndex = bitOffset % 8;
111 currByte = *(src += bitOffset / 8);
112 dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
msarett99f567e2015-08-05 12:58:26 -0700113 }
114
msarett99f567e2015-08-05 12:58:26 -0700115 return SkSwizzler::kOpaque_ResultAlpha;
116}
117
scroggocc2feb12015-08-14 08:32:46 -0700118#define RGB565_BLACK 0
119#define RGB565_WHITE 0xFFFF
120
121static SkSwizzler::ResultAlpha swizzle_bit_to_565(
122 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700123 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
scroggocc2feb12015-08-14 08:32:46 -0700124 uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow;
125
126 // increment src by byte offset and bitIndex by bit offset
127 src += offset / 8;
128 int bitIndex = offset % 8;
129 uint8_t currByte = *src;
130
131 dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK;
132
133 for (int x = 1; x < dstWidth; x++) {
134 int bitOffset = bitIndex + deltaSrc;
135 bitIndex = bitOffset % 8;
136 currByte = *(src += bitOffset / 8);
137 dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK;
138 }
139
140 return SkSwizzler::kOpaque_ResultAlpha;
141}
142
143#undef RGB565_BLACK
144#undef RGB565_WHITE
145
msarett74114382015-03-16 11:55:18 -0700146// kIndex1, kIndex2, kIndex4
147
msarett438b2ad2015-04-09 12:43:10 -0700148static SkSwizzler::ResultAlpha swizzle_small_index_to_index(
emmaleer8f4ba762015-08-14 07:44:46 -0700149 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700150 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett438b2ad2015-04-09 12:43:10 -0700151
msarett5406d6f2015-08-31 06:55:13 -0700152 uint8_t* dst = (uint8_t*) dstRow;
msarett438b2ad2015-04-09 12:43:10 -0700153 INIT_RESULT_ALPHA;
msarett5406d6f2015-08-31 06:55:13 -0700154 src += offset / 8;
155 int bitIndex = offset % 8;
156 uint8_t currByte = *src;
157 const uint8_t mask = (1 << bpp) - 1;
158 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
159 dst[0] = index;
160 UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT);
161
162 for (int x = 1; x < dstWidth; x++) {
163 int bitOffset = bitIndex + deltaSrc;
164 bitIndex = bitOffset % 8;
165 currByte = *(src += bitOffset / 8);
166 index = (currByte >> (8 - bpp - bitIndex)) & mask;
167 dst[x] = index;
168 UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT);
msarett438b2ad2015-04-09 12:43:10 -0700169 }
170 return COMPUTE_RESULT_ALPHA;
171}
172
scroggocc2feb12015-08-14 08:32:46 -0700173static SkSwizzler::ResultAlpha swizzle_small_index_to_565(
174 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700175 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
scroggocc2feb12015-08-14 08:32:46 -0700176
msarett5406d6f2015-08-31 06:55:13 -0700177 uint16_t* dst = (uint16_t*) dstRow;
178 src += offset / 8;
179 int bitIndex = offset % 8;
180 uint8_t currByte = *src;
181 const uint8_t mask = (1 << bpp) - 1;
182 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
183 dst[0] = SkPixel32ToPixel16(ctable[index]);
184
185 for (int x = 1; x < dstWidth; x++) {
186 int bitOffset = bitIndex + deltaSrc;
187 bitIndex = bitOffset % 8;
188 currByte = *(src += bitOffset / 8);
189 index = (currByte >> (8 - bpp - bitIndex)) & mask;
190 dst[x] = SkPixel32ToPixel16(ctable[index]);
scroggocc2feb12015-08-14 08:32:46 -0700191 }
msarett5406d6f2015-08-31 06:55:13 -0700192 return SkAlphaType::kOpaque_SkAlphaType;
scroggocc2feb12015-08-14 08:32:46 -0700193}
194
msarett74114382015-03-16 11:55:18 -0700195static SkSwizzler::ResultAlpha swizzle_small_index_to_n32(
emmaleer8f4ba762015-08-14 07:44:46 -0700196 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700197 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett74114382015-03-16 11:55:18 -0700198
msarett5406d6f2015-08-31 06:55:13 -0700199 SkPMColor* dst = (SkPMColor*) dstRow;
msarett74114382015-03-16 11:55:18 -0700200 INIT_RESULT_ALPHA;
msarett5406d6f2015-08-31 06:55:13 -0700201 src += offset / 8;
202 int bitIndex = offset % 8;
203 uint8_t currByte = *src;
204 const uint8_t mask = (1 << bpp) - 1;
205 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
206 dst[0] = ctable[index];
207 UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT);
208
209 for (int x = 1; x < dstWidth; x++) {
210 int bitOffset = bitIndex + deltaSrc;
211 bitIndex = bitOffset % 8;
212 currByte = *(src += bitOffset / 8);
213 index = (currByte >> (8 - bpp - bitIndex)) & mask;
214 dst[x] = ctable[index];
215 UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT);
msarett74114382015-03-16 11:55:18 -0700216 }
217 return COMPUTE_RESULT_ALPHA;
218}
219
msarette16b04a2015-04-15 07:32:19 -0700220// kIndex
221
msarett438b2ad2015-04-09 12:43:10 -0700222static SkSwizzler::ResultAlpha swizzle_index_to_index(
emmaleer8f4ba762015-08-14 07:44:46 -0700223 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700224 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msaretteed039b2015-03-18 11:11:19 -0700225
emmaleer8f4ba762015-08-14 07:44:46 -0700226 src += offset;
msarett438b2ad2015-04-09 12:43:10 -0700227 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700228 INIT_RESULT_ALPHA;
msarett438b2ad2015-04-09 12:43:10 -0700229 // TODO (msarett): Should we skip the loop here and guess that the row is opaque/not opaque?
230 // SkScaledBitmap sampler just guesses that it is opaque. This is dangerous
231 // and probably wrong since gif and bmp (rarely) may have alpha.
emmaleer8f4ba762015-08-14 07:44:46 -0700232 if (1 == deltaSrc) {
233 // A non-zero offset is only used when sampling, meaning that deltaSrc will be
234 // greater than 1. The below loop relies on the fact that src remains unchanged.
235 SkASSERT(0 == offset);
236 memcpy(dst, src, dstWidth);
237 for (int x = 0; x < dstWidth; x++) {
238 UPDATE_RESULT_ALPHA(ctable[src[x]] >> SK_A32_SHIFT);
239 }
240 } else {
241 for (int x = 0; x < dstWidth; x++) {
242 dst[x] = *src;
243 UPDATE_RESULT_ALPHA(ctable[*src] >> SK_A32_SHIFT);
244 src += deltaSrc;
emmaleerb1579172015-08-14 05:46:08 -0700245 }
emmaleerb1579172015-08-14 05:46:08 -0700246 }
247 return COMPUTE_RESULT_ALPHA;
248}
249
emmaleer8f4ba762015-08-14 07:44:46 -0700250static SkSwizzler::ResultAlpha swizzle_index_to_n32(
251 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700252 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
emmaleer8f4ba762015-08-14 07:44:46 -0700253
254 src += offset;
255 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
256 INIT_RESULT_ALPHA;
257 for (int x = 0; x < dstWidth; x++) {
258 SkPMColor c = ctable[*src];
259 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
260 dst[x] = c;
261 src += deltaSrc;
262 }
263 return COMPUTE_RESULT_ALPHA;
264}
265
266static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ(
267 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700268 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
emmaleer8f4ba762015-08-14 07:44:46 -0700269
270 src += offset;
271 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
272 INIT_RESULT_ALPHA;
273 for (int x = 0; x < dstWidth; x++) {
274 SkPMColor c = ctable[*src];
275 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
276 if (c != 0) {
277 dst[x] = c;
278 }
279 src += deltaSrc;
280 }
281 return COMPUTE_RESULT_ALPHA;
282}
283
scroggoab60c5b2015-08-06 06:08:18 -0700284static SkSwizzler::ResultAlpha swizzle_index_to_565(
emmaleer8f4ba762015-08-14 07:44:46 -0700285 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700286 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
scroggoab60c5b2015-08-06 06:08:18 -0700287 // FIXME: Support dithering? Requires knowing y, which I think is a bigger
288 // change.
emmaleer8f4ba762015-08-14 07:44:46 -0700289 src += offset;
scroggoab60c5b2015-08-06 06:08:18 -0700290 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700291 for (int x = 0; x < dstWidth; x++) {
scroggoab60c5b2015-08-06 06:08:18 -0700292 dst[x] = SkPixel32ToPixel16(ctable[*src]);
msarett5406d6f2015-08-31 06:55:13 -0700293 src += deltaSrc;
scroggoab60c5b2015-08-06 06:08:18 -0700294 }
295 return SkSwizzler::kOpaque_ResultAlpha;
296}
297
298
scroggof24f2242015-03-03 08:59:20 -0800299#undef A32_MASK_IN_PLACE
300
msarette16b04a2015-04-15 07:32:19 -0700301// kGray
302
303static SkSwizzler::ResultAlpha swizzle_gray_to_n32(
emmaleer8f4ba762015-08-14 07:44:46 -0700304 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700305 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarette16b04a2015-04-15 07:32:19 -0700306
emmaleer8f4ba762015-08-14 07:44:46 -0700307 src += offset;
msarette16b04a2015-04-15 07:32:19 -0700308 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700309 for (int x = 0; x < dstWidth; x++) {
310 dst[x] = SkPackARGB32NoCheck(0xFF, *src, *src, *src);
311 src += deltaSrc;
msarette16b04a2015-04-15 07:32:19 -0700312 }
313 return SkSwizzler::kOpaque_ResultAlpha;
314}
315
316static SkSwizzler::ResultAlpha swizzle_gray_to_gray(
emmaleer8f4ba762015-08-14 07:44:46 -0700317 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700318 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
emmaleer8f4ba762015-08-14 07:44:46 -0700319
320 src += offset;
321 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
322 if (1 == deltaSrc) {
323 memcpy(dstRow, src, dstWidth);
324 } else {
325 for (int x = 0; x < dstWidth; x++) {
326 dst[x] = src[0];
327 src += deltaSrc;
328 }
329 }
msarette16b04a2015-04-15 07:32:19 -0700330 return SkSwizzler::kOpaque_ResultAlpha;
331}
332
scroggoab60c5b2015-08-06 06:08:18 -0700333static SkSwizzler::ResultAlpha swizzle_gray_to_565(
emmaleer8f4ba762015-08-14 07:44:46 -0700334 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700335 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
scroggoab60c5b2015-08-06 06:08:18 -0700336 // FIXME: Support dithering?
emmaleer8f4ba762015-08-14 07:44:46 -0700337 src += offset;
scroggoab60c5b2015-08-06 06:08:18 -0700338 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700339 for (int x = 0; x < dstWidth; x++) {
scroggoab60c5b2015-08-06 06:08:18 -0700340 dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
msarett5406d6f2015-08-31 06:55:13 -0700341 src += deltaSrc;
scroggoab60c5b2015-08-06 06:08:18 -0700342 }
343 return SkSwizzler::kOpaque_ResultAlpha;
344}
345
msarette16b04a2015-04-15 07:32:19 -0700346// kBGRX
347
msarett74114382015-03-16 11:55:18 -0700348static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32(
emmaleer8f4ba762015-08-14 07:44:46 -0700349 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700350 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett74114382015-03-16 11:55:18 -0700351
emmaleer8f4ba762015-08-14 07:44:46 -0700352 src += offset;
msarett74114382015-03-16 11:55:18 -0700353 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700354 for (int x = 0; x < dstWidth; x++) {
msarett74114382015-03-16 11:55:18 -0700355 dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]);
emmaleer8f4ba762015-08-14 07:44:46 -0700356 src += deltaSrc;
msarett74114382015-03-16 11:55:18 -0700357 }
358 return SkSwizzler::kOpaque_ResultAlpha;
359}
360
scroggocc2feb12015-08-14 08:32:46 -0700361static SkSwizzler::ResultAlpha swizzle_bgrx_to_565(
362 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700363 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
scroggocc2feb12015-08-14 08:32:46 -0700364 // FIXME: Support dithering?
365 src += offset;
366 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
367 for (int x = 0; x < dstWidth; x++) {
368 dst[x] = SkPack888ToRGB16(src[2], src[1], src[0]);
369 src += deltaSrc;
370 }
371 return SkSwizzler::kOpaque_ResultAlpha;
372}
373
msarett74114382015-03-16 11:55:18 -0700374// kBGRA
375
msaretteed039b2015-03-18 11:11:19 -0700376static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_unpremul(
emmaleer8f4ba762015-08-14 07:44:46 -0700377 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700378 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett74114382015-03-16 11:55:18 -0700379
emmaleer8f4ba762015-08-14 07:44:46 -0700380 src += offset;
msarett74114382015-03-16 11:55:18 -0700381 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
382 INIT_RESULT_ALPHA;
emmaleer8f4ba762015-08-14 07:44:46 -0700383 for (int x = 0; x < dstWidth; x++) {
msarett74114382015-03-16 11:55:18 -0700384 uint8_t alpha = src[3];
385 UPDATE_RESULT_ALPHA(alpha);
386 dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]);
emmaleer8f4ba762015-08-14 07:44:46 -0700387 src += deltaSrc;
msarett74114382015-03-16 11:55:18 -0700388 }
389 return COMPUTE_RESULT_ALPHA;
390}
391
msaretteed039b2015-03-18 11:11:19 -0700392static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_premul(
emmaleer8f4ba762015-08-14 07:44:46 -0700393 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700394 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msaretteed039b2015-03-18 11:11:19 -0700395
emmaleer8f4ba762015-08-14 07:44:46 -0700396 src += offset;
msaretteed039b2015-03-18 11:11:19 -0700397 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
398 INIT_RESULT_ALPHA;
emmaleer8f4ba762015-08-14 07:44:46 -0700399 for (int x = 0; x < dstWidth; x++) {
msaretteed039b2015-03-18 11:11:19 -0700400 uint8_t alpha = src[3];
401 UPDATE_RESULT_ALPHA(alpha);
402 dst[x] = SkPreMultiplyARGB(alpha, src[2], src[1], src[0]);
emmaleer8f4ba762015-08-14 07:44:46 -0700403 src += deltaSrc;
msaretteed039b2015-03-18 11:11:19 -0700404 }
405 return COMPUTE_RESULT_ALPHA;
406}
407
scroggoab60c5b2015-08-06 06:08:18 -0700408// kRGBX
msarett74114382015-03-16 11:55:18 -0700409static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32(
emmaleer8f4ba762015-08-14 07:44:46 -0700410 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700411 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett74114382015-03-16 11:55:18 -0700412
emmaleer8f4ba762015-08-14 07:44:46 -0700413 src += offset;
scroggof24f2242015-03-03 08:59:20 -0800414 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700415 for (int x = 0; x < dstWidth; x++) {
scroggof24f2242015-03-03 08:59:20 -0800416 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
emmaleer8f4ba762015-08-14 07:44:46 -0700417 src += deltaSrc;
scroggof24f2242015-03-03 08:59:20 -0800418 }
msarett74114382015-03-16 11:55:18 -0700419 return SkSwizzler::kOpaque_ResultAlpha;
scroggof24f2242015-03-03 08:59:20 -0800420}
421
scroggoab60c5b2015-08-06 06:08:18 -0700422static SkSwizzler::ResultAlpha swizzle_rgbx_to_565(
emmaleer8f4ba762015-08-14 07:44:46 -0700423 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700424 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
scroggoab60c5b2015-08-06 06:08:18 -0700425 // FIXME: Support dithering?
emmaleer8f4ba762015-08-14 07:44:46 -0700426 src += offset;
scroggoab60c5b2015-08-06 06:08:18 -0700427 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
emmaleer8f4ba762015-08-14 07:44:46 -0700428 for (int x = 0; x < dstWidth; x++) {
scroggoab60c5b2015-08-06 06:08:18 -0700429 dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
msarett5406d6f2015-08-31 06:55:13 -0700430 src += deltaSrc;
scroggoab60c5b2015-08-06 06:08:18 -0700431 }
432 return SkSwizzler::kOpaque_ResultAlpha;
433}
434
435
436// kRGBA
msarett74114382015-03-16 11:55:18 -0700437static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul(
emmaleer8f4ba762015-08-14 07:44:46 -0700438 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700439 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett74114382015-03-16 11:55:18 -0700440
emmaleer8f4ba762015-08-14 07:44:46 -0700441 src += offset;
scroggof24f2242015-03-03 08:59:20 -0800442 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
msarett74114382015-03-16 11:55:18 -0700443 INIT_RESULT_ALPHA;
emmaleer8f4ba762015-08-14 07:44:46 -0700444 for (int x = 0; x < dstWidth; x++) {
scroggof24f2242015-03-03 08:59:20 -0800445 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700446 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800447 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
emmaleer8f4ba762015-08-14 07:44:46 -0700448 src += deltaSrc;
scroggof24f2242015-03-03 08:59:20 -0800449 }
msarett74114382015-03-16 11:55:18 -0700450 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800451}
452
msarett74114382015-03-16 11:55:18 -0700453static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_unpremul(
emmaleer8f4ba762015-08-14 07:44:46 -0700454 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700455 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett74114382015-03-16 11:55:18 -0700456
emmaleer8f4ba762015-08-14 07:44:46 -0700457 src += offset;
scroggof24f2242015-03-03 08:59:20 -0800458 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
msarett74114382015-03-16 11:55:18 -0700459 INIT_RESULT_ALPHA;
emmaleer8f4ba762015-08-14 07:44:46 -0700460 for (int x = 0; x < dstWidth; x++) {
scroggof24f2242015-03-03 08:59:20 -0800461 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700462 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800463 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
emmaleer8f4ba762015-08-14 07:44:46 -0700464 src += deltaSrc;
scroggof24f2242015-03-03 08:59:20 -0800465 }
msarett74114382015-03-16 11:55:18 -0700466 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800467}
468
msarett74114382015-03-16 11:55:18 -0700469static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ(
emmaleer8f4ba762015-08-14 07:44:46 -0700470 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
msarett5406d6f2015-08-31 06:55:13 -0700471 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
msarett74114382015-03-16 11:55:18 -0700472
emmaleer8f4ba762015-08-14 07:44:46 -0700473 src += offset;
scroggof24f2242015-03-03 08:59:20 -0800474 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
msarett74114382015-03-16 11:55:18 -0700475 INIT_RESULT_ALPHA;
emmaleer8f4ba762015-08-14 07:44:46 -0700476 for (int x = 0; x < dstWidth; x++) {
scroggof24f2242015-03-03 08:59:20 -0800477 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700478 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800479 if (0 != alpha) {
480 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
481 }
emmaleer8f4ba762015-08-14 07:44:46 -0700482 src += deltaSrc;
scroggof24f2242015-03-03 08:59:20 -0800483 }
msarett74114382015-03-16 11:55:18 -0700484 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800485}
486
487/**
488 FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes.
489 This would be fine for drawing normally, but not for drawing with transfer modes. Being
490 honest means we can draw correctly with transfer modes, with the cost of not being able
491 to take advantage of Android's free unwritten pages. Something to keep in mind when we
492 decide whether to switch to unpremul default.
493static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow,
494 const uint8_t* SK_RESTRICT src,
emmaleer8f4ba762015-08-14 07:44:46 -0700495 int dstWidth, int bitsPerPixel, int offset,
scroggof24f2242015-03-03 08:59:20 -0800496 const SkPMColor[]) {
emmaleer8f4ba762015-08-14 07:44:46 -0700497 src += offset;
scroggof24f2242015-03-03 08:59:20 -0800498 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
499 unsigned alphaMask = 0xFF;
emmaleer8f4ba762015-08-14 07:44:46 -0700500 for (int x = 0; x < dstWidth; x++) {
scroggof24f2242015-03-03 08:59:20 -0800501 unsigned alpha = src[3];
502 // NOTE: We cheat here. The caller requested unpremul and skip zeroes. It's possible
503 // the color components are not zero, but we skip them anyway, meaning they'll remain
504 // zero (implied by the request to skip zeroes).
505 if (0 != alpha) {
506 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
507 }
508 src += deltaSrc;
509 alphaMask &= alpha;
510 }
511 return alphaMask != 0xFF;
512}
513*/
514
msarett74114382015-03-16 11:55:18 -0700515SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
516 const SkPMColor* ctable,
emmaleer8f4ba762015-08-14 07:44:46 -0700517 const SkImageInfo& dstInfo,
scroggoe7fc14b2015-10-02 13:14:46 -0700518 SkCodec::ZeroInitialized zeroInit) {
emmaleer8f4ba762015-08-14 07:44:46 -0700519 if (dstInfo.colorType() == kUnknown_SkColorType || kUnknown == sc) {
halcanary96fcdcc2015-08-27 07:41:13 -0700520 return nullptr;
scroggof24f2242015-03-03 08:59:20 -0800521 }
msarett74114382015-03-16 11:55:18 -0700522 if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc)
halcanary96fcdcc2015-08-27 07:41:13 -0700523 && nullptr == ctable) {
524 return nullptr;
scroggof24f2242015-03-03 08:59:20 -0800525 }
halcanary96fcdcc2015-08-27 07:41:13 -0700526 RowProc proc = nullptr;
emmaleer8f4ba762015-08-14 07:44:46 -0700527
scroggof24f2242015-03-03 08:59:20 -0800528 switch (sc) {
msarett99f567e2015-08-05 12:58:26 -0700529 case kBit:
emmaleer8f4ba762015-08-14 07:44:46 -0700530 switch (dstInfo.colorType()) {
msarett99f567e2015-08-05 12:58:26 -0700531 case kN32_SkColorType:
532 proc = &swizzle_bit_to_n32;
533 break;
534 case kIndex_8_SkColorType:
535 proc = &swizzle_bit_to_index;
536 break;
scroggocc2feb12015-08-14 08:32:46 -0700537 case kRGB_565_SkColorType:
538 proc = &swizzle_bit_to_565;
539 break;
msarett99f567e2015-08-05 12:58:26 -0700540 case kGray_8_SkColorType:
541 proc = &swizzle_bit_to_grayscale;
542 break;
543 default:
544 break;
545 }
546 break;
msarett74114382015-03-16 11:55:18 -0700547 case kIndex1:
548 case kIndex2:
549 case kIndex4:
emmaleer8f4ba762015-08-14 07:44:46 -0700550 switch (dstInfo.colorType()) {
msarett74114382015-03-16 11:55:18 -0700551 case kN32_SkColorType:
552 proc = &swizzle_small_index_to_n32;
553 break;
scroggocc2feb12015-08-14 08:32:46 -0700554 case kRGB_565_SkColorType:
555 proc = &swizzle_small_index_to_565;
556 break;
msarett438b2ad2015-04-09 12:43:10 -0700557 case kIndex_8_SkColorType:
558 proc = &swizzle_small_index_to_index;
msaretteed039b2015-03-18 11:11:19 -0700559 break;
msarett74114382015-03-16 11:55:18 -0700560 default:
561 break;
562 }
563 break;
scroggof24f2242015-03-03 08:59:20 -0800564 case kIndex:
emmaleer8f4ba762015-08-14 07:44:46 -0700565 switch (dstInfo.colorType()) {
scroggof24f2242015-03-03 08:59:20 -0800566 case kN32_SkColorType:
scroggo95526622015-03-17 05:02:17 -0700567 // We assume the color premultiplied ctable (or not) as desired.
scroggoeb602a52015-07-09 08:16:03 -0700568 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
scroggof24f2242015-03-03 08:59:20 -0800569 proc = &swizzle_index_to_n32_skipZ;
msaretteed039b2015-03-18 11:11:19 -0700570 break;
scroggof24f2242015-03-03 08:59:20 -0800571 } else {
572 proc = &swizzle_index_to_n32;
msaretteed039b2015-03-18 11:11:19 -0700573 break;
scroggof24f2242015-03-03 08:59:20 -0800574 }
575 break;
scroggoab60c5b2015-08-06 06:08:18 -0700576 case kRGB_565_SkColorType:
577 proc = &swizzle_index_to_565;
578 break;
msarett438b2ad2015-04-09 12:43:10 -0700579 case kIndex_8_SkColorType:
580 proc = &swizzle_index_to_index;
msaretteed039b2015-03-18 11:11:19 -0700581 break;
msarett74114382015-03-16 11:55:18 -0700582 default:
583 break;
584 }
585 break;
msarette16b04a2015-04-15 07:32:19 -0700586 case kGray:
emmaleer8f4ba762015-08-14 07:44:46 -0700587 switch (dstInfo.colorType()) {
msarette16b04a2015-04-15 07:32:19 -0700588 case kN32_SkColorType:
589 proc = &swizzle_gray_to_n32;
590 break;
591 case kGray_8_SkColorType:
592 proc = &swizzle_gray_to_gray;
scroggoab60c5b2015-08-06 06:08:18 -0700593 break;
594 case kRGB_565_SkColorType:
595 proc = &swizzle_gray_to_565;
596 break;
msarette16b04a2015-04-15 07:32:19 -0700597 default:
598 break;
599 }
600 break;
msarett74114382015-03-16 11:55:18 -0700601 case kBGR:
602 case kBGRX:
emmaleer8f4ba762015-08-14 07:44:46 -0700603 switch (dstInfo.colorType()) {
msarett74114382015-03-16 11:55:18 -0700604 case kN32_SkColorType:
605 proc = &swizzle_bgrx_to_n32;
606 break;
scroggocc2feb12015-08-14 08:32:46 -0700607 case kRGB_565_SkColorType:
608 proc = &swizzle_bgrx_to_565;
609 break;
msarett74114382015-03-16 11:55:18 -0700610 default:
611 break;
612 }
613 break;
614 case kBGRA:
emmaleer8f4ba762015-08-14 07:44:46 -0700615 switch (dstInfo.colorType()) {
msarett74114382015-03-16 11:55:18 -0700616 case kN32_SkColorType:
emmaleer8f4ba762015-08-14 07:44:46 -0700617 switch (dstInfo.alphaType()) {
msaretteed039b2015-03-18 11:11:19 -0700618 case kUnpremul_SkAlphaType:
619 proc = &swizzle_bgra_to_n32_unpremul;
620 break;
621 case kPremul_SkAlphaType:
622 proc = &swizzle_bgra_to_n32_premul;
623 break;
624 default:
625 break;
626 }
msarett74114382015-03-16 11:55:18 -0700627 break;
scroggof24f2242015-03-03 08:59:20 -0800628 default:
629 break;
630 }
631 break;
632 case kRGBX:
633 // TODO: Support other swizzles.
emmaleer8f4ba762015-08-14 07:44:46 -0700634 switch (dstInfo.colorType()) {
scroggof24f2242015-03-03 08:59:20 -0800635 case kN32_SkColorType:
636 proc = &swizzle_rgbx_to_n32;
637 break;
scroggoab60c5b2015-08-06 06:08:18 -0700638 case kRGB_565_SkColorType:
639 proc = &swizzle_rgbx_to_565;
scroggof24f2242015-03-03 08:59:20 -0800640 default:
641 break;
642 }
643 break;
644 case kRGBA:
emmaleer8f4ba762015-08-14 07:44:46 -0700645 switch (dstInfo.colorType()) {
scroggof24f2242015-03-03 08:59:20 -0800646 case kN32_SkColorType:
emmaleer8f4ba762015-08-14 07:44:46 -0700647 if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
scroggo95526622015-03-17 05:02:17 -0700648 // Respect zeroInit?
scroggof24f2242015-03-03 08:59:20 -0800649 proc = &swizzle_rgba_to_n32_unpremul;
650 } else {
scroggoeb602a52015-07-09 08:16:03 -0700651 if (SkCodec::kYes_ZeroInitialized == zeroInit) {
scroggof24f2242015-03-03 08:59:20 -0800652 proc = &swizzle_rgba_to_n32_premul_skipZ;
653 } else {
654 proc = &swizzle_rgba_to_n32_premul;
655 }
656 }
657 break;
658 default:
659 break;
660 }
661 break;
msarett74114382015-03-16 11:55:18 -0700662 case kRGB:
emmaleer8f4ba762015-08-14 07:44:46 -0700663 switch (dstInfo.colorType()) {
msarett74114382015-03-16 11:55:18 -0700664 case kN32_SkColorType:
665 proc = &swizzle_rgbx_to_n32;
666 break;
667 default:
668 break;
669 }
670 break;
emmaleer8f4ba762015-08-14 07:44:46 -0700671 case kRGB_565:
672 switch (dstInfo.colorType()) {
673 case kRGB_565_SkColorType:
674 proc = &sample565;
675 break;
676 default:
677 break;
678 }
scroggof24f2242015-03-03 08:59:20 -0800679 default:
680 break;
681 }
halcanary96fcdcc2015-08-27 07:41:13 -0700682 if (nullptr == proc) {
683 return nullptr;
scroggof24f2242015-03-03 08:59:20 -0800684 }
msarett74114382015-03-16 11:55:18 -0700685
686 // Store deltaSrc in bytes if it is an even multiple, otherwise use bits
emmaleer8f4ba762015-08-14 07:44:46 -0700687 int deltaSrc = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc);
688
scroggoe7fc14b2015-10-02 13:14:46 -0700689 return new SkSwizzler(proc, ctable, deltaSrc, dstInfo.width());
scroggof24f2242015-03-03 08:59:20 -0800690}
691
msarett74114382015-03-16 11:55:18 -0700692SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable,
scroggoe7fc14b2015-10-02 13:14:46 -0700693 int deltaSrc, int srcWidth)
scroggof24f2242015-03-03 08:59:20 -0800694 : fRowProc(proc)
695 , fColorTable(ctable)
msarett74114382015-03-16 11:55:18 -0700696 , fDeltaSrc(deltaSrc)
scroggoe7fc14b2015-10-02 13:14:46 -0700697 , fSrcWidth(srcWidth)
698 , fDstWidth(srcWidth)
699 , fSampleX(1)
700 , fX0(0)
701{}
702
703int SkSwizzler::onSetSampleX(int sampleX) {
704 SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be
705 // way to report failure?
706 fSampleX = sampleX;
707 fX0 = get_start_coord(sampleX);
708 fDstWidth = get_scaled_dimension(fSrcWidth, sampleX);
709
emmaleer8f4ba762015-08-14 07:44:46 -0700710 // check that fX0 is less than original width
scroggoe7fc14b2015-10-02 13:14:46 -0700711 SkASSERT(fX0 >= 0 && fX0 < fSrcWidth);
712 return fDstWidth;
emmaleer8f4ba762015-08-14 07:44:46 -0700713}
scroggof24f2242015-03-03 08:59:20 -0800714
msarett614aa072015-07-27 15:13:17 -0700715SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
halcanary96fcdcc2015-08-27 07:41:13 -0700716 SkASSERT(nullptr != dst && nullptr != src);
scroggoe7fc14b2015-10-02 13:14:46 -0700717 return fRowProc(dst, src, fDstWidth, fDeltaSrc, fSampleX * fDeltaSrc,
msarett5406d6f2015-08-31 06:55:13 -0700718 fX0 * fDeltaSrc, fColorTable);
scroggof24f2242015-03-03 08:59:20 -0800719}