LCOV - code coverage report
Current view: directory - gfx/skia/src/core - SkBlitter_RGB16.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 511 0 0.0 %
Date: 2012-06-02 Functions: 47 0 0.0 %

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

Generated by: LCOV version 1.7