/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/v1/SurfaceDrawContext_v1.h"

#include "include/core/SkDrawable.h"
#include "include/core/SkVertices.h"
#include "include/gpu/GrBackendSemaphore.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrRecordingContext.h"
#include "include/private/GrImageContext.h"
#include "include/private/SkShadowFlags.h"
#include "include/private/SkVx.h"
#include "include/utils/SkShadowUtils.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkConvertPixels.h"
#include "src/core/SkDrawProcs.h"
#include "src/core/SkDrawShadowInfo.h"
#include "src/core/SkGlyphRunPainter.h"
#include "src/core/SkLatticeIter.h"
#include "src/core/SkMatrixPriv.h"
#include "src/core/SkMatrixProvider.h"
#include "src/core/SkRRectPriv.h"
#include "src/gpu/GrAppliedClip.h"
#include "src/gpu/GrAttachment.h"
#include "src/gpu/GrBlurUtils.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrClip.h"
#include "src/gpu/GrColor.h"
#include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrDrawingManager.h"
#include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrImageContextPriv.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrStencilSettings.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/GrTracing.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrBicubicEffect.h"
#include "src/gpu/effects/GrBlendFragmentProcessor.h"
#include "src/gpu/effects/GrDisableColorXP.h"
#include "src/gpu/effects/GrRRectEffect.h"
#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/geometry/GrQuad.h"
#include "src/gpu/geometry/GrQuadUtils.h"
#include "src/gpu/geometry/GrStyledShape.h"
#include "src/gpu/ops/GrClearOp.h"
#include "src/gpu/ops/GrDrawAtlasOp.h"
#include "src/gpu/ops/GrDrawOp.h"
#include "src/gpu/ops/GrDrawVerticesOp.h"
#include "src/gpu/ops/GrDrawableOp.h"
#include "src/gpu/ops/GrFillRRectOp.h"
#include "src/gpu/ops/GrFillRectOp.h"
#include "src/gpu/ops/GrLatticeOp.h"
#include "src/gpu/ops/GrOp.h"
#include "src/gpu/ops/GrOvalOpFactory.h"
#include "src/gpu/ops/GrRegionOp.h"
#include "src/gpu/ops/GrShadowRRectOp.h"
#include "src/gpu/ops/GrStrokeRectOp.h"
#include "src/gpu/ops/GrTextureOp.h"
#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
#include "src/gpu/text/GrSDFTControl.h"
#include "src/gpu/text/GrTextBlobCache.h"

#if SK_GPU_V1
#include "src/gpu/GrPathRenderer.h"
#endif

#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
#define ASSERT_SINGLE_OWNER        GR_ASSERT_SINGLE_OWNER(this->singleOwner())
#define RETURN_IF_ABANDONED        if (fContext->abandoned()) { return; }
#define RETURN_FALSE_IF_ABANDONED  if (fContext->abandoned()) { return false; }

//////////////////////////////////////////////////////////////////////////////

namespace {

void op_bounds(SkRect* bounds, const GrOp* op) {
    *bounds = op->bounds();
    if (op->hasZeroArea()) {
        if (op->hasAABloat()) {
            bounds->outset(0.5f, 0.5f);
        } else {
            // We don't know which way the particular GPU will snap lines or points at integer
            // coords. So we ensure that the bounds is large enough for either snap.
            SkRect before = *bounds;
            bounds->roundOut(bounds);
            if (bounds->fLeft == before.fLeft) {
                bounds->fLeft -= 1;
            }
            if (bounds->fTop == before.fTop) {
                bounds->fTop -= 1;
            }
            if (bounds->fRight == before.fRight) {
                bounds->fRight += 1;
            }
            if (bounds->fBottom == before.fBottom) {
                bounds->fBottom += 1;
            }
        }
    }
}

} // anonymous namespace

namespace skgpu::v1 {

using DoSimplify = GrStyledShape::DoSimplify;

class AutoCheckFlush {
public:
    AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
        SkASSERT(fDrawingManager);
    }
    ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }

private:
    GrDrawingManager* fDrawingManager;
};

std::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::Make(GrRecordingContext* rContext,
                                                             GrColorType colorType,
                                                             sk_sp<GrSurfaceProxy> proxy,
                                                             sk_sp<SkColorSpace> colorSpace,
                                                             GrSurfaceOrigin origin,
                                                             const SkSurfaceProps& surfaceProps,
                                                             bool flushTimeOpsTask) {
    if (!rContext || !proxy) {
        return nullptr;
    }

    const GrBackendFormat& format = proxy->backendFormat();
    GrSwizzle readSwizzle, writeSwizzle;
    if (colorType != GrColorType::kUnknown) {
        readSwizzle = rContext->priv().caps()->getReadSwizzle(format, colorType);
        writeSwizzle = rContext->priv().caps()->getWriteSwizzle(format, colorType);
    }

    GrSurfaceProxyView readView (           proxy, origin,  readSwizzle);
    GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);

    return std::make_unique<SurfaceDrawContext>(rContext,
                                                std::move(readView),
                                                std::move(writeView),
                                                colorType,
                                                std::move(colorSpace),
                                                surfaceProps,
                                                flushTimeOpsTask);
}

std::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::Make(
        GrRecordingContext* rContext,
        sk_sp<SkColorSpace> colorSpace,
        SkBackingFit fit,
        SkISize dimensions,
        const GrBackendFormat& format,
        int sampleCnt,
        GrMipmapped mipMapped,
        GrProtected isProtected,
        GrSwizzle readSwizzle,
        GrSwizzle writeSwizzle,
        GrSurfaceOrigin origin,
        SkBudgeted budgeted,
        const SkSurfaceProps& surfaceProps) {
    // It is probably not necessary to check if the context is abandoned here since uses of the
    // SurfaceDrawContext which need the context will mostly likely fail later on without an
    // issue. However having this hear adds some reassurance in case there is a path doesn't handle
    // an abandoned context correctly. It also lets us early out of some extra work.
    if (rContext->abandoned()) {
        return nullptr;
    }

    sk_sp<GrTextureProxy> proxy = rContext->priv().proxyProvider()->createProxy(
            format,
            dimensions,
            GrRenderable::kYes,
            sampleCnt,
            mipMapped,
            fit,
            budgeted,
            isProtected);
    if (!proxy) {
        return nullptr;
    }

    GrSurfaceProxyView readView (           proxy, origin,  readSwizzle);
    GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);

    auto sdc = std::make_unique<SurfaceDrawContext>(rContext,
                                                    std::move(readView),
                                                    std::move(writeView),
                                                    GrColorType::kUnknown,
                                                    std::move(colorSpace),
                                                    surfaceProps);
    sdc->discard();
    return sdc;
}

std::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::Make(
        GrRecordingContext* rContext,
        GrColorType colorType,
        sk_sp<SkColorSpace> colorSpace,
        SkBackingFit fit,
        SkISize dimensions,
        const SkSurfaceProps& surfaceProps,
        int sampleCnt,
        GrMipmapped mipMapped,
        GrProtected isProtected,
        GrSurfaceOrigin origin,
        SkBudgeted budgeted) {
    auto format = rContext->priv().caps()->getDefaultBackendFormat(colorType, GrRenderable::kYes);
    if (!format.isValid()) {
        return nullptr;
    }
    sk_sp<GrTextureProxy> proxy = rContext->priv().proxyProvider()->createProxy(format,
                                                                                dimensions,
                                                                                GrRenderable::kYes,
                                                                                sampleCnt,
                                                                                mipMapped,
                                                                                fit,
                                                                                budgeted,
                                                                                isProtected);
    if (!proxy) {
        return nullptr;
    }

    return SurfaceDrawContext::Make(rContext,
                                    colorType,
                                    std::move(proxy),
                                    std::move(colorSpace),
                                    origin,
                                    surfaceProps);
}

std::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::MakeWithFallback(
        GrRecordingContext* rContext,
        GrColorType colorType,
        sk_sp<SkColorSpace> colorSpace,
        SkBackingFit fit,
        SkISize dimensions,
        const SkSurfaceProps& surfaceProps,
        int sampleCnt,
        GrMipmapped mipMapped,
        GrProtected isProtected,
        GrSurfaceOrigin origin,
        SkBudgeted budgeted) {
    const GrCaps* caps = rContext->priv().caps();
    auto [ct, _] = caps->getFallbackColorTypeAndFormat(colorType, sampleCnt);
    if (ct == GrColorType::kUnknown) {
        return nullptr;
    }
    return SurfaceDrawContext::Make(rContext, ct, colorSpace, fit, dimensions, surfaceProps,
                                    sampleCnt, mipMapped, isProtected, origin, budgeted);
}

std::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::MakeFromBackendTexture(
        GrRecordingContext* rContext,
        GrColorType colorType,
        sk_sp<SkColorSpace> colorSpace,
        const GrBackendTexture& tex,
        int sampleCnt,
        GrSurfaceOrigin origin,
        const SkSurfaceProps& surfaceProps,
        sk_sp<GrRefCntedCallback> releaseHelper) {
    SkASSERT(sampleCnt > 0);
    sk_sp<GrTextureProxy> proxy(rContext->priv().proxyProvider()->wrapRenderableBackendTexture(
            tex, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
            std::move(releaseHelper)));
    if (!proxy) {
        return nullptr;
    }

    return SurfaceDrawContext::Make(rContext, colorType, std::move(proxy), std::move(colorSpace),
                                    origin, surfaceProps);
}

// In MDB mode the reffing of the 'getLastOpsTask' call's result allows in-progress
// GrOpsTask to be picked up and added to by SurfaceDrawContexts lower in the call
// stack. When this occurs with a closed GrOpsTask, a new one will be allocated
// when the surfaceDrawContext attempts to use it (via getOpsTask).
SurfaceDrawContext::SurfaceDrawContext(GrRecordingContext* rContext,
                                       GrSurfaceProxyView readView,
                                       GrSurfaceProxyView writeView,
                                       GrColorType colorType,
                                       sk_sp<SkColorSpace> colorSpace,
                                       const SkSurfaceProps& surfaceProps,
                                       bool flushTimeOpsTask)
        : SurfaceFillContext(rContext,
                             std::move(readView),
                             std::move(writeView),
                             {colorType, kPremul_SkAlphaType, std::move(colorSpace)},
                             flushTimeOpsTask)
        , fSurfaceProps(surfaceProps)
        , fCanUseDynamicMSAA(
                (fSurfaceProps.flags() & SkSurfaceProps::kDynamicMSAA_Flag) &&
                rContext->priv().caps()->supportsDynamicMSAA(this->asRenderTargetProxy()))
        , fGlyphPainter(*this) {
    SkDEBUGCODE(this->validate();)
}

