• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrStencilAttachment.h"
26 #include "GrTracing.h"
27 #include "SkDrawShadowInfo.h"
28 #include "SkGr.h"
29 #include "SkLatticeIter.h"
30 #include "SkMatrixPriv.h"
31 #include "SkShadowUtils.h"
32 #include "SkSurfacePriv.h"
33 #include "effects/GrRRectEffect.h"
34 #include "ops/GrAtlasTextOp.h"
35 #include "ops/GrClearOp.h"
36 #include "ops/GrClearStencilClipOp.h"
37 #include "ops/GrDebugMarkerOp.h"
38 #include "ops/GrDrawAtlasOp.h"
39 #include "ops/GrDrawOp.h"
40 #include "ops/GrDrawVerticesOp.h"
41 #include "ops/GrLatticeOp.h"
42 #include "ops/GrOp.h"
43 #include "ops/GrOvalOpFactory.h"
44 #include "ops/GrRectOpFactory.h"
45 #include "ops/GrRegionOp.h"
46 #include "ops/GrSemaphoreOp.h"
47 #include "ops/GrShadowRRectOp.h"
48 #include "ops/GrStencilPathOp.h"
49 #include "ops/GrTextureOp.h"
50 #include "text/GrAtlasTextContext.h"
51 #include "text/GrStencilAndCoverTextContext.h"
52 #include "text/GrTextUtils.h"
53 
54 class GrRenderTargetContext::TextTarget : public GrTextUtils::Target {
55 public:
TextTarget(GrRenderTargetContext * renderTargetContext)56     TextTarget(GrRenderTargetContext* renderTargetContext)
57             : Target(renderTargetContext->width(), renderTargetContext->height(),
58                      renderTargetContext->colorSpaceInfo())
59             , fRenderTargetContext(renderTargetContext) {}
60 
addDrawOp(const GrClip & clip,std::unique_ptr<GrAtlasTextOp> op)61     void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) {
62         fRenderTargetContext->addDrawOp(clip, std::move(op));
63     }
64 
drawPath(const GrClip & clip,const SkPath & path,const SkPaint & paint,const SkMatrix & viewMatrix,const SkMatrix * pathMatrix,const SkIRect & clipBounds)65     void drawPath(const GrClip& clip, const SkPath& path, const SkPaint& paint,
66                   const SkMatrix& viewMatrix, const SkMatrix* pathMatrix,
67                   const SkIRect& clipBounds) {
68         GrBlurUtils::drawPathWithMaskFilter(fRenderTargetContext->fContext, fRenderTargetContext,
69                                             clip, path, paint, viewMatrix, pathMatrix, clipBounds,
70                                             false);
71     }
72 
makeGrPaint(GrMaskFormat maskFormat,const SkPaint & skPaint,const SkMatrix & viewMatrix,GrPaint * grPaint)73     void makeGrPaint(GrMaskFormat maskFormat, const SkPaint& skPaint, const SkMatrix& viewMatrix,
74                      GrPaint* grPaint) {
75         GrContext* context = fRenderTargetContext->fContext;
76         const GrColorSpaceInfo& colorSpaceInfo = fRenderTargetContext->colorSpaceInfo();
77         if (kARGB_GrMaskFormat == maskFormat) {
78             SkPaintToGrPaintWithPrimitiveColor(context, colorSpaceInfo, skPaint, grPaint);
79         } else {
80             SkPaintToGrPaint(context, colorSpaceInfo, skPaint, viewMatrix, grPaint);
81         }
82     }
83 
84 private:
85     GrRenderTargetContext* fRenderTargetContext;
86 };
87 
88 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
89 #define ASSERT_SINGLE_OWNER \
90     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
91 #define ASSERT_SINGLE_OWNER_PRIV \
92     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
93 #define RETURN_IF_ABANDONED        if (this->drawingManager()->wasAbandoned()) { return; }
94 #define RETURN_IF_ABANDONED_PRIV   if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return; }
95 #define RETURN_FALSE_IF_ABANDONED  if (this->drawingManager()->wasAbandoned()) { return false; }
96 #define RETURN_FALSE_IF_ABANDONED_PRIV  if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return false; }
97 #define RETURN_NULL_IF_ABANDONED   if (this->drawingManager()->wasAbandoned()) { return nullptr; }
98 
99 //////////////////////////////////////////////////////////////////////////////
100 
GrChooseAAType(GrAA aa,GrFSAAType fsaaType,GrAllowMixedSamples allowMixedSamples,const GrCaps & caps)101 GrAAType GrChooseAAType(GrAA aa, GrFSAAType fsaaType, GrAllowMixedSamples allowMixedSamples,
102                         const GrCaps& caps) {
103     if (GrAA::kNo == aa) {
104         // On some devices we cannot disable MSAA if it is enabled so we make the AA type reflect
105         // that.
106         if (fsaaType == GrFSAAType::kUnifiedMSAA && !caps.multisampleDisableSupport()) {
107             return GrAAType::kMSAA;
108         }
109         return GrAAType::kNone;
110     }
111     switch (fsaaType) {
112         case GrFSAAType::kNone:
113             return GrAAType::kCoverage;
114         case GrFSAAType::kUnifiedMSAA:
115             return GrAAType::kMSAA;
116         case GrFSAAType::kMixedSamples:
117             return GrAllowMixedSamples::kYes == allowMixedSamples ? GrAAType::kMixedSamples
118                                                                   : GrAAType::kCoverage;
119     }
120     SK_ABORT("Unexpected fsaa type");
121     return GrAAType::kNone;
122 }
123 
124 //////////////////////////////////////////////////////////////////////////////
125 
126 class AutoCheckFlush {
127 public:
AutoCheckFlush(GrDrawingManager * drawingManager)128     AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
129         SkASSERT(fDrawingManager);
130     }
~AutoCheckFlush()131     ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
132 
133 private:
134     GrDrawingManager* fDrawingManager;
135 };
136 
wasAbandoned() const137 bool GrRenderTargetContext::wasAbandoned() const {
138     return this->drawingManager()->wasAbandoned();
139 }
140 
141 // In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
142 // GrOpLists to be picked up and added to by renderTargetContexts lower in the call
143 // stack. When this occurs with a closed GrOpList, a new one will be allocated
144 // 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)145 GrRenderTargetContext::GrRenderTargetContext(GrContext* context,
146                                              GrDrawingManager* drawingMgr,
147                                              sk_sp<GrRenderTargetProxy> rtp,
148                                              sk_sp<SkColorSpace> colorSpace,
149                                              const SkSurfaceProps* surfaceProps,
150                                              GrAuditTrail* auditTrail,
151                                              GrSingleOwner* singleOwner,
152                                              bool managedOpList)
153         : GrSurfaceContext(context, drawingMgr, rtp->config(), std::move(colorSpace), auditTrail,
154                            singleOwner)
155         , fRenderTargetProxy(std::move(rtp))
156         , fOpList(sk_ref_sp(fRenderTargetProxy->getLastRenderTargetOpList()))
157         , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
158         , fManagedOpList(managedOpList) {
159 #ifdef SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION
160     // MDB TODO: to ensure all resources still get allocated in the correct order in the hybrid
161     // world we need to get the correct opList here so that it, in turn, can grab and hold
162     // its rendertarget.
163     this->getRTOpList();
164 #endif
165     fTextTarget.reset(new TextTarget(this));
166     SkDEBUGCODE(this->validate();)
167 }
168 
169 #ifdef SK_DEBUG
validate() const170 void GrRenderTargetContext::validate() const {
171     SkASSERT(fRenderTargetProxy);
172     fRenderTargetProxy->validate(fContext);
173 
174     if (fOpList && !fOpList->isClosed()) {
175         SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList.get());
176     }
177 }
178 #endif
179 
~GrRenderTargetContext()180 GrRenderTargetContext::~GrRenderTargetContext() {
181     ASSERT_SINGLE_OWNER
182 }
183 
asTextureProxy()184 GrTextureProxy* GrRenderTargetContext::asTextureProxy() {
185     return fRenderTargetProxy->asTextureProxy();
186 }
187 
asTextureProxy() const188 const GrTextureProxy* GrRenderTargetContext::asTextureProxy() const {
189     return fRenderTargetProxy->asTextureProxy();
190 }
191 
asTextureProxyRef()192 sk_sp<GrTextureProxy> GrRenderTargetContext::asTextureProxyRef() {
193     return sk_ref_sp(fRenderTargetProxy->asTextureProxy());
194 }
195 
mipMapped() const196 GrMipMapped GrRenderTargetContext::mipMapped() const {
197     if (const GrTextureProxy* proxy = this->asTextureProxy()) {
198         return proxy->mipMapped();
199     }
200     return GrMipMapped::kNo;
201 }
202 
getRTOpList()203 GrRenderTargetOpList* GrRenderTargetContext::getRTOpList() {
204     ASSERT_SINGLE_OWNER
205     SkDEBUGCODE(this->validate();)
206 
207     if (!fOpList || fOpList->isClosed()) {
208         fOpList = this->drawingManager()->newRTOpList(fRenderTargetProxy.get(), fManagedOpList);
209     }
210 
211     return fOpList.get();
212 }
213 
getOpList()214 GrOpList* GrRenderTargetContext::getOpList() {
215     return this->getRTOpList();
216 }
217 
drawText(const GrClip & clip,const SkPaint & skPaint,const SkMatrix & viewMatrix,const char text[],size_t byteLength,SkScalar x,SkScalar y,const SkIRect & clipBounds)218 void GrRenderTargetContext::drawText(const GrClip& clip, const SkPaint& skPaint,
219                                      const SkMatrix& viewMatrix, const char text[],
220                                      size_t byteLength, SkScalar x, SkScalar y,
221                                      const SkIRect& clipBounds) {
222     ASSERT_SINGLE_OWNER
223     RETURN_IF_ABANDONED
224     SkDEBUGCODE(this->validate();)
225     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawText", fContext);
226 
227     GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
228     atlasTextContext->drawText(fContext, fTextTarget.get(), clip, skPaint, viewMatrix,
229                                fSurfaceProps, text, byteLength, x, y, clipBounds);
230 }
231 
drawPosText(const GrClip & clip,const SkPaint & paint,const SkMatrix & viewMatrix,const char text[],size_t byteLength,const SkScalar pos[],int scalarsPerPosition,const SkPoint & offset,const SkIRect & clipBounds)232 void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint,
233                                         const SkMatrix& viewMatrix, const char text[],
234                                         size_t byteLength, const SkScalar pos[],
235                                         int scalarsPerPosition, const SkPoint& offset,
236                                         const SkIRect& clipBounds) {
237     ASSERT_SINGLE_OWNER
238     RETURN_IF_ABANDONED
239     SkDEBUGCODE(this->validate();)
240     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPosText", fContext);
241 
242     GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
243     atlasTextContext->drawPosText(fContext, fTextTarget.get(), clip, paint, viewMatrix,
244                                   fSurfaceProps, text, byteLength, pos, scalarsPerPosition, offset,
245                                   clipBounds);
246 }
247 
drawTextBlob(const GrClip & clip,const SkPaint & paint,const SkMatrix & viewMatrix,const SkTextBlob * blob,SkScalar x,SkScalar y,SkDrawFilter * filter,const SkIRect & clipBounds)248 void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& paint,
249                                          const SkMatrix& viewMatrix, const SkTextBlob* blob,
250                                          SkScalar x, SkScalar y, SkDrawFilter* filter,
251                                          const SkIRect& clipBounds) {
252     ASSERT_SINGLE_OWNER
253     RETURN_IF_ABANDONED
254     SkDEBUGCODE(this->validate();)
255     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextBlob", fContext);
256 
257     GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
258     atlasTextContext->drawTextBlob(fContext, fTextTarget.get(), clip, paint, viewMatrix,
259                                    fSurfaceProps, blob, x, y, filter, clipBounds);
260 }
261 
discard()262 void GrRenderTargetContext::discard() {
263     ASSERT_SINGLE_OWNER
264     RETURN_IF_ABANDONED
265     SkDEBUGCODE(this->validate();)
266     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "discard", fContext);
267 
268     AutoCheckFlush acf(this->drawingManager());
269 
270     this->getRTOpList()->discard();
271 }
272 
clear(const SkIRect * rect,const GrColor color,CanClearFullscreen canClearFullscreen)273 void GrRenderTargetContext::clear(const SkIRect* rect,
274                                   const GrColor color,
275                                   CanClearFullscreen canClearFullscreen) {
276     ASSERT_SINGLE_OWNER
277     RETURN_IF_ABANDONED
278     SkDEBUGCODE(this->validate();)
279     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "clear", fContext);
280 
281     AutoCheckFlush acf(this->drawingManager());
282     this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color,
283                         canClearFullscreen);
284 }
285 
absClear(const SkIRect * clearRect,const GrColor color)286 void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const GrColor color) {
287     ASSERT_SINGLE_OWNER_PRIV
288     RETURN_IF_ABANDONED_PRIV
289     SkDEBUGCODE(fRenderTargetContext->validate();)
290     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "absClear",
291                                    fRenderTargetContext->fContext);
292 
293     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
294 
295     SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(),
296                                      fRenderTargetContext->fRenderTargetProxy->worstCaseHeight());
297 
298     if (clearRect) {
299         if (clearRect->contains(rtRect)) {
300             clearRect = nullptr; // full screen
301         } else {
302             if (!rtRect.intersect(*clearRect)) {
303                 return;
304             }
305         }
306     }
307 
308     // TODO: in a post-MDB world this should be handled at the OpList level.
309     // An op-list that is initially cleared and has no other ops should receive an
310     // extra draw.
311     // This path doesn't handle coalescing of full screen clears b.c. it
312     // has to clear the entire render target - not just the content area.
313     // It could be done but will take more finagling.
314     std::unique_ptr<GrOp> op(GrClearOp::Make(rtRect, color, !clearRect));
315     if (!op) {
316         return;
317     }
318     fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
319 }
320 
clear(const GrFixedClip & clip,const GrColor color,CanClearFullscreen canClearFullscreen)321 void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
322                                       const GrColor color,
323                                       CanClearFullscreen canClearFullscreen) {
324     ASSERT_SINGLE_OWNER_PRIV
325     RETURN_IF_ABANDONED_PRIV
326     SkDEBUGCODE(fRenderTargetContext->validate();)
327     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clear",
328                                    fRenderTargetContext->fContext);
329 
330     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
331     fRenderTargetContext->internalClear(clip, color, canClearFullscreen);
332 }
333 
internalClear(const GrFixedClip & clip,const GrColor color,CanClearFullscreen canClearFullscreen)334 void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
335                                           const GrColor color,
336                                           CanClearFullscreen canClearFullscreen) {
337     bool isFull = false;
338     if (!clip.hasWindowRectangles()) {
339         isFull = !clip.scissorEnabled() ||
340                  (CanClearFullscreen::kYes == canClearFullscreen &&
341                   fContext->caps()->preferFullscreenClears()) ||
342                  clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
343     }
344 
345     if (isFull) {
346         this->getRTOpList()->fullClear(*this->caps(), color);
347     } else {
348         std::unique_ptr<GrOp> op(GrClearOp::Make(clip, color, this->asSurfaceProxy()));
349         if (!op) {
350             return;
351         }
352         this->getRTOpList()->addOp(std::move(op), *this->caps());
353     }
354 }
355 
drawPaint(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix)356 void GrRenderTargetContext::drawPaint(const GrClip& clip,
357                                       GrPaint&& paint,
358                                       const SkMatrix& viewMatrix) {
359     ASSERT_SINGLE_OWNER
360     RETURN_IF_ABANDONED
361     SkDEBUGCODE(this->validate();)
362     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPaint", fContext);
363 
364     // set rect to be big enough to fill the space, but not super-huge, so we
365     // don't overflow fixed-point implementations
366 
367     SkRect r = fRenderTargetProxy->getBoundsRect();
368 
369     SkRRect rrect;
370     GrAA aa;
371     // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the
372     // transformation for non-rect rrects. Rects caused a performance regression on an Android
373     // test that needs investigation. We also skip cases where there are fragment processors
374     // because they may depend on having correct local coords and this path draws in device space
375     // without a local matrix.
376     if (!paint.numTotalFragmentProcessors() && clip.isRRect(r, &rrect, &aa) && !rrect.isRect()) {
377         this->drawRRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect,
378                         GrStyle::SimpleFill());
379         return;
380     }
381 
382 
383     bool isPerspective = viewMatrix.hasPerspective();
384 
385     // We attempt to map r by the inverse matrix and draw that. mapRect will
386     // map the four corners and bound them with a new rect. This will not
387     // produce a correct result for some perspective matrices.
388     if (!isPerspective) {
389         if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
390             SkDebugf("Could not invert matrix\n");
391             return;
392         }
393         this->drawRect(clip, std::move(paint), GrAA::kNo, viewMatrix, r);
394     } else {
395         SkMatrix localMatrix;
396         if (!viewMatrix.invert(&localMatrix)) {
397             SkDebugf("Could not invert matrix\n");
398             return;
399         }
400 
401         AutoCheckFlush acf(this->drawingManager());
402 
403         std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
404                 std::move(paint), SkMatrix::I(), localMatrix, r, GrAAType::kNone);
405         this->addDrawOp(clip, std::move(op));
406     }
407 }
408 
rect_contains_inclusive(const SkRect & rect,const SkPoint & point)409 static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
410     return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
411            point.fY >= rect.fTop && point.fY <= rect.fBottom;
412 }
413 
414 // Attempts to crop a rect and optional local rect to the clip boundaries.
415 // 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)416 static bool crop_filled_rect(int width, int height, const GrClip& clip,
417                              const SkMatrix& viewMatrix, SkRect* rect,
418                              SkRect* localRect = nullptr) {
419     if (!viewMatrix.rectStaysRect()) {
420         return true;
421     }
422 
423     SkIRect clipDevBounds;
424     SkRect clipBounds;
425 
426     clip.getConservativeBounds(width, height, &clipDevBounds);
427     if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
428         return false;
429     }
430 
431     if (localRect) {
432         if (!rect->intersects(clipBounds)) {
433             return false;
434         }
435         const SkScalar dx = localRect->width() / rect->width();
436         const SkScalar dy = localRect->height() / rect->height();
437         if (clipBounds.fLeft > rect->fLeft) {
438             localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
439             rect->fLeft = clipBounds.fLeft;
440         }
441         if (clipBounds.fTop > rect->fTop) {
442             localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
443             rect->fTop = clipBounds.fTop;
444         }
445         if (clipBounds.fRight < rect->fRight) {
446             localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
447             rect->fRight = clipBounds.fRight;
448         }
449         if (clipBounds.fBottom < rect->fBottom) {
450             localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
451             rect->fBottom = clipBounds.fBottom;
452         }
453         return true;
454     }
455 
456     return rect->intersect(clipBounds);
457 }
458 
drawFilledRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rect,const GrUserStencilSettings * ss)459 bool GrRenderTargetContext::drawFilledRect(const GrClip& clip,
460                                            GrPaint&& paint,
461                                            GrAA aa,
462                                            const SkMatrix& viewMatrix,
463                                            const SkRect& rect,
464                                            const GrUserStencilSettings* ss) {
465     SkRect croppedRect = rect;
466     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
467         return true;
468     }
469 
470     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
471     std::unique_ptr<GrDrawOp> op;
472     if (GrAAType::kCoverage == aaType) {
473         op = GrRectOpFactory::MakeAAFill(std::move(paint), viewMatrix, croppedRect, ss);
474     } else {
475         op = GrRectOpFactory::MakeNonAAFill(std::move(paint), viewMatrix, croppedRect, aaType, ss);
476     }
477     if (!op) {
478         return false;
479     }
480     this->addDrawOp(clip, std::move(op));
481     return true;
482 }
483 
drawRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rect,const GrStyle * style)484 void GrRenderTargetContext::drawRect(const GrClip& clip,
485                                      GrPaint&& paint,
486                                      GrAA aa,
487                                      const SkMatrix& viewMatrix,
488                                      const SkRect& rect,
489                                      const GrStyle* style) {
490     if (!style) {
491         style = &GrStyle::SimpleFill();
492     }
493     ASSERT_SINGLE_OWNER
494     RETURN_IF_ABANDONED
495     SkDEBUGCODE(this->validate();)
496     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRect", fContext);
497 
498     // Path effects should've been devolved to a path in SkGpuDevice
499     SkASSERT(!style->pathEffect());
500 
501     AutoCheckFlush acf(this->drawingManager());
502 
503     const SkStrokeRec& stroke = style->strokeRec();
504     if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
505         // Check if this is a full RT draw and can be replaced with a clear. We don't bother
506         // checking cases where the RT is fully inside a stroke.
507         SkRect rtRect = fRenderTargetProxy->getBoundsRect();
508         // Does the clip contain the entire RT?
509         if (clip.quickContains(rtRect)) {
510             SkMatrix invM;
511             if (!viewMatrix.invert(&invM)) {
512                 return;
513             }
514             // Does the rect bound the RT?
515             GrQuad quad;
516             quad.setFromMappedRect(rtRect, invM);
517             if (rect_contains_inclusive(rect, quad.point(0)) &&
518                 rect_contains_inclusive(rect, quad.point(1)) &&
519                 rect_contains_inclusive(rect, quad.point(2)) &&
520                 rect_contains_inclusive(rect, quad.point(3))) {
521                 // Will it blend?
522                 GrColor clearColor;
523                 if (paint.isConstantBlendedColor(&clearColor)) {
524                     this->clear(nullptr, clearColor,
525                                 GrRenderTargetContext::CanClearFullscreen::kYes);
526                     return;
527                 }
528             }
529         }
530 
531         if (this->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, nullptr)) {
532             return;
533         }
534     } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
535                stroke.getStyle() == SkStrokeRec::kHairline_Style) {
536         if ((!rect.width() || !rect.height()) &&
537             SkStrokeRec::kHairline_Style != stroke.getStyle()) {
538             SkScalar r = stroke.getWidth() / 2;
539             // TODO: Move these stroke->fill fallbacks to GrShape?
540             switch (stroke.getJoin()) {
541                 case SkPaint::kMiter_Join:
542                     this->drawRect(
543                             clip, std::move(paint), aa, viewMatrix,
544                             {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
545                             &GrStyle::SimpleFill());
546                     return;
547                 case SkPaint::kRound_Join:
548                     // Raster draws nothing when both dimensions are empty.
549                     if (rect.width() || rect.height()){
550                         SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
551                         this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
552                                         GrStyle::SimpleFill());
553                         return;
554                     }
555                 case SkPaint::kBevel_Join:
556                     if (!rect.width()) {
557                         this->drawRect(clip, std::move(paint), aa, viewMatrix,
558                                        {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
559                                        &GrStyle::SimpleFill());
560                     } else {
561                         this->drawRect(clip, std::move(paint), aa, viewMatrix,
562                                        {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
563                                        &GrStyle::SimpleFill());
564                     }
565                     return;
566                 }
567         }
568 
569         std::unique_ptr<GrDrawOp> op;
570 
571         GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
572         if (GrAAType::kCoverage == aaType) {
573             // The stroke path needs the rect to remain axis aligned (no rotation or skew).
574             if (viewMatrix.rectStaysRect()) {
575                 op = GrRectOpFactory::MakeAAStroke(std::move(paint), viewMatrix, rect, stroke);
576             }
577         } else {
578             op = GrRectOpFactory::MakeNonAAStroke(std::move(paint), viewMatrix, rect, stroke,
579                                                   aaType);
580         }
581 
582         if (op) {
583             this->addDrawOp(clip, std::move(op));
584             return;
585         }
586     }
587     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(rect, *style));
588 }
589 
maxWindowRectangles() const590 int GrRenderTargetContextPriv::maxWindowRectangles() const {
591     return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
592                                                     *fRenderTargetContext->fContext->caps());
593 }
594 
clearStencilClip(const GrFixedClip & clip,bool insideStencilMask)595 void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
596     ASSERT_SINGLE_OWNER_PRIV
597     RETURN_IF_ABANDONED_PRIV
598     SkDEBUGCODE(fRenderTargetContext->validate();)
599     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clearStencilClip",
600                                    fRenderTargetContext->fContext);
601 
602     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
603 
604     std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(
605                                                  clip, insideStencilMask,
606                                                  fRenderTargetContext->fRenderTargetProxy.get()));
607     if (!op) {
608         return;
609     }
610     fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
611 }
612 
stencilPath(const GrHardClip & clip,GrAAType aaType,const SkMatrix & viewMatrix,const GrPath * path)613 void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip,
614                                             GrAAType aaType,
615                                             const SkMatrix& viewMatrix,
616                                             const GrPath* path) {
617     ASSERT_SINGLE_OWNER_PRIV
618     RETURN_IF_ABANDONED_PRIV
619     SkDEBUGCODE(fRenderTargetContext->validate();)
620     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilPath",
621                                    fRenderTargetContext->fContext);
622 
623     SkASSERT(aaType != GrAAType::kCoverage);
624 
625     bool useHWAA = GrAATypeIsHW(aaType);
626     // TODO: extract portions of checkDraw that are relevant to path stenciling.
627     SkASSERT(path);
628     SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
629 
630     // FIXME: Use path bounds instead of this WAR once
631     // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
632     SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
633 
634     // Setup clip
635     GrAppliedHardClip appliedClip;
636     if (!clip.apply(fRenderTargetContext->width(), fRenderTargetContext->height(), &appliedClip,
637                     &bounds)) {
638         return;
639     }
640 
641     fRenderTargetContext->setNeedsStencil();
642 
643     std::unique_ptr<GrOp> op = GrStencilPathOp::Make(viewMatrix,
644                                                      useHWAA,
645                                                      path->getFillType(),
646                                                      appliedClip.hasStencilClip(),
647                                                      appliedClip.scissorState(),
648                                                      path);
649     if (!op) {
650         return;
651     }
652     op->setClippedBounds(bounds);
653     fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
654 }
655 
stencilRect(const GrHardClip & clip,const GrUserStencilSettings * ss,GrAAType aaType,const SkMatrix & viewMatrix,const SkRect & rect)656 void GrRenderTargetContextPriv::stencilRect(const GrHardClip& clip,
657                                             const GrUserStencilSettings* ss,
658                                             GrAAType aaType,
659                                             const SkMatrix& viewMatrix,
660                                             const SkRect& rect) {
661     ASSERT_SINGLE_OWNER_PRIV
662     RETURN_IF_ABANDONED_PRIV
663     SkDEBUGCODE(fRenderTargetContext->validate();)
664     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilRect",
665                                    fRenderTargetContext->fContext);
666 
667     SkASSERT(GrAAType::kCoverage != aaType);
668     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
669 
670     GrPaint paint;
671     paint.setXPFactory(GrDisableColorXPFactory::Get());
672     std::unique_ptr<GrDrawOp> op =
673             GrRectOpFactory::MakeNonAAFill(std::move(paint), viewMatrix, rect, aaType, ss);
674     fRenderTargetContext->addDrawOp(clip, std::move(op));
675 }
676 
drawAndStencilRect(const GrHardClip & clip,const GrUserStencilSettings * ss,SkRegion::Op op,bool invert,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rect)677 bool GrRenderTargetContextPriv::drawAndStencilRect(const GrHardClip& clip,
678                                                    const GrUserStencilSettings* ss,
679                                                    SkRegion::Op op,
680                                                    bool invert,
681                                                    GrAA aa,
682                                                    const SkMatrix& viewMatrix,
683                                                    const SkRect& rect) {
684     ASSERT_SINGLE_OWNER_PRIV
685     RETURN_FALSE_IF_ABANDONED_PRIV
686     SkDEBUGCODE(fRenderTargetContext->validate();)
687     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilRect",
688                                    fRenderTargetContext->fContext);
689 
690     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
691 
692     GrPaint paint;
693     paint.setCoverageSetOpXPFactory(op, invert);
694 
695     if (fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss)) {
696         return true;
697     }
698     SkPath path;
699     path.setIsVolatile(true);
700     path.addRect(rect);
701     return this->drawAndStencilPath(clip, ss, op, invert, aa, viewMatrix, path);
702 }
703 
fillRectToRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rectToDraw,const SkRect & localRect)704 void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
705                                            GrPaint&& paint,
706                                            GrAA aa,
707                                            const SkMatrix& viewMatrix,
708                                            const SkRect& rectToDraw,
709                                            const SkRect& localRect) {
710     ASSERT_SINGLE_OWNER
711     RETURN_IF_ABANDONED
712     SkDEBUGCODE(this->validate();)
713             GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectToRect", fContext);
714 
715     SkRect croppedRect = rectToDraw;
716     SkRect croppedLocalRect = localRect;
717     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
718                           &croppedRect, &croppedLocalRect)) {
719         return;
720     }
721 
722     AutoCheckFlush acf(this->drawingManager());
723 
724     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
725     if (GrAAType::kCoverage != aaType) {
726         std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFillWithLocalRect(
727                 std::move(paint), viewMatrix, croppedRect, croppedLocalRect, aaType);
728         this->addDrawOp(clip, std::move(op));
729         return;
730     }
731 
732     std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeAAFillWithLocalRect(
733             std::move(paint), viewMatrix, croppedRect, croppedLocalRect);
734     if (op) {
735         this->addDrawOp(clip, std::move(op));
736         return;
737     }
738 
739     SkMatrix viewAndUnLocalMatrix;
740     if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
741         SkDebugf("fillRectToRect called with empty local matrix.\n");
742         return;
743     }
744     viewAndUnLocalMatrix.postConcat(viewMatrix);
745 
746     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewAndUnLocalMatrix,
747                                      GrShape(localRect));
748 }
749 
must_filter(const SkRect & src,const SkRect & dst,const SkMatrix & ctm)750 static bool must_filter(const SkRect& src, const SkRect& dst, const SkMatrix& ctm) {
751     // We don't currently look for 90 degree rotations, mirroring, or downscales that sample at
752     // texel centers.
753     if (!ctm.isTranslate()) {
754         return true;
755     }
756     if (src.width() != dst.width() || src.height() != dst.height()) {
757         return true;
758     }
759     // Check that the device space rectangle's fractional offset is the same as the src rectangle,
760     // and that therefore integers in the src image fall on integers in device space.
761     SkScalar x = ctm.getTranslateX(), y = ctm.getTranslateY();
762     x += dst.fLeft; y += dst.fTop;
763     x -= src.fLeft; y -= src.fTop;
764     return !SkScalarIsInt(x) || !SkScalarIsInt(y);
765 }
766 
drawTextureAffine(const GrClip & clip,sk_sp<GrTextureProxy> proxy,GrSamplerState::Filter filter,GrColor color,const SkRect & srcRect,const SkRect & dstRect,GrAA aa,const SkMatrix & viewMatrix,sk_sp<GrColorSpaceXform> colorSpaceXform)767 void GrRenderTargetContext::drawTextureAffine(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
768                                               GrSamplerState::Filter filter, GrColor color,
769                                               const SkRect& srcRect, const SkRect& dstRect, GrAA aa,
770                                               const SkMatrix& viewMatrix,
771                                               sk_sp<GrColorSpaceXform> colorSpaceXform) {
772     ASSERT_SINGLE_OWNER
773     RETURN_IF_ABANDONED
774     SkDEBUGCODE(this->validate();)
775     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextureAffine", fContext);
776     SkASSERT(!viewMatrix.hasPerspective());
777     if (filter != GrSamplerState::Filter::kNearest && !must_filter(srcRect, dstRect, viewMatrix)) {
778         filter = GrSamplerState::Filter::kNearest;
779     }
780     SkRect clippedDstRect = dstRect;
781     SkRect clippedSrcRect = srcRect;
782     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &clippedDstRect,
783                           &clippedSrcRect)) {
784         return;
785     }
786     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
787     bool allowSRGB = SkToBool(this->colorSpaceInfo().colorSpace());
788     this->addDrawOp(
789             clip, GrTextureOp::Make(std::move(proxy), filter, color, clippedSrcRect, clippedDstRect,
790                                     aaType, viewMatrix, std::move(colorSpaceXform), allowSRGB));
791 }
792 
fillRectWithLocalMatrix(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rectToDraw,const SkMatrix & localMatrix)793 void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
794                                                     GrPaint&& paint,
795                                                     GrAA aa,
796                                                     const SkMatrix& viewMatrix,
797                                                     const SkRect& rectToDraw,
798                                                     const SkMatrix& localMatrix) {
799     ASSERT_SINGLE_OWNER
800     RETURN_IF_ABANDONED
801     SkDEBUGCODE(this->validate();)
802     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithLocalMatrix", fContext);
803 
804     SkRect croppedRect = rectToDraw;
805     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
806         return;
807     }
808 
809     AutoCheckFlush acf(this->drawingManager());
810 
811     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
812     if (GrAAType::kCoverage != aaType) {
813         std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
814                 std::move(paint), viewMatrix, localMatrix, croppedRect, aaType);
815         this->addDrawOp(clip, std::move(op));
816         return;
817     }
818 
819     std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeAAFillWithLocalMatrix(
820             std::move(paint), viewMatrix, localMatrix, croppedRect);
821     if (op) {
822         this->addDrawOp(clip, std::move(op));
823         return;
824     }
825 
826     SkMatrix viewAndUnLocalMatrix;
827     if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
828         SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
829         return;
830     }
831     viewAndUnLocalMatrix.postConcat(viewMatrix);
832 
833     SkPath path;
834     path.setIsVolatile(true);
835     path.addRect(rectToDraw);
836     path.transform(localMatrix);
837     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewAndUnLocalMatrix,
838                                      GrShape(path));
839 }
840 
drawVertices(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix,sk_sp<SkVertices> vertices,GrPrimitiveType * overridePrimType)841 void GrRenderTargetContext::drawVertices(const GrClip& clip,
842                                          GrPaint&& paint,
843                                          const SkMatrix& viewMatrix,
844                                          sk_sp<SkVertices> vertices,
845                                          GrPrimitiveType* overridePrimType) {
846     ASSERT_SINGLE_OWNER
847     RETURN_IF_ABANDONED
848     SkDEBUGCODE(this->validate();)
849     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawVertices", fContext);
850 
851     AutoCheckFlush acf(this->drawingManager());
852 
853     SkASSERT(vertices);
854     GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
855     std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make(
856             std::move(paint), std::move(vertices), viewMatrix, aaType,
857             this->colorSpaceInfo().isGammaCorrect(),
858             this->colorSpaceInfo().refColorSpaceXformFromSRGB(), overridePrimType);
859     this->addDrawOp(clip, std::move(op));
860 }
861 
862 ///////////////////////////////////////////////////////////////////////////////
863 
drawAtlas(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix,int spriteCount,const SkRSXform xform[],const SkRect texRect[],const SkColor colors[])864 void GrRenderTargetContext::drawAtlas(const GrClip& clip,
865                                       GrPaint&& paint,
866                                       const SkMatrix& viewMatrix,
867                                       int spriteCount,
868                                       const SkRSXform xform[],
869                                       const SkRect texRect[],
870                                       const SkColor colors[]) {
871     ASSERT_SINGLE_OWNER
872     RETURN_IF_ABANDONED
873     SkDEBUGCODE(this->validate();)
874     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawAtlas", fContext);
875 
876     AutoCheckFlush acf(this->drawingManager());
877 
878     GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
879     std::unique_ptr<GrDrawOp> op = GrDrawAtlasOp::Make(std::move(paint), viewMatrix, aaType,
880                                                        spriteCount, xform, texRect, colors);
881     this->addDrawOp(clip, std::move(op));
882 }
883 
884 ///////////////////////////////////////////////////////////////////////////////
885 
drawRRect(const GrClip & origClip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRRect & rrect,const GrStyle & style)886 void GrRenderTargetContext::drawRRect(const GrClip& origClip,
887                                       GrPaint&& paint,
888                                       GrAA aa,
889                                       const SkMatrix& viewMatrix,
890                                       const SkRRect& rrect,
891                                       const GrStyle& style) {
892     ASSERT_SINGLE_OWNER
893     RETURN_IF_ABANDONED
894     SkDEBUGCODE(this->validate();)
895     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRRect", fContext);
896     if (rrect.isEmpty()) {
897        return;
898     }
899 
900     GrNoClip noclip;
901     const GrClip* clip = &origClip;
902 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
903     // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
904     // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
905     // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
906     // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
907     // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
908     SkRRect devRRect;
909     if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
910         clip = &noclip;
911     }
912 #endif
913     SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
914 
915     AutoCheckFlush acf(this->drawingManager());
916     const SkStrokeRec stroke = style.strokeRec();
917 
918     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
919     if (GrAAType::kCoverage == aaType) {
920         const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
921         std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeRRectOp(std::move(paint),
922                                                                     viewMatrix,
923                                                                     rrect,
924                                                                     stroke,
925                                                                     shaderCaps);
926         if (op) {
927             this->addDrawOp(*clip, std::move(op));
928             return;
929         }
930     }
931 
932     this->drawShapeUsingPathRenderer(*clip, std::move(paint), aa, viewMatrix,
933                                      GrShape(rrect, style));
934 }
935 
936 ///////////////////////////////////////////////////////////////////////////////
937 
map(const SkMatrix & m,const SkPoint3 & pt)938 static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) {
939     SkPoint3 result;
940     m.mapXY(pt.fX, pt.fY, (SkPoint*)&result.fX);
941     result.fZ = pt.fZ;
942     return result;
943 }
944 
drawFastShadow(const GrClip & clip,const SkMatrix & viewMatrix,const SkPath & path,const SkDrawShadowRec & rec)945 bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
946                                            const SkMatrix& viewMatrix,
947                                            const SkPath& path,
948                                            const SkDrawShadowRec& rec) {
949     ASSERT_SINGLE_OWNER
950     if (this->drawingManager()->wasAbandoned()) {
951         return true;
952     }
953     SkDEBUGCODE(this->validate();)
954     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawFastShadow", fContext);
955 
956     // check z plane
957     bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) ||
958                                !SkScalarNearlyZero(rec.fZPlaneParams.fY));
959     bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
960     if (tiltZPlane || skipAnalytic || !viewMatrix.rectStaysRect() || !viewMatrix.isSimilarity()) {
961         return false;
962     }
963 
964     SkRRect rrect;
965     SkRect rect;
966     // we can only handle rects, circles, and rrects with circular corners
967     bool isRRect = path.isRRect(&rrect) && rrect.isSimpleCircular() &&
968         rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero;
969     if (!isRRect &&
970         path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
971         rect.width() > SK_ScalarNearlyZero) {
972         rrect.setOval(rect);
973         isRRect = true;
974     }
975     if (!isRRect && path.isRect(&rect)) {
976         rrect.setRect(rect);
977         isRRect = true;
978     }
979 
980     if (!isRRect) {
981         return false;
982     }
983 
984     if (rrect.isEmpty()) {
985         return true;
986     }
987 
988     AutoCheckFlush acf(this->drawingManager());
989 
990     // transform light
991     SkPoint3 devLightPos = map(viewMatrix, rec.fLightPos);
992 
993     // 1/scale
994     SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ?
995         SkScalarInvert(viewMatrix[SkMatrix::kMScaleX]) :
996         sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] +
997                        viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]);
998 
999     SkScalar occluderHeight = rec.fZPlaneParams.fZ;
1000     bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
1001 
1002     if (SkColorGetA(rec.fAmbientColor) > 0) {
1003         SkScalar devSpaceInsetWidth = SkDrawShadowMetrics::AmbientBlurRadius(occluderHeight);
1004         const SkScalar umbraRecipAlpha = SkDrawShadowMetrics::AmbientRecipAlpha(occluderHeight);
1005         const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha;
1006 
1007         // Outset the shadow rrect to the border of the penumbra
1008         SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale;
1009         SkRRect ambientRRect;
1010         SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset);
1011         // If the rrect was an oval then its outset will also be one.
1012         // We set it explicitly to avoid errors.
1013         if (rrect.isOval()) {
1014             ambientRRect = SkRRect::MakeOval(outsetRect);
1015         } else {
1016             SkScalar outsetRad = rrect.getSimpleRadii().fX + ambientPathOutset;
1017             ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1018         }
1019 
1020         GrColor ambientColor = SkColorToPremulGrColor(rec.fAmbientColor);
1021         if (transparent) {
1022             // set a large inset to force a fill
1023             devSpaceInsetWidth = ambientRRect.width();
1024         }
1025         // the fraction of the blur we want to apply is devSpaceInsetWidth/devSpaceAmbientBlur,
1026         // which is just 1/umbraRecipAlpha.
1027         SkScalar blurClamp = SkScalarInvert(umbraRecipAlpha);
1028 
1029         std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(ambientColor, viewMatrix,
1030                                                              ambientRRect,
1031                                                              devSpaceAmbientBlur,
1032                                                              devSpaceInsetWidth,
1033                                                              blurClamp);
1034         SkASSERT(op);
1035         this->addDrawOp(clip, std::move(op));
1036     }
1037 
1038     if (SkColorGetA(rec.fSpotColor) > 0) {
1039         SkScalar devSpaceSpotBlur;
1040         SkScalar spotScale;
1041         SkVector spotOffset;
1042         SkDrawShadowMetrics::GetSpotParams(occluderHeight, devLightPos.fX, devLightPos.fY,
1043                                            devLightPos.fZ, rec.fLightRadius,
1044                                            &devSpaceSpotBlur, &spotScale, &spotOffset);
1045         // handle scale of radius due to CTM
1046         const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale;
1047 
1048         // Adjust translate for the effect of the scale.
1049         spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX];
1050         spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY];
1051         // This offset is in dev space, need to transform it into source space.
1052         SkMatrix ctmInverse;
1053         if (viewMatrix.invert(&ctmInverse)) {
1054             ctmInverse.mapPoints(&spotOffset, 1);
1055         } else {
1056             // Since the matrix is a similarity, this should never happen, but just in case...
1057             SkDebugf("Matrix is degenerate. Will not render spot shadow correctly!\n");
1058             SkASSERT(false);
1059         }
1060 
1061         // Compute the transformed shadow rrect
1062         SkRRect spotShadowRRect;
1063         SkMatrix shadowTransform;
1064         shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY);
1065         rrect.transform(shadowTransform, &spotShadowRRect);
1066         SkScalar spotRadius = spotShadowRRect.getSimpleRadii().fX;
1067 
1068         // Compute the insetWidth
1069         SkScalar blurOutset = srcSpaceSpotBlur;
1070         SkScalar insetWidth = blurOutset;
1071         if (transparent) {
1072             // If transparent, just do a fill
1073             insetWidth += spotShadowRRect.width();
1074         } else {
1075             // For shadows, instead of using a stroke we specify an inset from the penumbra
1076             // border. We want to extend this inset area so that it meets up with the caster
1077             // geometry. The inset geometry will by default already be inset by the blur width.
1078             //
1079             // We compare the min and max corners inset by the radius between the original
1080             // rrect and the shadow rrect. The distance between the two plus the difference
1081             // between the scaled radius and the original radius gives the distance from the
1082             // transformed shadow shape to the original shape in that corner. The max
1083             // of these gives the maximum distance we need to cover.
1084             //
1085             // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to
1086             // that to get the full insetWidth.
1087             SkScalar maxOffset;
1088             if (rrect.isRect()) {
1089                 // Manhattan distance works better for rects
1090                 maxOffset = SkTMax(SkTMax(SkTAbs(spotShadowRRect.rect().fLeft -
1091                                                  rrect.rect().fLeft),
1092                                           SkTAbs(spotShadowRRect.rect().fTop -
1093                                                  rrect.rect().fTop)),
1094                                    SkTMax(SkTAbs(spotShadowRRect.rect().fRight -
1095                                                  rrect.rect().fRight),
1096                                           SkTAbs(spotShadowRRect.rect().fBottom -
1097                                                  rrect.rect().fBottom)));
1098             } else {
1099                 SkScalar dr = spotRadius - rrect.getSimpleRadii().fX;
1100                 SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft -
1101                                                         rrect.rect().fLeft + dr,
1102                                                         spotShadowRRect.rect().fTop -
1103                                                         rrect.rect().fTop + dr);
1104                 SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight -
1105                                                          rrect.rect().fRight - dr,
1106                                                          spotShadowRRect.rect().fBottom -
1107                                                          rrect.rect().fBottom - dr);
1108                 maxOffset = SkScalarSqrt(SkTMax(SkPointPriv::LengthSqd(upperLeftOffset),
1109                                                 SkPointPriv::LengthSqd(lowerRightOffset))) + dr;
1110             }
1111             insetWidth += maxOffset;
1112         }
1113 
1114         // Outset the shadow rrect to the border of the penumbra
1115         SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset);
1116         if (spotShadowRRect.isOval()) {
1117             spotShadowRRect = SkRRect::MakeOval(outsetRect);
1118         } else {
1119             SkScalar outsetRad = spotRadius + blurOutset;
1120             spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1121         }
1122 
1123         GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor);
1124 
1125         std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(spotColor, viewMatrix,
1126                                                              spotShadowRRect,
1127                                                              2.0f * devSpaceSpotBlur,
1128                                                              insetWidth);
1129         SkASSERT(op);
1130         this->addDrawOp(clip, std::move(op));
1131     }
1132 
1133     return true;
1134 }
1135 
1136 ///////////////////////////////////////////////////////////////////////////////
1137 
drawFilledDRRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRRect & origOuter,const SkRRect & origInner)1138 bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
1139                                              GrPaint&& paint,
1140                                              GrAA aa,
1141                                              const SkMatrix& viewMatrix,
1142                                              const SkRRect& origOuter,
1143                                              const SkRRect& origInner) {
1144     SkASSERT(!origInner.isEmpty());
1145     SkASSERT(!origOuter.isEmpty());
1146 
1147     SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1148 
1149     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1150 
1151     if (GrAAType::kMSAA == aaType) {
1152         return false;
1153     }
1154 
1155     if (GrAAType::kCoverage == aaType && inner->isCircle() && outer->isCircle()) {
1156         auto outerR = outer->width() / 2.f;
1157         auto innerR = inner->width() / 2.f;
1158         auto cx = outer->getBounds().fLeft + outerR;
1159         auto cy = outer->getBounds().fTop + outerR;
1160         if (SkScalarNearlyEqual(cx, inner->getBounds().fLeft + innerR) &&
1161             SkScalarNearlyEqual(cy, inner->getBounds().fTop + innerR)) {
1162             auto avgR = (innerR + outerR) / 2.f;
1163             auto circleBounds = SkRect::MakeLTRB(cx - avgR, cy - avgR, cx + avgR, cy + avgR);
1164             SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
1165             stroke.setStrokeStyle(outerR - innerR);
1166             auto op = GrOvalOpFactory::MakeOvalOp(std::move(paint), viewMatrix, circleBounds,
1167                                                   stroke, this->caps()->shaderCaps());
1168             if (op) {
1169                 this->addDrawOp(clip, std::move(op));
1170                 return true;
1171             }
1172         }
1173     }
1174 
1175     GrClipEdgeType innerEdgeType, outerEdgeType;
1176     if (GrAAType::kCoverage == aaType) {
1177         innerEdgeType = GrClipEdgeType::kInverseFillAA;
1178         outerEdgeType = GrClipEdgeType::kFillAA;
1179     } else {
1180         innerEdgeType = GrClipEdgeType::kInverseFillBW;
1181         outerEdgeType = GrClipEdgeType::kFillBW;
1182     }
1183 
1184     SkMatrix inverseVM;
1185     if (!viewMatrix.isIdentity()) {
1186         if (!origInner.transform(viewMatrix, inner.writable())) {
1187             return false;
1188         }
1189         if (!origOuter.transform(viewMatrix, outer.writable())) {
1190             return false;
1191         }
1192         if (!viewMatrix.invert(&inverseVM)) {
1193             return false;
1194         }
1195     } else {
1196         inverseVM.reset();
1197     }
1198 
1199     const auto& caps = *this->caps()->shaderCaps();
1200     // TODO these need to be a geometry processors
1201     auto innerEffect = GrRRectEffect::Make(innerEdgeType, *inner, caps);
1202     if (!innerEffect) {
1203         return false;
1204     }
1205 
1206     auto outerEffect = GrRRectEffect::Make(outerEdgeType, *outer, caps);
1207     if (!outerEffect) {
1208         return false;
1209     }
1210 
1211     paint.addCoverageFragmentProcessor(std::move(innerEffect));
1212     paint.addCoverageFragmentProcessor(std::move(outerEffect));
1213 
1214     SkRect bounds = outer->getBounds();
1215     if (GrAAType::kCoverage == aaType) {
1216         bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1217     }
1218 
1219     this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1220                                   inverseVM);
1221     return true;
1222 }
1223 
drawDRRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRRect & outer,const SkRRect & inner)1224 void GrRenderTargetContext::drawDRRect(const GrClip& clip,
1225                                        GrPaint&& paint,
1226                                        GrAA aa,
1227                                        const SkMatrix& viewMatrix,
1228                                        const SkRRect& outer,
1229                                        const SkRRect& inner) {
1230     ASSERT_SINGLE_OWNER
1231     RETURN_IF_ABANDONED
1232     SkDEBUGCODE(this->validate();)
1233     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawDRRect", fContext);
1234 
1235     SkASSERT(!outer.isEmpty());
1236     SkASSERT(!inner.isEmpty());
1237 
1238     AutoCheckFlush acf(this->drawingManager());
1239 
1240     if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
1241         return;
1242     }
1243 
1244     SkPath path;
1245     path.setIsVolatile(true);
1246     path.addRRect(inner);
1247     path.addRRect(outer);
1248     path.setFillType(SkPath::kEvenOdd_FillType);
1249     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(path));
1250 }
1251 
1252 ///////////////////////////////////////////////////////////////////////////////
1253 
drawRegion(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRegion & region,const GrStyle & style,const GrUserStencilSettings * ss)1254 void GrRenderTargetContext::drawRegion(const GrClip& clip,
1255                                        GrPaint&& paint,
1256                                        GrAA aa,
1257                                        const SkMatrix& viewMatrix,
1258                                        const SkRegion& region,
1259                                        const GrStyle& style,
1260                                        const GrUserStencilSettings* ss) {
1261     ASSERT_SINGLE_OWNER
1262     RETURN_IF_ABANDONED
1263     SkDEBUGCODE(this->validate();)
1264     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRegion", fContext);
1265 
1266     if (GrAA::kYes == aa) {
1267         // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
1268         // to see whether aa is really required.
1269         if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
1270             SkScalarIsInt(viewMatrix.getTranslateX()) &&
1271             SkScalarIsInt(viewMatrix.getTranslateY())) {
1272             aa = GrAA::kNo;
1273         }
1274     }
1275     bool complexStyle = !style.isSimpleFill();
1276     if (complexStyle || GrAA::kYes == aa) {
1277         SkPath path;
1278         region.getBoundaryPath(&path);
1279         return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
1280     }
1281 
1282     GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
1283     std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(std::move(paint), viewMatrix, region, aaType,
1284                                                     ss);
1285     this->addDrawOp(clip, std::move(op));
1286 }
1287 
drawOval(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & oval,const GrStyle & style)1288 void GrRenderTargetContext::drawOval(const GrClip& clip,
1289                                      GrPaint&& paint,
1290                                      GrAA aa,
1291                                      const SkMatrix& viewMatrix,
1292                                      const SkRect& oval,
1293                                      const GrStyle& style) {
1294     ASSERT_SINGLE_OWNER
1295     RETURN_IF_ABANDONED
1296     SkDEBUGCODE(this->validate();)
1297     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawOval", fContext);
1298 
1299     if (oval.isEmpty()) {
1300        return;
1301     }
1302 
1303     SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
1304 
1305     AutoCheckFlush acf(this->drawingManager());
1306     const SkStrokeRec& stroke = style.strokeRec();
1307 
1308     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1309     if (GrAAType::kCoverage == aaType) {
1310         const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
1311         std::unique_ptr<GrDrawOp> op =
1312                 GrOvalOpFactory::MakeOvalOp(std::move(paint), viewMatrix, oval, stroke, shaderCaps);
1313         if (op) {
1314             this->addDrawOp(clip, std::move(op));
1315             return;
1316         }
1317     }
1318 
1319     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
1320                                      GrShape(SkRRect::MakeOval(oval), style));
1321 }
1322 
drawArc(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const GrStyle & style)1323 void GrRenderTargetContext::drawArc(const GrClip& clip,
1324                                     GrPaint&& paint,
1325                                     GrAA aa,
1326                                     const SkMatrix& viewMatrix,
1327                                     const SkRect& oval,
1328                                     SkScalar startAngle,
1329                                     SkScalar sweepAngle,
1330                                     bool useCenter,
1331                                     const GrStyle& style) {
1332     ASSERT_SINGLE_OWNER
1333     RETURN_IF_ABANDONED
1334     SkDEBUGCODE(this->validate();)
1335             GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawArc", fContext);
1336 
1337     AutoCheckFlush acf(this->drawingManager());
1338 
1339     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1340     if (GrAAType::kCoverage == aaType) {
1341         const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
1342         std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(std::move(paint),
1343                                                                   viewMatrix,
1344                                                                   oval,
1345                                                                   startAngle,
1346                                                                   sweepAngle,
1347                                                                   useCenter,
1348                                                                   style,
1349                                                                   shaderCaps);
1350         if (op) {
1351             this->addDrawOp(clip, std::move(op));
1352             return;
1353         }
1354     }
1355     SkPath path;
1356     SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1357                                   style.isSimpleFill());
1358     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(path, style));
1359 }
1360 
drawImageLattice(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix,int imageWidth,int imageHeight,std::unique_ptr<SkLatticeIter> iter,const SkRect & dst)1361 void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
1362                                              GrPaint&& paint,
1363                                              const SkMatrix& viewMatrix,
1364                                              int imageWidth,
1365                                              int imageHeight,
1366                                              std::unique_ptr<SkLatticeIter> iter,
1367                                              const SkRect& dst) {
1368     ASSERT_SINGLE_OWNER
1369     RETURN_IF_ABANDONED
1370     SkDEBUGCODE(this->validate();)
1371     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawImageLattice", fContext);
1372 
1373     AutoCheckFlush acf(this->drawingManager());
1374 
1375     std::unique_ptr<GrDrawOp> op = GrLatticeOp::MakeNonAA(std::move(paint), viewMatrix, imageWidth,
1376                                                           imageHeight, std::move(iter), dst);
1377     this->addDrawOp(clip, std::move(op));
1378 }
1379 
prepareForExternalIO(int numSemaphores,GrBackendSemaphore backendSemaphores[])1380 GrSemaphoresSubmitted GrRenderTargetContext::prepareForExternalIO(
1381         int numSemaphores, GrBackendSemaphore backendSemaphores[]) {
1382     ASSERT_SINGLE_OWNER
1383     if (this->drawingManager()->wasAbandoned()) { return GrSemaphoresSubmitted::kNo; }
1384     SkDEBUGCODE(this->validate();)
1385     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "prepareForExternalIO", fContext);
1386 
1387     return this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get(),
1388                                                                numSemaphores,
1389                                                                backendSemaphores);
1390 }
1391 
waitOnSemaphores(int numSemaphores,const GrBackendSemaphore * waitSemaphores)1392 bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
1393                                              const GrBackendSemaphore* waitSemaphores) {
1394     ASSERT_SINGLE_OWNER
1395     RETURN_FALSE_IF_ABANDONED
1396     SkDEBUGCODE(this->validate();)
1397     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "waitOnSemaphores", fContext);
1398 
1399     AutoCheckFlush acf(this->drawingManager());
1400 
1401     if (numSemaphores && !this->caps()->fenceSyncSupport()) {
1402         return false;
1403     }
1404 
1405     auto resourceProvider = fContext->contextPriv().resourceProvider();
1406 
1407     SkTArray<sk_sp<GrSemaphore>> semaphores(numSemaphores);
1408     for (int i = 0; i < numSemaphores; ++i) {
1409         sk_sp<GrSemaphore> sema = resourceProvider->wrapBackendSemaphore(
1410                 waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
1411                 kAdopt_GrWrapOwnership);
1412         std::unique_ptr<GrOp> waitOp(GrSemaphoreOp::MakeWait(sema, fRenderTargetProxy.get()));
1413         this->getRTOpList()->addOp(std::move(waitOp), *this->caps());
1414     }
1415     return true;
1416 }
1417 
insertEventMarker(const SkString & str)1418 void GrRenderTargetContext::insertEventMarker(const SkString& str) {
1419     std::unique_ptr<GrOp> op(GrDebugMarkerOp::Make(fRenderTargetProxy.get(), str));
1420     this->getRTOpList()->addOp(std::move(op), *this->caps());
1421 }
1422 
1423 
1424 // Can 'path' be drawn as a pair of filled nested rectangles?
fills_as_nested_rects(const SkMatrix & viewMatrix,const SkPath & path,SkRect rects[2])1425 static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
1426 
1427     if (path.isInverseFillType()) {
1428         return false;
1429     }
1430 
1431     // TODO: this restriction could be lifted if we were willing to apply
1432     // the matrix to all the points individually rather than just to the rect
1433     if (!viewMatrix.rectStaysRect()) {
1434         return false;
1435     }
1436 
1437     SkPath::Direction dirs[2];
1438     if (!path.isNestedFillRects(rects, dirs)) {
1439         return false;
1440     }
1441 
1442     if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1443         // The two rects need to be wound opposite to each other
1444         return false;
1445     }
1446 
1447     // Right now, nested rects where the margin is not the same width
1448     // all around do not render correctly
1449     const SkScalar* outer = rects[0].asScalars();
1450     const SkScalar* inner = rects[1].asScalars();
1451 
1452     bool allEq = true;
1453 
1454     SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1455     bool allGoE1 = margin >= SK_Scalar1;
1456 
1457     for (int i = 1; i < 4; ++i) {
1458         SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1459         if (temp < SK_Scalar1) {
1460             allGoE1 = false;
1461         }
1462         if (!SkScalarNearlyEqual(margin, temp)) {
1463             allEq = false;
1464         }
1465     }
1466 
1467     return allEq || allGoE1;
1468 }
1469 
drawPath(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkPath & path,const GrStyle & style)1470 void GrRenderTargetContext::drawPath(const GrClip& clip,
1471                                      GrPaint&& paint,
1472                                      GrAA aa,
1473                                      const SkMatrix& viewMatrix,
1474                                      const SkPath& path,
1475                                      const GrStyle& style) {
1476     ASSERT_SINGLE_OWNER
1477     RETURN_IF_ABANDONED
1478     SkDEBUGCODE(this->validate();)
1479             GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawPath", fContext);
1480 
1481     GrShape shape(path, style);
1482     if (shape.isEmpty()) {
1483         if (shape.inverseFilled()) {
1484             this->drawPaint(clip, std::move(paint), viewMatrix);
1485         }
1486         return;
1487     }
1488 
1489     AutoCheckFlush acf(this->drawingManager());
1490 
1491     if (!shape.style().hasPathEffect()) {
1492         SkRRect rrect;
1493         // We can ignore the starting point and direction since there is no path effect.
1494         bool inverted;
1495         if (shape.asRRect(&rrect, nullptr, nullptr, &inverted) && !inverted) {
1496             if (rrect.isRect()) {
1497                 this->drawRect(clip, std::move(paint), aa, viewMatrix, rrect.rect(),
1498                                &shape.style());
1499                 return;
1500             } else if (rrect.isOval()) {
1501                 this->drawOval(clip, std::move(paint), aa, viewMatrix, rrect.rect(), shape.style());
1502                 return;
1503             }
1504             this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect, shape.style());
1505             return;
1506         }
1507     }
1508 
1509     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1510     if (GrAAType::kCoverage == aaType) {
1511         // TODO: Make GrShape check for nested rects.
1512         SkRect rects[2];
1513         if (shape.style().isSimpleFill() && fills_as_nested_rects(viewMatrix, path, rects)) {
1514             // Concave AA paths are expensive - try to avoid them for special cases
1515             SkRect rects[2];
1516 
1517             if (fills_as_nested_rects(viewMatrix, path, rects)) {
1518                 std::unique_ptr<GrDrawOp> op =
1519                         GrRectOpFactory::MakeAAFillNestedRects(std::move(paint), viewMatrix, rects);
1520                 if (op) {
1521                     this->addDrawOp(clip, std::move(op));
1522                 }
1523                 // A null return indicates that there is nothing to draw in this case.
1524                 return;
1525             }
1526         }
1527     }
1528     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, shape);
1529 }
1530 
drawAndStencilPath(const GrHardClip & clip,const GrUserStencilSettings * ss,SkRegion::Op op,bool invert,GrAA aa,const SkMatrix & viewMatrix,const SkPath & path)1531 bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
1532                                                    const GrUserStencilSettings* ss,
1533                                                    SkRegion::Op op,
1534                                                    bool invert,
1535                                                    GrAA aa,
1536                                                    const SkMatrix& viewMatrix,
1537                                                    const SkPath& path) {
1538     ASSERT_SINGLE_OWNER_PRIV
1539     RETURN_FALSE_IF_ABANDONED_PRIV
1540     SkDEBUGCODE(fRenderTargetContext->validate();)
1541     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilPath",
1542                                    fRenderTargetContext->fContext);
1543 
1544     if (path.isEmpty() && path.isInverseFillType()) {
1545         this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
1546                                  SkRect::MakeIWH(fRenderTargetContext->width(),
1547                                                  fRenderTargetContext->height()));
1548         return true;
1549     }
1550 
1551     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
1552 
1553     // An Assumption here is that path renderer would use some form of tweaking
1554     // the src color (either the input alpha or in the frag shader) to implement
1555     // aa. If we have some future driver-mojo path AA that can do the right
1556     // thing WRT to the blend then we'll need some query on the PR.
1557     GrAAType aaType = fRenderTargetContext->chooseAAType(aa, GrAllowMixedSamples::kNo);
1558     bool hasUserStencilSettings = !ss->isUnused();
1559 
1560     SkIRect clipConservativeBounds;
1561     clip.getConservativeBounds(fRenderTargetContext->width(), fRenderTargetContext->height(),
1562                                &clipConservativeBounds, nullptr);
1563 
1564     GrShape shape(path, GrStyle::SimpleFill());
1565     GrPathRenderer::CanDrawPathArgs canDrawArgs;
1566     canDrawArgs.fCaps = fRenderTargetContext->drawingManager()->getContext()->caps();
1567     canDrawArgs.fViewMatrix = &viewMatrix;
1568     canDrawArgs.fShape = &shape;
1569     canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
1570     canDrawArgs.fAAType = aaType;
1571     canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
1572 
1573     // Don't allow the SW renderer
1574     GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
1575             canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
1576     if (!pr) {
1577         return false;
1578     }
1579 
1580     GrPaint paint;
1581     paint.setCoverageSetOpXPFactory(op, invert);
1582 
1583     GrPathRenderer::DrawPathArgs args{fRenderTargetContext->drawingManager()->getContext(),
1584                                       std::move(paint),
1585                                       ss,
1586                                       fRenderTargetContext,
1587                                       &clip,
1588                                       &clipConservativeBounds,
1589                                       &viewMatrix,
1590                                       &shape,
1591                                       aaType,
1592                                       fRenderTargetContext->colorSpaceInfo().isGammaCorrect()};
1593     pr->drawPath(args);
1594     return true;
1595 }
1596 
isBudgeted() const1597 SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
1598     ASSERT_SINGLE_OWNER_PRIV
1599 
1600     if (fRenderTargetContext->wasAbandoned()) {
1601         return SkBudgeted::kNo;
1602     }
1603 
1604     SkDEBUGCODE(fRenderTargetContext->validate();)
1605 
1606     return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
1607 }
1608 
drawShapeUsingPathRenderer(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const GrShape & originalShape)1609 void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
1610                                                        GrPaint&& paint,
1611                                                        GrAA aa,
1612                                                        const SkMatrix& viewMatrix,
1613                                                        const GrShape& originalShape) {
1614     ASSERT_SINGLE_OWNER
1615     RETURN_IF_ABANDONED
1616     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "internalDrawPath", fContext);
1617 
1618     SkIRect clipConservativeBounds;
1619     clip.getConservativeBounds(this->width(), this->height(), &clipConservativeBounds, nullptr);
1620 
1621     GrShape tempShape;
1622     // NVPR cannot handle hairlines, so this would get picked up by a different stencil and
1623     // cover path renderer (i.e. default path renderer). The hairline renderer produces much
1624     // smoother hairlines than MSAA.
1625     GrAllowMixedSamples allowMixedSamples = originalShape.style().isSimpleHairline()
1626                                                     ? GrAllowMixedSamples::kNo
1627                                                     : GrAllowMixedSamples::kYes;
1628     GrAAType aaType = this->chooseAAType(aa, allowMixedSamples);
1629     GrPathRenderer::CanDrawPathArgs canDrawArgs;
1630     canDrawArgs.fCaps = this->drawingManager()->getContext()->caps();
1631     canDrawArgs.fViewMatrix = &viewMatrix;
1632     canDrawArgs.fShape = &originalShape;
1633     canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
1634     canDrawArgs.fHasUserStencilSettings = false;
1635 
1636     GrPathRenderer* pr;
1637     static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
1638     if (originalShape.isEmpty() && !originalShape.inverseFilled()) {
1639         return;
1640     }
1641 
1642     canDrawArgs.fAAType = aaType;
1643 
1644     // Try a 1st time without applying any of the style to the geometry (and barring sw)
1645     pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
1646     SkScalar styleScale =  GrStyle::MatrixToScaleFactor(viewMatrix);
1647 
1648     if (!pr && originalShape.style().pathEffect()) {
1649         // It didn't work above, so try again with the path effect applied.
1650         tempShape = originalShape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1651         if (tempShape.isEmpty()) {
1652             return;
1653         }
1654         canDrawArgs.fShape = &tempShape;
1655         pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
1656     }
1657     if (!pr) {
1658         if (canDrawArgs.fShape->style().applies()) {
1659             tempShape = canDrawArgs.fShape->applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec,
1660                                                        styleScale);
1661             if (tempShape.isEmpty()) {
1662                 return;
1663             }
1664             canDrawArgs.fShape = &tempShape;
1665         }
1666         // This time, allow SW renderer
1667         pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
1668     }
1669 
1670     if (!pr) {
1671 #ifdef SK_DEBUG
1672         SkDebugf("Unable to find path renderer compatible with path.\n");
1673 #endif
1674         return;
1675     }
1676 
1677     GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
1678                                       std::move(paint),
1679                                       &GrUserStencilSettings::kUnused,
1680                                       this,
1681                                       &clip,
1682                                       &clipConservativeBounds,
1683                                       &viewMatrix,
1684                                       canDrawArgs.fShape,
1685                                       aaType,
1686                                       this->colorSpaceInfo().isGammaCorrect()};
1687     pr->drawPath(args);
1688 }
1689 
op_bounds(SkRect * bounds,const GrOp * op)1690 static void op_bounds(SkRect* bounds, const GrOp* op) {
1691     *bounds = op->bounds();
1692     if (op->hasZeroArea()) {
1693         if (op->hasAABloat()) {
1694             bounds->outset(0.5f, 0.5f);
1695         } else {
1696             // We don't know which way the particular GPU will snap lines or points at integer
1697             // coords. So we ensure that the bounds is large enough for either snap.
1698             SkRect before = *bounds;
1699             bounds->roundOut(bounds);
1700             if (bounds->fLeft == before.fLeft) {
1701                 bounds->fLeft -= 1;
1702             }
1703             if (bounds->fTop == before.fTop) {
1704                 bounds->fTop -= 1;
1705             }
1706             if (bounds->fRight == before.fRight) {
1707                 bounds->fRight += 1;
1708             }
1709             if (bounds->fBottom == before.fBottom) {
1710                 bounds->fBottom += 1;
1711             }
1712         }
1713     }
1714 }
1715 
addDrawOp(const GrClip & clip,std::unique_ptr<GrDrawOp> op)1716 uint32_t GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op) {
1717     ASSERT_SINGLE_OWNER
1718     if (this->drawingManager()->wasAbandoned()) {
1719         return SK_InvalidUniqueID;
1720     }
1721     SkDEBUGCODE(this->validate();)
1722     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "addDrawOp", fContext);
1723 
1724     // Setup clip
1725     SkRect bounds;
1726     op_bounds(&bounds, op.get());
1727     GrAppliedClip appliedClip;
1728     GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
1729     if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
1730                     fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
1731                     &bounds)) {
1732         return SK_InvalidUniqueID;
1733     }
1734 
1735     if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
1736         appliedClip.hasStencilClip()) {
1737         this->getOpList()->setStencilLoadOp(GrLoadOp::kClear);
1738 
1739         this->setNeedsStencil();
1740     }
1741 
1742     GrPixelConfigIsClamped dstIsClamped =
1743             GrGetPixelConfigIsClamped(this->colorSpaceInfo().config());
1744     GrXferProcessor::DstProxy dstProxy;
1745     if (GrDrawOp::RequiresDstTexture::kYes == op->finalize(*this->caps(), &appliedClip,
1746                                                            dstIsClamped)) {
1747         if (!this->setupDstProxy(this->asRenderTargetProxy(), clip, op->bounds(), &dstProxy)) {
1748             return SK_InvalidUniqueID;
1749         }
1750     }
1751 
1752     op->setClippedBounds(bounds);
1753     return this->getRTOpList()->addOp(std::move(op), *this->caps(),
1754                                       std::move(appliedClip), dstProxy);
1755 }
1756 
setupDstProxy(GrRenderTargetProxy * rtProxy,const GrClip & clip,const SkRect & opBounds,GrXferProcessor::DstProxy * dstProxy)1757 bool GrRenderTargetContext::setupDstProxy(GrRenderTargetProxy* rtProxy, const GrClip& clip,
1758                                           const SkRect& opBounds,
1759                                           GrXferProcessor::DstProxy* dstProxy) {
1760     if (this->caps()->textureBarrierSupport()) {
1761         if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
1762             // The render target is a texture, so we can read from it directly in the shader. The XP
1763             // will be responsible to detect this situation and request a texture barrier.
1764             dstProxy->setProxy(sk_ref_sp(texProxy));
1765             dstProxy->setOffset(0, 0);
1766             return true;
1767         }
1768     }
1769 
1770     SkIRect copyRect = SkIRect::MakeWH(rtProxy->width(), rtProxy->height());
1771 
1772     SkIRect clippedRect;
1773     clip.getConservativeBounds(rtProxy->width(), rtProxy->height(), &clippedRect);
1774     SkIRect drawIBounds;
1775     opBounds.roundOut(&drawIBounds);
1776     // Cover up for any precision issues by outsetting the op bounds a pixel in each direction.
1777     drawIBounds.outset(1, 1);
1778     if (!clippedRect.intersect(drawIBounds)) {
1779 #ifdef SK_DEBUG
1780         GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
1781 #endif
1782         return false;
1783     }
1784 
1785     // MSAA consideration: When there is support for reading MSAA samples in the shader we could
1786     // have per-sample dst values by making the copy multisampled.
1787     GrSurfaceDesc desc;
1788     bool rectsMustMatch = false;
1789     bool disallowSubrect = false;
1790     if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &rectsMustMatch, &disallowSubrect)) {
1791         desc.fFlags = kRenderTarget_GrSurfaceFlag;
1792         desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
1793         desc.fConfig = rtProxy->config();
1794     }
1795 
1796     if (!disallowSubrect) {
1797         copyRect = clippedRect;
1798     }
1799 
1800     SkIPoint dstPoint, dstOffset;
1801     SkBackingFit fit;
1802     if (rectsMustMatch) {
1803         SkASSERT(desc.fOrigin == rtProxy->origin());
1804         desc.fWidth = rtProxy->width();
1805         desc.fHeight = rtProxy->height();
1806         dstPoint = {copyRect.fLeft, copyRect.fTop};
1807         dstOffset = {0, 0};
1808         fit = SkBackingFit::kExact;
1809     } else {
1810         desc.fWidth = copyRect.width();
1811         desc.fHeight = copyRect.height();
1812         dstPoint = {0, 0};
1813         dstOffset = {copyRect.fLeft, copyRect.fTop};
1814         fit = SkBackingFit::kApprox;
1815     }
1816 
1817     sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeDeferredSurfaceContext(
1818                                                                                 desc,
1819                                                                                 GrMipMapped::kNo,
1820                                                                                 fit,
1821                                                                                 SkBudgeted::kYes);
1822     if (!sContext) {
1823         SkDebugf("setupDstTexture: surfaceContext creation failed.\n");
1824         return false;
1825     }
1826 
1827     if (!sContext->copy(rtProxy, copyRect, dstPoint)) {
1828         SkDebugf("setupDstTexture: copy failed.\n");
1829         return false;
1830     }
1831 
1832     dstProxy->setProxy(sContext->asTextureProxyRef());
1833     dstProxy->setOffset(dstOffset);
1834     return true;
1835 }
1836