1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkSpriteBlitter_ARGB32.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,307 @@ 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 "SkColorFilter.h" 1.16 +#include "SkColorPriv.h" 1.17 +#include "SkTemplates.h" 1.18 +#include "SkUtils.h" 1.19 +#include "SkXfermode.h" 1.20 + 1.21 +/////////////////////////////////////////////////////////////////////////////// 1.22 + 1.23 +class Sprite_D32_S32 : public SkSpriteBlitter { 1.24 +public: 1.25 + Sprite_D32_S32(const SkBitmap& src, U8CPU alpha) : INHERITED(src) { 1.26 + SkASSERT(src.colorType() == kPMColor_SkColorType); 1.27 + 1.28 + unsigned flags32 = 0; 1.29 + if (255 != alpha) { 1.30 + flags32 |= SkBlitRow::kGlobalAlpha_Flag32; 1.31 + } 1.32 + if (!src.isOpaque()) { 1.33 + flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; 1.34 + } 1.35 + 1.36 + fProc32 = SkBlitRow::Factory32(flags32); 1.37 + fAlpha = alpha; 1.38 + } 1.39 + 1.40 + virtual void blitRect(int x, int y, int width, int height) { 1.41 + SkASSERT(width > 0 && height > 0); 1.42 + uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y); 1.43 + const uint32_t* SK_RESTRICT src = fSource->getAddr32(x - fLeft, 1.44 + y - fTop); 1.45 + size_t dstRB = fDevice->rowBytes(); 1.46 + size_t srcRB = fSource->rowBytes(); 1.47 + SkBlitRow::Proc32 proc = fProc32; 1.48 + U8CPU alpha = fAlpha; 1.49 + 1.50 + do { 1.51 + proc(dst, src, width, alpha); 1.52 + dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); 1.53 + src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); 1.54 + } while (--height != 0); 1.55 + } 1.56 + 1.57 +private: 1.58 + SkBlitRow::Proc32 fProc32; 1.59 + U8CPU fAlpha; 1.60 + 1.61 + typedef SkSpriteBlitter INHERITED; 1.62 +}; 1.63 + 1.64 +/////////////////////////////////////////////////////////////////////////////// 1.65 + 1.66 +class Sprite_D32_XferFilter : public SkSpriteBlitter { 1.67 +public: 1.68 + Sprite_D32_XferFilter(const SkBitmap& source, const SkPaint& paint) 1.69 + : SkSpriteBlitter(source) { 1.70 + fColorFilter = paint.getColorFilter(); 1.71 + SkSafeRef(fColorFilter); 1.72 + 1.73 + fXfermode = paint.getXfermode(); 1.74 + SkSafeRef(fXfermode); 1.75 + 1.76 + fBufferSize = 0; 1.77 + fBuffer = NULL; 1.78 + 1.79 + unsigned flags32 = 0; 1.80 + if (255 != paint.getAlpha()) { 1.81 + flags32 |= SkBlitRow::kGlobalAlpha_Flag32; 1.82 + } 1.83 + if (!source.isOpaque()) { 1.84 + flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; 1.85 + } 1.86 + 1.87 + fProc32 = SkBlitRow::Factory32(flags32); 1.88 + fAlpha = paint.getAlpha(); 1.89 + } 1.90 + 1.91 + virtual ~Sprite_D32_XferFilter() { 1.92 + delete[] fBuffer; 1.93 + SkSafeUnref(fXfermode); 1.94 + SkSafeUnref(fColorFilter); 1.95 + } 1.96 + 1.97 + virtual void setup(const SkBitmap& device, int left, int top, 1.98 + const SkPaint& paint) { 1.99 + this->INHERITED::setup(device, left, top, paint); 1.100 + 1.101 + int width = device.width(); 1.102 + if (width > fBufferSize) { 1.103 + fBufferSize = width; 1.104 + delete[] fBuffer; 1.105 + fBuffer = new SkPMColor[width]; 1.106 + } 1.107 + } 1.108 + 1.109 +protected: 1.110 + SkColorFilter* fColorFilter; 1.111 + SkXfermode* fXfermode; 1.112 + int fBufferSize; 1.113 + SkPMColor* fBuffer; 1.114 + SkBlitRow::Proc32 fProc32; 1.115 + U8CPU fAlpha; 1.116 + 1.117 +private: 1.118 + typedef SkSpriteBlitter INHERITED; 1.119 +}; 1.120 + 1.121 +/////////////////////////////////////////////////////////////////////////////// 1.122 + 1.123 +class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter { 1.124 +public: 1.125 + Sprite_D32_S32A_XferFilter(const SkBitmap& source, const SkPaint& paint) 1.126 + : Sprite_D32_XferFilter(source, paint) {} 1.127 + 1.128 + virtual void blitRect(int x, int y, int width, int height) { 1.129 + SkASSERT(width > 0 && height > 0); 1.130 + uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y); 1.131 + const uint32_t* SK_RESTRICT src = fSource->getAddr32(x - fLeft, 1.132 + y - fTop); 1.133 + size_t dstRB = fDevice->rowBytes(); 1.134 + size_t srcRB = fSource->rowBytes(); 1.135 + SkColorFilter* colorFilter = fColorFilter; 1.136 + SkXfermode* xfermode = fXfermode; 1.137 + 1.138 + do { 1.139 + const SkPMColor* tmp = src; 1.140 + 1.141 + if (NULL != colorFilter) { 1.142 + colorFilter->filterSpan(src, width, fBuffer); 1.143 + tmp = fBuffer; 1.144 + } 1.145 + 1.146 + if (NULL != xfermode) { 1.147 + xfermode->xfer32(dst, tmp, width, NULL); 1.148 + } else { 1.149 + fProc32(dst, tmp, width, fAlpha); 1.150 + } 1.151 + 1.152 + dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); 1.153 + src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); 1.154 + } while (--height != 0); 1.155 + } 1.156 + 1.157 +private: 1.158 + typedef Sprite_D32_XferFilter INHERITED; 1.159 +}; 1.160 + 1.161 +static void fillbuffer(SkPMColor* SK_RESTRICT dst, 1.162 + const SkPMColor16* SK_RESTRICT src, int count) { 1.163 + SkASSERT(count > 0); 1.164 + 1.165 + do { 1.166 + *dst++ = SkPixel4444ToPixel32(*src++); 1.167 + } while (--count != 0); 1.168 +} 1.169 + 1.170 +class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter { 1.171 +public: 1.172 + Sprite_D32_S4444_XferFilter(const SkBitmap& source, const SkPaint& paint) 1.173 + : Sprite_D32_XferFilter(source, paint) {} 1.174 + 1.175 + virtual void blitRect(int x, int y, int width, int height) { 1.176 + SkASSERT(width > 0 && height > 0); 1.177 + SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); 1.178 + const SkPMColor16* SK_RESTRICT src = fSource->getAddr16(x - fLeft, 1.179 + y - fTop); 1.180 + size_t dstRB = fDevice->rowBytes(); 1.181 + size_t srcRB = fSource->rowBytes(); 1.182 + SkPMColor* SK_RESTRICT buffer = fBuffer; 1.183 + SkColorFilter* colorFilter = fColorFilter; 1.184 + SkXfermode* xfermode = fXfermode; 1.185 + 1.186 + do { 1.187 + fillbuffer(buffer, src, width); 1.188 + 1.189 + if (NULL != colorFilter) { 1.190 + colorFilter->filterSpan(buffer, width, buffer); 1.191 + } 1.192 + if (NULL != xfermode) { 1.193 + xfermode->xfer32(dst, buffer, width, NULL); 1.194 + } else { 1.195 + fProc32(dst, buffer, width, fAlpha); 1.196 + } 1.197 + 1.198 + dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 1.199 + src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 1.200 + } while (--height != 0); 1.201 + } 1.202 + 1.203 +private: 1.204 + typedef Sprite_D32_XferFilter INHERITED; 1.205 +}; 1.206 + 1.207 +/////////////////////////////////////////////////////////////////////////////// 1.208 + 1.209 +static void src_row(SkPMColor* SK_RESTRICT dst, 1.210 + const SkPMColor16* SK_RESTRICT src, int count) { 1.211 + do { 1.212 + *dst = SkPixel4444ToPixel32(*src); 1.213 + src += 1; 1.214 + dst += 1; 1.215 + } while (--count != 0); 1.216 +} 1.217 + 1.218 +class Sprite_D32_S4444_Opaque : public SkSpriteBlitter { 1.219 +public: 1.220 + Sprite_D32_S4444_Opaque(const SkBitmap& source) : SkSpriteBlitter(source) {} 1.221 + 1.222 + virtual void blitRect(int x, int y, int width, int height) { 1.223 + SkASSERT(width > 0 && height > 0); 1.224 + SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); 1.225 + const SkPMColor16* SK_RESTRICT src = fSource->getAddr16(x - fLeft, 1.226 + y - fTop); 1.227 + size_t dstRB = fDevice->rowBytes(); 1.228 + size_t srcRB = fSource->rowBytes(); 1.229 + 1.230 + do { 1.231 + src_row(dst, src, width); 1.232 + dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 1.233 + src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 1.234 + } while (--height != 0); 1.235 + } 1.236 +}; 1.237 + 1.238 +static void srcover_row(SkPMColor* SK_RESTRICT dst, 1.239 + const SkPMColor16* SK_RESTRICT src, int count) { 1.240 + do { 1.241 + *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst); 1.242 + src += 1; 1.243 + dst += 1; 1.244 + } while (--count != 0); 1.245 +} 1.246 + 1.247 +class Sprite_D32_S4444 : public SkSpriteBlitter { 1.248 +public: 1.249 + Sprite_D32_S4444(const SkBitmap& source) : SkSpriteBlitter(source) {} 1.250 + 1.251 + virtual void blitRect(int x, int y, int width, int height) { 1.252 + SkASSERT(width > 0 && height > 0); 1.253 + SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); 1.254 + const SkPMColor16* SK_RESTRICT src = fSource->getAddr16(x - fLeft, 1.255 + y - fTop); 1.256 + size_t dstRB = fDevice->rowBytes(); 1.257 + size_t srcRB = fSource->rowBytes(); 1.258 + 1.259 + do { 1.260 + srcover_row(dst, src, width); 1.261 + dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 1.262 + src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 1.263 + } while (--height != 0); 1.264 + } 1.265 +}; 1.266 + 1.267 +/////////////////////////////////////////////////////////////////////////////// 1.268 + 1.269 +SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source, const SkPaint& paint, 1.270 + SkTBlitterAllocator* allocator) { 1.271 + SkASSERT(allocator != NULL); 1.272 + 1.273 + if (paint.getMaskFilter() != NULL) { 1.274 + return NULL; 1.275 + } 1.276 + 1.277 + U8CPU alpha = paint.getAlpha(); 1.278 + SkXfermode* xfermode = paint.getXfermode(); 1.279 + SkColorFilter* filter = paint.getColorFilter(); 1.280 + SkSpriteBlitter* blitter = NULL; 1.281 + 1.282 + switch (source.colorType()) { 1.283 + case kARGB_4444_SkColorType: 1.284 + if (alpha != 0xFF) { 1.285 + return NULL; // we only have opaque sprites 1.286 + } 1.287 + if (xfermode || filter) { 1.288 + blitter = allocator->createT<Sprite_D32_S4444_XferFilter>(source, paint); 1.289 + } else if (source.isOpaque()) { 1.290 + blitter = allocator->createT<Sprite_D32_S4444_Opaque>(source); 1.291 + } else { 1.292 + blitter = allocator->createT<Sprite_D32_S4444>(source); 1.293 + } 1.294 + break; 1.295 + case kPMColor_SkColorType: 1.296 + if (xfermode || filter) { 1.297 + if (255 == alpha) { 1.298 + // this can handle xfermode or filter, but not alpha 1.299 + blitter = allocator->createT<Sprite_D32_S32A_XferFilter>(source, paint); 1.300 + } 1.301 + } else { 1.302 + // this can handle alpha, but not xfermode or filter 1.303 + blitter = allocator->createT<Sprite_D32_S32>(source, alpha); 1.304 + } 1.305 + break; 1.306 + default: 1.307 + break; 1.308 + } 1.309 + return blitter; 1.310 +}