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