SurfaceDrawContext::~SurfaceDrawContext() {
    ASSERT_SINGLE_OWNER
}

void SurfaceDrawContext::willReplaceOpsTask(GrOpsTask* prevTask, GrOpsTask* nextTask) {
    if (prevTask && fNeedsStencil) {
        // Store the stencil values in memory upon completion of fOpsTask.
        prevTask->setMustPreserveStencil();
        // Reload the stencil buffer content at the beginning of newOpsTask.
        // FIXME: Could the topo sort insert a task between these two that modifies the stencil
        // values?
        nextTask->setInitialStencilContent(GrOpsTask::StencilContent::kPreserved);
    }
#if GR_GPU_STATS && GR_TEST_UTILS
    if (fCanUseDynamicMSAA) {
        fContext->priv().dmsaaStats().fNumRenderPasses++;
    }
#endif
}

inline GrAAType SurfaceDrawContext::chooseAAType(GrAA aa) {
    if (fCanUseDynamicMSAA) {
        // Always trigger DMSAA when it's available. The coverage ops that know how to handle both
        // single and multisample targets without popping will do so without calling chooseAAType.
        return GrAAType::kMSAA;
    }
    if (GrAA::kNo == aa) {
        // On some devices we cannot disable MSAA if it is enabled so we make the AA type reflect
        // that.
        if (this->numSamples() > 1 && !this->caps()->multisampleDisableSupport()) {
            return GrAAType::kMSAA;
        }
        return GrAAType::kNone;
    }
    return (this->numSamples() > 1) ? GrAAType::kMSAA : GrAAType::kCoverage;
}

void SurfaceDrawContext::drawGlyphRunListNoCache(const GrClip* clip,
                                                 const SkMatrixProvider& viewMatrix,
                                                 const SkGlyphRunList& glyphRunList,
                                                 const SkPaint& paint) {
    GrSDFTControl control =
            fContext->priv().getSDFTControl(fSurfaceProps.isUseDeviceIndependentFonts());
    const SkPoint drawOrigin = glyphRunList.origin();
    SkMatrix drawMatrix = viewMatrix.localToDevice();
    drawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
    GrSubRunAllocator* const alloc = this->subRunAlloc();

    for (auto& glyphRun : glyphRunList) {
        GrSubRunNoCachePainter painter{this, alloc, clip, viewMatrix, glyphRunList, paint};

        // Make and add the text ops.
        fGlyphPainter.processGlyphRun(glyphRun,
                                      drawMatrix,
                                      paint,
                                      control,
                                      &painter);
    }
}

void SurfaceDrawContext::drawGlyphRunListWithCache(const GrClip* clip,
                                                   const SkMatrixProvider& viewMatrix,
                                                   const SkGlyphRunList& glyphRunList,
                                                   const SkPaint& paint) {
    SkMatrix drawMatrix(viewMatrix.localToDevice());
    drawMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());

    GrSDFTControl control =
            this->recordingContext()->priv().getSDFTControl(
                    this->surfaceProps().isUseDeviceIndependentFonts());

    auto [canCache, key] = GrTextBlob::Key::Make(glyphRunList,
                                                 paint,
                                                 fSurfaceProps,
                                                 this->colorInfo(),
                                                 drawMatrix,
                                                 control);

    sk_sp<GrTextBlob> blob;
    GrTextBlobCache* textBlobCache = fContext->priv().getTextBlobCache();
    if (canCache) {
        blob = textBlobCache->find(key);
    }

    if (blob == nullptr || !blob->canReuse(paint, drawMatrix)) {
        if (blob != nullptr) {
            // We have to remake the blob because changes may invalidate our masks.
            // TODO we could probably get away with reuse most of the time if the pointer is unique,
            //      but we'd have to clear the SubRun information
            textBlobCache->remove(blob.get());
        }

        blob = GrTextBlob::Make(glyphRunList, paint, drawMatrix, control, &fGlyphPainter);

        if (canCache) {
            blob->addKey(key);
            // The blob may already have been created on a different thread. Use the first one
            // that was there.
            blob = textBlobCache->addOrReturnExisting(glyphRunList, blob);
        }
    }

    for (const GrSubRun& subRun : blob->subRunList()) {
        subRun.draw(clip, viewMatrix, glyphRunList, paint, this);
    }
}

// choose to use the GrTextBlob cache or not.
bool gGrDrawTextNoCache = false;
void SurfaceDrawContext::drawGlyphRunList(const GrClip* clip,
                                          const SkMatrixProvider& viewMatrix,
                                          const SkGlyphRunList& glyphRunList,
                                          const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawGlyphRunList", fContext);

    // Drawing text can cause us to do inline uploads. This is not supported for wrapped vulkan
    // secondary command buffers because it would require stopping and starting a render pass which
    // we don't have access to.
    if (this->wrapsVkSecondaryCB()) {
        return;
    }

    if (gGrDrawTextNoCache || glyphRunList.blob() == nullptr) {
        // If the glyphRunList does not have an associated text blob, then it was created by one of
        // the direct draw APIs (drawGlyphs, etc.). There is no need to create a GrTextBlob just
        // build the sub run directly and place it in the op.
        this->drawGlyphRunListNoCache(clip, viewMatrix, glyphRunList, paint);
    } else {
        this->drawGlyphRunListWithCache(clip, viewMatrix, glyphRunList, paint);
    }
}

void SurfaceDrawContext::drawPaint(const GrClip* clip,
                                   GrPaint&& paint,
                                   const SkMatrix& viewMatrix) {
    // Start with the render target, since that is the maximum content we could possibly fill.
    // drawFilledQuad() will automatically restrict it to clip bounds for us if possible.
    if (!paint.numTotalFragmentProcessors()) {
        // The paint is trivial so we won't need to use local coordinates, so skip calculating the
        // inverse view matrix.
        SkRect r = this->asSurfaceProxy()->getBoundsRect();
        this->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), r, r);
    } else {
        // Use the inverse view matrix to arrive at appropriate local coordinates for the paint.
        SkMatrix localMatrix;
        if (!viewMatrix.invert(&localMatrix)) {
            return;
        }
        SkIRect bounds = SkIRect::MakeSize(this->asSurfaceProxy()->dimensions());
        this->fillPixelsWithLocalMatrix(clip, std::move(paint), bounds, localMatrix);
    }
}

enum class SurfaceDrawContext::QuadOptimization {
    // The rect to draw doesn't intersect clip or render target, so no draw op should be added
    kDiscarded,
    // The rect to draw was converted to some other op and appended to the oplist, so no additional
    // op is necessary. Currently this can convert it to a clear op or a rrect op. Only valid if
    // a constColor is provided.
    kSubmitted,
    // The clip was folded into the device quad, with updated edge flags and local coords, and
    // caller is responsible for adding an appropriate op.
    kClipApplied,
    // No change to clip, but quad updated to better fit clip/render target, and caller is
    // responsible for adding an appropriate op.
    kCropped
};

SurfaceDrawContext::QuadOptimization SurfaceDrawContext::attemptQuadOptimization(
        const GrClip* clip, const GrUserStencilSettings* stencilSettings, GrAA* aa, DrawQuad* quad,
        GrPaint* paint) {
    // Optimization requirements:
    // 1. kDiscard applies when clip bounds and quad bounds do not intersect
    // 2a. kSubmitted applies when constColor and final geom is pixel aligned rect;
    //       pixel aligned rect requires rect clip and (rect quad or quad covers clip) OR
    // 2b. kSubmitted applies when constColor and rrect clip and quad covers clip
    // 4. kClipApplied applies when rect clip and (rect quad or quad covers clip)
    // 5. kCropped in all other scenarios (although a crop may be a no-op)
    const SkPMColor4f* constColor = nullptr;
    SkPMColor4f paintColor;
    if (!stencilSettings && paint && !paint->hasCoverageFragmentProcessor() &&
        paint->isConstantBlendedColor(&paintColor)) {
        // Only consider clears/rrects when it's easy to guarantee 100% fill with single color
        constColor = &paintColor;
    }

    // Save the old AA flags since CropToRect will modify 'quad' and if kCropped is returned, it's
    // better to just keep the old flags instead of introducing mixed edge flags.
    GrQuadAAFlags oldFlags = quad->fEdgeFlags;

    // Use the logical size of the render target, which allows for "fullscreen" clears even if
    // the render target has an approximate backing fit
    SkRect rtRect = this->asSurfaceProxy()->getBoundsRect();

    SkRect drawBounds = quad->fDevice.bounds();
    if (!quad->fDevice.isFinite() || drawBounds.isEmpty() ||
        GrClip::IsOutsideClip(rtRect, drawBounds)) {
        return QuadOptimization::kDiscarded;
    } else if (GrQuadUtils::WillUseHairline(quad->fDevice, GrAAType::kCoverage, quad->fEdgeFlags)) {
        // Don't try to apply the clip early if we know rendering will use hairline methods, as this
        // has an effect on the op bounds not otherwise taken into account in this function.
        return QuadOptimization::kCropped;
    }

    auto conservativeCrop = [&]() {
        static constexpr int kLargeDrawLimit = 15000;
        // Crop the quad to the render target. This doesn't change the visual results of drawing but
        // is meant to help numerical stability for excessively large draws.
        if (drawBounds.width() > kLargeDrawLimit || drawBounds.height() > kLargeDrawLimit) {
            GrQuadUtils::CropToRect(rtRect, *aa, quad, /* compute local */ !constColor);
        }
    };

    bool simpleColor = !stencilSettings && constColor;
    GrClip::PreClipResult result = clip ? clip->preApply(drawBounds, *aa)
                                        : GrClip::PreClipResult(GrClip::Effect::kUnclipped);
    switch(result.fEffect) {
        case GrClip::Effect::kClippedOut:
            return QuadOptimization::kDiscarded;
        case GrClip::Effect::kUnclipped:
            if (!simpleColor) {
                conservativeCrop();
                return QuadOptimization::kClipApplied;
            } else {
                // Update result to store the render target bounds in order and then fall
                // through to attempt the draw->native clear optimization
                result = GrClip::PreClipResult(SkRRect::MakeRect(rtRect), *aa);
            }
            break;
        case GrClip::Effect::kClipped:
            if (!result.fIsRRect || (stencilSettings && result.fAA != *aa) ||
                (!result.fRRect.isRect() && !simpleColor)) {
                // The clip and draw state are too complicated to try and reduce
                conservativeCrop();
                return QuadOptimization::kCropped;
            } // Else fall through to attempt to combine the draw and clip geometry together
            break;
        default:
            SkUNREACHABLE;
    }

    // If we reached here, we know we're an axis-aligned clip that is either a rect or a round rect,
    // so we can potentially combine it with the draw geometry so that no clipping is needed.
    SkASSERT(result.fEffect == GrClip::Effect::kClipped && result.fIsRRect);
    SkRect clippedBounds = result.fRRect.getBounds();
    clippedBounds.intersect(rtRect);
    if (!drawBounds.intersect(clippedBounds)) {
        // Our fractional bounds aren't actually inside the clip. GrClip::preApply() can sometimes
        // think in terms of rounded-out bounds. Discard the draw.
        return QuadOptimization::kDiscarded;
    }
    // Guard against the clipped draw turning into a hairline draw after intersection
    if (drawBounds.width() < 1.f || drawBounds.height() < 1.f) {
        return QuadOptimization::kCropped;
    }

    if (result.fRRect.isRect()) {
        // No rounded corners, so we might be able to become a native clear or we might be able to
        // modify geometry and edge flags to represent intersected shape of clip and draw.
        if (GrQuadUtils::CropToRect(clippedBounds, result.fAA, quad,
                                    /*compute local*/ !constColor)) {
            if (simpleColor && quad->fDevice.quadType() == GrQuad::Type::kAxisAligned) {
                // Clear optimization is possible
                drawBounds = quad->fDevice.bounds();
                if (drawBounds.contains(rtRect)) {
                    // Fullscreen clear
                    this->clear(*constColor);
                    return QuadOptimization::kSubmitted;
                } else if (GrClip::IsPixelAligned(drawBounds) &&
                           drawBounds.width() > 256 && drawBounds.height() > 256) {
                    // Scissor + clear (round shouldn't do anything since we are pixel aligned)
                    SkIRect scissorRect;
                    drawBounds.round(&scissorRect);
                    this->clear(scissorRect, *constColor);
                    return QuadOptimization::kSubmitted;
                }
            }

            // else the draw and clip were combined so just update the AA to reflect combination
            if (*aa == GrAA::kNo && result.fAA == GrAA::kYes &&
                quad->fEdgeFlags != GrQuadAAFlags::kNone) {
                // The clip was anti-aliased and now the draw needs to be upgraded to AA to
                // properly reflect the smooth edge of the clip.
                *aa = GrAA::kYes;
            }
            // We intentionally do not downgrade AA here because we don't know if we need to
            // preserve MSAA (see GrQuadAAFlags docs). But later in the pipeline, the ops can
            // use GrResolveAATypeForQuad() to turn off coverage AA when all flags are off.
            // deviceQuad is exactly the intersection of original quad and clip, so it can be
            // drawn with no clip (submitted by caller)
            return QuadOptimization::kClipApplied;
        }
    } else {
        // Rounded corners and constant filled color (limit ourselves to solid colors because
        // there is no way to use custom local coordinates with drawRRect).
        SkASSERT(simpleColor);
        if (GrQuadUtils::CropToRect(clippedBounds, result.fAA, quad,
                                    /* compute local */ false) &&
            quad->fDevice.quadType() == GrQuad::Type::kAxisAligned &&
            quad->fDevice.bounds().contains(clippedBounds)) {
            // Since the cropped quad became a rectangle which covered the bounds of the rrect,
            // we can draw the rrect directly and ignore the edge flags
            this->drawRRect(nullptr, std::move(*paint), result.fAA, SkMatrix::I(), result.fRRect,
                            GrStyle::SimpleFill());
            return QuadOptimization::kSubmitted;
        }
    }

    // The quads have been updated to better fit the clip bounds, but can't get rid of
    // the clip entirely
    quad->fEdgeFlags = oldFlags;
    return QuadOptimization::kCropped;
}

