SkSpriteBlitter_RGB16.cpp revision 1c12abe3508cd69615c2dd50653f782835e325ce
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* libs/graphics/sgl/SkSpriteBlitter_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 "SkSpriteBlitter.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitRow.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define D16_S32A_Opaque_Pixel(dst, sc)                                        \
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comdo {                                                                          \
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (sc) {                                                                 \
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst = SkSrcOver32To16(sc, *dst);                                     \
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }                                                                         \
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} while (0)
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline void D16_S32A_Blend_Pixel_helper(uint16_t* dst, SkPMColor sc,
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                               unsigned src_scale) {
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t dc = *dst;
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sa = SkGetPackedA32(sc);
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dr, dg, db;
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (255 == sa) {
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale);
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale);
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale);
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale);
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dr = (SkPacked32ToR16(sc) * src_scale +
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com              SkGetPackedR16(dc) * dst_scale) >> 8;
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dg = (SkPacked32ToG16(sc) * src_scale +
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com              SkGetPackedG16(dc) * dst_scale) >> 8;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        db = (SkPacked32ToB16(sc) * src_scale +
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com              SkGetPackedB16(dc) * dst_scale) >> 8;
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *dst = SkPackRGB16(dr, dg, db);
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define D16_S32A_Blend_Pixel(dst, sc, src_scale) \
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do { if (sc) D16_S32A_Blend_Pixel_helper(dst, sc, src_scale); } while (0)
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sprite_D16_S16_Opaque : public SkSpriteBlitter {
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sprite_D16_S16_Opaque(const SkBitmap& source)
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : SkSpriteBlitter(source) {}
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // overrides
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void blitRect(int x, int y, int width, int height) {
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SK_RESTRICT uint16_t* dst = fDevice->getAddr16(x, y);
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SK_RESTRICT uint16_t* src = fSource->getAddr16(x - fLeft,
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                             y - fTop);
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned dstRB = fDevice->rowBytes();
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned srcRB = fSource->rowBytes();
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (--height >= 0) {
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(dst, src, width << 1);
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst = (uint16_t*)((char*)dst + dstRB);
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            src = (const uint16_t*)((const char*)src + srcRB);
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define D16_S16_Blend_Pixel(dst, sc, scale)     \
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                        \
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t dc = *dst;                     \
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst = SkBlendRGB16(sc, dc, scale);     \
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_S16_Blend
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS                       , uint8_t alpha
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS                     uint8_t  fSrcAlpha;
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT                       fSrcAlpha = alpha;
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint16_t
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr16
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      int scale = SkAlpha255To256(fSrcAlpha);
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S16_Blend_Pixel(dst, src, scale)
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define D16_S4444_Opaque(dst, sc)           \
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                    \
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t dc = *dst;                 \
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst = SkSrcOver4444To16(sc, dc);   \
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_S4444_Opaque
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   SkPMColor16
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr16
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S4444_Opaque(dst, src)
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define D16_S4444_Blend(dst, sc, scale16)           \
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                            \
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint16_t dc = *dst;                         \
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst = SkBlend4444To16(sc, dc, scale16);    \
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_S4444_Blend
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS                       , uint8_t alpha
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS                     uint8_t  fSrcAlpha;
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT                       fSrcAlpha = alpha;
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint16_t
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr16
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      int scale = SkAlpha15To16(fSrcAlpha);
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S4444_Blend(dst, src, scale)
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8A_Opaque
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint8_t
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr8
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      const SkPMColor* ctable = srcBM.getColorTable()->lockColors()
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S32A_Opaque_Pixel(dst, ctable[src])
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlockColors(false)
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8A_Blend
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS                       , uint8_t alpha
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS                     uint8_t fSrcAlpha;
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT                       fSrcAlpha = alpha;
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint8_t
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr8
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      const SkPMColor* ctable = srcBM.getColorTable()->lockColors(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S32A_Blend_Pixel(dst, ctable[src], src_scale)
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlockColors(false);
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1751c12abe3508cd69615c2dd50653f782835e325cereed@android.comstatic intptr_t asint(const void* ptr) {
1761c12abe3508cd69615c2dd50653f782835e325cereed@android.com    return reinterpret_cast<const char*>(ptr) - (const char*)0;
1771c12abe3508cd69615c2dd50653f782835e325cereed@android.com}
1781c12abe3508cd69615c2dd50653f782835e325cereed@android.com
1791c12abe3508cd69615c2dd50653f782835e325cereed@android.comstatic void blitrow_d16_si8(SK_RESTRICT uint16_t* dst,
1801c12abe3508cd69615c2dd50653f782835e325cereed@android.com                            SK_RESTRICT const uint8_t* src, int count,
1811c12abe3508cd69615c2dd50653f782835e325cereed@android.com                            SK_RESTRICT const uint16_t* ctable) {
1821c12abe3508cd69615c2dd50653f782835e325cereed@android.com    if (count <= 8) {
1831c12abe3508cd69615c2dd50653f782835e325cereed@android.com        do {
1841c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[*src++];
1851c12abe3508cd69615c2dd50653f782835e325cereed@android.com        } while (--count);
1861c12abe3508cd69615c2dd50653f782835e325cereed@android.com        return;
1871c12abe3508cd69615c2dd50653f782835e325cereed@android.com    }
1881c12abe3508cd69615c2dd50653f782835e325cereed@android.com
1891c12abe3508cd69615c2dd50653f782835e325cereed@android.com    // eat src until we're on a 4byte boundary
1901c12abe3508cd69615c2dd50653f782835e325cereed@android.com    while (asint(src) & 3) {
1911c12abe3508cd69615c2dd50653f782835e325cereed@android.com        *dst++ = ctable[*src++];
1921c12abe3508cd69615c2dd50653f782835e325cereed@android.com        count -= 1;
1931c12abe3508cd69615c2dd50653f782835e325cereed@android.com    }
1941c12abe3508cd69615c2dd50653f782835e325cereed@android.com
1951c12abe3508cd69615c2dd50653f782835e325cereed@android.com    int qcount = count >> 2;
1961c12abe3508cd69615c2dd50653f782835e325cereed@android.com    SkASSERT(qcount > 0);
1971c12abe3508cd69615c2dd50653f782835e325cereed@android.com    const uint32_t* qsrc = reinterpret_cast<const uint32_t*>(src);
1981c12abe3508cd69615c2dd50653f782835e325cereed@android.com    if (asint(dst) & 2) {
1991c12abe3508cd69615c2dd50653f782835e325cereed@android.com        do {
2001c12abe3508cd69615c2dd50653f782835e325cereed@android.com            uint32_t s4 = *qsrc++;
2011c12abe3508cd69615c2dd50653f782835e325cereed@android.com#ifdef SK_CPU_LENDIAN
2021c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[s4 & 0xFF];
2031c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[(s4 >> 8) & 0xFF];
2041c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[(s4 >> 16) & 0xFF];
2051c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[s4 >> 24];
2061c12abe3508cd69615c2dd50653f782835e325cereed@android.com#else   // BENDIAN
2071c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[s4 >> 24];
2081c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[(s4 >> 16) & 0xFF];
2091c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[(s4 >> 8) & 0xFF];
2101c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *dst++ = ctable[s4 & 0xFF];
2111c12abe3508cd69615c2dd50653f782835e325cereed@android.com#endif
2121c12abe3508cd69615c2dd50653f782835e325cereed@android.com        } while (--qcount);
2131c12abe3508cd69615c2dd50653f782835e325cereed@android.com    } else {    // dst is on a 4byte boundary
2141c12abe3508cd69615c2dd50653f782835e325cereed@android.com        uint32_t* ddst = reinterpret_cast<uint32_t*>(dst);
2151c12abe3508cd69615c2dd50653f782835e325cereed@android.com        do {
2161c12abe3508cd69615c2dd50653f782835e325cereed@android.com            uint32_t s4 = *qsrc++;
2171c12abe3508cd69615c2dd50653f782835e325cereed@android.com#ifdef SK_CPU_LENDIAN
2181c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF];
2191c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF];
2201c12abe3508cd69615c2dd50653f782835e325cereed@android.com#else   // BENDIAN
2211c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF];
2221c12abe3508cd69615c2dd50653f782835e325cereed@android.com            *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF];
2231c12abe3508cd69615c2dd50653f782835e325cereed@android.com#endif
2241c12abe3508cd69615c2dd50653f782835e325cereed@android.com        } while (--qcount);
2251c12abe3508cd69615c2dd50653f782835e325cereed@android.com        dst = reinterpret_cast<uint16_t*>(ddst);
2261c12abe3508cd69615c2dd50653f782835e325cereed@android.com    }
2271c12abe3508cd69615c2dd50653f782835e325cereed@android.com    src = reinterpret_cast<const uint8_t*>(qsrc);
2281c12abe3508cd69615c2dd50653f782835e325cereed@android.com    count &= 3;
2291c12abe3508cd69615c2dd50653f782835e325cereed@android.com    // catch any remaining (will be < 4)
2301c12abe3508cd69615c2dd50653f782835e325cereed@android.com    while (--count >= 0) {
2311c12abe3508cd69615c2dd50653f782835e325cereed@android.com        *dst++ = ctable[*src++];
2321c12abe3508cd69615c2dd50653f782835e325cereed@android.com    }
2331c12abe3508cd69615c2dd50653f782835e325cereed@android.com}
2341c12abe3508cd69615c2dd50653f782835e325cereed@android.com
2351c12abe3508cd69615c2dd50653f782835e325cereed@android.com#define SkSPRITE_ROW_PROC(d, s, n, x, y)    blitrow_d16_si8(d, s, n, ctable)
2361c12abe3508cd69615c2dd50653f782835e325cereed@android.com
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8_Opaque
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint8_t
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr8
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache()
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       *dst = ctable[src]
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlock16BitCache()
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8_Blend
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_ARGS                       , uint8_t alpha
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_FIELDS                     uint8_t fSrcAlpha;
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_INIT                       fSrcAlpha = alpha;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_TYPE                   uint16_t
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_TYPE                   uint8_t
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_DST_GETADDR                getAddr16
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_SRC_GETADDR                getAddr8
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_PREAMBLE(srcBM, x, y)      const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S16_Blend_Pixel(dst, ctable[src], src_scale)
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_NEXT_ROW
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlock16BitCache();
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkSpriteBlitterTemplate.h"
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sprite_D16_S32_BlitRowProc : public SkSpriteBlitter {
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sprite_D16_S32_BlitRowProc(const SkBitmap& source)
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : SkSpriteBlitter(source) {}
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // overrides
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void setup(const SkBitmap& device, int left, int top,
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->INHERITED::setup(device, left, top, paint);
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned flags = 0;
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.getAlpha() < 0xFF) {
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            flags |= SkBlitRow::kGlobalAlpha_Flag;
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fSource->isOpaque()) {
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            flags |= SkBlitRow::kSrcPixelAlpha_Flag;
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.isDither()) {
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            flags |= SkBlitRow::kDither_Flag;
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void blitRect(int x, int y, int width, int height) {
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SK_RESTRICT uint16_t* dst = fDevice->getAddr16(x, y);
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SK_RESTRICT SkPMColor* src = fSource->getAddr32(x - fLeft,
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                              y - fTop);
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned dstRB = fDevice->rowBytes();
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned srcRB = fSource->rowBytes();
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkBlitRow::Proc proc = fProc;
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        U8CPU alpha = fPaint->getAlpha();
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (--height >= 0) {
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc(dst, src, width, alpha, x, y);
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            y += 1;
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst = (SK_RESTRICT uint16_t*)((char*)dst + dstRB);
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            src = (const SK_RESTRICT SkPMColor*)((const char*)src + srcRB);
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBlitRow::Proc fProc;
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkSpriteBlitter INHERITED;
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplatesPriv.h"
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source,
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            const SkPaint& paint,
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            void* storage, size_t storageSize) {
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.getMaskFilter() != NULL) { // may add cases for this
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.getXfermode() != NULL) { // may add cases for this
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.getColorFilter() != NULL) { // may add cases for this
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSpriteBlitter* blitter = NULL;
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned alpha = paint.getAlpha();
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (source.getConfig()) {
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkBitmap::kARGB_8888_Config:
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32_BlitRowProc,
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                  storage, storageSize, (source));
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkBitmap::kARGB_4444_Config:
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (255 == alpha) {
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Opaque,
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      storage, storageSize, (source));
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Blend,
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    storage, storageSize, (source, alpha >> 4));
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkBitmap::kRGB_565_Config:
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (255 == alpha) {
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Opaque,
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      storage, storageSize, (source));
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Blend,
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      storage, storageSize, (source, alpha));
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkBitmap::kIndex8_Config:
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (source.isOpaque()) {
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (255 == alpha) {
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Opaque,
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                          storage, storageSize, (source));
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } else {
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Blend,
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         storage, storageSize, (source, alpha));
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (255 == alpha) {
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Opaque,
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                          storage, storageSize, (source));
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } else {
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Blend,
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         storage, storageSize, (source, alpha));
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return blitter;
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
383