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