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