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