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