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