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