1 /*
2  * Copyright 2015 Google Inc.
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 "GrRenderTargetContext.h"
9 #include "../private/GrAuditTrail.h"
10 #include "../private/SkShadowFlags.h"
11 #include "GrAppliedClip.h"
12 #include "GrBackendSemaphore.h"
13 #include "GrBlurUtils.h"
14 #include "GrColor.h"
15 #include "GrContextPriv.h"
16 #include "GrDrawingManager.h"
17 #include "GrFixedClip.h"
18 #include "GrGpuResourcePriv.h"
19 #include "GrOpList.h"
20 #include "GrPathRenderer.h"
21 #include "GrQuad.h"
22 #include "GrRenderTarget.h"
23 #include "GrRenderTargetContextPriv.h"
24 #include "GrResourceProvider.h"
25 #include "GrShape.h"
26 #include "GrStencilAttachment.h"
27 #include "GrStyle.h"
28 #include "GrTracing.h"
29 #include "SkDrawable.h"
30 #include "SkDrawShadowInfo.h"
31 #include "SkGlyphRunPainter.h"
32 #include "SkGr.h"
33 #include "SkLatticeIter.h"
34 #include "SkMatrixPriv.h"
35 #include "SkRRectPriv.h"
36 #include "SkShadowUtils.h"
37 #include "SkSurfacePriv.h"
38 #include "effects/GrRRectEffect.h"
39 #include "ops/GrAtlasTextOp.h"
40 #include "ops/GrClearOp.h"
41 #include "ops/GrClearStencilClipOp.h"
42 #include "ops/GrDebugMarkerOp.h"
43 #include "ops/GrDrawableOp.h"
44 #include "ops/GrDrawAtlasOp.h"
45 #include "ops/GrDrawOp.h"
46 #include "ops/GrDrawVerticesOp.h"
47 #include "ops/GrFillRectOp.h"
48 #include "ops/GrAAFillRRectOp.h"
49 #include "ops/GrLatticeOp.h"
50 #include "ops/GrOp.h"
51 #include "ops/GrOvalOpFactory.h"
52 #include "ops/GrRegionOp.h"
53 #include "ops/GrSemaphoreOp.h"
54 #include "ops/GrShadowRRectOp.h"
55 #include "ops/GrStencilPathOp.h"
56 #include "ops/GrStrokeRectOp.h"
57 #include "ops/GrTextureOp.h"
58 #include "text/GrTextContext.h"
59 #include "text/GrTextTarget.h"
60 
61 class GrRenderTargetContext::TextTarget : public GrTextTarget {
62 public:
TextTarget(GrRenderTargetContext * renderTargetContext)63     TextTarget(GrRenderTargetContext* renderTargetContext)
64             : GrTextTarget(renderTargetContext->width(), renderTargetContext->height(),
65                      renderTargetContext->colorSpaceInfo())
66             , fRenderTargetContext(renderTargetContext)
67             , fGlyphPainter{*renderTargetContext}{}
68 
addDrawOp(const GrClip & clip,std::unique_ptr<GrAtlasTextOp> op)69     void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) override {
70         fRenderTargetContext->addDrawOp(clip, std::move(op));
71     }
72 
drawShape(const GrClip & clip,const SkPaint & paint,const SkMatrix & viewMatrix,const GrShape & shape)73     void drawShape(const GrClip& clip, const SkPaint& paint,
74                   const SkMatrix& viewMatrix, const GrShape& shape) override {
75         GrBlurUtils::drawShapeWithMaskFilter(fRenderTargetContext->fContext, fRenderTargetContext,
76                                              clip, paint, viewMatrix, shape);
77     }
78 
makeGrPaint(GrMaskFormat maskFormat,const SkPaint & skPaint,const SkMatrix & viewMatrix,GrPaint * grPaint)79     void makeGrPaint(GrMaskFormat maskFormat, const SkPaint& skPaint, const SkMatrix& viewMatrix,
80                      GrPaint* grPaint) override {
81         GrContext* context = fRenderTargetContext->fContext;
82         const GrColorSpaceInfo& colorSpaceInfo = fRenderTargetContext->colorSpaceInfo();
83         if (kARGB_GrMaskFormat == maskFormat) {
84             SkPaintToGrPaintWithPrimitiveColor(context, colorSpaceInfo, skPaint, grPaint);
85         } else {
86             SkPaintToGrPaint(context, colorSpaceInfo, skPaint, viewMatrix, grPaint);
87         }
88     }
89 
getContext()90     GrContext* getContext() override {
91         return fRenderTargetContext->fContext;
92     }
93 
glyphPainter()94     SkGlyphRunListPainter* glyphPainter() override {
95         return &fGlyphPainter;
96     }
97 
98 private:
99     GrRenderTargetContext* fRenderTargetContext;
100     SkGlyphRunListPainter fGlyphPainter;
101 
102 };
103 
104 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
105 #define ASSERT_SINGLE_OWNER \
106     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
107 #define ASSERT_SINGLE_OWNER_PRIV \
108     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
109 #define RETURN_IF_ABANDONED        if (this->drawingManager()->wasAbandoned()) { return; }
110 #define RETURN_IF_ABANDONED_PRIV   if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return; }
111 #define RETURN_FALSE_IF_ABANDONED  if (this->drawingManager()->wasAbandoned()) { return false; }
112 #define RETURN_FALSE_IF_ABANDONED_PRIV  if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return false; }
113 #define RETURN_NULL_IF_ABANDONED   if (this->drawingManager()->wasAbandoned()) { return nullptr; }
114 
115 //////////////////////////////////////////////////////////////////////////////
116 
GrChooseAAType(GrAA aa,GrFSAAType fsaaType,GrAllowMixedSamples allowMixedSamples,const GrCaps & caps)117 GrAAType GrChooseAAType(GrAA aa, GrFSAAType fsaaType, GrAllowMixedSamples allowMixedSamples,
118                         const GrCaps& caps) {
119     if (GrAA::kNo == aa) {
120         // On some devices we cannot disable MSAA if it is enabled so we make the AA type reflect
121         // that.
122         if (fsaaType == GrFSAAType::kUnifiedMSAA && !caps.multisampleDisableSupport()) {
123             return GrAAType::kMSAA;
124         }
125         return GrAAType::kNone;
126     }
127     switch (fsaaType) {
128         case GrFSAAType::kNone:
129             return GrAAType::kCoverage;
130         case GrFSAAType::kUnifiedMSAA:
131             return GrAAType::kMSAA;
132         case GrFSAAType::kMixedSamples:
133             return GrAllowMixedSamples::kYes == allowMixedSamples ? GrAAType::kMixedSamples
134                                                                   : GrAAType::kCoverage;
135     }
136     SK_ABORT("Unexpected fsaa type");
137     return GrAAType::kNone;
138 }
139 
140 //////////////////////////////////////////////////////////////////////////////
141 
142 class AutoCheckFlush {
143 public:
AutoCheckFlush(GrDrawingManager * drawingManager)144     AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
145         SkASSERT(fDrawingManager);
146     }
~AutoCheckFlush()147     ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
148 
149 private:
150     GrDrawingManager* fDrawingManager;
151 };
152 
wasAbandoned() const153 bool GrRenderTargetContext::wasAbandoned() const {
154     return this->drawingManager()->wasAbandoned();
155 }
156 
157 // In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
158 // GrOpLists to be picked up and added to by renderTargetContexts lower in the call
159 // stack. When this occurs with a closed GrOpList, a new one will be allocated
160 // when the renderTargetContext attempts to use it (via getOpList).
GrRenderTargetContext(GrContext * context,GrDrawingManager * drawingMgr,sk_sp<GrRenderTargetProxy> rtp,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * surfaceProps,GrAuditTrail * auditTrail,GrSingleOwner * singleOwner,bool managedOpList)161 GrRenderTargetContext::GrRenderTargetContext(GrContext* context,
162                                              GrDrawingManager* drawingMgr,
163                                              sk_sp<GrRenderTargetProxy> rtp,
164                                              sk_sp<SkColorSpace> colorSpace,
165                                              const SkSurfaceProps* surfaceProps,
166                                              GrAuditTrail* auditTrail,
167                                              GrSingleOwner* singleOwner,
168                                              bool managedOpList)
169         : GrSurfaceContext(context, drawingMgr, rtp->config(), std::move(colorSpace), auditTrail,
170                            singleOwner)
171         , fRenderTargetProxy(std::move(rtp))
172         , fOpList(sk_ref_sp(fRenderTargetProxy->getLastRenderTargetOpList()))
173         , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
174         , fManagedOpList(managedOpList) {
175     GrResourceProvider* resourceProvider = context->contextPriv().resourceProvider();
176     if (resourceProvider && !resourceProvider->explicitlyAllocateGPUResources()) {
177         // MDB TODO: to ensure all resources still get allocated in the correct order in the hybrid
178         // world we need to get the correct opList here so that it, in turn, can grab and hold
179         // its rendertarget.
180         this->getRTOpList();
181     }
182 
183     fTextTarget.reset(new TextTarget(this));
184     SkDEBUGCODE(this->validate();)
185 }
186 
187 #ifdef SK_DEBUG
validate() const188 void GrRenderTargetContext::validate() const {
189     SkASSERT(fRenderTargetProxy);
190     fRenderTargetProxy->validate(fContext);
191 
192     if (fOpList && !fOpList->isClosed()) {
193         SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList.get());
194     }
195 }
196 #endif
197 
~GrRenderTargetContext()198 GrRenderTargetContext::~GrRenderTargetContext() {
199     ASSERT_SINGLE_OWNER
200 }
201 
asTextureProxy()202 GrTextureProxy* GrRenderTargetContext::asTextureProxy() {
203     return fRenderTargetProxy->asTextureProxy();
204 }
205 
asTextureProxy() const206 const GrTextureProxy* GrRenderTargetContext::asTextureProxy() const {
207     return fRenderTargetProxy->asTextureProxy();
208 }
209 
asTextureProxyRef()210 sk_sp<GrTextureProxy> GrRenderTargetContext::asTextureProxyRef() {
211     return sk_ref_sp(fRenderTargetProxy->asTextureProxy());
212 }
213 
mipMapped() const214 GrMipMapped GrRenderTargetContext::mipMapped() const {
215     if (const GrTextureProxy* proxy = this->asTextureProxy()) {
216         return proxy->mipMapped();
217     }
218     return GrMipMapped::kNo;
219 }
220 
getRTOpList()221 GrRenderTargetOpList* GrRenderTargetContext::getRTOpList() {
222     ASSERT_SINGLE_OWNER
223     SkDEBUGCODE(this->validate();)
224 
225     if (!fOpList || fOpList->isClosed()) {
226         fOpList = this->drawingManager()->newRTOpList(fRenderTargetProxy.get(), fManagedOpList);
227     }
228 
229     return fOpList.get();
230 }
231 
getOpList()232 GrOpList* GrRenderTargetContext::getOpList() {
233     return this->getRTOpList();
234 }
235 
drawGlyphRunList(const GrClip & clip,const SkMatrix & viewMatrix,const SkGlyphRunList & blob)236 void GrRenderTargetContext::drawGlyphRunList(
237         const GrClip& clip, const SkMatrix& viewMatrix,
238         const SkGlyphRunList& blob) {
239     ASSERT_SINGLE_OWNER
240     RETURN_IF_ABANDONED
241     SkDEBUGCODE(this->validate();)
242     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawGlyphRunList", fContext);
243 
244     // Drawing text can cause us to do inline uploads. This is not supported for wrapped vulkan
245     // secondary command buffers because it would require stopping and starting a render pass which
246     // we don't have access to.
247     if (this->wrapsVkSecondaryCB()) {
248         return;
249     }
250 
251     GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
252     atlasTextContext->drawGlyphRunList(fContext, fTextTarget.get(), clip, viewMatrix,
253                                        fSurfaceProps, blob);
254 }
255 
discard()256 void GrRenderTargetContext::discard() {
257     ASSERT_SINGLE_OWNER
258     RETURN_IF_ABANDONED
259     SkDEBUGCODE(this->validate();)
260     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "discard", fContext);
261 
262     AutoCheckFlush acf(this->drawingManager());
263 
264     this->getRTOpList()->discard();
265 }
266 
clear(const SkIRect * rect,const SkPMColor4f & color,CanClearFullscreen canClearFullscreen)267 void GrRenderTargetContext::clear(const SkIRect* rect,
268                                   const SkPMColor4f& color,
269                                   CanClearFullscreen canClearFullscreen) {
270     ASSERT_SINGLE_OWNER
271     RETURN_IF_ABANDONED
272     SkDEBUGCODE(this->validate();)
273     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "clear", fContext);
274 
275     AutoCheckFlush acf(this->drawingManager());
276     this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color,
277                         canClearFullscreen);
278 }
279 
clear(const GrFixedClip & clip,const SkPMColor4f & color,CanClearFullscreen canClearFullscreen)280 void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
281                                       const SkPMColor4f& color,
282                                       CanClearFullscreen canClearFullscreen) {
283     ASSERT_SINGLE_OWNER_PRIV
284     RETURN_IF_ABANDONED_PRIV
285     SkDEBUGCODE(fRenderTargetContext->validate();)
286     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clear",
287                                    fRenderTargetContext->fContext);
288 
289     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
290     fRenderTargetContext->internalClear(clip, color, canClearFullscreen);
291 }
292 
clear_to_grpaint(const SkPMColor4f & color,GrPaint * paint)293 static void clear_to_grpaint(const SkPMColor4f& color, GrPaint* paint) {
294     paint->setColor4f(color);
295     if (color.isOpaque()) {
296         // Can just rely on the src-over blend mode to do the right thing
297         paint->setPorterDuffXPFactory(SkBlendMode::kSrcOver);
298     } else {
299         // A clear overwrites the prior color, so even if it's transparent, it behaves as if it
300         // were src blended
301         paint->setPorterDuffXPFactory(SkBlendMode::kSrc);
302     }
303 }
304 
internalClear(const GrFixedClip & clip,const SkPMColor4f & color,CanClearFullscreen canClearFullscreen)305 void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
306                                           const SkPMColor4f& color,
307                                           CanClearFullscreen canClearFullscreen) {
308     bool isFull = false;
309     if (!clip.hasWindowRectangles()) {
310         isFull = !clip.scissorEnabled() ||
311                  (CanClearFullscreen::kYes == canClearFullscreen &&
312                   this->caps()->preferFullscreenClears()) ||
313                  clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
314     }
315 
316     if (isFull) {
317         if (this->getRTOpList()->resetForFullscreenClear() &&
318             !this->caps()->performColorClearsAsDraws()) {
319             // The op list was emptied and native clears are allowed, so just use the load op
320             this->getRTOpList()->setColorLoadOp(GrLoadOp::kClear, color);
321             return;
322         } else {
323             // Will use an op for the clear, reset the load op to discard since the op will
324             // blow away the color buffer contents
325             this->getRTOpList()->setColorLoadOp(GrLoadOp::kDiscard);
326         }
327 
328         // Must add an op to the list (either because we couldn't use a load op, or because the
329         // clear load op isn't supported)
330         if (this->caps()->performColorClearsAsDraws()) {
331             SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
332             GrPaint paint;
333             clear_to_grpaint(color, &paint);
334             this->addDrawOp(GrFixedClip::Disabled(),
335                             GrFillRectOp::Make(fContext, std::move(paint),
336                                                GrAAType::kNone, SkMatrix::I(), rtRect));
337         } else {
338             this->getRTOpList()->addOp(GrClearOp::Make(fContext, SkIRect::MakeEmpty(), color,
339                                                        /* fullscreen */ true), *this->caps());
340         }
341     } else {
342         if (this->caps()->performPartialClearsAsDraws()) {
343             // performPartialClearsAsDraws() also returns true if any clear has to be a draw.
344             SkRect scissor = SkRect::Make(clip.scissorRect());
345             GrPaint paint;
346             clear_to_grpaint(color, &paint);
347 
348             this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint), GrAAType::kNone,
349                                                      SkMatrix::I(), scissor));
350         } else {
351             std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color,
352                                                      this->asSurfaceProxy()));
353             // This version of the clear op factory can return null if the clip doesn't intersect
354             // with the surface proxy's boundary
355             if (!op) {
356                 return;
357             }
358             this->getRTOpList()->addOp(std::move(op), *this->caps());
359         }
360     }
361 }
362 
absClear(const SkIRect * clearRect,const SkPMColor4f & color)363 void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const SkPMColor4f& color) {
364     ASSERT_SINGLE_OWNER_PRIV
365     RETURN_IF_ABANDONED_PRIV
366     SkDEBUGCODE(fRenderTargetContext->validate();)
367     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "absClear",
368                                    fRenderTargetContext->fContext);
369 
370     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
371 
372     SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(),
373                                      fRenderTargetContext->fRenderTargetProxy->worstCaseHeight());
374 
375     if (clearRect) {
376         if (clearRect->contains(rtRect)) {
377             clearRect = nullptr; // full screen
378         } else {
379             if (!rtRect.intersect(*clearRect)) {
380                 return;
381             }
382         }
383     }
384 
385     // TODO: in a post-MDB world this should be handled at the OpList level.
386     // This makes sure to always add an op to the list, instead of marking the clear as a load op.
387     // This code follows very similar logic to internalClear() below, but critical differences are
388     // highlighted in line related to absClear()'s unique behavior.
389     if (clearRect) {
390         if (fRenderTargetContext->caps()->performPartialClearsAsDraws()) {
391             GrPaint paint;
392             clear_to_grpaint(color, &paint);
393 
394             // Use the disabled clip; the rect geometry already matches the clear rectangle and
395             // if it were added to a scissor, that would be intersected with the logical surface
396             // bounds and not the worst case dimensions required here.
397             fRenderTargetContext->addDrawOp(GrFixedClip::Disabled(),
398                                             GrFillRectOp::Make(fRenderTargetContext->fContext,
399                                                                std::move(paint),
400                                                                GrAAType::kNone,
401                                                                SkMatrix::I(),
402                                                                SkRect::Make(rtRect)));
403         } else {
404             // Must use the ClearOp factory that takes a boolean (false) instead of a surface
405             // proxy. The surface proxy variant would intersect the clip rect with its logical
406             // bounds, which is not desired in this special case.
407             fRenderTargetContext->getRTOpList()->addOp(
408                     GrClearOp::Make(fRenderTargetContext->fContext, rtRect, color,
409                                     /* fullscreen */ false),
410                     *fRenderTargetContext->caps());
411         }
412     } else {
413         // Reset the oplist like in internalClear(), but do not rely on a load op for the clear
414         fRenderTargetContext->getRTOpList()->resetForFullscreenClear();
415         fRenderTargetContext->getRTOpList()->setColorLoadOp(GrLoadOp::kDiscard);
416 
417         if (fRenderTargetContext->caps()->performColorClearsAsDraws()) {
418             // This draws a quad covering the worst case dimensions instead of just the logical
419             // width and height like in internalClear().
420             GrPaint paint;
421             clear_to_grpaint(color, &paint);
422             fRenderTargetContext->addDrawOp(GrFixedClip::Disabled(),
423                                             GrFillRectOp::Make(fRenderTargetContext->fContext,
424                                                                std::move(paint),
425                                                                GrAAType::kNone,
426                                                                SkMatrix::I(),
427                                                                SkRect::Make(rtRect)));
428         } else {
429             // Nothing special about this path in absClear compared to internalClear()
430             fRenderTargetContext->getRTOpList()->addOp(
431                     GrClearOp::Make(fRenderTargetContext->fContext, SkIRect::MakeEmpty(), color,
432                                     /* fullscreen */ true),
433                     *fRenderTargetContext->caps());
434         }
435     }
436 }
437 
drawPaint(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix)438 void GrRenderTargetContext::drawPaint(const GrClip& clip,
439                                       GrPaint&& paint,
440                                       const SkMatrix& viewMatrix) {
441     ASSERT_SINGLE_OWNER
442     RETURN_IF_ABANDONED
443     SkDEBUGCODE(this->validate();)
444     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPaint", fContext);
445 
446     // set rect to be big enough to fill the space, but not super-huge, so we
447     // don't overflow fixed-point implementations
448 
449     SkRect r = fRenderTargetProxy->getBoundsRect();
450 
451     // Check if we can optimize a clipped drawPaint(). We only do the transformation when there are
452     // no fragment processors because they may depend on having correct local coords and this path
453     // draws in device space without a local matrix. It currently handles converting clipRRect()
454     // to drawRRect() and solid colors to screen-filling drawRects() (which are then converted into
455     // clears if possible in drawRect).
456     if (!paint.numTotalFragmentProcessors()) {
457         SkRRect rrect;
458         GrAA aa = GrAA::kNo;
459         if (clip.isRRect(r, &rrect, &aa)) {
460             if (rrect.isRect()) {
461                 // Use drawFilledRect() with no clip and the reduced rectangle
462                 this->drawFilledRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect.rect());
463             } else {
464                 // Use drawRRect() with no clip
465                 this->drawRRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect,
466                                 GrStyle::SimpleFill());
467             }
468         } else {
469             // Use drawFilledRect() with no view matrix to draw a fullscreen quad, but preserve
470             // the clip. Since the paint has no FPs we can drop the view matrix without worrying
471             // about local coordinates. If the clip is simple, drawFilledRect() will turn this into
472             // a clear or a scissored clear.
473             this->drawFilledRect(clip, std::move(paint), aa, SkMatrix::I(), r);
474         }
475         return;
476     }
477 
478     // Since the paint is not trivial, there's no way at this point drawRect() could have converted
479     // this drawPaint() into an optimized clear. drawRect() would then use GrFillRectOp without
480     // a local matrix, so we can simplify things and use the local matrix variant to draw a screen
481     // filling rect with the inverse view matrix for local coords, which works for all matrix
482     // conditions.
483     SkMatrix localMatrix;
484     if (!viewMatrix.invert(&localMatrix)) {
485         return;
486     }
487 
488     AutoCheckFlush acf(this->drawingManager());
489     std::unique_ptr<GrDrawOp> op = GrFillRectOp::MakeWithLocalMatrix(
490             fContext, std::move(paint), GrAAType::kNone, SkMatrix::I(), localMatrix, r);
491     this->addDrawOp(clip, std::move(op));
492 }
493 
rect_contains_inclusive(const SkRect & rect,const SkPoint & point)494 static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
495     return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
496            point.fY >= rect.fTop && point.fY <= rect.fBottom;
497 }
498 
499 // Attempts to crop a rect and optional local rect to the clip boundaries.
500 // Returns false if the draw can be skipped entirely.
crop_filled_rect(int width,int height,const GrClip & clip,const SkMatrix & viewMatrix,SkRect * rect,SkRect * localRect=nullptr)501 static bool crop_filled_rect(int width, int height, const GrClip& clip,
502                              const SkMatrix& viewMatrix, SkRect* rect,
503                              SkRect* localRect = nullptr) {
504     if (!viewMatrix.rectStaysRect()) {
505         return true;
506     }
507 
508     SkIRect clipDevBounds;
509     SkRect clipBounds;
510 
511     clip.getConservativeBounds(width, height, &clipDevBounds);
512     if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
513         return false;
514     }
515 
516     if (localRect) {
517         if (!rect->intersects(clipBounds)) {
518             return false;
519         }
520         const SkScalar dx = localRect->width() / rect->width();
521         const SkScalar dy = localRect->height() / rect->height();
522         if (clipBounds.fLeft > rect->fLeft) {
523             localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
524             rect->fLeft = clipBounds.fLeft;
525         }
526         if (clipBounds.fTop > rect->fTop) {
527             localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
528             rect->fTop = clipBounds.fTop;
529         }
530         if (clipBounds.fRight < rect->fRight) {
531             localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
532             rect->fRight = clipBounds.fRight;
533         }
534         if (clipBounds.fBottom < rect->fBottom) {
535             localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
536             rect->fBottom = clipBounds.fBottom;
537         }
538         return true;
539     }
540 
541     return rect->intersect(clipBounds);
542 }
543 
drawFilledRectAsClear(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rect)544 bool GrRenderTargetContext::drawFilledRectAsClear(const GrClip& clip, GrPaint&& paint, GrAA aa,
545                                                   const SkMatrix& viewMatrix, const SkRect& rect) {
546     // Rules for a filled rect to become a clear [+scissor]:
547     // 1. The paint is a constant blend color with no other FPs
548     // 2. The view matrix maps rectangles to rectangles, or the transformed quad fully covers
549     //    the render target (or clear region in #3).
550     // 3. The clip is an intersection of rectangles, so the clear region will be the
551     //    intersection of the clip and the provided rect.
552     // 4. The clear region aligns with pixel bounds
553     // 5. There are no user stencil settings (and since the clip was IOR, the clip won't need
554     //    to use the stencil either).
555     // If all conditions pass, the filled rect can either be a fullscreen clear (if it's big
556     // enough), or the rectangle geometry will be used as the scissor clip on the clear.
557     // If everything passes but rule #4, this submits a simplified fill rect op instead so that the
558     // rounding differences between clip and draws don't fight each other.
559     // NOTE: we route draws into clear() regardless of performColorClearsAsDraws() since the
560     // clear call is allowed to reset the oplist even when it also happens to use a GrFillRectOp.
561 
562     SkPMColor4f clearColor;
563     if (paint.numCoverageFragmentProcessors() > 0 || !paint.isConstantBlendedColor(&clearColor)) {
564         return false;
565     }
566 
567     const SkRect rtRect = fRenderTargetProxy->getBoundsRect();
568     // Will be the intersection of render target, clip, and quad
569     SkRect combinedRect = rtRect;
570 
571     SkRRect clipRRect;
572     GrAA clipAA;
573     if (!clip.quickContains(rtRect)) {
574         // If the clip is an rrect with no rounding, then it can replace the full RT bounds as the
575         // limiting region, although we will have to worry about AA. If the clip is anything
576         // more complicated, just punt to the regular fill rect op.
577         if (!clip.isRRect(rtRect, &clipRRect, &clipAA) || !clipRRect.isRect()) {
578             return false;
579         }
580         combinedRect = clipRRect.rect();
581     } else {
582         // The clip is outside the render target, so the clip can be ignored
583         clipAA = GrAA::kNo;
584     }
585 
586     if (viewMatrix.rectStaysRect()) {
587         // Skip the extra overhead of inverting the view matrix to see if rtRect is contained in the
588         // drawn rectangle, and instead just intersect rtRect with the transformed rect. It will be
589         // the new clear region.
590         if (!combinedRect.intersect(viewMatrix.mapRect(rect))) {
591             // No intersection means nothing should be drawn, so return true but don't add an op
592             return true;
593         }
594     } else {
595         // If the transformed rectangle does not contain the combined rt and clip, the draw is too
596         // complex to be implemented as a clear
597         SkMatrix invM;
598         if (!viewMatrix.invert(&invM)) {
599             return false;
600         }
601         // The clip region in the rect's local space, so the test becomes the local rect containing
602         // the quad's points.
603         GrQuad quad(rtRect, invM);
604         if (!rect_contains_inclusive(rect, quad.point(0)) ||
605             !rect_contains_inclusive(rect, quad.point(1)) ||
606             !rect_contains_inclusive(rect, quad.point(2)) ||
607             !rect_contains_inclusive(rect, quad.point(3))) {
608             // No containment, so rtRect can't be filled by a solid color
609             return false;
610         }
611         // combinedRect can be filled by a solid color but doesn't need to be modified since it's
612         // inside the quad to be drawn.
613     }
614 
615     // Almost every condition is met; now it requires that the combined rect align with pixel
616     // boundaries in order for it to become a scissor-clear. Ignore the AA status in this case
617     // since non-AA with partial-pixel coordinates can be rounded differently on the GPU,
618     // leading to unexpected differences between a scissor test and a rasterized quad.
619     // Also skip very small rectangles since the scissor+clear doesn't by us much then.
620     if (combinedRect.contains(rtRect)) {
621         // Full screen clear
622         this->clear(nullptr, clearColor, CanClearFullscreen::kYes);
623         return true;
624     } else if (GrClip::IsPixelAligned(combinedRect) &&
625                combinedRect.width() > 256 && combinedRect.height() > 256) {
626         // Scissor + clear (round shouldn't do anything since we are pixel aligned)
627         SkIRect scissorRect;
628         combinedRect.round(&scissorRect);
629         this->clear(&scissorRect, clearColor, CanClearFullscreen::kNo);
630         return true;
631     }
632 
633     // If we got here, we can't use a scissor + clear, but combinedRect represents the correct
634     // geometry combination of quad + clip so we can perform a simplified fill rect op. We do this
635     // mostly to avoid mismatches in rounding logic on the CPU vs. the GPU, which frequently appears
636     // when drawing and clipping something to the same non-AA rect that never-the-less has
637     // non-integer coordinates.
638 
639     // For AA, use non-AA only when both clip and draw are non-AA.
640     if (clipAA == GrAA::kYes) {
641         aa = GrAA::kYes;
642     }
643     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
644     this->addDrawOp(GrFixedClip::Disabled(),
645                     GrFillRectOp::Make(fContext, std::move(paint), aaType, SkMatrix::I(),
646                                        combinedRect));
647     return true;
648 }
649 
drawFilledRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rect,const GrUserStencilSettings * ss)650 void GrRenderTargetContext::drawFilledRect(const GrClip& clip,
651                                            GrPaint&& paint,
652                                            GrAA aa,
653                                            const SkMatrix& viewMatrix,
654                                            const SkRect& rect,
655                                            const GrUserStencilSettings* ss) {
656 
657     if (!ss) {
658         if (this->drawFilledRectAsClear(clip, std::move(paint), aa, viewMatrix, rect)) {
659             return;
660         }
661         // Fall through to fill rect op
662         assert_alive(paint);
663     }
664 
665     SkRect croppedRect = rect;
666     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
667         // The rectangle would not be drawn, so no need to add a draw op to the list
668         return;
669     }
670 
671     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
672     this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint), aaType, viewMatrix,
673                                              croppedRect, ss));
674 }
675 
drawRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rect,const GrStyle * style)676 void GrRenderTargetContext::drawRect(const GrClip& clip,
677                                      GrPaint&& paint,
678                                      GrAA aa,
679                                      const SkMatrix& viewMatrix,
680                                      const SkRect& rect,
681                                      const GrStyle* style) {
682     if (!style) {
683         style = &GrStyle::SimpleFill();
684     }
685     ASSERT_SINGLE_OWNER
686     RETURN_IF_ABANDONED
687     SkDEBUGCODE(this->validate();)
688     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRect", fContext);
689 
690     // Path effects should've been devolved to a path in SkGpuDevice
691     SkASSERT(!style->pathEffect());
692 
693     AutoCheckFlush acf(this->drawingManager());
694 
695     const SkStrokeRec& stroke = style->strokeRec();
696     if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
697         this->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect);
698         return;
699     } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
700                stroke.getStyle() == SkStrokeRec::kHairline_Style) {
701         if ((!rect.width() || !rect.height()) &&
702             SkStrokeRec::kHairline_Style != stroke.getStyle()) {
703             SkScalar r = stroke.getWidth() / 2;
704             // TODO: Move these stroke->fill fallbacks to GrShape?
705             switch (stroke.getJoin()) {
706                 case SkPaint::kMiter_Join:
707                     this->drawRect(
708                             clip, std::move(paint), aa, viewMatrix,
709                             {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
710                             &GrStyle::SimpleFill());
711                     return;
712                 case SkPaint::kRound_Join:
713                     // Raster draws nothing when both dimensions are empty.
714                     if (rect.width() || rect.height()){
715                         SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
716                         this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
717                                         GrStyle::SimpleFill());
718                         return;
719                     }
720                 case SkPaint::kBevel_Join:
721                     if (!rect.width()) {
722                         this->drawRect(clip, std::move(paint), aa, viewMatrix,
723                                        {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
724                                        &GrStyle::SimpleFill());
725                     } else {
726                         this->drawRect(clip, std::move(paint), aa, viewMatrix,
727                                        {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
728                                        &GrStyle::SimpleFill());
729                     }
730                     return;
731                 }
732         }
733 
734         std::unique_ptr<GrDrawOp> op;
735 
736         GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
737         op = GrStrokeRectOp::Make(fContext, std::move(paint), aaType, viewMatrix, rect, stroke);
738         // op may be null if the stroke is not supported or if using coverage aa and the view matrix
739         // does not preserve rectangles.
740         if (op) {
741             this->addDrawOp(clip, std::move(op));
742             return;
743         }
744     }
745     assert_alive(paint);
746     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(rect, *style));
747 }
748 
drawQuadSet(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const QuadSetEntry quads[],int cnt)749 void GrRenderTargetContext::drawQuadSet(const GrClip& clip, GrPaint&& paint, GrAA aa,
750                                         const SkMatrix& viewMatrix, const QuadSetEntry quads[],
751                                         int cnt) {
752     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
753     this->addDrawOp(clip, GrFillRectOp::MakeSet(fContext, std::move(paint), aaType, viewMatrix,
754                                                 quads, cnt));
755 }
756 
maxWindowRectangles() const757 int GrRenderTargetContextPriv::maxWindowRectangles() const {
758     return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
759             *fRenderTargetContext->caps());
760 }
761 
clearStencilClip(const GrFixedClip & clip,bool insideStencilMask)762 void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
763     ASSERT_SINGLE_OWNER_PRIV
764     RETURN_IF_ABANDONED_PRIV
765     SkDEBUGCODE(fRenderTargetContext->validate();)
766     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clearStencilClip",
767                                    fRenderTargetContext->fContext);
768 
769     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
770 
771     fRenderTargetContext->internalStencilClear(clip, insideStencilMask);
772 }
773 
internalStencilClear(const GrFixedClip & clip,bool insideStencilMask)774 void GrRenderTargetContext::internalStencilClear(const GrFixedClip& clip, bool insideStencilMask) {
775     if (this->caps()->performStencilClearsAsDraws()) {
776         const GrUserStencilSettings* ss = GrStencilSettings::SetClipBitSettings(insideStencilMask);
777         SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
778 
779         // Configure the paint to have no impact on the color buffer
780         GrPaint paint;
781         paint.setColor4f({0.f, 0.f, 0.f, 0.f});
782         paint.setPorterDuffXPFactory(SkBlendMode::kSrcOver);
783 
784         // Mark stencil usage here before addDrawOp() so that it doesn't try to re-call
785         // internalStencilClear() just because the op has stencil settings.
786         this->setNeedsStencil();
787         this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint),
788                         GrAAType::kNone, SkMatrix::I(), rtRect, ss));
789     } else {
790         std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(fContext, clip, insideStencilMask,
791                                                             fRenderTargetProxy.get()));
792         if (!op) {
793             return;
794         }
795         this->getRTOpList()->addOp(std::move(op), *this->caps());
796     }
797 }
798 
stencilPath(const GrHardClip & clip,GrAAType aaType,const SkMatrix & viewMatrix,const GrPath * path)799 void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip,
800                                             GrAAType aaType,
801                                             const SkMatrix& viewMatrix,
802                                             const GrPath* path) {
803     ASSERT_SINGLE_OWNER_PRIV
804     RETURN_IF_ABANDONED_PRIV
805     SkDEBUGCODE(fRenderTargetContext->validate();)
806     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilPath",
807                                    fRenderTargetContext->fContext);
808 
809     SkASSERT(aaType != GrAAType::kCoverage);
810 
811     bool useHWAA = GrAATypeIsHW(aaType);
812     // TODO: extract portions of checkDraw that are relevant to path stenciling.
813     SkASSERT(path);
814     SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
815 
816     // FIXME: Use path bounds instead of this WAR once
817     // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
818     SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
819 
820     // Setup clip
821     GrAppliedHardClip appliedClip;
822     if (!clip.apply(fRenderTargetContext->width(), fRenderTargetContext->height(), &appliedClip,
823                     &bounds)) {
824         return;
825     }
826 
827     fRenderTargetContext->setNeedsStencil();
828 
829     std::unique_ptr<GrOp> op = GrStencilPathOp::Make(fRenderTargetContext->fContext,
830                                                      viewMatrix,
831                                                      useHWAA,
832                                                      path->getFillType(),
833                                                      appliedClip.hasStencilClip(),
834                                                      appliedClip.scissorState(),
835                                                      path);
836     if (!op) {
837         return;
838     }
839     op->setClippedBounds(bounds);
840     fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
841 }
842 
stencilRect(const GrHardClip & clip,const GrUserStencilSettings * ss,GrAAType aaType,const SkMatrix & viewMatrix,const SkRect & rect)843 void GrRenderTargetContextPriv::stencilRect(const GrHardClip& clip,
844                                             const GrUserStencilSettings* ss,
845                                             GrAAType aaType,
846                                             const SkMatrix& viewMatrix,
847                                             const SkRect& rect) {
848     ASSERT_SINGLE_OWNER_PRIV
849     RETURN_IF_ABANDONED_PRIV
850     SkDEBUGCODE(fRenderTargetContext->validate();)
851     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilRect",
852                                    fRenderTargetContext->fContext);
853 
854     SkASSERT(GrAAType::kCoverage != aaType);
855     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
856 
857     GrPaint paint;
858     paint.setXPFactory(GrDisableColorXPFactory::Get());
859     std::unique_ptr<GrDrawOp> op = GrFillRectOp::Make(
860             fRenderTargetContext->fContext, std::move(paint), aaType, viewMatrix,  rect, ss);
861     fRenderTargetContext->addDrawOp(clip, std::move(op));
862 }
863 
drawAndStencilRect(const GrHardClip & clip,const GrUserStencilSettings * ss,SkRegion::Op op,bool invert,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rect)864 bool GrRenderTargetContextPriv::drawAndStencilRect(const GrHardClip& clip,
865                                                    const GrUserStencilSettings* ss,
866                                                    SkRegion::Op op,
867                                                    bool invert,
868                                                    GrAA aa,
869                                                    const SkMatrix& viewMatrix,
870                                                    const SkRect& rect) {
871     ASSERT_SINGLE_OWNER_PRIV
872     RETURN_FALSE_IF_ABANDONED_PRIV
873     SkDEBUGCODE(fRenderTargetContext->validate();)
874     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilRect",
875                                    fRenderTargetContext->fContext);
876 
877     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
878 
879     GrPaint paint;
880     paint.setCoverageSetOpXPFactory(op, invert);
881 
882     // This will always succeed to draw a rectangle
883     fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss);
884     return true;
885 }
886 
fillRectToRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rectToDraw,const SkRect & localRect)887 void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
888                                            GrPaint&& paint,
889                                            GrAA aa,
890                                            const SkMatrix& viewMatrix,
891                                            const SkRect& rectToDraw,
892                                            const SkRect& localRect) {
893     ASSERT_SINGLE_OWNER
894     RETURN_IF_ABANDONED
895     SkDEBUGCODE(this->validate();)
896             GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectToRect", fContext);
897 
898     SkRect croppedRect = rectToDraw;
899     SkRect croppedLocalRect = localRect;
900     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
901                           &croppedRect, &croppedLocalRect)) {
902         return;
903     }
904 
905     AutoCheckFlush acf(this->drawingManager());
906 
907     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
908     this->addDrawOp(clip, GrFillRectOp::MakeWithLocalRect(fContext, std::move(paint), aaType,
909             viewMatrix, croppedRect, croppedLocalRect));
910 }
911 
fillRectWithEdgeAA(const GrClip & clip,GrPaint && paint,GrQuadAAFlags edgeAA,const SkMatrix & viewMatrix,const SkRect & rect)912 void GrRenderTargetContext::fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint,
913                                                GrQuadAAFlags edgeAA, const SkMatrix& viewMatrix,
914                                                const SkRect& rect) {
915     ASSERT_SINGLE_OWNER
916     RETURN_IF_ABANDONED
917     SkDEBUGCODE(this->validate();)
918     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithEdgeAA", fContext);
919 
920     // If aaType turns into MSAA, make sure to keep quads with no AA edges as MSAA. Sending those
921     // to drawFilledRect() would have it turn off MSAA in that case, which breaks seaming with
922     // any partial AA edges that kept MSAA.
923     GrAAType aaType = this->chooseAAType(GrAA::kYes, GrAllowMixedSamples::kNo);
924     if (aaType != GrAAType::kMSAA &&
925         (edgeAA == GrQuadAAFlags::kNone || edgeAA == GrQuadAAFlags::kAll)) {
926         // This is equivalent to a regular filled rect draw, so route through there to take
927         // advantage of draw->clear optimizations
928         this->drawFilledRect(clip, std::move(paint), GrAA(edgeAA == GrQuadAAFlags::kAll),
929                              viewMatrix, rect);
930         return;
931     }
932 
933     SkRect croppedRect = rect;
934     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
935         return;
936     }
937 
938     AutoCheckFlush acf(this->drawingManager());
939     this->addDrawOp(clip, GrFillRectOp::MakePerEdge(fContext, std::move(paint), aaType, edgeAA,
940                                                     viewMatrix, croppedRect));
941 }
942 
drawTexture(const GrClip & clip,sk_sp<GrTextureProxy> proxy,GrSamplerState::Filter filter,const SkPMColor4f & color,const SkRect & srcRect,const SkRect & dstRect,GrQuadAAFlags aaFlags,SkCanvas::SrcRectConstraint constraint,const SkMatrix & viewMatrix,sk_sp<GrColorSpaceXform> textureColorSpaceXform)943 void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
944                                         GrSamplerState::Filter filter, const SkPMColor4f& color,
945                                         const SkRect& srcRect, const SkRect& dstRect,
946                                         GrQuadAAFlags aaFlags,
947                                         SkCanvas::SrcRectConstraint constraint,
948                                         const SkMatrix& viewMatrix,
949                                         sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
950     ASSERT_SINGLE_OWNER
951     RETURN_IF_ABANDONED
952     SkDEBUGCODE(this->validate();)
953     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTexture", fContext);
954     if (constraint == SkCanvas::kStrict_SrcRectConstraint &&
955         srcRect.contains(proxy->getWorstCaseBoundsRect())) {
956         constraint = SkCanvas::kFast_SrcRectConstraint;
957     }
958     GrAAType aaType =
959             this->chooseAAType(GrAA(aaFlags != GrQuadAAFlags::kNone), GrAllowMixedSamples::kNo);
960     SkRect clippedDstRect = dstRect;
961     SkRect clippedSrcRect = srcRect;
962     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &clippedDstRect,
963                           &clippedSrcRect)) {
964         return;
965     }
966     auto op = GrTextureOp::Make(fContext, std::move(proxy), filter, color, clippedSrcRect,
967                                 clippedDstRect, aaType, aaFlags, constraint, viewMatrix,
968                                 std::move(textureColorSpaceXform));
969     this->addDrawOp(clip, std::move(op));
970 }
971 
drawTextureSet(const GrClip & clip,const TextureSetEntry set[],int cnt,GrSamplerState::Filter filter,SkBlendMode mode,const SkMatrix & viewMatrix,sk_sp<GrColorSpaceXform> texXform)972 void GrRenderTargetContext::drawTextureSet(const GrClip& clip, const TextureSetEntry set[], int cnt,
973                                            GrSamplerState::Filter filter, SkBlendMode mode,
974                                            const SkMatrix& viewMatrix,
975                                            sk_sp<GrColorSpaceXform> texXform) {
976     ASSERT_SINGLE_OWNER
977     RETURN_IF_ABANDONED
978     SkDEBUGCODE(this->validate();)
979     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextureSet", fContext);
980 
981     AutoCheckFlush acf(this->drawingManager());
982 
983     GrAAType aaType = this->chooseAAType(GrAA::kYes, GrAllowMixedSamples::kNo);
984     if (mode != SkBlendMode::kSrcOver ||
985         !fContext->contextPriv().caps()->dynamicStateArrayGeometryProcessorTextureSupport()) {
986         // Draw one at a time with GrFillRectOp and a GrPaint that emulates what GrTextureOp does
987         const GrXPFactory* xpFactory = SkBlendMode_AsXPFactory(mode);
988         for (int i = 0; i < cnt; ++i) {
989             GrPaint paint;
990             paint.setColor4f({set[i].fAlpha, set[i].fAlpha, set[i].fAlpha, set[i].fAlpha});
991             paint.setXPFactory(xpFactory);
992 
993             // See if we can disable bilerp filtering when the src and dst rects line up
994             if (filter != GrSamplerState::Filter::kNearest &&
995                 !GrTextureOp::GetFilterHasEffect(viewMatrix, set[i].fSrcRect, set[i].fDstRect)) {
996                 filter = GrSamplerState::Filter::kNearest;
997             }
998 
999             auto fp = GrSimpleTextureEffect::Make(set[i].fProxy, SkMatrix::I(), filter);
1000             fp = GrColorSpaceXformEffect::Make(std::move(fp), texXform);
1001             paint.addColorFragmentProcessor(std::move(fp));
1002 
1003             auto op = GrFillRectOp::MakePerEdgeWithLocalRect(fContext, std::move(paint), aaType,
1004                                                              set[i].fAAFlags, viewMatrix,
1005                                                              set[i].fDstRect, set[i].fSrcRect);
1006             this->addDrawOp(clip, std::move(op));
1007         }
1008     } else {
1009         // Can use a single op, avoiding GrPaint creation, and can batch across proxies
1010         auto op = GrTextureOp::Make(fContext, set, cnt, filter, aaType, viewMatrix,
1011                                     std::move(texXform));
1012         this->addDrawOp(clip, std::move(op));
1013     }
1014 }
1015 
fillRectWithLocalMatrix(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rectToDraw,const SkMatrix & localMatrix)1016 void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
1017                                                     GrPaint&& paint,
1018                                                     GrAA aa,
1019                                                     const SkMatrix& viewMatrix,
1020                                                     const SkRect& rectToDraw,
1021                                                     const SkMatrix& localMatrix) {
1022     ASSERT_SINGLE_OWNER
1023     RETURN_IF_ABANDONED
1024     SkDEBUGCODE(this->validate();)
1025     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithLocalMatrix", fContext);
1026 
1027     SkRect croppedRect = rectToDraw;
1028     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
1029         return;
1030     }
1031 
1032     AutoCheckFlush acf(this->drawingManager());
1033 
1034     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1035     this->addDrawOp(clip, GrFillRectOp::MakeWithLocalMatrix(fContext, std::move(paint), aaType,
1036                                                             viewMatrix, localMatrix, croppedRect));
1037 }
1038 
drawVertices(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix,sk_sp<SkVertices> vertices,const SkVertices::Bone bones[],int boneCount,GrPrimitiveType * overridePrimType)1039 void GrRenderTargetContext::drawVertices(const GrClip& clip,
1040                                          GrPaint&& paint,
1041                                          const SkMatrix& viewMatrix,
1042                                          sk_sp<SkVertices> vertices,
1043                                          const SkVertices::Bone bones[],
1044                                          int boneCount,
1045                                          GrPrimitiveType* overridePrimType) {
1046     ASSERT_SINGLE_OWNER
1047     RETURN_IF_ABANDONED
1048     SkDEBUGCODE(this->validate();)
1049     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawVertices", fContext);
1050 
1051     AutoCheckFlush acf(this->drawingManager());
1052 
1053     SkASSERT(vertices);
1054     GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
1055     std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make(
1056             fContext, std::move(paint), std::move(vertices), bones, boneCount, viewMatrix, aaType,
1057             this->colorSpaceInfo().refColorSpaceXformFromSRGB(), overridePrimType);
1058     this->addDrawOp(clip, std::move(op));
1059 }
1060 
1061 ///////////////////////////////////////////////////////////////////////////////
1062 
drawAtlas(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix,int spriteCount,const SkRSXform xform[],const SkRect texRect[],const SkColor colors[])1063 void GrRenderTargetContext::drawAtlas(const GrClip& clip,
1064                                       GrPaint&& paint,
1065                                       const SkMatrix& viewMatrix,
1066                                       int spriteCount,
1067                                       const SkRSXform xform[],
1068                                       const SkRect texRect[],
1069                                       const SkColor colors[]) {
1070     ASSERT_SINGLE_OWNER
1071     RETURN_IF_ABANDONED
1072     SkDEBUGCODE(this->validate();)
1073     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawAtlas", fContext);
1074 
1075     AutoCheckFlush acf(this->drawingManager());
1076 
1077     GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
1078     std::unique_ptr<GrDrawOp> op = GrDrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
1079                                                        aaType, spriteCount, xform, texRect, colors);
1080     this->addDrawOp(clip, std::move(op));
1081 }
1082 
1083 ///////////////////////////////////////////////////////////////////////////////
1084 
drawRRect(const GrClip & origClip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRRect & rrect,const GrStyle & style)1085 void GrRenderTargetContext::drawRRect(const GrClip& origClip,
1086                                       GrPaint&& paint,
1087                                       GrAA aa,
1088                                       const SkMatrix& viewMatrix,
1089                                       const SkRRect& rrect,
1090                                       const GrStyle& style) {
1091     ASSERT_SINGLE_OWNER
1092     RETURN_IF_ABANDONED
1093     SkDEBUGCODE(this->validate();)
1094     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRRect", fContext);
1095 
1096     const SkStrokeRec& stroke = style.strokeRec();
1097     if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.isEmpty()) {
1098        return;
1099     }
1100 
1101     GrNoClip noclip;
1102     const GrClip* clip = &origClip;
1103 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
1104     // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
1105     // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
1106     // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
1107     // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
1108     // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
1109     SkRRect devRRect;
1110     if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
1111         clip = &noclip;
1112     }
1113 #endif
1114     SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
1115 
1116     AutoCheckFlush acf(this->drawingManager());
1117 
1118     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1119     if (GrAAType::kCoverage == aaType) {
1120         std::unique_ptr<GrDrawOp> op;
1121         if (style.isSimpleFill()) {
1122             op = GrAAFillRRectOp::Make(fContext, viewMatrix, rrect, *this->caps(),
1123                                        std::move(paint));
1124         }
1125         if (!op) {
1126             assert_alive(paint);
1127             op = GrOvalOpFactory::MakeRRectOp(fContext, std::move(paint), viewMatrix, rrect, stroke,
1128                                               this->caps()->shaderCaps());
1129         }
1130 
1131         if (op) {
1132             this->addDrawOp(*clip, std::move(op));
1133             return;
1134         }
1135     }
1136 
1137     assert_alive(paint);
1138     this->drawShapeUsingPathRenderer(*clip, std::move(paint), aa, viewMatrix,
1139                                      GrShape(rrect, style));
1140 }
1141 
1142 ///////////////////////////////////////////////////////////////////////////////
1143 
map(const SkMatrix & m,const SkPoint3 & pt)1144 static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) {
1145     SkPoint3 result;
1146     m.mapXY(pt.fX, pt.fY, (SkPoint*)&result.fX);
1147     result.fZ = pt.fZ;
1148     return result;
1149 }
1150 
drawFastShadow(const GrClip & clip,const SkMatrix & viewMatrix,const SkPath & path,const SkDrawShadowRec & rec)1151 bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
1152                                            const SkMatrix& viewMatrix,
1153                                            const SkPath& path,
1154                                            const SkDrawShadowRec& rec) {
1155     ASSERT_SINGLE_OWNER
1156     if (this->drawingManager()->wasAbandoned()) {
1157         return true;
1158     }
1159     SkDEBUGCODE(this->validate();)
1160     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawFastShadow", fContext);
1161 
1162     // check z plane
1163     bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) ||
1164                                !SkScalarNearlyZero(rec.fZPlaneParams.fY));
1165     bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
1166     if (tiltZPlane || skipAnalytic || !viewMatrix.rectStaysRect() || !viewMatrix.isSimilarity()) {
1167         return false;
1168     }
1169 
1170     SkRRect rrect;
1171     SkRect rect;
1172     // we can only handle rects, circles, and rrects with circular corners
1173     bool isRRect = path.isRRect(&rrect) && SkRRectPriv::IsSimpleCircular(rrect) &&
1174         rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero;
1175     if (!isRRect &&
1176         path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
1177         rect.width() > SK_ScalarNearlyZero) {
1178         rrect.setOval(rect);
1179         isRRect = true;
1180     }
1181     if (!isRRect && path.isRect(&rect)) {
1182         rrect.setRect(rect);
1183         isRRect = true;
1184     }
1185 
1186     if (!isRRect) {
1187         return false;
1188     }
1189 
1190     if (rrect.isEmpty()) {
1191         return true;
1192     }
1193 
1194     AutoCheckFlush acf(this->drawingManager());
1195 
1196     // transform light
1197     SkPoint3 devLightPos = map(viewMatrix, rec.fLightPos);
1198 
1199     // 1/scale
1200     SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ?
1201         SkScalarInvert(viewMatrix[SkMatrix::kMScaleX]) :
1202         sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] +
1203                        viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]);
1204 
1205     SkScalar occluderHeight = rec.fZPlaneParams.fZ;
1206     bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
1207 
1208     if (SkColorGetA(rec.fAmbientColor) > 0) {
1209         SkScalar devSpaceInsetWidth = SkDrawShadowMetrics::AmbientBlurRadius(occluderHeight);
1210         const SkScalar umbraRecipAlpha = SkDrawShadowMetrics::AmbientRecipAlpha(occluderHeight);
1211         const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha;
1212 
1213         // Outset the shadow rrect to the border of the penumbra
1214         SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale;
1215         SkRRect ambientRRect;
1216         SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset);
1217         // If the rrect was an oval then its outset will also be one.
1218         // We set it explicitly to avoid errors.
1219         if (rrect.isOval()) {
1220             ambientRRect = SkRRect::MakeOval(outsetRect);
1221         } else {
1222             SkScalar outsetRad = SkRRectPriv::GetSimpleRadii(rrect).fX + ambientPathOutset;
1223             ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1224         }
1225 
1226         GrColor ambientColor = SkColorToPremulGrColor(rec.fAmbientColor);
1227         if (transparent) {
1228             // set a large inset to force a fill
1229             devSpaceInsetWidth = ambientRRect.width();
1230         }
1231 
1232         std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1233                                                              ambientColor,
1234                                                              viewMatrix,
1235                                                              ambientRRect,
1236                                                              devSpaceAmbientBlur,
1237                                                              devSpaceInsetWidth);
1238         SkASSERT(op);
1239         this->addDrawOp(clip, std::move(op));
1240     }
1241 
1242     if (SkColorGetA(rec.fSpotColor) > 0) {
1243         SkScalar devSpaceSpotBlur;
1244         SkScalar spotScale;
1245         SkVector spotOffset;
1246         SkDrawShadowMetrics::GetSpotParams(occluderHeight, devLightPos.fX, devLightPos.fY,
1247                                            devLightPos.fZ, rec.fLightRadius,
1248                                            &devSpaceSpotBlur, &spotScale, &spotOffset);
1249         // handle scale of radius due to CTM
1250         const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale;
1251 
1252         // Adjust translate for the effect of the scale.
1253         spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX];
1254         spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY];
1255         // This offset is in dev space, need to transform it into source space.
1256         SkMatrix ctmInverse;
1257         if (viewMatrix.invert(&ctmInverse)) {
1258             ctmInverse.mapPoints(&spotOffset, 1);
1259         } else {
1260             // Since the matrix is a similarity, this should never happen, but just in case...
1261             SkDebugf("Matrix is degenerate. Will not render spot shadow correctly!\n");
1262             SkASSERT(false);
1263         }
1264 
1265         // Compute the transformed shadow rrect
1266         SkRRect spotShadowRRect;
1267         SkMatrix shadowTransform;
1268         shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY);
1269         rrect.transform(shadowTransform, &spotShadowRRect);
1270         SkScalar spotRadius = SkRRectPriv::GetSimpleRadii(spotShadowRRect).fX;
1271 
1272         // Compute the insetWidth
1273         SkScalar blurOutset = srcSpaceSpotBlur;
1274         SkScalar insetWidth = blurOutset;
1275         if (transparent) {
1276             // If transparent, just do a fill
1277             insetWidth += spotShadowRRect.width();
1278         } else {
1279             // For shadows, instead of using a stroke we specify an inset from the penumbra
1280             // border. We want to extend this inset area so that it meets up with the caster
1281             // geometry. The inset geometry will by default already be inset by the blur width.
1282             //
1283             // We compare the min and max corners inset by the radius between the original
1284             // rrect and the shadow rrect. The distance between the two plus the difference
1285             // between the scaled radius and the original radius gives the distance from the
1286             // transformed shadow shape to the original shape in that corner. The max
1287             // of these gives the maximum distance we need to cover.
1288             //
1289             // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to
1290             // that to get the full insetWidth.
1291             SkScalar maxOffset;
1292             if (rrect.isRect()) {
1293                 // Manhattan distance works better for rects
1294                 maxOffset = SkTMax(SkTMax(SkTAbs(spotShadowRRect.rect().fLeft -
1295                                                  rrect.rect().fLeft),
1296                                           SkTAbs(spotShadowRRect.rect().fTop -
1297                                                  rrect.rect().fTop)),
1298                                    SkTMax(SkTAbs(spotShadowRRect.rect().fRight -
1299                                                  rrect.rect().fRight),
1300                                           SkTAbs(spotShadowRRect.rect().fBottom -
1301                                                  rrect.rect().fBottom)));
1302             } else {
1303                 SkScalar dr = spotRadius - SkRRectPriv::GetSimpleRadii(rrect).fX;
1304                 SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft -
1305                                                         rrect.rect().fLeft + dr,
1306                                                         spotShadowRRect.rect().fTop -
1307                                                         rrect.rect().fTop + dr);
1308                 SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight -
1309                                                          rrect.rect().fRight - dr,
1310                                                          spotShadowRRect.rect().fBottom -
1311                                                          rrect.rect().fBottom - dr);
1312                 maxOffset = SkScalarSqrt(SkTMax(SkPointPriv::LengthSqd(upperLeftOffset),
1313                                                 SkPointPriv::LengthSqd(lowerRightOffset))) + dr;
1314             }
1315             insetWidth += SkTMax(blurOutset, maxOffset);
1316         }
1317 
1318         // Outset the shadow rrect to the border of the penumbra
1319         SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset);
1320         if (spotShadowRRect.isOval()) {
1321             spotShadowRRect = SkRRect::MakeOval(outsetRect);
1322         } else {
1323             SkScalar outsetRad = spotRadius + blurOutset;
1324             spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1325         }
1326 
1327         GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor);
1328 
1329         std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1330                                                              spotColor,
1331                                                              viewMatrix,
1332                                                              spotShadowRRect,
1333                                                              2.0f * devSpaceSpotBlur,
1334                                                              insetWidth);
1335         SkASSERT(op);
1336         this->addDrawOp(clip, std::move(op));
1337     }
1338 
1339     return true;
1340 }
1341 
1342 ///////////////////////////////////////////////////////////////////////////////
1343 
drawFilledDRRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRRect & origOuter,const SkRRect & origInner)1344 bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
1345                                              GrPaint&& paint,
1346                                              GrAA aa,
1347                                              const SkMatrix& viewMatrix,
1348                                              const SkRRect& origOuter,
1349                                              const SkRRect& origInner) {
1350     SkASSERT(!origInner.isEmpty());
1351     SkASSERT(!origOuter.isEmpty());
1352 
1353     SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1354 
1355     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1356 
1357     if (GrAAType::kMSAA == aaType) {
1358         return false;
1359     }
1360 
1361     if (GrAAType::kCoverage == aaType && SkRRectPriv::IsCircle(*inner)
1362                                       && SkRRectPriv::IsCircle(*outer)) {
1363         auto outerR = outer->width() / 2.f;
1364         auto innerR = inner->width() / 2.f;
1365         auto cx = outer->getBounds().fLeft + outerR;
1366         auto cy = outer->getBounds().fTop + outerR;
1367         if (SkScalarNearlyEqual(cx, inner->getBounds().fLeft + innerR) &&
1368             SkScalarNearlyEqual(cy, inner->getBounds().fTop + innerR)) {
1369             auto avgR = (innerR + outerR) / 2.f;
1370             auto circleBounds = SkRect::MakeLTRB(cx - avgR, cy - avgR, cx + avgR, cy + avgR);
1371             SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
1372             stroke.setStrokeStyle(outerR - innerR);
1373             auto op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix,
1374                                                   circleBounds, GrStyle(stroke, nullptr),
1375                                                   this->caps()->shaderCaps());
1376             if (op) {
1377                 this->addDrawOp(clip, std::move(op));
1378                 return true;
1379             }
1380             assert_alive(paint);
1381         }
1382     }
1383 
1384     GrClipEdgeType innerEdgeType, outerEdgeType;
1385     if (GrAAType::kCoverage == aaType) {
1386         innerEdgeType = GrClipEdgeType::kInverseFillAA;
1387         outerEdgeType = GrClipEdgeType::kFillAA;
1388     } else {
1389         innerEdgeType = GrClipEdgeType::kInverseFillBW;
1390         outerEdgeType = GrClipEdgeType::kFillBW;
1391     }
1392 
1393     SkMatrix inverseVM;
1394     if (!viewMatrix.isIdentity()) {
1395         if (!origInner.transform(viewMatrix, inner.writable())) {
1396             return false;
1397         }
1398         if (!origOuter.transform(viewMatrix, outer.writable())) {
1399             return false;
1400         }
1401         if (!viewMatrix.invert(&inverseVM)) {
1402             return false;
1403         }
1404     } else {
1405         inverseVM.reset();
1406     }
1407 
1408     const auto& caps = *this->caps()->shaderCaps();
1409     // TODO these need to be a geometry processors
1410     auto innerEffect = GrRRectEffect::Make(innerEdgeType, *inner, caps);
1411     if (!innerEffect) {
1412         return false;
1413     }
1414 
1415     auto outerEffect = GrRRectEffect::Make(outerEdgeType, *outer, caps);
1416     if (!outerEffect) {
1417         return false;
1418     }
1419 
1420     paint.addCoverageFragmentProcessor(std::move(innerEffect));
1421     paint.addCoverageFragmentProcessor(std::move(outerEffect));
1422 
1423     SkRect bounds = outer->getBounds();
1424     if (GrAAType::kCoverage == aaType) {
1425         bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1426     }
1427 
1428     this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1429                                   inverseVM);
1430     return true;
1431 }
1432 
drawDRRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRRect & outer,const SkRRect & inner)1433 void GrRenderTargetContext::drawDRRect(const GrClip& clip,
1434                                        GrPaint&& paint,
1435                                        GrAA aa,
1436                                        const SkMatrix& viewMatrix,
1437                                        const SkRRect& outer,
1438                                        const SkRRect& inner) {
1439     ASSERT_SINGLE_OWNER
1440     RETURN_IF_ABANDONED
1441     SkDEBUGCODE(this->validate();)
1442     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawDRRect", fContext);
1443 
1444     SkASSERT(!outer.isEmpty());
1445     SkASSERT(!inner.isEmpty());
1446 
1447     AutoCheckFlush acf(this->drawingManager());
1448 
1449     if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
1450         return;
1451     }
1452     assert_alive(paint);
1453 
1454     SkPath path;
1455     path.setIsVolatile(true);
1456     path.addRRect(inner);
1457     path.addRRect(outer);
1458     path.setFillType(SkPath::kEvenOdd_FillType);
1459     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(path));
1460 }
1461 
1462 ///////////////////////////////////////////////////////////////////////////////
1463 
drawRegion(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRegion & region,const GrStyle & style,const GrUserStencilSettings * ss)1464 void GrRenderTargetContext::drawRegion(const GrClip& clip,
1465                                        GrPaint&& paint,
1466                                        GrAA aa,
1467                                        const SkMatrix& viewMatrix,
1468                                        const SkRegion& region,
1469                                        const GrStyle& style,
1470                                        const GrUserStencilSettings* ss) {
1471     ASSERT_SINGLE_OWNER
1472     RETURN_IF_ABANDONED
1473     SkDEBUGCODE(this->validate();)
1474     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRegion", fContext);
1475 
1476     if (GrAA::kYes == aa) {
1477         // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
1478         // to see whether aa is really required.
1479         if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
1480             SkScalarIsInt(viewMatrix.getTranslateX()) &&
1481             SkScalarIsInt(viewMatrix.getTranslateY())) {
1482             aa = GrAA::kNo;
1483         }
1484     }
1485     bool complexStyle = !style.isSimpleFill();
1486     if (complexStyle || GrAA::kYes == aa) {
1487         SkPath path;
1488         region.getBoundaryPath(&path);
1489         path.setIsVolatile(true);
1490 
1491         return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
1492     }
1493 
1494     GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
1495     std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(fContext, std::move(paint), viewMatrix, region,
1496                                                     aaType, ss);
1497     this->addDrawOp(clip, std::move(op));
1498 }
1499 
drawOval(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & oval,const GrStyle & style)1500 void GrRenderTargetContext::drawOval(const GrClip& clip,
1501                                      GrPaint&& paint,
1502                                      GrAA aa,
1503                                      const SkMatrix& viewMatrix,
1504                                      const SkRect& oval,
1505                                      const GrStyle& style) {
1506     ASSERT_SINGLE_OWNER
1507     RETURN_IF_ABANDONED
1508     SkDEBUGCODE(this->validate();)
1509     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawOval", fContext);
1510 
1511     const SkStrokeRec& stroke = style.strokeRec();
1512 
1513     if (oval.isEmpty() && !style.pathEffect()) {
1514         if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
1515             return;
1516         }
1517 
1518         this->drawRect(clip, std::move(paint), aa, viewMatrix, oval, &style);
1519         return;
1520     }
1521 
1522     AutoCheckFlush acf(this->drawingManager());
1523 
1524     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1525     if (GrAAType::kCoverage == aaType) {
1526         std::unique_ptr<GrDrawOp> op;
1527         // GrAAFillRRectOp has special geometry and a fragment-shader branch to conditionally
1528         // evaluate the arc equation. This same special geometry and fragment branch also turn out
1529         // to be a substantial optimization for drawing ovals (namely, by not evaluating the arc
1530         // equation inside the oval's inner diamond). Given these optimizations, it's a clear win to
1531         // draw ovals the exact same way we do round rects.
1532         //
1533         // However, we still don't draw true circles as round rects, because it can cause perf
1534         // regressions on some platforms as compared to the dedicated circle Op.
1535         if (style.isSimpleFill() && oval.height() != oval.width()) {
1536             op = GrAAFillRRectOp::Make(fContext, viewMatrix, SkRRect::MakeOval(oval), *this->caps(),
1537                                        std::move(paint));
1538         }
1539         if (!op) {
1540             assert_alive(paint);
1541             op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix, oval, style,
1542                                              this->caps()->shaderCaps());
1543         }
1544         if (op) {
1545             this->addDrawOp(clip, std::move(op));
1546             return;
1547         }
1548     }
1549 
1550     assert_alive(paint);
1551     this->drawShapeUsingPathRenderer(
1552             clip, std::move(paint), aa, viewMatrix,
1553             GrShape(SkRRect::MakeOval(oval), SkPath::kCW_Direction, 2, false, style));
1554 }
1555 
drawArc(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const GrStyle & style)1556 void GrRenderTargetContext::drawArc(const GrClip& clip,
1557                                     GrPaint&& paint,
1558                                     GrAA aa,
1559                                     const SkMatrix& viewMatrix,
1560                                     const SkRect& oval,
1561                                     SkScalar startAngle,
1562                                     SkScalar sweepAngle,
1563                                     bool useCenter,
1564                                     const GrStyle& style) {
1565     ASSERT_SINGLE_OWNER
1566     RETURN_IF_ABANDONED
1567     SkDEBUGCODE(this->validate();)
1568             GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawArc", fContext);
1569 
1570     AutoCheckFlush acf(this->drawingManager());
1571 
1572     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1573     if (GrAAType::kCoverage == aaType) {
1574         const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
1575         std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(fContext,
1576                                                                   std::move(paint),
1577                                                                   viewMatrix,
1578                                                                   oval,
1579                                                                   startAngle,
1580                                                                   sweepAngle,
1581                                                                   useCenter,
1582                                                                   style,
1583                                                                   shaderCaps);
1584         if (op) {
1585             this->addDrawOp(clip, std::move(op));
1586             return;
1587         }
1588         assert_alive(paint);
1589     }
1590     this->drawShapeUsingPathRenderer(
1591             clip, std::move(paint), aa, viewMatrix,
1592             GrShape::MakeArc(oval, startAngle, sweepAngle, useCenter, style));
1593 }
1594 
drawImageLattice(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix,sk_sp<GrTextureProxy> image,sk_sp<GrColorSpaceXform> csxf,GrSamplerState::Filter filter,std::unique_ptr<SkLatticeIter> iter,const SkRect & dst)1595 void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
1596                                              GrPaint&& paint,
1597                                              const SkMatrix& viewMatrix,
1598                                              sk_sp<GrTextureProxy> image,
1599                                              sk_sp<GrColorSpaceXform> csxf,
1600                                              GrSamplerState::Filter filter,
1601                                              std::unique_ptr<SkLatticeIter> iter,
1602                                              const SkRect& dst) {
1603     ASSERT_SINGLE_OWNER
1604     RETURN_IF_ABANDONED
1605     SkDEBUGCODE(this->validate();)
1606     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawImageLattice", fContext);
1607 
1608     AutoCheckFlush acf(this->drawingManager());
1609 
1610     std::unique_ptr<GrDrawOp> op =
1611             GrLatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(image),
1612                                    std::move(csxf), filter, std::move(iter), dst);
1613     this->addDrawOp(clip, std::move(op));
1614 }
1615 
drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,const SkRect & bounds)1616 void GrRenderTargetContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
1617                                          const SkRect& bounds) {
1618     std::unique_ptr<GrOp> op(GrDrawableOp::Make(fContext, std::move(drawable), bounds));
1619     SkASSERT(op);
1620     this->getRTOpList()->addOp(std::move(op), *this->caps());
1621 }
1622 
prepareForExternalIO(int numSemaphores,GrBackendSemaphore backendSemaphores[])1623 GrSemaphoresSubmitted GrRenderTargetContext::prepareForExternalIO(
1624         int numSemaphores, GrBackendSemaphore backendSemaphores[]) {
1625     ASSERT_SINGLE_OWNER
1626     if (this->drawingManager()->wasAbandoned()) { return GrSemaphoresSubmitted::kNo; }
1627     SkDEBUGCODE(this->validate();)
1628     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "prepareForExternalIO", fContext);
1629 
1630     return this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get(),
1631                                                                numSemaphores,
1632                                                                backendSemaphores);
1633 }
1634 
waitOnSemaphores(int numSemaphores,const GrBackendSemaphore * waitSemaphores)1635 bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
1636                                              const GrBackendSemaphore* waitSemaphores) {
1637     ASSERT_SINGLE_OWNER
1638     RETURN_FALSE_IF_ABANDONED
1639     SkDEBUGCODE(this->validate();)
1640     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "waitOnSemaphores", fContext);
1641 
1642     AutoCheckFlush acf(this->drawingManager());
1643 
1644     if (numSemaphores && !this->caps()->fenceSyncSupport()) {
1645         return false;
1646     }
1647 
1648     auto resourceProvider = fContext->contextPriv().resourceProvider();
1649 
1650     SkTArray<sk_sp<GrSemaphore>> semaphores(numSemaphores);
1651     for (int i = 0; i < numSemaphores; ++i) {
1652         sk_sp<GrSemaphore> sema = resourceProvider->wrapBackendSemaphore(
1653                 waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
1654                 kAdopt_GrWrapOwnership);
1655         std::unique_ptr<GrOp> waitOp(GrSemaphoreOp::MakeWait(fContext, sema,
1656                                                              fRenderTargetProxy.get()));
1657         this->getRTOpList()->addOp(std::move(waitOp), *this->caps());
1658     }
1659     return true;
1660 }
1661 
insertEventMarker(const SkString & str)1662 void GrRenderTargetContext::insertEventMarker(const SkString& str) {
1663     std::unique_ptr<GrOp> op(GrDebugMarkerOp::Make(fContext, fRenderTargetProxy.get(), str));
1664     this->getRTOpList()->addOp(std::move(op), *this->caps());
1665 }
1666 
drawPath(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkPath & path,const GrStyle & style)1667 void GrRenderTargetContext::drawPath(const GrClip& clip,
1668                                      GrPaint&& paint,
1669                                      GrAA aa,
1670                                      const SkMatrix& viewMatrix,
1671                                      const SkPath& path,
1672                                      const GrStyle& style) {
1673     ASSERT_SINGLE_OWNER
1674     RETURN_IF_ABANDONED
1675     SkDEBUGCODE(this->validate();)
1676     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPath", fContext);
1677 
1678     GrShape shape(path, style);
1679 
1680     this->drawShape(clip, std::move(paint), aa, viewMatrix, shape);
1681 }
1682 
drawShape(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const GrShape & shape)1683 void GrRenderTargetContext::drawShape(const GrClip& clip,
1684                                       GrPaint&& paint,
1685                                       GrAA aa,
1686                                       const SkMatrix& viewMatrix,
1687                                       const GrShape& shape) {
1688     ASSERT_SINGLE_OWNER
1689     RETURN_IF_ABANDONED
1690     SkDEBUGCODE(this->validate();)
1691     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawShape", fContext);
1692 
1693     if (shape.isEmpty()) {
1694         if (shape.inverseFilled()) {
1695             this->drawPaint(clip, std::move(paint), viewMatrix);
1696         }
1697         return;
1698     }
1699 
1700     AutoCheckFlush acf(this->drawingManager());
1701 
1702     if (!shape.style().hasPathEffect()) {
1703         GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1704         SkRRect rrect;
1705         // We can ignore the starting point and direction since there is no path effect.
1706         bool inverted;
1707         if (shape.asRRect(&rrect, nullptr, nullptr, &inverted) && !inverted) {
1708             if (rrect.isRect()) {
1709                 this->drawRect(clip, std::move(paint), aa, viewMatrix, rrect.rect(),
1710                                &shape.style());
1711                 return;
1712             } else if (rrect.isOval()) {
1713                 this->drawOval(clip, std::move(paint), aa, viewMatrix, rrect.rect(), shape.style());
1714                 return;
1715             }
1716             this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect, shape.style());
1717             return;
1718         } else if (GrAAType::kCoverage == aaType && shape.style().isSimpleFill() &&
1719                    viewMatrix.rectStaysRect()) {
1720             // TODO: the rectStaysRect restriction could be lifted if we were willing to apply
1721             // the matrix to all the points individually rather than just to the rect
1722             SkRect rects[2];
1723             if (shape.asNestedRects(rects)) {
1724                 // Concave AA paths are expensive - try to avoid them for special cases
1725                 std::unique_ptr<GrDrawOp> op = GrStrokeRectOp::MakeNested(
1726                                 fContext, std::move(paint), viewMatrix, rects);
1727                 if (op) {
1728                     this->addDrawOp(clip, std::move(op));
1729                 }
1730                 // Returning here indicates that there is nothing to draw in this case.
1731                 return;
1732             }
1733         }
1734     }
1735 
1736     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, shape);
1737 }
1738 
drawAndStencilPath(const GrHardClip & clip,const GrUserStencilSettings * ss,SkRegion::Op op,bool invert,GrAA aa,const SkMatrix & viewMatrix,const SkPath & path)1739 bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
1740                                                    const GrUserStencilSettings* ss,
1741                                                    SkRegion::Op op,
1742                                                    bool invert,
1743                                                    GrAA aa,
1744                                                    const SkMatrix& viewMatrix,
1745                                                    const SkPath& path) {
1746     ASSERT_SINGLE_OWNER_PRIV
1747     RETURN_FALSE_IF_ABANDONED_PRIV
1748     SkDEBUGCODE(fRenderTargetContext->validate();)
1749     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilPath",
1750                                    fRenderTargetContext->fContext);
1751 
1752     if (path.isEmpty() && path.isInverseFillType()) {
1753         this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
1754                                  SkRect::MakeIWH(fRenderTargetContext->width(),
1755                                                  fRenderTargetContext->height()));
1756         return true;
1757     }
1758 
1759     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
1760 
1761     // An Assumption here is that path renderer would use some form of tweaking
1762     // the src color (either the input alpha or in the frag shader) to implement
1763     // aa. If we have some future driver-mojo path AA that can do the right
1764     // thing WRT to the blend then we'll need some query on the PR.
1765     GrAAType aaType = fRenderTargetContext->chooseAAType(aa, GrAllowMixedSamples::kNo);
1766     bool hasUserStencilSettings = !ss->isUnused();
1767 
1768     SkIRect clipConservativeBounds;
1769     clip.getConservativeBounds(fRenderTargetContext->width(), fRenderTargetContext->height(),
1770                                &clipConservativeBounds, nullptr);
1771 
1772     GrShape shape(path, GrStyle::SimpleFill());
1773     GrPathRenderer::CanDrawPathArgs canDrawArgs;
1774     canDrawArgs.fCaps = fRenderTargetContext->caps();
1775     canDrawArgs.fViewMatrix = &viewMatrix;
1776     canDrawArgs.fShape = &shape;
1777     canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
1778     canDrawArgs.fAAType = aaType;
1779     SkASSERT(!fRenderTargetContext->wrapsVkSecondaryCB());
1780     canDrawArgs.fTargetIsWrappedVkSecondaryCB = false;
1781     canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
1782 
1783     // Don't allow the SW renderer
1784     GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
1785             canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
1786     if (!pr) {
1787         return false;
1788     }
1789 
1790     GrPaint paint;
1791     paint.setCoverageSetOpXPFactory(op, invert);
1792 
1793     GrPathRenderer::DrawPathArgs args{fRenderTargetContext->drawingManager()->getContext(),
1794                                       std::move(paint),
1795                                       ss,
1796                                       fRenderTargetContext,
1797                                       &clip,
1798                                       &clipConservativeBounds,
1799                                       &viewMatrix,
1800                                       &shape,
1801                                       aaType,
1802                                       fRenderTargetContext->colorSpaceInfo().isLinearlyBlended()};
1803     pr->drawPath(args);
1804     return true;
1805 }
1806 
isBudgeted() const1807 SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
1808     ASSERT_SINGLE_OWNER_PRIV
1809 
1810     if (fRenderTargetContext->wasAbandoned()) {
1811         return SkBudgeted::kNo;
1812     }
1813 
1814     SkDEBUGCODE(fRenderTargetContext->validate();)
1815 
1816     return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
1817 }
1818 
drawShapeUsingPathRenderer(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const GrShape & originalShape)1819 void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
1820                                                        GrPaint&& paint,
1821                                                        GrAA aa,
1822                                                        const SkMatrix& viewMatrix,
1823                                                        const GrShape& originalShape) {
1824     ASSERT_SINGLE_OWNER
1825     RETURN_IF_ABANDONED
1826     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "internalDrawPath", fContext);
1827 
1828     if (!viewMatrix.isFinite() || !originalShape.bounds().isFinite()) {
1829         return;
1830     }
1831 
1832     SkIRect clipConservativeBounds;
1833     clip.getConservativeBounds(this->width(), this->height(), &clipConservativeBounds, nullptr);
1834 
1835     GrShape tempShape;
1836     // NVPR cannot handle hairlines, so this would get picked up by a different stencil and
1837     // cover path renderer (i.e. default path renderer). The hairline renderer produces much
1838     // smoother hairlines than MSAA.
1839     GrAllowMixedSamples allowMixedSamples = originalShape.style().isSimpleHairline()
1840                                                     ? GrAllowMixedSamples::kNo
1841                                                     : GrAllowMixedSamples::kYes;
1842     GrAAType aaType = this->chooseAAType(aa, allowMixedSamples);
1843     GrPathRenderer::CanDrawPathArgs canDrawArgs;
1844     canDrawArgs.fCaps = this->caps();
1845     canDrawArgs.fViewMatrix = &viewMatrix;
1846     canDrawArgs.fShape = &originalShape;
1847     canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
1848     canDrawArgs.fTargetIsWrappedVkSecondaryCB = this->wrapsVkSecondaryCB();
1849     canDrawArgs.fHasUserStencilSettings = false;
1850 
1851     GrPathRenderer* pr;
1852     static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
1853     if (originalShape.isEmpty() && !originalShape.inverseFilled()) {
1854         return;
1855     }
1856 
1857     canDrawArgs.fAAType = aaType;
1858 
1859     // Try a 1st time without applying any of the style to the geometry (and barring sw)
1860     pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
1861     SkScalar styleScale =  GrStyle::MatrixToScaleFactor(viewMatrix);
1862 
1863     if (!pr && originalShape.style().pathEffect()) {
1864         // It didn't work above, so try again with the path effect applied.
1865         tempShape = originalShape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1866         if (tempShape.isEmpty()) {
1867             return;
1868         }
1869         canDrawArgs.fShape = &tempShape;
1870         pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
1871     }
1872     if (!pr) {
1873         if (canDrawArgs.fShape->style().applies()) {
1874             tempShape = canDrawArgs.fShape->applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec,
1875                                                        styleScale);
1876             if (tempShape.isEmpty()) {
1877                 return;
1878             }
1879             canDrawArgs.fShape = &tempShape;
1880             // This time, allow SW renderer
1881             pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
1882         } else {
1883             pr = this->drawingManager()->getSoftwarePathRenderer();
1884         }
1885     }
1886 
1887     if (!pr) {
1888 #ifdef SK_DEBUG
1889         SkDebugf("Unable to find path renderer compatible with path.\n");
1890 #endif
1891         return;
1892     }
1893 
1894     GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
1895                                       std::move(paint),
1896                                       &GrUserStencilSettings::kUnused,
1897                                       this,
1898                                       &clip,
1899                                       &clipConservativeBounds,
1900                                       &viewMatrix,
1901                                       canDrawArgs.fShape,
1902                                       aaType,
1903                                       this->colorSpaceInfo().isLinearlyBlended()};
1904     pr->drawPath(args);
1905 }
1906 
op_bounds(SkRect * bounds,const GrOp * op)1907 static void op_bounds(SkRect* bounds, const GrOp* op) {
1908     *bounds = op->bounds();
1909     if (op->hasZeroArea()) {
1910         if (op->hasAABloat()) {
1911             bounds->outset(0.5f, 0.5f);
1912         } else {
1913             // We don't know which way the particular GPU will snap lines or points at integer
1914             // coords. So we ensure that the bounds is large enough for either snap.
1915             SkRect before = *bounds;
1916             bounds->roundOut(bounds);
1917             if (bounds->fLeft == before.fLeft) {
1918                 bounds->fLeft -= 1;
1919             }
1920             if (bounds->fTop == before.fTop) {
1921                 bounds->fTop -= 1;
1922             }
1923             if (bounds->fRight == before.fRight) {
1924                 bounds->fRight += 1;
1925             }
1926             if (bounds->fBottom == before.fBottom) {
1927                 bounds->fBottom += 1;
1928             }
1929         }
1930     }
1931 }
1932 
addDrawOp(const GrClip & clip,std::unique_ptr<GrDrawOp> op,const std::function<WillAddOpFn> & willAddFn)1933 void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op,
1934                                       const std::function<WillAddOpFn>& willAddFn) {
1935     ASSERT_SINGLE_OWNER
1936     if (this->drawingManager()->wasAbandoned()) {
1937         fContext->contextPriv().opMemoryPool()->release(std::move(op));
1938         return;
1939     }
1940     SkDEBUGCODE(this->validate();)
1941     SkDEBUGCODE(op->fAddDrawOpCalled = true;)
1942     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "addDrawOp", fContext);
1943 
1944     // Setup clip
1945     SkRect bounds;
1946     op_bounds(&bounds, op.get());
1947     GrAppliedClip appliedClip;
1948     GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
1949     if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
1950                     fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
1951                     &bounds)) {
1952         fContext->contextPriv().opMemoryPool()->release(std::move(op));
1953         return;
1954     }
1955 
1956     if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
1957         appliedClip.hasStencilClip()) {
1958         if (this->caps()->performStencilClearsAsDraws()) {
1959             // Must use an op to perform the clear of the stencil buffer before this op, but only
1960             // have to clear the first time any draw needs it (this also ensures we don't loop
1961             // forever when the internal stencil clear adds a draw op that has stencil settings).
1962             if (!fRenderTargetProxy->needsStencil()) {
1963                 // Send false so that the stencil buffer is fully cleared to 0
1964                 this->internalStencilClear(GrFixedClip::Disabled(), /* inside mask */ false);
1965             }
1966         } else {
1967             // Just make sure the stencil buffer is cleared before the draw op, easy to do it as
1968             // a load at the start
1969             this->getRTOpList()->setStencilLoadOp(GrLoadOp::kClear);
1970         }
1971 
1972         this->setNeedsStencil();
1973     }
1974 
1975     GrXferProcessor::DstProxy dstProxy;
1976     GrProcessorSet::Analysis analysis = op->finalize(*this->caps(), &appliedClip);
1977     if (analysis.requiresDstTexture()) {
1978         if (!this->setupDstProxy(this->asRenderTargetProxy(), clip, *op, &dstProxy)) {
1979             fContext->contextPriv().opMemoryPool()->release(std::move(op));
1980             return;
1981         }
1982     }
1983 
1984     op->setClippedBounds(bounds);
1985     auto opList = this->getRTOpList();
1986     if (willAddFn) {
1987         willAddFn(op.get(), opList->uniqueID());
1988     }
1989     opList->addDrawOp(std::move(op), analysis, std::move(appliedClip), dstProxy, *this->caps());
1990 }
1991 
setupDstProxy(GrRenderTargetProxy * rtProxy,const GrClip & clip,const GrOp & op,GrXferProcessor::DstProxy * dstProxy)1992 bool GrRenderTargetContext::setupDstProxy(GrRenderTargetProxy* rtProxy, const GrClip& clip,
1993                                           const GrOp& op,
1994                                           GrXferProcessor::DstProxy* dstProxy) {
1995     // If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we
1996     // don't actually have a VkImage to make a copy of. Additionally we don't have the power to
1997     // start and stop the render pass in order to make the copy.
1998     if (rtProxy->wrapsVkSecondaryCB()) {
1999         return false;
2000     }
2001 
2002     if (this->caps()->textureBarrierSupport()) {
2003         if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
2004             // The render target is a texture, so we can read from it directly in the shader. The XP
2005             // will be responsible to detect this situation and request a texture barrier.
2006             dstProxy->setProxy(sk_ref_sp(texProxy));
2007             dstProxy->setOffset(0, 0);
2008             return true;
2009         }
2010     }
2011 
2012     SkIRect copyRect = SkIRect::MakeWH(rtProxy->width(), rtProxy->height());
2013 
2014     SkIRect clippedRect;
2015     clip.getConservativeBounds(rtProxy->width(), rtProxy->height(), &clippedRect);
2016     SkRect opBounds = op.bounds();
2017     // If the op has aa bloating or is a infinitely thin geometry (hairline) outset the bounds by
2018     // 0.5 pixels.
2019     if (op.hasAABloat() || op.hasZeroArea()) {
2020         opBounds.outset(0.5f, 0.5f);
2021         // An antialiased/hairline draw can sometimes bleed outside of the clips bounds. For
2022         // performance we may ignore the clip when the draw is entirely inside the clip is float
2023         // space but will hit pixels just outside the clip when actually rasterizing.
2024         clippedRect.outset(1, 1);
2025         clippedRect.intersect(SkIRect::MakeWH(rtProxy->width(), rtProxy->height()));
2026     }
2027     SkIRect opIBounds;
2028     opBounds.roundOut(&opIBounds);
2029     if (!clippedRect.intersect(opIBounds)) {
2030 #ifdef SK_DEBUG
2031         GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
2032 #endif
2033         return false;
2034     }
2035 
2036     // MSAA consideration: When there is support for reading MSAA samples in the shader we could
2037     // have per-sample dst values by making the copy multisampled.
2038     GrSurfaceDesc desc;
2039     bool rectsMustMatch = false;
2040     bool disallowSubrect = false;
2041     GrSurfaceOrigin origin;
2042     if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &origin, &rectsMustMatch,
2043                                           &disallowSubrect)) {
2044         desc.fFlags = kRenderTarget_GrSurfaceFlag;
2045         desc.fConfig = rtProxy->config();
2046         origin = rtProxy->origin();
2047     }
2048 
2049     if (!disallowSubrect) {
2050         copyRect = clippedRect;
2051     }
2052 
2053     SkIPoint dstPoint, dstOffset;
2054     SkBackingFit fit;
2055     if (rectsMustMatch) {
2056         desc.fWidth = rtProxy->width();
2057         desc.fHeight = rtProxy->height();
2058         dstPoint = {copyRect.fLeft, copyRect.fTop};
2059         dstOffset = {0, 0};
2060         fit = SkBackingFit::kExact;
2061     } else {
2062         desc.fWidth = copyRect.width();
2063         desc.fHeight = copyRect.height();
2064         dstPoint = {0, 0};
2065         dstOffset = {copyRect.fLeft, copyRect.fTop};
2066         fit = SkBackingFit::kApprox;
2067     }
2068 
2069     SkASSERT(rtProxy->backendFormat().textureType() == GrTextureType::k2D);
2070     const GrBackendFormat& format = rtProxy->backendFormat();
2071     sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeDeferredSurfaceContext(
2072             format, desc, origin, GrMipMapped::kNo, fit, SkBudgeted::kYes,
2073             sk_ref_sp(this->colorSpaceInfo().colorSpace()));
2074     if (!sContext) {
2075         SkDebugf("setupDstTexture: surfaceContext creation failed.\n");
2076         return false;
2077     }
2078 
2079     if (!sContext->copy(rtProxy, copyRect, dstPoint)) {
2080         SkDebugf("setupDstTexture: copy failed.\n");
2081         return false;
2082     }
2083 
2084     dstProxy->setProxy(sContext->asTextureProxyRef());
2085     dstProxy->setOffset(dstOffset);
2086     return true;
2087 }
2088