void SurfaceDrawContext::drawFilledQuad(const GrClip* clip,
                                        GrPaint&& paint,
                                        GrAA aa,
                                        DrawQuad* quad,
                                        const GrUserStencilSettings* ss) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawFilledQuad", fContext);

    AutoCheckFlush acf(this->drawingManager());

    QuadOptimization opt = this->attemptQuadOptimization(clip, ss, &aa, quad, &paint);
    if (opt >= QuadOptimization::kClipApplied) {
        // These optimizations require caller to add an op themselves
        const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip;
        GrAAType aaType;
        if (ss) {
            aaType = (aa == GrAA::kYes) ? GrAAType::kMSAA : GrAAType::kNone;
        } else if (fCanUseDynamicMSAA && aa == GrAA::kNo) {
            // The SkGpuDevice ensures GrAA is always kYes when using dmsaa. If the caller calls
            // into here with GrAA::kNo, trust that they know what they're doing and that the
            // rendering will be equal with or without msaa.
            aaType = GrAAType::kNone;
        } else {
            aaType = this->chooseAAType(aa);
        }
        this->addDrawOp(finalClip, GrFillRectOp::Make(fContext, std::move(paint), aaType,
                                                      quad, ss));
    }
    // All other optimization levels were completely handled inside attempt(), so no extra op needed
}

void SurfaceDrawContext::drawTexture(const GrClip* clip,
                                     GrSurfaceProxyView view,
                                     SkAlphaType srcAlphaType,
                                     GrSamplerState::Filter filter,
                                     GrSamplerState::MipmapMode mm,
                                     SkBlendMode blendMode,
                                     const SkPMColor4f& color,
                                     const SkRect& srcRect,
                                     const SkRect& dstRect,
                                     GrAA aa,
                                     GrQuadAAFlags edgeAA,
                                     SkCanvas::SrcRectConstraint constraint,
                                     const SkMatrix& viewMatrix,
                                     sk_sp<GrColorSpaceXform> colorSpaceXform) {
    // If we are using dmsaa then go through GrFillRRectOp (via fillRectToRect).
    if ((this->alwaysAntialias() || this->caps()->reducedShaderMode()) && aa == GrAA::kYes) {
        GrPaint paint;
        paint.setColor4f(color);
        std::unique_ptr<GrFragmentProcessor> fp;
        if (constraint == SkCanvas::kStrict_SrcRectConstraint) {
            fp = GrTextureEffect::MakeSubset(view, srcAlphaType, SkMatrix::I(),
                                             GrSamplerState(filter, mm), srcRect,
                                             *this->caps());
        } else {
            fp = GrTextureEffect::Make(view, srcAlphaType, SkMatrix::I(), filter, mm);
        }
        if (colorSpaceXform) {
            fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(colorSpaceXform));
        }
        fp = GrBlendFragmentProcessor::Make(std::move(fp), nullptr, SkBlendMode::kModulate);
        paint.setColorFragmentProcessor(std::move(fp));
        if (blendMode != SkBlendMode::kSrcOver) {
            paint.setXPFactory(SkBlendMode_AsXPFactory(blendMode));
        }
        this->fillRectToRect(clip, std::move(paint), GrAA::kYes, viewMatrix, dstRect, srcRect);
        return;
    }

    const SkRect* subset = constraint == SkCanvas::kStrict_SrcRectConstraint ?
            &srcRect : nullptr;
    DrawQuad quad{GrQuad::MakeFromRect(dstRect, viewMatrix), GrQuad(srcRect), edgeAA};

    this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(colorSpaceXform), filter,
                           mm, color, blendMode, aa, &quad, subset);
}

void SurfaceDrawContext::drawTexturedQuad(const GrClip* clip,
                                          GrSurfaceProxyView proxyView,
                                          SkAlphaType srcAlphaType,
                                          sk_sp<GrColorSpaceXform> textureXform,
                                          GrSamplerState::Filter filter,
                                          GrSamplerState::MipmapMode mm,
                                          const SkPMColor4f& color,
                                          SkBlendMode blendMode,
                                          GrAA aa,
                                          DrawQuad* quad,
                                          const SkRect* subset) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    SkASSERT(proxyView.asTextureProxy());
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawTexturedQuad", fContext);

    AutoCheckFlush acf(this->drawingManager());

    // Functionally this is very similar to drawFilledQuad except that there's no constColor to
    // enable the kSubmitted optimizations, no stencil settings support, and its a GrTextureOp.
    QuadOptimization opt = this->attemptQuadOptimization(clip, nullptr/*stencil*/, &aa, quad,
                                                         nullptr/*paint*/);

    SkASSERT(opt != QuadOptimization::kSubmitted);
    if (opt != QuadOptimization::kDiscarded) {
        // And the texture op if not discarded
        const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip;
        GrAAType aaType = this->chooseAAType(aa);
        auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
        auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
                                                          : GrTextureOp::Saturate::kNo;
        // Use the provided subset, although hypothetically we could detect that the cropped local
        // quad is sufficiently inside the subset and the constraint could be dropped.
        this->addDrawOp(finalClip,
                        GrTextureOp::Make(fContext, std::move(proxyView), srcAlphaType,
                                          std::move(textureXform), filter, mm, color, saturate,
                                          blendMode, aaType, quad, subset));
    }
}

void SurfaceDrawContext::drawRect(const GrClip* clip,
                                  GrPaint&& paint,
                                  GrAA aa,
                                  const SkMatrix& viewMatrix,
                                  const SkRect& rect,
                                  const GrStyle* style) {
    if (!style) {
        style = &GrStyle::SimpleFill();
    }
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawRect", fContext);

    // Path effects should've been devolved to a path in SkGpuDevice
    SkASSERT(!style->pathEffect());

    AutoCheckFlush acf(this->drawingManager());

    const SkStrokeRec& stroke = style->strokeRec();
    if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
        // Fills the rect, using rect as its own local coordinates
        this->fillRectToRect(clip, std::move(paint), aa, viewMatrix, rect, rect);
        return;
    } else if ((stroke.getStyle() == SkStrokeRec::kStroke_Style ||
                stroke.getStyle() == SkStrokeRec::kHairline_Style) &&
               rect.width()                                        &&
               rect.height()                                       &&
               !this->caps()->reducedShaderMode()) {
        // Only use the StrokeRectOp for non-empty rectangles. Empty rectangles will be processed by
        // GrStyledShape to handle stroke caps and dashing properly.
        //
        // http://skbug.com/12206 -- there is a double-blend issue with the bevel version of
        // AAStrokeRectOp, and if we increase the AA bloat for MSAA it becomes more pronounced.
        // Don't use the bevel version with DMSAA.
        GrAAType aaType = (fCanUseDynamicMSAA &&
                           stroke.getJoin() == SkPaint::kMiter_Join &&
                           stroke.getMiter() >= SK_ScalarSqrt2) ? GrAAType::kCoverage
                                                                : this->chooseAAType(aa);
        GrOp::Owner op = GrStrokeRectOp::Make(
                fContext, std::move(paint), aaType, viewMatrix, rect, stroke);
        // op may be null if the stroke is not supported or if using coverage aa and the view matrix
        // does not preserve rectangles.
        if (op) {
            this->addDrawOp(clip, std::move(op));
            return;
        }
    }
    assert_alive(paint);
    this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
                                     GrStyledShape(rect, *style, DoSimplify::kNo));
}

