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