SkSpriteBlitter_RGB16.cpp revision e5f48243bdbed2662be7a31be0888abc273b09e8
1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkSpriteBlitter.h" 11#include "SkBlitRow.h" 12#include "SkTemplates.h" 13#include "SkUtils.h" 14#include "SkColorPriv.h" 15 16#define D16_S32A_Opaque_Pixel(dst, sc) \ 17do { \ 18 if (sc) { \ 19 *dst = SkSrcOver32To16(sc, *dst); \ 20 } \ 21} while (0) 22 23static inline void D16_S32A_Blend_Pixel_helper(uint16_t* dst, SkPMColor sc, 24 unsigned src_scale) { 25 uint16_t dc = *dst; 26 unsigned sa = SkGetPackedA32(sc); 27 unsigned dr, dg, db; 28 29 if (255 == sa) { 30 dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale); 31 dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale); 32 db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale); 33 } else { 34 unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale); 35 dr = (SkPacked32ToR16(sc) * src_scale + 36 SkGetPackedR16(dc) * dst_scale) >> 8; 37 dg = (SkPacked32ToG16(sc) * src_scale + 38 SkGetPackedG16(dc) * dst_scale) >> 8; 39 db = (SkPacked32ToB16(sc) * src_scale + 40 SkGetPackedB16(dc) * dst_scale) >> 8; 41 } 42 *dst = SkPackRGB16(dr, dg, db); 43} 44 45#define D16_S32A_Blend_Pixel(dst, sc, src_scale) \ 46 do { if (sc) D16_S32A_Blend_Pixel_helper(dst, sc, src_scale); } while (0) 47 48 49/////////////////////////////////////////////////////////////////////////////// 50 51class Sprite_D16_S16_Opaque : public SkSpriteBlitter { 52public: 53 Sprite_D16_S16_Opaque(const SkBitmap& source) 54 : SkSpriteBlitter(source) {} 55 56 // overrides 57 virtual void blitRect(int x, int y, int width, int height) { 58 uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y); 59 const uint16_t* SK_RESTRICT src = fSource->getAddr16(x - fLeft, 60 y - fTop); 61 size_t dstRB = fDevice->rowBytes(); 62 size_t srcRB = fSource->rowBytes(); 63 64 while (--height >= 0) { 65 memcpy(dst, src, width << 1); 66 dst = (uint16_t*)((char*)dst + dstRB); 67 src = (const uint16_t*)((const char*)src + srcRB); 68 } 69 } 70}; 71 72#define D16_S16_Blend_Pixel(dst, sc, scale) \ 73 do { \ 74 uint16_t dc = *dst; \ 75 *dst = SkBlendRGB16(sc, dc, scale); \ 76 } while (0) 77 78#define SkSPRITE_CLASSNAME Sprite_D16_S16_Blend 79#define SkSPRITE_ARGS , uint8_t alpha 80#define SkSPRITE_FIELDS uint8_t fSrcAlpha; 81#define SkSPRITE_INIT fSrcAlpha = alpha; 82#define SkSPRITE_DST_TYPE uint16_t 83#define SkSPRITE_SRC_TYPE uint16_t 84#define SkSPRITE_DST_GETADDR getAddr16 85#define SkSPRITE_SRC_GETADDR getAddr16 86#define SkSPRITE_PREAMBLE(srcBM, x, y) int scale = SkAlpha255To256(fSrcAlpha); 87#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S16_Blend_Pixel(dst, src, scale) 88#define SkSPRITE_NEXT_ROW 89#define SkSPRITE_POSTAMBLE(srcBM) 90#include "SkSpriteBlitterTemplate.h" 91 92/////////////////////////////////////////////////////////////////////////////// 93 94#define D16_S4444_Opaque(dst, sc) \ 95 do { \ 96 uint16_t dc = *dst; \ 97 *dst = SkSrcOver4444To16(sc, dc); \ 98 } while (0) 99 100#define SkSPRITE_CLASSNAME Sprite_D16_S4444_Opaque 101#define SkSPRITE_ARGS 102#define SkSPRITE_FIELDS 103#define SkSPRITE_INIT 104#define SkSPRITE_DST_TYPE uint16_t 105#define SkSPRITE_SRC_TYPE SkPMColor16 106#define SkSPRITE_DST_GETADDR getAddr16 107#define SkSPRITE_SRC_GETADDR getAddr16 108#define SkSPRITE_PREAMBLE(srcBM, x, y) 109#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S4444_Opaque(dst, src) 110#define SkSPRITE_NEXT_ROW 111#define SkSPRITE_POSTAMBLE(srcBM) 112#include "SkSpriteBlitterTemplate.h" 113 114#define D16_S4444_Blend(dst, sc, scale16) \ 115 do { \ 116 uint16_t dc = *dst; \ 117 *dst = SkBlend4444To16(sc, dc, scale16); \ 118 } while (0) 119 120 121#define SkSPRITE_CLASSNAME Sprite_D16_S4444_Blend 122#define SkSPRITE_ARGS , uint8_t alpha 123#define SkSPRITE_FIELDS uint8_t fSrcAlpha; 124#define SkSPRITE_INIT fSrcAlpha = alpha; 125#define SkSPRITE_DST_TYPE uint16_t 126#define SkSPRITE_SRC_TYPE uint16_t 127#define SkSPRITE_DST_GETADDR getAddr16 128#define SkSPRITE_SRC_GETADDR getAddr16 129#define SkSPRITE_PREAMBLE(srcBM, x, y) int scale = SkAlpha15To16(fSrcAlpha); 130#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S4444_Blend(dst, src, scale) 131#define SkSPRITE_NEXT_ROW 132#define SkSPRITE_POSTAMBLE(srcBM) 133#include "SkSpriteBlitterTemplate.h" 134 135/////////////////////////////////////////////////////////////////////////////// 136 137#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8A_Opaque 138#define SkSPRITE_ARGS 139#define SkSPRITE_FIELDS 140#define SkSPRITE_INIT 141#define SkSPRITE_DST_TYPE uint16_t 142#define SkSPRITE_SRC_TYPE uint8_t 143#define SkSPRITE_DST_GETADDR getAddr16 144#define SkSPRITE_SRC_GETADDR getAddr8 145#define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.getColorTable()->lockColors() 146#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Opaque_Pixel(dst, ctable[src]) 147#define SkSPRITE_NEXT_ROW 148#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors(false) 149#include "SkSpriteBlitterTemplate.h" 150 151#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8A_Blend 152#define SkSPRITE_ARGS , uint8_t alpha 153#define SkSPRITE_FIELDS uint8_t fSrcAlpha; 154#define SkSPRITE_INIT fSrcAlpha = alpha; 155#define SkSPRITE_DST_TYPE uint16_t 156#define SkSPRITE_SRC_TYPE uint8_t 157#define SkSPRITE_DST_GETADDR getAddr16 158#define SkSPRITE_SRC_GETADDR getAddr8 159#define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.getColorTable()->lockColors(); unsigned src_scale = SkAlpha255To256(fSrcAlpha); 160#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Blend_Pixel(dst, ctable[src], src_scale) 161#define SkSPRITE_NEXT_ROW 162#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors(false); 163#include "SkSpriteBlitterTemplate.h" 164 165/////////////////////////////////////////////////////////////////////////////// 166 167static intptr_t asint(const void* ptr) { 168 return reinterpret_cast<const char*>(ptr) - (const char*)0; 169} 170 171static void blitrow_d16_si8(uint16_t* SK_RESTRICT dst, 172 const uint8_t* SK_RESTRICT src, int count, 173 const uint16_t* SK_RESTRICT ctable) { 174 if (count <= 8) { 175 do { 176 *dst++ = ctable[*src++]; 177 } while (--count); 178 return; 179 } 180 181 // eat src until we're on a 4byte boundary 182 while (asint(src) & 3) { 183 *dst++ = ctable[*src++]; 184 count -= 1; 185 } 186 187 int qcount = count >> 2; 188 SkASSERT(qcount > 0); 189 const uint32_t* qsrc = reinterpret_cast<const uint32_t*>(src); 190 if (asint(dst) & 2) { 191 do { 192 uint32_t s4 = *qsrc++; 193#ifdef SK_CPU_LENDIAN 194 *dst++ = ctable[s4 & 0xFF]; 195 *dst++ = ctable[(s4 >> 8) & 0xFF]; 196 *dst++ = ctable[(s4 >> 16) & 0xFF]; 197 *dst++ = ctable[s4 >> 24]; 198#else // BENDIAN 199 *dst++ = ctable[s4 >> 24]; 200 *dst++ = ctable[(s4 >> 16) & 0xFF]; 201 *dst++ = ctable[(s4 >> 8) & 0xFF]; 202 *dst++ = ctable[s4 & 0xFF]; 203#endif 204 } while (--qcount); 205 } else { // dst is on a 4byte boundary 206 uint32_t* ddst = reinterpret_cast<uint32_t*>(dst); 207 do { 208 uint32_t s4 = *qsrc++; 209#ifdef SK_CPU_LENDIAN 210 *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF]; 211 *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF]; 212#else // BENDIAN 213 *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF]; 214 *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF]; 215#endif 216 } while (--qcount); 217 dst = reinterpret_cast<uint16_t*>(ddst); 218 } 219 src = reinterpret_cast<const uint8_t*>(qsrc); 220 count &= 3; 221 // catch any remaining (will be < 4) 222 while (--count >= 0) { 223 *dst++ = ctable[*src++]; 224 } 225} 226 227#define SkSPRITE_ROW_PROC(d, s, n, x, y) blitrow_d16_si8(d, s, n, ctable) 228 229#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8_Opaque 230#define SkSPRITE_ARGS 231#define SkSPRITE_FIELDS 232#define SkSPRITE_INIT 233#define SkSPRITE_DST_TYPE uint16_t 234#define SkSPRITE_SRC_TYPE uint8_t 235#define SkSPRITE_DST_GETADDR getAddr16 236#define SkSPRITE_SRC_GETADDR getAddr8 237#define SkSPRITE_PREAMBLE(srcBM, x, y) const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache() 238#define SkSPRITE_BLIT_PIXEL(dst, src) *dst = ctable[src] 239#define SkSPRITE_NEXT_ROW 240#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlock16BitCache() 241#include "SkSpriteBlitterTemplate.h" 242 243#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8_Blend 244#define SkSPRITE_ARGS , uint8_t alpha 245#define SkSPRITE_FIELDS uint8_t fSrcAlpha; 246#define SkSPRITE_INIT fSrcAlpha = alpha; 247#define SkSPRITE_DST_TYPE uint16_t 248#define SkSPRITE_SRC_TYPE uint8_t 249#define SkSPRITE_DST_GETADDR getAddr16 250#define SkSPRITE_SRC_GETADDR getAddr8 251#define SkSPRITE_PREAMBLE(srcBM, x, y) const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache(); unsigned src_scale = SkAlpha255To256(fSrcAlpha); 252#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S16_Blend_Pixel(dst, ctable[src], src_scale) 253#define SkSPRITE_NEXT_ROW 254#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlock16BitCache(); 255#include "SkSpriteBlitterTemplate.h" 256 257/////////////////////////////////////////////////////////////////////////////// 258 259class Sprite_D16_S32_BlitRowProc : public SkSpriteBlitter { 260public: 261 Sprite_D16_S32_BlitRowProc(const SkBitmap& source) 262 : SkSpriteBlitter(source) {} 263 264 // overrides 265 266 virtual void setup(const SkBitmap& device, int left, int top, 267 const SkPaint& paint) { 268 this->INHERITED::setup(device, left, top, paint); 269 270 unsigned flags = 0; 271 272 if (paint.getAlpha() < 0xFF) { 273 flags |= SkBlitRow::kGlobalAlpha_Flag; 274 } 275 if (!fSource->isOpaque()) { 276 flags |= SkBlitRow::kSrcPixelAlpha_Flag; 277 } 278 if (paint.isDither()) { 279 flags |= SkBlitRow::kDither_Flag; 280 } 281 fProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config); 282 } 283 284 virtual void blitRect(int x, int y, int width, int height) { 285 uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y); 286 const SkPMColor* SK_RESTRICT src = fSource->getAddr32(x - fLeft, 287 y - fTop); 288 size_t dstRB = fDevice->rowBytes(); 289 size_t srcRB = fSource->rowBytes(); 290 SkBlitRow::Proc proc = fProc; 291 U8CPU alpha = fPaint->getAlpha(); 292 293 while (--height >= 0) { 294 proc(dst, src, width, alpha, x, y); 295 y += 1; 296 dst = (uint16_t* SK_RESTRICT)((char*)dst + dstRB); 297 src = (const SkPMColor* SK_RESTRICT)((const char*)src + srcRB); 298 } 299 } 300 301private: 302 SkBlitRow::Proc fProc; 303 304 typedef SkSpriteBlitter INHERITED; 305}; 306 307/////////////////////////////////////////////////////////////////////////////// 308 309#include "SkTemplatesPriv.h" 310 311SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source, 312 const SkPaint& paint, 313 void* storage, size_t storageSize) { 314 if (paint.getMaskFilter() != NULL) { // may add cases for this 315 return NULL; 316 } 317 if (paint.getXfermode() != NULL) { // may add cases for this 318 return NULL; 319 } 320 if (paint.getColorFilter() != NULL) { // may add cases for this 321 return NULL; 322 } 323 324 SkSpriteBlitter* blitter = NULL; 325 unsigned alpha = paint.getAlpha(); 326 327 switch (source.getConfig()) { 328 case SkBitmap::kARGB_8888_Config: 329 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32_BlitRowProc, 330 storage, storageSize, (source)); 331 break; 332 case SkBitmap::kARGB_4444_Config: 333 if (255 == alpha) { 334 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Opaque, 335 storage, storageSize, (source)); 336 } else { 337 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Blend, 338 storage, storageSize, (source, alpha >> 4)); 339 } 340 break; 341 case SkBitmap::kRGB_565_Config: 342 if (255 == alpha) { 343 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Opaque, 344 storage, storageSize, (source)); 345 } else { 346 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Blend, 347 storage, storageSize, (source, alpha)); 348 } 349 break; 350 case SkBitmap::kIndex8_Config: 351 if (paint.isDither()) { 352 // we don't support dither yet in these special cases 353 break; 354 } 355 if (source.isOpaque()) { 356 if (255 == alpha) { 357 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Opaque, 358 storage, storageSize, (source)); 359 } else { 360 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Blend, 361 storage, storageSize, (source, alpha)); 362 } 363 } else { 364 if (255 == alpha) { 365 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Opaque, 366 storage, storageSize, (source)); 367 } else { 368 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Blend, 369 storage, storageSize, (source, alpha)); 370 } 371 } 372 break; 373 default: 374 break; 375 } 376 return blitter; 377} 378