void SurfaceDrawContext::fillRectToRect(const GrClip* clip,
                                        GrPaint&& paint,
                                        GrAA aa,
                                        const SkMatrix& viewMatrix,
                                        const SkRect& rectToDraw,
                                        const SkRect& localRect) {
    DrawQuad quad{GrQuad::MakeFromRect(rectToDraw, viewMatrix), GrQuad(localRect),
                  aa == GrAA::kYes ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone};

    // If we are using dmsaa then attempt to draw the rect with GrFillRRectOp.
    if ((fContext->priv().caps()->reducedShaderMode() || this->alwaysAntialias()) &&
        this->caps()->drawInstancedSupport()                                      &&
        aa == GrAA::kYes) {  // If aa is kNo when using dmsaa, the rect is axis aligned. Don't use
                             // GrFillRRectOp because it might require dual source blending.
                             // http://skbug.com/11756
        QuadOptimization opt = this->attemptQuadOptimization(clip, nullptr/*stencil*/, &aa, &quad,
                                                             &paint);
        if (opt < QuadOptimization::kClipApplied) {
            // The optimization was completely handled inside attempt().
            return;
        }

        SkRect croppedRect, croppedLocal{};
        const GrClip* optimizedClip = clip;
        if (clip && viewMatrix.isScaleTranslate() && quad.fDevice.asRect(&croppedRect) &&
            (!paint.usesLocalCoords() || quad.fLocal.asRect(&croppedLocal))) {
            // The cropped quad is still a rect, and our view matrix preserves rects. Map it back
            // to pre-matrix space.
            SkMatrix inverse;
            if (!viewMatrix.invert(&inverse)) {
                return;
            }
            SkASSERT(inverse.rectStaysRect());
            inverse.mapRect(&croppedRect);
            if (opt == QuadOptimization::kClipApplied) {
                optimizedClip = nullptr;
            }
        } else {
            // Even if attemptQuadOptimization gave us an optimized quad, GrFillRRectOp needs a rect
            // in pre-matrix space, so use the original rect. Also preserve the original clip.
            croppedRect = rectToDraw;
            croppedLocal = localRect;
        }

        if (auto op = GrFillRRectOp::Make(fContext, this->arenaAlloc(), std::move(paint),
                                          viewMatrix, SkRRect::MakeRect(croppedRect), croppedLocal,
                                          GrAA::kYes)) {
            this->addDrawOp(optimizedClip, std::move(op));
            return;
        }
    }

    assert_alive(paint);
    this->drawFilledQuad(clip, std::move(paint), aa, &quad);
}

void SurfaceDrawContext::drawQuadSet(const GrClip* clip,
                                     GrPaint&& paint,
                                     GrAA aa,
                                     const SkMatrix& viewMatrix,
                                     const GrQuadSetEntry quads[],
                                     int cnt) {
    GrAAType aaType = this->chooseAAType(aa);

    GrFillRectOp::AddFillRectOps(this, clip, fContext, std::move(paint), aaType, viewMatrix,
                                 quads, cnt);
}

int SurfaceDrawContext::maxWindowRectangles() const {
    return this->asRenderTargetProxy()->maxWindowRectangles(*this->caps());
}

GrOpsTask::CanDiscardPreviousOps SurfaceDrawContext::canDiscardPreviousOpsOnFullClear() const {
#if GR_TEST_UTILS
    if (fPreserveOpsOnFullClear_TestingOnly) {
        return GrOpsTask::CanDiscardPreviousOps::kNo;
    }
#endif
    // Regardless of how the clear is implemented (native clear or a fullscreen quad), all prior ops
    // would normally be overwritten. The one exception is if the render target context is marked as
    // needing a stencil buffer then there may be a prior op that writes to the stencil buffer.
    // Although the clear will ignore the stencil buffer, following draw ops may not so we can't get
    // rid of all the preceding ops. Beware! If we ever add any ops that have a side effect beyond
    // modifying the stencil buffer we will need a more elaborate tracking system (skbug.com/7002).
    return GrOpsTask::CanDiscardPreviousOps(!fNeedsStencil);
}

void SurfaceDrawContext::setNeedsStencil() {
    // Don't clear stencil until after we've set fNeedsStencil. This ensures we don't loop forever
    // in the event that there are driver bugs and we need to clear as a draw.
    bool hasInitializedStencil = fNeedsStencil;
    fNeedsStencil = true;
    if (!hasInitializedStencil) {
        this->asRenderTargetProxy()->setNeedsStencil();
        if (this->caps()->performStencilClearsAsDraws()) {
            // There is a driver bug with clearing stencil. We must use an op to manually clear the
            // stencil buffer before the op that required 'setNeedsStencil'.
            this->internalStencilClear(nullptr, /* inside mask */ false);
        } else {
            this->getOpsTask()->setInitialStencilContent(
                    GrOpsTask::StencilContent::kUserBitsCleared);
        }
    }
}

void SurfaceDrawContext::internalStencilClear(const SkIRect* scissor, bool insideStencilMask) {
    this->setNeedsStencil();

    GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions());
    if (scissor && !scissorState.set(*scissor)) {
        // The requested clear region is off screen, so nothing to do.
        return;
    }

    bool clearWithDraw = this->caps()->performStencilClearsAsDraws() ||
                         (scissorState.enabled() && this->caps()->performPartialClearsAsDraws());
    if (clearWithDraw) {
        const GrUserStencilSettings* ss = GrStencilSettings::SetClipBitSettings(insideStencilMask);

        // Configure the paint to have no impact on the color buffer
        GrPaint paint;
        paint.setXPFactory(GrDisableColorXPFactory::Get());
        this->addDrawOp(nullptr,
                        GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
                                                    SkRect::Make(scissorState.rect()), ss));
    } else {
        this->addOp(GrClearOp::MakeStencilClip(fContext, scissorState, insideStencilMask));
    }
}

bool SurfaceDrawContext::stencilPath(const GrHardClip* clip,
                                     GrAA doStencilMSAA,
                                     const SkMatrix& viewMatrix,
                                     const SkPath& path) {
#if SK_GPU_V1
    SkIRect clipBounds = clip ? clip->getConservativeBounds()
                              : SkIRect::MakeSize(this->dimensions());
    GrStyledShape shape(path, GrStyledShape::DoSimplify::kNo);

    GrPathRenderer::CanDrawPathArgs canDrawArgs;
    canDrawArgs.fCaps = fContext->priv().caps();
    canDrawArgs.fProxy = this->asRenderTargetProxy();
    canDrawArgs.fClipConservativeBounds = &clipBounds;
    canDrawArgs.fViewMatrix = &viewMatrix;
    canDrawArgs.fShape = &shape;
    canDrawArgs.fPaint = nullptr;
    canDrawArgs.fSurfaceProps = &fSurfaceProps;
    canDrawArgs.fAAType = (doStencilMSAA == GrAA::kYes) ? GrAAType::kMSAA : GrAAType::kNone;
    canDrawArgs.fHasUserStencilSettings = false;
    GrPathRenderer* pr = this->drawingManager()->getPathRenderer(
            canDrawArgs, false, GrPathRendererChain::DrawType::kStencil);
    if (!pr) {
        SkDebugf("WARNING: No path renderer to stencil path.\n");
        return false;
    }

    GrPathRenderer::StencilPathArgs args;
    args.fContext = fContext;
    args.fSurfaceDrawContext = this;
    args.fClip = clip;
    args.fClipConservativeBounds = &clipBounds;
    args.fViewMatrix = &viewMatrix;
    args.fShape = &shape;
    args.fDoStencilMSAA = doStencilMSAA;
    pr->stencilPath(args);
    return true;
#else
    return false;
#endif // SK_GPU_V1
}

void SurfaceDrawContext::drawTextureSet(const GrClip* clip,
                                        GrTextureSetEntry set[],
                                        int cnt,
                                        int proxyRunCnt,
                                        GrSamplerState::Filter filter,
                                        GrSamplerState::MipmapMode mm,
                                        SkBlendMode mode,
                                        GrAA aa,
                                        SkCanvas::SrcRectConstraint constraint,
                                        const SkMatrix& viewMatrix,
                                        sk_sp<GrColorSpaceXform> texXform) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawTextureSet", fContext);

    // Create the minimum number of GrTextureOps needed to draw this set. Individual
    // GrTextureOps can rebind the texture between draws thus avoiding GrPaint (re)creation.
    AutoCheckFlush acf(this->drawingManager());
    GrAAType aaType = this->chooseAAType(aa);
    auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
    auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
                                                      : GrTextureOp::Saturate::kNo;
    GrTextureOp::AddTextureSetOps(this, clip, fContext, set, cnt, proxyRunCnt, filter, mm, saturate,
                                  mode, aaType, constraint, viewMatrix, std::move(texXform));
}

void SurfaceDrawContext::drawVertices(const GrClip* clip,
                                      GrPaint&& paint,
                                      const SkMatrixProvider& matrixProvider,
                                      sk_sp<SkVertices> vertices,
                                      GrPrimitiveType* overridePrimType,
                                      const SkRuntimeEffect* effect) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawVertices", fContext);

    AutoCheckFlush acf(this->drawingManager());

    SkASSERT(vertices);
    GrAAType aaType = fCanUseDynamicMSAA ? GrAAType::kMSAA : this->chooseAAType(GrAA::kNo);
    GrOp::Owner op =
            GrDrawVerticesOp::Make(fContext, std::move(paint), std::move(vertices), matrixProvider,
                                   aaType, this->colorInfo().refColorSpaceXformFromSRGB(),
                                   overridePrimType, effect);
    this->addDrawOp(clip, std::move(op));
}

///////////////////////////////////////////////////////////////////////////////

void SurfaceDrawContext::drawAtlas(const GrClip* clip,
                                   GrPaint&& paint,
                                   const SkMatrix& viewMatrix,
                                   int spriteCount,
                                   const SkRSXform xform[],
                                   const SkRect texRect[],
                                   const SkColor colors[]) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawAtlas", fContext);

    AutoCheckFlush acf(this->drawingManager());

    GrAAType aaType = this->chooseAAType(GrAA::kNo);
    GrOp::Owner op = GrDrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
                                         aaType, spriteCount, xform, texRect, colors);
    this->addDrawOp(clip, std::move(op));
}

///////////////////////////////////////////////////////////////////////////////

