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) \ 17 do { \ 18 if (sc) { \ 19 *dst = SkSrcOver32To16(sc, *dst); \ 20 } \ 21 } while (0) 22 23 static 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 51 class Sprite_D16_S16_Opaque : public SkSpriteBlitter { 52 public: 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 167 static intptr_t asint(const void* ptr) { 168 return reinterpret_cast<const char*>(ptr) - (const char*)0; 169 } 170 171 static 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 259 class Sprite_D16_S32_BlitRowProc : public SkSpriteBlitter { 260 public: 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 301 private: 302 SkBlitRow::Proc fProc; 303 304 typedef SkSpriteBlitter INHERITED; 305 }; 306 307 /////////////////////////////////////////////////////////////////////////////// 308 309 SkSpriteBlitter* 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