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"
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);
25 #if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
28 // if we don't have neon, then our black blitter is worth the extra code
29 #define USE_BLACK_BLITTER
32 void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
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
38 if (((char*)dst - (char*)0) & 2) {
41 SkTSwap(value, other);
44 // fast way to set [value,other] pairs
46 sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
48 sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
52 dst[count - 1] = value;
57 ///////////////////////////////////////////////////////////////////////////////
59 class SkRGB16_Blitter : public SkRasterBlitter {
61 SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint);
62 void blitH(int x, int y, int width) SK_OVERRIDE;
63 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
64 const int16_t* runs) SK_OVERRIDE;
65 void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE;
66 void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
67 virtual void blitMask(const SkMask&,
68 const SkIRect&) SK_OVERRIDE;
69 const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE;
72 SkPMColor fSrcColor32;
73 uint32_t fExpandedRaw16;
75 uint16_t fColor16; // already scaled by fScale
76 uint16_t fRawColor16; // unscaled
77 uint16_t fRawDither16; // unscaled
80 SkBlitRow::ColorProc16 fColorProc16;
83 SkRGB16_Blitter& operator=(const SkRGB16_Blitter&);
85 typedef SkRasterBlitter INHERITED;
88 class SkRGB16_Opaque_Blitter : public SkRGB16_Blitter {
90 SkRGB16_Opaque_Blitter(const SkBitmap& device, const SkPaint& paint);
91 void blitH(int x, int y, int width) SK_OVERRIDE;
92 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
93 const int16_t* runs) SK_OVERRIDE;
94 void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE;
95 void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
96 virtual void blitMask(const SkMask&,
97 const SkIRect&) SK_OVERRIDE;
100 typedef SkRGB16_Blitter INHERITED;
103 #ifdef USE_BLACK_BLITTER
104 class SkRGB16_Black_Blitter : public SkRGB16_Opaque_Blitter {
106 SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint);
107 void blitMask(const SkMask&, const SkIRect&) SK_OVERRIDE;
108 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
109 const int16_t* runs) SK_OVERRIDE;
112 typedef SkRGB16_Opaque_Blitter INHERITED;
116 class SkRGB16_Shader_Blitter : public SkShaderBlitter {
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) SK_OVERRIDE;
122 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
123 const int16_t* runs) SK_OVERRIDE;
124 void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
128 SkBlitRow::Proc16 fOpaqueProc;
129 SkBlitRow::Proc16 fAlphaProc;
133 SkRGB16_Shader_Blitter& operator=(const SkRGB16_Shader_Blitter&);
135 typedef SkShaderBlitter INHERITED;
138 // used only if the shader can perform shadSpan16
139 class SkRGB16_Shader16_Blitter : public SkRGB16_Shader_Blitter {
141 SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint,
142 SkShader::Context* shaderContext);
143 void blitH(int x, int y, int width) SK_OVERRIDE;
144 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
145 const int16_t* runs) SK_OVERRIDE;
146 void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
149 typedef SkRGB16_Shader_Blitter INHERITED;
152 class SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter {
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) SK_OVERRIDE;
158 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
159 const int16_t* runs) SK_OVERRIDE;
162 SkXfermode* fXfermode;
167 SkRGB16_Shader_Xfermode_Blitter& operator=(const SkRGB16_Shader_Xfermode_Blitter&);
169 typedef SkShaderBlitter INHERITED;
172 ///////////////////////////////////////////////////////////////////////////////
173 #ifdef USE_BLACK_BLITTER
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);
183 #define black_8_pixels(mask, dst) \
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; \
195 static inline black_8_pixels(U8CPU mask, uint16_t dst[])
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;
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"
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);
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;
227 SkASSERT((int)height > 0);
228 SkASSERT((int)width > 0);
229 SkASSERT((int)deviceRB >= 0);
230 SkASSERT((int)maskRB >= 0);
235 unsigned aa = *alpha++;
236 *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
239 device = (uint16_t*)((char*)device + deviceRB);
241 } while (--height != 0);
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);
252 SkASSERT(count >= 0);
258 unsigned aa = antialias[0];
262 memset(device, 0, count << 1);
264 aa = SkAlpha255To256(255 - aa);
266 *device = SkAlphaMulRGB16(*device, aa);
268 } while (--count != 0);
277 ///////////////////////////////////////////////////////////////////////////////
278 ///////////////////////////////////////////////////////////////////////////////
280 SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkBitmap& device,
281 const SkPaint& paint)
282 : INHERITED(device, paint) {}
284 void SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) {
286 SkASSERT(x + width <= fDevice.width());
287 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
288 uint16_t srcColor = fColor16;
290 SkASSERT(fRawColor16 == srcColor);
292 uint16_t ditherColor = fRawDither16;
294 SkTSwap(ditherColor, srcColor);
296 sk_dither_memset16(device, srcColor, ditherColor, width);
298 sk_memset16(device, srcColor, width);
302 // return 1 or 0 from a bool
303 static inline int Bool2Int(int value) {
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);
321 SkASSERT(count >= 0);
327 unsigned aa = antialias[0];
332 sk_dither_memset16(device, srcColor,
335 sk_memset16(device, srcColor, count);
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
344 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
345 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
353 // if we have no dithering, this will always fail
354 if (count & ditherInt) {
355 SkTSwap(ditherColor, srcColor);
360 #define solid_8_pixels(mask, dst, color) \
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; \
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"
379 #if !defined(SK_MIPS_HAS_DSP)
380 static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
381 return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
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);
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;
400 #if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
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;
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);
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);
424 vdev = vld1q_u16(device);
425 dev_lo = vmovl_u16(vget_low_u16(vdev));
426 dev_hi = vmovl_u16(vget_high_u16(vdev));
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);
433 tmp = (color - dev_lo) * vmovl_u16(valpha_lo);
434 tmp = vshrq_n_u32(tmp, 5);
437 tmp = vmulq_u32(color - dev_hi, vmovl_u16(valpha_hi));
438 tmp = vshrq_n_u32(tmp, 5);
442 wn1 = dev_lo & vmask_ng16;
443 wn2 = vshrq_n_u32(dev_lo, 16) & vmask_g16;
444 odev_lo = vmovn_u32(wn1 | wn2);
446 wn1 = dev_hi & vmask_ng16;
447 wn2 = vshrq_n_u32(dev_hi, 16) & vmask_g16;
448 odev_hi = vmovn_u32(wn1 | wn2);
451 vst1q_u16(device, vcombine_u16(odev_lo, odev_hi));
456 } while (w >= UNROLL);
461 *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
462 SkAlpha255To256(*alpha++) >> 3);
466 device = (uint16_t*)((char*)device + deviceRB);
468 } while (--height != 0);
470 #elif SK_MIPS_HAS_DSP
471 blitmask_d565_opaque_mips(width, height, device, deviceRB, alpha, expanded32, maskRB);
472 #else // non-neon code
476 *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
477 SkAlpha255To256(*alpha++) >> 3);
480 device = (uint16_t*)((char*)device + deviceRB);
482 } while (--height != 0);
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();
490 // TODO: respect fDoDither
491 unsigned scale5 = SkAlpha255To256(alpha) >> 3;
492 uint32_t src32 = fExpandedRaw16 * scale5;
493 scale5 = 32 - scale5;
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);
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;
508 uint16_t ditherColor = fRawDither16;
510 SkTSwap(ditherColor, color16);
512 while (--height >= 0) {
513 sk_dither_memset16(device, color16, ditherColor, width);
514 SkTSwap(ditherColor, color16);
515 device = (uint16_t*)((char*)device + deviceRB);
517 } else { // no dither
518 while (--height >= 0) {
519 sk_memset16(device, color16, width);
520 device = (uint16_t*)((char*)device + deviceRB);
525 ///////////////////////////////////////////////////////////////////////////////
527 SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
528 : INHERITED(device) {
529 SkColor color = paint.getColor();
531 fSrcColor32 = SkPreMultiplyColor(color);
532 fScale = SkAlpha255To256(SkColorGetA(color));
534 int r = SkColorGetR(color);
535 int g = SkColorGetG(color);
536 int b = SkColorGetB(color);
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);
544 fExpandedRaw16 = SkExpand_rgb_16(fRawColor16);
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));
550 // compute SkBlitRow::Procs
553 if (SkGetPackedA32(fSrcColor32) < 0xFF) {
554 flags |= SkBlitRow::kSrcPixelAlpha_Flag;
558 flags |= SkBlitRow::kDither_Flag;
561 fColorProc16 = SkBlitRow::ColorFactory16(flags);
564 const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
565 if (!fDoDither && 256 == fScale) {
566 *value = fRawColor16;
572 void SkRGB16_Blitter::blitH(int x, int y, int width) {
574 SkASSERT(x + width <= fDevice.width());
575 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
577 fColorProc16(device, fSrcColor32, width, x, y);
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;
587 // TODO: respect fDoDither
590 SkASSERT(count >= 0);
596 unsigned aa = antialias[0];
599 unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
600 uint32_t src32 = srcExpanded * scale5;
601 scale5 = 32 - scale5;
603 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
604 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
605 } while (--count != 0);
612 static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
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);
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"
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);
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;
646 unsigned scale256 = fScale;
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);
656 device = (uint16_t*)((char*)device + deviceRB);
658 } while (--height != 0);
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();
665 // TODO: respect fDoDither
666 unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
667 uint32_t src32 = fExpandedRaw16 * scale5;
668 scale5 = 32 - scale5;
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);
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();
681 while (--height >= 0) {
682 fColorProc16(device, fSrcColor32, width, x, y);
683 device = (uint16_t*)((char*)device + deviceRB);
687 ///////////////////////////////////////////////////////////////////////////////
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));
696 void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) {
697 SkASSERT(x + width <= fDevice.width());
699 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
700 SkShader::Context* shaderContext = fShaderContext;
702 int alpha = shaderContext->getSpan16Alpha();
704 shaderContext->shadeSpan16(x, y, device, width);
706 uint16_t* span16 = (uint16_t*)fBuffer;
707 shaderContext->shadeSpan16(x, y, span16, width);
708 SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
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();
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
724 const uint16_t* orig = dst;
726 dst = (uint16_t*)((char*)dst + dstRB);
727 memcpy(dst, orig, width << 1);
730 } else { // need to call shadeSpan16 for every line
732 shaderContext->shadeSpan16(x, y, dst, width);
734 dst = (uint16_t*)((char*)dst + dstRB);
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);
743 SkBlendRGB16(span16, dst, scale, width);
744 dst = (uint16_t*)((char*)dst + dstRB);
748 shaderContext->shadeSpan16(x, y, span16, width);
749 SkBlendRGB16(span16, dst, scale, width);
751 dst = (uint16_t*)((char*)dst + dstRB);
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);
764 int alpha = shaderContext->getSpan16Alpha();
765 uint16_t* span16 = (uint16_t*)span;
773 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
777 // go direct to the device!
778 shaderContext->shadeSpan16(x, y, device, count);
780 shaderContext->shadeSpan16(x, y, span16, count);
781 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
788 } else { // span alpha is < 255
789 alpha = SkAlpha255To256(alpha);
795 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
797 int aa = SkAlphaMul(*antialias, alpha);
799 shaderContext->shadeSpan16(x, y, span16, count);
800 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
811 ///////////////////////////////////////////////////////////////////////////////
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);
819 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
821 // compute SkBlitRow::Procs
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;
829 // don't dither if the shader is really 16bit
830 if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
831 flags |= SkBlitRow::kDither_Flag;
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);
839 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
843 void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
844 SkASSERT(x + width <= fDevice.width());
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);
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();
858 if (fShaderFlags & SkShader::kConstInY32_Flag) {
859 shaderContext->shadeSpan(x, y, buffer, width);
861 proc(dst, buffer, width, 0xFF, x, y);
863 dst = (uint16_t*)((char*)dst + dstRB);
867 shaderContext->shadeSpan(x, y, buffer, width);
868 proc(dst, buffer, width, 0xFF, x, y);
870 dst = (uint16_t*)((char*)dst + dstRB);
875 static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
879 if (n == 0 || *aa == 0) {
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);
910 int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
912 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
913 shaderContext->shadeSpan(x, y, span, nonZeroCount);
915 SkPMColor* localSpan = span;
917 SkBlitRow::Proc16 proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
918 proc(device, localSpan, count, aa, x, y);
924 nonZeroCount -= count;
925 if (nonZeroCount == 0) {
929 SkASSERT(nonZeroCount > 0);
937 ///////////////////////////////////////////////////////////////////////
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();
947 int width = device.width();
948 fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
949 fAAExpand = (uint8_t*)(fBuffer + width);
952 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
957 void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
958 SkASSERT(x + width <= fDevice.width());
960 uint16_t* device = fDevice.getAddr16(x, y);
961 SkPMColor* span = fBuffer;
963 fShaderContext->shadeSpan(x, y, span, width);
964 fXfermode->xfer16(device, span, width, NULL);
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);
990 int nonZeroCount = count + count_nonzero_span(runs + count,
993 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
994 shaderContext->shadeSpan(x, y, span, nonZeroCount);
997 SkPMColor* localSpan = span;
1000 mode->xfer16(device, localSpan, count, NULL);
1003 memset(aaExpand, aa, count);
1004 mode->xfer16(device, localSpan, count, aaExpand);
1009 nonZeroCount -= count;
1010 if (nonZeroCount == 0) {
1014 SkASSERT(nonZeroCount > 0);
1016 SkASSERT(count > 0);
1022 ///////////////////////////////////////////////////////////////////////////////
1024 SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
1025 SkShader::Context* shaderContext,
1026 SkTBlitterAllocator* allocator) {
1027 SkASSERT(allocator != NULL);
1030 SkShader* shader = paint.getShader();
1031 SkXfermode* mode = paint.getXfermode();
1033 // we require a shader if there is an xfermode, handled by our caller
1034 SkASSERT(NULL == mode || shader);
1037 SkASSERT(shaderContext != NULL);
1039 blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint,
1041 } else if (shaderContext->canCallShadeSpan16()) {
1042 blitter = allocator->createT<SkRGB16_Shader16_Blitter>(device, paint, shaderContext);
1044 blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint, shaderContext);
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);
1055 } else if (0xFF == SkColorGetA(color)) {
1056 blitter = allocator->createT<SkRGB16_Opaque_Blitter>(device, paint);
1058 blitter = allocator->createT<SkRGB16_Blitter>(device, paint);