1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitRow.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCoreBlitters.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDither.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
16e552dc82be1512df0a8a7f24310d27d2740d7601djsollen@google.com#include "SkUtilsArm.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
196336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut#if SK_MIPS_HAS_DSP
206336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesutextern void blitmask_d565_opaque_mips(int width, int height, uint16_t* device,
216336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut                                      unsigned deviceRB, const uint8_t* alpha,
226336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut                                      uint32_t expanded32, unsigned maskRB);
236336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut#endif
246336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut
2589351ec35a05eaf59edb7431d23a754cd084a363commit-bot@chromium.org#if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
26867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    #include <arm_neon.h>
27867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#else
28867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    // if we don't have neon, then our black blitter is worth the extra code
29867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    #define USE_BLACK_BLITTER
30867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
31867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        int count) {
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // see if we need to write one short before we can cast to an 4byte ptr
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // (we do this subtract rather than (unsigned)dst so we don't get warnings
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        //  on 64bit machines)
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (((char*)dst - (char*)0) & 2) {
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *dst++ = value;
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count -= 1;
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkTSwap(value, other);
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
43fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // fast way to set [value,other] pairs
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_CPU_BENDIAN
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
50fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count & 1) {
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst[count - 1] = value;
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
591fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Blitter : public SkRasterBlitter {
601fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
611fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint);
621fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual void blitH(int x, int y, int width);
63a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
64a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                           const int16_t* runs);
651fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual void blitV(int x, int y, int height, SkAlpha alpha);
661fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual void blitRect(int x, int y, int width, int height);
67a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitMask(const SkMask&,
68a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                          const SkIRect&);
691fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual const SkBitmap* justAnOpaqueColor(uint32_t*);
70fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
711fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprotected:
721fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkPMColor   fSrcColor32;
73ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    fExpandedRaw16;
741fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    unsigned    fScale;
751fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    uint16_t    fColor16;       // already scaled by fScale
761fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    uint16_t    fRawColor16;    // unscaled
771fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    uint16_t    fRawDither16;   // unscaled
781fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkBool8     fDoDither;
79fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
801fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // illegal
811fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Blitter& operator=(const SkRGB16_Blitter&);
82fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
831fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkRasterBlitter INHERITED;
841fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
851fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
861fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Opaque_Blitter : public SkRGB16_Blitter {
871fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
881fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Opaque_Blitter(const SkBitmap& device, const SkPaint& paint);
891fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual void blitH(int x, int y, int width);
90a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
91a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                           const int16_t* runs);
92ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    virtual void blitV(int x, int y, int height, SkAlpha alpha);
931fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual void blitRect(int x, int y, int width, int height);
94a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitMask(const SkMask&,
95a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                          const SkIRect&);
96fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
971fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
981fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkRGB16_Blitter INHERITED;
991fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
1001fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
101867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#ifdef USE_BLACK_BLITTER
1021fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Black_Blitter : public SkRGB16_Opaque_Blitter {
1031fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
1041fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint);
1051fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual void blitMask(const SkMask&, const SkIRect&);
106a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
107a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                           const int16_t* runs);
108fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1091fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1101fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkRGB16_Opaque_Blitter INHERITED;
1111fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
112867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
1131fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
1141fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Shader_Blitter : public SkShaderBlitter {
1151fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
11687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkRGB16_Shader_Blitter(const SkBitmap& device, const SkPaint& paint,
11787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                           SkShader::Context* shaderContext);
1181fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual ~SkRGB16_Shader_Blitter();
1191fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual void blitH(int x, int y, int width);
120a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
121a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                           const int16_t* runs);
1221fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual void blitRect(int x, int y, int width, int height);
123fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1241fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprotected:
1251fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkPMColor*      fBuffer;
1261fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkBlitRow::Proc fOpaqueProc;
1271fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkBlitRow::Proc fAlphaProc;
128fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1291fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1301fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // illegal
1311fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Shader_Blitter& operator=(const SkRGB16_Shader_Blitter&);
132fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1331fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkShaderBlitter INHERITED;
1341fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
1351fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
1361fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com// used only if the shader can perform shadSpan16
1371fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Shader16_Blitter : public SkRGB16_Shader_Blitter {
1381fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
13987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint,
14087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                             SkShader::Context* shaderContext);
1411fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual void blitH(int x, int y, int width);
142a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
143a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                           const int16_t* runs);
1441fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual void blitRect(int x, int y, int width, int height);
145fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1461fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1471fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkRGB16_Shader_Blitter INHERITED;
1481fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
1491fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
1501fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter {
1511fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
15287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkRGB16_Shader_Xfermode_Blitter(const SkBitmap& device, const SkPaint& paint,
15387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                    SkShader::Context* shaderContext);
1541fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual ~SkRGB16_Shader_Xfermode_Blitter();
1551fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual void blitH(int x, int y, int width);
156a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
157a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                           const int16_t* runs);
158fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1591fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1601fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkXfermode* fXfermode;
1611fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkPMColor*  fBuffer;
1621fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    uint8_t*    fAAExpand;
163fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1641fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // illegal
1651fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Shader_Xfermode_Blitter& operator=(const SkRGB16_Shader_Xfermode_Blitter&);
166fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1671fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkShaderBlitter INHERITED;
1681fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
1691fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
1701fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com///////////////////////////////////////////////////////////////////////////////
171867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#ifdef USE_BLACK_BLITTER
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint)
173dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    : INHERITED(device, paint) {
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getShader() == NULL);
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getColorFilter() == NULL);
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getXfermode() == NULL);
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getColor() == SK_ColorBLACK);
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 1
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define black_8_pixels(mask, dst)       \
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                \
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x80) dst[0] = 0;    \
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x40) dst[1] = 0;    \
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x20) dst[2] = 0;    \
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x10) dst[3] = 0;    \
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x08) dst[4] = 0;    \
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x04) dst[5] = 0;    \
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x02) dst[6] = 0;    \
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x01) dst[7] = 0;    \
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline black_8_pixels(U8CPU mask, uint16_t dst[])
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x80) dst[0] = 0;
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x40) dst[1] = 0;
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x20) dst[2] = 0;
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x10) dst[3] = 0;
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x08) dst[4] = 0;
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x04) dst[5] = 0;
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x02) dst[6] = 0;
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x01) dst[7] = 0;
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_Black_BlitBW
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      black_8_pixels(mask, dst)
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR               getAddr16
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
213333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.comvoid SkRGB16_Black_Blitter::blitMask(const SkMask& mask,
214333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.com                                     const SkIRect& clip) {
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRGB16_Black_BlitBW(fDevice, mask, clip);
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
2197989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com        const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned width = clip.width();
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned height = clip.height();
222e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com        size_t deviceRB = fDevice.rowBytes() - (width << 1);
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned maskRB = mask.fRowBytes - width;
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)height > 0);
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)width > 0);
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)deviceRB >= 0);
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)maskRB >= 0);
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned w = width;
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned aa = *alpha++;
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device += 1;
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while (--w != 0);
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device = (uint16_t*)((char*)device + deviceRB);
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += maskRB;
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Black_Blitter::blitAntiH(int x, int y,
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      const SkAlpha* SK_RESTRICT antialias,
245a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                      const int16_t* SK_RESTRICT runs) {
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = runs[0];
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count >= 0);
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += count;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned aa = antialias[0];
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        antialias += count;
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (aa) {
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 255) {
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memset(device, 0, count << 1);
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                aa = SkAlpha255To256(255 - aa);
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                do {
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    *device = SkAlphaMulRGB16(*device, aa);
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    device += 1;
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } while (--count != 0);
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                continue;
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device += count;
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
273867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2759a74d313452f30629e2615eb8cbfe902433582c0reed@android.com///////////////////////////////////////////////////////////////////////////////
2769a74d313452f30629e2615eb8cbfe902433582c0reed@android.com///////////////////////////////////////////////////////////////////////////////
2779a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
2789a74d313452f30629e2615eb8cbfe902433582c0reed@android.comSkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkBitmap& device,
2799a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                                               const SkPaint& paint)
2809a74d313452f30629e2615eb8cbfe902433582c0reed@android.com: INHERITED(device, paint) {}
2819a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
282a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) {
2839a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(width > 0);
2849a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(x + width <= fDevice.width());
2859a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
2869a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t srcColor = fColor16;
28731d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
2889a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(fRawColor16 == srcColor);
2899a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if (fDoDither) {
2909a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        uint16_t ditherColor = fRawDither16;
2919a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if ((x ^ y) & 1) {
2929a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, srcColor);
2939a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
2949a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        sk_dither_memset16(device, srcColor, ditherColor, width);
2959a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } else {
2969a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        sk_memset16(device, srcColor, width);
2979a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
2989a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
2999a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3009a74d313452f30629e2615eb8cbfe902433582c0reed@android.com// return 1 or 0 from a bool
30163debae4c1020fa1e0ccd92ef3cbfdc8735acf8ereed@android.comstatic inline int Bool2Int(int value) {
302fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    return !!value;
3039a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
3049a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3059a74d313452f30629e2615eb8cbfe902433582c0reed@android.comvoid SkRGB16_Opaque_Blitter::blitAntiH(int x, int y,
3069a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                                       const SkAlpha* SK_RESTRICT antialias,
307a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                       const int16_t* SK_RESTRICT runs) {
3089a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
3099a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t    srcColor = fRawColor16;
310ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    srcExpanded = fExpandedRaw16;
3119a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    int         ditherInt = Bool2Int(fDoDither);
3129a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t    ditherColor = fRawDither16;
3139a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    // if we have no dithering, this will always fail
3149a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if ((x ^ y) & ditherInt) {
3159a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkTSwap(ditherColor, srcColor);
3169a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
3179a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    for (;;) {
3189a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int count = runs[0];
3199a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkASSERT(count >= 0);
3209a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (count <= 0) {
3219a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            return;
3229a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
3239a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        runs += count;
32431d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
3259a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        unsigned aa = antialias[0];
3269a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        antialias += count;
3279a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (aa) {
3289a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            if (aa == 255) {
3299a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                if (ditherInt) {
3309a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    sk_dither_memset16(device, srcColor,
3319a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                                       ditherColor, count);
3329a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                } else {
3339a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    sk_memset16(device, srcColor, count);
3349a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                }
3359a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            } else {
3369a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                // TODO: respect fDoDither
3379a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                unsigned scale5 = SkAlpha255To256(aa) >> 3;
338ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com                uint32_t src32 = srcExpanded * scale5;
3399a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                scale5 = 32 - scale5; // now we can use it on the device
3409a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                int n = count;
3419a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                do {
3429a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
3439a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
3449a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                } while (--n != 0);
3459a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                goto DONE;
3469a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            }
3479a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
3489a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device += count;
34931d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
3509a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    DONE:
3519a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        // if we have no dithering, this will always fail
3529a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (count & ditherInt) {
3539a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, srcColor);
3549a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
3559a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
3569a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
3579a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3589a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define solid_8_pixels(mask, dst, color)    \
3599a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    do {                                    \
3609a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x80) dst[0] = color;    \
3619a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x40) dst[1] = color;    \
3629a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x20) dst[2] = color;    \
3639a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x10) dst[3] = color;    \
3649a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x08) dst[4] = color;    \
3659a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x04) dst[5] = color;    \
3669a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x02) dst[6] = color;    \
3679a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x01) dst[7] = color;    \
3689a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } while (0)
3699a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3709a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_BlitBW
3719a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_ARGS                  , uint16_t color
3729a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
3739a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_GETADDR               getAddr16
3749a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
3759a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#include "SkBlitBWMaskTemplate.h"
3769a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3776336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut#if !defined(SK_MIPS_HAS_DSP)
3789a74d313452f30629e2615eb8cbfe902433582c0reed@android.comstatic U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
3799a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
3809a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
3816336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut#endif
3829a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
383333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.comvoid SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask,
384333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.com                                      const SkIRect& clip) {
3859a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
3869a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
3879a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        return;
3889a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
38931d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
3909a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
3917989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com    const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
3929a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    int width = clip.width();
3939a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    int height = clip.height();
394e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t      deviceRB = fDevice.rowBytes() - (width << 1);
3959a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    unsigned    maskRB = mask.fRowBytes - width;
396ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    expanded32 = fExpandedRaw16;
39731d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
39889351ec35a05eaf59edb7431d23a754cd084a363commit-bot@chromium.org#if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
399fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define    UNROLL    8
400867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    do {
401867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        int w = width;
402867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        if (w >= UNROLL) {
403641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint32x4_t color, dev_lo, dev_hi;
404641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint32x4_t wn1, wn2, tmp;
405641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint32x4_t vmask_g16, vmask_ng16;
406641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint16x8_t valpha, vdev;
407641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint16x4_t odev_lo, odev_hi, valpha_lo, valpha_hi;
408641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
409641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            // prepare constants
410641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            vmask_g16 = vdupq_n_u32(SK_G16_MASK_IN_PLACE);
411641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            vmask_ng16 = vdupq_n_u32(~SK_G16_MASK_IN_PLACE);
412867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            color = vdupq_n_u32(expanded32);
413fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
414867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            do {
415641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // alpha is 8x8, widen and split to get a pair of 16x4
416641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha = vaddw_u8(vdupq_n_u16(1), vld1_u8(alpha));
417641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha = vshrq_n_u16(valpha, 3);
418641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha_lo = vget_low_u16(valpha);
419641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha_hi = vget_high_u16(valpha);
420641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
421641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // load pixels
422641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                vdev = vld1q_u16(device);
423641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_lo = vmovl_u16(vget_low_u16(vdev));
424641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_hi = vmovl_u16(vget_high_u16(vdev));
425641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
426641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // unpack them in 32 bits
427641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_lo = (dev_lo & vmask_ng16) | vshlq_n_u32(dev_lo & vmask_g16, 16);
428641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_hi = (dev_hi & vmask_ng16) | vshlq_n_u32(dev_hi & vmask_g16, 16);
429641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
430641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // blend with color
431641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = (color - dev_lo) * vmovl_u16(valpha_lo);
432641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = vshrq_n_u32(tmp, 5);
433641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_lo += tmp;
434641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
435641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = vmulq_u32(color - dev_hi, vmovl_u16(valpha_hi));
436641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = vshrq_n_u32(tmp, 5);
437641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_hi += tmp;
438641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
439641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // re-compact
440641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn1 = dev_lo & vmask_ng16;
441641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn2 = vshrq_n_u32(dev_lo, 16) & vmask_g16;
442641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                odev_lo = vmovn_u32(wn1 | wn2);
443641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
444641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn1 = dev_hi & vmask_ng16;
445641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn2 = vshrq_n_u32(dev_hi, 16) & vmask_g16;
446641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                odev_hi = vmovn_u32(wn1 | wn2);
447641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
448641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // store
449641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                vst1q_u16(device, vcombine_u16(odev_lo, odev_hi));
450fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
451867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                device += UNROLL;
452867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                alpha += UNROLL;
453867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                w -= UNROLL;
454867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            } while (w >= UNROLL);
455867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        }
456fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
457641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org        // residuals
458867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        while (w > 0) {
459867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
460867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                                    SkAlpha255To256(*alpha++) >> 3);
461867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            device += 1;
462867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            --w;
463867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        }
464867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
465867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        alpha += maskRB;
466867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    } while (--height != 0);
467fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    UNROLL
4686336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut#elif SK_MIPS_HAS_DSP
4696336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut    blitmask_d565_opaque_mips(width, height, device, deviceRB, alpha, expanded32, maskRB);
470867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#else   // non-neon code
4719a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    do {
4729a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int w = width;
4739a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        do {
474ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com            *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
4759a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                                    SkAlpha255To256(*alpha++) >> 3);
4769a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            device += 1;
4779a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        } while (--w != 0);
4789a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
4799a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        alpha += maskRB;
4809a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } while (--height != 0);
481867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
4829a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
4839a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
484ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.comvoid SkRGB16_Opaque_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
485ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
486e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t    deviceRB = fDevice.rowBytes();
487fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
488ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    // TODO: respect fDoDither
489ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    unsigned scale5 = SkAlpha255To256(alpha) >> 3;
490ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t src32 =  fExpandedRaw16 * scale5;
491ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    scale5 = 32 - scale5;
492ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    do {
493ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
494ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        *device = SkCompact_rgb_16((src32 + dst32) >> 5);
495ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
496ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    } while (--height != 0);
497ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com}
498ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com
4999a74d313452f30629e2615eb8cbfe902433582c0reed@android.comvoid SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) {
5009a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
5019a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
502e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t      deviceRB = fDevice.rowBytes();
5039a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t    color16 = fColor16;
50431d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
5059a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if (fDoDither) {
5069a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        uint16_t ditherColor = fRawDither16;
5079a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if ((x ^ y) & 1) {
5089a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, color16);
5099a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
5109a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        while (--height >= 0) {
5119a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            sk_dither_memset16(device, color16, ditherColor, width);
5129a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, color16);
5139a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            device = (uint16_t*)((char*)device + deviceRB);
5149a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
5159a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } else {  // no dither
5169a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        while (--height >= 0) {
5179a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            sk_memset16(device, color16, width);
5189a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            device = (uint16_t*)((char*)device + deviceRB);
5199a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
5209a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
5219a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
5229a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
5239a74d313452f30629e2615eb8cbfe902433582c0reed@android.com///////////////////////////////////////////////////////////////////////////////
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    : INHERITED(device) {
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkColor color = paint.getColor();
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcColor32 = SkPreMultiplyColor(color);
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fScale = SkAlpha255To256(SkColorGetA(color));
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int r = SkColorGetR(color);
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int g = SkColorGetG(color);
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int b = SkColorGetB(color);
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we're dithered, use fRawDither16 to hold that.
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((fDoDither = paint.isDither()) != false) {
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
541ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com
542ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    fExpandedRaw16 = SkExpand_rgb_16(fRawColor16);
543ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!fDoDither && 256 == fScale) {
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *value = fRawColor16;
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return &fDevice;
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
557dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.comstatic uint32_t pmcolor_to_expand16(SkPMColor c) {
558dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    unsigned r = SkGetPackedR32(c);
559dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    unsigned g = SkGetPackedG32(c);
560dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    unsigned b = SkGetPackedB32(c);
561dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    return (g << 24) | (r << 13) | (b << 2);
562dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com}
563dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com
564dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.comstatic inline void blend32_16_row(SkPMColor src, uint16_t dst[], int count) {
565dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    SkASSERT(count > 0);
566dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    uint32_t src_expand = pmcolor_to_expand16(src);
567b602b8e5334edc0bfcdf086c2ea58e2b5d5f1f3breed@android.com    unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3;
568dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    do {
569dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        uint32_t dst_expand = SkExpand_rgb_16(*dst) * scale;
570dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        *dst = SkCompact_rgb_16((src_expand + dst_expand) >> 5);
571dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        dst += 1;
572dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    } while (--count != 0);
573dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com}
574dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com
575a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkRGB16_Blitter::blitH(int x, int y, int width) {
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(width > 0);
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5809a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    // TODO: respect fDoDither
581dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    blend32_16_row(fSrcColor32, device, width);
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitAntiH(int x, int y,
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkAlpha* SK_RESTRICT antialias,
586a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                const int16_t* SK_RESTRICT runs) {
5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
588ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    srcExpanded = fExpandedRaw16;
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    scale = fScale;
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5919a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    // TODO: respect fDoDither
5929a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    for (;;) {
5939a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int count = runs[0];
5949a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkASSERT(count >= 0);
5959a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (count <= 0) {
5969a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            return;
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5989a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        runs += count;
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6009a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        unsigned aa = antialias[0];
6019a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        antialias += count;
6029a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (aa) {
6039a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
604ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com            uint32_t src32 =  srcExpanded * scale5;
6059a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            scale5 = 32 - scale5;
6069a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            do {
6079a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
6089a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
6099a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            } while (--count != 0);
6109a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            continue;
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6129a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device += count;
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                  U16CPU srcColor) {
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_BlendBW
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS                  , unsigned dst_scale, U16CPU src_color
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, dst_scale, src_color)
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR               getAddr16
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
635333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.comvoid SkRGB16_Blitter::blitMask(const SkMask& mask,
636333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.com                               const SkIRect& clip) {
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
6389a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
6437989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com    const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = clip.width();
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int height = clip.height();
646e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t      deviceRB = fDevice.rowBytes() - (width << 1);
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    maskRB = mask.fRowBytes - width;
648ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    color32 = fExpandedRaw16;
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6509a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    unsigned scale256 = fScale;
6519a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    do {
6529a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int w = width;
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
6549a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            unsigned aa = *alpha++;
6559a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
6569a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            uint32_t src32 = color32 * scale;
6579a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
6589a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
6599a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        } while (--w != 0);
6609a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
6619a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        alpha += maskRB;
6629a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } while (--height != 0);
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
667e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t    deviceRB = fDevice.rowBytes();
6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
669ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    // TODO: respect fDoDither
670ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
671ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t src32 =  fExpandedRaw16 * scale5;
672ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    scale5 = 32 - scale5;
673ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    do {
674ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
675ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        *device = SkCompact_rgb_16((src32 + dst32) >> 5);
676ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
677ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    } while (--height != 0);
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
683e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t    deviceRB = fDevice.rowBytes();
6849a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkPMColor src32 = fSrcColor32;
6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6869a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    while (--height >= 0) {
687dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        blend32_16_row(src32, device, width);
6889a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
69587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                                   const SkPaint& paint,
69687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                                   SkShader::Context* shaderContext)
69787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    : SkRGB16_Shader_Blitter(device, paint, shaderContext) {
6985119bdb952025a30f115b9c6a187173956e55097reed@android.com    SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags));
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
701a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) {
7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
70587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context*    shaderContext = fShaderContext;
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
70787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    int alpha = shaderContext->getSpan16Alpha();
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
70987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan16(x, y, device, width);
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t* span16 = (uint16_t*)fBuffer;
71287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan16(x, y, span16, width);
7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
717dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.comvoid SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
71887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context* shaderContext = fShaderContext;
71987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint16_t*          dst = fDevice.getAddr16(x, y);
72087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    size_t             dstRB = fDevice.rowBytes();
72187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    int                alpha = shaderContext->getSpan16Alpha();
722dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com
723dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    if (0xFF == alpha) {
7243c9b2a4a0e4f57db23640e85959ee78b86634628reed@android.com        if (fShaderFlags & SkShader::kConstInY16_Flag) {
725dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            // have the shader blit directly into the device the first time
72687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            shaderContext->shadeSpan16(x, y, dst, width);
727dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            // and now just memcpy that line on the subsequent lines
728dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            if (--height > 0) {
729dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                const uint16_t* orig = dst;
730dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                do {
731dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                    dst = (uint16_t*)((char*)dst + dstRB);
732dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                    memcpy(dst, orig, width << 1);
733dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                } while (--height);
734dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            }
735dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        } else {    // need to call shadeSpan16 for every line
736dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            do {
73787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan16(x, y, dst, width);
738dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                y += 1;
739dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                dst = (uint16_t*)((char*)dst + dstRB);
740dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            } while (--height);
741dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        }
742dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    } else {
743dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        int scale = SkAlpha255To256(alpha);
744dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        uint16_t* span16 = (uint16_t*)fBuffer;
7453c9b2a4a0e4f57db23640e85959ee78b86634628reed@android.com        if (fShaderFlags & SkShader::kConstInY16_Flag) {
74687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            shaderContext->shadeSpan16(x, y, span16, width);
747dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            do {
748dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                SkBlendRGB16(span16, dst, scale, width);
749dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                dst = (uint16_t*)((char*)dst + dstRB);
750dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            } while (--height);
751dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        } else {
752dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            do {
75387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan16(x, y, span16, width);
754dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                SkBlendRGB16(span16, dst, scale, width);
755dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                y += 1;
756dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                dst = (uint16_t*)((char*)dst + dstRB);
757dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            } while (--height);
758dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        }
759dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    }
760dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com}
761dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         const SkAlpha* SK_RESTRICT antialias,
764a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                         const int16_t* SK_RESTRICT runs) {
76587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context*     shaderContext = fShaderContext;
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT span = fBuffer;
76787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint16_t* SK_RESTRICT  device = fDevice.getAddr16(x, y);
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
76987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    int alpha = shaderContext->getSpan16Alpha();
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* span16 = (uint16_t*)span;
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = *antialias;
7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 255) {
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                // go direct to the device!
78387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan16(x, y, device, count);
7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else if (aa) {
78587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan16(x, y, span16, count);
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {  // span alpha is < 255
7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        alpha = SkAlpha255To256(alpha);
7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = SkAlphaMul(*antialias, alpha);
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa) {
80487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan16(x, y, span16, count);
8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
81987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                               const SkPaint& paint,
82087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                               SkShader::Context* shaderContext)
82187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org: INHERITED(device, paint, shaderContext) {
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getXfermode() == NULL);
8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // compute SkBlitRow::Procs
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned flags = 0;
828fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
8295119bdb952025a30f115b9c6a187173956e55097reed@android.com    uint32_t shaderFlags = fShaderFlags;
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // shaders take care of global alpha, so we never set it in SkBlitRow
8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= SkBlitRow::kSrcPixelAlpha_Flag;
833c2050e3a3ecfb8738b36e2add15c526e8e0f21fecommit-bot@chromium.org    }
8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // don't dither if the shader is really 16bit
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= SkBlitRow::kDither_Flag;
8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // used when we know our global alpha is 0xFF
839cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    fOpaqueProc = SkBlitRow::Factory(flags, kRGB_565_SkColorType);
8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // used when we know our global alpha is < 0xFF
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fAlphaProc  = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
842cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org                                     kRGB_565_SkColorType);
8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fBuffer);
8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
85287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fShaderContext->shadeSpan(x, y, fBuffer, width);
8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // shaders take care of global alpha, so we pass 0xFF (should be ignored)
8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8575119bdb952025a30f115b9c6a187173956e55097reed@android.comvoid SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
85887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context* shaderContext = fShaderContext;
85987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkBlitRow::Proc    proc = fOpaqueProc;
86087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkPMColor*         buffer = fBuffer;
86187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint16_t*          dst = fDevice.getAddr16(x, y);
86287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    size_t             dstRB = fDevice.rowBytes();
8635119bdb952025a30f115b9c6a187173956e55097reed@android.com
8643c9b2a4a0e4f57db23640e85959ee78b86634628reed@android.com    if (fShaderFlags & SkShader::kConstInY32_Flag) {
86587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan(x, y, buffer, width);
8665119bdb952025a30f115b9c6a187173956e55097reed@android.com        do {
8675119bdb952025a30f115b9c6a187173956e55097reed@android.com            proc(dst, buffer, width, 0xFF, x, y);
8685119bdb952025a30f115b9c6a187173956e55097reed@android.com            y += 1;
8695119bdb952025a30f115b9c6a187173956e55097reed@android.com            dst = (uint16_t*)((char*)dst + dstRB);
8705119bdb952025a30f115b9c6a187173956e55097reed@android.com        } while (--height);
8715119bdb952025a30f115b9c6a187173956e55097reed@android.com    } else {
8725119bdb952025a30f115b9c6a187173956e55097reed@android.com        do {
87387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            shaderContext->shadeSpan(x, y, buffer, width);
8745119bdb952025a30f115b9c6a187173956e55097reed@android.com            proc(dst, buffer, width, 0xFF, x, y);
8755119bdb952025a30f115b9c6a187173956e55097reed@android.com            y += 1;
8765119bdb952025a30f115b9c6a187173956e55097reed@android.com            dst = (uint16_t*)((char*)dst + dstRB);
8775119bdb952025a30f115b9c6a187173956e55097reed@android.com        } while (--height);
8785119bdb952025a30f115b9c6a187173956e55097reed@android.com    }
8795119bdb952025a30f115b9c6a187173956e55097reed@android.com}
8805119bdb952025a30f115b9c6a187173956e55097reed@android.com
8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int count = 0;
8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int n = *runs;
8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (n == 0 || *aa == 0) {
8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += n;
8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        aa += n;
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count += n;
8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       const SkAlpha* SK_RESTRICT antialias,
897a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                       const int16_t* SK_RESTRICT runs) {
89887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context*     shaderContext = fShaderContext;
8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT span = fBuffer;
90087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint16_t* SK_RESTRICT  device = fDevice.getAddr16(x, y);
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = *runs;
9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int aa = *antialias;
9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (0 == aa) {
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
91987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan(x, y, span, nonZeroCount);
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor* localSpan = span;
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc(device, localSpan, count, aa, x, y);
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            nonZeroCount -= count;
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (nonZeroCount == 0) {
9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            localSpan += count;
9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(nonZeroCount > 0);
9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count = *runs;
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count > 0);
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa = *antialias;
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
94687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                const SkBitmap& device, const SkPaint& paint,
94787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                SkShader::Context* shaderContext)
94887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org: INHERITED(device, paint, shaderContext) {
9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode = paint.getXfermode();
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fXfermode);
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode->ref();
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = device.width();
9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fAAExpand = (uint8_t*)(fBuffer + width);
9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode->unref();
9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fBuffer);
9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t*   device = fDevice.getAddr16(x, y);
9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor*  span = fBuffer;
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
96987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fShaderContext->shadeSpan(x, y, span, width);
9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode->xfer16(device, span, width, NULL);
9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
9748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkAlpha* SK_RESTRICT antialias,
975a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                const int16_t* SK_RESTRICT runs) {
97687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context*     shaderContext = fShaderContext;
97787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkXfermode*            mode = fXfermode;
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT span = fBuffer;
97987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint8_t* SK_RESTRICT   aaExpand = fAAExpand;
98087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint16_t* SK_RESTRICT  device = fDevice.getAddr16(x, y);
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = *runs;
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int aa = *antialias;
9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (0 == aa) {
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int nonZeroCount = count + count_nonzero_span(runs + count,
9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                      antialias + count);
9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
100087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan(x, y, span, nonZeroCount);
10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x += nonZeroCount;
10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor* localSpan = span;
10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 0xFF) {
10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                mode->xfer16(device, localSpan, count, NULL);
10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkASSERT(aa);
10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memset(aaExpand, aa, count);
10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                mode->xfer16(device, localSpan, count, aaExpand);
10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
10138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            nonZeroCount -= count;
10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (nonZeroCount == 0) {
10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
10188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            localSpan += count;
10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(nonZeroCount > 0);
10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count = *runs;
10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count > 0);
10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa = *antialias;
10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1025fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10281fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com///////////////////////////////////////////////////////////////////////////////
10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10301fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comSkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
103187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        SkShader::Context* shaderContext,
1032a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org        SkTBlitterAllocator* allocator) {
1033a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org    SkASSERT(allocator != NULL);
1034a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org
10351fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkBlitter* blitter;
10361fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkShader* shader = paint.getShader();
10371fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkXfermode* mode = paint.getXfermode();
10381fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
10391fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // we require a shader if there is an xfermode, handled by our caller
104049f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(NULL == mode || shader);
10411fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
10421fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    if (shader) {
104387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        SkASSERT(shaderContext != NULL);
10441fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        if (mode) {
104587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint,
104687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                                                          shaderContext);
104787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        } else if (shaderContext->canCallShadeSpan16()) {
104887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Shader16_Blitter>(device, paint, shaderContext);
10491fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else {
105087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint, shaderContext);
10511fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        }
10521fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    } else {
10531fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        // no shader, no xfermode, (and we always ignore colorfilter)
10541fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        SkColor color = paint.getColor();
10551fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        if (0 == SkColorGetA(color)) {
1056a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkNullBlitter>();
1057867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#ifdef USE_BLACK_BLITTER
10581fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else if (SK_ColorBLACK == color) {
1059a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Black_Blitter>(device, paint);
1060867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
10611fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else if (0xFF == SkColorGetA(color)) {
1062a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Opaque_Blitter>(device, paint);
10631fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else {
1064a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Blitter>(device, paint);
10651fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        }
10661fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    }
1067fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
10681fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    return blitter;
10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1070