LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu - GrRenderTargetContext.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 910 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 55 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13