SkBlitter_RGB16.cpp revision 8a1c16ff38322f0210116fa7293eb8817c7e477e
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* libs/graphics/sgl/SkBlitter_RGB16.cpp
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com**
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Copyright 2006, The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com**
58a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Licensed under the Apache License, Version 2.0 (the "License");
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** you may not use this file except in compliance with the License.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** You may obtain a copy of the License at
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com**
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com**     http://www.apache.org/licenses/LICENSE-2.0
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com**
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Unless required by applicable law or agreed to in writing, software
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** distributed under the License is distributed on an "AS IS" BASIS,
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** See the License for the specific language governing permissions and
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** limitations under the License.
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitRow.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCoreBlitters.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDither.h"
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h"
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        int count) {
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // see if we need to write one short before we can cast to an 4byte ptr
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // (we do this subtract rather than (unsigned)dst so we don't get warnings
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        //  on 64bit machines)
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (((char*)dst - (char*)0) & 2) {
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *dst++ = value;
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count -= 1;
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkTSwap(value, other);
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // fast way to set [value,other] pairs
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_CPU_BENDIAN
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count & 1) {
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst[count - 1] = value;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint)
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    : SkRGB16_Blitter(device, paint) {
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getShader() == NULL);
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getColorFilter() == NULL);
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getXfermode() == NULL);
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getColor() == SK_ColorBLACK);
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 1
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define black_8_pixels(mask, dst)       \
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                \
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x80) dst[0] = 0;    \
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x40) dst[1] = 0;    \
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x20) dst[2] = 0;    \
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x10) dst[3] = 0;    \
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x08) dst[4] = 0;    \
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x04) dst[5] = 0;    \
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x02) dst[6] = 0;    \
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x01) dst[7] = 0;    \
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline black_8_pixels(U8CPU mask, uint16_t dst[])
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x80) dst[0] = 0;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x40) dst[1] = 0;
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x20) dst[2] = 0;
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x10) dst[3] = 0;
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x08) dst[4] = 0;
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x04) dst[5] = 0;
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x02) dst[6] = 0;
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask & 0x01) dst[7] = 0;
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_Black_BlitBW
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      black_8_pixels(mask, dst)
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR               getAddr16
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Black_Blitter::blitMask(const SkMask& SK_RESTRICT mask,
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                     const SkIRect& SK_RESTRICT clip)
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                     SK_RESTRICT {
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRGB16_Black_BlitBW(fDevice, mask, clip);
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop);
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned width = clip.width();
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned height = clip.height();
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned deviceRB = fDevice.rowBytes() - (width << 1);
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned maskRB = mask.fRowBytes - width;
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)height > 0);
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)width > 0);
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)deviceRB >= 0);
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((int)maskRB >= 0);
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned w = width;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned aa = *alpha++;
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device += 1;
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while (--w != 0);
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device = (uint16_t*)((char*)device + deviceRB);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += maskRB;
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Black_Blitter::blitAntiH(int x, int y,
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      const SkAlpha* SK_RESTRICT antialias,
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      const int16_t* SK_RESTRICT runs)
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      SK_RESTRICT {
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = runs[0];
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count >= 0);
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += count;
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned aa = antialias[0];
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        antialias += count;
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (aa) {
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 255) {
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memset(device, 0, count << 1);
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                aa = SkAlpha255To256(255 - aa);
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                do {
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    *device = SkAlphaMulRGB16(*device, aa);
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    device += 1;
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } while (--count != 0);
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                continue;
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device += count;
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////////////////
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////////////////
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    : INHERITED(device) {
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkColor color = paint.getColor();
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcColor32 = SkPreMultiplyColor(color);
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fScale = SkAlpha255To256(SkColorGetA(color));
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int r = SkColorGetR(color);
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int g = SkColorGetG(color);
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int b = SkColorGetB(color);
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we're dithered, use fRawDither16 to hold that.
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((fDoDither = paint.isDither()) != false) {
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!fDoDither && 256 == fScale) {
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *value = fRawColor16;
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return &fDevice;
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(width > 0);
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fScale == 0) {
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t srcColor = fColor16;
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (256 == fScale) {
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fRawColor16 == srcColor);
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fDoDither) {
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            uint16_t ditherColor = fRawDither16;
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if ((x ^ y) & 1) {
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkTSwap(ditherColor, srcColor);
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            sk_dither_memset16(device, srcColor, ditherColor, width);
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            sk_memset16(device, srcColor, width);
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // TODO: respect fDoDither
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor src32 = fSrcColor32;
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *device = SkSrcOver32To16(src32, *device);
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += 1;
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--width != 0);
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// return 1 or 0 from a bool
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int Bool2Int(bool value) {
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return !!value;
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitAntiH(int x, int y,
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkAlpha* SK_RESTRICT antialias,
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const int16_t* SK_RESTRICT runs) SK_RESTRICT {
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fScale == 0) {
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t    srcColor = fRawColor16;
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    scale = fScale;
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int         ditherInt = Bool2Int(fDoDither);
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (256 == scale) {
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t    ditherColor = fRawDither16;
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // if we have no dithering, this will always fail
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x ^ y) & ditherInt) {
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkTSwap(ditherColor, srcColor);
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = runs[0];
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count >= 0);
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned aa = antialias[0];
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa) {
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (aa == 255) {
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    if (ditherInt) {
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        sk_dither_memset16(device, srcColor,
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                           ditherColor, count);
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    } else {
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        sk_memset16(device, srcColor, count);
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } else {
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    // TODO: respect fDoDither
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    unsigned scale5 = SkAlpha255To256(aa) >> 3;
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5;
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    scale5 = 32 - scale5; // now we can use it on the device
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    int n = count;
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    do {
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    } while (--n != 0);
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    goto DONE;
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            DONE:
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // if we have no dithering, this will always fail
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count & ditherInt) {
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkTSwap(ditherColor, srcColor);
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // TODO: respect fDoDither
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = runs[0];
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count >= 0);
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned aa = antialias[0];
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa) {
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                uint32_t src32 =  SkExpand_rgb_16(srcColor) * scale5;
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                scale5 = 32 - scale5;
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                do {
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } while (--count != 0);
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                continue;
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define solid_8_pixels(mask, dst, color)    \
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                    \
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x80) dst[0] = color;    \
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x40) dst[1] = color;    \
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x20) dst[2] = color;    \
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x10) dst[3] = color;    \
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x08) dst[4] = color;    \
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x04) dst[5] = color;    \
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x02) dst[6] = color;    \
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x01) dst[7] = color;    \
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_BlitBW
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS                  , uint16_t color
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR               getAddr16
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                  U16CPU srcColor) {
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkRGB16_BlendBW
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS                  , unsigned dst_scale, U16CPU src_color
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, dst_scale, src_color)
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR               getAddr16
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint16_t
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitMask(const SkMask& SK_RESTRICT mask,
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                               const SkIRect& SK_RESTRICT clip) SK_RESTRICT {
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fScale == 0) {
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fScale == 256) {
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop);
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = clip.width();
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int height = clip.height();
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    deviceRB = fDevice.rowBytes() - (width << 1);
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    maskRB = mask.fRowBytes - width;
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t    color32 = SkExpand_rgb_16(fRawColor16);
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (256 == fScale) {
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int w = width;
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *device = blend_compact(color32, SkExpand_rgb_16(*device),
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                        SkAlpha255To256(*alpha++) >> 3);
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device += 1;
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while (--w != 0);
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device = (uint16_t*)((char*)device + deviceRB);
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += maskRB;
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {   // scale < 256
3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scale256 = fScale;
3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int w = width;
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned aa = *alpha++;
3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                uint32_t src32 = color32 * scale;
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while (--w != 0);
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device = (uint16_t*)((char*)device + deviceRB);
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += maskRB;
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fScale == 0) {
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t    color16 = fRawColor16;
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    deviceRB = fDevice.rowBytes();
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (alpha + fScale == (255 + 256)) {
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fDoDither) {
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            uint16_t ditherColor = fRawDither16;
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if ((x ^ y) & 1) {
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkTSwap(ditherColor, color16);
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device[0] = color16;
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device = (uint16_t*)((char*)device + deviceRB);
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkTSwap(ditherColor, color16);
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while (--height != 0);
4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device[0] = color16;
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device = (uint16_t*)((char*)device + deviceRB);
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while (--height != 0);
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // TODO: respect fDoDither
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t src32 =  SkExpand_rgb_16(color16) * scale5;
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        scale5 = 32 - scale5;
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *device = SkCompact_rgb_16((src32 + dst32) >> 5);
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device = (uint16_t*)((char*)device + deviceRB);
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fScale == 0) {
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    deviceRB = fDevice.rowBytes();
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t    color16 = fColor16;
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (256 == fScale) {
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fDoDither) {
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            uint16_t ditherColor = fRawDither16;
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if ((x ^ y) & 1) {
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkTSwap(ditherColor, color16);
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (--height >= 0) {
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sk_dither_memset16(device, color16, ditherColor, width);
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkTSwap(ditherColor, color16);
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device = (uint16_t*)((char*)device + deviceRB);
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {  // no dither
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (--height >= 0) {
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sk_memset16(device, color16, width);
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device = (uint16_t*)((char*)device + deviceRB);
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor src32 = fSrcColor32;
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (--height >= 0) {
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (int i = width - 1; i >= 0; --i) {
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                device[i] = SkSrcOver32To16(src32, device[i]);
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device = (uint16_t*)((char*)device + deviceRB);
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                   const SkPaint& paint)
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    : SkRGB16_Shader_Blitter(device, paint) {
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(SkShader::CanCallShadeSpan16(fShader->getFlags()));
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader*   shader = fShader;
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int alpha = shader->getSpan16Alpha();
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shader->shadeSpan16(x, y, device, width);
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t* span16 = (uint16_t*)fBuffer;
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shader->shadeSpan16(x, y, span16, width);
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         const SkAlpha* SK_RESTRICT antialias,
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         const int16_t* SK_RESTRICT runs)
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SK_RESTRICT {
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader*   shader = fShader;
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT span = fBuffer;
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int alpha = shader->getSpan16Alpha();
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* span16 = (uint16_t*)span;
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = *antialias;
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 255) {
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                // go direct to the device!
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                shader->shadeSpan16(x, y, device, count);
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else if (aa) {
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                shader->shadeSpan16(x, y, span16, count);
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {  // span alpha is < 255
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        alpha = SkAlpha255To256(alpha);
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = SkAlphaMul(*antialias, alpha);
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa) {
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                shader->shadeSpan16(x, y, span16, count);
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                               const SkPaint& paint)
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com: INHERITED(device, paint) {
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(paint.getXfermode() == NULL);
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // compute SkBlitRow::Procs
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned flags = 0;
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t shaderFlags = fShader->getFlags();
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // shaders take care of global alpha, so we never set it in SkBlitRow
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= SkBlitRow::kSrcPixelAlpha_Flag;
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // don't dither if the shader is really 16bit
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= SkBlitRow::kDither_Flag;
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // used when we know our global alpha is 0xFF
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // used when we know our global alpha is < 0xFF
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fAlphaProc  = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                     SkBitmap::kRGB_565_Config);
5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fBuffer);
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader->shadeSpan(x, y, fBuffer, width);
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // shaders take care of global alpha, so we pass 0xFF (should be ignored)
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int count = 0;
6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int n = *runs;
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (n == 0 || *aa == 0) {
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += n;
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        aa += n;
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count += n;
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       const SkAlpha* SK_RESTRICT antialias,
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       const int16_t* SK_RESTRICT runs)
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       SK_RESTRICT {
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader*   shader = fShader;
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT span = fBuffer;
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = *runs;
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int aa = *antialias;
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (0 == aa) {
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shader->shadeSpan(x, y, span, nonZeroCount);
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor* localSpan = span;
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc(device, localSpan, count, aa, x, y);
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            nonZeroCount -= count;
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (nonZeroCount == 0) {
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            localSpan += count;
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(nonZeroCount > 0);
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count = *runs;
6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count > 0);
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa = *antialias;
6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////
6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkBitmap& device, const SkPaint& paint)
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com: INHERITED(device, paint) {
6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode = paint.getXfermode();
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fXfermode);
6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode->ref();
6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = device.width();
6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fAAExpand = (uint8_t*)(fBuffer + width);
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode->unref();
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fBuffer);
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x + width <= fDevice.width());
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t*   device = fDevice.getAddr16(x, y);
6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor*  span = fBuffer;
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader->shadeSpan(x, y, span, width);
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode->xfer16(device, span, width, NULL);
6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkAlpha* SK_RESTRICT antialias,
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const int16_t* SK_RESTRICT runs) SK_RESTRICT {
6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader*   shader = fShader;
6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermode* mode = fXfermode;
6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT span = fBuffer;
6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint8_t* SK_RESTRICT aaExpand = fAAExpand;
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = *runs;
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int aa = *antialias;
7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (0 == aa) {
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int nonZeroCount = count + count_nonzero_span(runs + count,
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                      antialias + count);
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shader->shadeSpan(x, y, span, nonZeroCount);
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x += nonZeroCount;
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor* localSpan = span;
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 0xFF) {
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                mode->xfer16(device, localSpan, count, NULL);
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkASSERT(aa);
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memset(aaExpand, aa, count);
7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                mode->xfer16(device, localSpan, count, aaExpand);
7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            nonZeroCount -= count;
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (nonZeroCount == 0) {
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            localSpan += count;
7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(nonZeroCount > 0);
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count = *runs;
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count > 0);
7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa = *antialias;
7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint16_t aa_blendS32D16(SkPMColor src, U16CPU dst, int aa
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef DITHER_SHADER
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      , int dither
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      )
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)aa <= 255);
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int src_scale = SkAlpha255To256(aa);
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int sa = SkGetPackedA32(src);
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef DITHER_SHADER
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int sr = SkGetPackedR32(src);
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int sg = SkGetPackedG32(src);
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int sb = SkGetPackedB32(src);
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sr = SkDITHER_R32To16(sr, dither);
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sg = SkDITHER_G32To16(sg, dither);
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sb = SkDITHER_B32To16(sb, dither);
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int sr = SkPacked32ToR16(src);
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int sg = SkPacked32ToG16(src);
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int sb = SkPacked32ToB16(src);
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int dr = (sr * src_scale + SkGetPackedR16(dst) * dst_scale) >> 8;
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int dg = (sg * src_scale + SkGetPackedG16(dst) * dst_scale) >> 8;
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int db = (sb * src_scale + SkGetPackedB16(dst) * dst_scale) >> 8;
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(dr, dg, db);
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
783