blob: 99e392b7b986248841aab903905dcf6d8a44d4e1 [file] [log] [blame]
/* libs/graphics/sgl/SkSpriteBlitter_RGB16.cpp
**
** Copyright 2006, Google Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include "SkSpriteBlitter.h"
#include "SkTemplates.h"
#include "SkUtils.h"
#include "SkColorPriv.h"
#define D16_S32A_Opaque_Pixel(dst, sc) \
do { \
if (sc) \
{ \
unsigned srcA = SkGetPackedA32(sc); \
unsigned result = SkPixel32ToPixel16(sc); \
if (srcA != 0xFF) \
result += SkAlphaMulRGB16(*dst, SkAlpha255To256(255 - srcA)); \
*dst = SkToU16(result); \
} \
} while (0)
#define SkSPRITE_CLASSNAME Sprite_D16_S32A_Opaque
#define SkSPRITE_ARGS
#define SkSPRITE_FIELDS
#define SkSPRITE_INIT
#define SkSPRITE_DST_TYPE uint16_t
#define SkSPRITE_SRC_TYPE uint32_t
#define SkSPRITE_DST_GETADDR getAddr16
#define SkSPRITE_SRC_GETADDR getAddr32
#define SkSPRITE_PREAMBLE(srcBM, x, y)
#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Opaque_Pixel(dst, src)
#define SkSPRITE_NEXT_ROW
#define SkSPRITE_POSTAMBLE(srcBM)
#include "SkSpriteBlitterTemplate.h"
static inline void D16_S32A_Blend_Pixel_helper(U16* dst, U32 sc, unsigned src_scale)
{
uint16_t dc = *dst;
unsigned sa = SkGetPackedA32(sc);
unsigned dr, dg, db;
if (sa == 255)
{
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)
#define SkSPRITE_CLASSNAME Sprite_D16_S32A_Blend
#define SkSPRITE_ARGS , U8 alpha
#define SkSPRITE_FIELDS U8 fSrcAlpha;
#define SkSPRITE_INIT fSrcAlpha = alpha;
#define SkSPRITE_DST_TYPE uint16_t
#define SkSPRITE_SRC_TYPE uint32_t
#define SkSPRITE_DST_GETADDR getAddr16
#define SkSPRITE_SRC_GETADDR getAddr32
#define SkSPRITE_PREAMBLE(srcBM, x, y) unsigned src_scale = SkAlpha255To256(fSrcAlpha);
#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Blend_Pixel(dst, src, src_scale)
#define SkSPRITE_NEXT_ROW
#define SkSPRITE_POSTAMBLE(srcBM)
#include "SkSpriteBlitterTemplate.h"
//////////////////////////////////////////////////////////////////////////////////////////////////
#define SkSPRITE_CLASSNAME Sprite_D16_S32_Opaque
#define SkSPRITE_ARGS
#define SkSPRITE_FIELDS
#define SkSPRITE_INIT
#define SkSPRITE_DST_TYPE uint16_t
#define SkSPRITE_SRC_TYPE uint32_t
#define SkSPRITE_DST_GETADDR getAddr16
#define SkSPRITE_SRC_GETADDR getAddr32
#define SkSPRITE_PREAMBLE(srcBM, x, y)
#define SkSPRITE_BLIT_PIXEL(dst, src) *dst = SkPixel32ToPixel16_ToU16(src)
#define SkSPRITE_NEXT_ROW
#define SkSPRITE_POSTAMBLE(srcBM)
#include "SkSpriteBlitterTemplate.h"
#if 1
#define D16_S32_Blend_Pixel(dst, sc, scale) \
do { \
U16 dc = *dst; \
*dst = SkPackRGB16( SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), scale), \
SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), scale), \
SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), scale)); \
} while (0)
#else
static inline void D16_S32_Blend_Pixel(uint16_t* dst, uint32_t sc, int scale)
{
U16 dc = *dst;
*dst = SkPackRGB16( SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), scale),
SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), scale),
SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), scale));
}
#endif
#define SkSPRITE_CLASSNAME Sprite_D16_S32_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 uint32_t
#define SkSPRITE_DST_GETADDR getAddr16
#define SkSPRITE_SRC_GETADDR getAddr32
#define SkSPRITE_PREAMBLE(srcBM, x, y) int src_scale = SkAlpha255To256(fSrcAlpha);
#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32_Blend_Pixel(dst, src, src_scale)
#define SkSPRITE_NEXT_ROW
#define SkSPRITE_POSTAMBLE(srcBM)
#include "SkSpriteBlitterTemplate.h"
//////////////////////////////////////////////////////////////////////////////////////////////////
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* dst = fDevice->getAddr16(x, y);
const uint16_t* src = fSource->getAddr16(x - fLeft, y - fTop);
unsigned dstRB = fDevice->rowBytes();
unsigned 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 = SkToU16(SkBlendRGB16(sc, dc, scale)); \
} while (0)
#define SkSPRITE_CLASSNAME Sprite_D16_S16_Blend
#define SkSPRITE_ARGS , U8 alpha
#define SkSPRITE_FIELDS U8 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 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(false)
#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(false);
#include "SkSpriteBlitterTemplate.h"
//////////////////////////////////////////////////////////////////////////////////////////////////
#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"
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
#include "SkTemplatesPriv.h"
SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source, SkXfermode* mode, U8 alpha,
void* storage, size_t storageSize)
{
SkSpriteBlitter* blitter = nil;
switch (source.getConfig()) {
case SkBitmap::kARGB_8888_Config:
if (mode == nil)
{
bool srcIsOpaque = source.isOpaque();
if (alpha == 255)
{
if (srcIsOpaque)
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32_Opaque, storage, storageSize, (source));
else
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32A_Opaque, storage, storageSize, (source));
}
else
{
if (srcIsOpaque)
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32_Blend, storage, storageSize, (source, alpha));
else
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32A_Blend, storage, storageSize, (source, alpha));
}
}
break;
case SkBitmap::kRGB_565_Config:
#ifdef SK_SUPPORT_16_8_BITMAP
if (source.getA8Plane())
{
if (mode == nil)
{
if (alpha == 255)
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S816_Opaque, storage, storageSize, (source));
else
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S816_Blend, storage, storageSize, (source, alpha));
}
}
else
#endif
if (mode == nil)
{
if (alpha == 255)
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Opaque, storage, storageSize, (source));
else
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Blend, storage, storageSize, (source, alpha));
}
break;
case SkBitmap::kIndex8_Config:
if (mode == nil)
{
if (source.getColorTable()->getFlags() & SkColorTable::kColorsAreOpaque_Flag)
{
if (alpha == 255)
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Opaque, storage, storageSize, (source));
else
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Blend, storage, storageSize, (source, alpha));
}
else
{
if (alpha == 255)
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Opaque, storage, storageSize, (source));
else
SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Blend, storage, storageSize, (source, alpha));
}
}
break;
default:
break;
}
return blitter;
}