void SurfaceDrawContext::drawRRect(const GrClip* origClip,
                                   GrPaint&& paint,
                                   GrAA aa,
                                   const SkMatrix& viewMatrix,
                                   const SkRRect& rrect,
                                   const GrStyle& style) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawRRect", fContext);

    SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice

    const SkStrokeRec& stroke = style.strokeRec();
    if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.isEmpty()) {
       return;
    }

    const GrClip* clip = origClip;
    // It is not uncommon to clip to a round rect and then draw that same round rect. Since our
    // lower level clip code works from op bounds, which are SkRects, it doesn't detect that the
    // clip can be ignored. The following test attempts to mitigate the stencil clip cost but only
    // works for axis-aligned round rects. This also only works for filled rrects since the stroke
    // width outsets beyond the rrect itself.
    // TODO: skbug.com/10462 - There was mixed performance wins and regressions when this
    // optimization was turned on outside of Android Framework. I (michaelludwig) believe this is
    // do to the overhead in determining if an SkClipStack is just a rrect. Once that is improved,
    // re-enable this and see if we avoid the regressions.
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    SkRRect devRRect;
    if (clip && stroke.getStyle() == SkStrokeRec::kFill_Style &&
        rrect.transform(viewMatrix, &devRRect)) {
        GrClip::PreClipResult result = clip->preApply(devRRect.getBounds(), aa);
        switch(result.fEffect) {
            case GrClip::Effect::kClippedOut:
                return;
            case GrClip::Effect::kUnclipped:
                clip = nullptr;
                break;
            case GrClip::Effect::kClipped:
                // Currently there's no general-purpose rrect-to-rrect contains function, and if we
                // got here, we know the devRRect's bounds aren't fully contained by the clip.
                // Testing for equality between the two is a reasonable stop-gap for now.
                if (result.fIsRRect && result.fRRect == devRRect) {
                    // NOTE: On the android framework, we allow this optimization even when the clip
                    // is non-AA and the draw is AA.
                    if (result.fAA == aa || (result.fAA == GrAA::kNo && aa == GrAA::kYes)) {
                        clip = nullptr;
                    }
                }
                break;
            default:
                SkUNREACHABLE;
        }
    }
#endif

    AutoCheckFlush acf(this->drawingManager());

    GrAAType aaType = this->chooseAAType(aa);

    GrOp::Owner op;
    if (aaType == GrAAType::kCoverage                          &&
        !fCanUseDynamicMSAA                                    &&
        !this->caps()->reducedShaderMode()                     &&
        rrect.isSimple()                                       &&
        rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY &&
        viewMatrix.rectStaysRect() && viewMatrix.isSimilarity()) {
        // In specific cases we use a dedicated circular round rect op to try and get better perf.
        assert_alive(paint);
        op = GrOvalOpFactory::MakeCircularRRectOp(fContext, std::move(paint), viewMatrix, rrect,
                                                  stroke, this->caps()->shaderCaps());
    }
    if (!op && style.isSimpleFill()) {
        assert_alive(paint);
        op = GrFillRRectOp::Make(fContext, this->arenaAlloc(), std::move(paint), viewMatrix, rrect,
                                 rrect.rect(), GrAA(aaType != GrAAType::kNone));
    }
    if (!op && (aaType == GrAAType::kCoverage || fCanUseDynamicMSAA)) {
        assert_alive(paint);
        op = GrOvalOpFactory::MakeRRectOp(
                fContext, std::move(paint), viewMatrix, rrect, stroke, this->caps()->shaderCaps());
    }
    if (op) {
        this->addDrawOp(clip, std::move(op));
        return;
    }

    assert_alive(paint);
    this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
                                     GrStyledShape(rrect, style, DoSimplify::kNo));
}

///////////////////////////////////////////////////////////////////////////////

bool SurfaceDrawContext::drawFastShadow(const GrClip* clip,
                                        const SkMatrix& viewMatrix,
                                        const SkPath& path,
                                        const SkDrawShadowRec& rec) {
    ASSERT_SINGLE_OWNER
    if (fContext->abandoned()) {
        return true;
    }
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawFastShadow", fContext);

    // check z plane
    bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) ||
                               !SkScalarNearlyZero(rec.fZPlaneParams.fY));
    bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
    if (tiltZPlane || skipAnalytic || !viewMatrix.rectStaysRect() || !viewMatrix.isSimilarity()) {
        return false;
    }

    SkRRect rrect;
    SkRect rect;
    // we can only handle rects, circles, and simple rrects with circular corners
    bool isRRect = path.isRRect(&rrect) && SkRRectPriv::IsNearlySimpleCircular(rrect) &&
                   rrect.getSimpleRadii().fX > SK_ScalarNearlyZero;
    if (!isRRect &&
        path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
        rect.width() > SK_ScalarNearlyZero) {
        rrect.setOval(rect);
        isRRect = true;
    }
    if (!isRRect && path.isRect(&rect)) {
        rrect.setRect(rect);
        isRRect = true;
    }

    if (!isRRect) {
        return false;
    }

    if (rrect.isEmpty()) {
        return true;
    }

    AutoCheckFlush acf(this->drawingManager());

    SkPoint3 devLightPos = rec.fLightPos;
    bool directional = SkToBool(rec.fFlags & kDirectionalLight_ShadowFlag);
    if (!directional) {
        // transform light
        viewMatrix.mapPoints((SkPoint*)&devLightPos.fX, 1);
    }

    // 1/scale
    SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ?
        SkScalarInvert(SkScalarAbs(viewMatrix[SkMatrix::kMScaleX])) :
        sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] +
                       viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]);

    SkScalar occluderHeight = rec.fZPlaneParams.fZ;
    bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);

    if (SkColorGetA(rec.fAmbientColor) > 0) {
        SkScalar devSpaceInsetWidth = SkDrawShadowMetrics::AmbientBlurRadius(occluderHeight);
        const SkScalar umbraRecipAlpha = SkDrawShadowMetrics::AmbientRecipAlpha(occluderHeight);
        const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha;

        // Outset the shadow rrect to the border of the penumbra
        SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale;
        SkRRect ambientRRect;
        SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset);
        // If the rrect was an oval then its outset will also be one.
        // We set it explicitly to avoid errors.
        if (rrect.isOval()) {
            ambientRRect = SkRRect::MakeOval(outsetRect);
        } else {
            SkScalar outsetRad = SkRRectPriv::GetSimpleRadii(rrect).fX + ambientPathOutset;
            ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
        }

        GrColor ambientColor = SkColorToPremulGrColor(rec.fAmbientColor);
        if (transparent) {
            // set a large inset to force a fill
            devSpaceInsetWidth = ambientRRect.width();
        }

        GrOp::Owner op = GrShadowRRectOp::Make(fContext,
                                               ambientColor,
                                               viewMatrix,
                                               ambientRRect,
                                               devSpaceAmbientBlur,
                                               devSpaceInsetWidth);
        if (op) {
            this->addDrawOp(clip, std::move(op));
        }
    }

    if (SkColorGetA(rec.fSpotColor) > 0) {
        SkScalar devSpaceSpotBlur;
        SkScalar spotScale;
        SkVector spotOffset;
        if (directional) {
            SkDrawShadowMetrics::GetDirectionalParams(occluderHeight, devLightPos.fX,
                                                      devLightPos.fY, devLightPos.fZ,
                                                      rec.fLightRadius, &devSpaceSpotBlur,
                                                      &spotScale, &spotOffset);
        } else {
            SkDrawShadowMetrics::GetSpotParams(occluderHeight, devLightPos.fX, devLightPos.fY,
                                               devLightPos.fZ, rec.fLightRadius,
                                               &devSpaceSpotBlur, &spotScale, &spotOffset);
        }
        // handle scale of radius due to CTM
        const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale;

        // Adjust translate for the effect of the scale.
        spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX];
        spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY];
        // This offset is in dev space, need to transform it into source space.
        SkMatrix ctmInverse;
        if (viewMatrix.invert(&ctmInverse)) {
            ctmInverse.mapPoints(&spotOffset, 1);
        } else {
            // Since the matrix is a similarity, this should never happen, but just in case...
            SkDebugf("Matrix is degenerate. Will not render spot shadow correctly!\n");
            SkASSERT(false);
        }

        // Compute the transformed shadow rrect
        SkRRect spotShadowRRect;
        SkMatrix shadowTransform;
        shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY);
        rrect.transform(shadowTransform, &spotShadowRRect);
        SkScalar spotRadius = spotShadowRRect.getSimpleRadii().fX;

        // Compute the insetWidth
        SkScalar blurOutset = srcSpaceSpotBlur;
        SkScalar insetWidth = blurOutset;
        if (transparent) {
            // If transparent, just do a fill
            insetWidth += spotShadowRRect.width();
        } else {
            // For shadows, instead of using a stroke we specify an inset from the penumbra
            // border. We want to extend this inset area so that it meets up with the caster
            // geometry. The inset geometry will by default already be inset by the blur width.
            //
            // We compare the min and max corners inset by the radius between the original
            // rrect and the shadow rrect. The distance between the two plus the difference
            // between the scaled radius and the original radius gives the distance from the
            // transformed shadow shape to the original shape in that corner. The max
            // of these gives the maximum distance we need to cover.
            //
            // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to
            // that to get the full insetWidth.
            SkScalar maxOffset;
            if (rrect.isRect()) {
                // Manhattan distance works better for rects
                maxOffset = std::max(std::max(SkTAbs(spotShadowRRect.rect().fLeft -
                                                 rrect.rect().fLeft),
                                          SkTAbs(spotShadowRRect.rect().fTop -
                                                 rrect.rect().fTop)),
                                   std::max(SkTAbs(spotShadowRRect.rect().fRight -
                                                 rrect.rect().fRight),
                                          SkTAbs(spotShadowRRect.rect().fBottom -
                                                 rrect.rect().fBottom)));
            } else {
                SkScalar dr = spotRadius - SkRRectPriv::GetSimpleRadii(rrect).fX;
                SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft -
                                                        rrect.rect().fLeft + dr,
                                                        spotShadowRRect.rect().fTop -
                                                        rrect.rect().fTop + dr);
                SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight -
                                                         rrect.rect().fRight - dr,
                                                         spotShadowRRect.rect().fBottom -
                                                         rrect.rect().fBottom - dr);
                maxOffset = SkScalarSqrt(std::max(SkPointPriv::LengthSqd(upperLeftOffset),
                                                  SkPointPriv::LengthSqd(lowerRightOffset))) + dr;
            }
            insetWidth += std::max(blurOutset, maxOffset);
        }

        // Outset the shadow rrect to the border of the penumbra
        SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset);
        if (spotShadowRRect.isOval()) {
            spotShadowRRect = SkRRect::MakeOval(outsetRect);
        } else {
            SkScalar outsetRad = spotRadius + blurOutset;
            spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
        }

        GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor);

        GrOp::Owner op = GrShadowRRectOp::Make(fContext,
                                               spotColor,
                                               viewMatrix,
                                               spotShadowRRect,
                                               2.0f * devSpaceSpotBlur,
                                               insetWidth);
        if (op) {
            this->addDrawOp(clip, std::move(op));
        }
    }

    return true;
}

