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