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         size_t 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     size_t      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, dev_lo, dev_hi;
    394             uint32x4_t wn1, wn2, tmp;
    395             uint32x4_t vmask_g16, vmask_ng16;
    396             uint16x8_t valpha, vdev;
    397             uint16x4_t odev_lo, odev_hi, valpha_lo, valpha_hi;
    398 
    399             // prepare constants
    400             vmask_g16 = vdupq_n_u32(SK_G16_MASK_IN_PLACE);
    401             vmask_ng16 = vdupq_n_u32(~SK_G16_MASK_IN_PLACE);
    402             color = vdupq_n_u32(expanded32);
    403 
    404             do {
    405                 // alpha is 8x8, widen and split to get a pair of 16x4
    406                 valpha = vaddw_u8(vdupq_n_u16(1), vld1_u8(alpha));
    407                 valpha = vshrq_n_u16(valpha, 3);
    408                 valpha_lo = vget_low_u16(valpha);
    409                 valpha_hi = vget_high_u16(valpha);
    410 
    411                 // load pixels
    412                 vdev = vld1q_u16(device);
    413                 dev_lo = vmovl_u16(vget_low_u16(vdev));
    414                 dev_hi = vmovl_u16(vget_high_u16(vdev));
    415 
    416                 // unpack them in 32 bits
    417                 dev_lo = (dev_lo & vmask_ng16) | vshlq_n_u32(dev_lo & vmask_g16, 16);
    418                 dev_hi = (dev_hi & vmask_ng16) | vshlq_n_u32(dev_hi & vmask_g16, 16);
    419 
    420                 // blend with color
    421                 tmp = (color - dev_lo) * vmovl_u16(valpha_lo);
    422                 tmp = vshrq_n_u32(tmp, 5);
    423                 dev_lo += tmp;
    424 
    425                 tmp = vmulq_u32(color - dev_hi, vmovl_u16(valpha_hi));
    426                 tmp = vshrq_n_u32(tmp, 5);
    427                 dev_hi += tmp;
    428 
    429                 // re-compact
    430                 wn1 = dev_lo & vmask_ng16;
    431                 wn2 = vshrq_n_u32(dev_lo, 16) & vmask_g16;
    432                 odev_lo = vmovn_u32(wn1 | wn2);
    433 
    434                 wn1 = dev_hi & vmask_ng16;
    435                 wn2 = vshrq_n_u32(dev_hi, 16) & vmask_g16;
    436                 odev_hi = vmovn_u32(wn1 | wn2);
    437 
    438                 // store
    439                 vst1q_u16(device, vcombine_u16(odev_lo, odev_hi));
    440 
    441                 device += UNROLL;
    442                 alpha += UNROLL;
    443                 w -= UNROLL;
    444             } while (w >= UNROLL);
    445         }
    446 
    447         // residuals
    448         while (w > 0) {
    449             *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
    450                                     SkAlpha255To256(*alpha++) >> 3);
    451             device += 1;
    452             --w;
    453         }
    454         device = (uint16_t*)((char*)device + deviceRB);
    455         alpha += maskRB;
    456     } while (--height != 0);
    457 #undef    UNROLL
    458 #else   // non-neon code
    459     do {
    460         int w = width;
    461         do {
    462             *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
    463                                     SkAlpha255To256(*alpha++) >> 3);
    464             device += 1;
    465         } while (--w != 0);
    466         device = (uint16_t*)((char*)device + deviceRB);
    467         alpha += maskRB;
    468     } while (--height != 0);
    469 #endif
    470 }
    471 
    472 void SkRGB16_Opaque_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
    473     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
    474     size_t    deviceRB = fDevice.rowBytes();
    475 
    476     // TODO: respect fDoDither
    477     unsigned scale5 = SkAlpha255To256(alpha) >> 3;
    478     uint32_t src32 =  fExpandedRaw16 * scale5;
    479     scale5 = 32 - scale5;
    480     do {
    481         uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
    482         *device = SkCompact_rgb_16((src32 + dst32) >> 5);
    483         device = (uint16_t*)((char*)device + deviceRB);
    484     } while (--height != 0);
    485 }
    486 
    487 void SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) {
    488     SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
    489     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
    490     size_t      deviceRB = fDevice.rowBytes();
    491     uint16_t    color16 = fColor16;
    492 
    493     if (fDoDither) {
    494         uint16_t ditherColor = fRawDither16;
    495         if ((x ^ y) & 1) {
    496             SkTSwap(ditherColor, color16);
    497         }
    498         while (--height >= 0) {
    499             sk_dither_memset16(device, color16, ditherColor, width);
    500             SkTSwap(ditherColor, color16);
    501             device = (uint16_t*)((char*)device + deviceRB);
    502         }
    503     } else {  // no dither
    504         while (--height >= 0) {
    505             sk_memset16(device, color16, width);
    506             device = (uint16_t*)((char*)device + deviceRB);
    507         }
    508     }
    509 }
    510 
    511 ///////////////////////////////////////////////////////////////////////////////
    512 
    513 SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
    514     : INHERITED(device) {
    515     SkColor color = paint.getColor();
    516 
    517     fSrcColor32 = SkPreMultiplyColor(color);
    518     fScale = SkAlpha255To256(SkColorGetA(color));
    519 
    520     int r = SkColorGetR(color);
    521     int g = SkColorGetG(color);
    522     int b = SkColorGetB(color);
    523 
    524     fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
    525     // if we're dithered, use fRawDither16 to hold that.
    526     if ((fDoDither = paint.isDither()) != false) {
    527         fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
    528     }
    529 
    530     fExpandedRaw16 = SkExpand_rgb_16(fRawColor16);
    531 
    532     fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
    533                             SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
    534                             SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
    535 }
    536 
    537 const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
    538     if (!fDoDither && 256 == fScale) {
    539         *value = fRawColor16;
    540         return &fDevice;
    541     }
    542     return NULL;
    543 }
    544 
    545 static uint32_t pmcolor_to_expand16(SkPMColor c) {
    546     unsigned r = SkGetPackedR32(c);
    547     unsigned g = SkGetPackedG32(c);
    548     unsigned b = SkGetPackedB32(c);
    549     return (g << 24) | (r << 13) | (b << 2);
    550 }
    551 
    552 static inline void blend32_16_row(SkPMColor src, uint16_t dst[], int count) {
    553     SkASSERT(count > 0);
    554     uint32_t src_expand = pmcolor_to_expand16(src);
    555     unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3;
    556     do {
    557         uint32_t dst_expand = SkExpand_rgb_16(*dst) * scale;
    558         *dst = SkCompact_rgb_16((src_expand + dst_expand) >> 5);
    559         dst += 1;
    560     } while (--count != 0);
    561 }
    562 
    563 void SkRGB16_Blitter::blitH(int x, int y, int width) {
    564     SkASSERT(width > 0);
    565     SkASSERT(x + width <= fDevice.width());
    566     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
    567 
    568     // TODO: respect fDoDither
    569     blend32_16_row(fSrcColor32, device, width);
    570 }
    571 
    572 void SkRGB16_Blitter::blitAntiH(int x, int y,
    573                                 const SkAlpha* SK_RESTRICT antialias,
    574                                 const int16_t* SK_RESTRICT runs) {
    575     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
    576     uint32_t    srcExpanded = fExpandedRaw16;
    577     unsigned    scale = fScale;
    578 
    579     // TODO: respect fDoDither
    580     for (;;) {
    581         int count = runs[0];
    582         SkASSERT(count >= 0);
    583         if (count <= 0) {
    584             return;
    585         }
    586         runs += count;
    587 
    588         unsigned aa = antialias[0];
    589         antialias += count;
    590         if (aa) {
    591             unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
    592             uint32_t src32 =  srcExpanded * scale5;
    593             scale5 = 32 - scale5;
    594             do {
    595                 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
    596                 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
    597             } while (--count != 0);
    598             continue;
    599         }
    600         device += count;
    601     }
    602 }
    603 
    604 static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
    605                                   U16CPU srcColor) {
    606     if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
    607     if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
    608     if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
    609     if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
    610     if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
    611     if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
    612     if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
    613     if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
    614 }
    615 
    616 #define SK_BLITBWMASK_NAME                  SkRGB16_BlendBW
    617 #define SK_BLITBWMASK_ARGS                  , unsigned dst_scale, U16CPU src_color
    618 #define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, dst_scale, src_color)
    619 #define SK_BLITBWMASK_GETADDR               getAddr16
    620 #define SK_BLITBWMASK_DEVTYPE               uint16_t
    621 #include "SkBlitBWMaskTemplate.h"
    622 
    623 void SkRGB16_Blitter::blitMask(const SkMask& mask,
    624                                const SkIRect& clip) {
    625     if (mask.fFormat == SkMask::kBW_Format) {
    626         SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
    627         return;
    628     }
    629 
    630     uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
    631     const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
    632     int width = clip.width();
    633     int height = clip.height();
    634     size_t      deviceRB = fDevice.rowBytes() - (width << 1);
    635     unsigned    maskRB = mask.fRowBytes - width;
    636     uint32_t    color32 = fExpandedRaw16;
    637 
    638     unsigned scale256 = fScale;
    639     do {
    640         int w = width;
    641         do {
    642             unsigned aa = *alpha++;
    643             unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
    644             uint32_t src32 = color32 * scale;
    645             uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
    646             *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
    647         } while (--w != 0);
    648         device = (uint16_t*)((char*)device + deviceRB);
    649         alpha += maskRB;
    650     } while (--height != 0);
    651 }
    652 
    653 void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
    654     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
    655     size_t    deviceRB = fDevice.rowBytes();
    656 
    657     // TODO: respect fDoDither
    658     unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
    659     uint32_t src32 =  fExpandedRaw16 * scale5;
    660     scale5 = 32 - scale5;
    661     do {
    662         uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
    663         *device = SkCompact_rgb_16((src32 + dst32) >> 5);
    664         device = (uint16_t*)((char*)device + deviceRB);
    665     } while (--height != 0);
    666 }
    667 
    668 void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
    669     SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
    670     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
    671     size_t    deviceRB = fDevice.rowBytes();
    672     SkPMColor src32 = fSrcColor32;
    673 
    674     while (--height >= 0) {
    675         blend32_16_row(src32, device, width);
    676         device = (uint16_t*)((char*)device + deviceRB);
    677     }
    678 }
    679 
    680 ///////////////////////////////////////////////////////////////////////////////
    681 
    682 SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
    683                                                    const SkPaint& paint)
    684     : SkRGB16_Shader_Blitter(device, paint) {
    685     SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags));
    686 }
    687 
    688 void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) {
    689     SkASSERT(x + width <= fDevice.width());
    690 
    691     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
    692     SkShader*   shader = fShader;
    693 
    694     int alpha = shader->getSpan16Alpha();
    695     if (0xFF == alpha) {
    696         shader->shadeSpan16(x, y, device, width);
    697     } else {
    698         uint16_t* span16 = (uint16_t*)fBuffer;
    699         shader->shadeSpan16(x, y, span16, width);
    700         SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
    701     }
    702 }
    703 
    704 void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
    705     SkShader*   shader = fShader;
    706     uint16_t*   dst = fDevice.getAddr16(x, y);
    707     size_t      dstRB = fDevice.rowBytes();
    708     int         alpha = shader->getSpan16Alpha();
    709 
    710     if (0xFF == alpha) {
    711         if (fShaderFlags & SkShader::kConstInY16_Flag) {
    712             // have the shader blit directly into the device the first time
    713             shader->shadeSpan16(x, y, dst, width);
    714             // and now just memcpy that line on the subsequent lines
    715             if (--height > 0) {
    716                 const uint16_t* orig = dst;
    717                 do {
    718                     dst = (uint16_t*)((char*)dst + dstRB);
    719                     memcpy(dst, orig, width << 1);
    720                 } while (--height);
    721             }
    722         } else {    // need to call shadeSpan16 for every line
    723             do {
    724                 shader->shadeSpan16(x, y, dst, width);
    725                 y += 1;
    726                 dst = (uint16_t*)((char*)dst + dstRB);
    727             } while (--height);
    728         }
    729     } else {
    730         int scale = SkAlpha255To256(alpha);
    731         uint16_t* span16 = (uint16_t*)fBuffer;
    732         if (fShaderFlags & SkShader::kConstInY16_Flag) {
    733             shader->shadeSpan16(x, y, span16, width);
    734             do {
    735                 SkBlendRGB16(span16, dst, scale, width);
    736                 dst = (uint16_t*)((char*)dst + dstRB);
    737             } while (--height);
    738         } else {
    739             do {
    740                 shader->shadeSpan16(x, y, span16, width);
    741                 SkBlendRGB16(span16, dst, scale, width);
    742                 y += 1;
    743                 dst = (uint16_t*)((char*)dst + dstRB);
    744             } while (--height);
    745         }
    746     }
    747 }
    748 
    749 void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
    750                                          const SkAlpha* SK_RESTRICT antialias,
    751                                          const int16_t* SK_RESTRICT runs) {
    752     SkShader*   shader = fShader;
    753     SkPMColor* SK_RESTRICT span = fBuffer;
    754     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
    755 
    756     int alpha = shader->getSpan16Alpha();
    757     uint16_t* span16 = (uint16_t*)span;
    758 
    759     if (0xFF == alpha) {
    760         for (;;) {
    761             int count = *runs;
    762             if (count <= 0) {
    763                 break;
    764             }
    765             SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
    766 
    767             int aa = *antialias;
    768             if (aa == 255) {
    769                 // go direct to the device!
    770                 shader->shadeSpan16(x, y, device, count);
    771             } else if (aa) {
    772                 shader->shadeSpan16(x, y, span16, count);
    773                 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
    774             }
    775             device += count;
    776             runs += count;
    777             antialias += count;
    778             x += count;
    779         }
    780     } else {  // span alpha is < 255
    781         alpha = SkAlpha255To256(alpha);
    782         for (;;) {
    783             int count = *runs;
    784             if (count <= 0) {
    785                 break;
    786             }
    787             SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
    788 
    789             int aa = SkAlphaMul(*antialias, alpha);
    790             if (aa) {
    791                 shader->shadeSpan16(x, y, span16, count);
    792                 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
    793             }
    794 
    795             device += count;
    796             runs += count;
    797             antialias += count;
    798             x += count;
    799         }
    800     }
    801 }
    802 
    803 ///////////////////////////////////////////////////////////////////////////////
    804 
    805 SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
    806                                                const SkPaint& paint)
    807 : INHERITED(device, paint) {
    808     SkASSERT(paint.getXfermode() == NULL);
    809 
    810     fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
    811 
    812     // compute SkBlitRow::Procs
    813     unsigned flags = 0;
    814 
    815     uint32_t shaderFlags = fShaderFlags;
    816     // shaders take care of global alpha, so we never set it in SkBlitRow
    817     if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
    818         flags |= SkBlitRow::kSrcPixelAlpha_Flag;
    819     }
    820     // don't dither if the shader is really 16bit
    821     if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
    822         flags |= SkBlitRow::kDither_Flag;
    823     }
    824     // used when we know our global alpha is 0xFF
    825     fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
    826     // used when we know our global alpha is < 0xFF
    827     fAlphaProc  = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
    828                                      SkBitmap::kRGB_565_Config);
    829 }
    830 
    831 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
    832     sk_free(fBuffer);
    833 }
    834 
    835 void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
    836     SkASSERT(x + width <= fDevice.width());
    837 
    838     fShader->shadeSpan(x, y, fBuffer, width);
    839     // shaders take care of global alpha, so we pass 0xFF (should be ignored)
    840     fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
    841 }
    842 
    843 void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
    844     SkShader*       shader = fShader;
    845     SkBlitRow::Proc proc = fOpaqueProc;
    846     SkPMColor*      buffer = fBuffer;
    847     uint16_t*       dst = fDevice.getAddr16(x, y);
    848     size_t          dstRB = fDevice.rowBytes();
    849 
    850     if (fShaderFlags & SkShader::kConstInY32_Flag) {
    851         shader->shadeSpan(x, y, buffer, width);
    852         do {
    853             proc(dst, buffer, width, 0xFF, x, y);
    854             y += 1;
    855             dst = (uint16_t*)((char*)dst + dstRB);
    856         } while (--height);
    857     } else {
    858         do {
    859             shader->shadeSpan(x, y, buffer, width);
    860             proc(dst, buffer, width, 0xFF, x, y);
    861             y += 1;
    862             dst = (uint16_t*)((char*)dst + dstRB);
    863         } while (--height);
    864     }
    865 }
    866 
    867 static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
    868     int count = 0;
    869     for (;;) {
    870         int n = *runs;
    871         if (n == 0 || *aa == 0) {
    872             break;
    873         }
    874         runs += n;
    875         aa += n;
    876         count += n;
    877     }
    878     return count;
    879 }
    880 
    881 void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
    882                                        const SkAlpha* SK_RESTRICT antialias,
    883                                        const int16_t* SK_RESTRICT runs) {
    884     SkShader*   shader = fShader;
    885     SkPMColor* SK_RESTRICT span = fBuffer;
    886     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
    887 
    888     for (;;) {
    889         int count = *runs;
    890         if (count <= 0) {
    891             break;
    892         }
    893         int aa = *antialias;
    894         if (0 == aa) {
    895             device += count;
    896             runs += count;
    897             antialias += count;
    898             x += count;
    899             continue;
    900         }
    901 
    902         int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
    903 
    904         SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
    905         shader->shadeSpan(x, y, span, nonZeroCount);
    906 
    907         SkPMColor* localSpan = span;
    908         for (;;) {
    909             SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
    910             proc(device, localSpan, count, aa, x, y);
    911 
    912             x += count;
    913             device += count;
    914             runs += count;
    915             antialias += count;
    916             nonZeroCount -= count;
    917             if (nonZeroCount == 0) {
    918                 break;
    919             }
    920             localSpan += count;
    921             SkASSERT(nonZeroCount > 0);
    922             count = *runs;
    923             SkASSERT(count > 0);
    924             aa = *antialias;
    925         }
    926     }
    927 }
    928 
    929 ///////////////////////////////////////////////////////////////////////
    930 
    931 SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
    932                                 const SkBitmap& device, const SkPaint& paint)
    933 : INHERITED(device, paint) {
    934     fXfermode = paint.getXfermode();
    935     SkASSERT(fXfermode);
    936     fXfermode->ref();
    937 
    938     int width = device.width();
    939     fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
    940     fAAExpand = (uint8_t*)(fBuffer + width);
    941 }
    942 
    943 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
    944     fXfermode->unref();
    945     sk_free(fBuffer);
    946 }
    947 
    948 void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
    949     SkASSERT(x + width <= fDevice.width());
    950 
    951     uint16_t*   device = fDevice.getAddr16(x, y);
    952     SkPMColor*  span = fBuffer;
    953 
    954     fShader->shadeSpan(x, y, span, width);
    955     fXfermode->xfer16(device, span, width, NULL);
    956 }
    957 
    958 void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
    959                                 const SkAlpha* SK_RESTRICT antialias,
    960                                 const int16_t* SK_RESTRICT runs) {
    961     SkShader*   shader = fShader;
    962     SkXfermode* mode = fXfermode;
    963     SkPMColor* SK_RESTRICT span = fBuffer;
    964     uint8_t* SK_RESTRICT aaExpand = fAAExpand;
    965     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
    966 
    967     for (;;) {
    968         int count = *runs;
    969         if (count <= 0) {
    970             break;
    971         }
    972         int aa = *antialias;
    973         if (0 == aa) {
    974             device += count;
    975             runs += count;
    976             antialias += count;
    977             x += count;
    978             continue;
    979         }
    980 
    981         int nonZeroCount = count + count_nonzero_span(runs + count,
    982                                                       antialias + count);
    983 
    984         SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
    985         shader->shadeSpan(x, y, span, nonZeroCount);
    986 
    987         x += nonZeroCount;
    988         SkPMColor* localSpan = span;
    989         for (;;) {
    990             if (aa == 0xFF) {
    991                 mode->xfer16(device, localSpan, count, NULL);
    992             } else {
    993                 SkASSERT(aa);
    994                 memset(aaExpand, aa, count);
    995                 mode->xfer16(device, localSpan, count, aaExpand);
    996             }
    997             device += count;
    998             runs += count;
    999             antialias += count;
   1000             nonZeroCount -= count;
   1001             if (nonZeroCount == 0) {
   1002                 break;
   1003             }
   1004             localSpan += count;
   1005             SkASSERT(nonZeroCount > 0);
   1006             count = *runs;
   1007             SkASSERT(count > 0);
   1008             aa = *antialias;
   1009         }
   1010     }
   1011 }
   1012 
   1013 ///////////////////////////////////////////////////////////////////////////////
   1014 
   1015 SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
   1016                                 void* storage, size_t storageSize) {
   1017     SkBlitter* blitter;
   1018     SkShader* shader = paint.getShader();
   1019     SkXfermode* mode = paint.getXfermode();
   1020 
   1021     // we require a shader if there is an xfermode, handled by our caller
   1022     SkASSERT(NULL == mode || NULL != shader);
   1023 
   1024     if (shader) {
   1025         if (mode) {
   1026             SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Xfermode_Blitter,
   1027                                   storage, storageSize, (device, paint));
   1028         } else if (shader->canCallShadeSpan16()) {
   1029             SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader16_Blitter,
   1030                                   storage, storageSize, (device, paint));
   1031         } else {
   1032             SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Blitter,
   1033                                   storage, storageSize, (device, paint));
   1034         }
   1035     } else {
   1036         // no shader, no xfermode, (and we always ignore colorfilter)
   1037         SkColor color = paint.getColor();
   1038         if (0 == SkColorGetA(color)) {
   1039             SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
   1040 #ifdef USE_BLACK_BLITTER
   1041         } else if (SK_ColorBLACK == color) {
   1042             SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Black_Blitter, storage,
   1043                                   storageSize, (device, paint));
   1044 #endif
   1045         } else if (0xFF == SkColorGetA(color)) {
   1046             SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Opaque_Blitter, storage,
   1047                                   storageSize, (device, paint));
   1048         } else {
   1049             SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Blitter, storage,
   1050                                   storageSize, (device, paint));
   1051         }
   1052     }
   1053 
   1054     return blitter;
   1055 }
   1056