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