xref: /aosp_15_r20/external/skia/src/core/SkBlitter.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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