gfx/skia/trunk/src/core/SkSpriteBlitter_RGB16.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/core/SkSpriteBlitter_RGB16.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,369 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2006 The Android Open Source Project
     1.7 + *
     1.8 + * Use of this source code is governed by a BSD-style license that can be
     1.9 + * found in the LICENSE file.
    1.10 + */
    1.11 +
    1.12 +
    1.13 +#include "SkSpriteBlitter.h"
    1.14 +#include "SkBlitRow.h"
    1.15 +#include "SkTemplates.h"
    1.16 +#include "SkUtils.h"
    1.17 +#include "SkColorPriv.h"
    1.18 +
    1.19 +#define D16_S32A_Opaque_Pixel(dst, sc)                                        \
    1.20 +do {                                                                          \
    1.21 +    if (sc) {                                                                 \
    1.22 +        *dst = SkSrcOver32To16(sc, *dst);                                     \
    1.23 +    }                                                                         \
    1.24 +} while (0)
    1.25 +
    1.26 +static inline void D16_S32A_Blend_Pixel_helper(uint16_t* dst, SkPMColor sc,
    1.27 +                                               unsigned src_scale) {
    1.28 +    uint16_t dc = *dst;
    1.29 +    unsigned sa = SkGetPackedA32(sc);
    1.30 +    unsigned dr, dg, db;
    1.31 +
    1.32 +    if (255 == sa) {
    1.33 +        dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale);
    1.34 +        dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale);
    1.35 +        db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale);
    1.36 +    } else {
    1.37 +        unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale);
    1.38 +        dr = (SkPacked32ToR16(sc) * src_scale +
    1.39 +              SkGetPackedR16(dc) * dst_scale) >> 8;
    1.40 +        dg = (SkPacked32ToG16(sc) * src_scale +
    1.41 +              SkGetPackedG16(dc) * dst_scale) >> 8;
    1.42 +        db = (SkPacked32ToB16(sc) * src_scale +
    1.43 +              SkGetPackedB16(dc) * dst_scale) >> 8;
    1.44 +    }
    1.45 +    *dst = SkPackRGB16(dr, dg, db);
    1.46 +}
    1.47 +
    1.48 +#define D16_S32A_Blend_Pixel(dst, sc, src_scale) \
    1.49 +    do { if (sc) D16_S32A_Blend_Pixel_helper(dst, sc, src_scale); } while (0)
    1.50 +
    1.51 +
    1.52 +///////////////////////////////////////////////////////////////////////////////
    1.53 +
    1.54 +class Sprite_D16_S16_Opaque : public SkSpriteBlitter {
    1.55 +public:
    1.56 +    Sprite_D16_S16_Opaque(const SkBitmap& source)
    1.57 +        : SkSpriteBlitter(source) {}
    1.58 +
    1.59 +    // overrides
    1.60 +    virtual void blitRect(int x, int y, int width, int height) {
    1.61 +        uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y);
    1.62 +        const uint16_t* SK_RESTRICT src = fSource->getAddr16(x - fLeft,
    1.63 +                                                             y - fTop);
    1.64 +        size_t dstRB = fDevice->rowBytes();
    1.65 +        size_t srcRB = fSource->rowBytes();
    1.66 +
    1.67 +        while (--height >= 0) {
    1.68 +            memcpy(dst, src, width << 1);
    1.69 +            dst = (uint16_t*)((char*)dst + dstRB);
    1.70 +            src = (const uint16_t*)((const char*)src + srcRB);
    1.71 +        }
    1.72 +    }
    1.73 +};
    1.74 +
    1.75 +#define D16_S16_Blend_Pixel(dst, sc, scale)     \
    1.76 +    do {                                        \
    1.77 +        uint16_t dc = *dst;                     \
    1.78 +        *dst = SkBlendRGB16(sc, dc, scale);     \
    1.79 +    } while (0)
    1.80 +
    1.81 +#define SkSPRITE_CLASSNAME                  Sprite_D16_S16_Blend
    1.82 +#define SkSPRITE_ARGS                       , uint8_t alpha
    1.83 +#define SkSPRITE_FIELDS                     uint8_t  fSrcAlpha;
    1.84 +#define SkSPRITE_INIT                       fSrcAlpha = alpha;
    1.85 +#define SkSPRITE_DST_TYPE                   uint16_t
    1.86 +#define SkSPRITE_SRC_TYPE                   uint16_t
    1.87 +#define SkSPRITE_DST_GETADDR                getAddr16
    1.88 +#define SkSPRITE_SRC_GETADDR                getAddr16
    1.89 +#define SkSPRITE_PREAMBLE(srcBM, x, y)      int scale = SkAlpha255To256(fSrcAlpha);
    1.90 +#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S16_Blend_Pixel(dst, src, scale)
    1.91 +#define SkSPRITE_NEXT_ROW
    1.92 +#define SkSPRITE_POSTAMBLE(srcBM)
    1.93 +#include "SkSpriteBlitterTemplate.h"
    1.94 +
    1.95 +///////////////////////////////////////////////////////////////////////////////
    1.96 +
    1.97 +#define D16_S4444_Opaque(dst, sc)           \
    1.98 +    do {                                    \
    1.99 +        uint16_t dc = *dst;                 \
   1.100 +        *dst = SkSrcOver4444To16(sc, dc);   \
   1.101 +    } while (0)
   1.102 +
   1.103 +#define SkSPRITE_CLASSNAME                  Sprite_D16_S4444_Opaque
   1.104 +#define SkSPRITE_ARGS
   1.105 +#define SkSPRITE_FIELDS
   1.106 +#define SkSPRITE_INIT
   1.107 +#define SkSPRITE_DST_TYPE                   uint16_t
   1.108 +#define SkSPRITE_SRC_TYPE                   SkPMColor16
   1.109 +#define SkSPRITE_DST_GETADDR                getAddr16
   1.110 +#define SkSPRITE_SRC_GETADDR                getAddr16
   1.111 +#define SkSPRITE_PREAMBLE(srcBM, x, y)
   1.112 +#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S4444_Opaque(dst, src)
   1.113 +#define SkSPRITE_NEXT_ROW
   1.114 +#define SkSPRITE_POSTAMBLE(srcBM)
   1.115 +#include "SkSpriteBlitterTemplate.h"
   1.116 +
   1.117 +#define D16_S4444_Blend(dst, sc, scale16)           \
   1.118 +    do {                                            \
   1.119 +        uint16_t dc = *dst;                         \
   1.120 +        *dst = SkBlend4444To16(sc, dc, scale16);    \
   1.121 +    } while (0)
   1.122 +
   1.123 +
   1.124 +#define SkSPRITE_CLASSNAME                  Sprite_D16_S4444_Blend
   1.125 +#define SkSPRITE_ARGS                       , uint8_t alpha
   1.126 +#define SkSPRITE_FIELDS                     uint8_t  fSrcAlpha;
   1.127 +#define SkSPRITE_INIT                       fSrcAlpha = alpha;
   1.128 +#define SkSPRITE_DST_TYPE                   uint16_t
   1.129 +#define SkSPRITE_SRC_TYPE                   uint16_t
   1.130 +#define SkSPRITE_DST_GETADDR                getAddr16
   1.131 +#define SkSPRITE_SRC_GETADDR                getAddr16
   1.132 +#define SkSPRITE_PREAMBLE(srcBM, x, y)      int scale = SkAlpha15To16(fSrcAlpha);
   1.133 +#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S4444_Blend(dst, src, scale)
   1.134 +#define SkSPRITE_NEXT_ROW
   1.135 +#define SkSPRITE_POSTAMBLE(srcBM)
   1.136 +#include "SkSpriteBlitterTemplate.h"
   1.137 +
   1.138 +///////////////////////////////////////////////////////////////////////////////
   1.139 +
   1.140 +#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8A_Opaque
   1.141 +#define SkSPRITE_ARGS
   1.142 +#define SkSPRITE_FIELDS
   1.143 +#define SkSPRITE_INIT
   1.144 +#define SkSPRITE_DST_TYPE                   uint16_t
   1.145 +#define SkSPRITE_SRC_TYPE                   uint8_t
   1.146 +#define SkSPRITE_DST_GETADDR                getAddr16
   1.147 +#define SkSPRITE_SRC_GETADDR                getAddr8
   1.148 +#define SkSPRITE_PREAMBLE(srcBM, x, y)      const SkPMColor* ctable = srcBM.getColorTable()->lockColors()
   1.149 +#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S32A_Opaque_Pixel(dst, ctable[src])
   1.150 +#define SkSPRITE_NEXT_ROW
   1.151 +#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlockColors()
   1.152 +#include "SkSpriteBlitterTemplate.h"
   1.153 +
   1.154 +#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8A_Blend
   1.155 +#define SkSPRITE_ARGS                       , uint8_t alpha
   1.156 +#define SkSPRITE_FIELDS                     uint8_t fSrcAlpha;
   1.157 +#define SkSPRITE_INIT                       fSrcAlpha = alpha;
   1.158 +#define SkSPRITE_DST_TYPE                   uint16_t
   1.159 +#define SkSPRITE_SRC_TYPE                   uint8_t
   1.160 +#define SkSPRITE_DST_GETADDR                getAddr16
   1.161 +#define SkSPRITE_SRC_GETADDR                getAddr8
   1.162 +#define SkSPRITE_PREAMBLE(srcBM, x, y)      const SkPMColor* ctable = srcBM.getColorTable()->lockColors(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
   1.163 +#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S32A_Blend_Pixel(dst, ctable[src], src_scale)
   1.164 +#define SkSPRITE_NEXT_ROW
   1.165 +#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlockColors();
   1.166 +#include "SkSpriteBlitterTemplate.h"
   1.167 +
   1.168 +///////////////////////////////////////////////////////////////////////////////
   1.169 +
   1.170 +static intptr_t asint(const void* ptr) {
   1.171 +    return reinterpret_cast<const char*>(ptr) - (const char*)0;
   1.172 +}
   1.173 +
   1.174 +static void blitrow_d16_si8(uint16_t* SK_RESTRICT dst,
   1.175 +                            const uint8_t* SK_RESTRICT src, int count,
   1.176 +                            const uint16_t* SK_RESTRICT ctable) {
   1.177 +    if (count <= 8) {
   1.178 +        do {
   1.179 +            *dst++ = ctable[*src++];
   1.180 +        } while (--count);
   1.181 +        return;
   1.182 +    }
   1.183 +
   1.184 +    // eat src until we're on a 4byte boundary
   1.185 +    while (asint(src) & 3) {
   1.186 +        *dst++ = ctable[*src++];
   1.187 +        count -= 1;
   1.188 +    }
   1.189 +
   1.190 +    int qcount = count >> 2;
   1.191 +    SkASSERT(qcount > 0);
   1.192 +    const uint32_t* qsrc = reinterpret_cast<const uint32_t*>(src);
   1.193 +    if (asint(dst) & 2) {
   1.194 +        do {
   1.195 +            uint32_t s4 = *qsrc++;
   1.196 +#ifdef SK_CPU_LENDIAN
   1.197 +            *dst++ = ctable[s4 & 0xFF];
   1.198 +            *dst++ = ctable[(s4 >> 8) & 0xFF];
   1.199 +            *dst++ = ctable[(s4 >> 16) & 0xFF];
   1.200 +            *dst++ = ctable[s4 >> 24];
   1.201 +#else   // BENDIAN
   1.202 +            *dst++ = ctable[s4 >> 24];
   1.203 +            *dst++ = ctable[(s4 >> 16) & 0xFF];
   1.204 +            *dst++ = ctable[(s4 >> 8) & 0xFF];
   1.205 +            *dst++ = ctable[s4 & 0xFF];
   1.206 +#endif
   1.207 +        } while (--qcount);
   1.208 +    } else {    // dst is on a 4byte boundary
   1.209 +        uint32_t* ddst = reinterpret_cast<uint32_t*>(dst);
   1.210 +        do {
   1.211 +            uint32_t s4 = *qsrc++;
   1.212 +#ifdef SK_CPU_LENDIAN
   1.213 +            *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF];
   1.214 +            *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF];
   1.215 +#else   // BENDIAN
   1.216 +            *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF];
   1.217 +            *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF];
   1.218 +#endif
   1.219 +        } while (--qcount);
   1.220 +        dst = reinterpret_cast<uint16_t*>(ddst);
   1.221 +    }
   1.222 +    src = reinterpret_cast<const uint8_t*>(qsrc);
   1.223 +    count &= 3;
   1.224 +    // catch any remaining (will be < 4)
   1.225 +    while (--count >= 0) {
   1.226 +        *dst++ = ctable[*src++];
   1.227 +    }
   1.228 +}
   1.229 +
   1.230 +#define SkSPRITE_ROW_PROC(d, s, n, x, y)    blitrow_d16_si8(d, s, n, ctable)
   1.231 +
   1.232 +#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8_Opaque
   1.233 +#define SkSPRITE_ARGS
   1.234 +#define SkSPRITE_FIELDS
   1.235 +#define SkSPRITE_INIT
   1.236 +#define SkSPRITE_DST_TYPE                   uint16_t
   1.237 +#define SkSPRITE_SRC_TYPE                   uint8_t
   1.238 +#define SkSPRITE_DST_GETADDR                getAddr16
   1.239 +#define SkSPRITE_SRC_GETADDR                getAddr8
   1.240 +#define SkSPRITE_PREAMBLE(srcBM, x, y)      const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache()
   1.241 +#define SkSPRITE_BLIT_PIXEL(dst, src)       *dst = ctable[src]
   1.242 +#define SkSPRITE_NEXT_ROW
   1.243 +#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlock16BitCache()
   1.244 +#include "SkSpriteBlitterTemplate.h"
   1.245 +
   1.246 +#define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8_Blend
   1.247 +#define SkSPRITE_ARGS                       , uint8_t alpha
   1.248 +#define SkSPRITE_FIELDS                     uint8_t fSrcAlpha;
   1.249 +#define SkSPRITE_INIT                       fSrcAlpha = alpha;
   1.250 +#define SkSPRITE_DST_TYPE                   uint16_t
   1.251 +#define SkSPRITE_SRC_TYPE                   uint8_t
   1.252 +#define SkSPRITE_DST_GETADDR                getAddr16
   1.253 +#define SkSPRITE_SRC_GETADDR                getAddr8
   1.254 +#define SkSPRITE_PREAMBLE(srcBM, x, y)      const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
   1.255 +#define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S16_Blend_Pixel(dst, ctable[src], src_scale)
   1.256 +#define SkSPRITE_NEXT_ROW
   1.257 +#define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlock16BitCache();
   1.258 +#include "SkSpriteBlitterTemplate.h"
   1.259 +
   1.260 +///////////////////////////////////////////////////////////////////////////////
   1.261 +
   1.262 +class Sprite_D16_S32_BlitRowProc : public SkSpriteBlitter {
   1.263 +public:
   1.264 +    Sprite_D16_S32_BlitRowProc(const SkBitmap& source)
   1.265 +        : SkSpriteBlitter(source) {}
   1.266 +
   1.267 +    // overrides
   1.268 +
   1.269 +    virtual void setup(const SkBitmap& device, int left, int top,
   1.270 +                       const SkPaint& paint) {
   1.271 +        this->INHERITED::setup(device, left, top, paint);
   1.272 +
   1.273 +        unsigned flags = 0;
   1.274 +
   1.275 +        if (paint.getAlpha() < 0xFF) {
   1.276 +            flags |= SkBlitRow::kGlobalAlpha_Flag;
   1.277 +        }
   1.278 +        if (!fSource->isOpaque()) {
   1.279 +            flags |= SkBlitRow::kSrcPixelAlpha_Flag;
   1.280 +        }
   1.281 +        if (paint.isDither()) {
   1.282 +            flags |= SkBlitRow::kDither_Flag;
   1.283 +        }
   1.284 +        fProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
   1.285 +    }
   1.286 +
   1.287 +    virtual void blitRect(int x, int y, int width, int height) {
   1.288 +        uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y);
   1.289 +        const SkPMColor* SK_RESTRICT src = fSource->getAddr32(x - fLeft,
   1.290 +                                                              y - fTop);
   1.291 +        size_t dstRB = fDevice->rowBytes();
   1.292 +        size_t srcRB = fSource->rowBytes();
   1.293 +        SkBlitRow::Proc proc = fProc;
   1.294 +        U8CPU alpha = fPaint->getAlpha();
   1.295 +
   1.296 +        while (--height >= 0) {
   1.297 +            proc(dst, src, width, alpha, x, y);
   1.298 +            y += 1;
   1.299 +            dst = (uint16_t* SK_RESTRICT)((char*)dst + dstRB);
   1.300 +            src = (const SkPMColor* SK_RESTRICT)((const char*)src + srcRB);
   1.301 +        }
   1.302 +    }
   1.303 +
   1.304 +private:
   1.305 +    SkBlitRow::Proc fProc;
   1.306 +
   1.307 +    typedef SkSpriteBlitter INHERITED;
   1.308 +};
   1.309 +
   1.310 +///////////////////////////////////////////////////////////////////////////////
   1.311 +
   1.312 +SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source, const SkPaint& paint,
   1.313 +        SkTBlitterAllocator* allocator) {
   1.314 +
   1.315 +    SkASSERT(allocator != NULL);
   1.316 +
   1.317 +    if (paint.getMaskFilter() != NULL) { // may add cases for this
   1.318 +        return NULL;
   1.319 +    }
   1.320 +    if (paint.getXfermode() != NULL) { // may add cases for this
   1.321 +        return NULL;
   1.322 +    }
   1.323 +    if (paint.getColorFilter() != NULL) { // may add cases for this
   1.324 +        return NULL;
   1.325 +    }
   1.326 +
   1.327 +    SkSpriteBlitter* blitter = NULL;
   1.328 +    unsigned alpha = paint.getAlpha();
   1.329 +
   1.330 +    switch (source.colorType()) {
   1.331 +        case kPMColor_SkColorType: {
   1.332 +            blitter = allocator->createT<Sprite_D16_S32_BlitRowProc>(source);
   1.333 +            break;
   1.334 +        }
   1.335 +        case kARGB_4444_SkColorType:
   1.336 +            if (255 == alpha) {
   1.337 +                blitter = allocator->createT<Sprite_D16_S4444_Opaque>(source);
   1.338 +            } else {
   1.339 +                blitter = allocator->createT<Sprite_D16_S4444_Blend>(source, alpha >> 4);
   1.340 +            }
   1.341 +            break;
   1.342 +        case kRGB_565_SkColorType:
   1.343 +            if (255 == alpha) {
   1.344 +                blitter = allocator->createT<Sprite_D16_S16_Opaque>(source);
   1.345 +            } else {
   1.346 +                blitter = allocator->createT<Sprite_D16_S16_Blend>(source, alpha);
   1.347 +            }
   1.348 +            break;
   1.349 +        case kIndex_8_SkColorType:
   1.350 +            if (paint.isDither()) {
   1.351 +                // we don't support dither yet in these special cases
   1.352 +                break;
   1.353 +            }
   1.354 +            if (source.isOpaque()) {
   1.355 +                if (255 == alpha) {
   1.356 +                    blitter = allocator->createT<Sprite_D16_SIndex8_Opaque>(source);
   1.357 +                } else {
   1.358 +                    blitter = allocator->createT<Sprite_D16_SIndex8_Blend>(source, alpha);
   1.359 +                }
   1.360 +            } else {
   1.361 +                if (255 == alpha) {
   1.362 +                    blitter = allocator->createT<Sprite_D16_SIndex8A_Opaque>(source);
   1.363 +                } else {
   1.364 +                    blitter = allocator->createT<Sprite_D16_SIndex8A_Blend>(source, alpha);
   1.365 +                }
   1.366 +            }
   1.367 +            break;
   1.368 +        default:
   1.369 +            break;
   1.370 +    }
   1.371 +    return blitter;
   1.372 +}

mercurial