• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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