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