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