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, 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 301 private: 302 SkBlitRow::Proc fProc; 303 304 typedef SkSpriteBlitter INHERITED; 305 }; 306 307 /////////////////////////////////////////////////////////////////////////////// 308 309 #include "SkTemplatesPriv.h" 310 311 SkSpriteBlitter* 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.config()) { 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