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 +}