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);
6236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override;
63a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
6436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                           const int16_t* runs) override;
6536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitV(int x, int y, int height, SkAlpha alpha) override;
6636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitRect(int x, int y, int width, int height) override;
67a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitMask(const SkMask&,
6836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                          const SkIRect&) override;
6936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    const SkBitmap* justAnOpaqueColor(uint32_t*) override;
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
80402448d6818cab9d7b7633a0c18fcf574c915357mlee    SkBlitRow::ColorProc16 fColorProc16;
81402448d6818cab9d7b7633a0c18fcf574c915357mlee
821fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // illegal
831fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Blitter& operator=(const SkRGB16_Blitter&);
84fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
851fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkRasterBlitter INHERITED;
861fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
871fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
881fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Opaque_Blitter : public SkRGB16_Blitter {
891fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
901fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Opaque_Blitter(const SkBitmap& device, const SkPaint& paint);
9136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override;
92a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
9336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                           const int16_t* runs) override;
9436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitV(int x, int y, int height, SkAlpha alpha) override;
9536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitRect(int x, int y, int width, int height) override;
96a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitMask(const SkMask&,
9736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                          const SkIRect&) override;
98fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
991fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1001fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkRGB16_Blitter INHERITED;
1011fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
1021fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
103867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#ifdef USE_BLACK_BLITTER
1041fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Black_Blitter : public SkRGB16_Opaque_Blitter {
1051fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
1061fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint);
10736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitMask(const SkMask&, const SkIRect&) override;
108a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
10936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                           const int16_t* runs) override;
110fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1111fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1121fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkRGB16_Opaque_Blitter INHERITED;
1131fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
114867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
1151fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
1161fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Shader_Blitter : public SkShaderBlitter {
1171fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
11887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkRGB16_Shader_Blitter(const SkBitmap& device, const SkPaint& paint,
11987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                           SkShader::Context* shaderContext);
1201fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual ~SkRGB16_Shader_Blitter();
12136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override;
122a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
12336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                           const int16_t* runs) override;
12436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitRect(int x, int y, int width, int height) override;
125fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1261fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprotected:
127a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkPMColor*          fBuffer;
128a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkBlitRow::Proc16   fOpaqueProc;
129a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkBlitRow::Proc16   fAlphaProc;
130fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1311fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1321fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // illegal
1331fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Shader_Blitter& operator=(const SkRGB16_Shader_Blitter&);
134fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1351fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkShaderBlitter INHERITED;
1361fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
1371fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
1381fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com// used only if the shader can perform shadSpan16
1391fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Shader16_Blitter : public SkRGB16_Shader_Blitter {
1401fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
14187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint,
14287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                             SkShader::Context* shaderContext);
14336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override;
144a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
14536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                           const int16_t* runs) override;
14636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitRect(int x, int y, int width, int height) override;
147fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1481fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1491fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkRGB16_Shader_Blitter INHERITED;
1501fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
1511fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
1521fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter {
1531fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
15487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkRGB16_Shader_Xfermode_Blitter(const SkBitmap& device, const SkPaint& paint,
15587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                    SkShader::Context* shaderContext);
1561fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual ~SkRGB16_Shader_Xfermode_Blitter();
15736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override;
158a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
15936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                           const int16_t* runs) override;
160fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1611fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1621fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkXfermode* fXfermode;
1631fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkPMColor*  fBuffer;
1641fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    uint8_t*    fAAExpand;
165fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1661fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // illegal
1671fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Shader_Xfermode_Blitter& operator=(const SkRGB16_Shader_Xfermode_Blitter&);
168fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1691fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkShaderBlitter INHERITED;
1701fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
1711fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
1721fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com///////////////////////////////////////////////////////////////////////////////
173867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#ifdef USE_BLACK_BLITTER
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint)
175dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    : INHERITED(device, paint) {
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getShader() == NULL);
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getColorFilter() == NULL);
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getXfermode() == NULL);
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getColor() == SK_ColorBLACK);
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 1
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define black_8_pixels(mask, dst)       \
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                \
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x80) dst[0] = 0;    \
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x40) dst[1] = 0;    \
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x20) dst[2] = 0;    \
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x10) dst[3] = 0;    \
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x08) dst[4] = 0;    \
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x04) dst[5] = 0;    \
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x02) dst[6] = 0;    \
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x01) dst[7] = 0;    \
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline black_8_pixels(U8CPU mask, uint16_t dst[])
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x80) dst[0] = 0;
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x40) dst[1] = 0;
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x20) dst[2] = 0;
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x10) dst[3] = 0;
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x08) dst[4] = 0;
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x04) dst[5] = 0;
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x02) dst[6] = 0;
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x01) dst[7] = 0;
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_Black_BlitBW
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      black_8_pixels(mask, dst)
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR               getAddr16
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
215333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.comvoid SkRGB16_Black_Blitter::blitMask(const SkMask& mask,
216333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.com                                     const SkIRect& clip) {
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRGB16_Black_BlitBW(fDevice, mask, clip);
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
2217989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com        const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned width = clip.width();
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned height = clip.height();
224e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com        size_t deviceRB = fDevice.rowBytes() - (width << 1);
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned maskRB = mask.fRowBytes - width;
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)height > 0);
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)width > 0);
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)deviceRB >= 0);
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)maskRB >= 0);
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned w = width;
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned aa = *alpha++;
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device += 1;
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while (--w != 0);
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device = (uint16_t*)((char*)device + deviceRB);
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += maskRB;
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Black_Blitter::blitAntiH(int x, int y,
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      const SkAlpha* SK_RESTRICT antialias,
247a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                      const int16_t* SK_RESTRICT runs) {
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = runs[0];
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count >= 0);
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += count;
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned aa = antialias[0];
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        antialias += count;
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (aa) {
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 255) {
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memset(device, 0, count << 1);
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                aa = SkAlpha255To256(255 - aa);
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                do {
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    *device = SkAlphaMulRGB16(*device, aa);
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    device += 1;
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } while (--count != 0);
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                continue;
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device += count;
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
275867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2779a74d313452f30629e2615eb8cbfe902433582c0reed@android.com///////////////////////////////////////////////////////////////////////////////
2789a74d313452f30629e2615eb8cbfe902433582c0reed@android.com///////////////////////////////////////////////////////////////////////////////
2799a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
2809a74d313452f30629e2615eb8cbfe902433582c0reed@android.comSkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkBitmap& device,
2819a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                                               const SkPaint& paint)
2829a74d313452f30629e2615eb8cbfe902433582c0reed@android.com: INHERITED(device, paint) {}
2839a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
284a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) {
2859a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(width > 0);
2869a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(x + width <= fDevice.width());
2879a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
2889a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t srcColor = fColor16;
28931d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
2909a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(fRawColor16 == srcColor);
2919a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if (fDoDither) {
2929a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        uint16_t ditherColor = fRawDither16;
2939a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if ((x ^ y) & 1) {
2949a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, srcColor);
2959a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
2969a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        sk_dither_memset16(device, srcColor, ditherColor, width);
2979a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } else {
2989a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        sk_memset16(device, srcColor, width);
2999a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
3009a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
3019a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3029a74d313452f30629e2615eb8cbfe902433582c0reed@android.com// return 1 or 0 from a bool
30363debae4c1020fa1e0ccd92ef3cbfdc8735acf8ereed@android.comstatic inline int Bool2Int(int value) {
304fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    return !!value;
3059a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
3069a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3079a74d313452f30629e2615eb8cbfe902433582c0reed@android.comvoid SkRGB16_Opaque_Blitter::blitAntiH(int x, int y,
3089a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                                       const SkAlpha* SK_RESTRICT antialias,
309a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                       const int16_t* SK_RESTRICT runs) {
3109a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
3119a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t    srcColor = fRawColor16;
312ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    srcExpanded = fExpandedRaw16;
3139a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    int         ditherInt = Bool2Int(fDoDither);
3149a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t    ditherColor = fRawDither16;
3159a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    // if we have no dithering, this will always fail
3169a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if ((x ^ y) & ditherInt) {
3179a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkTSwap(ditherColor, srcColor);
3189a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
3199a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    for (;;) {
3209a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int count = runs[0];
3219a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkASSERT(count >= 0);
3229a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (count <= 0) {
3239a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            return;
3249a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
3259a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        runs += count;
32631d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
3279a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        unsigned aa = antialias[0];
3289a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        antialias += count;
3299a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (aa) {
3309a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            if (aa == 255) {
3319a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                if (ditherInt) {
3329a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    sk_dither_memset16(device, srcColor,
3339a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                                       ditherColor, count);
3349a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                } else {
3359a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    sk_memset16(device, srcColor, count);
3369a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                }
3379a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            } else {
3389a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                // TODO: respect fDoDither
3399a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                unsigned scale5 = SkAlpha255To256(aa) >> 3;
340ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com                uint32_t src32 = srcExpanded * scale5;
3419a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                scale5 = 32 - scale5; // now we can use it on the device
3429a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                int n = count;
3439a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                do {
3449a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
3459a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
3469a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                } while (--n != 0);
3479a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                goto DONE;
3489a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            }
3499a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
3509a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device += count;
35131d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
3529a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    DONE:
3539a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        // if we have no dithering, this will always fail
3549a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (count & ditherInt) {
3559a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, srcColor);
3569a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
3579a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
3589a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
3599a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3609a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define solid_8_pixels(mask, dst, color)    \
3619a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    do {                                    \
3629a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x80) dst[0] = color;    \
3639a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x40) dst[1] = color;    \
3649a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x20) dst[2] = color;    \
3659a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x10) dst[3] = color;    \
3669a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x08) dst[4] = color;    \
3679a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x04) dst[5] = color;    \
3689a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x02) dst[6] = color;    \
3699a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x01) dst[7] = color;    \
3709a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } while (0)
3719a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3729a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_BlitBW
3739a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_ARGS                  , uint16_t color
3749a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
3759a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_GETADDR               getAddr16
3769a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
3779a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#include "SkBlitBWMaskTemplate.h"
3789a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3796336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut#if !defined(SK_MIPS_HAS_DSP)
3809a74d313452f30629e2615eb8cbfe902433582c0reed@android.comstatic U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
3819a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
3829a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
3836336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut#endif
3849a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
385333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.comvoid SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask,
386333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.com                                      const SkIRect& clip) {
3879a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
3889a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
3899a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        return;
3909a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
39131d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
3929a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
3937989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com    const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
3949a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    int width = clip.width();
3959a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    int height = clip.height();
396e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t      deviceRB = fDevice.rowBytes() - (width << 1);
3979a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    unsigned    maskRB = mask.fRowBytes - width;
398ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    expanded32 = fExpandedRaw16;
39931d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
40089351ec35a05eaf59edb7431d23a754cd084a363commit-bot@chromium.org#if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
401fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define    UNROLL    8
402867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    do {
403867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        int w = width;
404867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        if (w >= UNROLL) {
405641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint32x4_t color, dev_lo, dev_hi;
406641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint32x4_t wn1, wn2, tmp;
407641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint32x4_t vmask_g16, vmask_ng16;
408641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint16x8_t valpha, vdev;
409641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint16x4_t odev_lo, odev_hi, valpha_lo, valpha_hi;
410641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
411641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            // prepare constants
412641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            vmask_g16 = vdupq_n_u32(SK_G16_MASK_IN_PLACE);
413641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            vmask_ng16 = vdupq_n_u32(~SK_G16_MASK_IN_PLACE);
414867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            color = vdupq_n_u32(expanded32);
415fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
416867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            do {
417641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // alpha is 8x8, widen and split to get a pair of 16x4
418641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha = vaddw_u8(vdupq_n_u16(1), vld1_u8(alpha));
419641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha = vshrq_n_u16(valpha, 3);
420641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha_lo = vget_low_u16(valpha);
421641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha_hi = vget_high_u16(valpha);
422641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
423641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // load pixels
424641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                vdev = vld1q_u16(device);
425641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_lo = vmovl_u16(vget_low_u16(vdev));
426641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_hi = vmovl_u16(vget_high_u16(vdev));
427641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
428641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // unpack them in 32 bits
429641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_lo = (dev_lo & vmask_ng16) | vshlq_n_u32(dev_lo & vmask_g16, 16);
430641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_hi = (dev_hi & vmask_ng16) | vshlq_n_u32(dev_hi & vmask_g16, 16);
431641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
432641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // blend with color
433641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = (color - dev_lo) * vmovl_u16(valpha_lo);
434641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = vshrq_n_u32(tmp, 5);
435641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_lo += tmp;
436641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
437641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = vmulq_u32(color - dev_hi, vmovl_u16(valpha_hi));
438641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = vshrq_n_u32(tmp, 5);
439641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_hi += tmp;
440641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
441641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // re-compact
442641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn1 = dev_lo & vmask_ng16;
443641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn2 = vshrq_n_u32(dev_lo, 16) & vmask_g16;
444641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                odev_lo = vmovn_u32(wn1 | wn2);
445641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
446641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn1 = dev_hi & vmask_ng16;
447641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn2 = vshrq_n_u32(dev_hi, 16) & vmask_g16;
448641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                odev_hi = vmovn_u32(wn1 | wn2);
449641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
450641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // store
451641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                vst1q_u16(device, vcombine_u16(odev_lo, odev_hi));
452fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
453867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                device += UNROLL;
454867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                alpha += UNROLL;
455867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                w -= UNROLL;
456867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            } while (w >= UNROLL);
457867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        }
458fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
459641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org        // residuals
460867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        while (w > 0) {
461867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
462867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                                    SkAlpha255To256(*alpha++) >> 3);
463867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            device += 1;
464867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            --w;
465867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        }
466867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
467867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        alpha += maskRB;
468867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    } while (--height != 0);
469fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    UNROLL
4706336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut#elif SK_MIPS_HAS_DSP
4716336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut    blitmask_d565_opaque_mips(width, height, device, deviceRB, alpha, expanded32, maskRB);
472867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#else   // non-neon code
4739a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    do {
4749a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int w = width;
4759a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        do {
476ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com            *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
4779a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                                    SkAlpha255To256(*alpha++) >> 3);
4789a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            device += 1;
4799a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        } while (--w != 0);
4809a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
4819a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        alpha += maskRB;
4829a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } while (--height != 0);
483867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
4849a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
4859a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
486ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.comvoid SkRGB16_Opaque_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
487ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
488e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t    deviceRB = fDevice.rowBytes();
489fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
490ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    // TODO: respect fDoDither
491ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    unsigned scale5 = SkAlpha255To256(alpha) >> 3;
492ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t src32 =  fExpandedRaw16 * scale5;
493ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    scale5 = 32 - scale5;
494ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    do {
495ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
496ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        *device = SkCompact_rgb_16((src32 + dst32) >> 5);
497ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
498ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    } while (--height != 0);
499ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com}
500ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com
5019a74d313452f30629e2615eb8cbfe902433582c0reed@android.comvoid SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) {
5029a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
5039a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
504e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t      deviceRB = fDevice.rowBytes();
5059a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t    color16 = fColor16;
50631d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
5079a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if (fDoDither) {
5089a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        uint16_t ditherColor = fRawDither16;
5099a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if ((x ^ y) & 1) {
5109a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, color16);
5119a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
5129a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        while (--height >= 0) {
5139a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            sk_dither_memset16(device, color16, ditherColor, width);
5149a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, color16);
5159a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            device = (uint16_t*)((char*)device + deviceRB);
5169a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
5179a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } else {  // no dither
5189a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        while (--height >= 0) {
5199a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            sk_memset16(device, color16, width);
5209a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            device = (uint16_t*)((char*)device + deviceRB);
5219a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
5229a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
5239a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
5249a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
5259a74d313452f30629e2615eb8cbfe902433582c0reed@android.com///////////////////////////////////////////////////////////////////////////////
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    : INHERITED(device) {
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkColor color = paint.getColor();
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcColor32 = SkPreMultiplyColor(color);
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fScale = SkAlpha255To256(SkColorGetA(color));
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int r = SkColorGetR(color);
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int g = SkColorGetG(color);
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int b = SkColorGetB(color);
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we're dithered, use fRawDither16 to hold that.
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((fDoDither = paint.isDither()) != false) {
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
543ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com
544ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    fExpandedRaw16 = SkExpand_rgb_16(fRawColor16);
545ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
549402448d6818cab9d7b7633a0c18fcf574c915357mlee
550402448d6818cab9d7b7633a0c18fcf574c915357mlee    // compute SkBlitRow::Procs
551402448d6818cab9d7b7633a0c18fcf574c915357mlee    unsigned flags = 0;
552402448d6818cab9d7b7633a0c18fcf574c915357mlee
553402448d6818cab9d7b7633a0c18fcf574c915357mlee    if (SkGetPackedA32(fSrcColor32) < 0xFF) {
554402448d6818cab9d7b7633a0c18fcf574c915357mlee        flags |= SkBlitRow::kSrcPixelAlpha_Flag;
555402448d6818cab9d7b7633a0c18fcf574c915357mlee    }
556402448d6818cab9d7b7633a0c18fcf574c915357mlee
557402448d6818cab9d7b7633a0c18fcf574c915357mlee    if (fDoDither) {
558402448d6818cab9d7b7633a0c18fcf574c915357mlee        flags |= SkBlitRow::kDither_Flag;
559402448d6818cab9d7b7633a0c18fcf574c915357mlee    }
560402448d6818cab9d7b7633a0c18fcf574c915357mlee
561402448d6818cab9d7b7633a0c18fcf574c915357mlee    fColorProc16 = SkBlitRow::ColorFactory16(flags);
5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!fDoDither && 256 == fScale) {
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *value = fRawColor16;
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return &fDevice;
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
572a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkRGB16_Blitter::blitH(int x, int y, int width) {
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(width > 0);
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
577402448d6818cab9d7b7633a0c18fcf574c915357mlee    fColorProc16(device, fSrcColor32, width, x, y);
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitAntiH(int x, int y,
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkAlpha* SK_RESTRICT antialias,
582a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                const int16_t* SK_RESTRICT runs) {
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
584ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    srcExpanded = fExpandedRaw16;
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    scale = fScale;
5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5879a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    // TODO: respect fDoDither
5889a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    for (;;) {
5899a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int count = runs[0];
5909a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkASSERT(count >= 0);
5919a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (count <= 0) {
5929a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            return;
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5949a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        runs += count;
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5969a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        unsigned aa = antialias[0];
5979a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        antialias += count;
5989a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (aa) {
5999a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
600ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com            uint32_t src32 =  srcExpanded * scale5;
6019a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            scale5 = 32 - scale5;
6029a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            do {
6039a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
6049a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
6059a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            } while (--count != 0);
6069a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            continue;
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6089a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device += count;
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                  U16CPU srcColor) {
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_BlendBW
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS                  , unsigned dst_scale, U16CPU src_color
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, dst_scale, src_color)
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR               getAddr16
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
631333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.comvoid SkRGB16_Blitter::blitMask(const SkMask& mask,
632333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.com                               const SkIRect& clip) {
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
6349a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
6397989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com    const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = clip.width();
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int height = clip.height();
642e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t      deviceRB = fDevice.rowBytes() - (width << 1);
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    maskRB = mask.fRowBytes - width;
644ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    color32 = fExpandedRaw16;
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6469a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    unsigned scale256 = fScale;
6479a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    do {
6489a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int w = width;
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
6509a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            unsigned aa = *alpha++;
6519a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
6529a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            uint32_t src32 = color32 * scale;
6539a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
6549a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
6559a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        } while (--w != 0);
6569a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
6579a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        alpha += maskRB;
6589a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } while (--height != 0);
6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
663e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t    deviceRB = fDevice.rowBytes();
6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
665ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    // TODO: respect fDoDither
666ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
667ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t src32 =  fExpandedRaw16 * scale5;
668ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    scale5 = 32 - scale5;
669ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    do {
670ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
671ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        *device = SkCompact_rgb_16((src32 + dst32) >> 5);
672ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
673ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    } while (--height != 0);
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
679e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t    deviceRB = fDevice.rowBytes();
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6819a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    while (--height >= 0) {
682402448d6818cab9d7b7633a0c18fcf574c915357mlee        fColorProc16(device, fSrcColor32, width, x, y);
6839a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
69087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                                   const SkPaint& paint,
69187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                                   SkShader::Context* shaderContext)
69287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    : SkRGB16_Shader_Blitter(device, paint, shaderContext) {
6935119bdb952025a30f115b9c6a187173956e55097reed@android.com    SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags));
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
696a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) {
6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
70087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context*    shaderContext = fShaderContext;
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
70287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    int alpha = shaderContext->getSpan16Alpha();
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
70487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan16(x, y, device, width);
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t* span16 = (uint16_t*)fBuffer;
70787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan16(x, y, span16, width);
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
712dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.comvoid SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
71387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context* shaderContext = fShaderContext;
71487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint16_t*          dst = fDevice.getAddr16(x, y);
71587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    size_t             dstRB = fDevice.rowBytes();
71687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    int                alpha = shaderContext->getSpan16Alpha();
717dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com
718dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    if (0xFF == alpha) {
7193c9b2a4a0e4f57db23640e85959ee78b86634628reed@android.com        if (fShaderFlags & SkShader::kConstInY16_Flag) {
720dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            // have the shader blit directly into the device the first time
72187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            shaderContext->shadeSpan16(x, y, dst, width);
722dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            // and now just memcpy that line on the subsequent lines
723dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            if (--height > 0) {
724dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                const uint16_t* orig = dst;
725dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                do {
726dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                    dst = (uint16_t*)((char*)dst + dstRB);
727dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                    memcpy(dst, orig, width << 1);
728dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                } while (--height);
729dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            }
730dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        } else {    // need to call shadeSpan16 for every line
731dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            do {
73287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan16(x, y, dst, width);
733dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                y += 1;
734dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                dst = (uint16_t*)((char*)dst + dstRB);
735dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            } while (--height);
736dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        }
737dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    } else {
738dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        int scale = SkAlpha255To256(alpha);
739dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        uint16_t* span16 = (uint16_t*)fBuffer;
7403c9b2a4a0e4f57db23640e85959ee78b86634628reed@android.com        if (fShaderFlags & SkShader::kConstInY16_Flag) {
74187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            shaderContext->shadeSpan16(x, y, span16, width);
742dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            do {
743dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                SkBlendRGB16(span16, dst, scale, width);
744dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                dst = (uint16_t*)((char*)dst + dstRB);
745dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            } while (--height);
746dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        } else {
747dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            do {
74887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan16(x, y, span16, width);
749dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                SkBlendRGB16(span16, dst, scale, width);
750dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                y += 1;
751dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com                dst = (uint16_t*)((char*)dst + dstRB);
752dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com            } while (--height);
753dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com        }
754dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    }
755dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com}
756dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         const SkAlpha* SK_RESTRICT antialias,
759a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                         const int16_t* SK_RESTRICT runs) {
76087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context*     shaderContext = fShaderContext;
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT span = fBuffer;
76287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint16_t* SK_RESTRICT  device = fDevice.getAddr16(x, y);
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
76487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    int alpha = shaderContext->getSpan16Alpha();
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* span16 = (uint16_t*)span;
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = *antialias;
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 255) {
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                // go direct to the device!
77887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan16(x, y, device, count);
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else if (aa) {
78087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan16(x, y, span16, count);
7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {  // span alpha is < 255
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        alpha = SkAlpha255To256(alpha);
7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = SkAlphaMul(*antialias, alpha);
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa) {
79987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan16(x, y, span16, count);
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
81487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                               const SkPaint& paint,
81587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                               SkShader::Context* shaderContext)
81687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org: INHERITED(device, paint, shaderContext) {
8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getXfermode() == NULL);
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // compute SkBlitRow::Procs
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned flags = 0;
823fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
8245119bdb952025a30f115b9c6a187173956e55097reed@android.com    uint32_t shaderFlags = fShaderFlags;
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // shaders take care of global alpha, so we never set it in SkBlitRow
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= SkBlitRow::kSrcPixelAlpha_Flag;
828c2050e3a3ecfb8738b36e2add15c526e8e0f21fecommit-bot@chromium.org    }
8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // don't dither if the shader is really 16bit
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= SkBlitRow::kDither_Flag;
8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // used when we know our global alpha is 0xFF
834a7f11918d92621507f35b228a290f05dcaf0f4b6reed    fOpaqueProc = SkBlitRow::Factory16(flags);
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // used when we know our global alpha is < 0xFF
836a7f11918d92621507f35b228a290f05dcaf0f4b6reed    fAlphaProc  = SkBlitRow::Factory16(flags | SkBlitRow::kGlobalAlpha_Flag);
8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fBuffer);
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
84687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fShaderContext->shadeSpan(x, y, fBuffer, width);
8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // shaders take care of global alpha, so we pass 0xFF (should be ignored)
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8515119bdb952025a30f115b9c6a187173956e55097reed@android.comvoid SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
85287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context* shaderContext = fShaderContext;
853a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkBlitRow::Proc16  proc = fOpaqueProc;
85487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkPMColor*         buffer = fBuffer;
85587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint16_t*          dst = fDevice.getAddr16(x, y);
85687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    size_t             dstRB = fDevice.rowBytes();
8575119bdb952025a30f115b9c6a187173956e55097reed@android.com
8583c9b2a4a0e4f57db23640e85959ee78b86634628reed@android.com    if (fShaderFlags & SkShader::kConstInY32_Flag) {
85987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan(x, y, buffer, width);
8605119bdb952025a30f115b9c6a187173956e55097reed@android.com        do {
8615119bdb952025a30f115b9c6a187173956e55097reed@android.com            proc(dst, buffer, width, 0xFF, x, y);
8625119bdb952025a30f115b9c6a187173956e55097reed@android.com            y += 1;
8635119bdb952025a30f115b9c6a187173956e55097reed@android.com            dst = (uint16_t*)((char*)dst + dstRB);
8645119bdb952025a30f115b9c6a187173956e55097reed@android.com        } while (--height);
8655119bdb952025a30f115b9c6a187173956e55097reed@android.com    } else {
8665119bdb952025a30f115b9c6a187173956e55097reed@android.com        do {
86787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            shaderContext->shadeSpan(x, y, buffer, width);
8685119bdb952025a30f115b9c6a187173956e55097reed@android.com            proc(dst, buffer, width, 0xFF, x, y);
8695119bdb952025a30f115b9c6a187173956e55097reed@android.com            y += 1;
8705119bdb952025a30f115b9c6a187173956e55097reed@android.com            dst = (uint16_t*)((char*)dst + dstRB);
8715119bdb952025a30f115b9c6a187173956e55097reed@android.com        } while (--height);
8725119bdb952025a30f115b9c6a187173956e55097reed@android.com    }
8735119bdb952025a30f115b9c6a187173956e55097reed@android.com}
8745119bdb952025a30f115b9c6a187173956e55097reed@android.com
8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int count = 0;
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int n = *runs;
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (n == 0 || *aa == 0) {
8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += n;
8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        aa += n;
8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count += n;
8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       const SkAlpha* SK_RESTRICT antialias,
891a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                       const int16_t* SK_RESTRICT runs) {
89287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context*     shaderContext = fShaderContext;
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT span = fBuffer;
89487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint16_t* SK_RESTRICT  device = fDevice.getAddr16(x, y);
8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = *runs;
8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int aa = *antialias;
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (0 == aa) {
9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
91387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan(x, y, span, nonZeroCount);
9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor* localSpan = span;
9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
917a7f11918d92621507f35b228a290f05dcaf0f4b6reed            SkBlitRow::Proc16 proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc(device, localSpan, count, aa, x, y);
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            nonZeroCount -= count;
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (nonZeroCount == 0) {
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            localSpan += count;
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(nonZeroCount > 0);
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count = *runs;
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count > 0);
9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa = *antialias;
9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
94087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                const SkBitmap& device, const SkPaint& paint,
94187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                SkShader::Context* shaderContext)
94287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org: INHERITED(device, paint, shaderContext) {
9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode = paint.getXfermode();
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fXfermode);
9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode->ref();
9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = device.width();
9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fAAExpand = (uint8_t*)(fBuffer + width);
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode->unref();
9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fBuffer);
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t*   device = fDevice.getAddr16(x, y);
9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor*  span = fBuffer;
9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
96387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fShaderContext->shadeSpan(x, y, span, width);
9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode->xfer16(device, span, width, NULL);
9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkAlpha* SK_RESTRICT antialias,
969a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                const int16_t* SK_RESTRICT runs) {
97087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context*     shaderContext = fShaderContext;
97187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkXfermode*            mode = fXfermode;
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT span = fBuffer;
97387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint8_t* SK_RESTRICT   aaExpand = fAAExpand;
97487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint16_t* SK_RESTRICT  device = fDevice.getAddr16(x, y);
9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
9778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = *runs;
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int aa = *antialias;
9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (0 == aa) {
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int nonZeroCount = count + count_nonzero_span(runs + count,
9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                      antialias + count);
9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
99487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan(x, y, span, nonZeroCount);
9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x += nonZeroCount;
9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor* localSpan = span;
9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 0xFF) {
10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                mode->xfer16(device, localSpan, count, NULL);
10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkASSERT(aa);
10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memset(aaExpand, aa, count);
10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                mode->xfer16(device, localSpan, count, aaExpand);
10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            nonZeroCount -= count;
10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (nonZeroCount == 0) {
10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            localSpan += count;
10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(nonZeroCount > 0);
10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count = *runs;
10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count > 0);
10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa = *antialias;
10188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1019fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10221fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com///////////////////////////////////////////////////////////////////////////////
10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10241fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comSkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
102587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        SkShader::Context* shaderContext,
1026a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org        SkTBlitterAllocator* allocator) {
1027a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org    SkASSERT(allocator != NULL);
1028a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org
10291fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkBlitter* blitter;
10301fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkShader* shader = paint.getShader();
10311fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkXfermode* mode = paint.getXfermode();
10321fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
10331fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // we require a shader if there is an xfermode, handled by our caller
103449f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(NULL == mode || shader);
10351fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
10361fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    if (shader) {
103787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        SkASSERT(shaderContext != NULL);
10381fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        if (mode) {
103987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint,
104087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                                                          shaderContext);
104187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        } else if (shaderContext->canCallShadeSpan16()) {
104287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Shader16_Blitter>(device, paint, shaderContext);
10431fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else {
104487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint, shaderContext);
10451fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        }
10461fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    } else {
10471fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        // no shader, no xfermode, (and we always ignore colorfilter)
10481fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        SkColor color = paint.getColor();
10491fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        if (0 == SkColorGetA(color)) {
1050a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkNullBlitter>();
1051867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#ifdef USE_BLACK_BLITTER
10521fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else if (SK_ColorBLACK == color) {
1053a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Black_Blitter>(device, paint);
1054867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
10551fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else if (0xFF == SkColorGetA(color)) {
1056a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Opaque_Blitter>(device, paint);
10571fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else {
1058a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Blitter>(device, paint);
10591fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        }
10601fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    }
1061fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
10621fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    return blitter;
10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1064