11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkSpriteBlitter.h"
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlitRow.h"
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTemplates.h"
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkUtils.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkColorPriv.h"
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define D16_S32A_Opaque_Pixel(dst, sc)                                        \
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectdo {                                                                          \
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (sc) {                                                                 \
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst = SkSrcOver32To16(sc, *dst);                                     \
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }                                                                         \
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} while (0)
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline void D16_S32A_Blend_Pixel_helper(uint16_t* dst, SkPMColor sc,
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                               unsigned src_scale) {
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint16_t dc = *dst;
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned sa = SkGetPackedA32(sc);
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned dr, dg, db;
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (255 == sa) {
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale);
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale);
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale);
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale);
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dr = (SkPacked32ToR16(sc) * src_scale +
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project              SkGetPackedR16(dc) * dst_scale) >> 8;
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dg = (SkPacked32ToG16(sc) * src_scale +
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project              SkGetPackedG16(dc) * dst_scale) >> 8;
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        db = (SkPacked32ToB16(sc) * src_scale +
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project              SkGetPackedB16(dc) * dst_scale) >> 8;
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *dst = SkPackRGB16(dr, dg, db);
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define D16_S32A_Blend_Pixel(dst, sc, src_scale) \
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do { if (sc) D16_S32A_Blend_Pixel_helper(dst, sc, src_scale); } while (0)
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass Sprite_D16_S16_Opaque : public SkSpriteBlitter {
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Sprite_D16_S16_Opaque(const SkBitmap& source)
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        : SkSpriteBlitter(source) {}
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // overrides
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void blitRect(int x, int y, int width, int height) {
581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y);
591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const uint16_t* SK_RESTRICT src = fSource->getAddr16(x - fLeft,
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                                             y - fTop);
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        unsigned dstRB = fDevice->rowBytes();
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        unsigned srcRB = fSource->rowBytes();
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        while (--height >= 0) {
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            memcpy(dst, src, width << 1);
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            dst = (uint16_t*)((char*)dst + dstRB);
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            src = (const uint16_t*)((const char*)src + srcRB);
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define D16_S16_Blend_Pixel(dst, sc, scale)     \
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {                                        \
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        uint16_t dc = *dst;                     \
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst = SkBlendRGB16(sc, dc, scale);     \
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while (0)
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_CLASSNAME                  Sprite_D16_S16_Blend
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_ARGS                       , uint8_t alpha
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_FIELDS                     uint8_t  fSrcAlpha;
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_INIT                       fSrcAlpha = alpha;
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_TYPE                   uint16_t
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_TYPE                   uint16_t
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_GETADDR                getAddr16
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_GETADDR                getAddr16
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_PREAMBLE(srcBM, x, y)      int scale = SkAlpha255To256(fSrcAlpha);
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S16_Blend_Pixel(dst, src, scale)
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_NEXT_ROW
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_POSTAMBLE(srcBM)
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkSpriteBlitterTemplate.h"
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define D16_S4444_Opaque(dst, sc)           \
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {                                    \
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        uint16_t dc = *dst;                 \
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst = SkSrcOver4444To16(sc, dc);   \
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while (0)
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_CLASSNAME                  Sprite_D16_S4444_Opaque
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_ARGS
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_FIELDS
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_INIT
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_TYPE                   uint16_t
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_TYPE                   SkPMColor16
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_GETADDR                getAddr16
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_GETADDR                getAddr16
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_PREAMBLE(srcBM, x, y)
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S4444_Opaque(dst, src)
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_NEXT_ROW
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_POSTAMBLE(srcBM)
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkSpriteBlitterTemplate.h"
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define D16_S4444_Blend(dst, sc, scale16)           \
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {                                            \
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        uint16_t dc = *dst;                         \
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst = SkBlend4444To16(sc, dc, scale16);    \
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while (0)
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_CLASSNAME                  Sprite_D16_S4444_Blend
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_ARGS                       , uint8_t alpha
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_FIELDS                     uint8_t  fSrcAlpha;
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_INIT                       fSrcAlpha = alpha;
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_TYPE                   uint16_t
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_TYPE                   uint16_t
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_GETADDR                getAddr16
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_GETADDR                getAddr16
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_PREAMBLE(srcBM, x, y)      int scale = SkAlpha15To16(fSrcAlpha);
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S4444_Blend(dst, src, scale)
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_NEXT_ROW
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_POSTAMBLE(srcBM)
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkSpriteBlitterTemplate.h"
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8A_Opaque
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_ARGS
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_FIELDS
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_INIT
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_TYPE                   uint16_t
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_TYPE                   uint8_t
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_GETADDR                getAddr16
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_GETADDR                getAddr8
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_PREAMBLE(srcBM, x, y)      const SkPMColor* ctable = srcBM.getColorTable()->lockColors()
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S32A_Opaque_Pixel(dst, ctable[src])
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_NEXT_ROW
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlockColors(false)
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkSpriteBlitterTemplate.h"
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8A_Blend
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_ARGS                       , uint8_t alpha
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_FIELDS                     uint8_t fSrcAlpha;
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_INIT                       fSrcAlpha = alpha;
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_TYPE                   uint16_t
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_TYPE                   uint8_t
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_GETADDR                getAddr16
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_GETADDR                getAddr8
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_PREAMBLE(srcBM, x, y)      const SkPMColor* ctable = srcBM.getColorTable()->lockColors(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S32A_Blend_Pixel(dst, ctable[src], src_scale)
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_NEXT_ROW
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlockColors(false);
1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkSpriteBlitterTemplate.h"
1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
167fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reedstatic intptr_t asint(const void* ptr) {
168fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    return reinterpret_cast<const char*>(ptr) - (const char*)0;
169fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed}
170fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed
1711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void blitrow_d16_si8(uint16_t* SK_RESTRICT dst,
1721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            const uint8_t* SK_RESTRICT src, int count,
1731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            const uint16_t* SK_RESTRICT ctable) {
174fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    if (count <= 8) {
175fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        do {
176fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *dst++ = ctable[*src++];
177fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        } while (--count);
178fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        return;
179fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    }
180fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed
181fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    // eat src until we're on a 4byte boundary
182fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    while (asint(src) & 3) {
183fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        *dst++ = ctable[*src++];
184fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        count -= 1;
185fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    }
186fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed
187fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    int qcount = count >> 2;
188fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    SkASSERT(qcount > 0);
189fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    const uint32_t* qsrc = reinterpret_cast<const uint32_t*>(src);
190fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    if (asint(dst) & 2) {
191fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        do {
192fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            uint32_t s4 = *qsrc++;
193fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed#ifdef SK_CPU_LENDIAN
194fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *dst++ = ctable[s4 & 0xFF];
195fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *dst++ = ctable[(s4 >> 8) & 0xFF];
196fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *dst++ = ctable[(s4 >> 16) & 0xFF];
197fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *dst++ = ctable[s4 >> 24];
198fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed#else   // BENDIAN
199fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *dst++ = ctable[s4 >> 24];
200fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *dst++ = ctable[(s4 >> 16) & 0xFF];
201fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *dst++ = ctable[(s4 >> 8) & 0xFF];
202fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *dst++ = ctable[s4 & 0xFF];
203fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed#endif
204fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        } while (--qcount);
205fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    } else {    // dst is on a 4byte boundary
206fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        uint32_t* ddst = reinterpret_cast<uint32_t*>(dst);
207fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        do {
208fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            uint32_t s4 = *qsrc++;
209fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed#ifdef SK_CPU_LENDIAN
210fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF];
211fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF];
212fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed#else   // BENDIAN
213fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF];
214fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed            *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF];
215fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed#endif
216fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        } while (--qcount);
217fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        dst = reinterpret_cast<uint16_t*>(ddst);
218fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    }
219fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    src = reinterpret_cast<const uint8_t*>(qsrc);
220fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    count &= 3;
221fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    // catch any remaining (will be < 4)
222fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    while (--count >= 0) {
223fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed        *dst++ = ctable[*src++];
224fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed    }
225fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed}
226fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed
227fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed#define SkSPRITE_ROW_PROC(d, s, n, x, y)    blitrow_d16_si8(d, s, n, ctable)
228fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reed
2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8_Opaque
2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_ARGS
2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_FIELDS
2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_INIT
2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_TYPE                   uint16_t
2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_TYPE                   uint8_t
2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_GETADDR                getAddr16
2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_GETADDR                getAddr8
2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_PREAMBLE(srcBM, x, y)      const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache()
2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_BLIT_PIXEL(dst, src)       *dst = ctable[src]
2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_NEXT_ROW
2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlock16BitCache()
2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkSpriteBlitterTemplate.h"
2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8_Blend
2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_ARGS                       , uint8_t alpha
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_FIELDS                     uint8_t fSrcAlpha;
2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_INIT                       fSrcAlpha = alpha;
2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_TYPE                   uint16_t
2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_TYPE                   uint8_t
2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_DST_GETADDR                getAddr16
2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_SRC_GETADDR                getAddr8
2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_PREAMBLE(srcBM, x, y)      const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S16_Blend_Pixel(dst, ctable[src], src_scale)
2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_NEXT_ROW
2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlock16BitCache();
2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkSpriteBlitterTemplate.h"
2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass Sprite_D16_S32_BlitRowProc : public SkSpriteBlitter {
2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Sprite_D16_S32_BlitRowProc(const SkBitmap& source)
2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        : SkSpriteBlitter(source) {}
2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // overrides
2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void setup(const SkBitmap& device, int left, int top,
2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                       const SkPaint& paint) {
2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->INHERITED::setup(device, left, top, paint);
2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        unsigned flags = 0;
2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (paint.getAlpha() < 0xFF) {
2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            flags |= SkBlitRow::kGlobalAlpha_Flag;
2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (!fSource->isOpaque()) {
2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            flags |= SkBlitRow::kSrcPixelAlpha_Flag;
2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (paint.isDither()) {
2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            flags |= SkBlitRow::kDither_Flag;
2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void blitRect(int x, int y, int width, int height) {
2851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y);
2861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const SkPMColor* SK_RESTRICT src = fSource->getAddr32(x - fLeft,
2870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                                              y - fTop);
2880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        unsigned dstRB = fDevice->rowBytes();
2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        unsigned srcRB = fSource->rowBytes();
2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkBlitRow::Proc proc = fProc;
2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        U8CPU alpha = fPaint->getAlpha();
2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        while (--height >= 0) {
2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            proc(dst, src, width, alpha, x, y);
2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            y += 1;
2961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            dst = (uint16_t* SK_RESTRICT)((char*)dst + dstRB);
2971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            src = (const SkPMColor* SK_RESTRICT)((const char*)src + srcRB);
2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkBlitRow::Proc fProc;
3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    typedef SkSpriteBlitter INHERITED;
3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTemplatesPriv.h"
3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source,
3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                            const SkPaint& paint,
3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                            void* storage, size_t storageSize) {
3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (paint.getMaskFilter() != NULL) { // may add cases for this
3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return NULL;
3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (paint.getXfermode() != NULL) { // may add cases for this
3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return NULL;
3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (paint.getColorFilter() != NULL) { // may add cases for this
3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return NULL;
3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkSpriteBlitter* blitter = NULL;
3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned alpha = paint.getAlpha();
3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (source.getConfig()) {
3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkBitmap::kARGB_8888_Config:
3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32_BlitRowProc,
3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                  storage, storageSize, (source));
3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkBitmap::kARGB_4444_Config:
3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (255 == alpha) {
3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Opaque,
3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                      storage, storageSize, (source));
3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Blend,
3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    storage, storageSize, (source, alpha >> 4));
3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkBitmap::kRGB_565_Config:
3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (255 == alpha) {
3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Opaque,
3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                      storage, storageSize, (source));
3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Blend,
3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                      storage, storageSize, (source, alpha));
3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkBitmap::kIndex8_Config:
3513026a9ec59b285412941d278a570e382088f8adaMike Reed            if (paint.isDither()) {
3523026a9ec59b285412941d278a570e382088f8adaMike Reed                // we don't support dither yet in these special cases
3533026a9ec59b285412941d278a570e382088f8adaMike Reed                break;
3543026a9ec59b285412941d278a570e382088f8adaMike Reed            }
3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (source.isOpaque()) {
3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (255 == alpha) {
3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Opaque,
3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                          storage, storageSize, (source));
3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                } else {
3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Blend,
3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                         storage, storageSize, (source, alpha));
3620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (255 == alpha) {
3650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Opaque,
3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                          storage, storageSize, (source));
3670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                } else {
3680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Blend,
3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                         storage, storageSize, (source, alpha));
3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return blitter;
3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
378