///////////////////////////////////////////////////////////////////////////////

void SurfaceDrawContext::drawRegion(const GrClip* clip,
                                    GrPaint&& paint,
                                    GrAA aa,
                                    const SkMatrix& viewMatrix,
                                    const SkRegion& region,
                                    const GrStyle& style,
                                    const GrUserStencilSettings* ss) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawRegion", fContext);

    if (GrAA::kYes == aa) {
        // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
        // to see whether aa is really required.
        if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
            SkScalarIsInt(viewMatrix.getTranslateX()) &&
            SkScalarIsInt(viewMatrix.getTranslateY())) {
            aa = GrAA::kNo;
        }
    }
    bool complexStyle = !style.isSimpleFill();
    if (complexStyle || GrAA::kYes == aa) {
        SkPath path;
        region.getBoundaryPath(&path);
        path.setIsVolatile(true);

        return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
    }

    GrAAType aaType = (this->numSamples() > 1 &&
                       !this->caps()->multisampleDisableSupport())
                    ? GrAAType::kMSAA
                    : GrAAType::kNone;
    GrOp::Owner op = GrRegionOp::Make(fContext, std::move(paint), viewMatrix, region, aaType, ss);
    this->addDrawOp(clip, std::move(op));
}

void SurfaceDrawContext::drawOval(const GrClip* clip,
                                  GrPaint&& paint,
                                  GrAA aa,
                                  const SkMatrix& viewMatrix,
                                  const SkRect& oval,
                                  const GrStyle& style) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawOval", fContext);

    const SkStrokeRec& stroke = style.strokeRec();

    if (oval.isEmpty() && !style.pathEffect()) {
        if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
            return;
        }

        this->drawRect(clip, std::move(paint), aa, viewMatrix, oval, &style);
        return;
    }

    AutoCheckFlush acf(this->drawingManager());

    GrAAType aaType = this->chooseAAType(aa);

    GrOp::Owner op;
    if (aaType == GrAAType::kCoverage      &&
        !fCanUseDynamicMSAA                &&
        !this->caps()->reducedShaderMode() &&
        oval.width() > SK_ScalarNearlyZero &&
        oval.width() == oval.height()      &&
        viewMatrix.isSimilarity()) {
        // In specific cases we use a dedicated circle op to try and get better perf.
        assert_alive(paint);
        op = GrOvalOpFactory::MakeCircleOp(fContext, std::move(paint), viewMatrix, oval, style,
                                           this->caps()->shaderCaps());
    }
    if (!op && style.isSimpleFill()) {
        // GrFillRRectOp has special geometry and a fragment-shader branch to conditionally evaluate
        // the arc equation. This same special geometry and fragment branch also turn out to be a
        // substantial optimization for drawing ovals (namely, by not evaluating the arc equation
        // inside the oval's inner diamond). Given these optimizations, it's a clear win to draw
        // ovals the exact same way we do round rects.
        assert_alive(paint);
        op = GrFillRRectOp::Make(fContext, this->arenaAlloc(), std::move(paint), viewMatrix,
                                 SkRRect::MakeOval(oval), oval, GrAA(aaType != GrAAType::kNone));
    }
    if (!op && (aaType == GrAAType::kCoverage || fCanUseDynamicMSAA)) {
        assert_alive(paint);
        op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix, oval, style,
                                         this->caps()->shaderCaps());
    }
    if (op) {
        this->addDrawOp(clip, std::move(op));
        return;
    }

    assert_alive(paint);
    this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
                                     GrStyledShape(SkRRect::MakeOval(oval), SkPathDirection::kCW, 2,
                                                   false, style, DoSimplify::kNo));
}

void SurfaceDrawContext::drawArc(const GrClip* clip,
                                 GrPaint&& paint,
                                 GrAA aa,
                                 const SkMatrix& viewMatrix,
                                 const SkRect& oval,
                                 SkScalar startAngle,
                                 SkScalar sweepAngle,
                                 bool useCenter,
                                 const GrStyle& style) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
            GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawArc", fContext);

    AutoCheckFlush acf(this->drawingManager());

    GrAAType aaType = this->chooseAAType(aa);
    if (aaType == GrAAType::kCoverage) {
        const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
        GrOp::Owner op = GrOvalOpFactory::MakeArcOp(fContext,
                                                    std::move(paint),
                                                    viewMatrix,
                                                    oval,
                                                    startAngle,
                                                    sweepAngle,
                                                    useCenter,
                                                    style,
                                                    shaderCaps);
        if (op) {
            this->addDrawOp(clip, std::move(op));
            return;
        }
        assert_alive(paint);
    }
    this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
                                     GrStyledShape::MakeArc(oval, startAngle, sweepAngle, useCenter,
                                                            style, DoSimplify::kNo));
}

void SurfaceDrawContext::drawImageLattice(const GrClip* clip,
                                          GrPaint&& paint,
                                          const SkMatrix& viewMatrix,
                                          GrSurfaceProxyView view,
                                          SkAlphaType alphaType,
                                          sk_sp<GrColorSpaceXform> csxf,
                                          GrSamplerState::Filter filter,
                                          std::unique_ptr<SkLatticeIter> iter,
                                          const SkRect& dst) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawImageLattice", fContext);

    AutoCheckFlush acf(this->drawingManager());

    GrOp::Owner op =
            GrLatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(view),
                                   alphaType, std::move(csxf), filter, std::move(iter), dst);
    this->addDrawOp(clip, std::move(op));
}

void SurfaceDrawContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
                                       const SkRect& bounds) {
    GrOp::Owner op(GrDrawableOp::Make(fContext, std::move(drawable), bounds));
    SkASSERT(op);
    this->addOp(std::move(op));
}

void SurfaceDrawContext::setLastClip(uint32_t clipStackGenID,
                                     const SkIRect& devClipBounds,
                                     int numClipAnalyticElements) {
    GrOpsTask* opsTask = this->getOpsTask();
    opsTask->fLastClipStackGenID = clipStackGenID;
    opsTask->fLastDevClipBounds = devClipBounds;
    opsTask->fLastClipNumAnalyticElements = numClipAnalyticElements;
}

bool SurfaceDrawContext::mustRenderClip(uint32_t clipStackGenID,
                                        const SkIRect& devClipBounds,
                                        int numClipAnalyticElements) {
    GrOpsTask* opsTask = this->getOpsTask();
    return opsTask->fLastClipStackGenID != clipStackGenID ||
           !opsTask->fLastDevClipBounds.contains(devClipBounds) ||
           opsTask->fLastClipNumAnalyticElements != numClipAnalyticElements;
}

bool SurfaceDrawContext::waitOnSemaphores(int numSemaphores,
                                          const GrBackendSemaphore waitSemaphores[],
                                          bool deleteSemaphoresAfterWait) {
    ASSERT_SINGLE_OWNER
    RETURN_FALSE_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "waitOnSemaphores", fContext);

    AutoCheckFlush acf(this->drawingManager());

    if (numSemaphores && !this->caps()->semaphoreSupport()) {
        return false;
    }

    auto direct = fContext->asDirectContext();
    if (!direct) {
        return false;
    }

    auto resourceProvider = direct->priv().resourceProvider();

    GrWrapOwnership ownership =
            deleteSemaphoresAfterWait ? kAdopt_GrWrapOwnership : kBorrow_GrWrapOwnership;

    std::unique_ptr<std::unique_ptr<GrSemaphore>[]> grSemaphores(
            new std::unique_ptr<GrSemaphore>[numSemaphores]);
    for (int i = 0; i < numSemaphores; ++i) {
        grSemaphores[i] = resourceProvider->wrapBackendSemaphore(waitSemaphores[i],
                                                                 GrSemaphoreWrapType::kWillWait,
                                                                 ownership);
    }
    this->drawingManager()->newWaitRenderTask(this->asSurfaceProxyRef(), std::move(grSemaphores),
                                              numSemaphores);
    return true;
}

void SurfaceDrawContext::drawPath(const GrClip* clip,
                                  GrPaint&& paint,
                                  GrAA aa,
                                  const SkMatrix& viewMatrix,
                                  const SkPath& path,
                                  const GrStyle& style) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawPath", fContext);

    GrStyledShape shape(path, style, DoSimplify::kNo);
    this->drawShape(clip, std::move(paint), aa, viewMatrix, std::move(shape));
}

void SurfaceDrawContext::drawShape(const GrClip* clip,
                                   GrPaint&& paint,
                                   GrAA aa,
                                   const SkMatrix& viewMatrix,
                                   GrStyledShape&& shape) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawShape", fContext);

    if (shape.isEmpty()) {
        if (shape.inverseFilled()) {
            this->drawPaint(clip, std::move(paint), viewMatrix);
        }
        return;
    }

    AutoCheckFlush acf(this->drawingManager());

    // If we get here in drawShape(), we definitely need to use path rendering
    this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, std::move(shape),
                                     /* attemptDrawSimple */ true);
}

#if SK_GPU_V1
static SkIRect get_clip_bounds(const SurfaceDrawContext* sdc, const GrClip* clip) {
    return clip ? clip->getConservativeBounds() : SkIRect::MakeWH(sdc->width(), sdc->height());
}
#endif // SK_GPU_V1

