• 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 "SkBlitter.h"
9 
10 #include "SkAntiRun.h"
11 #include "SkArenaAlloc.h"
12 #include "SkColor.h"
13 #include "SkColorData.h"
14 #include "SkColorFilter.h"
15 #include "SkMask.h"
16 #include "SkMaskFilterBase.h"
17 #include "SkPaintPriv.h"
18 #include "SkReadBuffer.h"
19 #include "SkRegionPriv.h"
20 #include "SkShaderBase.h"
21 #include "SkString.h"
22 #include "SkTLazy.h"
23 #include "SkTo.h"
24 #include "SkUtils.h"
25 #include "SkWriteBuffer.h"
26 #include "SkXfermodeInterpretation.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 
blitCoverageDeltas(SkCoverageDeltaList * deltas,const SkIRect & clip,bool isEvenOdd,bool isInverse,bool isConvex)105 void SkBlitter::blitCoverageDeltas(SkCoverageDeltaList* deltas, const SkIRect& clip,
106                                    bool isEvenOdd, bool isInverse, bool isConvex) {
107     int         runSize = clip.width() + 1; // +1 so we can set runs[clip.width()] = 0
108     void*       storage = this->allocBlitMemory(runSize * (sizeof(int16_t) + sizeof(SkAlpha)));
109     int16_t*    runs    = reinterpret_cast<int16_t*>(storage);
110     SkAlpha*    alphas  = reinterpret_cast<SkAlpha*>(runs + runSize);
111     runs[clip.width()]  = 0; // we must set the last run to 0 so blitAntiH can stop there
112 
113     bool canUseMask = !deltas->forceRLE() &&
114                       SkCoverageDeltaMask::CanHandle(SkIRect::MakeLTRB(0, 0, clip.width(), 1));
115     const SkAntiRect& antiRect = deltas->getAntiRect();
116 
117     // Only access rows within our clip. Otherwise, we'll have data race in the threaded backend.
118     int top = SkTMax(deltas->top(), clip.fTop);
119     int bottom = SkTMin(deltas->bottom(), clip.fBottom);
120     for(int y = top; y < bottom; ++y) {
121         // If antiRect is non-empty and we're in it, blit it and skip to the bottom
122         if (y >= antiRect.fY && y < antiRect.fY + antiRect.fHeight) {
123             // Clip the antiRect because of possible tilings (e.g., the threaded backend)
124             int leftOverClip = clip.fLeft - antiRect.fX;
125             int rightOverClip = antiRect.fX + antiRect.fWidth - clip.fRight;
126             int topOverClip = clip.fTop - antiRect.fY;
127             int botOverClip = antiRect.fY + antiRect.fHeight - clip.fBottom;
128 
129             int rectX = antiRect.fX;
130             int rectY = antiRect.fY;
131             int width = antiRect.fWidth;
132             int height = antiRect.fHeight;
133             SkAlpha leftAlpha = antiRect.fLeftAlpha;
134             SkAlpha rightAlpha = antiRect.fRightAlpha;
135 
136             if (leftOverClip > 0) {
137                 rectX = clip.fLeft;
138                 width -= leftOverClip;
139                 leftAlpha = 0xFF;
140             }
141             if (rightOverClip > 0) {
142                 width -= rightOverClip;
143                 rightAlpha = 0xFF;
144             }
145             if (topOverClip > 0) {
146                 rectY = clip.fTop;
147                 height -= topOverClip;
148             }
149             if (botOverClip > 0) {
150                 height -= botOverClip;
151             }
152 
153             if (width >= 0) {
154                 this->blitAntiRect(rectX, rectY, width, height, leftAlpha, rightAlpha);
155             }
156             y += antiRect.fHeight - 1; // -1 because ++y in the for loop
157             continue;
158         }
159 
160         // If there are too many deltas, sorting will be slow. Using a mask is much faster.
161         // This is such an important optimization that will bring ~2x speedup for benches like
162         // path_fill_small_long_line and path_stroke_small_sawtooth.
163         if (canUseMask && !deltas->sorted(y) && deltas->count(y) << 3 >= clip.width()) {
164             // Note that deltas->left()/right() may be different than clip.fLeft/fRight because in
165             // the threaded backend, deltas are generated in the initFn with full clip, while
166             // blitCoverageDeltas is called in drawFn with a subclip. For inverse fill, the clip
167             // might be wider than deltas' bounds (which is clippedIR).
168             SkIRect rowIR = SkIRect::MakeLTRB(SkTMin(clip.fLeft, deltas->left()), y,
169                                               SkTMax(clip.fRight, deltas->right()), y + 1);
170             SkSTArenaAlloc<SkCoverageDeltaMask::MAX_SIZE> alloc;
171             SkCoverageDeltaMask mask(&alloc, rowIR);
172             for(int i = 0; i < deltas->count(y); ++i) {
173                 const SkCoverageDelta& delta = deltas->getDelta(y, i);
174                 mask.addDelta(delta.fX, y, delta.fDelta);
175             }
176             mask.convertCoverageToAlpha(isEvenOdd, isInverse, isConvex);
177             this->blitMask(mask.prepareSkMask(), rowIR);
178             continue;
179         }
180 
181         // The normal flow of blitting deltas starts from here. First sort deltas.
182         deltas->sort(y);
183 
184         int     i = 0;              // init delta index to 0
185         int     lastX = clip.fLeft; // init x to clip.fLeft
186         SkFixed coverage = 0;       // init coverage to 0
187 
188         // skip deltas with x less than clip.fLeft; they may be:
189         //   1. precision errors
190         //   2. deltas generated during init-once phase (threaded backend) that has a wider
191         //      clip than the final tile clip.
192         for(; i < deltas->count(y) && deltas->getDelta(y, i).fX < clip.fLeft; ++i) {
193             coverage += deltas->getDelta(y, i).fDelta;
194         }
195         for(; i < deltas->count(y) && deltas->getDelta(y, i).fX < clip.fRight; ++i) {
196             const SkCoverageDelta& delta = deltas->getDelta(y, i);
197             SkASSERT(delta.fX >= lastX);    // delta must be x sorted
198             if (delta.fX > lastX) {         // we have proceeded to a new x (different from lastX)
199                 SkAlpha alpha = isConvex ? ConvexCoverageToAlpha(coverage, isInverse)
200                                          : CoverageToAlpha(coverage, isEvenOdd, isInverse);
201                 alphas[lastX - clip.fLeft]  = alpha;            // set alpha at lastX
202                 runs[lastX - clip.fLeft]    = delta.fX - lastX; // set the run length
203                 lastX                       = delta.fX;         // now set lastX to current x
204             }
205             coverage += delta.fDelta; // cumulate coverage with the current delta
206         }
207 
208         // Set the alpha and run length from the right-most delta to the right clip boundary
209         SkAlpha alpha = isConvex ? ConvexCoverageToAlpha(coverage, isInverse)
210                                  : CoverageToAlpha(coverage, isEvenOdd, isInverse);
211         alphas[lastX - clip.fLeft]  = alpha;
212         runs[lastX - clip.fLeft]    = clip.fRight - lastX;
213 
214         this->blitAntiH(clip.fLeft, y, alphas, runs); // finally blit the current row
215     }
216 }
217 
blitV(int x,int y,int height,SkAlpha alpha)218 void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
219     if (alpha == 255) {
220         this->blitRect(x, y, 1, height);
221     } else {
222         int16_t runs[2];
223         runs[0] = 1;
224         runs[1] = 0;
225 
226         while (--height >= 0) {
227             this->blitAntiH(x, y++, &alpha, runs);
228         }
229     }
230 }
231 
blitRect(int x,int y,int width,int height)232 void SkBlitter::blitRect(int x, int y, int width, int height) {
233     SkASSERT(width > 0);
234     while (--height >= 0) {
235         this->blitH(x, y++, width);
236     }
237 }
238 
239 /// Default implementation doesn't check for easy optimizations
240 /// such as alpha == 255; also uses blitV(), which some subclasses
241 /// may not support.
blitAntiRect(int x,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)242 void SkBlitter::blitAntiRect(int x, int y, int width, int height,
243                              SkAlpha leftAlpha, SkAlpha rightAlpha) {
244     if (leftAlpha > 0) { // we may send in x = -1 with leftAlpha = 0
245         this->blitV(x, y, height, leftAlpha);
246     }
247     x++;
248     if (width > 0) {
249         this->blitRect(x, y, width, height);
250         x += width;
251     }
252     if (rightAlpha > 0) {
253         this->blitV(x, y, height, rightAlpha);
254     }
255 }
256 
257 //////////////////////////////////////////////////////////////////////////////
258 
bits_to_runs(SkBlitter * blitter,int x,int y,const uint8_t bits[],uint8_t left_mask,ptrdiff_t rowBytes,uint8_t right_mask)259 static inline void bits_to_runs(SkBlitter* blitter, int x, int y,
260                                 const uint8_t bits[],
261                                 uint8_t left_mask, ptrdiff_t rowBytes,
262                                 uint8_t right_mask) {
263     int inFill = 0;
264     int pos = 0;
265 
266     while (--rowBytes >= 0) {
267         uint8_t b = *bits++ & left_mask;
268         if (rowBytes == 0) {
269             b &= right_mask;
270         }
271 
272         for (uint8_t test = 0x80U; test != 0; test >>= 1) {
273             if (b & test) {
274                 if (!inFill) {
275                     pos = x;
276                     inFill = true;
277                 }
278             } else {
279                 if (inFill) {
280                     blitter->blitH(pos, y, x - pos);
281                     inFill = false;
282                 }
283             }
284             x += 1;
285         }
286         left_mask = 0xFFU;
287     }
288 
289     // final cleanup
290     if (inFill) {
291         blitter->blitH(pos, y, x - pos);
292     }
293 }
294 
295 // 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)296 static uint8_t generate_right_mask(int maskBitCount) {
297     return static_cast<uint8_t>((0xFF00U >> maskBitCount) & 0xFF);
298 }
299 
blitMask(const SkMask & mask,const SkIRect & clip)300 void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
301     SkASSERT(mask.fBounds.contains(clip));
302 
303     if (mask.fFormat == SkMask::kLCD16_Format) {
304         return; // needs to be handled by subclass
305     }
306 
307     if (mask.fFormat == SkMask::kBW_Format) {
308         int cx = clip.fLeft;
309         int cy = clip.fTop;
310         int maskLeft = mask.fBounds.fLeft;
311         int maskRowBytes = mask.fRowBytes;
312         int height = clip.height();
313 
314         const uint8_t* bits = mask.getAddr1(cx, cy);
315 
316         SkDEBUGCODE(const uint8_t* endOfImage =
317             mask.fImage + (mask.fBounds.height() - 1) * maskRowBytes
318             + ((mask.fBounds.width() + 7) >> 3));
319 
320         if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
321             while (--height >= 0) {
322                 int affectedRightBit = mask.fBounds.width() - 1;
323                 ptrdiff_t rowBytes = (affectedRightBit >> 3) + 1;
324                 SkASSERT(bits + rowBytes <= endOfImage);
325                 U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
326                 bits_to_runs(this, cx, cy, bits, 0xFF, rowBytes, rightMask);
327                 bits += maskRowBytes;
328                 cy += 1;
329             }
330         } else {
331             // Bits is calculated as the offset into the mask at the point {cx, cy} therefore, all
332             // addressing into the bit mask is relative to that point. Since this is an address
333             // calculated from a arbitrary bit in that byte, calculate the left most bit.
334             int bitsLeft = cx - ((cx - maskLeft) & 7);
335 
336             // Everything is relative to the bitsLeft.
337             int leftEdge = cx - bitsLeft;
338             SkASSERT(leftEdge >= 0);
339             int rightEdge = clip.fRight - bitsLeft;
340             SkASSERT(rightEdge > leftEdge);
341 
342             // Calculate left byte and mask
343             const uint8_t* leftByte = bits;
344             U8CPU leftMask = 0xFFU >> (leftEdge & 7);
345 
346             // Calculate right byte and mask
347             int affectedRightBit = rightEdge - 1;
348             const uint8_t* rightByte = bits + (affectedRightBit >> 3);
349             U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
350 
351             // leftByte and rightByte are byte locations therefore, to get a count of bytes the
352             // code must add one.
353             ptrdiff_t rowBytes = rightByte - leftByte + 1;
354 
355             while (--height >= 0) {
356                 SkASSERT(bits + rowBytes <= endOfImage);
357                 bits_to_runs(this, bitsLeft, cy, bits, leftMask, rowBytes, rightMask);
358                 bits += maskRowBytes;
359                 cy += 1;
360             }
361         }
362     } else {
363         int                         width = clip.width();
364         SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
365         int16_t*                    runs = runStorage.get();
366         const uint8_t*              aa = mask.getAddr8(clip.fLeft, clip.fTop);
367 
368         sk_memset16((uint16_t*)runs, 1, width);
369         runs[width] = 0;
370 
371         int height = clip.height();
372         int y = clip.fTop;
373         while (--height >= 0) {
374             this->blitAntiH(clip.fLeft, y, aa, runs);
375             aa += mask.fRowBytes;
376             y += 1;
377         }
378     }
379 }
380 
381 /////////////////////// these guys are not virtual, just a helpers
382 
blitMaskRegion(const SkMask & mask,const SkRegion & clip)383 void SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
384     if (clip.quickReject(mask.fBounds)) {
385         return;
386     }
387 
388     SkRegion::Cliperator clipper(clip, mask.fBounds);
389 
390     while (!clipper.done()) {
391         const SkIRect& cr = clipper.rect();
392         this->blitMask(mask, cr);
393         clipper.next();
394     }
395 }
396 
blitRectRegion(const SkIRect & rect,const SkRegion & clip)397 void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
398     SkRegion::Cliperator clipper(clip, rect);
399 
400     while (!clipper.done()) {
401         const SkIRect& cr = clipper.rect();
402         this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
403         clipper.next();
404     }
405 }
406 
blitRegion(const SkRegion & clip)407 void SkBlitter::blitRegion(const SkRegion& clip) {
408     SkRegionPriv::VisitSpans(clip, [this](const SkIRect& r) {
409         this->blitRect(r.left(), r.top(), r.width(), r.height());
410     });
411 }
412 
413 ///////////////////////////////////////////////////////////////////////////////
414 
blitH(int x,int y,int width)415 void SkNullBlitter::blitH(int x, int y, int width) {}
416 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])417 void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
418                               const int16_t runs[]) {}
419 
blitV(int x,int y,int height,SkAlpha alpha)420 void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
421 
blitRect(int x,int y,int width,int height)422 void SkNullBlitter::blitRect(int x, int y, int width, int height) {}
423 
blitMask(const SkMask & mask,const SkIRect & clip)424 void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
425 
justAnOpaqueColor(uint32_t * value)426 const SkPixmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
427     return nullptr;
428 }
429 
isNullBlitter() const430 bool SkNullBlitter::isNullBlitter() const { return true; }
431 
432 ///////////////////////////////////////////////////////////////////////////////
433 
compute_anti_width(const int16_t runs[])434 static int compute_anti_width(const int16_t runs[]) {
435     int width = 0;
436 
437     for (;;) {
438         int count = runs[0];
439 
440         SkASSERT(count >= 0);
441         if (count == 0) {
442             break;
443         }
444         width += count;
445         runs += count;
446     }
447     return width;
448 }
449 
y_in_rect(int y,const SkIRect & rect)450 static inline bool y_in_rect(int y, const SkIRect& rect) {
451     return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
452 }
453 
x_in_rect(int x,const SkIRect & rect)454 static inline bool x_in_rect(int x, const SkIRect& rect) {
455     return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
456 }
457 
blitH(int left,int y,int width)458 void SkRectClipBlitter::blitH(int left, int y, int width) {
459     SkASSERT(width > 0);
460 
461     if (!y_in_rect(y, fClipRect)) {
462         return;
463     }
464 
465     int right = left + width;
466 
467     if (left < fClipRect.fLeft) {
468         left = fClipRect.fLeft;
469     }
470     if (right > fClipRect.fRight) {
471         right = fClipRect.fRight;
472     }
473 
474     width = right - left;
475     if (width > 0) {
476         fBlitter->blitH(left, y, width);
477     }
478 }
479 
blitAntiH(int left,int y,const SkAlpha aa[],const int16_t runs[])480 void SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
481                                   const int16_t runs[]) {
482     if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
483         return;
484     }
485 
486     int x0 = left;
487     int x1 = left + compute_anti_width(runs);
488 
489     if (x1 <= fClipRect.fLeft) {
490         return;
491     }
492 
493     SkASSERT(x0 < x1);
494     if (x0 < fClipRect.fLeft) {
495         int dx = fClipRect.fLeft - x0;
496         SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
497         runs += dx;
498         aa += dx;
499         x0 = fClipRect.fLeft;
500     }
501 
502     SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
503     if (x1 > fClipRect.fRight) {
504         x1 = fClipRect.fRight;
505         SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
506         ((int16_t*)runs)[x1 - x0] = 0;
507     }
508 
509     SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
510     SkASSERT(compute_anti_width(runs) == x1 - x0);
511 
512     fBlitter->blitAntiH(x0, y, aa, runs);
513 }
514 
blitV(int x,int y,int height,SkAlpha alpha)515 void SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
516     SkASSERT(height > 0);
517 
518     if (!x_in_rect(x, fClipRect)) {
519         return;
520     }
521 
522     int y0 = y;
523     int y1 = y + height;
524 
525     if (y0 < fClipRect.fTop) {
526         y0 = fClipRect.fTop;
527     }
528     if (y1 > fClipRect.fBottom) {
529         y1 = fClipRect.fBottom;
530     }
531 
532     if (y0 < y1) {
533         fBlitter->blitV(x, y0, y1 - y0, alpha);
534     }
535 }
536 
blitRect(int left,int y,int width,int height)537 void SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
538     SkIRect    r;
539 
540     r.set(left, y, left + width, y + height);
541     if (r.intersect(fClipRect)) {
542         fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
543     }
544 }
545 
blitAntiRect(int left,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)546 void SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height,
547                                      SkAlpha leftAlpha, SkAlpha rightAlpha) {
548     SkIRect    r;
549 
550     // The *true* width of the rectangle blitted is width+2:
551     r.set(left, y, left + width + 2, y + height);
552     if (r.intersect(fClipRect)) {
553         if (r.fLeft != left) {
554             SkASSERT(r.fLeft > left);
555             leftAlpha = 255;
556         }
557         if (r.fRight != left + width + 2) {
558             SkASSERT(r.fRight < left + width + 2);
559             rightAlpha = 255;
560         }
561         if (255 == leftAlpha && 255 == rightAlpha) {
562             fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
563         } else if (1 == r.width()) {
564             if (r.fLeft == left) {
565                 fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha);
566             } else {
567                 SkASSERT(r.fLeft == left + width + 1);
568                 fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha);
569             }
570         } else {
571             fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
572                                    leftAlpha, rightAlpha);
573         }
574     }
575 }
576 
blitMask(const SkMask & mask,const SkIRect & clip)577 void SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
578     SkASSERT(mask.fBounds.contains(clip));
579 
580     SkIRect    r = clip;
581 
582     if (r.intersect(fClipRect)) {
583         fBlitter->blitMask(mask, r);
584     }
585 }
586 
justAnOpaqueColor(uint32_t * value)587 const SkPixmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
588     return fBlitter->justAnOpaqueColor(value);
589 }
590 
591 ///////////////////////////////////////////////////////////////////////////////
592 
blitH(int x,int y,int width)593 void SkRgnClipBlitter::blitH(int x, int y, int width) {
594     SkRegion::Spanerator span(*fRgn, y, x, x + width);
595     int left, right;
596 
597     while (span.next(&left, &right)) {
598         SkASSERT(left < right);
599         fBlitter->blitH(left, y, right - left);
600     }
601 }
602 
blitAntiH(int x,int y,const SkAlpha aa[],const int16_t runs[])603 void SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
604                                  const int16_t runs[]) {
605     int width = compute_anti_width(runs);
606     SkRegion::Spanerator span(*fRgn, y, x, x + width);
607     int left, right;
608     SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
609 
610     int prevRite = x;
611     while (span.next(&left, &right)) {
612         SkASSERT(x <= left);
613         SkASSERT(left < right);
614         SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
615 
616         SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
617 
618         // now zero before left
619         if (left > prevRite) {
620             int index = prevRite - x;
621             ((uint8_t*)aa)[index] = 0;   // skip runs after right
622             ((int16_t*)runs)[index] = SkToS16(left - prevRite);
623         }
624 
625         prevRite = right;
626     }
627 
628     if (prevRite > x) {
629         ((int16_t*)runs)[prevRite - x] = 0;
630 
631         if (x < 0) {
632             int skip = runs[0];
633             SkASSERT(skip >= -x);
634             aa += skip;
635             runs += skip;
636             x += skip;
637         }
638         fBlitter->blitAntiH(x, y, aa, runs);
639     }
640 }
641 
blitV(int x,int y,int height,SkAlpha alpha)642 void SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
643     SkIRect    bounds;
644     bounds.set(x, y, x + 1, y + height);
645 
646     SkRegion::Cliperator    iter(*fRgn, bounds);
647 
648     while (!iter.done()) {
649         const SkIRect& r = iter.rect();
650         SkASSERT(bounds.contains(r));
651 
652         fBlitter->blitV(x, r.fTop, r.height(), alpha);
653         iter.next();
654     }
655 }
656 
blitRect(int x,int y,int width,int height)657 void SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
658     SkIRect    bounds;
659     bounds.set(x, y, x + width, y + height);
660 
661     SkRegion::Cliperator    iter(*fRgn, bounds);
662 
663     while (!iter.done()) {
664         const SkIRect& r = iter.rect();
665         SkASSERT(bounds.contains(r));
666 
667         fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
668         iter.next();
669     }
670 }
671 
blitAntiRect(int x,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)672 void SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height,
673                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
674     // The *true* width of the rectangle to blit is width + 2
675     SkIRect    bounds;
676     bounds.set(x, y, x + width + 2, y + height);
677 
678     SkRegion::Cliperator    iter(*fRgn, bounds);
679 
680     while (!iter.done()) {
681         const SkIRect& r = iter.rect();
682         SkASSERT(bounds.contains(r));
683         SkASSERT(r.fLeft >= x);
684         SkASSERT(r.fRight <= x + width + 2);
685 
686         SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255;
687         SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ?
688                                       rightAlpha : 255;
689 
690         if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) {
691             fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
692         } else if (1 == r.width()) {
693             if (r.fLeft == x) {
694                 fBlitter->blitV(r.fLeft, r.fTop, r.height(),
695                                 effectiveLeftAlpha);
696             } else {
697                 SkASSERT(r.fLeft == x + width + 1);
698                 fBlitter->blitV(r.fLeft, r.fTop, r.height(),
699                                 effectiveRightAlpha);
700             }
701         } else {
702             fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
703                                    effectiveLeftAlpha, effectiveRightAlpha);
704         }
705         iter.next();
706     }
707 }
708 
709 
blitMask(const SkMask & mask,const SkIRect & clip)710 void SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
711     SkASSERT(mask.fBounds.contains(clip));
712 
713     SkRegion::Cliperator iter(*fRgn, clip);
714     const SkIRect&       r = iter.rect();
715     SkBlitter*           blitter = fBlitter;
716 
717     while (!iter.done()) {
718         blitter->blitMask(mask, r);
719         iter.next();
720     }
721 }
722 
justAnOpaqueColor(uint32_t * value)723 const SkPixmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
724     return fBlitter->justAnOpaqueColor(value);
725 }
726 
727 ///////////////////////////////////////////////////////////////////////////////
728 
apply(SkBlitter * blitter,const SkRegion * clip,const SkIRect * ir)729 SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
730                                    const SkIRect* ir) {
731     if (clip) {
732         const SkIRect& clipR = clip->getBounds();
733 
734         if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
735             blitter = &fNullBlitter;
736         } else if (clip->isRect()) {
737             if (ir == nullptr || !clipR.contains(*ir)) {
738                 fRectBlitter.init(blitter, clipR);
739                 blitter = &fRectBlitter;
740             }
741         } else {
742             fRgnBlitter.init(blitter, clip);
743             blitter = &fRgnBlitter;
744         }
745     }
746     return blitter;
747 }
748 
749 ///////////////////////////////////////////////////////////////////////////////
750 
751 #include "SkCoreBlitters.h"
752 
753 // hack for testing, not to be exposed to clients
754 bool gSkForceRasterPipelineBlitter;
755 
UseRasterPipelineBlitter(const SkPixmap & device,const SkPaint & paint,const SkMatrix & matrix)756 bool SkBlitter::UseRasterPipelineBlitter(const SkPixmap& device, const SkPaint& paint,
757                                          const SkMatrix& matrix) {
758     if (gSkForceRasterPipelineBlitter) {
759         return true;
760     }
761 #if 0 || defined(SK_FORCE_RASTER_PIPELINE_BLITTER)
762     return true;
763 #else
764 
765     const SkMaskFilterBase* mf = as_MFB(paint.getMaskFilter());
766 
767     // The legacy blitters cannot handle any of these complex features (anymore).
768     if (device.alphaType() == kUnpremul_SkAlphaType        ||
769         matrix.hasPerspective()                            ||
770         paint.getColorFilter()                             ||
771         paint.getBlendMode() > SkBlendMode::kLastCoeffMode ||
772         paint.getFilterQuality() == kHigh_SkFilterQuality  ||
773         (mf && mf->getFormat() == SkMask::k3D_Format)) {
774         return true;
775     }
776 
777     // All the real legacy fast paths are for shaders and SrcOver.
778     // Choosing SkRasterPipelineBlitter will also let us to hit its single-color memset path.
779     if (!paint.getShader() && paint.getBlendMode() != SkBlendMode::kSrcOver) {
780         return true;
781     }
782 
783     auto cs = device.colorSpace();
784     // We check (indirectly via makeContext()) later on if the shader can handle the colorspace
785     // in legacy mode, so here we just focus on if a single color needs raster-pipeline.
786     if (cs && !paint.getShader()) {
787         if (!paint.getColor4f().fitsInBytes() || !cs->isSRGB()) {
788             return true;
789         }
790     }
791 
792     // Only kN32 and 565 are handled by legacy blitters now, 565 mostly just for Android.
793     return device.colorType() != kN32_SkColorType
794         && device.colorType() != kRGB_565_SkColorType;
795 #endif
796 }
797 
Choose(const SkPixmap & device,const SkMatrix & matrix,const SkPaint & origPaint,SkArenaAlloc * alloc,bool drawCoverage)798 SkBlitter* SkBlitter::Choose(const SkPixmap& device,
799                              const SkMatrix& matrix,
800                              const SkPaint& origPaint,
801                              SkArenaAlloc* alloc,
802                              bool drawCoverage) {
803     SkASSERT(alloc);
804 
805     if (kUnknown_SkColorType == device.colorType()) {
806         return alloc->make<SkNullBlitter>();
807     }
808 
809     // We may tweak the original paint as we go.
810     SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
811 
812     // We have the most fast-paths for SrcOver, so see if we can act like SrcOver.
813     if (paint->getBlendMode() != SkBlendMode::kSrcOver) {
814         switch (SkInterpretXfermode(*paint, SkColorTypeIsAlwaysOpaque(device.colorType()))) {
815             case kSrcOver_SkXfermodeInterpretation:
816                 paint.writable()->setBlendMode(SkBlendMode::kSrcOver);
817                 break;
818             case kSkipDrawing_SkXfermodeInterpretation:
819                 return alloc->make<SkNullBlitter>();
820             default:
821                 break;
822         }
823     }
824 
825     // A Clear blend mode will ignore the entire color pipeline, as if Src mode with 0x00000000.
826     if (paint->getBlendMode() == SkBlendMode::kClear) {
827         SkPaint* p = paint.writable();
828         p->setShader(nullptr);
829         p->setColorFilter(nullptr);
830         p->setBlendMode(SkBlendMode::kSrc);
831         p->setColor(0x00000000);
832     }
833 
834     if (drawCoverage) {
835         if (device.colorType() == kAlpha_8_SkColorType) {
836             SkASSERT(!paint->getShader());
837             SkASSERT(paint->isSrcOver());
838             return alloc->make<SkA8_Coverage_Blitter>(device, *paint);
839         }
840         return alloc->make<SkNullBlitter>();
841     }
842 
843     if (paint->isDither() && !SkPaintPriv::ShouldDither(*paint, device.colorType())) {
844         paint.writable()->setDither(false);
845     }
846 
847     // We'll end here for many interesting cases: color spaces, color filters, most color types.
848     if (UseRasterPipelineBlitter(device, *paint, matrix)) {
849         auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
850         SkASSERT(blitter);
851         return blitter;
852     }
853 
854     // Everything but legacy kN32_SkColorType and kRGB_565_SkColorType should already be handled.
855     SkASSERT(device.colorType() == kN32_SkColorType ||
856              device.colorType() == kRGB_565_SkColorType);
857 
858     // And we should either have a shader, be blending with SrcOver, or both.
859     SkASSERT(paint->getShader() || paint->getBlendMode() == SkBlendMode::kSrcOver);
860 
861     // Legacy blitters keep their shader state on a shader context.
862     SkShaderBase::Context* shaderContext = nullptr;
863     if (paint->getShader()) {
864         shaderContext = as_SB(paint->getShader())->makeContext(
865                 {*paint, matrix, nullptr, device.colorType(), device.colorSpace()},
866                 alloc);
867 
868         // Creating the context isn't always possible... we'll just fall back to raster pipeline.
869         if (!shaderContext) {
870             auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
871             SkASSERT(blitter);
872             return blitter;
873         }
874     }
875 
876     switch (device.colorType()) {
877         case kN32_SkColorType:
878             if (shaderContext) {
879                 return alloc->make<SkARGB32_Shader_Blitter>(device, *paint, shaderContext);
880             } else if (paint->getColor() == SK_ColorBLACK) {
881                 return alloc->make<SkARGB32_Black_Blitter>(device, *paint);
882             } else if (paint->getAlpha() == 0xFF) {
883                 return alloc->make<SkARGB32_Opaque_Blitter>(device, *paint);
884             } else {
885                 return alloc->make<SkARGB32_Blitter>(device, *paint);
886             }
887 
888         case kRGB_565_SkColorType:
889             if (shaderContext && SkRGB565_Shader_Blitter::Supports(device, *paint)) {
890                 return alloc->make<SkRGB565_Shader_Blitter>(device, *paint, shaderContext);
891             } else {
892                 return SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
893             }
894 
895         default:
896             SkASSERT(false);
897             return alloc->make<SkNullBlitter>();
898     }
899 }
900 
901 ///////////////////////////////////////////////////////////////////////////////
902 
SkShaderBlitter(const SkPixmap & device,const SkPaint & paint,SkShaderBase::Context * shaderContext)903 SkShaderBlitter::SkShaderBlitter(const SkPixmap& device, const SkPaint& paint,
904                                  SkShaderBase::Context* shaderContext)
905         : INHERITED(device)
906         , fShader(paint.getShader())
907         , fShaderContext(shaderContext) {
908     SkASSERT(fShader);
909     SkASSERT(fShaderContext);
910 
911     fShader->ref();
912     fShaderFlags = fShaderContext->getFlags();
913     fConstInY = SkToBool(fShaderFlags & SkShaderBase::kConstInY32_Flag);
914 }
915 
~SkShaderBlitter()916 SkShaderBlitter::~SkShaderBlitter() {
917     fShader->unref();
918 }
919 
920 ///////////////////////////////////////////////////////////////////////////////////////////////////
921 
922 #ifdef SK_DEBUG
923 
blitH(int x,int y,int width)924 void SkRectClipCheckBlitter::blitH(int x, int y, int width) {
925     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
926     fBlitter->blitH(x, y, width);
927 }
928 
blitAntiH(int x,int y,const SkAlpha aa[],const int16_t runs[])929 void SkRectClipCheckBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) {
930     const int16_t* iter = runs;
931     for (; *iter; iter += *iter)
932         ;
933     int width = iter - runs;
934     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
935     fBlitter->blitAntiH(x, y, aa, runs);
936 }
937 
blitV(int x,int y,int height,SkAlpha alpha)938 void SkRectClipCheckBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
939     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, height)));
940     fBlitter->blitV(x, y, height, alpha);
941 }
942 
blitRect(int x,int y,int width,int height)943 void SkRectClipCheckBlitter::blitRect(int x, int y, int width, int height) {
944     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, height)));
945     fBlitter->blitRect(x, y, width, height);
946 }
947 
blitAntiRect(int x,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)948 void SkRectClipCheckBlitter::blitAntiRect(int x, int y, int width, int height,
949                                      SkAlpha leftAlpha, SkAlpha rightAlpha) {
950     bool skipLeft = !leftAlpha;
951     bool skipRight = !rightAlpha;
952 #ifdef SK_DEBUG
953     SkIRect r = SkIRect::MakeXYWH(x + skipLeft, y, width + 2 - skipRight - skipLeft, height);
954     SkASSERT(r.isEmpty() || fClipRect.contains(r));
955 #endif
956     fBlitter->blitAntiRect(x, y, width, height, leftAlpha, rightAlpha);
957 }
958 
blitMask(const SkMask & mask,const SkIRect & clip)959 void SkRectClipCheckBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
960     SkASSERT(mask.fBounds.contains(clip));
961     SkASSERT(fClipRect.contains(clip));
962     fBlitter->blitMask(mask, clip);
963 }
964 
justAnOpaqueColor(uint32_t * value)965 const SkPixmap* SkRectClipCheckBlitter::justAnOpaqueColor(uint32_t* value) {
966     return fBlitter->justAnOpaqueColor(value);
967 }
968 
blitAntiH2(int x,int y,U8CPU a0,U8CPU a1)969 void SkRectClipCheckBlitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
970     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 2, 1)));
971     fBlitter->blitAntiH2(x, y, a0, a1);
972 }
973 
blitAntiV2(int x,int y,U8CPU a0,U8CPU a1)974 void SkRectClipCheckBlitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
975     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, 2)));
976     fBlitter->blitAntiV2(x, y, a0, a1);
977 }
978 
979 #endif
980