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