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