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