Home | History | Annotate | Download | only in core
      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 
     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
    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
    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 
    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 
    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 
    270 SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkBitmap& device,
    271                                                const SkPaint& paint)
    272 : INHERITED(device, paint) {}
    273 
    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
    293 static inline int Bool2Int(int value) {
    294 	return !!value;
    295 }
    296 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    841 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
    842     sk_free(fBuffer);
    843 }
    844 
    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 
    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 
    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 
    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 
    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 
    953 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
    954     fXfermode->unref();
    955     sk_free(fBuffer);
    956 }
    957 
    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 
    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 
   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