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