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 "SkCoreBlitters.h"
9a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
12d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed#include "SkXfermodePriv.h"
1358af9a64701540c7f8083bc22a42d0bae3a5583creed@google.com#include "SkBlitMask.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com///////////////////////////////////////////////////////////////////////////////
16f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com
1741e010cb901c0da9066c4df562030808c9ccd7f8reedstatic void SkARGB32_Blit32(const SkPixmap& device, const SkMask& mask,
18fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                            const SkIRect& clip, SkPMColor srcColor) {
19fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    U8CPU alpha = SkGetPackedA32(srcColor);
20fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32;
21fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (alpha != 255) {
22fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        flags |= SkBlitRow::kGlobalAlpha_Flag32;
23fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
24fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
25f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
26f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    int x = clip.fLeft;
27f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    int y = clip.fTop;
28f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    int width = clip.width();
29f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    int height = clip.height();
3082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3141e010cb901c0da9066c4df562030808c9ccd7f8reed    SkPMColor* dstRow = device.writable_addr32(x, y);
327989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com    const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr8(x, y));
33f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
34f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    do {
35fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        proc(dstRow, srcRow, width, alpha);
36f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
37f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
38f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    } while (--height != 0);
39f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com}
40f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
41f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com//////////////////////////////////////////////////////////////////////////////////////
42f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
4341e010cb901c0da9066c4df562030808c9ccd7f8reedSkARGB32_Blitter::SkARGB32_Blitter(const SkPixmap& device, const SkPaint& paint)
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(device) {
45ee467ee79d449ebe6ae7f7946e613cc70a479c69reed@google.com    SkColor color = paint.getColor();
46ee467ee79d449ebe6ae7f7946e613cc70a479c69reed@google.com    fColor = color;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcA = SkColorGetA(color);
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned scale = SkAlpha255To256(fSrcA);
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcR = SkAlphaMul(SkColorGetR(color), scale);
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcG = SkAlphaMul(SkColorGetG(color), scale);
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcB = SkAlphaMul(SkColorGetB(color), scale);
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB);
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5741e010cb901c0da9066c4df562030808c9ccd7f8reedconst SkPixmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (255 == fSrcA) {
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *value = fPMColor;
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return &fDevice;
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65d7dc76f7e99309cbd09a5420c22e55b951067debbungeman#if defined _WIN32  // disable warning : local variable used without having been initialized
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push )
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4701 )
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Blitter::blitH(int x, int y, int width) {
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7341e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t* device = fDevice.writable_addr32(x, y);
7495cc012ccaea20f372893ae277ea0a8a6339d094mtklein    SkBlitRow::Color32(device, device, width, fPMColor);
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                 const int16_t runs[]) {
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fSrcA == 0) {
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t    color = fPMColor;
8441e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t*   device = fDevice.writable_addr32(x, y);
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = runs[0];
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count >= 0);
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned aa = antialias[0];
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (aa) {
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if ((opaqueMask & aa) == 255) {
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sk_memset32(device, color, count);
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
98c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa));
9995cc012ccaea20f372893ae277ea0a8a6339d094mtklein                SkBlitRow::Color32(device, device, count, sc);
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += count;
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        antialias += count;
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device += count;
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1086983f66d8b3a489133b751e2cef03e72a03bfeaereedvoid SkARGB32_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
10941e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t* device = fDevice.writable_addr32(x, y);
11041e010cb901c0da9066c4df562030808c9ccd7f8reed    SkDEBUGCODE((void)fDevice.writable_addr32(x + 1, y);)
11195cc012ccaea20f372893ae277ea0a8a6339d094mtklein
1126983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[0] = SkBlendARGB32(fPMColor, device[0], a0);
1136983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[1] = SkBlendARGB32(fPMColor, device[1], a1);
1146983f66d8b3a489133b751e2cef03e72a03bfeaereed}
1156983f66d8b3a489133b751e2cef03e72a03bfeaereed
1166983f66d8b3a489133b751e2cef03e72a03bfeaereedvoid SkARGB32_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
11741e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t* device = fDevice.writable_addr32(x, y);
11841e010cb901c0da9066c4df562030808c9ccd7f8reed    SkDEBUGCODE((void)fDevice.writable_addr32(x, y + 1);)
11995cc012ccaea20f372893ae277ea0a8a6339d094mtklein
1206983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[0] = SkBlendARGB32(fPMColor, device[0], a0);
1216983f66d8b3a489133b751e2cef03e72a03bfeaereed    device = (uint32_t*)((char*)device + fDevice.rowBytes());
1226983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[0] = SkBlendARGB32(fPMColor, device[0], a1);
1236983f66d8b3a489133b751e2cef03e72a03bfeaereed}
1246983f66d8b3a489133b751e2cef03e72a03bfeaereed
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define solid_8_pixels(mask, dst, color)    \
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                    \
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x80) dst[0] = color;    \
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x40) dst[1] = color;    \
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x20) dst[2] = color;    \
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x10) dst[3] = color;    \
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x08) dst[4] = color;    \
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x04) dst[5] = color;    \
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x02) dst[6] = color;    \
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x01) dst[7] = color;    \
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkARGB32_BlitBW
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS                  , SkPMColor color
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
14241e010cb901c0da9066c4df562030808c9ccd7f8reed#define SK_BLITBWMASK_GETADDR               writable_addr32
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint32_t
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define blend_8_pixels(mask, dst, sc, dst_scale)                            \
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                                                    \
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); }  \
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); }  \
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); }  \
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); }  \
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); }  \
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); }  \
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); }  \
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); }  \
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkARGB32_BlendBW
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS                  , uint32_t sc, unsigned dst_scale
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sc, dst_scale)
16141e010cb901c0da9066c4df562030808c9ccd7f8reed#define SK_BLITBWMASK_GETADDR               writable_addr32
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint32_t
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fSrcA != 0xFF);
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fSrcA == 0) {
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
173edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com    if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
174edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com        return;
175edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com    }
176edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com
1773be72b0413ebc7cb1133e704169e3d543830d8e7herb    switch (mask.fFormat) {
1783be72b0413ebc7cb1133e704169e3d543830d8e7herb        case SkMask::kBW_Format:
1793be72b0413ebc7cb1133e704169e3d543830d8e7herb            SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
1803be72b0413ebc7cb1133e704169e3d543830d8e7herb            break;
1813be72b0413ebc7cb1133e704169e3d543830d8e7herb        case SkMask::kARGB32_Format:
1823be72b0413ebc7cb1133e704169e3d543830d8e7herb            SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
1833be72b0413ebc7cb1133e704169e3d543830d8e7herb            break;
1843be72b0413ebc7cb1133e704169e3d543830d8e7herb        default:
185b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner            SK_ABORT("Mask format not handled.");
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       const SkIRect& clip) {
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
193edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com    if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
194edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com        return;
195edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com    }
196fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1973be72b0413ebc7cb1133e704169e3d543830d8e7herb    switch (mask.fFormat) {
1983be72b0413ebc7cb1133e704169e3d543830d8e7herb        case SkMask::kBW_Format:
1993be72b0413ebc7cb1133e704169e3d543830d8e7herb            SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
2003be72b0413ebc7cb1133e704169e3d543830d8e7herb            break;
2013be72b0413ebc7cb1133e704169e3d543830d8e7herb        case SkMask::kARGB32_Format:
2023be72b0413ebc7cb1133e704169e3d543830d8e7herb            SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
2033be72b0413ebc7cb1133e704169e3d543830d8e7herb            break;
2043be72b0413ebc7cb1133e704169e3d543830d8e7herb        default:
205b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner            SK_ABORT("Mask format not handled.");
206fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2096983f66d8b3a489133b751e2cef03e72a03bfeaereedvoid SkARGB32_Opaque_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
21041e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t* device = fDevice.writable_addr32(x, y);
21141e010cb901c0da9066c4df562030808c9ccd7f8reed    SkDEBUGCODE((void)fDevice.writable_addr32(x + 1, y);)
2126983f66d8b3a489133b751e2cef03e72a03bfeaereed
2136983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[0] = SkFastFourByteInterp(fPMColor, device[0], a0);
2146983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[1] = SkFastFourByteInterp(fPMColor, device[1], a1);
2156983f66d8b3a489133b751e2cef03e72a03bfeaereed}
2166983f66d8b3a489133b751e2cef03e72a03bfeaereed
2176983f66d8b3a489133b751e2cef03e72a03bfeaereedvoid SkARGB32_Opaque_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
21841e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t* device = fDevice.writable_addr32(x, y);
21941e010cb901c0da9066c4df562030808c9ccd7f8reed    SkDEBUGCODE((void)fDevice.writable_addr32(x, y + 1);)
2206983f66d8b3a489133b751e2cef03e72a03bfeaereed
2216983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[0] = SkFastFourByteInterp(fPMColor, device[0], a0);
2226983f66d8b3a489133b751e2cef03e72a03bfeaereed    device = (uint32_t*)((char*)device + fDevice.rowBytes());
2236983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[0] = SkFastFourByteInterp(fPMColor, device[0], a1);
2246983f66d8b3a489133b751e2cef03e72a03bfeaereed}
2256983f66d8b3a489133b751e2cef03e72a03bfeaereed
22667cdbf5c63cfd77523d2a3070a44a200fabf0739reed@google.com///////////////////////////////////////////////////////////////////////////////
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (alpha == 0 || fSrcA == 0) {
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23341e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t* device = fDevice.writable_addr32(x, y);
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t  color = fPMColor;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (alpha != 255) {
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24040254c2c2dc28a34f96294d5a1ad94a99b0be8a6lsalzman    unsigned dst_scale = SkAlpha255To256(255 - SkGetPackedA32(color));
241e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com    size_t rowBytes = fDevice.rowBytes();
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (--height >= 0) {
24367cdbf5c63cfd77523d2a3070a44a200fabf0739reed@google.com        device[0] = color + SkAlphaMulQ(device[0], dst_scale);
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device = (uint32_t*)((char*)device + rowBytes);
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fSrcA == 0) {
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25541e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t*   device = fDevice.writable_addr32(x, y);
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t    color = fPMColor;
257c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    size_t      rowBytes = fDevice.rowBytes();
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
259edeccc58606e0421a1ae275e391ee4347c6f52f6mtklein    while (--height >= 0) {
26095cc012ccaea20f372893ae277ea0a8a6339d094mtklein        SkBlitRow::Color32(device, device, width, color);
261edeccc58606e0421a1ae275e391ee4347c6f52f6mtklein        device = (uint32_t*)((char*)device + rowBytes);
26257e080c1eb34253a3fc3829c2b03bb3ee63e006ftomhudson@google.com    }
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
265d7dc76f7e99309cbd09a5420c22e55b951067debbungeman#if defined _WIN32
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop )
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       const int16_t runs[]) {
27341e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t*   device = fDevice.writable_addr32(x, y);
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor   black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = runs[0];
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count >= 0);
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned aa = antialias[0];
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (aa) {
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 255) {
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sk_memset32(device, black, count);
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkPMColor src = aa << SK_A32_SHIFT;
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned dst_scale = 256 - aa;
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int n = count;
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                do {
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    --n;
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    device[n] = src + SkAlphaMulQ(device[n], dst_scale);
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } while (n > 0);
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += count;
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        antialias += count;
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device += count;
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3026983f66d8b3a489133b751e2cef03e72a03bfeaereedvoid SkARGB32_Black_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
30341e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t* device = fDevice.writable_addr32(x, y);
30441e010cb901c0da9066c4df562030808c9ccd7f8reed    SkDEBUGCODE((void)fDevice.writable_addr32(x + 1, y);)
3056983f66d8b3a489133b751e2cef03e72a03bfeaereed
3066983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[0] = (a0 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a0);
3076983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[1] = (a1 << SK_A32_SHIFT) + SkAlphaMulQ(device[1], 256 - a1);
3086983f66d8b3a489133b751e2cef03e72a03bfeaereed}
3096983f66d8b3a489133b751e2cef03e72a03bfeaereed
3106983f66d8b3a489133b751e2cef03e72a03bfeaereedvoid SkARGB32_Black_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
31141e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t* device = fDevice.writable_addr32(x, y);
31241e010cb901c0da9066c4df562030808c9ccd7f8reed    SkDEBUGCODE((void)fDevice.writable_addr32(x, y + 1);)
31395cc012ccaea20f372893ae277ea0a8a6339d094mtklein
3146983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[0] = (a0 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a0);
3156983f66d8b3a489133b751e2cef03e72a03bfeaereed    device = (uint32_t*)((char*)device + fDevice.rowBytes());
3166983f66d8b3a489133b751e2cef03e72a03bfeaereed    device[0] = (a1 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a1);
3176983f66d8b3a489133b751e2cef03e72a03bfeaereed}
3186983f66d8b3a489133b751e2cef03e72a03bfeaereed
3191750bf17635e788198200f971d9cb66f67399363reed@google.com///////////////////////////////////////////////////////////////////////////////
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
32113201e74f43b9c5fa173339eb36de515370e6973reed@google.com// Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode,
32213201e74f43b9c5fa173339eb36de515370e6973reed@google.com// instead of kSrcOver_Mode
32313201e74f43b9c5fa173339eb36de515370e6973reed@google.comstatic void blend_srcmode(SkPMColor* SK_RESTRICT device,
32413201e74f43b9c5fa173339eb36de515370e6973reed@google.com                          const SkPMColor* SK_RESTRICT span,
32513201e74f43b9c5fa173339eb36de515370e6973reed@google.com                          int count, U8CPU aa) {
32613201e74f43b9c5fa173339eb36de515370e6973reed@google.com    int aa256 = SkAlpha255To256(aa);
32713201e74f43b9c5fa173339eb36de515370e6973reed@google.com    for (int i = 0; i < count; ++i) {
32813201e74f43b9c5fa173339eb36de515370e6973reed@google.com        device[i] = SkFourByteInterp256(span[i], device[i], aa256);
32913201e74f43b9c5fa173339eb36de515370e6973reed@google.com    }
33013201e74f43b9c5fa173339eb36de515370e6973reed@google.com}
33113201e74f43b9c5fa173339eb36de515370e6973reed@google.com
33241e010cb901c0da9066c4df562030808c9ccd7f8reedSkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkPixmap& device,
3334aed13889bd9085337e0d4c20df28686687b833bFlorin Malita        const SkPaint& paint, SkShaderBase::Context* shaderContext)
33487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    : INHERITED(device, paint, shaderContext)
33587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org{
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
338374772bd61951f01bf84fe17bf53d8867681c9aereed    fXfermode = SkXfermode::Peek(paint.getBlendMode());
339c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
340c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    int flags = 0;
3414aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    if (!(shaderContext->getFlags() & SkShaderBase::kOpaqueAlpha_Flag)) {
342c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
343c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    }
344c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    // we call this on the output from the shader
345c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    fProc32 = SkBlitRow::Factory32(flags);
346c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    // we call this on the output from the shader + alpha from the aa buffer
347c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
34813201e74f43b9c5fa173339eb36de515370e6973reed@google.com
34913201e74f43b9c5fa173339eb36de515370e6973reed@google.com    fShadeDirectlyIntoDevice = false;
35096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (fXfermode == nullptr) {
3514aed13889bd9085337e0d4c20df28686687b833bFlorin Malita        if (shaderContext->getFlags() & SkShaderBase::kOpaqueAlpha_Flag) {
35213201e74f43b9c5fa173339eb36de515370e6973reed@google.com            fShadeDirectlyIntoDevice = true;
35313201e74f43b9c5fa173339eb36de515370e6973reed@google.com        }
35413201e74f43b9c5fa173339eb36de515370e6973reed@google.com    } else {
355cde9031a5a347a762a3946d216f96542d9cfcef4Mike Reed        if (SkBlendMode::kSrc == paint.getBlendMode()) {
356cde9031a5a347a762a3946d216f96542d9cfcef4Mike Reed            fShadeDirectlyIntoDevice = true;
357cde9031a5a347a762a3946d216f96542d9cfcef4Mike Reed            fProc32Blend = blend_srcmode;
35813201e74f43b9c5fa173339eb36de515370e6973reed@google.com        }
35913201e74f43b9c5fa173339eb36de515370e6973reed@google.com    }
36013201e74f43b9c5fa173339eb36de515370e6973reed@google.com
3614aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    fConstInY = SkToBool(shaderContext->getFlags() & SkShaderBase::kConstInY32_Flag);
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fBuffer);
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
37141e010cb901c0da9066c4df562030808c9ccd7f8reed    uint32_t* device = fDevice.writable_addr32(x, y);
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
37313201e74f43b9c5fa173339eb36de515370e6973reed@google.com    if (fShadeDirectlyIntoDevice) {
37487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        fShaderContext->shadeSpan(x, y, device, width);
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor*  span = fBuffer;
37787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        fShaderContext->shadeSpan(x, y, span, width);
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fXfermode) {
37996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            fXfermode->xfer32(device, span, width, nullptr);
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
381c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            fProc32(device, span, width, 255);
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3863bafe74a29c37761082980ed4ee9b831256bd27ereed@google.comvoid SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
3873bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com    SkASSERT(x >= 0 && y >= 0 &&
3883bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com             x + width <= fDevice.width() && y + height <= fDevice.height());
389f57c01bdcfdf1c923b9a473974bfe6f8c66eca3eskia.committer@gmail.com
3904aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    uint32_t*  device = fDevice.writable_addr32(x, y);
3914aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    size_t     deviceRB = fDevice.rowBytes();
3924aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    auto*      shaderContext = fShaderContext;
3934aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    SkPMColor* span = fBuffer;
39413201e74f43b9c5fa173339eb36de515370e6973reed@google.com
39513201e74f43b9c5fa173339eb36de515370e6973reed@google.com    if (fConstInY) {
39613201e74f43b9c5fa173339eb36de515370e6973reed@google.com        if (fShadeDirectlyIntoDevice) {
39713201e74f43b9c5fa173339eb36de515370e6973reed@google.com            // shade the first row directly into the device
39887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            shaderContext->shadeSpan(x, y, device, width);
39913201e74f43b9c5fa173339eb36de515370e6973reed@google.com            span = device;
40013201e74f43b9c5fa173339eb36de515370e6973reed@google.com            while (--height > 0) {
40113201e74f43b9c5fa173339eb36de515370e6973reed@google.com                device = (uint32_t*)((char*)device + deviceRB);
40213201e74f43b9c5fa173339eb36de515370e6973reed@google.com                memcpy(device, span, width << 2);
40313201e74f43b9c5fa173339eb36de515370e6973reed@google.com            }
40413201e74f43b9c5fa173339eb36de515370e6973reed@google.com        } else {
40587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            shaderContext->shadeSpan(x, y, span, width);
40613201e74f43b9c5fa173339eb36de515370e6973reed@google.com            SkXfermode* xfer = fXfermode;
40713201e74f43b9c5fa173339eb36de515370e6973reed@google.com            if (xfer) {
40813201e74f43b9c5fa173339eb36de515370e6973reed@google.com                do {
40996fcdcc219d2a0d3579719b84b28bede76efba64halcanary                    xfer->xfer32(device, span, width, nullptr);
41013201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    y += 1;
41113201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
41213201e74f43b9c5fa173339eb36de515370e6973reed@google.com                } while (--height > 0);
41313201e74f43b9c5fa173339eb36de515370e6973reed@google.com            } else {
41413201e74f43b9c5fa173339eb36de515370e6973reed@google.com                SkBlitRow::Proc32 proc = fProc32;
41513201e74f43b9c5fa173339eb36de515370e6973reed@google.com                do {
41613201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    proc(device, span, width, 255);
41713201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    y += 1;
41813201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
41913201e74f43b9c5fa173339eb36de515370e6973reed@google.com                } while (--height > 0);
42013201e74f43b9c5fa173339eb36de515370e6973reed@google.com            }
42113201e74f43b9c5fa173339eb36de515370e6973reed@google.com        }
42213201e74f43b9c5fa173339eb36de515370e6973reed@google.com        return;
42313201e74f43b9c5fa173339eb36de515370e6973reed@google.com    }
4243bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com
42513201e74f43b9c5fa173339eb36de515370e6973reed@google.com    if (fShadeDirectlyIntoDevice) {
4268aeec29bec673e7a3585625dc48e00e51897d474Mike Reed        do {
4278aeec29bec673e7a3585625dc48e00e51897d474Mike Reed            shaderContext->shadeSpan(x, y, device, width);
4288aeec29bec673e7a3585625dc48e00e51897d474Mike Reed            y += 1;
4298aeec29bec673e7a3585625dc48e00e51897d474Mike Reed            device = (uint32_t*)((char*)device + deviceRB);
4308aeec29bec673e7a3585625dc48e00e51897d474Mike Reed        } while (--height > 0);
4313bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com    } else {
4323bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com        SkXfermode* xfer = fXfermode;
4333bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com        if (xfer) {
4343bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com            do {
43587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan(x, y, span, width);
43696fcdcc219d2a0d3579719b84b28bede76efba64halcanary                xfer->xfer32(device, span, width, nullptr);
4373bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com                y += 1;
4383bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com                device = (uint32_t*)((char*)device + deviceRB);
4393bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com            } while (--height > 0);
4403bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com        } else {
4413bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com            SkBlitRow::Proc32 proc = fProc32;
4423bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com            do {
44387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan(x, y, span, width);
4443bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com                proc(device, span, width, 255);
4453bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com                y += 1;
4463bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com                device = (uint32_t*)((char*)device + deviceRB);
4473bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com            } while (--height > 0);
4483bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com        }
4493bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com    }
4503bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com}
4513bafe74a29c37761082980ed4ee9b831256bd27ereed@google.com
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                        const int16_t runs[]) {
4544aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    SkPMColor* span = fBuffer;
4554aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    uint32_t*  device = fDevice.writable_addr32(x, y);
4564aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    auto*      shaderContext = fShaderContext;
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45813201e74f43b9c5fa173339eb36de515370e6973reed@google.com    if (fXfermode && !fShadeDirectlyIntoDevice) {
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkXfermode* xfer = fXfermode;
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0)
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = *antialias;
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa) {
46787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan(x, y, span, count);
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (aa == 255) {
46996fcdcc219d2a0d3579719b84b28bede76efba64halcanary                    xfer->xfer32(device, span, count, nullptr);
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } else {
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    // count is almost always 1
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    for (int i = count - 1; i >= 0; --i) {
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        xfer->xfer32(&device[i], &span[i], 1, antialias);
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
48182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
48213201e74f43b9c5fa173339eb36de515370e6973reed@google.com    } else if (fShadeDirectlyIntoDevice ||
4834aed13889bd9085337e0d4c20df28686687b833bFlorin Malita               (shaderContext->getFlags() & SkShaderBase::kOpaqueAlpha_Flag)) {
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = *antialias;
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa) {
491c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                if (aa == 255) {
492c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                    // cool, have the shader draw right into the device
49387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    shaderContext->shadeSpan(x, y, device, count);
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } else {
49587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    shaderContext->shadeSpan(x, y, span, count);
496c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                    fProc32Blend(device, span, count, aa);
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
50382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
50413201e74f43b9c5fa173339eb36de515370e6973reed@google.com    } else {
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = *antialias;
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa) {
51287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan(x, y, span, count);
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (aa == 255) {
514c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                    fProc32(device, span, count, 255);
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } else {
516c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                    fProc32Blend(device, span, count, aa);
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
52382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5261750bf17635e788198200f971d9cb66f67399363reed@google.com
5271750bf17635e788198200f971d9cb66f67399363reed@google.comvoid SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
5281750bf17635e788198200f971d9cb66f67399363reed@google.com    // we only handle kA8 with an xfermode
5291750bf17635e788198200f971d9cb66f67399363reed@google.com    if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) {
5301750bf17635e788198200f971d9cb66f67399363reed@google.com        this->INHERITED::blitMask(mask, clip);
5311750bf17635e788198200f971d9cb66f67399363reed@google.com        return;
5321750bf17635e788198200f971d9cb66f67399363reed@google.com    }
5331750bf17635e788198200f971d9cb66f67399363reed@google.com
5341750bf17635e788198200f971d9cb66f67399363reed@google.com    SkASSERT(mask.fBounds.contains(clip));
5351750bf17635e788198200f971d9cb66f67399363reed@google.com
5364aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    auto* shaderContext = fShaderContext;
53796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkBlitMask::RowProc proc = nullptr;
5381750bf17635e788198200f971d9cb66f67399363reed@google.com    if (!fXfermode) {
5391750bf17635e788198200f971d9cb66f67399363reed@google.com        unsigned flags = 0;
5404aed13889bd9085337e0d4c20df28686687b833bFlorin Malita        if (shaderContext->getFlags() & SkShaderBase::kOpaqueAlpha_Flag) {
5411750bf17635e788198200f971d9cb66f67399363reed@google.com            flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
5421750bf17635e788198200f971d9cb66f67399363reed@google.com        }
543cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        proc = SkBlitMask::RowFactory(kN32_SkColorType, mask.fFormat,
5441750bf17635e788198200f971d9cb66f67399363reed@google.com                                      (SkBlitMask::RowFlags)flags);
54596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == proc) {
5461750bf17635e788198200f971d9cb66f67399363reed@google.com            this->INHERITED::blitMask(mask, clip);
5471750bf17635e788198200f971d9cb66f67399363reed@google.com            return;
5481750bf17635e788198200f971d9cb66f67399363reed@google.com        }
5491750bf17635e788198200f971d9cb66f67399363reed@google.com    }
5501750bf17635e788198200f971d9cb66f67399363reed@google.com
5511750bf17635e788198200f971d9cb66f67399363reed@google.com    const int x = clip.fLeft;
5521750bf17635e788198200f971d9cb66f67399363reed@google.com    const int width = clip.width();
5531750bf17635e788198200f971d9cb66f67399363reed@google.com    int y = clip.fTop;
5541750bf17635e788198200f971d9cb66f67399363reed@google.com    int height = clip.height();
5551750bf17635e788198200f971d9cb66f67399363reed@google.com
55641e010cb901c0da9066c4df562030808c9ccd7f8reed    char* dstRow = (char*)fDevice.writable_addr32(x, y);
5571750bf17635e788198200f971d9cb66f67399363reed@google.com    const size_t dstRB = fDevice.rowBytes();
5581750bf17635e788198200f971d9cb66f67399363reed@google.com    const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
5591750bf17635e788198200f971d9cb66f67399363reed@google.com    const size_t maskRB = mask.fRowBytes;
5601750bf17635e788198200f971d9cb66f67399363reed@google.com
5611750bf17635e788198200f971d9cb66f67399363reed@google.com    SkPMColor* span = fBuffer;
5621750bf17635e788198200f971d9cb66f67399363reed@google.com
5631750bf17635e788198200f971d9cb66f67399363reed@google.com    if (fXfermode) {
5641750bf17635e788198200f971d9cb66f67399363reed@google.com        SkASSERT(SkMask::kA8_Format == mask.fFormat);
5651750bf17635e788198200f971d9cb66f67399363reed@google.com        SkXfermode* xfer = fXfermode;
5661750bf17635e788198200f971d9cb66f67399363reed@google.com        do {
56787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            shaderContext->shadeSpan(x, y, span, width);
568c7a784cc8cb1c1dfcd39a32b2170ffe547904e9fherb            xfer->xfer32(reinterpret_cast<SkPMColor*>(dstRow), span, width, maskRow);
5691750bf17635e788198200f971d9cb66f67399363reed@google.com            dstRow += dstRB;
5701750bf17635e788198200f971d9cb66f67399363reed@google.com            maskRow += maskRB;
5711750bf17635e788198200f971d9cb66f67399363reed@google.com            y += 1;
5721750bf17635e788198200f971d9cb66f67399363reed@google.com        } while (--height > 0);
5731750bf17635e788198200f971d9cb66f67399363reed@google.com    } else {
5741750bf17635e788198200f971d9cb66f67399363reed@google.com        do {
57587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            shaderContext->shadeSpan(x, y, span, width);
576c7a784cc8cb1c1dfcd39a32b2170ffe547904e9fherb            proc(reinterpret_cast<SkPMColor*>(dstRow), maskRow, span, width);
5771750bf17635e788198200f971d9cb66f67399363reed@google.com            dstRow += dstRB;
5781750bf17635e788198200f971d9cb66f67399363reed@google.com            maskRow += maskRB;
5791750bf17635e788198200f971d9cb66f67399363reed@google.com            y += 1;
5801750bf17635e788198200f971d9cb66f67399363reed@google.com        } while (--height > 0);
5811750bf17635e788198200f971d9cb66f67399363reed@google.com    }
5821750bf17635e788198200f971d9cb66f67399363reed@google.com}
5831750bf17635e788198200f971d9cb66f67399363reed@google.com
58413201e74f43b9c5fa173339eb36de515370e6973reed@google.comvoid SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
58513201e74f43b9c5fa173339eb36de515370e6973reed@google.com    SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
586886b25f14ce6a6974521f096eb5feac0b4327236skia.committer@gmail.com
5874aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    uint32_t* device = fDevice.writable_addr32(x, y);
5884aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    size_t    deviceRB = fDevice.rowBytes();
5894aed13889bd9085337e0d4c20df28686687b833bFlorin Malita    auto*     shaderContext = fShaderContext;
590886b25f14ce6a6974521f096eb5feac0b4327236skia.committer@gmail.com
59113201e74f43b9c5fa173339eb36de515370e6973reed@google.com    if (fConstInY) {
59213201e74f43b9c5fa173339eb36de515370e6973reed@google.com        SkPMColor c;
59387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderContext->shadeSpan(x, y, &c, 1);
59413201e74f43b9c5fa173339eb36de515370e6973reed@google.com
59513201e74f43b9c5fa173339eb36de515370e6973reed@google.com        if (fShadeDirectlyIntoDevice) {
59613201e74f43b9c5fa173339eb36de515370e6973reed@google.com            if (255 == alpha) {
59713201e74f43b9c5fa173339eb36de515370e6973reed@google.com                do {
59813201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    *device = c;
59913201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
60013201e74f43b9c5fa173339eb36de515370e6973reed@google.com                } while (--height > 0);
60113201e74f43b9c5fa173339eb36de515370e6973reed@google.com            } else {
60213201e74f43b9c5fa173339eb36de515370e6973reed@google.com                do {
60313201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    *device = SkFourByteInterp(c, *device, alpha);
60413201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
60513201e74f43b9c5fa173339eb36de515370e6973reed@google.com                } while (--height > 0);
60613201e74f43b9c5fa173339eb36de515370e6973reed@google.com            }
60713201e74f43b9c5fa173339eb36de515370e6973reed@google.com        } else {
60813201e74f43b9c5fa173339eb36de515370e6973reed@google.com            SkXfermode* xfer = fXfermode;
60913201e74f43b9c5fa173339eb36de515370e6973reed@google.com            if (xfer) {
61013201e74f43b9c5fa173339eb36de515370e6973reed@google.com                do {
61113201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    xfer->xfer32(device, &c, 1, &alpha);
61213201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
61313201e74f43b9c5fa173339eb36de515370e6973reed@google.com                } while (--height > 0);
61413201e74f43b9c5fa173339eb36de515370e6973reed@google.com            } else {
61553007a2b1724c15c170340658daac012f9d909bereed@google.com                SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
61613201e74f43b9c5fa173339eb36de515370e6973reed@google.com                do {
61713201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    proc(device, &c, 1, alpha);
61813201e74f43b9c5fa173339eb36de515370e6973reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
61913201e74f43b9c5fa173339eb36de515370e6973reed@google.com                } while (--height > 0);
62013201e74f43b9c5fa173339eb36de515370e6973reed@google.com            }
62113201e74f43b9c5fa173339eb36de515370e6973reed@google.com        }
62213201e74f43b9c5fa173339eb36de515370e6973reed@google.com        return;
62313201e74f43b9c5fa173339eb36de515370e6973reed@google.com    }
62413201e74f43b9c5fa173339eb36de515370e6973reed@google.com
62513201e74f43b9c5fa173339eb36de515370e6973reed@google.com    if (fShadeDirectlyIntoDevice) {
62613201e74f43b9c5fa173339eb36de515370e6973reed@google.com        if (255 == alpha) {
6278aeec29bec673e7a3585625dc48e00e51897d474Mike Reed            do {
6288aeec29bec673e7a3585625dc48e00e51897d474Mike Reed                shaderContext->shadeSpan(x, y, device, 1);
6298aeec29bec673e7a3585625dc48e00e51897d474Mike Reed                y += 1;
6308aeec29bec673e7a3585625dc48e00e51897d474Mike Reed                device = (uint32_t*)((char*)device + deviceRB);
6318aeec29bec673e7a3585625dc48e00e51897d474Mike Reed            } while (--height > 0);
6328aeec29bec673e7a3585625dc48e00e51897d474Mike Reed        } else {
6338aeec29bec673e7a3585625dc48e00e51897d474Mike Reed            do {
6348aeec29bec673e7a3585625dc48e00e51897d474Mike Reed                SkPMColor c;
6358aeec29bec673e7a3585625dc48e00e51897d474Mike Reed                shaderContext->shadeSpan(x, y, &c, 1);
6368aeec29bec673e7a3585625dc48e00e51897d474Mike Reed                *device = SkFourByteInterp(c, *device, alpha);
6378aeec29bec673e7a3585625dc48e00e51897d474Mike Reed                y += 1;
6388aeec29bec673e7a3585625dc48e00e51897d474Mike Reed                device = (uint32_t*)((char*)device + deviceRB);
6398aeec29bec673e7a3585625dc48e00e51897d474Mike Reed            } while (--height > 0);
64013201e74f43b9c5fa173339eb36de515370e6973reed@google.com        }
64113201e74f43b9c5fa173339eb36de515370e6973reed@google.com    } else {
64213201e74f43b9c5fa173339eb36de515370e6973reed@google.com        SkPMColor* span = fBuffer;
64313201e74f43b9c5fa173339eb36de515370e6973reed@google.com        SkXfermode* xfer = fXfermode;
64413201e74f43b9c5fa173339eb36de515370e6973reed@google.com        if (xfer) {
64513201e74f43b9c5fa173339eb36de515370e6973reed@google.com            do {
64687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan(x, y, span, 1);
64713201e74f43b9c5fa173339eb36de515370e6973reed@google.com                xfer->xfer32(device, span, 1, &alpha);
64813201e74f43b9c5fa173339eb36de515370e6973reed@google.com                y += 1;
64913201e74f43b9c5fa173339eb36de515370e6973reed@google.com                device = (uint32_t*)((char*)device + deviceRB);
65013201e74f43b9c5fa173339eb36de515370e6973reed@google.com            } while (--height > 0);
65113201e74f43b9c5fa173339eb36de515370e6973reed@google.com        } else {
65259d968fb29b39cc1f4eb0ac687007c74618c6c1creed@google.com            SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
65313201e74f43b9c5fa173339eb36de515370e6973reed@google.com            do {
65487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                shaderContext->shadeSpan(x, y, span, 1);
65559d968fb29b39cc1f4eb0ac687007c74618c6c1creed@google.com                proc(device, span, 1, alpha);
65613201e74f43b9c5fa173339eb36de515370e6973reed@google.com                y += 1;
65713201e74f43b9c5fa173339eb36de515370e6973reed@google.com                device = (uint32_t*)((char*)device + deviceRB);
65813201e74f43b9c5fa173339eb36de515370e6973reed@google.com            } while (--height > 0);
65913201e74f43b9c5fa173339eb36de515370e6973reed@google.com        }
66013201e74f43b9c5fa173339eb36de515370e6973reed@google.com    }
66113201e74f43b9c5fa173339eb36de515370e6973reed@google.com}
662