1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitter.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitRow.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define D16_S32A_Opaque_Pixel(dst, sc)                                        \
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comdo {                                                                          \
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (sc) {                                                                 \
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst = SkSrcOver32To16(sc, *dst);                                     \
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }                                                                         \
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} while (0)
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline void D16_S32A_Blend_Pixel_helper(uint16_t* dst, SkPMColor sc,
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                               unsigned src_scale) {
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t dc = *dst;
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sa = SkGetPackedA32(sc);
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dr, dg, db;
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (255 == sa) {
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale);
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale);
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale);
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale);
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dr = (SkPacked32ToR16(sc) * src_scale +
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com              SkGetPackedR16(dc) * dst_scale) >> 8;
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dg = (SkPacked32ToG16(sc) * src_scale +
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com              SkGetPackedG16(dc) * dst_scale) >> 8;
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        db = (SkPacked32ToB16(sc) * src_scale +
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com              SkGetPackedB16(dc) * dst_scale) >> 8;
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *dst = SkPackRGB16(dr, dg, db);
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define D16_S32A_Blend_Pixel(dst, sc, src_scale) \
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do { if (sc) D16_S32A_Blend_Pixel_helper(dst, sc, src_scale); } while (0)
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sprite_D16_S16_Opaque : public SkSpriteBlitter {
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sprite_D16_S16_Opaque(const SkBitmap& source)
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : SkSpriteBlitter(source) {}
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // overrides
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void blitRect(int x, int y, int width, int height) {
58a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com        uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y);
59a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com        const uint16_t* SK_RESTRICT src = fSource->getAddr16(x - fLeft,
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                             y - fTop);
61e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com        size_t dstRB = fDevice->rowBytes();
62e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com        size_t srcRB = fSource->rowBytes();
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (--height >= 0) {
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(dst, src, width << 1);
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst = (uint16_t*)((char*)dst + dstRB);
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            src = (const uint16_t*)((const char*)src + srcRB);
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define D16_S16_Blend_Pixel(dst, sc, scale)     \
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                        \
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t dc = *dst;                     \
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst = SkBlendRGB16(sc, dc, scale);     \
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_S16_Blend
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS                       , uint8_t alpha
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS                     uint8_t  fSrcAlpha;
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT                       fSrcAlpha = alpha;
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint16_t
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr16
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      int scale = SkAlpha255To256(fSrcAlpha);
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S16_Blend_Pixel(dst, src, scale)
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define D16_S4444_Opaque(dst, sc)           \
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                    \
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t dc = *dst;                 \
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst = SkSrcOver4444To16(sc, dc);   \
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_S4444_Opaque
101fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define SkSPRITE_ARGS
102fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define SkSPRITE_FIELDS
103fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define SkSPRITE_INIT
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   SkPMColor16
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr16
108fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define SkSPRITE_PREAMBLE(srcBM, x, y)
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S4444_Opaque(dst, src)
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define D16_S4444_Blend(dst, sc, scale16)           \
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                            \
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t dc = *dst;                         \
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst = SkBlend4444To16(sc, dc, scale16);    \
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_S4444_Blend
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS                       , uint8_t alpha
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS                     uint8_t  fSrcAlpha;
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT                       fSrcAlpha = alpha;
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint16_t
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr16
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      int scale = SkAlpha15To16(fSrcAlpha);
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S4444_Blend(dst, src, scale)
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8A_Opaque
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint8_t
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr8
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      const SkPMColor* ctable = srcBM.getColorTable()->lockColors()
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S32A_Opaque_Pixel(dst, ctable[src])
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
1480a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlockColors()
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8A_Blend
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS                       , uint8_t alpha
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS                     uint8_t fSrcAlpha;
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT                       fSrcAlpha = alpha;
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint8_t
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr8
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      const SkPMColor* ctable = srcBM.getColorTable()->lockColors(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S32A_Blend_Pixel(dst, ctable[src], src_scale)
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
1620a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlockColors();
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1671c12abe3508cd69615c2dd50653f782835e325cereed@android.comstatic intptr_t asint(const void* ptr) {
1681c12abe3508cd69615c2dd50653f782835e325cereed@android.com    return reinterpret_cast<const char*>(ptr) - (const char*)0;
1691c12abe3508cd69615c2dd50653f782835e325cereed@android.com}
1701c12abe3508cd69615c2dd50653f782835e325cereed@android.com
171a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comstatic void blitrow_d16_si8(uint16_t* SK_RESTRICT dst,
172a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                            const uint8_t* SK_RESTRICT src, int count,
173a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                            const uint16_t* SK_RESTRICT ctable) {
1741c12abe3508cd69615c2dd50653f782835e325cereed@android.com    if (count <= 8) {
1751c12abe3508cd69615c2dd50653f782835e325cereed@android.com        do {
1761c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[*src++];
1771c12abe3508cd69615c2dd50653f782835e325cereed@android.com        } while (--count);
1781c12abe3508cd69615c2dd50653f782835e325cereed@android.com        return;
1791c12abe3508cd69615c2dd50653f782835e325cereed@android.com    }
1801c12abe3508cd69615c2dd50653f782835e325cereed@android.com
1811c12abe3508cd69615c2dd50653f782835e325cereed@android.com    // eat src until we're on a 4byte boundary
1821c12abe3508cd69615c2dd50653f782835e325cereed@android.com    while (asint(src) & 3) {
1831c12abe3508cd69615c2dd50653f782835e325cereed@android.com        *dst++ = ctable[*src++];
1841c12abe3508cd69615c2dd50653f782835e325cereed@android.com        count -= 1;
1851c12abe3508cd69615c2dd50653f782835e325cereed@android.com    }
1861c12abe3508cd69615c2dd50653f782835e325cereed@android.com
1871c12abe3508cd69615c2dd50653f782835e325cereed@android.com    int qcount = count >> 2;
1881c12abe3508cd69615c2dd50653f782835e325cereed@android.com    SkASSERT(qcount > 0);
1891c12abe3508cd69615c2dd50653f782835e325cereed@android.com    const uint32_t* qsrc = reinterpret_cast<const uint32_t*>(src);
1901c12abe3508cd69615c2dd50653f782835e325cereed@android.com    if (asint(dst) & 2) {
1911c12abe3508cd69615c2dd50653f782835e325cereed@android.com        do {
1921c12abe3508cd69615c2dd50653f782835e325cereed@android.com            uint32_t s4 = *qsrc++;
1931c12abe3508cd69615c2dd50653f782835e325cereed@android.com#ifdef SK_CPU_LENDIAN
1941c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[s4 & 0xFF];
1951c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[(s4 >> 8) & 0xFF];
1961c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[(s4 >> 16) & 0xFF];
1971c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[s4 >> 24];
1981c12abe3508cd69615c2dd50653f782835e325cereed@android.com#else   // BENDIAN
1991c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[s4 >> 24];
2001c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[(s4 >> 16) & 0xFF];
2011c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[(s4 >> 8) & 0xFF];
2021c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[s4 & 0xFF];
2031c12abe3508cd69615c2dd50653f782835e325cereed@android.com#endif
2041c12abe3508cd69615c2dd50653f782835e325cereed@android.com        } while (--qcount);
2051c12abe3508cd69615c2dd50653f782835e325cereed@android.com    } else {    // dst is on a 4byte boundary
2061c12abe3508cd69615c2dd50653f782835e325cereed@android.com        uint32_t* ddst = reinterpret_cast<uint32_t*>(dst);
2071c12abe3508cd69615c2dd50653f782835e325cereed@android.com        do {
2081c12abe3508cd69615c2dd50653f782835e325cereed@android.com            uint32_t s4 = *qsrc++;
2091c12abe3508cd69615c2dd50653f782835e325cereed@android.com#ifdef SK_CPU_LENDIAN
2101c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF];
2111c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF];
2121c12abe3508cd69615c2dd50653f782835e325cereed@android.com#else   // BENDIAN
2131c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF];
2141c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF];
2151c12abe3508cd69615c2dd50653f782835e325cereed@android.com#endif
2161c12abe3508cd69615c2dd50653f782835e325cereed@android.com        } while (--qcount);
2171c12abe3508cd69615c2dd50653f782835e325cereed@android.com        dst = reinterpret_cast<uint16_t*>(ddst);
2181c12abe3508cd69615c2dd50653f782835e325cereed@android.com    }
2191c12abe3508cd69615c2dd50653f782835e325cereed@android.com    src = reinterpret_cast<const uint8_t*>(qsrc);
2201c12abe3508cd69615c2dd50653f782835e325cereed@android.com    count &= 3;
2211c12abe3508cd69615c2dd50653f782835e325cereed@android.com    // catch any remaining (will be < 4)
2221c12abe3508cd69615c2dd50653f782835e325cereed@android.com    while (--count >= 0) {
2231c12abe3508cd69615c2dd50653f782835e325cereed@android.com        *dst++ = ctable[*src++];
2241c12abe3508cd69615c2dd50653f782835e325cereed@android.com    }
2251c12abe3508cd69615c2dd50653f782835e325cereed@android.com}
2261c12abe3508cd69615c2dd50653f782835e325cereed@android.com
2271c12abe3508cd69615c2dd50653f782835e325cereed@android.com#define SkSPRITE_ROW_PROC(d, s, n, x, y)    blitrow_d16_si8(d, s, n, ctable)
228084ad42b91546f0f99d7cd5064c04edacede66ffreed@android.com
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8_Opaque
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint8_t
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr8
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache()
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       *dst = ctable[src]
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlock16BitCache()
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8_Blend
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS                       , uint8_t alpha
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS                     uint8_t fSrcAlpha;
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT                       fSrcAlpha = alpha;
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint8_t
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr8
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S16_Blend_Pixel(dst, ctable[src], src_scale)
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlock16BitCache();
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sprite_D16_S32_BlitRowProc : public SkSpriteBlitter {
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sprite_D16_S32_BlitRowProc(const SkBitmap& source)
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : SkSpriteBlitter(source) {}
263fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // overrides
265fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void setup(const SkBitmap& device, int left, int top,
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->INHERITED::setup(device, left, top, paint);
269fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned flags = 0;
271fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.getAlpha() < 0xFF) {
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            flags |= SkBlitRow::kGlobalAlpha_Flag;
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fSource->isOpaque()) {
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            flags |= SkBlitRow::kSrcPixelAlpha_Flag;
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.isDither()) {
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            flags |= SkBlitRow::kDither_Flag;
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
281cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        fProc = SkBlitRow::Factory(flags, kRGB_565_SkColorType);
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
283fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void blitRect(int x, int y, int width, int height) {
285a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com        uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y);
286a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com        const SkPMColor* SK_RESTRICT src = fSource->getAddr32(x - fLeft,
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                              y - fTop);
288e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com        size_t dstRB = fDevice->rowBytes();
289e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com        size_t srcRB = fSource->rowBytes();
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkBlitRow::Proc proc = fProc;
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        U8CPU alpha = fPaint->getAlpha();
292fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (--height >= 0) {
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc(dst, src, width, alpha, x, y);
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            y += 1;
296a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com            dst = (uint16_t* SK_RESTRICT)((char*)dst + dstRB);
297a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com            src = (const SkPMColor* SK_RESTRICT)((const char*)src + srcRB);
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
300fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBlitRow::Proc fProc;
303fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkSpriteBlitter INHERITED;
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
309a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.orgSkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source, const SkPaint& paint,
310a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org        SkTBlitterAllocator* allocator) {
311a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org
312a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org    SkASSERT(allocator != NULL);
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.getMaskFilter() != NULL) { // may add cases for this
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.getXfermode() != NULL) { // may add cases for this
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.getColorFilter() != NULL) { // may add cases for this
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSpriteBlitter* blitter = NULL;
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned alpha = paint.getAlpha();
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
327900ecf2f1579d42c9d2959831787af0346320f86reed@google.com    switch (source.colorType()) {
32828fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType: {
329a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<Sprite_D16_S32_BlitRowProc>(source);
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
331a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org        }
332900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        case kARGB_4444_SkColorType:
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (255 == alpha) {
334a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                blitter = allocator->createT<Sprite_D16_S4444_Opaque>(source);
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
336a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                blitter = allocator->createT<Sprite_D16_S4444_Blend>(source, alpha >> 4);
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
339900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        case kRGB_565_SkColorType:
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (255 == alpha) {
341a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                blitter = allocator->createT<Sprite_D16_S16_Opaque>(source);
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
343a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                blitter = allocator->createT<Sprite_D16_S16_Blend>(source, alpha);
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
346900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        case kIndex_8_SkColorType:
347755dd4773dad70d5fbe3f8bb091eaf268ea752c7reed@android.com            if (paint.isDither()) {
348755dd4773dad70d5fbe3f8bb091eaf268ea752c7reed@android.com                // we don't support dither yet in these special cases
349755dd4773dad70d5fbe3f8bb091eaf268ea752c7reed@android.com                break;
350755dd4773dad70d5fbe3f8bb091eaf268ea752c7reed@android.com            }
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (source.isOpaque()) {
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (255 == alpha) {
353a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                    blitter = allocator->createT<Sprite_D16_SIndex8_Opaque>(source);
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } else {
355a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                    blitter = allocator->createT<Sprite_D16_SIndex8_Blend>(source, alpha);
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (255 == alpha) {
359a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                    blitter = allocator->createT<Sprite_D16_SIndex8A_Opaque>(source);
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } else {
361a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                    blitter = allocator->createT<Sprite_D16_SIndex8A_Blend>(source, alpha);
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return blitter;
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
370