3 * Copyright 2006 The Android Open Source Project
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
10 #include "SkBlitRow.h"
11 #include "SkCoreBlitters.h"
12 #include "SkColorPriv.h"
16 #include "SkUtilsArm.h"
17 #include "SkXfermode.h"
19 #if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
22 // if we don't have neon, then our black blitter is worth the extra code
23 #define USE_BLACK_BLITTER
26 void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
29 // see if we need to write one short before we can cast to an 4byte ptr
30 // (we do this subtract rather than (unsigned)dst so we don't get warnings
32 if (((char*)dst - (char*)0) & 2) {
35 SkTSwap(value, other);
38 // fast way to set [value,other] pairs
40 sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
42 sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
46 dst[count - 1] = value;
51 ///////////////////////////////////////////////////////////////////////////////
53 class SkRGB16_Blitter : public SkRasterBlitter {
55 SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint);
56 virtual void blitH(int x, int y, int width);
57 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
59 virtual void blitV(int x, int y, int height, SkAlpha alpha);
60 virtual void blitRect(int x, int y, int width, int height);
61 virtual void blitMask(const SkMask&,
63 virtual const SkBitmap* justAnOpaqueColor(uint32_t*);
66 SkPMColor fSrcColor32;
67 uint32_t fExpandedRaw16;
69 uint16_t fColor16; // already scaled by fScale
70 uint16_t fRawColor16; // unscaled
71 uint16_t fRawDither16; // unscaled
75 SkRGB16_Blitter& operator=(const SkRGB16_Blitter&);
77 typedef SkRasterBlitter INHERITED;
80 class SkRGB16_Opaque_Blitter : public SkRGB16_Blitter {
82 SkRGB16_Opaque_Blitter(const SkBitmap& device, const SkPaint& paint);
83 virtual void blitH(int x, int y, int width);
84 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
86 virtual void blitV(int x, int y, int height, SkAlpha alpha);
87 virtual void blitRect(int x, int y, int width, int height);
88 virtual void blitMask(const SkMask&,
92 typedef SkRGB16_Blitter INHERITED;
95 #ifdef USE_BLACK_BLITTER
96 class SkRGB16_Black_Blitter : public SkRGB16_Opaque_Blitter {
98 SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint);
99 virtual void blitMask(const SkMask&, const SkIRect&);
100 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
101 const int16_t* runs);
104 typedef SkRGB16_Opaque_Blitter INHERITED;
108 class SkRGB16_Shader_Blitter : public SkShaderBlitter {
110 SkRGB16_Shader_Blitter(const SkBitmap& device, const SkPaint& paint,
111 SkShader::Context* shaderContext);
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);
120 SkBlitRow::Proc fOpaqueProc;
121 SkBlitRow::Proc fAlphaProc;
125 SkRGB16_Shader_Blitter& operator=(const SkRGB16_Shader_Blitter&);
127 typedef SkShaderBlitter INHERITED;
130 // used only if the shader can perform shadSpan16
131 class SkRGB16_Shader16_Blitter : public SkRGB16_Shader_Blitter {
133 SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint,
134 SkShader::Context* shaderContext);
135 virtual void blitH(int x, int y, int width);
136 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
137 const int16_t* runs);
138 virtual void blitRect(int x, int y, int width, int height);
141 typedef SkRGB16_Shader_Blitter INHERITED;
144 class SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter {
146 SkRGB16_Shader_Xfermode_Blitter(const SkBitmap& device, const SkPaint& paint,
147 SkShader::Context* shaderContext);
148 virtual ~SkRGB16_Shader_Xfermode_Blitter();
149 virtual void blitH(int x, int y, int width);
150 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
151 const int16_t* runs);
154 SkXfermode* fXfermode;
159 SkRGB16_Shader_Xfermode_Blitter& operator=(const SkRGB16_Shader_Xfermode_Blitter&);
161 typedef SkShaderBlitter INHERITED;
164 ///////////////////////////////////////////////////////////////////////////////
165 #ifdef USE_BLACK_BLITTER
166 SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint)
167 : INHERITED(device, paint) {
168 SkASSERT(paint.getShader() == NULL);
169 SkASSERT(paint.getColorFilter() == NULL);
170 SkASSERT(paint.getXfermode() == NULL);
171 SkASSERT(paint.getColor() == SK_ColorBLACK);
175 #define black_8_pixels(mask, dst) \
177 if (mask & 0x80) dst[0] = 0; \
178 if (mask & 0x40) dst[1] = 0; \
179 if (mask & 0x20) dst[2] = 0; \
180 if (mask & 0x10) dst[3] = 0; \
181 if (mask & 0x08) dst[4] = 0; \
182 if (mask & 0x04) dst[5] = 0; \
183 if (mask & 0x02) dst[6] = 0; \
184 if (mask & 0x01) dst[7] = 0; \
187 static inline black_8_pixels(U8CPU mask, uint16_t dst[])
189 if (mask & 0x80) dst[0] = 0;
190 if (mask & 0x40) dst[1] = 0;
191 if (mask & 0x20) dst[2] = 0;
192 if (mask & 0x10) dst[3] = 0;
193 if (mask & 0x08) dst[4] = 0;
194 if (mask & 0x04) dst[5] = 0;
195 if (mask & 0x02) dst[6] = 0;
196 if (mask & 0x01) dst[7] = 0;
200 #define SK_BLITBWMASK_NAME SkRGB16_Black_BlitBW
201 #define SK_BLITBWMASK_ARGS
202 #define SK_BLITBWMASK_BLIT8(mask, dst) black_8_pixels(mask, dst)
203 #define SK_BLITBWMASK_GETADDR getAddr16
204 #define SK_BLITBWMASK_DEVTYPE uint16_t
205 #include "SkBlitBWMaskTemplate.h"
207 void SkRGB16_Black_Blitter::blitMask(const SkMask& mask,
208 const SkIRect& clip) {
209 if (mask.fFormat == SkMask::kBW_Format) {
210 SkRGB16_Black_BlitBW(fDevice, mask, clip);
212 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
213 const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
214 unsigned width = clip.width();
215 unsigned height = clip.height();
216 size_t deviceRB = fDevice.rowBytes() - (width << 1);
217 unsigned maskRB = mask.fRowBytes - width;
219 SkASSERT((int)height > 0);
220 SkASSERT((int)width > 0);
221 SkASSERT((int)deviceRB >= 0);
222 SkASSERT((int)maskRB >= 0);
227 unsigned aa = *alpha++;
228 *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
231 device = (uint16_t*)((char*)device + deviceRB);
233 } while (--height != 0);
237 void SkRGB16_Black_Blitter::blitAntiH(int x, int y,
238 const SkAlpha* SK_RESTRICT antialias,
239 const int16_t* SK_RESTRICT runs) {
240 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
244 SkASSERT(count >= 0);
250 unsigned aa = antialias[0];
254 memset(device, 0, count << 1);
256 aa = SkAlpha255To256(255 - aa);
258 *device = SkAlphaMulRGB16(*device, aa);
260 } while (--count != 0);
269 ///////////////////////////////////////////////////////////////////////////////
270 ///////////////////////////////////////////////////////////////////////////////
272 SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkBitmap& device,
273 const SkPaint& paint)
274 : INHERITED(device, paint) {}
276 void SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) {
278 SkASSERT(x + width <= fDevice.width());
279 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
280 uint16_t srcColor = fColor16;
282 SkASSERT(fRawColor16 == srcColor);
284 uint16_t ditherColor = fRawDither16;
286 SkTSwap(ditherColor, srcColor);
288 sk_dither_memset16(device, srcColor, ditherColor, width);
290 sk_memset16(device, srcColor, width);
294 // return 1 or 0 from a bool
295 static inline int Bool2Int(int value) {
299 void SkRGB16_Opaque_Blitter::blitAntiH(int x, int y,
300 const SkAlpha* SK_RESTRICT antialias,
301 const int16_t* SK_RESTRICT runs) {
302 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
303 uint16_t srcColor = fRawColor16;
304 uint32_t srcExpanded = fExpandedRaw16;
305 int ditherInt = Bool2Int(fDoDither);
306 uint16_t ditherColor = fRawDither16;
307 // if we have no dithering, this will always fail
308 if ((x ^ y) & ditherInt) {
309 SkTSwap(ditherColor, srcColor);
313 SkASSERT(count >= 0);
319 unsigned aa = antialias[0];
324 sk_dither_memset16(device, srcColor,
327 sk_memset16(device, srcColor, count);
330 // TODO: respect fDoDither
331 unsigned scale5 = SkAlpha255To256(aa) >> 3;
332 uint32_t src32 = srcExpanded * scale5;
333 scale5 = 32 - scale5; // now we can use it on the device
336 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
337 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
345 // if we have no dithering, this will always fail
346 if (count & ditherInt) {
347 SkTSwap(ditherColor, srcColor);
352 #define solid_8_pixels(mask, dst, color) \
354 if (mask & 0x80) dst[0] = color; \
355 if (mask & 0x40) dst[1] = color; \
356 if (mask & 0x20) dst[2] = color; \
357 if (mask & 0x10) dst[3] = color; \
358 if (mask & 0x08) dst[4] = color; \
359 if (mask & 0x04) dst[5] = color; \
360 if (mask & 0x02) dst[6] = color; \
361 if (mask & 0x01) dst[7] = color; \
364 #define SK_BLITBWMASK_NAME SkRGB16_BlitBW
365 #define SK_BLITBWMASK_ARGS , uint16_t color
366 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color)
367 #define SK_BLITBWMASK_GETADDR getAddr16
368 #define SK_BLITBWMASK_DEVTYPE uint16_t
369 #include "SkBlitBWMaskTemplate.h"
371 static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
372 return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
375 void SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask,
376 const SkIRect& clip) {
377 if (mask.fFormat == SkMask::kBW_Format) {
378 SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
382 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
383 const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
384 int width = clip.width();
385 int height = clip.height();
386 size_t deviceRB = fDevice.rowBytes() - (width << 1);
387 unsigned maskRB = mask.fRowBytes - width;
388 uint32_t expanded32 = fExpandedRaw16;
390 #if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
395 uint32x4_t color, dev_lo, dev_hi;
396 uint32x4_t wn1, wn2, tmp;
397 uint32x4_t vmask_g16, vmask_ng16;
398 uint16x8_t valpha, vdev;
399 uint16x4_t odev_lo, odev_hi, valpha_lo, valpha_hi;
402 vmask_g16 = vdupq_n_u32(SK_G16_MASK_IN_PLACE);
403 vmask_ng16 = vdupq_n_u32(~SK_G16_MASK_IN_PLACE);
404 color = vdupq_n_u32(expanded32);
407 // alpha is 8x8, widen and split to get a pair of 16x4
408 valpha = vaddw_u8(vdupq_n_u16(1), vld1_u8(alpha));
409 valpha = vshrq_n_u16(valpha, 3);
410 valpha_lo = vget_low_u16(valpha);
411 valpha_hi = vget_high_u16(valpha);
414 vdev = vld1q_u16(device);
415 dev_lo = vmovl_u16(vget_low_u16(vdev));
416 dev_hi = vmovl_u16(vget_high_u16(vdev));
418 // unpack them in 32 bits
419 dev_lo = (dev_lo & vmask_ng16) | vshlq_n_u32(dev_lo & vmask_g16, 16);
420 dev_hi = (dev_hi & vmask_ng16) | vshlq_n_u32(dev_hi & vmask_g16, 16);
423 tmp = (color - dev_lo) * vmovl_u16(valpha_lo);
424 tmp = vshrq_n_u32(tmp, 5);
427 tmp = vmulq_u32(color - dev_hi, vmovl_u16(valpha_hi));
428 tmp = vshrq_n_u32(tmp, 5);
432 wn1 = dev_lo & vmask_ng16;
433 wn2 = vshrq_n_u32(dev_lo, 16) & vmask_g16;
434 odev_lo = vmovn_u32(wn1 | wn2);
436 wn1 = dev_hi & vmask_ng16;
437 wn2 = vshrq_n_u32(dev_hi, 16) & vmask_g16;
438 odev_hi = vmovn_u32(wn1 | wn2);
441 vst1q_u16(device, vcombine_u16(odev_lo, odev_hi));
446 } while (w >= UNROLL);
451 *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
452 SkAlpha255To256(*alpha++) >> 3);
456 device = (uint16_t*)((char*)device + deviceRB);
458 } while (--height != 0);
460 #else // non-neon code
464 *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
465 SkAlpha255To256(*alpha++) >> 3);
468 device = (uint16_t*)((char*)device + deviceRB);
470 } while (--height != 0);
474 void SkRGB16_Opaque_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
475 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
476 size_t deviceRB = fDevice.rowBytes();
478 // TODO: respect fDoDither
479 unsigned scale5 = SkAlpha255To256(alpha) >> 3;
480 uint32_t src32 = fExpandedRaw16 * scale5;
481 scale5 = 32 - scale5;
483 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
484 *device = SkCompact_rgb_16((src32 + dst32) >> 5);
485 device = (uint16_t*)((char*)device + deviceRB);
486 } while (--height != 0);
489 void SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) {
490 SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
491 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
492 size_t deviceRB = fDevice.rowBytes();
493 uint16_t color16 = fColor16;
496 uint16_t ditherColor = fRawDither16;
498 SkTSwap(ditherColor, color16);
500 while (--height >= 0) {
501 sk_dither_memset16(device, color16, ditherColor, width);
502 SkTSwap(ditherColor, color16);
503 device = (uint16_t*)((char*)device + deviceRB);
505 } else { // no dither
506 while (--height >= 0) {
507 sk_memset16(device, color16, width);
508 device = (uint16_t*)((char*)device + deviceRB);
513 ///////////////////////////////////////////////////////////////////////////////
515 SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
516 : INHERITED(device) {
517 SkColor color = paint.getColor();
519 fSrcColor32 = SkPreMultiplyColor(color);
520 fScale = SkAlpha255To256(SkColorGetA(color));
522 int r = SkColorGetR(color);
523 int g = SkColorGetG(color);
524 int b = SkColorGetB(color);
526 fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
527 // if we're dithered, use fRawDither16 to hold that.
528 if ((fDoDither = paint.isDither()) != false) {
529 fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
532 fExpandedRaw16 = SkExpand_rgb_16(fRawColor16);
534 fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
535 SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
536 SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
539 const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
540 if (!fDoDither && 256 == fScale) {
541 *value = fRawColor16;
547 static uint32_t pmcolor_to_expand16(SkPMColor c) {
548 unsigned r = SkGetPackedR32(c);
549 unsigned g = SkGetPackedG32(c);
550 unsigned b = SkGetPackedB32(c);
551 return (g << 24) | (r << 13) | (b << 2);
554 static inline void blend32_16_row(SkPMColor src, uint16_t dst[], int count) {
556 uint32_t src_expand = pmcolor_to_expand16(src);
557 unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3;
559 uint32_t dst_expand = SkExpand_rgb_16(*dst) * scale;
560 *dst = SkCompact_rgb_16((src_expand + dst_expand) >> 5);
562 } while (--count != 0);
565 void SkRGB16_Blitter::blitH(int x, int y, int width) {
567 SkASSERT(x + width <= fDevice.width());
568 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
570 // TODO: respect fDoDither
571 blend32_16_row(fSrcColor32, device, width);
574 void SkRGB16_Blitter::blitAntiH(int x, int y,
575 const SkAlpha* SK_RESTRICT antialias,
576 const int16_t* SK_RESTRICT runs) {
577 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
578 uint32_t srcExpanded = fExpandedRaw16;
579 unsigned scale = fScale;
581 // TODO: respect fDoDither
584 SkASSERT(count >= 0);
590 unsigned aa = antialias[0];
593 unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
594 uint32_t src32 = srcExpanded * scale5;
595 scale5 = 32 - scale5;
597 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
598 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
599 } while (--count != 0);
606 static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
608 if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
609 if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
610 if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
611 if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
612 if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
613 if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
614 if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
615 if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
618 #define SK_BLITBWMASK_NAME SkRGB16_BlendBW
619 #define SK_BLITBWMASK_ARGS , unsigned dst_scale, U16CPU src_color
620 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, dst_scale, src_color)
621 #define SK_BLITBWMASK_GETADDR getAddr16
622 #define SK_BLITBWMASK_DEVTYPE uint16_t
623 #include "SkBlitBWMaskTemplate.h"
625 void SkRGB16_Blitter::blitMask(const SkMask& mask,
626 const SkIRect& clip) {
627 if (mask.fFormat == SkMask::kBW_Format) {
628 SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
632 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
633 const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
634 int width = clip.width();
635 int height = clip.height();
636 size_t deviceRB = fDevice.rowBytes() - (width << 1);
637 unsigned maskRB = mask.fRowBytes - width;
638 uint32_t color32 = fExpandedRaw16;
640 unsigned scale256 = fScale;
644 unsigned aa = *alpha++;
645 unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
646 uint32_t src32 = color32 * scale;
647 uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
648 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
650 device = (uint16_t*)((char*)device + deviceRB);
652 } while (--height != 0);
655 void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
656 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
657 size_t deviceRB = fDevice.rowBytes();
659 // TODO: respect fDoDither
660 unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
661 uint32_t src32 = fExpandedRaw16 * scale5;
662 scale5 = 32 - scale5;
664 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
665 *device = SkCompact_rgb_16((src32 + dst32) >> 5);
666 device = (uint16_t*)((char*)device + deviceRB);
667 } while (--height != 0);
670 void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
671 SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
672 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
673 size_t deviceRB = fDevice.rowBytes();
674 SkPMColor src32 = fSrcColor32;
676 while (--height >= 0) {
677 blend32_16_row(src32, device, width);
678 device = (uint16_t*)((char*)device + deviceRB);
682 ///////////////////////////////////////////////////////////////////////////////
684 SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
685 const SkPaint& paint,
686 SkShader::Context* shaderContext)
687 : SkRGB16_Shader_Blitter(device, paint, shaderContext) {
688 SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags));
691 void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) {
692 SkASSERT(x + width <= fDevice.width());
694 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
695 SkShader::Context* shaderContext = fShaderContext;
697 int alpha = shaderContext->getSpan16Alpha();
699 shaderContext->shadeSpan16(x, y, device, width);
701 uint16_t* span16 = (uint16_t*)fBuffer;
702 shaderContext->shadeSpan16(x, y, span16, width);
703 SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
707 void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
708 SkShader::Context* shaderContext = fShaderContext;
709 uint16_t* dst = fDevice.getAddr16(x, y);
710 size_t dstRB = fDevice.rowBytes();
711 int alpha = shaderContext->getSpan16Alpha();
714 if (fShaderFlags & SkShader::kConstInY16_Flag) {
715 // have the shader blit directly into the device the first time
716 shaderContext->shadeSpan16(x, y, dst, width);
717 // and now just memcpy that line on the subsequent lines
719 const uint16_t* orig = dst;
721 dst = (uint16_t*)((char*)dst + dstRB);
722 memcpy(dst, orig, width << 1);
725 } else { // need to call shadeSpan16 for every line
727 shaderContext->shadeSpan16(x, y, dst, width);
729 dst = (uint16_t*)((char*)dst + dstRB);
733 int scale = SkAlpha255To256(alpha);
734 uint16_t* span16 = (uint16_t*)fBuffer;
735 if (fShaderFlags & SkShader::kConstInY16_Flag) {
736 shaderContext->shadeSpan16(x, y, span16, width);
738 SkBlendRGB16(span16, dst, scale, width);
739 dst = (uint16_t*)((char*)dst + dstRB);
743 shaderContext->shadeSpan16(x, y, span16, width);
744 SkBlendRGB16(span16, dst, scale, width);
746 dst = (uint16_t*)((char*)dst + dstRB);
752 void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
753 const SkAlpha* SK_RESTRICT antialias,
754 const int16_t* SK_RESTRICT runs) {
755 SkShader::Context* shaderContext = fShaderContext;
756 SkPMColor* SK_RESTRICT span = fBuffer;
757 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
759 int alpha = shaderContext->getSpan16Alpha();
760 uint16_t* span16 = (uint16_t*)span;
768 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
772 // go direct to the device!
773 shaderContext->shadeSpan16(x, y, device, count);
775 shaderContext->shadeSpan16(x, y, span16, count);
776 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
783 } else { // span alpha is < 255
784 alpha = SkAlpha255To256(alpha);
790 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
792 int aa = SkAlphaMul(*antialias, alpha);
794 shaderContext->shadeSpan16(x, y, span16, count);
795 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
806 ///////////////////////////////////////////////////////////////////////////////
808 SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
809 const SkPaint& paint,
810 SkShader::Context* shaderContext)
811 : INHERITED(device, paint, shaderContext) {
812 SkASSERT(paint.getXfermode() == NULL);
814 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
816 // compute SkBlitRow::Procs
819 uint32_t shaderFlags = fShaderFlags;
820 // shaders take care of global alpha, so we never set it in SkBlitRow
821 if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
822 flags |= SkBlitRow::kSrcPixelAlpha_Flag;
824 // don't dither if the shader is really 16bit
825 if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
826 flags |= SkBlitRow::kDither_Flag;
828 // used when we know our global alpha is 0xFF
829 fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
830 // used when we know our global alpha is < 0xFF
831 fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
832 SkBitmap::kRGB_565_Config);
835 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
839 void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
840 SkASSERT(x + width <= fDevice.width());
842 fShaderContext->shadeSpan(x, y, fBuffer, width);
843 // shaders take care of global alpha, so we pass 0xFF (should be ignored)
844 fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
847 void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
848 SkShader::Context* shaderContext = fShaderContext;
849 SkBlitRow::Proc proc = fOpaqueProc;
850 SkPMColor* buffer = fBuffer;
851 uint16_t* dst = fDevice.getAddr16(x, y);
852 size_t dstRB = fDevice.rowBytes();
854 if (fShaderFlags & SkShader::kConstInY32_Flag) {
855 shaderContext->shadeSpan(x, y, buffer, width);
857 proc(dst, buffer, width, 0xFF, x, y);
859 dst = (uint16_t*)((char*)dst + dstRB);
863 shaderContext->shadeSpan(x, y, buffer, width);
864 proc(dst, buffer, width, 0xFF, x, y);
866 dst = (uint16_t*)((char*)dst + dstRB);
871 static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
875 if (n == 0 || *aa == 0) {
885 void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
886 const SkAlpha* SK_RESTRICT antialias,
887 const int16_t* SK_RESTRICT runs) {
888 SkShader::Context* shaderContext = fShaderContext;
889 SkPMColor* SK_RESTRICT span = fBuffer;
890 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
906 int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
908 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
909 shaderContext->shadeSpan(x, y, span, nonZeroCount);
911 SkPMColor* localSpan = span;
913 SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
914 proc(device, localSpan, count, aa, x, y);
920 nonZeroCount -= count;
921 if (nonZeroCount == 0) {
925 SkASSERT(nonZeroCount > 0);
933 ///////////////////////////////////////////////////////////////////////
935 SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
936 const SkBitmap& device, const SkPaint& paint,
937 SkShader::Context* shaderContext)
938 : INHERITED(device, paint, shaderContext) {
939 fXfermode = paint.getXfermode();
943 int width = device.width();
944 fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
945 fAAExpand = (uint8_t*)(fBuffer + width);
948 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
953 void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
954 SkASSERT(x + width <= fDevice.width());
956 uint16_t* device = fDevice.getAddr16(x, y);
957 SkPMColor* span = fBuffer;
959 fShaderContext->shadeSpan(x, y, span, width);
960 fXfermode->xfer16(device, span, width, NULL);
963 void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
964 const SkAlpha* SK_RESTRICT antialias,
965 const int16_t* SK_RESTRICT runs) {
966 SkShader::Context* shaderContext = fShaderContext;
967 SkXfermode* mode = fXfermode;
968 SkPMColor* SK_RESTRICT span = fBuffer;
969 uint8_t* SK_RESTRICT aaExpand = fAAExpand;
970 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
986 int nonZeroCount = count + count_nonzero_span(runs + count,
989 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
990 shaderContext->shadeSpan(x, y, span, nonZeroCount);
993 SkPMColor* localSpan = span;
996 mode->xfer16(device, localSpan, count, NULL);
999 memset(aaExpand, aa, count);
1000 mode->xfer16(device, localSpan, count, aaExpand);
1005 nonZeroCount -= count;
1006 if (nonZeroCount == 0) {
1010 SkASSERT(nonZeroCount > 0);
1012 SkASSERT(count > 0);
1018 ///////////////////////////////////////////////////////////////////////////////
1020 SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
1021 SkShader::Context* shaderContext,
1022 SkTBlitterAllocator* allocator) {
1023 SkASSERT(allocator != NULL);
1026 SkShader* shader = paint.getShader();
1027 SkXfermode* mode = paint.getXfermode();
1029 // we require a shader if there is an xfermode, handled by our caller
1030 SkASSERT(NULL == mode || NULL != shader);
1033 SkASSERT(shaderContext != NULL);
1035 blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint,
1037 } else if (shaderContext->canCallShadeSpan16()) {
1038 blitter = allocator->createT<SkRGB16_Shader16_Blitter>(device, paint, shaderContext);
1040 blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint, shaderContext);
1043 // no shader, no xfermode, (and we always ignore colorfilter)
1044 SkColor color = paint.getColor();
1045 if (0 == SkColorGetA(color)) {
1046 blitter = allocator->createT<SkNullBlitter>();
1047 #ifdef USE_BLACK_BLITTER
1048 } else if (SK_ColorBLACK == color) {
1049 blitter = allocator->createT<SkRGB16_Black_Blitter>(device, paint);
1051 } else if (0xFF == SkColorGetA(color)) {
1052 blitter = allocator->createT<SkRGB16_Opaque_Blitter>(device, paint);
1054 blitter = allocator->createT<SkRGB16_Blitter>(device, paint);