1 /* libs/graphics/sgl/SkBlitter_RGB16.cpp 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #include "SkBlitRow.h" 19 #include "SkCoreBlitters.h" 20 #include "SkColorPriv.h" 21 #include "SkDither.h" 22 #include "SkShader.h" 23 #include "SkTemplatesPriv.h" 24 #include "SkUtils.h" 25 #include "SkXfermode.h" 26 27 #if defined(__ARM_HAVE_NEON) && defined(SK_CPU_LENDIAN) 28 #define SK_USE_NEON 29 #include <arm_neon.h> 30 #else 31 // if we don't have neon, then our black blitter is worth the extra code 32 #define USE_BLACK_BLITTER 33 #endif 34 35 void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, 36 int count) { 37 if (count > 0) { 38 // see if we need to write one short before we can cast to an 4byte ptr 39 // (we do this subtract rather than (unsigned)dst so we don't get warnings 40 // on 64bit machines) 41 if (((char*)dst - (char*)0) & 2) { 42 *dst++ = value; 43 count -= 1; 44 SkTSwap(value, other); 45 } 46 47 // fast way to set [value,other] pairs 48 #ifdef SK_CPU_BENDIAN 49 sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1); 50 #else 51 sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1); 52 #endif 53 54 if (count & 1) { 55 dst[count - 1] = value; 56 } 57 } 58 } 59 60 /////////////////////////////////////////////////////////////////////////////// 61 62 class SkRGB16_Blitter : public SkRasterBlitter { 63 public: 64 SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint); 65 virtual void blitH(int x, int y, int width); 66 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); 67 virtual void blitV(int x, int y, int height, SkAlpha alpha); 68 virtual void blitRect(int x, int y, int width, int height); 69 virtual void blitMask(const SkMask&, const SkIRect&); 70 virtual const SkBitmap* justAnOpaqueColor(uint32_t*); 71 72 protected: 73 SkPMColor fSrcColor32; 74 uint32_t fExpandedRaw16; 75 unsigned fScale; 76 uint16_t fColor16; // already scaled by fScale 77 uint16_t fRawColor16; // unscaled 78 uint16_t fRawDither16; // unscaled 79 SkBool8 fDoDither; 80 81 // illegal 82 SkRGB16_Blitter& operator=(const SkRGB16_Blitter&); 83 84 typedef SkRasterBlitter INHERITED; 85 }; 86 87 class SkRGB16_Opaque_Blitter : public SkRGB16_Blitter { 88 public: 89 SkRGB16_Opaque_Blitter(const SkBitmap& device, const SkPaint& paint); 90 virtual void blitH(int x, int y, int width); 91 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); 92 virtual void blitV(int x, int y, int height, SkAlpha alpha); 93 virtual void blitRect(int x, int y, int width, int height); 94 virtual void blitMask(const SkMask&, const SkIRect&); 95 96 private: 97 typedef SkRGB16_Blitter INHERITED; 98 }; 99 100 #ifdef USE_BLACK_BLITTER 101 class SkRGB16_Black_Blitter : public SkRGB16_Opaque_Blitter { 102 public: 103 SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint); 104 virtual void blitMask(const SkMask&, const SkIRect&); 105 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); 106 107 private: 108 typedef SkRGB16_Opaque_Blitter INHERITED; 109 }; 110 #endif 111 112 class SkRGB16_Shader_Blitter : public SkShaderBlitter { 113 public: 114 SkRGB16_Shader_Blitter(const SkBitmap& device, const SkPaint& paint); 115 virtual ~SkRGB16_Shader_Blitter(); 116 virtual void blitH(int x, int y, int width); 117 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); 118 virtual void blitRect(int x, int y, int width, int height); 119 120 protected: 121 SkPMColor* fBuffer; 122 SkBlitRow::Proc fOpaqueProc; 123 SkBlitRow::Proc fAlphaProc; 124 125 private: 126 // illegal 127 SkRGB16_Shader_Blitter& operator=(const SkRGB16_Shader_Blitter&); 128 129 typedef SkShaderBlitter INHERITED; 130 }; 131 132 // used only if the shader can perform shadSpan16 133 class SkRGB16_Shader16_Blitter : public SkRGB16_Shader_Blitter { 134 public: 135 SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint); 136 virtual void blitH(int x, int y, int width); 137 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); 138 virtual void blitRect(int x, int y, int width, int height); 139 140 private: 141 typedef SkRGB16_Shader_Blitter INHERITED; 142 }; 143 144 class SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter { 145 public: 146 SkRGB16_Shader_Xfermode_Blitter(const SkBitmap& device, const SkPaint& paint); 147 virtual ~SkRGB16_Shader_Xfermode_Blitter(); 148 virtual void blitH(int x, int y, int width); 149 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); 150 151 private: 152 SkXfermode* fXfermode; 153 SkPMColor* fBuffer; 154 uint8_t* fAAExpand; 155 156 // illegal 157 SkRGB16_Shader_Xfermode_Blitter& operator=(const SkRGB16_Shader_Xfermode_Blitter&); 158 159 typedef SkShaderBlitter INHERITED; 160 }; 161 162 /////////////////////////////////////////////////////////////////////////////// 163 #ifdef USE_BLACK_BLITTER 164 SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint) 165 : INHERITED(device, paint) { 166 SkASSERT(paint.getShader() == NULL); 167 SkASSERT(paint.getColorFilter() == NULL); 168 SkASSERT(paint.getXfermode() == NULL); 169 SkASSERT(paint.getColor() == SK_ColorBLACK); 170 } 171 172 #if 1 173 #define black_8_pixels(mask, dst) \ 174 do { \ 175 if (mask & 0x80) dst[0] = 0; \ 176 if (mask & 0x40) dst[1] = 0; \ 177 if (mask & 0x20) dst[2] = 0; \ 178 if (mask & 0x10) dst[3] = 0; \ 179 if (mask & 0x08) dst[4] = 0; \ 180 if (mask & 0x04) dst[5] = 0; \ 181 if (mask & 0x02) dst[6] = 0; \ 182 if (mask & 0x01) dst[7] = 0; \ 183 } while (0) 184 #else 185 static inline black_8_pixels(U8CPU mask, uint16_t dst[]) 186 { 187 if (mask & 0x80) dst[0] = 0; 188 if (mask & 0x40) dst[1] = 0; 189 if (mask & 0x20) dst[2] = 0; 190 if (mask & 0x10) dst[3] = 0; 191 if (mask & 0x08) dst[4] = 0; 192 if (mask & 0x04) dst[5] = 0; 193 if (mask & 0x02) dst[6] = 0; 194 if (mask & 0x01) dst[7] = 0; 195 } 196 #endif 197 198 #define SK_BLITBWMASK_NAME SkRGB16_Black_BlitBW 199 #define SK_BLITBWMASK_ARGS 200 #define SK_BLITBWMASK_BLIT8(mask, dst) black_8_pixels(mask, dst) 201 #define SK_BLITBWMASK_GETADDR getAddr16 202 #define SK_BLITBWMASK_DEVTYPE uint16_t 203 #include "SkBlitBWMaskTemplate.h" 204 205 void SkRGB16_Black_Blitter::blitMask(const SkMask& SK_RESTRICT mask, 206 const SkIRect& SK_RESTRICT clip) 207 SK_RESTRICT { 208 if (mask.fFormat == SkMask::kBW_Format) { 209 SkRGB16_Black_BlitBW(fDevice, mask, clip); 210 } else { 211 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop); 212 const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop); 213 unsigned width = clip.width(); 214 unsigned height = clip.height(); 215 unsigned deviceRB = fDevice.rowBytes() - (width << 1); 216 unsigned maskRB = mask.fRowBytes - width; 217 218 SkASSERT((int)height > 0); 219 SkASSERT((int)width > 0); 220 SkASSERT((int)deviceRB >= 0); 221 SkASSERT((int)maskRB >= 0); 222 223 do { 224 unsigned w = width; 225 do { 226 unsigned aa = *alpha++; 227 *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa)); 228 device += 1; 229 } while (--w != 0); 230 device = (uint16_t*)((char*)device + deviceRB); 231 alpha += maskRB; 232 } while (--height != 0); 233 } 234 } 235 236 void SkRGB16_Black_Blitter::blitAntiH(int x, int y, 237 const SkAlpha* SK_RESTRICT antialias, 238 const int16_t* SK_RESTRICT runs) 239 SK_RESTRICT { 240 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 241 242 for (;;) { 243 int count = runs[0]; 244 SkASSERT(count >= 0); 245 if (count <= 0) { 246 return; 247 } 248 runs += count; 249 250 unsigned aa = antialias[0]; 251 antialias += count; 252 if (aa) { 253 if (aa == 255) { 254 memset(device, 0, count << 1); 255 } else { 256 aa = SkAlpha255To256(255 - aa); 257 do { 258 *device = SkAlphaMulRGB16(*device, aa); 259 device += 1; 260 } while (--count != 0); 261 continue; 262 } 263 } 264 device += count; 265 } 266 } 267 #endif 268 269 /////////////////////////////////////////////////////////////////////////////// 270 /////////////////////////////////////////////////////////////////////////////// 271 272 SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkBitmap& device, 273 const SkPaint& paint) 274 : INHERITED(device, paint) {} 275 276 void SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) SK_RESTRICT { 277 SkASSERT(width > 0); 278 SkASSERT(x + width <= fDevice.width()); 279 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 280 uint16_t srcColor = fColor16; 281 282 SkASSERT(fRawColor16 == srcColor); 283 if (fDoDither) { 284 uint16_t ditherColor = fRawDither16; 285 if ((x ^ y) & 1) { 286 SkTSwap(ditherColor, srcColor); 287 } 288 sk_dither_memset16(device, srcColor, ditherColor, width); 289 } else { 290 sk_memset16(device, srcColor, width); 291 } 292 } 293 294 // return 1 or 0 from a bool 295 static inline int Bool2Int(int value) { 296 return !!value; 297 } 298 299 void SkRGB16_Opaque_Blitter::blitAntiH(int x, int y, 300 const SkAlpha* SK_RESTRICT antialias, 301 const int16_t* SK_RESTRICT runs) SK_RESTRICT { 302 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 303 uint16_t srcColor = fRawColor16; 304 uint32_t srcExpanded = fExpandedRaw16; 305 int ditherInt = Bool2Int(fDoDither); 306 uint16_t ditherColor = fRawDither16; 307 // if we have no dithering, this will always fail 308 if ((x ^ y) & ditherInt) { 309 SkTSwap(ditherColor, srcColor); 310 } 311 for (;;) { 312 int count = runs[0]; 313 SkASSERT(count >= 0); 314 if (count <= 0) { 315 return; 316 } 317 runs += count; 318 319 unsigned aa = antialias[0]; 320 antialias += count; 321 if (aa) { 322 if (aa == 255) { 323 if (ditherInt) { 324 sk_dither_memset16(device, srcColor, 325 ditherColor, count); 326 } else { 327 sk_memset16(device, srcColor, count); 328 } 329 } else { 330 // TODO: respect fDoDither 331 unsigned scale5 = SkAlpha255To256(aa) >> 3; 332 uint32_t src32 = srcExpanded * scale5; 333 scale5 = 32 - scale5; // now we can use it on the device 334 int n = count; 335 do { 336 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 337 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 338 } while (--n != 0); 339 goto DONE; 340 } 341 } 342 device += count; 343 344 DONE: 345 // if we have no dithering, this will always fail 346 if (count & ditherInt) { 347 SkTSwap(ditherColor, srcColor); 348 } 349 } 350 } 351 352 #define solid_8_pixels(mask, dst, color) \ 353 do { \ 354 if (mask & 0x80) dst[0] = color; \ 355 if (mask & 0x40) dst[1] = color; \ 356 if (mask & 0x20) dst[2] = color; \ 357 if (mask & 0x10) dst[3] = color; \ 358 if (mask & 0x08) dst[4] = color; \ 359 if (mask & 0x04) dst[5] = color; \ 360 if (mask & 0x02) dst[6] = color; \ 361 if (mask & 0x01) dst[7] = color; \ 362 } while (0) 363 364 #define SK_BLITBWMASK_NAME SkRGB16_BlitBW 365 #define SK_BLITBWMASK_ARGS , uint16_t color 366 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color) 367 #define SK_BLITBWMASK_GETADDR getAddr16 368 #define SK_BLITBWMASK_DEVTYPE uint16_t 369 #include "SkBlitBWMaskTemplate.h" 370 371 static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) { 372 return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5)); 373 } 374 375 void SkRGB16_Opaque_Blitter::blitMask(const SkMask& SK_RESTRICT mask, 376 const SkIRect& SK_RESTRICT clip) SK_RESTRICT { 377 if (mask.fFormat == SkMask::kBW_Format) { 378 SkRGB16_BlitBW(fDevice, mask, clip, fColor16); 379 return; 380 } 381 382 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop); 383 const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop); 384 int width = clip.width(); 385 int height = clip.height(); 386 unsigned deviceRB = fDevice.rowBytes() - (width << 1); 387 unsigned maskRB = mask.fRowBytes - width; 388 uint32_t expanded32 = fExpandedRaw16; 389 390 #ifdef SK_USE_NEON 391 #define UNROLL 8 392 do { 393 int w = width; 394 if (w >= UNROLL) { 395 uint32x4_t color; /* can use same one */ 396 uint32x4_t dev_lo, dev_hi; 397 uint32x4_t t1, t2; 398 uint32x4_t wn1, wn2; 399 uint16x4_t odev_lo, odev_hi; 400 uint16x4_t alpha_lo, alpha_hi; 401 uint16x8_t alpha_full; 402 403 color = vdupq_n_u32(expanded32); 404 405 do { 406 /* alpha is 8x8, widen and split to get pair of 16x4's */ 407 alpha_full = vmovl_u8(vld1_u8(alpha)); 408 alpha_full = vaddq_u16(alpha_full, vshrq_n_u16(alpha_full,7)); 409 alpha_full = vshrq_n_u16(alpha_full, 3); 410 alpha_lo = vget_low_u16(alpha_full); 411 alpha_hi = vget_high_u16(alpha_full); 412 413 dev_lo = vmovl_u16(vld1_u16(device)); 414 dev_hi = vmovl_u16(vld1_u16(device+4)); 415 416 /* unpack in 32 bits */ 417 dev_lo = vorrq_u32( 418 vandq_u32(dev_lo, vdupq_n_u32(0x0000F81F)), 419 vshlq_n_u32(vandq_u32(dev_lo, 420 vdupq_n_u32(0x000007E0)), 421 16) 422 ); 423 dev_hi = vorrq_u32( 424 vandq_u32(dev_hi, vdupq_n_u32(0x0000F81F)), 425 vshlq_n_u32(vandq_u32(dev_hi, 426 vdupq_n_u32(0x000007E0)), 427 16) 428 ); 429 430 /* blend the two */ 431 t1 = vmulq_u32(vsubq_u32(color, dev_lo), vmovl_u16(alpha_lo)); 432 t1 = vshrq_n_u32(t1, 5); 433 dev_lo = vaddq_u32(dev_lo, t1); 434 435 t1 = vmulq_u32(vsubq_u32(color, dev_hi), vmovl_u16(alpha_hi)); 436 t1 = vshrq_n_u32(t1, 5); 437 dev_hi = vaddq_u32(dev_hi, t1); 438 439 /* re-compact and store */ 440 wn1 = vandq_u32(dev_lo, vdupq_n_u32(0x0000F81F)), 441 wn2 = vshrq_n_u32(dev_lo, 16); 442 wn2 = vandq_u32(wn2, vdupq_n_u32(0x000007E0)); 443 odev_lo = vmovn_u32(vorrq_u32(wn1, wn2)); 444 445 wn1 = vandq_u32(dev_hi, vdupq_n_u32(0x0000F81F)), 446 wn2 = vshrq_n_u32(dev_hi, 16); 447 wn2 = vandq_u32(wn2, vdupq_n_u32(0x000007E0)); 448 odev_hi = vmovn_u32(vorrq_u32(wn1, wn2)); 449 450 vst1_u16(device, odev_lo); 451 vst1_u16(device+4, odev_hi); 452 453 device += UNROLL; 454 alpha += UNROLL; 455 w -= UNROLL; 456 } while (w >= UNROLL); 457 } 458 459 /* residuals (which is everything if we have no neon) */ 460 while (w > 0) { 461 *device = blend_compact(expanded32, SkExpand_rgb_16(*device), 462 SkAlpha255To256(*alpha++) >> 3); 463 device += 1; 464 --w; 465 } 466 device = (uint16_t*)((char*)device + deviceRB); 467 alpha += maskRB; 468 } while (--height != 0); 469 #undef UNROLL 470 #else // non-neon code 471 do { 472 int w = width; 473 do { 474 *device = blend_compact(expanded32, SkExpand_rgb_16(*device), 475 SkAlpha255To256(*alpha++) >> 3); 476 device += 1; 477 } while (--w != 0); 478 device = (uint16_t*)((char*)device + deviceRB); 479 alpha += maskRB; 480 } while (--height != 0); 481 #endif 482 } 483 484 void SkRGB16_Opaque_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 485 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 486 unsigned deviceRB = fDevice.rowBytes(); 487 488 // TODO: respect fDoDither 489 unsigned scale5 = SkAlpha255To256(alpha) >> 3; 490 uint32_t src32 = fExpandedRaw16 * scale5; 491 scale5 = 32 - scale5; 492 do { 493 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 494 *device = SkCompact_rgb_16((src32 + dst32) >> 5); 495 device = (uint16_t*)((char*)device + deviceRB); 496 } while (--height != 0); 497 } 498 499 void SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) { 500 SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height()); 501 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 502 unsigned deviceRB = fDevice.rowBytes(); 503 uint16_t color16 = fColor16; 504 505 if (fDoDither) { 506 uint16_t ditherColor = fRawDither16; 507 if ((x ^ y) & 1) { 508 SkTSwap(ditherColor, color16); 509 } 510 while (--height >= 0) { 511 sk_dither_memset16(device, color16, ditherColor, width); 512 SkTSwap(ditherColor, color16); 513 device = (uint16_t*)((char*)device + deviceRB); 514 } 515 } else { // no dither 516 while (--height >= 0) { 517 sk_memset16(device, color16, width); 518 device = (uint16_t*)((char*)device + deviceRB); 519 } 520 } 521 } 522 523 /////////////////////////////////////////////////////////////////////////////// 524 525 SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint) 526 : INHERITED(device) { 527 SkColor color = paint.getColor(); 528 529 fSrcColor32 = SkPreMultiplyColor(color); 530 fScale = SkAlpha255To256(SkColorGetA(color)); 531 532 int r = SkColorGetR(color); 533 int g = SkColorGetG(color); 534 int b = SkColorGetB(color); 535 536 fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b); 537 // if we're dithered, use fRawDither16 to hold that. 538 if ((fDoDither = paint.isDither()) != false) { 539 fRawDither16 = SkDitherPack888ToRGB16(r, g, b); 540 } 541 542 fExpandedRaw16 = SkExpand_rgb_16(fRawColor16); 543 544 fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS), 545 SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS), 546 SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS)); 547 } 548 549 const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) { 550 if (!fDoDither && 256 == fScale) { 551 *value = fRawColor16; 552 return &fDevice; 553 } 554 return NULL; 555 } 556 557 static uint32_t pmcolor_to_expand16(SkPMColor c) { 558 unsigned r = SkGetPackedR32(c); 559 unsigned g = SkGetPackedG32(c); 560 unsigned b = SkGetPackedB32(c); 561 return (g << 24) | (r << 13) | (b << 2); 562 } 563 564 static inline void blend32_16_row(SkPMColor src, uint16_t dst[], int count) { 565 SkASSERT(count > 0); 566 uint32_t src_expand = pmcolor_to_expand16(src); 567 unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3; 568 do { 569 uint32_t dst_expand = SkExpand_rgb_16(*dst) * scale; 570 *dst = SkCompact_rgb_16((src_expand + dst_expand) >> 5); 571 dst += 1; 572 } while (--count != 0); 573 } 574 575 void SkRGB16_Blitter::blitH(int x, int y, int width) SK_RESTRICT { 576 SkASSERT(width > 0); 577 SkASSERT(x + width <= fDevice.width()); 578 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 579 580 // TODO: respect fDoDither 581 blend32_16_row(fSrcColor32, device, width); 582 } 583 584 void SkRGB16_Blitter::blitAntiH(int x, int y, 585 const SkAlpha* SK_RESTRICT antialias, 586 const int16_t* SK_RESTRICT runs) SK_RESTRICT { 587 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 588 uint32_t srcExpanded = fExpandedRaw16; 589 unsigned scale = fScale; 590 591 // TODO: respect fDoDither 592 for (;;) { 593 int count = runs[0]; 594 SkASSERT(count >= 0); 595 if (count <= 0) { 596 return; 597 } 598 runs += count; 599 600 unsigned aa = antialias[0]; 601 antialias += count; 602 if (aa) { 603 unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3); 604 uint32_t src32 = srcExpanded * scale5; 605 scale5 = 32 - scale5; 606 do { 607 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 608 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 609 } while (--count != 0); 610 continue; 611 } 612 device += count; 613 } 614 } 615 616 static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale, 617 U16CPU srcColor) { 618 if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale); 619 if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale); 620 if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale); 621 if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale); 622 if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale); 623 if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale); 624 if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale); 625 if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale); 626 } 627 628 #define SK_BLITBWMASK_NAME SkRGB16_BlendBW 629 #define SK_BLITBWMASK_ARGS , unsigned dst_scale, U16CPU src_color 630 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, dst_scale, src_color) 631 #define SK_BLITBWMASK_GETADDR getAddr16 632 #define SK_BLITBWMASK_DEVTYPE uint16_t 633 #include "SkBlitBWMaskTemplate.h" 634 635 void SkRGB16_Blitter::blitMask(const SkMask& SK_RESTRICT mask, 636 const SkIRect& SK_RESTRICT clip) SK_RESTRICT { 637 if (mask.fFormat == SkMask::kBW_Format) { 638 SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16); 639 return; 640 } 641 642 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop); 643 const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop); 644 int width = clip.width(); 645 int height = clip.height(); 646 unsigned deviceRB = fDevice.rowBytes() - (width << 1); 647 unsigned maskRB = mask.fRowBytes - width; 648 uint32_t color32 = fExpandedRaw16; 649 650 unsigned scale256 = fScale; 651 do { 652 int w = width; 653 do { 654 unsigned aa = *alpha++; 655 unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3); 656 uint32_t src32 = color32 * scale; 657 uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale); 658 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 659 } while (--w != 0); 660 device = (uint16_t*)((char*)device + deviceRB); 661 alpha += maskRB; 662 } while (--height != 0); 663 } 664 665 void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 666 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 667 unsigned deviceRB = fDevice.rowBytes(); 668 669 // TODO: respect fDoDither 670 unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3); 671 uint32_t src32 = fExpandedRaw16 * scale5; 672 scale5 = 32 - scale5; 673 do { 674 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 675 *device = SkCompact_rgb_16((src32 + dst32) >> 5); 676 device = (uint16_t*)((char*)device + deviceRB); 677 } while (--height != 0); 678 } 679 680 void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) { 681 SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height()); 682 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 683 unsigned deviceRB = fDevice.rowBytes(); 684 SkPMColor src32 = fSrcColor32; 685 686 while (--height >= 0) { 687 blend32_16_row(src32, device, width); 688 device = (uint16_t*)((char*)device + deviceRB); 689 } 690 } 691 692 /////////////////////////////////////////////////////////////////////////////// 693 694 SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device, 695 const SkPaint& paint) 696 : SkRGB16_Shader_Blitter(device, paint) { 697 SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags)); 698 } 699 700 void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) SK_RESTRICT { 701 SkASSERT(x + width <= fDevice.width()); 702 703 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 704 SkShader* shader = fShader; 705 706 int alpha = shader->getSpan16Alpha(); 707 if (0xFF == alpha) { 708 shader->shadeSpan16(x, y, device, width); 709 } else { 710 uint16_t* span16 = (uint16_t*)fBuffer; 711 shader->shadeSpan16(x, y, span16, width); 712 SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width); 713 } 714 } 715 716 void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) { 717 SkShader* shader = fShader; 718 uint16_t* dst = fDevice.getAddr16(x, y); 719 size_t dstRB = fDevice.rowBytes(); 720 int alpha = shader->getSpan16Alpha(); 721 722 if (0xFF == alpha) { 723 if (fShaderFlags & SkShader::kConstInY16_Flag) { 724 // have the shader blit directly into the device the first time 725 shader->shadeSpan16(x, y, dst, width); 726 // and now just memcpy that line on the subsequent lines 727 if (--height > 0) { 728 const uint16_t* orig = dst; 729 do { 730 dst = (uint16_t*)((char*)dst + dstRB); 731 memcpy(dst, orig, width << 1); 732 } while (--height); 733 } 734 } else { // need to call shadeSpan16 for every line 735 do { 736 shader->shadeSpan16(x, y, dst, width); 737 y += 1; 738 dst = (uint16_t*)((char*)dst + dstRB); 739 } while (--height); 740 } 741 } else { 742 int scale = SkAlpha255To256(alpha); 743 uint16_t* span16 = (uint16_t*)fBuffer; 744 if (fShaderFlags & SkShader::kConstInY16_Flag) { 745 shader->shadeSpan16(x, y, span16, width); 746 do { 747 SkBlendRGB16(span16, dst, scale, width); 748 dst = (uint16_t*)((char*)dst + dstRB); 749 } while (--height); 750 } else { 751 do { 752 shader->shadeSpan16(x, y, span16, width); 753 SkBlendRGB16(span16, dst, scale, width); 754 y += 1; 755 dst = (uint16_t*)((char*)dst + dstRB); 756 } while (--height); 757 } 758 } 759 } 760 761 void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y, 762 const SkAlpha* SK_RESTRICT antialias, 763 const int16_t* SK_RESTRICT runs) 764 SK_RESTRICT { 765 SkShader* shader = fShader; 766 SkPMColor* SK_RESTRICT span = fBuffer; 767 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 768 769 int alpha = shader->getSpan16Alpha(); 770 uint16_t* span16 = (uint16_t*)span; 771 772 if (0xFF == alpha) { 773 for (;;) { 774 int count = *runs; 775 if (count <= 0) { 776 break; 777 } 778 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer 779 780 int aa = *antialias; 781 if (aa == 255) { 782 // go direct to the device! 783 shader->shadeSpan16(x, y, device, count); 784 } else if (aa) { 785 shader->shadeSpan16(x, y, span16, count); 786 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count); 787 } 788 device += count; 789 runs += count; 790 antialias += count; 791 x += count; 792 } 793 } else { // span alpha is < 255 794 alpha = SkAlpha255To256(alpha); 795 for (;;) { 796 int count = *runs; 797 if (count <= 0) { 798 break; 799 } 800 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer 801 802 int aa = SkAlphaMul(*antialias, alpha); 803 if (aa) { 804 shader->shadeSpan16(x, y, span16, count); 805 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count); 806 } 807 808 device += count; 809 runs += count; 810 antialias += count; 811 x += count; 812 } 813 } 814 } 815 816 /////////////////////////////////////////////////////////////////////////////// 817 818 SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device, 819 const SkPaint& paint) 820 : INHERITED(device, paint) { 821 SkASSERT(paint.getXfermode() == NULL); 822 823 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor)); 824 825 // compute SkBlitRow::Procs 826 unsigned flags = 0; 827 828 uint32_t shaderFlags = fShaderFlags; 829 // shaders take care of global alpha, so we never set it in SkBlitRow 830 if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) { 831 flags |= SkBlitRow::kSrcPixelAlpha_Flag; 832 } 833 // don't dither if the shader is really 16bit 834 if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) { 835 flags |= SkBlitRow::kDither_Flag; 836 } 837 // used when we know our global alpha is 0xFF 838 fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config); 839 // used when we know our global alpha is < 0xFF 840 fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag, 841 SkBitmap::kRGB_565_Config); 842 } 843 844 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() { 845 sk_free(fBuffer); 846 } 847 848 void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) { 849 SkASSERT(x + width <= fDevice.width()); 850 851 fShader->shadeSpan(x, y, fBuffer, width); 852 // shaders take care of global alpha, so we pass 0xFF (should be ignored) 853 fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y); 854 } 855 856 void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) { 857 SkShader* shader = fShader; 858 SkBlitRow::Proc proc = fOpaqueProc; 859 SkPMColor* buffer = fBuffer; 860 uint16_t* dst = fDevice.getAddr16(x, y); 861 size_t dstRB = fDevice.rowBytes(); 862 863 if (fShaderFlags & SkShader::kConstInY32_Flag) { 864 shader->shadeSpan(x, y, buffer, width); 865 do { 866 proc(dst, buffer, width, 0xFF, x, y); 867 y += 1; 868 dst = (uint16_t*)((char*)dst + dstRB); 869 } while (--height); 870 } else { 871 do { 872 shader->shadeSpan(x, y, buffer, width); 873 proc(dst, buffer, width, 0xFF, x, y); 874 y += 1; 875 dst = (uint16_t*)((char*)dst + dstRB); 876 } while (--height); 877 } 878 } 879 880 static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) { 881 int count = 0; 882 for (;;) { 883 int n = *runs; 884 if (n == 0 || *aa == 0) { 885 break; 886 } 887 runs += n; 888 aa += n; 889 count += n; 890 } 891 return count; 892 } 893 894 void SkRGB16_Shader_Blitter::blitAntiH(int x, int y, 895 const SkAlpha* SK_RESTRICT antialias, 896 const int16_t* SK_RESTRICT runs) 897 SK_RESTRICT { 898 SkShader* shader = fShader; 899 SkPMColor* SK_RESTRICT span = fBuffer; 900 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 901 902 for (;;) { 903 int count = *runs; 904 if (count <= 0) { 905 break; 906 } 907 int aa = *antialias; 908 if (0 == aa) { 909 device += count; 910 runs += count; 911 antialias += count; 912 x += count; 913 continue; 914 } 915 916 int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count); 917 918 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer 919 shader->shadeSpan(x, y, span, nonZeroCount); 920 921 SkPMColor* localSpan = span; 922 for (;;) { 923 SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc; 924 proc(device, localSpan, count, aa, x, y); 925 926 x += count; 927 device += count; 928 runs += count; 929 antialias += count; 930 nonZeroCount -= count; 931 if (nonZeroCount == 0) { 932 break; 933 } 934 localSpan += count; 935 SkASSERT(nonZeroCount > 0); 936 count = *runs; 937 SkASSERT(count > 0); 938 aa = *antialias; 939 } 940 } 941 } 942 943 /////////////////////////////////////////////////////////////////////// 944 945 SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter( 946 const SkBitmap& device, const SkPaint& paint) 947 : INHERITED(device, paint) { 948 fXfermode = paint.getXfermode(); 949 SkASSERT(fXfermode); 950 fXfermode->ref(); 951 952 int width = device.width(); 953 fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor)); 954 fAAExpand = (uint8_t*)(fBuffer + width); 955 } 956 957 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() { 958 fXfermode->unref(); 959 sk_free(fBuffer); 960 } 961 962 void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) { 963 SkASSERT(x + width <= fDevice.width()); 964 965 uint16_t* device = fDevice.getAddr16(x, y); 966 SkPMColor* span = fBuffer; 967 968 fShader->shadeSpan(x, y, span, width); 969 fXfermode->xfer16(device, span, width, NULL); 970 } 971 972 void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y, 973 const SkAlpha* SK_RESTRICT antialias, 974 const int16_t* SK_RESTRICT runs) SK_RESTRICT { 975 SkShader* shader = fShader; 976 SkXfermode* mode = fXfermode; 977 SkPMColor* SK_RESTRICT span = fBuffer; 978 uint8_t* SK_RESTRICT aaExpand = fAAExpand; 979 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 980 981 for (;;) { 982 int count = *runs; 983 if (count <= 0) { 984 break; 985 } 986 int aa = *antialias; 987 if (0 == aa) { 988 device += count; 989 runs += count; 990 antialias += count; 991 x += count; 992 continue; 993 } 994 995 int nonZeroCount = count + count_nonzero_span(runs + count, 996 antialias + count); 997 998 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer 999 shader->shadeSpan(x, y, span, nonZeroCount); 1000 1001 x += nonZeroCount; 1002 SkPMColor* localSpan = span; 1003 for (;;) { 1004 if (aa == 0xFF) { 1005 mode->xfer16(device, localSpan, count, NULL); 1006 } else { 1007 SkASSERT(aa); 1008 memset(aaExpand, aa, count); 1009 mode->xfer16(device, localSpan, count, aaExpand); 1010 } 1011 device += count; 1012 runs += count; 1013 antialias += count; 1014 nonZeroCount -= count; 1015 if (nonZeroCount == 0) { 1016 break; 1017 } 1018 localSpan += count; 1019 SkASSERT(nonZeroCount > 0); 1020 count = *runs; 1021 SkASSERT(count > 0); 1022 aa = *antialias; 1023 } 1024 } 1025 } 1026 1027 /////////////////////////////////////////////////////////////////////////////// 1028 1029 SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint, 1030 void* storage, size_t storageSize) { 1031 SkBlitter* blitter; 1032 SkShader* shader = paint.getShader(); 1033 SkXfermode* mode = paint.getXfermode(); 1034 1035 // we require a shader if there is an xfermode, handled by our caller 1036 SkASSERT(NULL == mode || NULL != shader); 1037 1038 if (shader) { 1039 if (mode) { 1040 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Xfermode_Blitter, 1041 storage, storageSize, (device, paint)); 1042 } else if (shader->canCallShadeSpan16()) { 1043 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader16_Blitter, 1044 storage, storageSize, (device, paint)); 1045 } else { 1046 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Blitter, 1047 storage, storageSize, (device, paint)); 1048 } 1049 } else { 1050 // no shader, no xfermode, (and we always ignore colorfilter) 1051 SkColor color = paint.getColor(); 1052 if (0 == SkColorGetA(color)) { 1053 SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize); 1054 #ifdef USE_BLACK_BLITTER 1055 } else if (SK_ColorBLACK == color) { 1056 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Black_Blitter, storage, 1057 storageSize, (device, paint)); 1058 #endif 1059 } else if (0xFF == SkColorGetA(color)) { 1060 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Opaque_Blitter, storage, 1061 storageSize, (device, paint)); 1062 } else { 1063 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Blitter, storage, 1064 storageSize, (device, paint)); 1065 } 1066 } 1067 1068 return blitter; 1069 } 1070