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() 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(); 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, kRGB_565_SkColorType); 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 309SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source, const SkPaint& paint, 310 SkTBlitterAllocator* allocator) { 311 312 SkASSERT(allocator != NULL); 313 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.colorType()) { 328 case kN32_SkColorType: { 329 blitter = allocator->createT<Sprite_D16_S32_BlitRowProc>(source); 330 break; 331 } 332 case kARGB_4444_SkColorType: 333 if (255 == alpha) { 334 blitter = allocator->createT<Sprite_D16_S4444_Opaque>(source); 335 } else { 336 blitter = allocator->createT<Sprite_D16_S4444_Blend>(source, alpha >> 4); 337 } 338 break; 339 case kRGB_565_SkColorType: 340 if (255 == alpha) { 341 blitter = allocator->createT<Sprite_D16_S16_Opaque>(source); 342 } else { 343 blitter = allocator->createT<Sprite_D16_S16_Blend>(source, alpha); 344 } 345 break; 346 case kIndex_8_SkColorType: 347 if (paint.isDither()) { 348 // we don't support dither yet in these special cases 349 break; 350 } 351 if (source.isOpaque()) { 352 if (255 == alpha) { 353 blitter = allocator->createT<Sprite_D16_SIndex8_Opaque>(source); 354 } else { 355 blitter = allocator->createT<Sprite_D16_SIndex8_Blend>(source, alpha); 356 } 357 } else { 358 if (255 == alpha) { 359 blitter = allocator->createT<Sprite_D16_SIndex8A_Opaque>(source); 360 } else { 361 blitter = allocator->createT<Sprite_D16_SIndex8A_Blend>(source, alpha); 362 } 363 } 364 break; 365 default: 366 break; 367 } 368 return blitter; 369} 370