Line data Source code
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 "SkArenaAlloc.h"
9 : #include "SkBlitter.h"
10 : #include "SkAntiRun.h"
11 : #include "SkColor.h"
12 : #include "SkColorFilter.h"
13 : #include "SkReadBuffer.h"
14 : #include "SkWriteBuffer.h"
15 : #include "SkMask.h"
16 : #include "SkMaskFilter.h"
17 : #include "SkString.h"
18 : #include "SkTLazy.h"
19 : #include "SkUtils.h"
20 : #include "SkXfermodeInterpretation.h"
21 :
22 : // define this for testing srgb blits
23 : //#define SK_FORCE_PM4f_FOR_L32_BLITS
24 :
25 2033 : SkBlitter::~SkBlitter() {}
26 :
27 0 : bool SkBlitter::isNullBlitter() const { return false; }
28 :
29 0 : const SkPixmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
30 0 : return nullptr;
31 : }
32 :
33 : /*
34 : void SkBlitter::blitH(int x, int y, int width) {
35 : SkDEBUGFAIL("unimplemented");
36 : }
37 :
38 :
39 : void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
40 : const int16_t runs[]) {
41 : SkDEBUGFAIL("unimplemented");
42 : }
43 : */
44 :
45 0 : void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
46 0 : if (alpha == 255) {
47 0 : this->blitRect(x, y, 1, height);
48 : } else {
49 : int16_t runs[2];
50 0 : runs[0] = 1;
51 0 : runs[1] = 0;
52 :
53 0 : while (--height >= 0) {
54 0 : this->blitAntiH(x, y++, &alpha, runs);
55 : }
56 : }
57 0 : }
58 :
59 9 : void SkBlitter::blitRect(int x, int y, int width, int height) {
60 9 : SkASSERT(width > 0);
61 671 : while (--height >= 0) {
62 331 : this->blitH(x, y++, width);
63 : }
64 9 : }
65 :
66 : /// Default implementation doesn't check for easy optimizations
67 : /// such as alpha == 255; also uses blitV(), which some subclasses
68 : /// may not support.
69 7 : void SkBlitter::blitAntiRect(int x, int y, int width, int height,
70 : SkAlpha leftAlpha, SkAlpha rightAlpha) {
71 7 : if (leftAlpha > 0) { // we may send in x = -1 with leftAlpha = 0
72 0 : this->blitV(x, y, height, leftAlpha);
73 : }
74 7 : x++;
75 7 : if (width > 0) {
76 7 : this->blitRect(x, y, width, height);
77 7 : x += width;
78 : }
79 7 : if (rightAlpha > 0) {
80 0 : this->blitV(x, y, height, rightAlpha);
81 : }
82 7 : }
83 :
84 : //////////////////////////////////////////////////////////////////////////////
85 :
86 0 : static inline void bits_to_runs(SkBlitter* blitter, int x, int y,
87 : const uint8_t bits[],
88 : uint8_t left_mask, ptrdiff_t rowBytes,
89 : uint8_t right_mask) {
90 0 : int inFill = 0;
91 0 : int pos = 0;
92 :
93 0 : while (--rowBytes >= 0) {
94 0 : uint8_t b = *bits++ & left_mask;
95 0 : if (rowBytes == 0) {
96 0 : b &= right_mask;
97 : }
98 :
99 0 : for (uint8_t test = 0x80U; test != 0; test >>= 1) {
100 0 : if (b & test) {
101 0 : if (!inFill) {
102 0 : pos = x;
103 0 : inFill = true;
104 : }
105 : } else {
106 0 : if (inFill) {
107 0 : blitter->blitH(pos, y, x - pos);
108 0 : inFill = false;
109 : }
110 : }
111 0 : x += 1;
112 : }
113 0 : left_mask = 0xFFU;
114 : }
115 :
116 : // final cleanup
117 0 : if (inFill) {
118 0 : blitter->blitH(pos, y, x - pos);
119 : }
120 0 : }
121 :
122 : // maskBitCount is the number of 1's to place in the mask. It must be in the range between 1 and 8.
123 0 : static uint8_t generate_right_mask(int maskBitCount) {
124 0 : return static_cast<uint8_t>(0xFF00U >> maskBitCount);
125 : }
126 :
127 0 : void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
128 0 : SkASSERT(mask.fBounds.contains(clip));
129 :
130 0 : if (mask.fFormat == SkMask::kLCD16_Format) {
131 0 : return; // needs to be handled by subclass
132 : }
133 :
134 0 : if (mask.fFormat == SkMask::kBW_Format) {
135 0 : int cx = clip.fLeft;
136 0 : int cy = clip.fTop;
137 0 : int maskLeft = mask.fBounds.fLeft;
138 0 : int maskRowBytes = mask.fRowBytes;
139 0 : int height = clip.height();
140 :
141 0 : const uint8_t* bits = mask.getAddr1(cx, cy);
142 :
143 0 : SkDEBUGCODE(const uint8_t* endOfImage =
144 : mask.fImage + (mask.fBounds.height() - 1) * maskRowBytes
145 : + ((mask.fBounds.width() + 7) >> 3));
146 :
147 0 : if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
148 0 : while (--height >= 0) {
149 0 : int affectedRightBit = mask.fBounds.width() - 1;
150 0 : ptrdiff_t rowBytes = (affectedRightBit >> 3) + 1;
151 0 : SkASSERT(bits + rowBytes <= endOfImage);
152 0 : U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
153 0 : bits_to_runs(this, cx, cy, bits, 0xFF, rowBytes, rightMask);
154 0 : bits += maskRowBytes;
155 0 : cy += 1;
156 0 : }
157 : } else {
158 : // Bits is calculated as the offset into the mask at the point {cx, cy} therefore, all
159 : // addressing into the bit mask is relative to that point. Since this is an address
160 : // calculated from a arbitrary bit in that byte, calculate the left most bit.
161 0 : int bitsLeft = cx - ((cx - maskLeft) & 7);
162 :
163 : // Everything is relative to the bitsLeft.
164 0 : int leftEdge = cx - bitsLeft;
165 0 : SkASSERT(leftEdge >= 0);
166 0 : int rightEdge = clip.fRight - bitsLeft;
167 0 : SkASSERT(rightEdge > leftEdge);
168 :
169 : // Calculate left byte and mask
170 0 : const uint8_t* leftByte = bits;
171 0 : U8CPU leftMask = 0xFFU >> (leftEdge & 7);
172 :
173 : // Calculate right byte and mask
174 0 : int affectedRightBit = rightEdge - 1;
175 0 : const uint8_t* rightByte = bits + (affectedRightBit >> 3);
176 0 : U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
177 :
178 : // leftByte and rightByte are byte locations therefore, to get a count of bytes the
179 : // code must add one.
180 0 : ptrdiff_t rowBytes = rightByte - leftByte + 1;
181 :
182 0 : while (--height >= 0) {
183 0 : SkASSERT(bits + rowBytes <= endOfImage);
184 0 : bits_to_runs(this, bitsLeft, cy, bits, leftMask, rowBytes, rightMask);
185 0 : bits += maskRowBytes;
186 0 : cy += 1;
187 : }
188 : }
189 : } else {
190 0 : int width = clip.width();
191 0 : SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
192 0 : int16_t* runs = runStorage.get();
193 0 : const uint8_t* aa = mask.getAddr8(clip.fLeft, clip.fTop);
194 :
195 0 : sk_memset16((uint16_t*)runs, 1, width);
196 0 : runs[width] = 0;
197 :
198 0 : int height = clip.height();
199 0 : int y = clip.fTop;
200 0 : while (--height >= 0) {
201 0 : this->blitAntiH(clip.fLeft, y, aa, runs);
202 0 : aa += mask.fRowBytes;
203 0 : y += 1;
204 : }
205 : }
206 : }
207 :
208 : /////////////////////// these guys are not virtual, just a helpers
209 :
210 4 : void SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
211 4 : if (clip.quickReject(mask.fBounds)) {
212 0 : return;
213 : }
214 :
215 4 : SkRegion::Cliperator clipper(clip, mask.fBounds);
216 :
217 12 : while (!clipper.done()) {
218 4 : const SkIRect& cr = clipper.rect();
219 4 : this->blitMask(mask, cr);
220 4 : clipper.next();
221 : }
222 : }
223 :
224 0 : void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
225 0 : SkRegion::Cliperator clipper(clip, rect);
226 :
227 0 : while (!clipper.done()) {
228 0 : const SkIRect& cr = clipper.rect();
229 0 : this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
230 0 : clipper.next();
231 : }
232 0 : }
233 :
234 0 : void SkBlitter::blitRegion(const SkRegion& clip) {
235 0 : SkRegion::Iterator iter(clip);
236 :
237 0 : while (!iter.done()) {
238 0 : const SkIRect& cr = iter.rect();
239 0 : this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
240 0 : iter.next();
241 : }
242 0 : }
243 :
244 : ///////////////////////////////////////////////////////////////////////////////
245 :
246 0 : void SkNullBlitter::blitH(int x, int y, int width) {}
247 :
248 0 : void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
249 0 : const int16_t runs[]) {}
250 :
251 0 : void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
252 :
253 0 : void SkNullBlitter::blitRect(int x, int y, int width, int height) {}
254 :
255 0 : void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
256 :
257 0 : const SkPixmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
258 0 : return nullptr;
259 : }
260 :
261 0 : bool SkNullBlitter::isNullBlitter() const { return true; }
262 :
263 : ///////////////////////////////////////////////////////////////////////////////
264 :
265 824 : static int compute_anti_width(const int16_t runs[]) {
266 824 : int width = 0;
267 :
268 : for (;;) {
269 4516 : int count = runs[0];
270 :
271 4516 : SkASSERT(count >= 0);
272 4516 : if (count == 0) {
273 824 : break;
274 : }
275 3692 : width += count;
276 3692 : runs += count;
277 3692 : }
278 824 : return width;
279 : }
280 :
281 558 : static inline bool y_in_rect(int y, const SkIRect& rect) {
282 558 : return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
283 : }
284 :
285 68 : static inline bool x_in_rect(int x, const SkIRect& rect) {
286 68 : return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
287 : }
288 :
289 146 : void SkRectClipBlitter::blitH(int left, int y, int width) {
290 146 : SkASSERT(width > 0);
291 :
292 146 : if (!y_in_rect(y, fClipRect)) {
293 0 : return;
294 : }
295 :
296 146 : int right = left + width;
297 :
298 146 : if (left < fClipRect.fLeft) {
299 0 : left = fClipRect.fLeft;
300 : }
301 146 : if (right > fClipRect.fRight) {
302 0 : right = fClipRect.fRight;
303 : }
304 :
305 146 : width = right - left;
306 146 : if (width > 0) {
307 146 : fBlitter->blitH(left, y, width);
308 : }
309 : }
310 :
311 412 : void SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
312 : const int16_t runs[]) {
313 412 : if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
314 0 : return;
315 : }
316 :
317 412 : int x0 = left;
318 412 : int x1 = left + compute_anti_width(runs);
319 :
320 412 : if (x1 <= fClipRect.fLeft) {
321 0 : return;
322 : }
323 :
324 412 : SkASSERT(x0 < x1);
325 412 : if (x0 < fClipRect.fLeft) {
326 0 : int dx = fClipRect.fLeft - x0;
327 0 : SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
328 0 : runs += dx;
329 0 : aa += dx;
330 0 : x0 = fClipRect.fLeft;
331 : }
332 :
333 412 : SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
334 412 : if (x1 > fClipRect.fRight) {
335 0 : x1 = fClipRect.fRight;
336 0 : SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
337 0 : ((int16_t*)runs)[x1 - x0] = 0;
338 : }
339 :
340 412 : SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
341 412 : SkASSERT(compute_anti_width(runs) == x1 - x0);
342 :
343 412 : fBlitter->blitAntiH(x0, y, aa, runs);
344 : }
345 :
346 68 : void SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
347 68 : SkASSERT(height > 0);
348 :
349 68 : if (!x_in_rect(x, fClipRect)) {
350 0 : return;
351 : }
352 :
353 68 : int y0 = y;
354 68 : int y1 = y + height;
355 :
356 68 : if (y0 < fClipRect.fTop) {
357 0 : y0 = fClipRect.fTop;
358 : }
359 68 : if (y1 > fClipRect.fBottom) {
360 0 : y1 = fClipRect.fBottom;
361 : }
362 :
363 68 : if (y0 < y1) {
364 68 : fBlitter->blitV(x, y0, y1 - y0, alpha);
365 : }
366 : }
367 :
368 0 : void SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
369 : SkIRect r;
370 :
371 0 : r.set(left, y, left + width, y + height);
372 0 : if (r.intersect(fClipRect)) {
373 0 : fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
374 : }
375 0 : }
376 :
377 4 : void SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height,
378 : SkAlpha leftAlpha, SkAlpha rightAlpha) {
379 : SkIRect r;
380 :
381 : // The *true* width of the rectangle blitted is width+2:
382 4 : r.set(left, y, left + width + 2, y + height);
383 4 : if (r.intersect(fClipRect)) {
384 4 : if (r.fLeft != left) {
385 4 : SkASSERT(r.fLeft > left);
386 4 : leftAlpha = 255;
387 : }
388 4 : if (r.fRight != left + width + 2) {
389 4 : SkASSERT(r.fRight < left + width + 2);
390 4 : rightAlpha = 255;
391 : }
392 4 : if (255 == leftAlpha && 255 == rightAlpha) {
393 4 : fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
394 0 : } else if (1 == r.width()) {
395 0 : if (r.fLeft == left) {
396 0 : fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha);
397 : } else {
398 0 : SkASSERT(r.fLeft == left + width + 1);
399 0 : fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha);
400 : }
401 : } else {
402 0 : fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
403 0 : leftAlpha, rightAlpha);
404 : }
405 : }
406 4 : }
407 :
408 1 : void SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
409 1 : SkASSERT(mask.fBounds.contains(clip));
410 :
411 1 : SkIRect r = clip;
412 :
413 1 : if (r.intersect(fClipRect)) {
414 1 : fBlitter->blitMask(mask, r);
415 : }
416 1 : }
417 :
418 0 : const SkPixmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
419 0 : return fBlitter->justAnOpaqueColor(value);
420 : }
421 :
422 : ///////////////////////////////////////////////////////////////////////////////
423 :
424 0 : void SkRgnClipBlitter::blitH(int x, int y, int width) {
425 0 : SkRegion::Spanerator span(*fRgn, y, x, x + width);
426 : int left, right;
427 :
428 0 : while (span.next(&left, &right)) {
429 0 : SkASSERT(left < right);
430 0 : fBlitter->blitH(left, y, right - left);
431 : }
432 0 : }
433 :
434 0 : void SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
435 : const int16_t runs[]) {
436 0 : int width = compute_anti_width(runs);
437 0 : SkRegion::Spanerator span(*fRgn, y, x, x + width);
438 : int left, right;
439 0 : SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
440 :
441 0 : int prevRite = x;
442 0 : while (span.next(&left, &right)) {
443 0 : SkASSERT(x <= left);
444 0 : SkASSERT(left < right);
445 0 : SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
446 :
447 0 : SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
448 :
449 : // now zero before left
450 0 : if (left > prevRite) {
451 0 : int index = prevRite - x;
452 0 : ((uint8_t*)aa)[index] = 0; // skip runs after right
453 0 : ((int16_t*)runs)[index] = SkToS16(left - prevRite);
454 : }
455 :
456 0 : prevRite = right;
457 : }
458 :
459 0 : if (prevRite > x) {
460 0 : ((int16_t*)runs)[prevRite - x] = 0;
461 :
462 0 : if (x < 0) {
463 0 : int skip = runs[0];
464 0 : SkASSERT(skip >= -x);
465 0 : aa += skip;
466 0 : runs += skip;
467 0 : x += skip;
468 : }
469 0 : fBlitter->blitAntiH(x, y, aa, runs);
470 : }
471 0 : }
472 :
473 0 : void SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
474 : SkIRect bounds;
475 0 : bounds.set(x, y, x + 1, y + height);
476 :
477 0 : SkRegion::Cliperator iter(*fRgn, bounds);
478 :
479 0 : while (!iter.done()) {
480 0 : const SkIRect& r = iter.rect();
481 0 : SkASSERT(bounds.contains(r));
482 :
483 0 : fBlitter->blitV(x, r.fTop, r.height(), alpha);
484 0 : iter.next();
485 : }
486 0 : }
487 :
488 0 : void SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
489 : SkIRect bounds;
490 0 : bounds.set(x, y, x + width, y + height);
491 :
492 0 : SkRegion::Cliperator iter(*fRgn, bounds);
493 :
494 0 : while (!iter.done()) {
495 0 : const SkIRect& r = iter.rect();
496 0 : SkASSERT(bounds.contains(r));
497 :
498 0 : fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
499 0 : iter.next();
500 : }
501 0 : }
502 :
503 0 : void SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height,
504 : SkAlpha leftAlpha, SkAlpha rightAlpha) {
505 : // The *true* width of the rectangle to blit is width + 2
506 : SkIRect bounds;
507 0 : bounds.set(x, y, x + width + 2, y + height);
508 :
509 0 : SkRegion::Cliperator iter(*fRgn, bounds);
510 :
511 0 : while (!iter.done()) {
512 0 : const SkIRect& r = iter.rect();
513 0 : SkASSERT(bounds.contains(r));
514 0 : SkASSERT(r.fLeft >= x);
515 0 : SkASSERT(r.fRight <= x + width + 2);
516 :
517 0 : SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255;
518 0 : SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ?
519 0 : rightAlpha : 255;
520 :
521 0 : if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) {
522 0 : fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
523 0 : } else if (1 == r.width()) {
524 0 : if (r.fLeft == x) {
525 0 : fBlitter->blitV(r.fLeft, r.fTop, r.height(),
526 0 : effectiveLeftAlpha);
527 : } else {
528 0 : SkASSERT(r.fLeft == x + width + 1);
529 0 : fBlitter->blitV(r.fLeft, r.fTop, r.height(),
530 0 : effectiveRightAlpha);
531 : }
532 : } else {
533 0 : fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
534 0 : effectiveLeftAlpha, effectiveRightAlpha);
535 : }
536 0 : iter.next();
537 : }
538 0 : }
539 :
540 :
541 0 : void SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
542 0 : SkASSERT(mask.fBounds.contains(clip));
543 :
544 0 : SkRegion::Cliperator iter(*fRgn, clip);
545 0 : const SkIRect& r = iter.rect();
546 0 : SkBlitter* blitter = fBlitter;
547 :
548 0 : while (!iter.done()) {
549 0 : blitter->blitMask(mask, r);
550 0 : iter.next();
551 : }
552 0 : }
553 :
554 0 : const SkPixmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
555 0 : return fBlitter->justAnOpaqueColor(value);
556 : }
557 :
558 : ///////////////////////////////////////////////////////////////////////////////
559 :
560 0 : SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
561 : const SkIRect* ir) {
562 0 : if (clip) {
563 0 : const SkIRect& clipR = clip->getBounds();
564 :
565 0 : if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
566 0 : blitter = &fNullBlitter;
567 0 : } else if (clip->isRect()) {
568 0 : if (ir == nullptr || !clipR.contains(*ir)) {
569 0 : fRectBlitter.init(blitter, clipR);
570 0 : blitter = &fRectBlitter;
571 : }
572 : } else {
573 0 : fRgnBlitter.init(blitter, clip);
574 0 : blitter = &fRgnBlitter;
575 : }
576 : }
577 0 : return blitter;
578 : }
579 :
580 : ///////////////////////////////////////////////////////////////////////////////
581 :
582 : #include "SkColorShader.h"
583 : #include "SkColorPriv.h"
584 :
585 0 : class Sk3DShader : public SkShader {
586 : public:
587 0 : Sk3DShader(sk_sp<SkShader> proxy) : fProxy(std::move(proxy)) {}
588 :
589 0 : Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override {
590 0 : SkShader::Context* proxyContext = nullptr;
591 0 : if (fProxy) {
592 0 : proxyContext = fProxy->makeContext(rec, alloc);
593 0 : if (!proxyContext) {
594 0 : return nullptr;
595 : }
596 : }
597 0 : return alloc->make<Sk3DShaderContext>(*this, rec, proxyContext);
598 : }
599 :
600 : class Sk3DShaderContext : public SkShader::Context {
601 : public:
602 : // Calls proxyContext's destructor but will NOT free its memory.
603 0 : Sk3DShaderContext(const Sk3DShader& shader, const ContextRec& rec,
604 : SkShader::Context* proxyContext)
605 0 : : INHERITED(shader, rec)
606 : , fMask(nullptr)
607 0 : , fProxyContext(proxyContext)
608 : {
609 0 : if (!fProxyContext) {
610 0 : fPMColor = SkPreMultiplyColor(rec.fPaint->getColor());
611 : }
612 0 : }
613 :
614 0 : ~Sk3DShaderContext() override {
615 0 : if (fProxyContext) {
616 0 : fProxyContext->~Context();
617 : }
618 0 : }
619 :
620 0 : void set3DMask(const SkMask* mask) override { fMask = mask; }
621 :
622 0 : void shadeSpan(int x, int y, SkPMColor span[], int count) override {
623 0 : if (fProxyContext) {
624 0 : fProxyContext->shadeSpan(x, y, span, count);
625 : }
626 :
627 0 : if (fMask == nullptr) {
628 0 : if (fProxyContext == nullptr) {
629 0 : sk_memset32(span, fPMColor, count);
630 : }
631 0 : return;
632 : }
633 :
634 0 : SkASSERT(fMask->fBounds.contains(x, y));
635 0 : SkASSERT(fMask->fBounds.contains(x + count - 1, y));
636 :
637 0 : size_t size = fMask->computeImageSize();
638 0 : const uint8_t* alpha = fMask->getAddr8(x, y);
639 0 : const uint8_t* mulp = alpha + size;
640 0 : const uint8_t* addp = mulp + size;
641 :
642 0 : if (fProxyContext) {
643 0 : for (int i = 0; i < count; i++) {
644 0 : if (alpha[i]) {
645 0 : SkPMColor c = span[i];
646 0 : if (c) {
647 0 : unsigned a = SkGetPackedA32(c);
648 0 : unsigned r = SkGetPackedR32(c);
649 0 : unsigned g = SkGetPackedG32(c);
650 0 : unsigned b = SkGetPackedB32(c);
651 :
652 0 : unsigned mul = SkAlpha255To256(mulp[i]);
653 0 : unsigned add = addp[i];
654 :
655 0 : r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
656 0 : g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
657 0 : b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
658 :
659 0 : span[i] = SkPackARGB32(a, r, g, b);
660 : }
661 : } else {
662 0 : span[i] = 0;
663 : }
664 : }
665 : } else { // color
666 0 : unsigned a = SkGetPackedA32(fPMColor);
667 0 : unsigned r = SkGetPackedR32(fPMColor);
668 0 : unsigned g = SkGetPackedG32(fPMColor);
669 0 : unsigned b = SkGetPackedB32(fPMColor);
670 0 : for (int i = 0; i < count; i++) {
671 0 : if (alpha[i]) {
672 0 : unsigned mul = SkAlpha255To256(mulp[i]);
673 0 : unsigned add = addp[i];
674 :
675 0 : span[i] = SkPackARGB32( a,
676 0 : SkFastMin32(SkAlphaMul(r, mul) + add, a),
677 0 : SkFastMin32(SkAlphaMul(g, mul) + add, a),
678 0 : SkFastMin32(SkAlphaMul(b, mul) + add, a));
679 : } else {
680 0 : span[i] = 0;
681 : }
682 : }
683 : }
684 : }
685 :
686 : private:
687 : // Unowned.
688 : const SkMask* fMask;
689 : // Memory is unowned, but we need to call the destructor.
690 : SkShader::Context* fProxyContext;
691 : SkPMColor fPMColor;
692 :
693 : typedef SkShader::Context INHERITED;
694 : };
695 :
696 : #ifndef SK_IGNORE_TO_STRING
697 0 : void toString(SkString* str) const override {
698 0 : str->append("Sk3DShader: (");
699 :
700 0 : if (fProxy) {
701 0 : str->append("Proxy: ");
702 0 : fProxy->toString(str);
703 : }
704 :
705 0 : this->INHERITED::toString(str);
706 :
707 0 : str->append(")");
708 0 : }
709 : #endif
710 :
711 0 : SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader)
712 :
713 : protected:
714 0 : void flatten(SkWriteBuffer& buffer) const override {
715 0 : buffer.writeFlattenable(fProxy.get());
716 0 : }
717 :
718 : private:
719 : sk_sp<SkShader> fProxy;
720 :
721 : typedef SkShader INHERITED;
722 : };
723 :
724 0 : sk_sp<SkFlattenable> Sk3DShader::CreateProc(SkReadBuffer& buffer) {
725 0 : return sk_make_sp<Sk3DShader>(buffer.readShader());
726 : }
727 :
728 0 : class Sk3DBlitter : public SkBlitter {
729 : public:
730 0 : Sk3DBlitter(SkBlitter* proxy, SkShader::Context* shaderContext)
731 0 : : fProxy(proxy)
732 0 : , fShaderContext(shaderContext)
733 0 : {}
734 :
735 0 : void blitH(int x, int y, int width) override {
736 0 : fProxy->blitH(x, y, width);
737 0 : }
738 :
739 0 : void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
740 0 : fProxy->blitAntiH(x, y, antialias, runs);
741 0 : }
742 :
743 0 : void blitV(int x, int y, int height, SkAlpha alpha) override {
744 0 : fProxy->blitV(x, y, height, alpha);
745 0 : }
746 :
747 0 : void blitRect(int x, int y, int width, int height) override {
748 0 : fProxy->blitRect(x, y, width, height);
749 0 : }
750 :
751 0 : void blitMask(const SkMask& mask, const SkIRect& clip) override {
752 0 : if (mask.fFormat == SkMask::k3D_Format) {
753 0 : fShaderContext->set3DMask(&mask);
754 :
755 0 : ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
756 0 : fProxy->blitMask(mask, clip);
757 0 : ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
758 :
759 0 : fShaderContext->set3DMask(nullptr);
760 : } else {
761 0 : fProxy->blitMask(mask, clip);
762 : }
763 0 : }
764 :
765 : private:
766 : // Both pointers are unowned. They will be deleted by SkSmallAllocator.
767 : SkBlitter* fProxy;
768 : SkShader::Context* fShaderContext;
769 : };
770 :
771 : ///////////////////////////////////////////////////////////////////////////////
772 :
773 : #include "SkCoreBlitters.h"
774 :
775 166 : SkShader::ContextRec::DstType SkBlitter::PreferredShaderDest(const SkImageInfo& dstInfo) {
776 : #ifdef SK_FORCE_PM4f_FOR_L32_BLITS
777 : return SkShader::ContextRec::kPM4f_DstType;
778 : #else
779 332 : return (dstInfo.gammaCloseToSRGB() || dstInfo.colorType() == kRGBA_F16_SkColorType)
780 166 : ? SkShader::ContextRec::kPM4f_DstType
781 166 : : SkShader::ContextRec::kPMColor_DstType;
782 : #endif
783 : }
784 :
785 312 : SkBlitter* SkBlitter::Choose(const SkPixmap& device,
786 : const SkMatrix& matrix,
787 : const SkPaint& origPaint,
788 : SkArenaAlloc* alloc,
789 : bool drawCoverage) {
790 312 : SkASSERT(alloc != nullptr);
791 :
792 : // which check, in case we're being called by a client with a dummy device
793 : // (e.g. they have a bounder that always aborts the draw)
794 312 : if (kUnknown_SkColorType == device.colorType() ||
795 0 : (drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) {
796 0 : return alloc->make<SkNullBlitter>();
797 : }
798 :
799 312 : SkShader* shader = origPaint.getShader();
800 312 : SkColorFilter* cf = origPaint.getColorFilter();
801 312 : SkBlendMode mode = origPaint.getBlendMode();
802 624 : sk_sp<Sk3DShader> shader3D;
803 :
804 624 : SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
805 :
806 312 : if (origPaint.getMaskFilter() != nullptr &&
807 0 : origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) {
808 0 : shader3D = sk_make_sp<Sk3DShader>(sk_ref_sp(shader));
809 : // we know we haven't initialized lazyPaint yet, so just do it
810 0 : paint.writable()->setShader(shader3D);
811 0 : shader = shader3D.get();
812 : }
813 :
814 312 : if (mode != SkBlendMode::kSrcOver) {
815 0 : bool deviceIsOpaque = kRGB_565_SkColorType == device.colorType();
816 0 : switch (SkInterpretXfermode(*paint, deviceIsOpaque)) {
817 : case kSrcOver_SkXfermodeInterpretation:
818 0 : mode = SkBlendMode::kSrcOver;
819 0 : paint.writable()->setBlendMode(mode);
820 0 : break;
821 : case kSkipDrawing_SkXfermodeInterpretation:{
822 0 : return alloc->make<SkNullBlitter>();
823 : }
824 : default:
825 0 : break;
826 : }
827 : }
828 :
829 : /*
830 : * If the xfermode is CLEAR, then we can completely ignore the installed
831 : * color/shader/colorfilter, and just pretend we're SRC + color==0. This
832 : * will fall into our optimizations for SRC mode.
833 : */
834 312 : if (mode == SkBlendMode::kClear) {
835 0 : SkPaint* p = paint.writable();
836 0 : p->setShader(nullptr);
837 0 : shader = nullptr;
838 0 : p->setColorFilter(nullptr);
839 0 : cf = nullptr;
840 0 : p->setBlendMode(mode = SkBlendMode::kSrc);
841 0 : p->setColor(0);
842 : }
843 :
844 312 : if (kAlpha_8_SkColorType == device.colorType() && drawCoverage) {
845 0 : SkASSERT(nullptr == shader);
846 0 : SkASSERT(paint->isSrcOver());
847 0 : return alloc->make<SkA8_Coverage_Blitter>(device, *paint);
848 : }
849 :
850 312 : if (SkBlitter* blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc)) {
851 2 : return blitter;
852 : }
853 :
854 310 : if (nullptr == shader) {
855 144 : if (mode != SkBlendMode::kSrcOver) {
856 : // xfermodes (and filters) require shaders for our current blitters
857 0 : paint.writable()->setShader(SkShader::MakeColorShader(paint->getColor()));
858 0 : paint.writable()->setAlpha(0xFF);
859 0 : shader = paint->getShader();
860 144 : } else if (cf) {
861 : // if no shader && no xfermode, we just apply the colorfilter to
862 : // our color and move on.
863 0 : SkPaint* writablePaint = paint.writable();
864 0 : writablePaint->setColor(cf->filterColor(paint->getColor()));
865 0 : writablePaint->setColorFilter(nullptr);
866 0 : cf = nullptr;
867 : }
868 : }
869 :
870 310 : if (cf) {
871 0 : SkASSERT(shader);
872 0 : paint.writable()->setShader(shader->makeWithColorFilter(sk_ref_sp(cf)));
873 0 : shader = paint->getShader();
874 : // blitters should ignore the presence/absence of a filter, since
875 : // if there is one, the shader will take care of it.
876 : }
877 :
878 : /*
879 : * We create a SkShader::Context object, and store it on the blitter.
880 : */
881 310 : SkShader::Context* shaderContext = nullptr;
882 310 : if (shader) {
883 : const SkShader::ContextRec rec(*paint, matrix, nullptr,
884 : PreferredShaderDest(device.info()),
885 166 : device.colorSpace());
886 : // Try to create the ShaderContext
887 166 : shaderContext = shader->makeContext(rec, alloc);
888 166 : if (!shaderContext) {
889 0 : return alloc->make<SkNullBlitter>();
890 : }
891 166 : SkASSERT(shaderContext);
892 : }
893 :
894 310 : SkBlitter* blitter = nullptr;
895 310 : switch (device.colorType()) {
896 : case kAlpha_8_SkColorType:
897 2 : SkASSERT(!drawCoverage); // Handled above.
898 2 : if (shader) {
899 2 : blitter = alloc->make<SkA8_Shader_Blitter>(device, *paint, shaderContext);
900 : } else {
901 0 : blitter = alloc->make<SkA8_Blitter>(device, *paint);
902 : }
903 2 : break;
904 :
905 : case kRGB_565_SkColorType:
906 0 : blitter = SkBlitter_ChooseD565(device, *paint, shaderContext, alloc);
907 0 : break;
908 :
909 : case kN32_SkColorType:
910 : #ifdef SK_FORCE_PM4f_FOR_L32_BLITS
911 : if (true)
912 : #else
913 308 : if (device.info().gammaCloseToSRGB())
914 : #endif
915 : {
916 0 : blitter = SkBlitter_ARGB32_Create(device, *paint, shaderContext, alloc);
917 : } else {
918 308 : if (shader) {
919 164 : blitter = alloc->make<SkARGB32_Shader_Blitter>(
920 164 : device, *paint, shaderContext);
921 144 : } else if (paint->getColor() == SK_ColorBLACK) {
922 1 : blitter = alloc->make<SkARGB32_Black_Blitter>(device, *paint);
923 143 : } else if (paint->getAlpha() == 0xFF) {
924 96 : blitter = alloc->make<SkARGB32_Opaque_Blitter>(device, *paint);
925 : } else {
926 47 : blitter = alloc->make<SkARGB32_Blitter>(device, *paint);
927 : }
928 : }
929 308 : break;
930 :
931 : case kRGBA_F16_SkColorType:
932 0 : blitter = SkBlitter_F16_Create(device, *paint, shaderContext, alloc);
933 0 : break;
934 :
935 : default:
936 0 : break;
937 : }
938 :
939 310 : if (!blitter) {
940 0 : blitter = alloc->make<SkNullBlitter>();
941 : }
942 :
943 310 : if (shader3D) {
944 0 : SkBlitter* innerBlitter = blitter;
945 : // FIXME - comment about allocator
946 : // innerBlitter was allocated by allocator, which will delete it.
947 : // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to
948 : // wrapper the blitter to notify it when we see an emboss mask.
949 0 : blitter = alloc->make<Sk3DBlitter>(innerBlitter, shaderContext);
950 : }
951 310 : return blitter;
952 : }
953 :
954 : ///////////////////////////////////////////////////////////////////////////////
955 :
956 : class SkZeroShaderContext : public SkShader::Context {
957 : public:
958 : SkZeroShaderContext(const SkShader& shader, const SkShader::ContextRec& rec)
959 : // Override rec with the identity matrix, so it is guaranteed to be invertible.
960 : : INHERITED(shader, SkShader::ContextRec(*rec.fPaint, SkMatrix::I(), nullptr,
961 : rec.fPreferredDstType, rec.fDstColorSpace)) {}
962 :
963 : void shadeSpan(int x, int y, SkPMColor colors[], int count) override {
964 : sk_bzero(colors, count * sizeof(SkPMColor));
965 : }
966 :
967 : private:
968 : typedef SkShader::Context INHERITED;
969 : };
970 :
971 166 : SkShaderBlitter::SkShaderBlitter(const SkPixmap& device, const SkPaint& paint,
972 166 : SkShader::Context* shaderContext)
973 : : INHERITED(device)
974 166 : , fShader(paint.getShader())
975 332 : , fShaderContext(shaderContext) {
976 166 : SkASSERT(fShader);
977 166 : SkASSERT(fShaderContext);
978 :
979 166 : fShader->ref();
980 166 : fShaderFlags = fShaderContext->getFlags();
981 166 : fConstInY = SkToBool(fShaderFlags & SkShader::kConstInY32_Flag);
982 166 : }
983 :
984 332 : SkShaderBlitter::~SkShaderBlitter() {
985 166 : fShader->unref();
986 166 : }
987 :
988 : ///////////////////////////////////////////////////////////////////////////////////////////////////
989 :
990 : #ifdef SK_DEBUG
991 :
992 696 : void SkRectClipCheckBlitter::blitH(int x, int y, int width) {
993 696 : SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
994 696 : fBlitter->blitH(x, y, width);
995 696 : }
996 :
997 1930 : void SkRectClipCheckBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) {
998 1930 : const int16_t* iter = runs;
999 9851 : for (; *iter; iter += *iter)
1000 : ;
1001 1930 : int width = iter - runs;
1002 1930 : SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
1003 1930 : fBlitter->blitAntiH(x, y, aa, runs);
1004 1930 : }
1005 :
1006 296 : void SkRectClipCheckBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
1007 296 : SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, height)));
1008 296 : fBlitter->blitV(x, y, height, alpha);
1009 296 : }
1010 :
1011 2 : void SkRectClipCheckBlitter::blitRect(int x, int y, int width, int height) {
1012 2 : SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, height)));
1013 2 : fBlitter->blitRect(x, y, width, height);
1014 2 : }
1015 :
1016 126 : void SkRectClipCheckBlitter::blitAntiRect(int x, int y, int width, int height,
1017 : SkAlpha leftAlpha, SkAlpha rightAlpha) {
1018 126 : bool skipLeft = !leftAlpha;
1019 126 : bool skipRight = !rightAlpha;
1020 126 : SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x + skipLeft, y,
1021 : width + 2 - skipRight - skipLeft, height)));
1022 126 : fBlitter->blitAntiRect(x, y, width, height, leftAlpha, rightAlpha);
1023 126 : }
1024 :
1025 33 : void SkRectClipCheckBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
1026 33 : SkASSERT(mask.fBounds.contains(clip));
1027 33 : SkASSERT(fClipRect.contains(clip));
1028 33 : fBlitter->blitMask(mask, clip);
1029 33 : }
1030 :
1031 0 : const SkPixmap* SkRectClipCheckBlitter::justAnOpaqueColor(uint32_t* value) {
1032 0 : return fBlitter->justAnOpaqueColor(value);
1033 : }
1034 :
1035 232 : void SkRectClipCheckBlitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
1036 232 : SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 2, 1)));
1037 232 : fBlitter->blitAntiH2(x, y, a0, a1);
1038 232 : }
1039 :
1040 0 : void SkRectClipCheckBlitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
1041 0 : SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, 2)));
1042 0 : fBlitter->blitAntiV2(x, y, a0, a1);
1043 0 : }
1044 :
1045 : #endif
|