bool SurfaceDrawContext::drawAndStencilPath(const GrHardClip* clip,
                                            const GrUserStencilSettings* ss,
                                            SkRegion::Op op,
                                            bool invert,
                                            GrAA aa,
                                            const SkMatrix& viewMatrix,
                                            const SkPath& path) {
#if SK_GPU_V1
    ASSERT_SINGLE_OWNER
    RETURN_FALSE_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawAndStencilPath", fContext);

    if (path.isEmpty() && path.isInverseFillType()) {
        GrPaint paint;
        paint.setCoverageSetOpXPFactory(op, invert);
        this->stencilRect(clip, ss, std::move(paint), GrAA::kNo, SkMatrix::I(),
                          SkRect::Make(this->dimensions()));
        return true;
    }

    AutoCheckFlush acf(this->drawingManager());

    // An Assumption here is that path renderer would use some form of tweaking
    // the src color (either the input alpha or in the frag shader) to implement
    // aa. If we have some future driver-mojo path AA that can do the right
    // thing WRT to the blend then we'll need some query on the PR.
    GrAAType aaType = this->chooseAAType(aa);
    bool hasUserStencilSettings = !ss->isUnused();

    SkIRect clipConservativeBounds = get_clip_bounds(this, clip);

    GrPaint paint;
    paint.setCoverageSetOpXPFactory(op, invert);

    GrStyledShape shape(path, GrStyle::SimpleFill());
    GrPathRenderer::CanDrawPathArgs canDrawArgs;
    canDrawArgs.fCaps = this->caps();
    canDrawArgs.fProxy = this->asRenderTargetProxy();
    canDrawArgs.fViewMatrix = &viewMatrix;
    canDrawArgs.fShape = &shape;
    canDrawArgs.fPaint = &paint;
    canDrawArgs.fSurfaceProps = &fSurfaceProps;
    canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
    canDrawArgs.fAAType = aaType;
    canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;

    // Don't allow the SW renderer
    GrPathRenderer* pr = this->drawingManager()->getPathRenderer(
            canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
    if (!pr) {
        return false;
    }

    GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
                                      std::move(paint),
                                      ss,
                                      this,
                                      clip,
                                      &clipConservativeBounds,
                                      &viewMatrix,
                                      &shape,
                                      aaType,
                                      this->colorInfo().isLinearlyBlended()};
    pr->drawPath(args);
    return true;
#else
    return false;
#endif
}

SkBudgeted SurfaceDrawContext::isBudgeted() const {
    ASSERT_SINGLE_OWNER

    if (fContext->abandoned()) {
        return SkBudgeted::kNo;
    }

    SkDEBUGCODE(this->validate();)

    return this->asSurfaceProxy()->isBudgeted();
}

void SurfaceDrawContext::drawStrokedLine(const GrClip* clip,
                                         GrPaint&& paint,
                                         GrAA aa,
                                         const SkMatrix& viewMatrix,
                                         const SkPoint points[2],
                                         const SkStrokeRec& stroke) {
    ASSERT_SINGLE_OWNER

    SkASSERT(stroke.getStyle() == SkStrokeRec::kStroke_Style);
    SkASSERT(stroke.getWidth() > 0);
    // Adding support for round capping would require a
    // SurfaceDrawContext::fillRRectWithLocalMatrix entry point
    SkASSERT(SkPaint::kRound_Cap != stroke.getCap());

    const SkScalar halfWidth = 0.5f * stroke.getWidth();
    if (halfWidth <= 0.f) {
        // Prevents underflow when stroke width is epsilon > 0 (so technically not a hairline).
        // The CTM would need to have a scale near 1/epsilon in order for this to have meaningful
        // coverage (although that would likely overflow elsewhere and cause the draw to drop due
        // to non-finite bounds). At any other scale, this line is so thin, it's coverage is
        // negligible, so discarding the draw is visually equivalent.
        return;
    }

    SkVector parallel = points[1] - points[0];

    if (!SkPoint::Normalize(&parallel)) {
        parallel.fX = 1.0f;
        parallel.fY = 0.0f;
    }
    parallel *= halfWidth;

    SkVector ortho = { parallel.fY, -parallel.fX };
    if (SkPaint::kButt_Cap == stroke.getCap()) {
        // No extra extension for butt caps
        parallel = {0.f, 0.f};
    }
    // Order is TL, TR, BR, BL where arbitrarily "down" is p0 to p1 and "right" is positive
    SkPoint corners[4] = { points[0] - ortho - parallel,
                           points[0] + ortho - parallel,
                           points[1] + ortho + parallel,
                           points[1] - ortho + parallel };

    GrQuadAAFlags edgeAA = (aa == GrAA::kYes) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
    this->fillQuadWithEdgeAA(clip, std::move(paint), aa, edgeAA, viewMatrix, corners, nullptr);
}

bool SurfaceDrawContext::drawSimpleShape(const GrClip* clip,
                                         GrPaint* paint,
                                         GrAA aa,
                                         const SkMatrix& viewMatrix,
                                         const GrStyledShape& shape) {
    if (!shape.style().hasPathEffect()) {
        GrAAType aaType = this->chooseAAType(aa);
        SkPoint linePts[2];
        SkRRect rrect;
        // We can ignore the starting point and direction since there is no path effect.
        bool inverted;
        if (shape.asLine(linePts, &inverted) && !inverted &&
            shape.style().strokeRec().getStyle() == SkStrokeRec::kStroke_Style &&
            shape.style().strokeRec().getCap() != SkPaint::kRound_Cap) {
            // The stroked line is an oriented rectangle, which looks the same or better (if
            // perspective) compared to path rendering. The exception is subpixel/hairline lines
            // that are non-AA or MSAA, in which case the default path renderer achieves higher
            // quality.
            // FIXME(michaelludwig): If the fill rect op could take an external coverage, or checks
            // for and outsets thin non-aa rects to 1px, the path renderer could be skipped.
            SkScalar coverage;
            if (aaType == GrAAType::kCoverage ||
                !SkDrawTreatAAStrokeAsHairline(shape.style().strokeRec().getWidth(), viewMatrix,
                                               &coverage)) {
                this->drawStrokedLine(clip, std::move(*paint), aa, viewMatrix, linePts,
                                      shape.style().strokeRec());
                return true;
            }
        } else if (shape.asRRect(&rrect, nullptr, nullptr, &inverted) && !inverted) {
            if (rrect.isRect()) {
                this->drawRect(clip, std::move(*paint), aa, viewMatrix, rrect.rect(),
                               &shape.style());
                return true;
            } else if (rrect.isOval()) {
                this->drawOval(clip, std::move(*paint), aa, viewMatrix, rrect.rect(),
                               shape.style());
                return true;
            }
            this->drawRRect(clip, std::move(*paint), aa, viewMatrix, rrect, shape.style());
            return true;
        } else if (GrAAType::kCoverage == aaType &&
                   shape.style().isSimpleFill()  &&
                   viewMatrix.rectStaysRect()    &&
                   !this->caps()->reducedShaderMode()) {
            // TODO: the rectStaysRect restriction could be lifted if we were willing to apply the
            // matrix to all the points individually rather than just to the rect
            SkRect rects[2];
            if (shape.asNestedRects(rects)) {
                // Concave AA paths are expensive - try to avoid them for special cases
                GrOp::Owner op = GrStrokeRectOp::MakeNested(
                                fContext, std::move(*paint), viewMatrix, rects);
                if (op) {
                    this->addDrawOp(clip, std::move(op));
                }
                // Returning here indicates that there is nothing to draw in this case.
                return true;
            }
        }
    }
    return false;
}

void SurfaceDrawContext::drawShapeUsingPathRenderer(const GrClip* clip,
                                                    GrPaint&& paint,
                                                    GrAA aa,
                                                    const SkMatrix& viewMatrix,
                                                    GrStyledShape&& shape,
                                                    bool attemptDrawSimple) {
#if SK_GPU_V1
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "internalDrawPath", fContext);

    if (!viewMatrix.isFinite() || !shape.bounds().isFinite()) {
        return;
    }

    SkIRect clipConservativeBounds = get_clip_bounds(this, clip);

    // Always allow paths to trigger DMSAA.
    GrAAType aaType = fCanUseDynamicMSAA ? GrAAType::kMSAA : this->chooseAAType(aa);

    GrPathRenderer::CanDrawPathArgs canDrawArgs;
    canDrawArgs.fCaps = this->caps();
    canDrawArgs.fProxy = this->asRenderTargetProxy();
    canDrawArgs.fViewMatrix = &viewMatrix;
    canDrawArgs.fShape = &shape;
    canDrawArgs.fPaint = &paint;
    canDrawArgs.fSurfaceProps = &fSurfaceProps;
    canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
    canDrawArgs.fHasUserStencilSettings = false;
    canDrawArgs.fAAType = aaType;

    constexpr static bool kDisallowSWPathRenderer = false;
    constexpr static bool kAllowSWPathRenderer = true;
    using DrawType = GrPathRendererChain::DrawType;

    GrPathRenderer* pr = nullptr;

    if (!shape.style().strokeRec().isFillStyle() && !shape.isEmpty()) {
        // Give the tessellation path renderer a chance to claim this stroke before we simplify it.
        GrPathRenderer* tess = this->drawingManager()->getTessellationPathRenderer();
        if (tess && tess->canDrawPath(canDrawArgs) == GrPathRenderer::CanDrawPath::kYes) {
            pr = tess;
        }
    }

    if (!pr) {
        // The shape isn't a stroke that can be drawn directly. Simplify if possible.
        shape.simplify();

        if (shape.isEmpty() && !shape.inverseFilled()) {
            return;
        }

        if (attemptDrawSimple || shape.simplified()) {
            // Usually we enter drawShapeUsingPathRenderer() because the shape+style was too complex
            // for dedicated draw ops. However, if GrStyledShape was able to reduce something we
            // ought to try again instead of going right to path rendering.
            if (this->drawSimpleShape(clip, &paint, aa, viewMatrix, shape)) {
                return;
            }
        }

        // Try a 1st time without applying any of the style to the geometry (and barring sw)
        pr = this->drawingManager()->getPathRenderer(canDrawArgs, kDisallowSWPathRenderer,
                                                     DrawType::kColor);
    }

    SkScalar styleScale =  GrStyle::MatrixToScaleFactor(viewMatrix);
    if (styleScale == 0.0f) {
        return;
    }

    if (!pr && shape.style().pathEffect()) {
        // It didn't work above, so try again with the path effect applied.
        shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
        if (shape.isEmpty()) {
            return;
        }
        pr = this->drawingManager()->getPathRenderer(canDrawArgs, kDisallowSWPathRenderer,
                                                     DrawType::kColor);
    }
    if (!pr) {
        if (shape.style().applies()) {
            shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
            if (shape.isEmpty()) {
                return;
            }
            // This time, allow SW renderer
            pr = this->drawingManager()->getPathRenderer(canDrawArgs, kAllowSWPathRenderer,
                                                         DrawType::kColor);
        } else {
            pr = this->drawingManager()->getSoftwarePathRenderer();
#if GR_PATH_RENDERER_SPEW
            SkDebugf("falling back to: %s\n", pr->name());
#endif
        }
    }

    if (!pr) {
#ifdef SK_DEBUG
        SkDebugf("Unable to find path renderer compatible with path.\n");
#endif
        return;
    }

    GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
                                      std::move(paint),
                                      &GrUserStencilSettings::kUnused,
                                      this,
                                      clip,
                                      &clipConservativeBounds,
                                      &viewMatrix,
                                      canDrawArgs.fShape,
                                      aaType,
                                      this->colorInfo().isLinearlyBlended()};
    pr->drawPath(args);
