1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitRow.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCoreBlitters.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDither.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
14e552dc82be1512df0a8a7f24310d27d2740d7601djsollen@google.com#include "SkUtilsArm.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17f62833d9c9075dd1028ef4395e3370d2597d9115mtklein#if defined(__mips_dsp)
186336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesutextern void blitmask_d565_opaque_mips(int width, int height, uint16_t* device,
196336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut                                      unsigned deviceRB, const uint8_t* alpha,
206336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut                                      uint32_t expanded32, unsigned maskRB);
216336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut#endif
226336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut
2389351ec35a05eaf59edb7431d23a754cd084a363commit-bot@chromium.org#if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
24867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    #include <arm_neon.h>
25dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhangextern void SkRGB16BlitterBlitV_neon(uint16_t* device,
26dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang                                     int height,
27dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang                                     size_t deviceRB,
28dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang                                     unsigned scale,
29dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang                                     uint32_t src32);
30867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#else
31867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    // if we don't have neon, then our black blitter is worth the extra code
32867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    #define USE_BLACK_BLITTER
33867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
34867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        int count) {
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // see if we need to write one short before we can cast to an 4byte ptr
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // (we do this subtract rather than (unsigned)dst so we don't get warnings
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        //  on 64bit machines)
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (((char*)dst - (char*)0) & 2) {
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *dst++ = value;
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count -= 1;
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkTSwap(value, other);
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
46fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // fast way to set [value,other] pairs
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_CPU_BENDIAN
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
53fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count & 1) {
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst[count - 1] = value;
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
621fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Blitter : public SkRasterBlitter {
631fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
6441e010cb901c0da9066c4df562030808c9ccd7f8reed    SkRGB16_Blitter(const SkPixmap& device, const SkPaint& paint);
6536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override;
66a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
6736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                           const int16_t* runs) override;
6836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitV(int x, int y, int height, SkAlpha alpha) override;
6936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitRect(int x, int y, int width, int height) override;
7041e010cb901c0da9066c4df562030808c9ccd7f8reed    void blitMask(const SkMask&, const SkIRect&) override;
7141e010cb901c0da9066c4df562030808c9ccd7f8reed    const SkPixmap* justAnOpaqueColor(uint32_t*) override;
72fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
731fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprotected:
741fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkPMColor   fSrcColor32;
75ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    fExpandedRaw16;
761fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    unsigned    fScale;
771fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    uint16_t    fColor16;       // already scaled by fScale
781fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    uint16_t    fRawColor16;    // unscaled
791fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    uint16_t    fRawDither16;   // unscaled
801fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkBool8     fDoDither;
81fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
82402448d6818cab9d7b7633a0c18fcf574c915357mlee    SkBlitRow::ColorProc16 fColorProc16;
83402448d6818cab9d7b7633a0c18fcf574c915357mlee
841fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // illegal
851fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Blitter& operator=(const SkRGB16_Blitter&);
86fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
871fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkRasterBlitter INHERITED;
881fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
891fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
901fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Opaque_Blitter : public SkRGB16_Blitter {
911fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
9241e010cb901c0da9066c4df562030808c9ccd7f8reed    SkRGB16_Opaque_Blitter(const SkPixmap& device, const SkPaint& paint);
9336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override;
9441e010cb901c0da9066c4df562030808c9ccd7f8reed    void blitAntiH(int x, int y, const SkAlpha* antialias, const int16_t* runs) override;
9536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitV(int x, int y, int height, SkAlpha alpha) override;
9636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitRect(int x, int y, int width, int height) override;
9741e010cb901c0da9066c4df562030808c9ccd7f8reed    void blitMask(const SkMask&, 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:
10641e010cb901c0da9066c4df562030808c9ccd7f8reed    SkRGB16_Black_Blitter(const SkPixmap& device, const SkPaint& paint);
10736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitMask(const SkMask&, const SkIRect&) override;
10841e010cb901c0da9066c4df562030808c9ccd7f8reed    void blitAntiH(int x, int y, const SkAlpha* antialias, const int16_t* runs) override;
109fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1101fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1111fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkRGB16_Opaque_Blitter INHERITED;
1121fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
113867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
1141fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
1151fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Shader_Blitter : public SkShaderBlitter {
1161fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
11741e010cb901c0da9066c4df562030808c9ccd7f8reed    SkRGB16_Shader_Blitter(const SkPixmap& device, const SkPaint& paint,
11887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                           SkShader::Context* shaderContext);
1191fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual ~SkRGB16_Shader_Blitter();
12036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override;
121a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
12236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                           const int16_t* runs) override;
12336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitRect(int x, int y, int width, int height) override;
124fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1251fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprotected:
126a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkPMColor*          fBuffer;
127a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkBlitRow::Proc16   fOpaqueProc;
128a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkBlitRow::Proc16   fAlphaProc;
129fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1301fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1311fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // illegal
1321fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Shader_Blitter& operator=(const SkRGB16_Shader_Blitter&);
133fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1341fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkShaderBlitter INHERITED;
1351fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
1361fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
1371fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comclass SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter {
1381fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.compublic:
13941e010cb901c0da9066c4df562030808c9ccd7f8reed    SkRGB16_Shader_Xfermode_Blitter(const SkPixmap& device, const SkPaint& paint,
14087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                    SkShader::Context* shaderContext);
1411fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    virtual ~SkRGB16_Shader_Xfermode_Blitter();
14236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override;
143a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com    virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
14436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                           const int16_t* runs) override;
145fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1461fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.comprivate:
1471fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkXfermode* fXfermode;
1481fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkPMColor*  fBuffer;
1491fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    uint8_t*    fAAExpand;
150fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1511fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // illegal
1521fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkRGB16_Shader_Xfermode_Blitter& operator=(const SkRGB16_Shader_Xfermode_Blitter&);
153fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1541fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    typedef SkShaderBlitter INHERITED;
1551fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com};
1561fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
1571fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com///////////////////////////////////////////////////////////////////////////////
158867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#ifdef USE_BLACK_BLITTER
15941e010cb901c0da9066c4df562030808c9ccd7f8reedSkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkPixmap& device, const SkPaint& paint)
160dafaf7ac4d89f183dc515907665cdac3e3098466reed@android.com    : INHERITED(device, paint) {
16196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(paint.getShader() == nullptr);
16296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(paint.getColorFilter() == nullptr);
16396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(paint.getXfermode() == nullptr);
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getColor() == SK_ColorBLACK);
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 1
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define black_8_pixels(mask, dst)       \
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                \
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x80) dst[0] = 0;    \
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x40) dst[1] = 0;    \
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x20) dst[2] = 0;    \
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x10) dst[3] = 0;    \
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x08) dst[4] = 0;    \
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x04) dst[5] = 0;    \
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x02) dst[6] = 0;    \
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x01) dst[7] = 0;    \
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline black_8_pixels(U8CPU mask, uint16_t dst[])
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x80) dst[0] = 0;
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x40) dst[1] = 0;
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x20) dst[2] = 0;
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x10) dst[3] = 0;
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x08) dst[4] = 0;
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x04) dst[5] = 0;
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x02) dst[6] = 0;
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x01) dst[7] = 0;
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_Black_BlitBW
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      black_8_pixels(mask, dst)
19641e010cb901c0da9066c4df562030808c9ccd7f8reed#define SK_BLITBWMASK_GETADDR               writable_addr16
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
200333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.comvoid SkRGB16_Black_Blitter::blitMask(const SkMask& mask,
201333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.com                                     const SkIRect& clip) {
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRGB16_Black_BlitBW(fDevice, mask, clip);
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
20541e010cb901c0da9066c4df562030808c9ccd7f8reed        uint16_t* SK_RESTRICT device = fDevice.writable_addr16(clip.fLeft, clip.fTop);
2067989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com        const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned width = clip.width();
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned height = clip.height();
209e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com        size_t deviceRB = fDevice.rowBytes() - (width << 1);
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned maskRB = mask.fRowBytes - width;
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)height > 0);
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)width > 0);
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)deviceRB >= 0);
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)maskRB >= 0);
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned w = width;
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned aa = *alpha++;
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device += 1;
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while (--w != 0);
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device = (uint16_t*)((char*)device + deviceRB);
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += maskRB;
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Black_Blitter::blitAntiH(int x, int y,
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      const SkAlpha* SK_RESTRICT antialias,
232a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                      const int16_t* SK_RESTRICT runs) {
23341e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = runs[0];
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count >= 0);
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += count;
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned aa = antialias[0];
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        antialias += count;
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (aa) {
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 255) {
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memset(device, 0, count << 1);
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                aa = SkAlpha255To256(255 - aa);
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                do {
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    *device = SkAlphaMulRGB16(*device, aa);
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    device += 1;
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } while (--count != 0);
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                continue;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device += count;
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
260867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2629a74d313452f30629e2615eb8cbfe902433582c0reed@android.com///////////////////////////////////////////////////////////////////////////////
2639a74d313452f30629e2615eb8cbfe902433582c0reed@android.com///////////////////////////////////////////////////////////////////////////////
2649a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
26541e010cb901c0da9066c4df562030808c9ccd7f8reedSkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkPixmap& device, const SkPaint& paint)
26641e010cb901c0da9066c4df562030808c9ccd7f8reed    : INHERITED(device, paint) {}
2679a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
268a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) {
2699a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(width > 0);
2709a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(x + width <= fDevice.width());
27141e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
2729a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t srcColor = fColor16;
27331d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
2749a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(fRawColor16 == srcColor);
2759a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if (fDoDither) {
2769a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        uint16_t ditherColor = fRawDither16;
2779a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if ((x ^ y) & 1) {
2789a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, srcColor);
2799a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
2809a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        sk_dither_memset16(device, srcColor, ditherColor, width);
2819a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } else {
2829a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        sk_memset16(device, srcColor, width);
2839a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
2849a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
2859a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
2869a74d313452f30629e2615eb8cbfe902433582c0reed@android.com// return 1 or 0 from a bool
28763debae4c1020fa1e0ccd92ef3cbfdc8735acf8ereed@android.comstatic inline int Bool2Int(int value) {
288fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    return !!value;
2899a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
2909a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
2919a74d313452f30629e2615eb8cbfe902433582c0reed@android.comvoid SkRGB16_Opaque_Blitter::blitAntiH(int x, int y,
2929a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                                       const SkAlpha* SK_RESTRICT antialias,
293a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                       const int16_t* SK_RESTRICT runs) {
29441e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
2959a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t    srcColor = fRawColor16;
296ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    srcExpanded = fExpandedRaw16;
2979a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    int         ditherInt = Bool2Int(fDoDither);
2989a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t    ditherColor = fRawDither16;
2999a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    // if we have no dithering, this will always fail
3009a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if ((x ^ y) & ditherInt) {
3019a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkTSwap(ditherColor, srcColor);
3029a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
3039a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    for (;;) {
3049a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int count = runs[0];
3059a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkASSERT(count >= 0);
3069a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (count <= 0) {
3079a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            return;
3089a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
3099a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        runs += count;
31031d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
3119a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        unsigned aa = antialias[0];
3129a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        antialias += count;
3139a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (aa) {
3149a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            if (aa == 255) {
3159a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                if (ditherInt) {
3169a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    sk_dither_memset16(device, srcColor,
3179a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                                       ditherColor, count);
3189a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                } else {
3199a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    sk_memset16(device, srcColor, count);
3209a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                }
3219a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            } else {
3229a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                // TODO: respect fDoDither
3239a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                unsigned scale5 = SkAlpha255To256(aa) >> 3;
324ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com                uint32_t src32 = srcExpanded * scale5;
3259a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                scale5 = 32 - scale5; // now we can use it on the device
3269a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                int n = count;
3279a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                do {
3289a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
3299a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                    *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
3309a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                } while (--n != 0);
3319a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                goto DONE;
3329a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            }
3339a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
3349a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device += count;
33531d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
3369a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    DONE:
3379a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        // if we have no dithering, this will always fail
3389a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (count & ditherInt) {
3399a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, srcColor);
3409a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
3419a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
3429a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
3439a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3449a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define solid_8_pixels(mask, dst, color)    \
3459a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    do {                                    \
3469a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x80) dst[0] = color;    \
3479a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x40) dst[1] = color;    \
3489a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x20) dst[2] = color;    \
3499a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x10) dst[3] = color;    \
3509a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x08) dst[4] = color;    \
3519a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x04) dst[5] = color;    \
3529a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x02) dst[6] = color;    \
3539a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (mask & 0x01) dst[7] = color;    \
3549a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } while (0)
3559a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
3569a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_BlitBW
3579a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_ARGS                  , uint16_t color
3589a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
35941e010cb901c0da9066c4df562030808c9ccd7f8reed#define SK_BLITBWMASK_GETADDR               writable_addr16
3609a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
3619a74d313452f30629e2615eb8cbfe902433582c0reed@android.com#include "SkBlitBWMaskTemplate.h"
3629a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
363f62833d9c9075dd1028ef4395e3370d2597d9115mtklein#if !defined(__mips_dsp)
3649a74d313452f30629e2615eb8cbfe902433582c0reed@android.comstatic U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
3659a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
3669a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
3676336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut#endif
3689a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
369333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.comvoid SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask,
370333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.com                                      const SkIRect& clip) {
3719a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
3729a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
3739a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        return;
3749a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
37531d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
37641e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT device = fDevice.writable_addr16(clip.fLeft, clip.fTop);
3777989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com    const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
3789a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    int width = clip.width();
3799a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    int height = clip.height();
380e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t      deviceRB = fDevice.rowBytes() - (width << 1);
3819a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    unsigned    maskRB = mask.fRowBytes - width;
382ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    expanded32 = fExpandedRaw16;
38331d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
38489351ec35a05eaf59edb7431d23a754cd084a363commit-bot@chromium.org#if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
385fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define    UNROLL    8
386867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    do {
387867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        int w = width;
388867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        if (w >= UNROLL) {
389641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint32x4_t color, dev_lo, dev_hi;
390641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint32x4_t wn1, wn2, tmp;
391641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint32x4_t vmask_g16, vmask_ng16;
392641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint16x8_t valpha, vdev;
393641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            uint16x4_t odev_lo, odev_hi, valpha_lo, valpha_hi;
394641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
395641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            // prepare constants
396641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            vmask_g16 = vdupq_n_u32(SK_G16_MASK_IN_PLACE);
397641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org            vmask_ng16 = vdupq_n_u32(~SK_G16_MASK_IN_PLACE);
398867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            color = vdupq_n_u32(expanded32);
399fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
400867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            do {
401641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // alpha is 8x8, widen and split to get a pair of 16x4
402641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha = vaddw_u8(vdupq_n_u16(1), vld1_u8(alpha));
403641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha = vshrq_n_u16(valpha, 3);
404641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha_lo = vget_low_u16(valpha);
405641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                valpha_hi = vget_high_u16(valpha);
406641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
407641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // load pixels
408641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                vdev = vld1q_u16(device);
409641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_lo = vmovl_u16(vget_low_u16(vdev));
410641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_hi = vmovl_u16(vget_high_u16(vdev));
411641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
412641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // unpack them in 32 bits
413641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_lo = (dev_lo & vmask_ng16) | vshlq_n_u32(dev_lo & vmask_g16, 16);
414641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_hi = (dev_hi & vmask_ng16) | vshlq_n_u32(dev_hi & vmask_g16, 16);
415641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
416641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // blend with color
417641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = (color - dev_lo) * vmovl_u16(valpha_lo);
418641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = vshrq_n_u32(tmp, 5);
419641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_lo += tmp;
420641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
421641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = vmulq_u32(color - dev_hi, vmovl_u16(valpha_hi));
422641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                tmp = vshrq_n_u32(tmp, 5);
423641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                dev_hi += tmp;
424641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
425641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // re-compact
426641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn1 = dev_lo & vmask_ng16;
427641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn2 = vshrq_n_u32(dev_lo, 16) & vmask_g16;
428641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                odev_lo = vmovn_u32(wn1 | wn2);
429641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
430641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn1 = dev_hi & vmask_ng16;
431641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                wn2 = vshrq_n_u32(dev_hi, 16) & vmask_g16;
432641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                odev_hi = vmovn_u32(wn1 | wn2);
433641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org
434641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                // store
435641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org                vst1q_u16(device, vcombine_u16(odev_lo, odev_hi));
436fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
437867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                device += UNROLL;
438867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                alpha += UNROLL;
439867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                w -= UNROLL;
440867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            } while (w >= UNROLL);
441867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        }
442fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
443641a2491964f7e5921fad6649be08175e03b0434commit-bot@chromium.org        // residuals
444867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        while (w > 0) {
445867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
446867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com                                    SkAlpha255To256(*alpha++) >> 3);
447867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            device += 1;
448867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com            --w;
449867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        }
450867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
451867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com        alpha += maskRB;
452867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com    } while (--height != 0);
453fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    UNROLL
454f62833d9c9075dd1028ef4395e3370d2597d9115mtklein#elif defined(__mips_dsp)
4556336f7c225f7806f5bbccea90ba6d2c881e8a470djordje.pesut    blitmask_d565_opaque_mips(width, height, device, deviceRB, alpha, expanded32, maskRB);
456867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#else   // non-neon code
4579a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    do {
4589a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int w = width;
4599a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        do {
460ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com            *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
4619a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                                    SkAlpha255To256(*alpha++) >> 3);
4629a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            device += 1;
4639a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        } while (--w != 0);
4649a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
4659a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        alpha += maskRB;
4669a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } while (--height != 0);
467867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
4689a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
4699a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
470ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.comvoid SkRGB16_Opaque_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
47141e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
472e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t    deviceRB = fDevice.rowBytes();
473fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
474ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    // TODO: respect fDoDither
475ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    unsigned scale5 = SkAlpha255To256(alpha) >> 3;
476ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t src32 =  fExpandedRaw16 * scale5;
477ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    scale5 = 32 - scale5;
478dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang#if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
479dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang    SkRGB16BlitterBlitV_neon(device, height, deviceRB, scale5, src32);
480dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang#else
481ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    do {
482ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
483ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        *device = SkCompact_rgb_16((src32 + dst32) >> 5);
484ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
485ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    } while (--height != 0);
486dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang#endif
487ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com}
488ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com
4899a74d313452f30629e2615eb8cbfe902433582c0reed@android.comvoid SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) {
4909a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
49141e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
492e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t      deviceRB = fDevice.rowBytes();
4939a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    uint16_t    color16 = fColor16;
49431d1c64bd54dd2b216846a30da4cc2e96765ec5freed@android.com
4959a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    if (fDoDither) {
4969a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        uint16_t ditherColor = fRawDither16;
4979a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if ((x ^ y) & 1) {
4989a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, color16);
4999a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
5009a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        while (--height >= 0) {
5019a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            sk_dither_memset16(device, color16, ditherColor, width);
5029a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            SkTSwap(ditherColor, color16);
5039a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            device = (uint16_t*)((char*)device + deviceRB);
5049a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
5059a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } else {  // no dither
5069a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        while (--height >= 0) {
5079a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            sk_memset16(device, color16, width);
5089a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            device = (uint16_t*)((char*)device + deviceRB);
5099a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        }
5109a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    }
5119a74d313452f30629e2615eb8cbfe902433582c0reed@android.com}
5129a74d313452f30629e2615eb8cbfe902433582c0reed@android.com
5139a74d313452f30629e2615eb8cbfe902433582c0reed@android.com///////////////////////////////////////////////////////////////////////////////
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
51541e010cb901c0da9066c4df562030808c9ccd7f8reedSkRGB16_Blitter::SkRGB16_Blitter(const SkPixmap& device, const SkPaint& paint)
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    : INHERITED(device) {
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkColor color = paint.getColor();
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcColor32 = SkPreMultiplyColor(color);
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fScale = SkAlpha255To256(SkColorGetA(color));
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int r = SkColorGetR(color);
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int g = SkColorGetG(color);
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int b = SkColorGetB(color);
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we're dithered, use fRawDither16 to hold that.
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((fDoDither = paint.isDither()) != false) {
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
531ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com
532ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    fExpandedRaw16 = SkExpand_rgb_16(fRawColor16);
533ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
537402448d6818cab9d7b7633a0c18fcf574c915357mlee
538402448d6818cab9d7b7633a0c18fcf574c915357mlee    // compute SkBlitRow::Procs
539402448d6818cab9d7b7633a0c18fcf574c915357mlee    unsigned flags = 0;
540402448d6818cab9d7b7633a0c18fcf574c915357mlee
541402448d6818cab9d7b7633a0c18fcf574c915357mlee    if (SkGetPackedA32(fSrcColor32) < 0xFF) {
542402448d6818cab9d7b7633a0c18fcf574c915357mlee        flags |= SkBlitRow::kSrcPixelAlpha_Flag;
543402448d6818cab9d7b7633a0c18fcf574c915357mlee    }
544402448d6818cab9d7b7633a0c18fcf574c915357mlee
545402448d6818cab9d7b7633a0c18fcf574c915357mlee    if (fDoDither) {
546402448d6818cab9d7b7633a0c18fcf574c915357mlee        flags |= SkBlitRow::kDither_Flag;
547402448d6818cab9d7b7633a0c18fcf574c915357mlee    }
548402448d6818cab9d7b7633a0c18fcf574c915357mlee
549402448d6818cab9d7b7633a0c18fcf574c915357mlee    fColorProc16 = SkBlitRow::ColorFactory16(flags);
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
55241e010cb901c0da9066c4df562030808c9ccd7f8reedconst SkPixmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!fDoDither && 256 == fScale) {
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *value = fRawColor16;
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return &fDevice;
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
55796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
560a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkRGB16_Blitter::blitH(int x, int y, int width) {
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(width > 0);
5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
56341e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
565402448d6818cab9d7b7633a0c18fcf574c915357mlee    fColorProc16(device, fSrcColor32, width, x, y);
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitAntiH(int x, int y,
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkAlpha* SK_RESTRICT antialias,
570a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                const int16_t* SK_RESTRICT runs) {
57141e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
572ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    srcExpanded = fExpandedRaw16;
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    scale = fScale;
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5759a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    // TODO: respect fDoDither
5769a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    for (;;) {
5779a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int count = runs[0];
5789a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkASSERT(count >= 0);
5799a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (count <= 0) {
5809a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            return;
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5829a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        runs += count;
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5849a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        unsigned aa = antialias[0];
5859a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        antialias += count;
5869a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        if (aa) {
5879a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
588ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com            uint32_t src32 =  srcExpanded * scale5;
5899a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            scale5 = 32 - scale5;
5909a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            do {
5919a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
5929a74d313452f30629e2615eb8cbfe902433582c0reed@android.com                *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
5939a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            } while (--count != 0);
5949a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            continue;
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5969a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device += count;
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                  U16CPU srcColor) {
6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_BlendBW
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS                  , unsigned dst_scale, U16CPU src_color
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, dst_scale, src_color)
61541e010cb901c0da9066c4df562030808c9ccd7f8reed#define SK_BLITBWMASK_GETADDR               writable_addr16
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
619333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.comvoid SkRGB16_Blitter::blitMask(const SkMask& mask,
620333d6cb2448d0febcbeb7c8c7310c0ff2d1a6104tomhudson@google.com                               const SkIRect& clip) {
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
6229a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62641e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT device = fDevice.writable_addr16(clip.fLeft, clip.fTop);
6277989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com    const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = clip.width();
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int height = clip.height();
630e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t      deviceRB = fDevice.rowBytes() - (width << 1);
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    maskRB = mask.fRowBytes - width;
632ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t    color32 = fExpandedRaw16;
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6349a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    unsigned scale256 = fScale;
6359a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    do {
6369a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        int w = width;
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
6389a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            unsigned aa = *alpha++;
6399a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
6409a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            uint32_t src32 = color32 * scale;
6419a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
6429a74d313452f30629e2615eb8cbfe902433582c0reed@android.com            *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
6439a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        } while (--w != 0);
6449a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
6459a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        alpha += maskRB;
6469a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    } while (--height != 0);
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
65041e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
651e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t    deviceRB = fDevice.rowBytes();
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
653ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    // TODO: respect fDoDither
654ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
655ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    uint32_t src32 =  fExpandedRaw16 * scale5;
656ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    scale5 = 32 - scale5;
657dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang#if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
658dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang    SkRGB16BlitterBlitV_neon(device, height, deviceRB, scale5, src32);
659dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang#else
660ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    do {
661ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
662ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        *device = SkCompact_rgb_16((src32 + dst32) >> 5);
663ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
664ea16cfa037bca933f6930a487b42f3c0faab9fe4reed@android.com    } while (--height != 0);
665dc77b3591841bf1e70ed45455490d688e5d4e6f9yang.zhang#endif
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
67041e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
671e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t    deviceRB = fDevice.rowBytes();
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6739a74d313452f30629e2615eb8cbfe902433582c0reed@android.com    while (--height >= 0) {
674402448d6818cab9d7b7633a0c18fcf574c915357mlee        fColorProc16(device, fSrcColor32, width, x, y);
6759a74d313452f30629e2615eb8cbfe902433582c0reed@android.com        device = (uint16_t*)((char*)device + deviceRB);
6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
68141e010cb901c0da9066c4df562030808c9ccd7f8reedSkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkPixmap& device,
68287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                               const SkPaint& paint,
68387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                               SkShader::Context* shaderContext)
68441e010cb901c0da9066c4df562030808c9ccd7f8reed    : INHERITED(device, paint, shaderContext)
68541e010cb901c0da9066c4df562030808c9ccd7f8reed{
68696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(paint.getXfermode() == nullptr);
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // compute SkBlitRow::Procs
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned flags = 0;
692fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
6935119bdb952025a30f115b9c6a187173956e55097reed@android.com    uint32_t shaderFlags = fShaderFlags;
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // shaders take care of global alpha, so we never set it in SkBlitRow
6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= SkBlitRow::kSrcPixelAlpha_Flag;
697c2050e3a3ecfb8738b36e2add15c526e8e0f21fecommit-bot@chromium.org    }
6984e5a758f3832594cf1828d367496b5a80bcab8eereed    if (paint.isDither()) {
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= SkBlitRow::kDither_Flag;
7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // used when we know our global alpha is 0xFF
702a7f11918d92621507f35b228a290f05dcaf0f4b6reed    fOpaqueProc = SkBlitRow::Factory16(flags);
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // used when we know our global alpha is < 0xFF
704a7f11918d92621507f35b228a290f05dcaf0f4b6reed    fAlphaProc  = SkBlitRow::Factory16(flags | SkBlitRow::kGlobalAlpha_Flag);
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fBuffer);
7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
71487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fShaderContext->shadeSpan(x, y, fBuffer, width);
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // shaders take care of global alpha, so we pass 0xFF (should be ignored)
71641e010cb901c0da9066c4df562030808c9ccd7f8reed    fOpaqueProc(fDevice.writable_addr16(x, y), fBuffer, width, 0xFF, x, y);
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7195119bdb952025a30f115b9c6a187173956e55097reed@android.comvoid SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
72087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context* shaderContext = fShaderContext;
721a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkBlitRow::Proc16  proc = fOpaqueProc;
72287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkPMColor*         buffer = fBuffer;
72341e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t*          dst = fDevice.writable_addr16(x, y);
72487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    size_t             dstRB = fDevice.rowBytes();
7255119bdb952025a30f115b9c6a187173956e55097reed@android.com
7263c9b2a4a0e4f57db23640e85959ee78b86634628reed@android.com    if (fShaderFlags & SkShader::kConstInY32_Flag) {
72787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan(x, y, buffer, width);
7285119bdb952025a30f115b9c6a187173956e55097reed@android.com        do {
7295119bdb952025a30f115b9c6a187173956e55097reed@android.com            proc(dst, buffer, width, 0xFF, x, y);
7305119bdb952025a30f115b9c6a187173956e55097reed@android.com            y += 1;
7315119bdb952025a30f115b9c6a187173956e55097reed@android.com            dst = (uint16_t*)((char*)dst + dstRB);
7325119bdb952025a30f115b9c6a187173956e55097reed@android.com        } while (--height);
7335119bdb952025a30f115b9c6a187173956e55097reed@android.com    } else {
7345119bdb952025a30f115b9c6a187173956e55097reed@android.com        do {
73587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            shaderContext->shadeSpan(x, y, buffer, width);
7365119bdb952025a30f115b9c6a187173956e55097reed@android.com            proc(dst, buffer, width, 0xFF, x, y);
7375119bdb952025a30f115b9c6a187173956e55097reed@android.com            y += 1;
7385119bdb952025a30f115b9c6a187173956e55097reed@android.com            dst = (uint16_t*)((char*)dst + dstRB);
7395119bdb952025a30f115b9c6a187173956e55097reed@android.com        } while (--height);
7405119bdb952025a30f115b9c6a187173956e55097reed@android.com    }
7415119bdb952025a30f115b9c6a187173956e55097reed@android.com}
7425119bdb952025a30f115b9c6a187173956e55097reed@android.com
7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int count = 0;
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int n = *runs;
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (n == 0 || *aa == 0) {
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += n;
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        aa += n;
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count += n;
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_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;
76241e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT  device = fDevice.writable_addr16(x, y);
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = *runs;
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int aa = *antialias;
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (0 == aa) {
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
78187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan(x, y, span, nonZeroCount);
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor* localSpan = span;
7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
785a7f11918d92621507f35b228a290f05dcaf0f4b6reed            SkBlitRow::Proc16 proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc(device, localSpan, count, aa, x, y);
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            nonZeroCount -= count;
7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (nonZeroCount == 0) {
7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            localSpan += count;
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(nonZeroCount > 0);
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count = *runs;
7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count > 0);
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa = *antialias;
8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
80841e010cb901c0da9066c4df562030808c9ccd7f8reed                                const SkPixmap& device, const SkPaint& paint,
80987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                SkShader::Context* shaderContext)
81041e010cb901c0da9066c4df562030808c9ccd7f8reed    : INHERITED(device, paint, shaderContext)
81141e010cb901c0da9066c4df562030808c9ccd7f8reed{
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode = paint.getXfermode();
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fXfermode);
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode->ref();
8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = device.width();
8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fAAExpand = (uint8_t*)(fBuffer + width);
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode->unref();
8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fBuffer);
8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
82941e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t*   device = fDevice.writable_addr16(x, y);
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor*  span = fBuffer;
8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
83287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fShaderContext->shadeSpan(x, y, span, width);
83396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fXfermode->xfer16(device, span, width, nullptr);
8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkAlpha* SK_RESTRICT antialias,
838a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                                const int16_t* SK_RESTRICT runs) {
83987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkShader::Context*     shaderContext = fShaderContext;
84087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkXfermode*            mode = fXfermode;
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT span = fBuffer;
84287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    uint8_t* SK_RESTRICT   aaExpand = fAAExpand;
84341e010cb901c0da9066c4df562030808c9ccd7f8reed    uint16_t* SK_RESTRICT  device = fDevice.writable_addr16(x, y);
8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = *runs;
8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int aa = *antialias;
8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (0 == aa) {
8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int nonZeroCount = count + count_nonzero_span(runs + count,
8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                      antialias + count);
8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
86387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan(x, y, span, nonZeroCount);
8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x += nonZeroCount;
8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor* localSpan = span;
8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 0xFF) {
86996fcdcc219d2a0d3579719b84b28bede76efba64halcanary                mode->xfer16(device, localSpan, count, nullptr);
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkASSERT(aa);
8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memset(aaExpand, aa, count);
8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                mode->xfer16(device, localSpan, count, aaExpand);
8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            nonZeroCount -= count;
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (nonZeroCount == 0) {
8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            localSpan += count;
8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(nonZeroCount > 0);
8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count = *runs;
8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count > 0);
8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa = *antialias;
8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
888fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8911fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com///////////////////////////////////////////////////////////////////////////////
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
89341e010cb901c0da9066c4df562030808c9ccd7f8reedSkBlitter* SkBlitter_ChooseD565(const SkPixmap& device, const SkPaint& paint,
89487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        SkShader::Context* shaderContext,
895a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org        SkTBlitterAllocator* allocator) {
89696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(allocator != nullptr);
897a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org
8981fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkBlitter* blitter;
8991fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkShader* shader = paint.getShader();
9001fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    SkXfermode* mode = paint.getXfermode();
9011fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
9021fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    // we require a shader if there is an xfermode, handled by our caller
90396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(nullptr == mode || shader);
9041fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com
9051fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    if (shader) {
90696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        SkASSERT(shaderContext != nullptr);
9071fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        if (mode) {
90887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint,
90987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                                                          shaderContext);
9101fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else {
91187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint, shaderContext);
9121fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        }
9131fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    } else {
9141fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        // no shader, no xfermode, (and we always ignore colorfilter)
9151fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        SkColor color = paint.getColor();
9161fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        if (0 == SkColorGetA(color)) {
917a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkNullBlitter>();
918867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#ifdef USE_BLACK_BLITTER
9191fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else if (SK_ColorBLACK == color) {
920a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Black_Blitter>(device, paint);
921867ee807cc95c77aff830e9e6c1988bfbe604405reed@android.com#endif
9221fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else if (0xFF == SkColorGetA(color)) {
923a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Opaque_Blitter>(device, paint);
9241fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        } else {
925a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkRGB16_Blitter>(device, paint);
9261fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        }
9271fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    }
928fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9291fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com    return blitter;
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
931