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