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