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)
18 extern 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>
25 extern 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 
sk_dither_memset16(uint16_t dst[],uint16_t value,uint16_t other,int count)35 void 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 
62 class SkRGB16_Blitter : public SkRasterBlitter {
63 public:
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 
73 protected:
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 
90 class SkRGB16_Opaque_Blitter : public SkRGB16_Blitter {
91 public:
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 
99 private:
100     typedef SkRGB16_Blitter INHERITED;
101 };
102 
103 #ifdef USE_BLACK_BLITTER
104 class SkRGB16_Black_Blitter : public SkRGB16_Opaque_Blitter {
105 public:
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 
110 private:
111     typedef SkRGB16_Opaque_Blitter INHERITED;
112 };
113 #endif
114 
115 class SkRGB16_Shader_Blitter : public SkShaderBlitter {
116 public:
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 
125 protected:
126     SkPMColor*          fBuffer;
127     SkBlitRow::Proc16   fOpaqueProc;
128     SkBlitRow::Proc16   fAlphaProc;
129 
130 private:
131     // illegal
132     SkRGB16_Shader_Blitter& operator=(const SkRGB16_Shader_Blitter&);
133 
134     typedef SkShaderBlitter INHERITED;
135 };
136 
137 class SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter {
138 public:
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 
146 private:
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
SkRGB16_Black_Blitter(const SkPixmap & device,const SkPaint & paint)159 SkRGB16_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
black_8_pixels(U8CPU mask,uint16_t dst[])180 static 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 
blitMask(const SkMask & mask,const SkIRect & clip)200 void 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 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)230 void 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 
SkRGB16_Opaque_Blitter(const SkPixmap & device,const SkPaint & paint)265 SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkPixmap& device, const SkPaint& paint)
266     : INHERITED(device, paint) {}
267 
blitH(int x,int y,int width)268 void 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
Bool2Int(int value)287 static inline int Bool2Int(int value) {
288     return !!value;
289 }
290 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)291 void 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)
blend_compact(uint32_t src32,uint32_t dst32,unsigned scale5)364 static 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 
blitMask(const SkMask & mask,const SkIRect & clip)369 void 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 
blitV(int x,int y,int height,SkAlpha alpha)470 void 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 
blitRect(int x,int y,int width,int height)489 void SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) {
490     SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
491     uint16_t* SK_RESTRICT device = fDevice.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 
SkRGB16_Blitter(const SkPixmap & device,const SkPaint & paint)515 SkRGB16_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 
justAnOpaqueColor(uint32_t * value)552 const SkPixmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
553     if (!fDoDither && 256 == fScale) {
554         *value = fRawColor16;
555         return &fDevice;
556     }
557     return nullptr;
558 }
559 
blitH(int x,int y,int width)560 void 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 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)568 void 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 
blend_8_pixels(U8CPU bw,uint16_t dst[],unsigned dst_scale,U16CPU srcColor)600 static 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 
blitMask(const SkMask & mask,const SkIRect & clip)619 void 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 
blitV(int x,int y,int height,SkAlpha alpha)649 void 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 
blitRect(int x,int y,int width,int height)668 void 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 
SkRGB16_Shader_Blitter(const SkPixmap & device,const SkPaint & paint,SkShader::Context * shaderContext)681 SkRGB16_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 
~SkRGB16_Shader_Blitter()707 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
708     sk_free(fBuffer);
709 }
710 
blitH(int x,int y,int width)711 void 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 
blitRect(int x,int y,int width,int height)719 void 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 
count_nonzero_span(const int16_t runs[],const SkAlpha aa[])743 static 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 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)757 void 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 
SkRGB16_Shader_Xfermode_Blitter(const SkPixmap & device,const SkPaint & paint,SkShader::Context * shaderContext)807 SkRGB16_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 
~SkRGB16_Shader_Xfermode_Blitter()821 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
822     fXfermode->unref();
823     sk_free(fBuffer);
824 }
825 
blitH(int x,int y,int width)826 void 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 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)836 void 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 
SkBlitter_ChooseD565(const SkPixmap & device,const SkPaint & paint,SkShader::Context * shaderContext,SkTBlitterAllocator * allocator)893 SkBlitter* 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