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