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