#endif
}

void SurfaceDrawContext::addDrawOp(const GrClip* clip,
                                   GrOp::Owner op,
                                   const std::function<WillAddOpFn>& willAddFn) {
    ASSERT_SINGLE_OWNER
    if (fContext->abandoned()) {
        return;
    }
    GrDrawOp* drawOp = (GrDrawOp*)op.get();
    SkDEBUGCODE(this->validate();)
    SkDEBUGCODE(drawOp->fAddDrawOpCalled = true;)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "addDrawOp", fContext);

    // Setup clip
    SkRect bounds;
    op_bounds(&bounds, op.get());
    GrAppliedClip appliedClip(this->dimensions(), this->asSurfaceProxy()->backingStoreDimensions());
    const bool opUsesMSAA = drawOp->usesMSAA();
    bool skipDraw = false;
    if (clip) {
        // Have a complex clip, so defer to its early clip culling
        GrAAType aaType;
        if (opUsesMSAA) {
            aaType = GrAAType::kMSAA;
        } else {
            aaType = op->hasAABloat() ? GrAAType::kCoverage : GrAAType::kNone;
        }
        skipDraw = clip->apply(fContext, this, drawOp, aaType,
                               &appliedClip, &bounds) == GrClip::Effect::kClippedOut;
    } else {
        // No clipping, so just clip the bounds against the logical render target dimensions
        skipDraw = !bounds.intersect(this->asSurfaceProxy()->getBoundsRect());
    }

    if (skipDraw) {
        return;
    }

    GrClampType clampType = GrColorTypeClampType(this->colorInfo().colorType());
    GrProcessorSet::Analysis analysis = drawOp->finalize(*this->caps(), &appliedClip, clampType);

    const bool opUsesStencil = drawOp->usesStencil();

    // Always trigger DMSAA when there is stencil. This ensures stencil contents get properly
    // preserved between render passes, if needed.
    const bool drawNeedsMSAA = opUsesMSAA || (fCanUseDynamicMSAA && opUsesStencil);

    // Must be called before setDstProxyView so that it sees the final bounds of the op.
    op->setClippedBounds(bounds);

    // Determine if the Op will trigger the use of a separate DMSAA attachment that requires manual
    // resolves.
    // TODO: Currently usesAttachmentIfDMSAA checks if this is a textureProxy or not. This check is
    // really only for GL which uses a normal texture sampling when using barriers. For Vulkan it
    // is possible to use the msaa buffer as an input attachment even if this is not a texture.
    // However, support for that is not fully implemented yet in Vulkan. Once it is, this check
    // should change to a virtual caps check that returns whether we need to break up an OpsTask
    // if it has barriers and we are about to promote to MSAA.
    bool usesAttachmentIfDMSAA =
            fCanUseDynamicMSAA &&
            (!this->caps()->msaaResolvesAutomatically() || !this->asTextureProxy());
    bool opRequiresDMSAAAttachment = usesAttachmentIfDMSAA && drawNeedsMSAA;
    bool opTriggersDMSAAAttachment =
            opRequiresDMSAAAttachment && !this->getOpsTask()->usesMSAASurface();
    if (opTriggersDMSAAAttachment) {
        // This will be the op that actually triggers use of a DMSAA attachment. Texture barriers
        // can't be moved to a DMSAA attachment, so if there already are any on the current opsTask
        // then we need to split.
        if (this->getOpsTask()->renderPassXferBarriers() & GrXferBarrierFlags::kTexture) {
            SkASSERT(!this->getOpsTask()->isColorNoOp());
            this->replaceOpsTask()->setCannotMergeBackward();
        }
    }

    GrDstProxyView dstProxyView;
    if (analysis.requiresDstTexture()) {
        if (!this->setupDstProxyView(drawOp->bounds(), drawNeedsMSAA, &dstProxyView)) {
            return;
        }
#ifdef SK_DEBUG
        if (fCanUseDynamicMSAA && drawNeedsMSAA && !this->caps()->msaaResolvesAutomatically()) {
            // Since we aren't literally writing to the render target texture while using a DMSAA
            // attachment, we need to resolve that texture before sampling it. Ensure the current
            // opsTask got closed off in order to initiate an implicit resolve.
            SkASSERT(this->getOpsTask()->isEmpty());
        }
#endif
    }

    auto opsTask = this->getOpsTask();
    if (willAddFn) {
        willAddFn(op.get(), opsTask->uniqueID());
    }

    // Note if the op needs stencil. Stencil clipping already called setNeedsStencil for itself, if
    // needed.
    if (opUsesStencil) {
        this->setNeedsStencil();
    }

#if GR_GPU_STATS && GR_TEST_UTILS
    if (fCanUseDynamicMSAA && drawNeedsMSAA) {
        if (!opsTask->usesMSAASurface()) {
            fContext->priv().dmsaaStats().fNumMultisampleRenderPasses++;
        }
        fContext->priv().dmsaaStats().fTriggerCounts[op->name()]++;
    }
#endif

    opsTask->addDrawOp(this->drawingManager(), std::move(op), drawNeedsMSAA, analysis,
                       std::move(appliedClip), dstProxyView,
                       GrTextureResolveManager(this->drawingManager()), *this->caps());

#ifdef SK_DEBUG
    if (fCanUseDynamicMSAA && drawNeedsMSAA) {
        SkASSERT(opsTask->usesMSAASurface());
    }
#endif
}

bool SurfaceDrawContext::setupDstProxyView(const SkRect& opBounds,
                                           bool opRequiresMSAA,
                                           GrDstProxyView* dstProxyView) {
    // If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we
    // don't actually have a VkImage to make a copy of. Additionally we don't have the power to
    // start and stop the render pass in order to make the copy.
    if (this->asRenderTargetProxy()->wrapsVkSecondaryCB()) {
        return false;
    }

    // First get the dstSampleFlags as if we will put the draw into the current GrOpsTask
    auto dstSampleFlags = this->caps()->getDstSampleFlagsForProxy(
            this->asRenderTargetProxy(), this->getOpsTask()->usesMSAASurface() || opRequiresMSAA);

    // If we don't have barriers for this draw then we will definitely be breaking up the GrOpsTask.
    // However, if using dynamic MSAA, the new GrOpsTask will not have MSAA already enabled on it
    // and that may allow us to use texture barriers. So we check if we can use barriers on the new
    // ops task and then break it up if so.
    if (!(dstSampleFlags & GrDstSampleFlags::kRequiresTextureBarrier) &&
        fCanUseDynamicMSAA && this->getOpsTask()->usesMSAASurface() && !opRequiresMSAA) {
        auto newFlags =
                this->caps()->getDstSampleFlagsForProxy(this->asRenderTargetProxy(),
                                                        false/*=opRequiresMSAA*/);
        if (newFlags & GrDstSampleFlags::kRequiresTextureBarrier) {
            // We can't have an empty ops task if we are in DMSAA and the ops task already returns
            // true for usesMSAASurface.
            SkASSERT(!this->getOpsTask()->isColorNoOp());
            this->replaceOpsTask()->setCannotMergeBackward();
            dstSampleFlags = newFlags;
        }
    }

    if (dstSampleFlags & GrDstSampleFlags::kRequiresTextureBarrier) {
        // If we require a barrier to sample the dst it means we are sampling the RT itself
        // either as a texture or input attachment. In this case we don't need to break up the
        // GrOpsTask.
        dstProxyView->setProxyView(this->readSurfaceView());
        dstProxyView->setOffset(0, 0);
        dstProxyView->setDstSampleFlags(dstSampleFlags);
        return true;
    }
    SkASSERT(dstSampleFlags == GrDstSampleFlags::kNone);

    // We are using a different surface from the main color attachment to sample the dst from. If we
    // are in DMSAA we can just use the single sampled RT texture itself. Otherwise, we must do a
    // copy.
    // We do have to check if we ended up here becasue we don't have texture barriers but do have
    // msaaResolvesAutomatically (i.e. render-to-msaa-texture). In that case there will be no op or
    // barrier between draws to flush the render target before being used as a texture in the next
    // draw. So in that case we just fall through to doing a copy.
    if (fCanUseDynamicMSAA && opRequiresMSAA && this->asTextureProxy() &&
        !this->caps()->msaaResolvesAutomatically()) {
        this->replaceOpsTaskIfModifiesColor()->setCannotMergeBackward();
        dstProxyView->setProxyView(this->readSurfaceView());
        dstProxyView->setOffset(0, 0);
        dstProxyView->setDstSampleFlags(dstSampleFlags);
        return true;
    }

    // Now we fallback to doing a copy.

    GrColorType colorType = this->colorInfo().colorType();
    // MSAA consideration: When there is support for reading MSAA samples in the shader we could
    // have per-sample dst values by making the copy multisampled.
    GrCaps::DstCopyRestrictions restrictions = this->caps()->getDstCopyRestrictions(
            this->asRenderTargetProxy(), colorType);

    SkIRect copyRect = SkIRect::MakeSize(this->asSurfaceProxy()->backingStoreDimensions());
    if (!restrictions.fMustCopyWholeSrc) {
        // If we don't need the whole source, restrict to the op's bounds. We add an extra pixel
        // of padding to account for AA bloat and the unpredictable rounding of coords near pixel
        // centers during rasterization.
        SkIRect conservativeDrawBounds = opBounds.roundOut();
        conservativeDrawBounds.outset(1, 1);
        SkAssertResult(copyRect.intersect(conservativeDrawBounds));
    }

    SkIPoint dstOffset;
    SkBackingFit fit;
    if (restrictions.fRectsMustMatch == GrSurfaceProxy::RectsMustMatch::kYes) {
        dstOffset = {0, 0};
        fit = SkBackingFit::kExact;
    } else {
        dstOffset = {copyRect.fLeft, copyRect.fTop};
        fit = SkBackingFit::kApprox;
    }
    auto copy = GrSurfaceProxy::Copy(fContext,
                                     this->asSurfaceProxyRef(),
                                     this->origin(),
                                     GrMipmapped::kNo,
                                     copyRect,
                                     fit,
                                     SkBudgeted::kYes,
                                     restrictions.fRectsMustMatch);
    SkASSERT(copy);

    dstProxyView->setProxyView({std::move(copy), this->origin(), this->readSwizzle()});
    dstProxyView->setOffset(dstOffset);
    dstProxyView->setDstSampleFlags(dstSampleFlags);
    return true;
}

GrOpsTask* SurfaceDrawContext::replaceOpsTaskIfModifiesColor() {
    if (!this->getOpsTask()->isColorNoOp()) {
        this->replaceOpsTask();
    }
    return this->getOpsTask();
}

} // namespace skgpu::v1
