SkSpriteBlitter_ARGB32.cpp revision c4cae85752e3e486cf4eac8cd8128f57b6f40563
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* libs/graphics/sgl/SkSpriteBlitter_ARGB32.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 "SkSpriteBlitter.h"
19c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com#include "SkBlitRow.h"
20c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com#include "SkColorFilter.h"
21c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com#include "SkColorPriv.h"
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
24c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com#include "SkXfermode.h"
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.comclass Sprite_D32_S32 : public SkSpriteBlitter {
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
30c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    Sprite_D32_S32(const SkBitmap& src, U8CPU alpha)  : INHERITED(src) {
31c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        SkASSERT(src.config() == SkBitmap::kARGB_8888_Config);
32c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
33c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        unsigned flags32 = 0;
34c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        if (255 != alpha) {
35c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
36c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        }
37c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        if (!src.isOpaque()) {
38c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
39c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        }
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
41c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        fProc32 = SkBlitRow::Factory32(flags32);
42c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        fAlpha = alpha;
43c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    }
44c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void blitRect(int x, int y, int width, int height) {
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(width > 0 && height > 0);
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SK_RESTRICT uint32_t* dst = fDevice->getAddr32(x, y);
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SK_RESTRICT uint32_t* src = fSource->getAddr32(x - fLeft,
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                             y - fTop);
50c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        size_t dstRB = fDevice->rowBytes();
51c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        size_t srcRB = fSource->rowBytes();
52c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        SkBlitRow::Proc32 proc = fProc32;
53c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        U8CPU             alpha = fAlpha;
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
56c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            proc(dst, src, width, alpha);
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst = (SK_RESTRICT uint32_t*)((char*)dst + dstRB);
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            src = (const SK_RESTRICT uint32_t*)((const char*)src + srcRB);
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
61c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
62c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.comprivate:
63c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkBlitRow::Proc32   fProc32;
64c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    U8CPU               fAlpha;
65c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
66c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    typedef SkSpriteBlitter INHERITED;
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sprite_D32_XferFilter : public SkSpriteBlitter {
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sprite_D32_XferFilter(const SkBitmap& source, const SkPaint& paint)
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : SkSpriteBlitter(source) {
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fColorFilter = paint.getColorFilter();
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fColorFilter->safeRef();
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fXfermode = paint.getXfermode();
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fXfermode->safeRef();
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBufferSize = 0;
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBuffer = NULL;
83c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
84c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        unsigned flags32 = 0;
85c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        if (255 != paint.getAlpha()) {
86c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
87c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        }
88c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        if (!source.isOpaque()) {
89c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
90c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        }
91c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
92c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        fProc32 = SkBlitRow::Factory32(flags32);
93c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        fAlpha = paint.getAlpha();
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual ~Sprite_D32_XferFilter() {
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        delete[] fBuffer;
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fXfermode->safeUnref();
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fColorFilter->safeUnref();
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void setup(const SkBitmap& device, int left, int top,
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->INHERITED::setup(device, left, top, paint);
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = device.width();
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (width > fBufferSize) {
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBufferSize = width;
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            delete[] fBuffer;
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBuffer = new SkPMColor[width];
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
115c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkColorFilter*      fColorFilter;
116c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkXfermode*         fXfermode;
117c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    int                 fBufferSize;
118c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkPMColor*          fBuffer;
119c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkBlitRow::Proc32   fProc32;
120c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    U8CPU               fAlpha;
121c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkSpriteBlitter INHERITED;
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter {
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sprite_D32_S32A_XferFilter(const SkBitmap& source, const SkPaint& paint)
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : Sprite_D32_XferFilter(source, paint) {}
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void blitRect(int x, int y, int width, int height) {
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(width > 0 && height > 0);
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SK_RESTRICT uint32_t* dst = fDevice->getAddr32(x, y);
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SK_RESTRICT uint32_t* src = fSource->getAddr32(x - fLeft,
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                             y - fTop);
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned dstRB = fDevice->rowBytes();
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned srcRB = fSource->rowBytes();
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkColorFilter* colorFilter = fColorFilter;
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkXfermode* xfermode = fXfermode;
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const SkPMColor* tmp = src;
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (NULL != colorFilter) {
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                colorFilter->filterSpan(src, width, fBuffer);
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                tmp = fBuffer;
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (NULL != xfermode) {
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                xfermode->xfer32(dst, tmp, width, NULL);
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
154c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                fProc32(dst, tmp, width, fAlpha);
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst = (SK_RESTRICT uint32_t*)((char*)dst + dstRB);
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            src = (const SK_RESTRICT uint32_t*)((const char*)src + srcRB);
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef Sprite_D32_XferFilter INHERITED;
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void fillbuffer(SK_RESTRICT SkPMColor dst[],
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SK_RESTRICT SkPMColor16 src[], int count) {
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(count > 0);
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst++ = SkPixel4444ToPixel32(*src++);
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (--count != 0);
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter {
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sprite_D32_S4444_XferFilter(const SkBitmap& source, const SkPaint& paint)
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : Sprite_D32_XferFilter(source, paint) {}
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void blitRect(int x, int y, int width, int height) {
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(width > 0 && height > 0);
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y);
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft,
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                                y - fTop);
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned dstRB = fDevice->rowBytes();
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned srcRB = fSource->rowBytes();
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SK_RESTRICT SkPMColor* buffer = fBuffer;
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkColorFilter* colorFilter = fColorFilter;
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkXfermode* xfermode = fXfermode;
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fillbuffer(buffer, src, width);
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (NULL != colorFilter) {
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                colorFilter->filterSpan(buffer, width, buffer);
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (NULL != xfermode) {
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                xfermode->xfer32(dst, buffer, width, NULL);
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
200c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                fProc32(dst, buffer, width, fAlpha);
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB);
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB);
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef Sprite_D32_XferFilter INHERITED;
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void src_row(SK_RESTRICT SkPMColor dst[],
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    const SK_RESTRICT SkPMColor16 src[], int count) {
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst = SkPixel4444ToPixel32(*src);
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += 1;
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst += 1;
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (--count != 0);
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sprite_D32_S4444_Opaque : public SkSpriteBlitter {
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sprite_D32_S4444_Opaque(const SkBitmap& source) : SkSpriteBlitter(source) {}
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void blitRect(int x, int y, int width, int height) {
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(width > 0 && height > 0);
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y);
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft,
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                                y - fTop);
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned dstRB = fDevice->rowBytes();
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned srcRB = fSource->rowBytes();
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            src_row(dst, src, width);
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB);
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB);
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void srcover_row(SK_RESTRICT SkPMColor dst[],
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SK_RESTRICT SkPMColor16 src[], int count) {
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst);
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += 1;
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst += 1;
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (--count != 0);
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sprite_D32_S4444 : public SkSpriteBlitter {
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sprite_D32_S4444(const SkBitmap& source) : SkSpriteBlitter(source) {}
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void blitRect(int x, int y, int width, int height) {
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(width > 0 && height > 0);
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y);
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft,
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                                y - fTop);
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned dstRB = fDevice->rowBytes();
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned srcRB = fSource->rowBytes();
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            srcover_row(dst, src, width);
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB);
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB);
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--height != 0);
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplatesPriv.h"
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source,
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            const SkPaint& paint,
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            void* storage, size_t storageSize) {
279c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    if (paint.getMaskFilter() != NULL) {
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
283c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    U8CPU       alpha = paint.getAlpha();
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermode* xfermode = paint.getXfermode();
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkColorFilter* filter = paint.getColorFilter();
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSpriteBlitter* blitter = NULL;
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (source.getConfig()) {
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkBitmap::kARGB_4444_Config:
290c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            if (alpha != 0xFF) {
291c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                return NULL;    // we only have opaque sprites
292c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            }
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (xfermode || filter) {
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_XferFilter,
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      storage, storageSize, (source, paint));
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else if (source.isOpaque()) {
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_Opaque,
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      storage, storageSize, (source));
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444,
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      storage, storageSize, (source));
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkBitmap::kARGB_8888_Config:
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (xfermode || filter) {
306c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                if (255 == alpha) {
307c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                    // this can handle xfermode or filter, but not alpha
308c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                    SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32A_XferFilter,
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      storage, storageSize, (source, paint));
310c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                }
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
312c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                // this can handle alpha, but not xfermode or filter
313c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32,
314c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                              storage, storageSize, (source, alpha));
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return blitter;
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
323