1
2 /*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10 #include "SkBlitRow.h"
11 #include "SkCoreBlitters.h"
12 #include "SkColorPriv.h"
13 #include "SkDither.h"
14 #include "SkShader.h"
15 #include "SkTemplatesPriv.h"
16 #include "SkUtils.h"
17 #include "SkXfermode.h"
18
19 #if defined(__ARM_HAVE_NEON) && defined(SK_CPU_LENDIAN)
20 #define SK_USE_NEON
21 #include <arm_neon.h>
22 #else
23 // if we don't have neon, then our black blitter is worth the extra code
24 #define USE_BLACK_BLITTER
25 #endif
26
sk_dither_memset16(uint16_t dst[],uint16_t value,uint16_t other,int count)27 void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
28 int count) {
29 if (count > 0) {
30 // see if we need to write one short before we can cast to an 4byte ptr
31 // (we do this subtract rather than (unsigned)dst so we don't get warnings
32 // on 64bit machines)
33 if (((char*)dst - (char*)0) & 2) {
34 *dst++ = value;
35 count -= 1;
36 SkTSwap(value, other);
37 }
38
39 // fast way to set [value,other] pairs
40 #ifdef SK_CPU_BENDIAN
41 sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
42 #else
43 sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
44 #endif
45
46 if (count & 1) {
47 dst[count - 1] = value;
48 }
49 }
50 }
51
52 ///////////////////////////////////////////////////////////////////////////////
53
54 class SkRGB16_Blitter : public SkRasterBlitter {
55 public:
56 SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint);
57 virtual void blitH(int x, int y, int width);
58 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
59 const int16_t* runs);
60 virtual void blitV(int x, int y, int height, SkAlpha alpha);
61 virtual void blitRect(int x, int y, int width, int height);
62 virtual void blitMask(const SkMask&,
63 const SkIRect&);
64 virtual const SkBitmap* justAnOpaqueColor(uint32_t*);
65
66 protected:
67 SkPMColor fSrcColor32;
68 uint32_t fExpandedRaw16;
69 unsigned fScale;
70 uint16_t fColor16; // already scaled by fScale
71 uint16_t fRawColor16; // unscaled
72 uint16_t fRawDither16; // unscaled
73 SkBool8 fDoDither;
74
75 // illegal
76 SkRGB16_Blitter& operator=(const SkRGB16_Blitter&);
77
78 typedef SkRasterBlitter INHERITED;
79 };
80
81 class SkRGB16_Opaque_Blitter : public SkRGB16_Blitter {
82 public:
83 SkRGB16_Opaque_Blitter(const SkBitmap& device, const SkPaint& paint);
84 virtual void blitH(int x, int y, int width);
85 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
86 const int16_t* runs);
87 virtual void blitV(int x, int y, int height, SkAlpha alpha);
88 virtual void blitRect(int x, int y, int width, int height);
89 virtual void blitMask(const SkMask&,
90 const SkIRect&);
91
92 private:
93 typedef SkRGB16_Blitter INHERITED;
94 };
95
96 #ifdef USE_BLACK_BLITTER
97 class SkRGB16_Black_Blitter : public SkRGB16_Opaque_Blitter {
98 public:
99 SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint);
100 virtual void blitMask(const SkMask&, const SkIRect&);
101 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
102 const int16_t* runs);
103
104 private:
105 typedef SkRGB16_Opaque_Blitter INHERITED;
106 };
107 #endif
108
109 class SkRGB16_Shader_Blitter : public SkShaderBlitter {
110 public:
111 SkRGB16_Shader_Blitter(const SkBitmap& device, const SkPaint& paint);
112 virtual ~SkRGB16_Shader_Blitter();
113 virtual void blitH(int x, int y, int width);
114 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
115 const int16_t* runs);
116 virtual void blitRect(int x, int y, int width, int height);
117
118 protected:
119 SkPMColor* fBuffer;
120 SkBlitRow::Proc fOpaqueProc;
121 SkBlitRow::Proc fAlphaProc;
122
123 private:
124 // illegal
125 SkRGB16_Shader_Blitter& operator=(const SkRGB16_Shader_Blitter&);
126
127 typedef SkShaderBlitter INHERITED;
128 };
129
130 // used only if the shader can perform shadSpan16
131 class SkRGB16_Shader16_Blitter : public SkRGB16_Shader_Blitter {
132 public:
133 SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint);
134 virtual void blitH(int x, int y, int width);
135 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
136 const int16_t* runs);
137 virtual void blitRect(int x, int y, int width, int height);
138
139 private:
140 typedef SkRGB16_Shader_Blitter INHERITED;
141 };
142
143 class SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter {
144 public:
145 SkRGB16_Shader_Xfermode_Blitter(const SkBitmap& device, const SkPaint& paint);
146 virtual ~SkRGB16_Shader_Xfermode_Blitter();
147 virtual void blitH(int x, int y, int width);
148 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
149 const int16_t* runs);
150
151 private:
152 SkXfermode* fXfermode;
153 SkPMColor* fBuffer;
154 uint8_t* fAAExpand;
155
156 // illegal
157 SkRGB16_Shader_Xfermode_Blitter& operator=(const SkRGB16_Shader_Xfermode_Blitter&);
158
159 typedef SkShaderBlitter INHERITED;
160 };
161
162 ///////////////////////////////////////////////////////////////////////////////
163 #ifdef USE_BLACK_BLITTER
SkRGB16_Black_Blitter(const SkBitmap & device,const SkPaint & paint)164 SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint)
165 : INHERITED(device, paint) {
166 SkASSERT(paint.getShader() == NULL);
167 SkASSERT(paint.getColorFilter() == NULL);
168 SkASSERT(paint.getXfermode() == NULL);
169 SkASSERT(paint.getColor() == SK_ColorBLACK);
170 }
171
172 #if 1
173 #define black_8_pixels(mask, dst) \
174 do { \
175 if (mask & 0x80) dst[0] = 0; \
176 if (mask & 0x40) dst[1] = 0; \
177 if (mask & 0x20) dst[2] = 0; \
178 if (mask & 0x10) dst[3] = 0; \
179 if (mask & 0x08) dst[4] = 0; \
180 if (mask & 0x04) dst[5] = 0; \
181 if (mask & 0x02) dst[6] = 0; \
182 if (mask & 0x01) dst[7] = 0; \
183 } while (0)
184 #else
black_8_pixels(U8CPU mask,uint16_t dst[])185 static inline black_8_pixels(U8CPU mask, uint16_t dst[])
186 {
187 if (mask & 0x80) dst[0] = 0;
188 if (mask & 0x40) dst[1] = 0;
189 if (mask & 0x20) dst[2] = 0;
190 if (mask & 0x10) dst[3] = 0;
191 if (mask & 0x08) dst[4] = 0;
192 if (mask & 0x04) dst[5] = 0;
193 if (mask & 0x02) dst[6] = 0;
194 if (mask & 0x01) dst[7] = 0;
195 }
196 #endif
197
198 #define SK_BLITBWMASK_NAME SkRGB16_Black_BlitBW
199 #define SK_BLITBWMASK_ARGS
200 #define SK_BLITBWMASK_BLIT8(mask, dst) black_8_pixels(mask, dst)
201 #define SK_BLITBWMASK_GETADDR getAddr16
202 #define SK_BLITBWMASK_DEVTYPE uint16_t
203 #include "SkBlitBWMaskTemplate.h"
204
blitMask(const SkMask & mask,const SkIRect & clip)205 void SkRGB16_Black_Blitter::blitMask(const SkMask& mask,
206 const SkIRect& clip) {
207 if (mask.fFormat == SkMask::kBW_Format) {
208 SkRGB16_Black_BlitBW(fDevice, mask, clip);
209 } else {
210 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
211 const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
212 unsigned width = clip.width();
213 unsigned height = clip.height();
214 unsigned deviceRB = fDevice.rowBytes() - (width << 1);
215 unsigned maskRB = mask.fRowBytes - width;
216
217 SkASSERT((int)height > 0);
218 SkASSERT((int)width > 0);
219 SkASSERT((int)deviceRB >= 0);
220 SkASSERT((int)maskRB >= 0);
221
222 do {
223 unsigned w = width;
224 do {
225 unsigned aa = *alpha++;
226 *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
227 device += 1;
228 } while (--w != 0);
229 device = (uint16_t*)((char*)device + deviceRB);
230 alpha += maskRB;
231 } while (--height != 0);
232 }
233 }
234
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)235 void SkRGB16_Black_Blitter::blitAntiH(int x, int y,
236 const SkAlpha* SK_RESTRICT antialias,
237 const int16_t* SK_RESTRICT runs) {
238 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
239
240 for (;;) {
241 int count = runs[0];
242 SkASSERT(count >= 0);
243 if (count <= 0) {
244 return;
245 }
246 runs += count;
247
248 unsigned aa = antialias[0];
249 antialias += count;
250 if (aa) {
251 if (aa == 255) {
252 memset(device, 0, count << 1);
253 } else {
254 aa = SkAlpha255To256(255 - aa);
255 do {
256 *device = SkAlphaMulRGB16(*device, aa);
257 device += 1;
258 } while (--count != 0);
259 continue;
260 }
261 }
262 device += count;
263 }
264 }
265 #endif
266
267 ///////////////////////////////////////////////////////////////////////////////
268 ///////////////////////////////////////////////////////////////////////////////
269
SkRGB16_Opaque_Blitter(const SkBitmap & device,const SkPaint & paint)270 SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkBitmap& device,
271 const SkPaint& paint)
272 : INHERITED(device, paint) {}
273
blitH(int x,int y,int width)274 void SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) {
275 SkASSERT(width > 0);
276 SkASSERT(x + width <= fDevice.width());
277 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
278 uint16_t srcColor = fColor16;
279
280 SkASSERT(fRawColor16 == srcColor);
281 if (fDoDither) {
282 uint16_t ditherColor = fRawDither16;
283 if ((x ^ y) & 1) {
284 SkTSwap(ditherColor, srcColor);
285 }
286 sk_dither_memset16(device, srcColor, ditherColor, width);
287 } else {
288 sk_memset16(device, srcColor, width);
289 }
290 }
291
292 // return 1 or 0 from a bool
Bool2Int(int value)293 static inline int Bool2Int(int value) {
294 return !!value;
295 }
296
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)297 void SkRGB16_Opaque_Blitter::blitAntiH(int x, int y,
298 const SkAlpha* SK_RESTRICT antialias,
299 const int16_t* SK_RESTRICT runs) {
300 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
301 uint16_t srcColor = fRawColor16;
302 uint32_t srcExpanded = fExpandedRaw16;
303 int ditherInt = Bool2Int(fDoDither);
304 uint16_t ditherColor = fRawDither16;
305 // if we have no dithering, this will always fail
306 if ((x ^ y) & ditherInt) {
307 SkTSwap(ditherColor, srcColor);
308 }
309 for (;;) {
310 int count = runs[0];
311 SkASSERT(count >= 0);
312 if (count <= 0) {
313 return;
314 }
315 runs += count;
316
317 unsigned aa = antialias[0];
318 antialias += count;
319 if (aa) {
320 if (aa == 255) {
321 if (ditherInt) {
322 sk_dither_memset16(device, srcColor,
323 ditherColor, count);
324 } else {
325 sk_memset16(device, srcColor, count);
326 }
327 } else {
328 // TODO: respect fDoDither
329 unsigned scale5 = SkAlpha255To256(aa) >> 3;
330 uint32_t src32 = srcExpanded * scale5;
331 scale5 = 32 - scale5; // now we can use it on the device
332 int n = count;
333 do {
334 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
335 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
336 } while (--n != 0);
337 goto DONE;
338 }
339 }
340 device += count;
341
342 DONE:
343 // if we have no dithering, this will always fail
344 if (count & ditherInt) {
345 SkTSwap(ditherColor, srcColor);
346 }
347 }
348 }
349
350 #define solid_8_pixels(mask, dst, color) \
351 do { \
352 if (mask & 0x80) dst[0] = color; \
353 if (mask & 0x40) dst[1] = color; \
354 if (mask & 0x20) dst[2] = color; \
355 if (mask & 0x10) dst[3] = color; \
356 if (mask & 0x08) dst[4] = color; \
357 if (mask & 0x04) dst[5] = color; \
358 if (mask & 0x02) dst[6] = color; \
359 if (mask & 0x01) dst[7] = color; \
360 } while (0)
361
362 #define SK_BLITBWMASK_NAME SkRGB16_BlitBW
363 #define SK_BLITBWMASK_ARGS , uint16_t color
364 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color)
365 #define SK_BLITBWMASK_GETADDR getAddr16
366 #define SK_BLITBWMASK_DEVTYPE uint16_t
367 #include "SkBlitBWMaskTemplate.h"
368
blend_compact(uint32_t src32,uint32_t dst32,unsigned scale5)369 static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
370 return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
371 }
372
blitMask(const SkMask & mask,const SkIRect & clip)373 void SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask,
374 const SkIRect& clip) {
375 if (mask.fFormat == SkMask::kBW_Format) {
376 SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
377 return;
378 }
379
380 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
381 const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
382 int width = clip.width();
383 int height = clip.height();
384 unsigned deviceRB = fDevice.rowBytes() - (width << 1);
385 unsigned maskRB = mask.fRowBytes - width;
386 uint32_t expanded32 = fExpandedRaw16;
387
388 #ifdef SK_USE_NEON
389 #define UNROLL 8
390 do {
391 int w = width;
392 if (w >= UNROLL) {
393 uint32x4_t color; /* can use same one */
394 uint32x4_t dev_lo, dev_hi;
395 uint32x4_t t1, t2;
396 uint32x4_t wn1, wn2;
397 uint16x4_t odev_lo, odev_hi;
398 uint16x4_t alpha_lo, alpha_hi;
399 uint16x8_t alpha_full;
400
401 color = vdupq_n_u32(expanded32);
402
403 do {
404 /* alpha is 8x8, widen and split to get pair of 16x4's */
405 alpha_full = vmovl_u8(vld1_u8(alpha));
406 alpha_full = vaddq_u16(alpha_full, vshrq_n_u16(alpha_full,7));
407 alpha_full = vshrq_n_u16(alpha_full, 3);
408 alpha_lo = vget_low_u16(alpha_full);
409 alpha_hi = vget_high_u16(alpha_full);
410
411 dev_lo = vmovl_u16(vld1_u16(device));
412 dev_hi = vmovl_u16(vld1_u16(device+4));
413
414 /* unpack in 32 bits */
415 dev_lo = vorrq_u32(
416 vandq_u32(dev_lo, vdupq_n_u32(0x0000F81F)),
417 vshlq_n_u32(vandq_u32(dev_lo,
418 vdupq_n_u32(0x000007E0)),
419 16)
420 );
421 dev_hi = vorrq_u32(
422 vandq_u32(dev_hi, vdupq_n_u32(0x0000F81F)),
423 vshlq_n_u32(vandq_u32(dev_hi,
424 vdupq_n_u32(0x000007E0)),
425 16)
426 );
427
428 /* blend the two */
429 t1 = vmulq_u32(vsubq_u32(color, dev_lo), vmovl_u16(alpha_lo));
430 t1 = vshrq_n_u32(t1, 5);
431 dev_lo = vaddq_u32(dev_lo, t1);
432
433 t1 = vmulq_u32(vsubq_u32(color, dev_hi), vmovl_u16(alpha_hi));
434 t1 = vshrq_n_u32(t1, 5);
435 dev_hi = vaddq_u32(dev_hi, t1);
436
437 /* re-compact and store */
438 wn1 = vandq_u32(dev_lo, vdupq_n_u32(0x0000F81F)),
439 wn2 = vshrq_n_u32(dev_lo, 16);
440 wn2 = vandq_u32(wn2, vdupq_n_u32(0x000007E0));
441 odev_lo = vmovn_u32(vorrq_u32(wn1, wn2));
442
443 wn1 = vandq_u32(dev_hi, vdupq_n_u32(0x0000F81F)),
444 wn2 = vshrq_n_u32(dev_hi, 16);
445 wn2 = vandq_u32(wn2, vdupq_n_u32(0x000007E0));
446 odev_hi = vmovn_u32(vorrq_u32(wn1, wn2));
447
448 vst1_u16(device, odev_lo);
449 vst1_u16(device+4, odev_hi);
450
451 device += UNROLL;
452 alpha += UNROLL;
453 w -= UNROLL;
454 } while (w >= UNROLL);
455 }
456
457 /* residuals (which is everything if we have no neon) */
458 while (w > 0) {
459 *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
460 SkAlpha255To256(*alpha++) >> 3);
461 device += 1;
462 --w;
463 }
464 device = (uint16_t*)((char*)device + deviceRB);
465 alpha += maskRB;
466 } while (--height != 0);
467 #undef UNROLL
468 #else // non-neon code
469 do {
470 int w = width;
471 do {
472 *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
473 SkAlpha255To256(*alpha++) >> 3);
474 device += 1;
475 } while (--w != 0);
476 device = (uint16_t*)((char*)device + deviceRB);
477 alpha += maskRB;
478 } while (--height != 0);
479 #endif
480 }
481
blitV(int x,int y,int height,SkAlpha alpha)482 void SkRGB16_Opaque_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
483 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
484 unsigned deviceRB = fDevice.rowBytes();
485
486 // TODO: respect fDoDither
487 unsigned scale5 = SkAlpha255To256(alpha) >> 3;
488 uint32_t src32 = fExpandedRaw16 * scale5;
489 scale5 = 32 - scale5;
490 do {
491 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
492 *device = SkCompact_rgb_16((src32 + dst32) >> 5);
493 device = (uint16_t*)((char*)device + deviceRB);
494 } while (--height != 0);
495 }
496
blitRect(int x,int y,int width,int height)497 void SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) {
498 SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
499 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
500 unsigned deviceRB = fDevice.rowBytes();
501 uint16_t color16 = fColor16;
502
503 if (fDoDither) {
504 uint16_t ditherColor = fRawDither16;
505 if ((x ^ y) & 1) {
506 SkTSwap(ditherColor, color16);
507 }
508 while (--height >= 0) {
509 sk_dither_memset16(device, color16, ditherColor, width);
510 SkTSwap(ditherColor, color16);
511 device = (uint16_t*)((char*)device + deviceRB);
512 }
513 } else { // no dither
514 while (--height >= 0) {
515 sk_memset16(device, color16, width);
516 device = (uint16_t*)((char*)device + deviceRB);
517 }
518 }
519 }
520
521 ///////////////////////////////////////////////////////////////////////////////
522
SkRGB16_Blitter(const SkBitmap & device,const SkPaint & paint)523 SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
524 : INHERITED(device) {
525 SkColor color = paint.getColor();
526
527 fSrcColor32 = SkPreMultiplyColor(color);
528 fScale = SkAlpha255To256(SkColorGetA(color));
529
530 int r = SkColorGetR(color);
531 int g = SkColorGetG(color);
532 int b = SkColorGetB(color);
533
534 fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
535 // if we're dithered, use fRawDither16 to hold that.
536 if ((fDoDither = paint.isDither()) != false) {
537 fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
538 }
539
540 fExpandedRaw16 = SkExpand_rgb_16(fRawColor16);
541
542 fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
543 SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
544 SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
545 }
546
justAnOpaqueColor(uint32_t * value)547 const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
548 if (!fDoDither && 256 == fScale) {
549 *value = fRawColor16;
550 return &fDevice;
551 }
552 return NULL;
553 }
554
pmcolor_to_expand16(SkPMColor c)555 static uint32_t pmcolor_to_expand16(SkPMColor c) {
556 unsigned r = SkGetPackedR32(c);
557 unsigned g = SkGetPackedG32(c);
558 unsigned b = SkGetPackedB32(c);
559 return (g << 24) | (r << 13) | (b << 2);
560 }
561
blend32_16_row(SkPMColor src,uint16_t dst[],int count)562 static inline void blend32_16_row(SkPMColor src, uint16_t dst[], int count) {
563 SkASSERT(count > 0);
564 uint32_t src_expand = pmcolor_to_expand16(src);
565 unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3;
566 do {
567 uint32_t dst_expand = SkExpand_rgb_16(*dst) * scale;
568 *dst = SkCompact_rgb_16((src_expand + dst_expand) >> 5);
569 dst += 1;
570 } while (--count != 0);
571 }
572
blitH(int x,int y,int width)573 void SkRGB16_Blitter::blitH(int x, int y, int width) {
574 SkASSERT(width > 0);
575 SkASSERT(x + width <= fDevice.width());
576 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
577
578 // TODO: respect fDoDither
579 blend32_16_row(fSrcColor32, device, width);
580 }
581
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)582 void SkRGB16_Blitter::blitAntiH(int x, int y,
583 const SkAlpha* SK_RESTRICT antialias,
584 const int16_t* SK_RESTRICT runs) {
585 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
586 uint32_t srcExpanded = fExpandedRaw16;
587 unsigned scale = fScale;
588
589 // TODO: respect fDoDither
590 for (;;) {
591 int count = runs[0];
592 SkASSERT(count >= 0);
593 if (count <= 0) {
594 return;
595 }
596 runs += count;
597
598 unsigned aa = antialias[0];
599 antialias += count;
600 if (aa) {
601 unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
602 uint32_t src32 = srcExpanded * scale5;
603 scale5 = 32 - scale5;
604 do {
605 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
606 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
607 } while (--count != 0);
608 continue;
609 }
610 device += count;
611 }
612 }
613
blend_8_pixels(U8CPU bw,uint16_t dst[],unsigned dst_scale,U16CPU srcColor)614 static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
615 U16CPU srcColor) {
616 if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
617 if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
618 if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
619 if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
620 if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
621 if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
622 if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
623 if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
624 }
625
626 #define SK_BLITBWMASK_NAME SkRGB16_BlendBW
627 #define SK_BLITBWMASK_ARGS , unsigned dst_scale, U16CPU src_color
628 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, dst_scale, src_color)
629 #define SK_BLITBWMASK_GETADDR getAddr16
630 #define SK_BLITBWMASK_DEVTYPE uint16_t
631 #include "SkBlitBWMaskTemplate.h"
632
blitMask(const SkMask & mask,const SkIRect & clip)633 void SkRGB16_Blitter::blitMask(const SkMask& mask,
634 const SkIRect& clip) {
635 if (mask.fFormat == SkMask::kBW_Format) {
636 SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
637 return;
638 }
639
640 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
641 const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
642 int width = clip.width();
643 int height = clip.height();
644 unsigned deviceRB = fDevice.rowBytes() - (width << 1);
645 unsigned maskRB = mask.fRowBytes - width;
646 uint32_t color32 = fExpandedRaw16;
647
648 unsigned scale256 = fScale;
649 do {
650 int w = width;
651 do {
652 unsigned aa = *alpha++;
653 unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
654 uint32_t src32 = color32 * scale;
655 uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
656 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
657 } while (--w != 0);
658 device = (uint16_t*)((char*)device + deviceRB);
659 alpha += maskRB;
660 } while (--height != 0);
661 }
662
blitV(int x,int y,int height,SkAlpha alpha)663 void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
664 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
665 unsigned deviceRB = fDevice.rowBytes();
666
667 // TODO: respect fDoDither
668 unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
669 uint32_t src32 = fExpandedRaw16 * scale5;
670 scale5 = 32 - scale5;
671 do {
672 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
673 *device = SkCompact_rgb_16((src32 + dst32) >> 5);
674 device = (uint16_t*)((char*)device + deviceRB);
675 } while (--height != 0);
676 }
677
blitRect(int x,int y,int width,int height)678 void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
679 SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
680 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
681 unsigned deviceRB = fDevice.rowBytes();
682 SkPMColor src32 = fSrcColor32;
683
684 while (--height >= 0) {
685 blend32_16_row(src32, device, width);
686 device = (uint16_t*)((char*)device + deviceRB);
687 }
688 }
689
690 ///////////////////////////////////////////////////////////////////////////////
691
SkRGB16_Shader16_Blitter(const SkBitmap & device,const SkPaint & paint)692 SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
693 const SkPaint& paint)
694 : SkRGB16_Shader_Blitter(device, paint) {
695 SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags));
696 }
697
blitH(int x,int y,int width)698 void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) {
699 SkASSERT(x + width <= fDevice.width());
700
701 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
702 SkShader* shader = fShader;
703
704 int alpha = shader->getSpan16Alpha();
705 if (0xFF == alpha) {
706 shader->shadeSpan16(x, y, device, width);
707 } else {
708 uint16_t* span16 = (uint16_t*)fBuffer;
709 shader->shadeSpan16(x, y, span16, width);
710 SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
711 }
712 }
713
blitRect(int x,int y,int width,int height)714 void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
715 SkShader* shader = fShader;
716 uint16_t* dst = fDevice.getAddr16(x, y);
717 size_t dstRB = fDevice.rowBytes();
718 int alpha = shader->getSpan16Alpha();
719
720 if (0xFF == alpha) {
721 if (fShaderFlags & SkShader::kConstInY16_Flag) {
722 // have the shader blit directly into the device the first time
723 shader->shadeSpan16(x, y, dst, width);
724 // and now just memcpy that line on the subsequent lines
725 if (--height > 0) {
726 const uint16_t* orig = dst;
727 do {
728 dst = (uint16_t*)((char*)dst + dstRB);
729 memcpy(dst, orig, width << 1);
730 } while (--height);
731 }
732 } else { // need to call shadeSpan16 for every line
733 do {
734 shader->shadeSpan16(x, y, dst, width);
735 y += 1;
736 dst = (uint16_t*)((char*)dst + dstRB);
737 } while (--height);
738 }
739 } else {
740 int scale = SkAlpha255To256(alpha);
741 uint16_t* span16 = (uint16_t*)fBuffer;
742 if (fShaderFlags & SkShader::kConstInY16_Flag) {
743 shader->shadeSpan16(x, y, span16, width);
744 do {
745 SkBlendRGB16(span16, dst, scale, width);
746 dst = (uint16_t*)((char*)dst + dstRB);
747 } while (--height);
748 } else {
749 do {
750 shader->shadeSpan16(x, y, span16, width);
751 SkBlendRGB16(span16, dst, scale, width);
752 y += 1;
753 dst = (uint16_t*)((char*)dst + dstRB);
754 } while (--height);
755 }
756 }
757 }
758
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)759 void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
760 const SkAlpha* SK_RESTRICT antialias,
761 const int16_t* SK_RESTRICT runs) {
762 SkShader* shader = fShader;
763 SkPMColor* SK_RESTRICT span = fBuffer;
764 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
765
766 int alpha = shader->getSpan16Alpha();
767 uint16_t* span16 = (uint16_t*)span;
768
769 if (0xFF == alpha) {
770 for (;;) {
771 int count = *runs;
772 if (count <= 0) {
773 break;
774 }
775 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
776
777 int aa = *antialias;
778 if (aa == 255) {
779 // go direct to the device!
780 shader->shadeSpan16(x, y, device, count);
781 } else if (aa) {
782 shader->shadeSpan16(x, y, span16, count);
783 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
784 }
785 device += count;
786 runs += count;
787 antialias += count;
788 x += count;
789 }
790 } else { // span alpha is < 255
791 alpha = SkAlpha255To256(alpha);
792 for (;;) {
793 int count = *runs;
794 if (count <= 0) {
795 break;
796 }
797 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
798
799 int aa = SkAlphaMul(*antialias, alpha);
800 if (aa) {
801 shader->shadeSpan16(x, y, span16, count);
802 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
803 }
804
805 device += count;
806 runs += count;
807 antialias += count;
808 x += count;
809 }
810 }
811 }
812
813 ///////////////////////////////////////////////////////////////////////////////
814
SkRGB16_Shader_Blitter(const SkBitmap & device,const SkPaint & paint)815 SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
816 const SkPaint& paint)
817 : INHERITED(device, paint) {
818 SkASSERT(paint.getXfermode() == NULL);
819
820 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
821
822 // compute SkBlitRow::Procs
823 unsigned flags = 0;
824
825 uint32_t shaderFlags = fShaderFlags;
826 // shaders take care of global alpha, so we never set it in SkBlitRow
827 if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
828 flags |= SkBlitRow::kSrcPixelAlpha_Flag;
829 }
830 // don't dither if the shader is really 16bit
831 if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
832 flags |= SkBlitRow::kDither_Flag;
833 }
834 // used when we know our global alpha is 0xFF
835 fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
836 // used when we know our global alpha is < 0xFF
837 fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
838 SkBitmap::kRGB_565_Config);
839 }
840
~SkRGB16_Shader_Blitter()841 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
842 sk_free(fBuffer);
843 }
844
blitH(int x,int y,int width)845 void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
846 SkASSERT(x + width <= fDevice.width());
847
848 fShader->shadeSpan(x, y, fBuffer, width);
849 // shaders take care of global alpha, so we pass 0xFF (should be ignored)
850 fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
851 }
852
blitRect(int x,int y,int width,int height)853 void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
854 SkShader* shader = fShader;
855 SkBlitRow::Proc proc = fOpaqueProc;
856 SkPMColor* buffer = fBuffer;
857 uint16_t* dst = fDevice.getAddr16(x, y);
858 size_t dstRB = fDevice.rowBytes();
859
860 if (fShaderFlags & SkShader::kConstInY32_Flag) {
861 shader->shadeSpan(x, y, buffer, width);
862 do {
863 proc(dst, buffer, width, 0xFF, x, y);
864 y += 1;
865 dst = (uint16_t*)((char*)dst + dstRB);
866 } while (--height);
867 } else {
868 do {
869 shader->shadeSpan(x, y, buffer, width);
870 proc(dst, buffer, width, 0xFF, x, y);
871 y += 1;
872 dst = (uint16_t*)((char*)dst + dstRB);
873 } while (--height);
874 }
875 }
876
count_nonzero_span(const int16_t runs[],const SkAlpha aa[])877 static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
878 int count = 0;
879 for (;;) {
880 int n = *runs;
881 if (n == 0 || *aa == 0) {
882 break;
883 }
884 runs += n;
885 aa += n;
886 count += n;
887 }
888 return count;
889 }
890
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)891 void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
892 const SkAlpha* SK_RESTRICT antialias,
893 const int16_t* SK_RESTRICT runs) {
894 SkShader* shader = fShader;
895 SkPMColor* SK_RESTRICT span = fBuffer;
896 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
897
898 for (;;) {
899 int count = *runs;
900 if (count <= 0) {
901 break;
902 }
903 int aa = *antialias;
904 if (0 == aa) {
905 device += count;
906 runs += count;
907 antialias += count;
908 x += count;
909 continue;
910 }
911
912 int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
913
914 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
915 shader->shadeSpan(x, y, span, nonZeroCount);
916
917 SkPMColor* localSpan = span;
918 for (;;) {
919 SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
920 proc(device, localSpan, count, aa, x, y);
921
922 x += count;
923 device += count;
924 runs += count;
925 antialias += count;
926 nonZeroCount -= count;
927 if (nonZeroCount == 0) {
928 break;
929 }
930 localSpan += count;
931 SkASSERT(nonZeroCount > 0);
932 count = *runs;
933 SkASSERT(count > 0);
934 aa = *antialias;
935 }
936 }
937 }
938
939 ///////////////////////////////////////////////////////////////////////
940
SkRGB16_Shader_Xfermode_Blitter(const SkBitmap & device,const SkPaint & paint)941 SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
942 const SkBitmap& device, const SkPaint& paint)
943 : INHERITED(device, paint) {
944 fXfermode = paint.getXfermode();
945 SkASSERT(fXfermode);
946 fXfermode->ref();
947
948 int width = device.width();
949 fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
950 fAAExpand = (uint8_t*)(fBuffer + width);
951 }
952
~SkRGB16_Shader_Xfermode_Blitter()953 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
954 fXfermode->unref();
955 sk_free(fBuffer);
956 }
957
blitH(int x,int y,int width)958 void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
959 SkASSERT(x + width <= fDevice.width());
960
961 uint16_t* device = fDevice.getAddr16(x, y);
962 SkPMColor* span = fBuffer;
963
964 fShader->shadeSpan(x, y, span, width);
965 fXfermode->xfer16(device, span, width, NULL);
966 }
967
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)968 void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
969 const SkAlpha* SK_RESTRICT antialias,
970 const int16_t* SK_RESTRICT runs) {
971 SkShader* shader = fShader;
972 SkXfermode* mode = fXfermode;
973 SkPMColor* SK_RESTRICT span = fBuffer;
974 uint8_t* SK_RESTRICT aaExpand = fAAExpand;
975 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
976
977 for (;;) {
978 int count = *runs;
979 if (count <= 0) {
980 break;
981 }
982 int aa = *antialias;
983 if (0 == aa) {
984 device += count;
985 runs += count;
986 antialias += count;
987 x += count;
988 continue;
989 }
990
991 int nonZeroCount = count + count_nonzero_span(runs + count,
992 antialias + count);
993
994 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
995 shader->shadeSpan(x, y, span, nonZeroCount);
996
997 x += nonZeroCount;
998 SkPMColor* localSpan = span;
999 for (;;) {
1000 if (aa == 0xFF) {
1001 mode->xfer16(device, localSpan, count, NULL);
1002 } else {
1003 SkASSERT(aa);
1004 memset(aaExpand, aa, count);
1005 mode->xfer16(device, localSpan, count, aaExpand);
1006 }
1007 device += count;
1008 runs += count;
1009 antialias += count;
1010 nonZeroCount -= count;
1011 if (nonZeroCount == 0) {
1012 break;
1013 }
1014 localSpan += count;
1015 SkASSERT(nonZeroCount > 0);
1016 count = *runs;
1017 SkASSERT(count > 0);
1018 aa = *antialias;
1019 }
1020 }
1021 }
1022
1023 ///////////////////////////////////////////////////////////////////////////////
1024
SkBlitter_ChooseD565(const SkBitmap & device,const SkPaint & paint,void * storage,size_t storageSize)1025 SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
1026 void* storage, size_t storageSize) {
1027 SkBlitter* blitter;
1028 SkShader* shader = paint.getShader();
1029 SkXfermode* mode = paint.getXfermode();
1030
1031 // we require a shader if there is an xfermode, handled by our caller
1032 SkASSERT(NULL == mode || NULL != shader);
1033
1034 if (shader) {
1035 if (mode) {
1036 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Xfermode_Blitter,
1037 storage, storageSize, (device, paint));
1038 } else if (shader->canCallShadeSpan16()) {
1039 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader16_Blitter,
1040 storage, storageSize, (device, paint));
1041 } else {
1042 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Blitter,
1043 storage, storageSize, (device, paint));
1044 }
1045 } else {
1046 // no shader, no xfermode, (and we always ignore colorfilter)
1047 SkColor color = paint.getColor();
1048 if (0 == SkColorGetA(color)) {
1049 SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
1050 #ifdef USE_BLACK_BLITTER
1051 } else if (SK_ColorBLACK == color) {
1052 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Black_Blitter, storage,
1053 storageSize, (device, paint));
1054 #endif
1055 } else if (0xFF == SkColorGetA(color)) {
1056 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Opaque_Blitter, storage,
1057 storageSize, (device, paint));
1058 } else {
1059 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Blitter, storage,
1060 storageSize, (device, paint));
1061 }
1062 }
1063
1064 return blitter;
1065 }
1066