1/* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "src/core/SkBlitter.h" 9 10#include "include/core/SkColor.h" 11#include "include/core/SkColorFilter.h" 12#include "include/core/SkString.h" 13#include "include/private/SkColorData.h" 14#include "include/private/SkTo.h" 15#include "src/core/SkAntiRun.h" 16#include "src/core/SkArenaAlloc.h" 17#include "src/core/SkMask.h" 18#include "src/core/SkMaskFilterBase.h" 19#include "src/core/SkMatrixProvider.h" 20#include "src/core/SkOpts.h" 21#include "src/core/SkPaintPriv.h" 22#include "src/core/SkReadBuffer.h" 23#include "src/core/SkRegionPriv.h" 24#include "src/core/SkTLazy.h" 25#include "src/core/SkVMBlitter.h" 26#include "src/core/SkWriteBuffer.h" 27#include "src/core/SkXfermodeInterpretation.h" 28#include "src/shaders/SkShaderBase.h" 29 30// Hacks for testing. 31bool gUseSkVMBlitter{false}; 32bool gSkForceRasterPipelineBlitter{false}; 33 34SkBlitter::~SkBlitter() {} 35 36bool SkBlitter::isNullBlitter() const { return false; } 37 38const SkPixmap* SkBlitter::justAnOpaqueColor(uint32_t* value) { 39 return nullptr; 40} 41 42/* 43void SkBlitter::blitH(int x, int y, int width) { 44 SkDEBUGFAIL("unimplemented"); 45} 46 47 48void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], 49 const int16_t runs[]) { 50 SkDEBUGFAIL("unimplemented"); 51} 52 */ 53 54inline static SkAlpha ScalarToAlpha(SkScalar a) { 55 SkAlpha alpha = (SkAlpha)(a * 255); 56 return alpha > 247 ? 0xFF : alpha < 8 ? 0 : alpha; 57} 58 59void SkBlitter::blitFatAntiRect(const SkRect& rect) { 60 SkIRect bounds = rect.roundOut(); 61 SkASSERT(bounds.width() >= 3); 62 63 // skbug.com/7813 64 // To ensure consistency of the threaded backend (a rect that's considered fat in the init-once 65 // phase must also be considered fat in the draw phase), we have to deal with rects with small 66 // heights because the horizontal tiling in the threaded backend may change the height. 67 // 68 // This also implies that we cannot do vertical tiling unless we can blit any rect (not just the 69 // fat one.) 70 if (bounds.height() == 0) { 71 return; 72 } 73 74 int runSize = bounds.width() + 1; // +1 so we can set runs[bounds.width()] = 0 75 void* storage = this->allocBlitMemory(runSize * (sizeof(int16_t) + sizeof(SkAlpha))); 76 int16_t* runs = reinterpret_cast<int16_t*>(storage); 77 SkAlpha* alphas = reinterpret_cast<SkAlpha*>(runs + runSize); 78 79 runs[0] = 1; 80 runs[1] = bounds.width() - 2; 81 runs[bounds.width() - 1] = 1; 82 runs[bounds.width()] = 0; 83 84 SkScalar partialL = bounds.fLeft + 1 - rect.fLeft; 85 SkScalar partialR = rect.fRight - (bounds.fRight - 1); 86 SkScalar partialT = bounds.fTop + 1 - rect.fTop; 87 SkScalar partialB = rect.fBottom - (bounds.fBottom - 1); 88 89 if (bounds.height() == 1) { 90 partialT = rect.fBottom - rect.fTop; 91 } 92 93 alphas[0] = ScalarToAlpha(partialL * partialT); 94 alphas[1] = ScalarToAlpha(partialT); 95 alphas[bounds.width() - 1] = ScalarToAlpha(partialR * partialT); 96 this->blitAntiH(bounds.fLeft, bounds.fTop, alphas, runs); 97 98 if (bounds.height() > 2) { 99 this->blitAntiRect(bounds.fLeft, bounds.fTop + 1, bounds.width() - 2, bounds.height() - 2, 100 ScalarToAlpha(partialL), ScalarToAlpha(partialR)); 101 } 102 103 if (bounds.height() > 1) { 104 alphas[0] = ScalarToAlpha(partialL * partialB); 105 alphas[1] = ScalarToAlpha(partialB); 106 alphas[bounds.width() - 1] = ScalarToAlpha(partialR * partialB); 107 this->blitAntiH(bounds.fLeft, bounds.fBottom - 1, alphas, runs); 108 } 109} 110 111void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 112 if (alpha == 255) { 113 this->blitRect(x, y, 1, height); 114 } else { 115 int16_t runs[2]; 116 runs[0] = 1; 117 runs[1] = 0; 118 119 while (--height >= 0) { 120 this->blitAntiH(x, y++, &alpha, runs); 121 } 122 } 123} 124 125void SkBlitter::blitRect(int x, int y, int width, int height) { 126 SkASSERT(width > 0); 127 while (--height >= 0) { 128 this->blitH(x, y++, width); 129 } 130} 131 132/// Default implementation doesn't check for easy optimizations 133/// such as alpha == 255; also uses blitV(), which some subclasses 134/// may not support. 135void SkBlitter::blitAntiRect(int x, int y, int width, int height, 136 SkAlpha leftAlpha, SkAlpha rightAlpha) { 137 if (leftAlpha > 0) { // we may send in x = -1 with leftAlpha = 0 138 this->blitV(x, y, height, leftAlpha); 139 } 140 x++; 141 if (width > 0) { 142 this->blitRect(x, y, width, height); 143 x += width; 144 } 145 if (rightAlpha > 0) { 146 this->blitV(x, y, height, rightAlpha); 147 } 148} 149 150////////////////////////////////////////////////////////////////////////////// 151 152static inline void bits_to_runs(SkBlitter* blitter, int x, int y, 153 const uint8_t bits[], 154 uint8_t left_mask, ptrdiff_t rowBytes, 155 uint8_t right_mask) { 156 int inFill = 0; 157 int pos = 0; 158 159 while (--rowBytes >= 0) { 160 uint8_t b = *bits++ & left_mask; 161 if (rowBytes == 0) { 162 b &= right_mask; 163 } 164 165 for (uint8_t test = 0x80U; test != 0; test >>= 1) { 166 if (b & test) { 167 if (!inFill) { 168 pos = x; 169 inFill = true; 170 } 171 } else { 172 if (inFill) { 173 blitter->blitH(pos, y, x - pos); 174 inFill = false; 175 } 176 } 177 x += 1; 178 } 179 left_mask = 0xFFU; 180 } 181 182 // final cleanup 183 if (inFill) { 184 blitter->blitH(pos, y, x - pos); 185 } 186} 187 188// maskBitCount is the number of 1's to place in the mask. It must be in the range between 1 and 8. 189static uint8_t generate_right_mask(int maskBitCount) { 190 return static_cast<uint8_t>((0xFF00U >> maskBitCount) & 0xFF); 191} 192 193void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 194 SkASSERT(mask.fBounds.contains(clip)); 195 196 if (mask.fFormat == SkMask::kLCD16_Format) { 197 return; // needs to be handled by subclass 198 } 199 200 if (mask.fFormat == SkMask::kBW_Format) { 201 int cx = clip.fLeft; 202 int cy = clip.fTop; 203 int maskLeft = mask.fBounds.fLeft; 204 int maskRowBytes = mask.fRowBytes; 205 int height = clip.height(); 206 207 const uint8_t* bits = mask.getAddr1(cx, cy); 208 209 SkDEBUGCODE(const uint8_t* endOfImage = 210 mask.fImage + (mask.fBounds.height() - 1) * maskRowBytes 211 + ((mask.fBounds.width() + 7) >> 3)); 212 213 if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) { 214 while (--height >= 0) { 215 int affectedRightBit = mask.fBounds.width() - 1; 216 ptrdiff_t rowBytes = (affectedRightBit >> 3) + 1; 217 SkASSERT(bits + rowBytes <= endOfImage); 218 U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1); 219 bits_to_runs(this, cx, cy, bits, 0xFF, rowBytes, rightMask); 220 bits += maskRowBytes; 221 cy += 1; 222 } 223 } else { 224 // Bits is calculated as the offset into the mask at the point {cx, cy} therefore, all 225 // addressing into the bit mask is relative to that point. Since this is an address 226 // calculated from a arbitrary bit in that byte, calculate the left most bit. 227 int bitsLeft = cx - ((cx - maskLeft) & 7); 228 229 // Everything is relative to the bitsLeft. 230 int leftEdge = cx - bitsLeft; 231 SkASSERT(leftEdge >= 0); 232 int rightEdge = clip.fRight - bitsLeft; 233 SkASSERT(rightEdge > leftEdge); 234 235 // Calculate left byte and mask 236 const uint8_t* leftByte = bits; 237 U8CPU leftMask = 0xFFU >> (leftEdge & 7); 238 239 // Calculate right byte and mask 240 int affectedRightBit = rightEdge - 1; 241 const uint8_t* rightByte = bits + (affectedRightBit >> 3); 242 U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1); 243 244 // leftByte and rightByte are byte locations therefore, to get a count of bytes the 245 // code must add one. 246 ptrdiff_t rowBytes = rightByte - leftByte + 1; 247 248 while (--height >= 0) { 249 SkASSERT(bits + rowBytes <= endOfImage); 250 bits_to_runs(this, bitsLeft, cy, bits, leftMask, rowBytes, rightMask); 251 bits += maskRowBytes; 252 cy += 1; 253 } 254 } 255 } else { 256 int width = clip.width(); 257 SkAutoSTMalloc<64, int16_t> runStorage(width + 1); 258 int16_t* runs = runStorage.get(); 259 const uint8_t* aa = mask.getAddr8(clip.fLeft, clip.fTop); 260 261 sk_memset16((uint16_t*)runs, 1, width); 262 runs[width] = 0; 263 264 int height = clip.height(); 265 int y = clip.fTop; 266 while (--height >= 0) { 267 this->blitAntiH(clip.fLeft, y, aa, runs); 268 aa += mask.fRowBytes; 269 y += 1; 270 } 271 } 272} 273 274/////////////////////// these are not virtual, just helpers 275 276void SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) { 277 if (clip.quickReject(mask.fBounds)) { 278 return; 279 } 280 281 SkRegion::Cliperator clipper(clip, mask.fBounds); 282 283 while (!clipper.done()) { 284 const SkIRect& cr = clipper.rect(); 285 this->blitMask(mask, cr); 286 clipper.next(); 287 } 288} 289 290void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) { 291 SkRegion::Cliperator clipper(clip, rect); 292 293 while (!clipper.done()) { 294 const SkIRect& cr = clipper.rect(); 295 this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); 296 clipper.next(); 297 } 298} 299 300void SkBlitter::blitRegion(const SkRegion& clip) { 301 SkRegionPriv::VisitSpans(clip, [this](const SkIRect& r) { 302 this->blitRect(r.left(), r.top(), r.width(), r.height()); 303 }); 304} 305 306/////////////////////////////////////////////////////////////////////////////// 307 308void SkNullBlitter::blitH(int x, int y, int width) {} 309 310void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], 311 const int16_t runs[]) {} 312 313void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {} 314 315void SkNullBlitter::blitRect(int x, int y, int width, int height) {} 316 317void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {} 318 319const SkPixmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) { 320 return nullptr; 321} 322 323bool SkNullBlitter::isNullBlitter() const { return true; } 324 325/////////////////////////////////////////////////////////////////////////////// 326 327static int compute_anti_width(const int16_t runs[]) { 328 int width = 0; 329 330 for (;;) { 331 int count = runs[0]; 332 333 SkASSERT(count >= 0); 334 if (count == 0) { 335 break; 336 } 337 width += count; 338 runs += count; 339 } 340 return width; 341} 342 343static inline bool y_in_rect(int y, const SkIRect& rect) { 344 return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); 345} 346 347static inline bool x_in_rect(int x, const SkIRect& rect) { 348 return (unsigned)(x - rect.fLeft) < (unsigned)rect.width(); 349} 350 351void SkRectClipBlitter::blitH(int left, int y, int width) { 352 SkASSERT(width > 0); 353 354 if (!y_in_rect(y, fClipRect)) { 355 return; 356 } 357 358 int right = left + width; 359 360 if (left < fClipRect.fLeft) { 361 left = fClipRect.fLeft; 362 } 363 if (right > fClipRect.fRight) { 364 right = fClipRect.fRight; 365 } 366 367 width = right - left; 368 if (width > 0) { 369 fBlitter->blitH(left, y, width); 370 } 371} 372 373void SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[], 374 const int16_t runs[]) { 375 if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) { 376 return; 377 } 378 379 int x0 = left; 380 int x1 = left + compute_anti_width(runs); 381 382 if (x1 <= fClipRect.fLeft) { 383 return; 384 } 385 386 SkASSERT(x0 < x1); 387 if (x0 < fClipRect.fLeft) { 388 int dx = fClipRect.fLeft - x0; 389 SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx); 390 runs += dx; 391 aa += dx; 392 x0 = fClipRect.fLeft; 393 } 394 395 SkASSERT(x0 < x1 && runs[x1 - x0] == 0); 396 if (x1 > fClipRect.fRight) { 397 x1 = fClipRect.fRight; 398 SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0); 399 ((int16_t*)runs)[x1 - x0] = 0; 400 } 401 402 SkASSERT(x0 < x1 && runs[x1 - x0] == 0); 403 SkASSERT(compute_anti_width(runs) == x1 - x0); 404 405 fBlitter->blitAntiH(x0, y, aa, runs); 406} 407 408void SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 409 SkASSERT(height > 0); 410 411 if (!x_in_rect(x, fClipRect)) { 412 return; 413 } 414 415 int y0 = y; 416 int y1 = y + height; 417 418 if (y0 < fClipRect.fTop) { 419 y0 = fClipRect.fTop; 420 } 421 if (y1 > fClipRect.fBottom) { 422 y1 = fClipRect.fBottom; 423 } 424 425 if (y0 < y1) { 426 fBlitter->blitV(x, y0, y1 - y0, alpha); 427 } 428} 429 430void SkRectClipBlitter::blitRect(int left, int y, int width, int height) { 431 SkIRect r; 432 433 r.setLTRB(left, y, left + width, y + height); 434 if (r.intersect(fClipRect)) { 435 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 436 } 437} 438 439void SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height, 440 SkAlpha leftAlpha, SkAlpha rightAlpha) { 441 SkIRect r; 442 443 // The *true* width of the rectangle blitted is width+2: 444 r.setLTRB(left, y, left + width + 2, y + height); 445 if (r.intersect(fClipRect)) { 446 if (r.fLeft != left) { 447 SkASSERT(r.fLeft > left); 448 leftAlpha = 255; 449 } 450 if (r.fRight != left + width + 2) { 451 SkASSERT(r.fRight < left + width + 2); 452 rightAlpha = 255; 453 } 454 if (255 == leftAlpha && 255 == rightAlpha) { 455 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 456 } else if (1 == r.width()) { 457 if (r.fLeft == left) { 458 fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha); 459 } else { 460 SkASSERT(r.fLeft == left + width + 1); 461 fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha); 462 } 463 } else { 464 fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(), 465 leftAlpha, rightAlpha); 466 } 467 } 468} 469 470void SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 471 SkASSERT(mask.fBounds.contains(clip)); 472 473 SkIRect r = clip; 474 475 if (r.intersect(fClipRect)) { 476 fBlitter->blitMask(mask, r); 477 } 478} 479 480const SkPixmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) { 481 return fBlitter->justAnOpaqueColor(value); 482} 483 484/////////////////////////////////////////////////////////////////////////////// 485 486void SkRgnClipBlitter::blitH(int x, int y, int width) { 487 SkRegion::Spanerator span(*fRgn, y, x, x + width); 488 int left, right; 489 490 while (span.next(&left, &right)) { 491 SkASSERT(left < right); 492 fBlitter->blitH(left, y, right - left); 493 } 494} 495 496void SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 497 const int16_t runs[]) { 498 int width = compute_anti_width(runs); 499 SkRegion::Spanerator span(*fRgn, y, x, x + width); 500 int left, right; 501 SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();) 502 503 int prevRite = x; 504 while (span.next(&left, &right)) { 505 SkASSERT(x <= left); 506 SkASSERT(left < right); 507 SkASSERT(left >= bounds.fLeft && right <= bounds.fRight); 508 509 SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left); 510 511 // now zero before left 512 if (left > prevRite) { 513 int index = prevRite - x; 514 ((uint8_t*)aa)[index] = 0; // skip runs after right 515 ((int16_t*)runs)[index] = SkToS16(left - prevRite); 516 } 517 518 prevRite = right; 519 } 520 521 if (prevRite > x) { 522 ((int16_t*)runs)[prevRite - x] = 0; 523 524 if (x < 0) { 525 int skip = runs[0]; 526 SkASSERT(skip >= -x); 527 aa += skip; 528 runs += skip; 529 x += skip; 530 } 531 fBlitter->blitAntiH(x, y, aa, runs); 532 } 533} 534 535void SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 536 SkIRect bounds; 537 bounds.setXYWH(x, y, 1, height); 538 539 SkRegion::Cliperator iter(*fRgn, bounds); 540 541 while (!iter.done()) { 542 const SkIRect& r = iter.rect(); 543 SkASSERT(bounds.contains(r)); 544 545 fBlitter->blitV(x, r.fTop, r.height(), alpha); 546 iter.next(); 547 } 548} 549 550void SkRgnClipBlitter::blitRect(int x, int y, int width, int height) { 551 SkIRect bounds; 552 bounds.setXYWH(x, y, width, height); 553 554 SkRegion::Cliperator iter(*fRgn, bounds); 555 556 while (!iter.done()) { 557 const SkIRect& r = iter.rect(); 558 SkASSERT(bounds.contains(r)); 559 560 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 561 iter.next(); 562 } 563} 564 565void SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height, 566 SkAlpha leftAlpha, SkAlpha rightAlpha) { 567 // The *true* width of the rectangle to blit is width + 2 568 SkIRect bounds; 569 bounds.setXYWH(x, y, width + 2, height); 570 571 SkRegion::Cliperator iter(*fRgn, bounds); 572 573 while (!iter.done()) { 574 const SkIRect& r = iter.rect(); 575 SkASSERT(bounds.contains(r)); 576 SkASSERT(r.fLeft >= x); 577 SkASSERT(r.fRight <= x + width + 2); 578 579 SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255; 580 SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ? 581 rightAlpha : 255; 582 583 if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) { 584 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 585 } else if (1 == r.width()) { 586 if (r.fLeft == x) { 587 fBlitter->blitV(r.fLeft, r.fTop, r.height(), 588 effectiveLeftAlpha); 589 } else { 590 SkASSERT(r.fLeft == x + width + 1); 591 fBlitter->blitV(r.fLeft, r.fTop, r.height(), 592 effectiveRightAlpha); 593 } 594 } else { 595 fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(), 596 effectiveLeftAlpha, effectiveRightAlpha); 597 } 598 iter.next(); 599 } 600} 601 602 603void SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 604 SkASSERT(mask.fBounds.contains(clip)); 605 606 SkRegion::Cliperator iter(*fRgn, clip); 607 const SkIRect& r = iter.rect(); 608 SkBlitter* blitter = fBlitter; 609 610 while (!iter.done()) { 611 blitter->blitMask(mask, r); 612 iter.next(); 613 } 614} 615 616const SkPixmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) { 617 return fBlitter->justAnOpaqueColor(value); 618} 619 620/////////////////////////////////////////////////////////////////////////////// 621 622SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip, 623 const SkIRect* ir) { 624 if (clip) { 625 const SkIRect& clipR = clip->getBounds(); 626 627 if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) { 628 blitter = &fNullBlitter; 629 } else if (clip->isRect()) { 630 if (ir == nullptr || !clipR.contains(*ir)) { 631 fRectBlitter.init(blitter, clipR); 632 blitter = &fRectBlitter; 633 } 634 } else { 635 fRgnBlitter.init(blitter, clip); 636 blitter = &fRgnBlitter; 637 } 638 } 639 return blitter; 640} 641 642/////////////////////////////////////////////////////////////////////////////// 643 644#include "src/core/SkCoreBlitters.h" 645 646bool SkBlitter::UseLegacyBlitter(const SkPixmap& device, 647 const SkPaint& paint, 648 const SkMatrix& matrix) { 649 if (gSkForceRasterPipelineBlitter) { 650 return false; 651 } 652#if defined(SK_FORCE_RASTER_PIPELINE_BLITTER) 653 return false; 654#else 655 656#if !defined(SK_SUPPORT_LEGACY_DITHER) 657 if (paint.isDither()) { 658 return false; 659 } 660#endif 661 662 const SkMaskFilterBase* mf = as_MFB(paint.getMaskFilter()); 663 const auto mode = paint.asBlendMode(); 664 665 // The legacy blitters cannot handle any of these complex features (anymore). 666 if (device.alphaType() == kUnpremul_SkAlphaType || 667 !mode || 668 mode.value() > SkBlendMode::kLastCoeffMode || 669 (mf && mf->getFormat() == SkMask::k3D_Format)) { 670 return false; 671 } 672 673 // All the real legacy fast paths are for shaders and SrcOver. 674 // Choosing SkRasterPipelineBlitter will also let us to hit its single-color memset path. 675 if (!paint.getShader() && mode != SkBlendMode::kSrcOver) { 676 return false; 677 } 678 679 auto cs = device.colorSpace(); 680 // We check (indirectly via makeContext()) later on if the shader can handle the colorspace 681 // in legacy mode, so here we just focus on if a single color needs raster-pipeline. 682 if (cs && !paint.getShader()) { 683 if (!paint.getColor4f().fitsInBytes() || !cs->isSRGB()) { 684 return false; 685 } 686 } 687 688 // Only kN32 and 565 are handled by legacy blitters now, 565 mostly just for Android. 689 return device.colorType() == kN32_SkColorType 690 || device.colorType() == kRGB_565_SkColorType; 691#endif 692} 693 694SkBlitter* SkBlitter::Choose(const SkPixmap& device, 695 const SkMatrixProvider& matrixProvider, 696 const SkPaint& origPaint, 697 SkArenaAlloc* alloc, 698 bool drawCoverage, 699 sk_sp<SkShader> clipShader) { 700 SkASSERT(alloc); 701 702 if (kUnknown_SkColorType == device.colorType()) { 703 return alloc->make<SkNullBlitter>(); 704 } 705 706 // We may tweak the original paint as we go. 707 SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 708 709 if (auto mode = paint->asBlendMode()) { 710 // We have the most fast-paths for SrcOver, so see if we can act like SrcOver. 711 if (mode.value() != SkBlendMode::kSrcOver) { 712 switch (SkInterpretXfermode(*paint, SkColorTypeIsAlwaysOpaque(device.colorType()))) { 713 case kSrcOver_SkXfermodeInterpretation: 714 paint.writable()->setBlendMode(SkBlendMode::kSrcOver); 715 break; 716 case kSkipDrawing_SkXfermodeInterpretation: 717 return alloc->make<SkNullBlitter>(); 718 default: 719 break; 720 } 721 } 722 723 // A Clear blend mode will ignore the entire color pipeline, as if Src mode with 0x00000000. 724 if (mode.value() == SkBlendMode::kClear) { 725 SkPaint* p = paint.writable(); 726 p->setShader(nullptr); 727 p->setColorFilter(nullptr); 728 p->setBlendMode(SkBlendMode::kSrc); 729 p->setColor(0x00000000); 730 } 731 } 732 733 if (paint->getColorFilter()) { 734 SkPaintPriv::RemoveColorFilter(paint.writable(), device.colorSpace()); 735 } 736 SkASSERT(!paint->getColorFilter()); 737 738 if (drawCoverage) { 739 if (device.colorType() == kAlpha_8_SkColorType) { 740 SkASSERT(!paint->getShader()); 741 SkASSERT(paint->isSrcOver()); 742 return alloc->make<SkA8_Coverage_Blitter>(device, *paint); 743 } 744 return alloc->make<SkNullBlitter>(); 745 } 746 747 if (paint->isDither() && !SkPaintPriv::ShouldDither(*paint, device.colorType())) { 748 paint.writable()->setDither(false); 749 } 750 751 if (gUseSkVMBlitter) { 752 if (auto blitter = SkVMBlitter::Make(device, *paint, matrixProvider, 753 alloc, clipShader)) { 754 return blitter; 755 } 756 } 757 758 // Same basic idea used a few times: try SkRP, then try SkVM, then give up with a null-blitter. 759 // (Setting gUseSkVMBlitter is the only way we prefer SkVM over SkRP at the moment.) 760 auto create_SkRP_or_SkVMBlitter = [&]() -> SkBlitter* { 761 if (auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrixProvider, 762 alloc, clipShader)) { 763 return blitter; 764 } 765 if (auto blitter = SkVMBlitter::Make(device, *paint, matrixProvider, 766 alloc, clipShader)) { 767 return blitter; 768 } 769 return alloc->make<SkNullBlitter>(); 770 }; 771 772 SkMatrix ctm = matrixProvider.localToDevice(); 773 // We'll end here for many interesting cases: color spaces, color filters, most color types. 774 if (clipShader || !UseLegacyBlitter(device, *paint, ctm)) { 775 return create_SkRP_or_SkVMBlitter(); 776 } 777 778 // Everything but legacy kN32_SkColorType and kRGB_565_SkColorType should already be handled. 779 SkASSERT(device.colorType() == kN32_SkColorType || 780 device.colorType() == kRGB_565_SkColorType); 781 782 // And we should either have a shader, be blending with SrcOver, or both. 783 SkASSERT(paint->getShader() || paint->asBlendMode() == SkBlendMode::kSrcOver); 784 785 // Legacy blitters keep their shader state on a shader context. 786 SkShaderBase::Context* shaderContext = nullptr; 787 if (paint->getShader()) { 788 shaderContext = as_SB(paint->getShader())->makeContext( 789 {*paint, ctm, nullptr, device.colorType(), device.colorSpace()}, 790 alloc); 791 792 // Creating the context isn't always possible... try fallbacks before giving up. 793 if (!shaderContext) { 794 return create_SkRP_or_SkVMBlitter(); 795 } 796 } 797 798 switch (device.colorType()) { 799 case kN32_SkColorType: 800 if (shaderContext) { 801 return alloc->make<SkARGB32_Shader_Blitter>(device, *paint, shaderContext); 802 } else if (paint->getColor() == SK_ColorBLACK) { 803 return alloc->make<SkARGB32_Black_Blitter>(device, *paint); 804 } else if (paint->getAlpha() == 0xFF) { 805 return alloc->make<SkARGB32_Opaque_Blitter>(device, *paint); 806 } else { 807 return alloc->make<SkARGB32_Blitter>(device, *paint); 808 } 809 810 case kRGB_565_SkColorType: 811 if (shaderContext && SkRGB565_Shader_Blitter::Supports(device, *paint)) { 812 return alloc->make<SkRGB565_Shader_Blitter>(device, *paint, shaderContext); 813 } else { 814 return create_SkRP_or_SkVMBlitter(); 815 } 816 817 default: 818 SkASSERT(false); 819 return alloc->make<SkNullBlitter>(); 820 } 821} 822 823/////////////////////////////////////////////////////////////////////////////// 824 825SkShaderBlitter::SkShaderBlitter(const SkPixmap& device, const SkPaint& paint, 826 SkShaderBase::Context* shaderContext) 827 : INHERITED(device) 828 , fShader(paint.getShader()) 829 , fShaderContext(shaderContext) { 830 SkASSERT(fShader); 831 SkASSERT(fShaderContext); 832 833 fShader->ref(); 834 fShaderFlags = fShaderContext->getFlags(); 835 fConstInY = SkToBool(fShaderFlags & SkShaderBase::kConstInY32_Flag); 836} 837 838SkShaderBlitter::~SkShaderBlitter() { 839 fShader->unref(); 840} 841 842/////////////////////////////////////////////////////////////////////////////////////////////////// 843 844#ifdef SK_DEBUG 845 846void SkRectClipCheckBlitter::blitH(int x, int y, int width) { 847 SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1))); 848 fBlitter->blitH(x, y, width); 849} 850 851void SkRectClipCheckBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) { 852 const int16_t* iter = runs; 853 for (; *iter; iter += *iter) 854 ; 855 int width = iter - runs; 856 SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1))); 857 fBlitter->blitAntiH(x, y, aa, runs); 858} 859 860void SkRectClipCheckBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 861 SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, height))); 862 fBlitter->blitV(x, y, height, alpha); 863} 864 865void SkRectClipCheckBlitter::blitRect(int x, int y, int width, int height) { 866 SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, height))); 867 fBlitter->blitRect(x, y, width, height); 868} 869 870void SkRectClipCheckBlitter::blitAntiRect(int x, int y, int width, int height, 871 SkAlpha leftAlpha, SkAlpha rightAlpha) { 872 bool skipLeft = !leftAlpha; 873 bool skipRight = !rightAlpha; 874 SkIRect r = SkIRect::MakeXYWH(x + skipLeft, y, width + 2 - skipRight - skipLeft, height); 875 SkASSERT(r.isEmpty() || fClipRect.contains(r)); 876 fBlitter->blitAntiRect(x, y, width, height, leftAlpha, rightAlpha); 877} 878 879void SkRectClipCheckBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 880 SkASSERT(mask.fBounds.contains(clip)); 881 SkASSERT(fClipRect.contains(clip)); 882 fBlitter->blitMask(mask, clip); 883} 884 885const SkPixmap* SkRectClipCheckBlitter::justAnOpaqueColor(uint32_t* value) { 886 return fBlitter->justAnOpaqueColor(value); 887} 888 889void SkRectClipCheckBlitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) { 890 SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 2, 1))); 891 fBlitter->blitAntiH2(x, y, a0, a1); 892} 893 894void SkRectClipCheckBlitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) { 895 SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, 2))); 896 fBlitter->blitAntiV2(x, y, a0, a1); 897} 898 899#endif 900