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