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