diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/core/SkSpriteBlitter_RGB16.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/core/SkSpriteBlitter_RGB16.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,369 @@ + +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#include "SkSpriteBlitter.h" +#include "SkBlitRow.h" +#include "SkTemplates.h" +#include "SkUtils.h" +#include "SkColorPriv.h" + +#define D16_S32A_Opaque_Pixel(dst, sc) \ +do { \ + if (sc) { \ + *dst = SkSrcOver32To16(sc, *dst); \ + } \ +} while (0) + +static inline void D16_S32A_Blend_Pixel_helper(uint16_t* dst, SkPMColor sc, + unsigned src_scale) { + uint16_t dc = *dst; + unsigned sa = SkGetPackedA32(sc); + unsigned dr, dg, db; + + if (255 == sa) { + dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale); + dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale); + db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale); + } else { + unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale); + dr = (SkPacked32ToR16(sc) * src_scale + + SkGetPackedR16(dc) * dst_scale) >> 8; + dg = (SkPacked32ToG16(sc) * src_scale + + SkGetPackedG16(dc) * dst_scale) >> 8; + db = (SkPacked32ToB16(sc) * src_scale + + SkGetPackedB16(dc) * dst_scale) >> 8; + } + *dst = SkPackRGB16(dr, dg, db); +} + +#define D16_S32A_Blend_Pixel(dst, sc, src_scale) \ + do { if (sc) D16_S32A_Blend_Pixel_helper(dst, sc, src_scale); } while (0) + + +/////////////////////////////////////////////////////////////////////////////// + +class Sprite_D16_S16_Opaque : public SkSpriteBlitter { +public: + Sprite_D16_S16_Opaque(const SkBitmap& source) + : SkSpriteBlitter(source) {} + + // overrides + virtual void blitRect(int x, int y, int width, int height) { + uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y); + const uint16_t* SK_RESTRICT src = fSource->getAddr16(x - fLeft, + y - fTop); + size_t dstRB = fDevice->rowBytes(); + size_t srcRB = fSource->rowBytes(); + + while (--height >= 0) { + memcpy(dst, src, width << 1); + dst = (uint16_t*)((char*)dst + dstRB); + src = (const uint16_t*)((const char*)src + srcRB); + } + } +}; + +#define D16_S16_Blend_Pixel(dst, sc, scale) \ + do { \ + uint16_t dc = *dst; \ + *dst = SkBlendRGB16(sc, dc, scale); \ + } while (0) + +#define SkSPRITE_CLASSNAME Sprite_D16_S16_Blend +#define SkSPRITE_ARGS , uint8_t alpha +#define SkSPRITE_FIELDS uint8_t fSrcAlpha; +#define SkSPRITE_INIT fSrcAlpha = alpha; +#define SkSPRITE_DST_TYPE uint16_t +#define SkSPRITE_SRC_TYPE uint16_t +#define SkSPRITE_DST_GETADDR getAddr16 +#define SkSPRITE_SRC_GETADDR getAddr16 +#define SkSPRITE_PREAMBLE(srcBM, x, y) int scale = SkAlpha255To256(fSrcAlpha); +#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S16_Blend_Pixel(dst, src, scale) +#define SkSPRITE_NEXT_ROW +#define SkSPRITE_POSTAMBLE(srcBM) +#include "SkSpriteBlitterTemplate.h" + +/////////////////////////////////////////////////////////////////////////////// + +#define D16_S4444_Opaque(dst, sc) \ + do { \ + uint16_t dc = *dst; \ + *dst = SkSrcOver4444To16(sc, dc); \ + } while (0) + +#define SkSPRITE_CLASSNAME Sprite_D16_S4444_Opaque +#define SkSPRITE_ARGS +#define SkSPRITE_FIELDS +#define SkSPRITE_INIT +#define SkSPRITE_DST_TYPE uint16_t +#define SkSPRITE_SRC_TYPE SkPMColor16 +#define SkSPRITE_DST_GETADDR getAddr16 +#define SkSPRITE_SRC_GETADDR getAddr16 +#define SkSPRITE_PREAMBLE(srcBM, x, y) +#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S4444_Opaque(dst, src) +#define SkSPRITE_NEXT_ROW +#define SkSPRITE_POSTAMBLE(srcBM) +#include "SkSpriteBlitterTemplate.h" + +#define D16_S4444_Blend(dst, sc, scale16) \ + do { \ + uint16_t dc = *dst; \ + *dst = SkBlend4444To16(sc, dc, scale16); \ + } while (0) + + +#define SkSPRITE_CLASSNAME Sprite_D16_S4444_Blend +#define SkSPRITE_ARGS , uint8_t alpha +#define SkSPRITE_FIELDS uint8_t fSrcAlpha; +#define SkSPRITE_INIT fSrcAlpha = alpha; +#define SkSPRITE_DST_TYPE uint16_t +#define SkSPRITE_SRC_TYPE uint16_t +#define SkSPRITE_DST_GETADDR getAddr16 +#define SkSPRITE_SRC_GETADDR getAddr16 +#define SkSPRITE_PREAMBLE(srcBM, x, y) int scale = SkAlpha15To16(fSrcAlpha); +#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S4444_Blend(dst, src, scale) +#define SkSPRITE_NEXT_ROW +#define SkSPRITE_POSTAMBLE(srcBM) +#include "SkSpriteBlitterTemplate.h" + +/////////////////////////////////////////////////////////////////////////////// + +#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8A_Opaque +#define SkSPRITE_ARGS +#define SkSPRITE_FIELDS +#define SkSPRITE_INIT +#define SkSPRITE_DST_TYPE uint16_t +#define SkSPRITE_SRC_TYPE uint8_t +#define SkSPRITE_DST_GETADDR getAddr16 +#define SkSPRITE_SRC_GETADDR getAddr8 +#define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.getColorTable()->lockColors() +#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Opaque_Pixel(dst, ctable[src]) +#define SkSPRITE_NEXT_ROW +#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors() +#include "SkSpriteBlitterTemplate.h" + +#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8A_Blend +#define SkSPRITE_ARGS , uint8_t alpha +#define SkSPRITE_FIELDS uint8_t fSrcAlpha; +#define SkSPRITE_INIT fSrcAlpha = alpha; +#define SkSPRITE_DST_TYPE uint16_t +#define SkSPRITE_SRC_TYPE uint8_t +#define SkSPRITE_DST_GETADDR getAddr16 +#define SkSPRITE_SRC_GETADDR getAddr8 +#define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.getColorTable()->lockColors(); unsigned src_scale = SkAlpha255To256(fSrcAlpha); +#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Blend_Pixel(dst, ctable[src], src_scale) +#define SkSPRITE_NEXT_ROW +#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors(); +#include "SkSpriteBlitterTemplate.h" + +/////////////////////////////////////////////////////////////////////////////// + +static intptr_t asint(const void* ptr) { + return reinterpret_cast(ptr) - (const char*)0; +} + +static void blitrow_d16_si8(uint16_t* SK_RESTRICT dst, + const uint8_t* SK_RESTRICT src, int count, + const uint16_t* SK_RESTRICT ctable) { + if (count <= 8) { + do { + *dst++ = ctable[*src++]; + } while (--count); + return; + } + + // eat src until we're on a 4byte boundary + while (asint(src) & 3) { + *dst++ = ctable[*src++]; + count -= 1; + } + + int qcount = count >> 2; + SkASSERT(qcount > 0); + const uint32_t* qsrc = reinterpret_cast(src); + if (asint(dst) & 2) { + do { + uint32_t s4 = *qsrc++; +#ifdef SK_CPU_LENDIAN + *dst++ = ctable[s4 & 0xFF]; + *dst++ = ctable[(s4 >> 8) & 0xFF]; + *dst++ = ctable[(s4 >> 16) & 0xFF]; + *dst++ = ctable[s4 >> 24]; +#else // BENDIAN + *dst++ = ctable[s4 >> 24]; + *dst++ = ctable[(s4 >> 16) & 0xFF]; + *dst++ = ctable[(s4 >> 8) & 0xFF]; + *dst++ = ctable[s4 & 0xFF]; +#endif + } while (--qcount); + } else { // dst is on a 4byte boundary + uint32_t* ddst = reinterpret_cast(dst); + do { + uint32_t s4 = *qsrc++; +#ifdef SK_CPU_LENDIAN + *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF]; + *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF]; +#else // BENDIAN + *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF]; + *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF]; +#endif + } while (--qcount); + dst = reinterpret_cast(ddst); + } + src = reinterpret_cast(qsrc); + count &= 3; + // catch any remaining (will be < 4) + while (--count >= 0) { + *dst++ = ctable[*src++]; + } +} + +#define SkSPRITE_ROW_PROC(d, s, n, x, y) blitrow_d16_si8(d, s, n, ctable) + +#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8_Opaque +#define SkSPRITE_ARGS +#define SkSPRITE_FIELDS +#define SkSPRITE_INIT +#define SkSPRITE_DST_TYPE uint16_t +#define SkSPRITE_SRC_TYPE uint8_t +#define SkSPRITE_DST_GETADDR getAddr16 +#define SkSPRITE_SRC_GETADDR getAddr8 +#define SkSPRITE_PREAMBLE(srcBM, x, y) const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache() +#define SkSPRITE_BLIT_PIXEL(dst, src) *dst = ctable[src] +#define SkSPRITE_NEXT_ROW +#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlock16BitCache() +#include "SkSpriteBlitterTemplate.h" + +#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8_Blend +#define SkSPRITE_ARGS , uint8_t alpha +#define SkSPRITE_FIELDS uint8_t fSrcAlpha; +#define SkSPRITE_INIT fSrcAlpha = alpha; +#define SkSPRITE_DST_TYPE uint16_t +#define SkSPRITE_SRC_TYPE uint8_t +#define SkSPRITE_DST_GETADDR getAddr16 +#define SkSPRITE_SRC_GETADDR getAddr8 +#define SkSPRITE_PREAMBLE(srcBM, x, y) const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache(); unsigned src_scale = SkAlpha255To256(fSrcAlpha); +#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S16_Blend_Pixel(dst, ctable[src], src_scale) +#define SkSPRITE_NEXT_ROW +#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlock16BitCache(); +#include "SkSpriteBlitterTemplate.h" + +/////////////////////////////////////////////////////////////////////////////// + +class Sprite_D16_S32_BlitRowProc : public SkSpriteBlitter { +public: + Sprite_D16_S32_BlitRowProc(const SkBitmap& source) + : SkSpriteBlitter(source) {} + + // overrides + + virtual void setup(const SkBitmap& device, int left, int top, + const SkPaint& paint) { + this->INHERITED::setup(device, left, top, paint); + + unsigned flags = 0; + + if (paint.getAlpha() < 0xFF) { + flags |= SkBlitRow::kGlobalAlpha_Flag; + } + if (!fSource->isOpaque()) { + flags |= SkBlitRow::kSrcPixelAlpha_Flag; + } + if (paint.isDither()) { + flags |= SkBlitRow::kDither_Flag; + } + fProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config); + } + + virtual void blitRect(int x, int y, int width, int height) { + uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y); + const SkPMColor* SK_RESTRICT src = fSource->getAddr32(x - fLeft, + y - fTop); + size_t dstRB = fDevice->rowBytes(); + size_t srcRB = fSource->rowBytes(); + SkBlitRow::Proc proc = fProc; + U8CPU alpha = fPaint->getAlpha(); + + while (--height >= 0) { + proc(dst, src, width, alpha, x, y); + y += 1; + dst = (uint16_t* SK_RESTRICT)((char*)dst + dstRB); + src = (const SkPMColor* SK_RESTRICT)((const char*)src + srcRB); + } + } + +private: + SkBlitRow::Proc fProc; + + typedef SkSpriteBlitter INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + +SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source, const SkPaint& paint, + SkTBlitterAllocator* allocator) { + + SkASSERT(allocator != NULL); + + if (paint.getMaskFilter() != NULL) { // may add cases for this + return NULL; + } + if (paint.getXfermode() != NULL) { // may add cases for this + return NULL; + } + if (paint.getColorFilter() != NULL) { // may add cases for this + return NULL; + } + + SkSpriteBlitter* blitter = NULL; + unsigned alpha = paint.getAlpha(); + + switch (source.colorType()) { + case kPMColor_SkColorType: { + blitter = allocator->createT(source); + break; + } + case kARGB_4444_SkColorType: + if (255 == alpha) { + blitter = allocator->createT(source); + } else { + blitter = allocator->createT(source, alpha >> 4); + } + break; + case kRGB_565_SkColorType: + if (255 == alpha) { + blitter = allocator->createT(source); + } else { + blitter = allocator->createT(source, alpha); + } + break; + case kIndex_8_SkColorType: + if (paint.isDither()) { + // we don't support dither yet in these special cases + break; + } + if (source.isOpaque()) { + if (255 == alpha) { + blitter = allocator->createT(source); + } else { + blitter = allocator->createT(source, alpha); + } + } else { + if (255 == alpha) { + blitter = allocator->createT(source); + } else { + blitter = allocator->createT(source, alpha); + } + } + break; + default: + break; + } + return blitter; +}