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