/*
 * 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/ganesh/SurfaceDrawContext.h"

#include "include/core/SkAlphaType.h"
#include "include/core/SkArc.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkDrawable.h"
#include "include/core/SkMesh.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPoint3.h"
#include "include/core/SkRRect.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkTypes.h"
#include "include/core/SkVertices.h"
#include "include/gpu/ganesh/GrBackendSemaphore.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "include/private/base/SingleOwner.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "include/utils/SkShadowUtils.h"
#include "src/core/SkDevice.h"
#include "src/core/SkDrawProcs.h"
#include "src/core/SkDrawShadowInfo.h"
#include "src/core/SkLatticeIter.h"
#include "src/core/SkMeshPriv.h"
#include "src/core/SkPointPriv.h"
#include "src/core/SkRRectPriv.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/RefCntedCallback.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/Swizzle.h"
#include "src/gpu/ganesh/GrAppliedClip.h"
#include "src/gpu/ganesh/GrAuditTrail.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrClip.h"
#include "src/gpu/ganesh/GrColor.h"
#include "src/gpu/ganesh/GrColorInfo.h"
#include "src/gpu/ganesh/GrColorSpaceXform.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrDrawingManager.h"
#include "src/gpu/ganesh/GrDstProxyView.h"
#include "src/gpu/ganesh/GrFragmentProcessor.h"
#include "src/gpu/ganesh/GrProcessorSet.h"
#include "src/gpu/ganesh/GrProxyProvider.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/GrScissorState.h"
#include "src/gpu/ganesh/GrSemaphore.h"
#include "src/gpu/ganesh/GrStencilSettings.h"
#include "src/gpu/ganesh/GrStyle.h"
#include "src/gpu/ganesh/GrTextureProxy.h"
#include "src/gpu/ganesh/GrTextureResolveManager.h"
#include "src/gpu/ganesh/GrTracing.h"
#include "src/gpu/ganesh/GrUserStencilSettings.h"
#include "src/gpu/ganesh/GrXferProcessor.h"
#include "src/gpu/ganesh/PathRenderer.h"
#include "src/gpu/ganesh/PathRendererChain.h"
#include "src/gpu/ganesh/SkGr.h"
#include "src/gpu/ganesh/effects/GrBlendFragmentProcessor.h"
#include "src/gpu/ganesh/effects/GrDisableColorXP.h"
#include "src/gpu/ganesh/effects/GrTextureEffect.h"
#include "src/gpu/ganesh/geometry/GrQuad.h"
#include "src/gpu/ganesh/geometry/GrQuadUtils.h"
#include "src/gpu/ganesh/geometry/GrStyledShape.h"
#include "src/gpu/ganesh/ops/AtlasTextOp.h"
#include "src/gpu/ganesh/ops/ClearOp.h"
#include "src/gpu/ganesh/ops/DrawAtlasOp.h"
#include "src/gpu/ganesh/ops/DrawMeshOp.h"
#include "src/gpu/ganesh/ops/DrawableOp.h"
#include "src/gpu/ganesh/ops/FillRRectOp.h"
#include "src/gpu/ganesh/ops/FillRectOp.h"
#include "src/gpu/ganesh/ops/GrDrawOp.h"
#include "src/gpu/ganesh/ops/GrOp.h"
#include "src/gpu/ganesh/ops/GrOvalOpFactory.h"
#include "src/gpu/ganesh/ops/LatticeOp.h"
#include "src/gpu/ganesh/ops/RegionOp.h"
#include "src/gpu/ganesh/ops/ShadowRRectOp.h"
#include "src/gpu/ganesh/ops/StrokeRectOp.h"
#include "src/gpu/ganesh/ops/TextureOp.h"
#include "src/text/gpu/SubRunContainer.h"
#include "src/text/gpu/TextBlobRedrawCoordinator.h"

#include <algorithm>
#include <map>
#include <string>

struct GrShaderCaps;

#define ASSERT_SINGLE_OWNER        SKGPU_ASSERT_SINGLE_OWNER(this->singleOwner())
#define RETURN_IF_ABANDONED        if (fContext->abandoned()) { return; }
#define RETURN_FALSE_IF_ABANDONED  if (fContext->abandoned()) { return false; }

using namespace skia_private;

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

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::ganesh {

using DoSimplify = GrStyledShape::DoSimplify;

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

    const GrBackendFormat& format = proxy->backendFormat();
    skgpu::Swizzle readSwizzle = rContext->priv().caps()->getReadSwizzle(format, colorType);
    skgpu::Swizzle 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);
}

std::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::Make(GrRecordingContext* rContext,
                                                             sk_sp<SkColorSpace> colorSpace,
                                                             SkBackingFit fit,
                                                             SkISize dimensions,
                                                             const GrBackendFormat& format,
                                                             int sampleCnt,
                                                             skgpu::Mipmapped mipmapped,
                                                             GrProtected isProtected,
                                                             skgpu::Swizzle readSwizzle,
                                                             skgpu::Swizzle writeSwizzle,
                                                             GrSurfaceOrigin origin,
                                                             skgpu::Budgeted budgeted,
                                                             const SkSurfaceProps& surfaceProps,
                                                             std::string_view label) {
    // 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,
            label);
    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,
                                                             std::string_view label,
                                                             int sampleCnt,
                                                             skgpu::Mipmapped mipmapped,
                                                             GrProtected isProtected,
                                                             GrSurfaceOrigin origin,
                                                             skgpu::Budgeted budgeted) {
    if (!rContext) {
        return nullptr;
    }

    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,
            label);
    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,
        skgpu::Mipmapped mipmapped,
        GrProtected isProtected,
        GrSurfaceOrigin origin,
        skgpu::Budgeted 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,
                                    /*label=*/"MakeSurfaceDrawContextWithFallback", 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<skgpu::RefCntedCallback> 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
// OpsTask to be picked up and added to by SurfaceDrawContexts lower in the call
// stack. When this occurs with a closed OpsTask, 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)
        : SurfaceFillContext(rContext,
                             std::move(readView),
                             std::move(writeView),
                             {colorType, kPremul_SkAlphaType, std::move(colorSpace)})
        , fSurfaceProps(surfaceProps)
        , fCanUseDynamicMSAA(
                (fSurfaceProps.flags() & SkSurfaceProps::kDynamicMSAA_Flag) &&
                rContext->priv().caps()->supportsDynamicMSAA(this->asRenderTargetProxy())) {
    SkDEBUGCODE(this->validate();)
}

SurfaceDrawContext::~SurfaceDrawContext() {
    ASSERT_SINGLE_OWNER
}

void SurfaceDrawContext::willReplaceOpsTask(OpsTask* prevTask, OpsTask* 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(OpsTask::StencilContent::kPreserved);
    }
#if GR_GPU_STATS && defined(GPU_TEST_UTILS)
    if (fCanUseDynamicMSAA) {
        fContext->priv().dmsaaStats().fNumRenderPasses++;
    }
#endif
}

void SurfaceDrawContext::drawGlyphRunList(SkCanvas* canvas,
                                          const GrClip* clip,
                                          const SkMatrix& viewMatrix,
                                          const sktext::GlyphRunList& glyphRunList,
                                          SkStrikeDeviceInfo strikeDeviceInfo,
                                          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;
    }

    sktext::gpu::TextBlobRedrawCoordinator* textBlobCache = fContext->priv().getTextBlobCache();

    auto atlasDelegate = [&](const sktext::gpu::AtlasSubRun* subRun,
                             SkPoint drawOrigin,
                             const SkPaint& paint,
                             sk_sp<SkRefCnt> subRunStorage,
                             sktext::gpu::RendererData) {
        auto [drawingClip, op] = AtlasTextOp::Make(
                this, subRun, clip, viewMatrix, drawOrigin, paint, std::move(subRunStorage));
        if (op != nullptr) {
            this->addDrawOp(drawingClip, std::move(op));
        }
    };

    textBlobCache->drawGlyphRunList(
            canvas, viewMatrix, glyphRunList, paint, strikeDeviceInfo, atlasDelegate);
}

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.
        if (auto localMatrix = viewMatrix.invert()) {
            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,
        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();

    // For historical reasons, we assume AA for exact bounds checking in IsOutsideClip.
    // TODO(michaelludwig) - Hopefully that can be revisited when the clipping optimizations are
    // refactored to work better with round rects and dmsaa.
    SkRect drawBounds = quad->fDevice.bounds();
    if (!quad->fDevice.isFinite() || drawBounds.isEmpty() ||
        GrClip::IsOutsideClip(SkIRect::MakeSize(this->dimensions()), drawBounds, GrAA::kYes)) {
        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;
    }

    GrAA drawUsesAA{quad->fEdgeFlags != GrQuadAAFlags::kNone};
    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, drawUsesAA, quad, /* compute local */ !constColor);
        }
    };

    bool simpleColor = !stencilSettings && constColor;
    GrClip::PreClipResult result = clip ? clip->preApply(drawBounds, drawUsesAA)
                                        : 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. Pick an AA value such
                // that any geometric clipping doesn't need to change aa or edge flags (since we
                // know this is on pixel boundaries, it will draw the same regardless).
                // See skbug.com/40044221 for more details.
                result = GrClip::PreClipResult(SkRRect::MakeRect(rtRect), drawUsesAA);
            }
            break;
        case GrClip::Effect::kClipped:
            if (!result.fIsRRect || (stencilSettings && result.fAA != drawUsesAA) ||
                (!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;
                }
            }

            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,
                                        DrawQuad* quad,
                                        const GrUserStencilSettings* ss) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawFilledQuad", fContext);

    QuadOptimization opt = this->attemptQuadOptimization(clip, ss, quad, &paint);
    if (opt >= QuadOptimization::kClipApplied) {
        // These optimizations require caller to add an op themselves
        const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip;
        // The quad being drawn requires AA if any of its edges requires AA
        GrAA aa{quad->fEdgeFlags != GrQuadAAFlags::kNone};
        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, FillRectOp::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,
                                     GrQuadAAFlags edgeAA,
                                     SkCanvas::SrcRectConstraint constraint,
                                     const SkMatrix& viewMatrix,
                                     sk_sp<GrColorSpaceXform> colorSpaceXform) {
    // If we are using dmsaa then go through FillRRectOp (via fillRectToRect).
    if ((this->alwaysAntialias() || this->caps()->reducedShaderMode()) &&
        edgeAA != GrQuadAAFlags::kNone) {
        auto [mustFilter, mustMM] = FilterAndMipmapHaveNoEffect(
                GrQuad::MakeFromRect(dstRect, viewMatrix), GrQuad(srcRect));
        if (!mustFilter) {
            // Chromeos-jacuzzi devices (ARM Mali-G72 MP3) have issues with blitting with linear
            // filtering. Likely some optimization or quantization causes fragments to be produced
            // with small offset/error. This will result in a slight blending of pixels when
            // sampling. Normally in most application this would be completely unnoticeable but when
            // trying to use the gpu as a per pixel blit we will end up with slightly blurry
            // results.
            // See https://crbug.com/326980863
            filter = GrSamplerState::Filter::kNearest;
        }

        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<SkBlendMode::kModulate>(std::move(fp), nullptr);
        paint.setColorFragmentProcessor(std::move(fp));
        if (blendMode != SkBlendMode::kSrcOver) {
            paint.setXPFactory(GrXPFactory::FromBlendMode(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, &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,
                                          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);

    // 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 TextureOp.
    QuadOptimization opt = this->attemptQuadOptimization(clip, nullptr/*stencil*/, quad,
                                                         nullptr/*paint*/);

    SkASSERT(opt != QuadOptimization::kSubmitted);
    if (opt != QuadOptimization::kDiscarded) {
        // Add the texture op if not discarded
        const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip;
        GrAAType aaType = this->chooseAAType(GrAA{quad->fEdgeFlags != GrQuadAAFlags::kNone});
        auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
        auto saturate = clampType == GrClampType::kManual ? ganesh::TextureOp::Saturate::kYes
                                                          : ganesh::TextureOp::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,
                        ganesh::TextureOp::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());

    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.
        //
        // skbug.com/40043303 -- 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 = ganesh::StrokeRectOp::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 FillRRectOp.
    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
                             // FillRRectOp because it might require dual source blending.
                             // skbug.com/40042830
        QuadOptimization opt = this->attemptQuadOptimization(clip, nullptr/*stencil*/, &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.
            auto inverse = viewMatrix.invert();
            if (!inverse) {
                return;
            }
            SkASSERT(inverse->rectStaysRect());
            inverse->mapRect(&croppedRect);
            if (opt == QuadOptimization::kClipApplied) {
                optimizedClip = nullptr;
            }
        } else {
            // Even if attemptQuadOptimization gave us an optimized quad, FillRRectOp needs a rect
            // in pre-matrix space, so use the original rect. Also preserve the original clip.
            croppedRect = rectToDraw;
            croppedLocal = localRect;
        }

        if (auto op = FillRRectOp::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), &quad);
}

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

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

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

OpsTask::CanDiscardPreviousOps SurfaceDrawContext::canDiscardPreviousOpsOnFullClear() const {
#if defined(GPU_TEST_UTILS)
    if (fPreserveOpsOnFullClear_TestingOnly) {
        return OpsTask::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/40038231).
    return OpsTask::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(
                    OpsTask::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,
                        FillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
                                                  SkRect::Make(scissorState.rect()), ss));
    } else {
        this->addOp(ClearOp::MakeStencilClip(fContext, scissorState, insideStencilMask));
    }
}

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

    PathRenderer::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;
    auto pr = this->drawingManager()->getPathRenderer(canDrawArgs,
                                                      false,
                                                      PathRendererChain::DrawType::kStencil);
    if (!pr) {
        SkDebugf("WARNING: No path renderer to stencil path.\n");
        return false;
    }

    PathRenderer::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;
}

void SurfaceDrawContext::drawTextureSet(const GrClip* clip,
                                        GrTextureSetEntry set[],
                                        int cnt,
                                        int proxyRunCnt,
                                        GrSamplerState::Filter filter,
                                        GrSamplerState::MipmapMode mm,
                                        SkBlendMode mode,
                                        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.
    GrAAType aaType = this->chooseAAType(GrAA::kYes);
    auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
    auto saturate = clampType == GrClampType::kManual ? ganesh::TextureOp::Saturate::kYes
                                                      : ganesh::TextureOp::Saturate::kNo;
    ganesh::TextureOp::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 SkMatrix& viewMatrix,
                                      sk_sp<SkVertices> vertices,
                                      GrPrimitiveType* overridePrimType,
                                      bool skipColorXform) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawVertices", fContext);

    SkASSERT(vertices);
    auto xform = skipColorXform ? nullptr : this->colorInfo().refColorSpaceXformFromSRGB();
    GrAAType aaType = fCanUseDynamicMSAA ? GrAAType::kMSAA : this->chooseAAType(GrAA::kNo);
    GrOp::Owner op = DrawMeshOp::Make(fContext,
                                      std::move(paint),
                                      std::move(vertices),
                                      overridePrimType,
                                      viewMatrix,
                                      aaType,
                                      std::move(xform));
    this->addDrawOp(clip, std::move(op));
}

void SurfaceDrawContext::drawMesh(const GrClip* clip,
                                  GrPaint&& paint,
                                  const SkMatrix& viewMatrix,
                                  const SkMesh& mesh,
                                  TArray<std::unique_ptr<GrFragmentProcessor>> children) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawMesh", fContext);

    SkASSERT(mesh.isValid());

    auto xform = GrColorSpaceXform::Make(SkMeshSpecificationPriv::ColorSpace(*mesh.spec()),
                                         SkMeshSpecificationPriv::AlphaType(*mesh.spec()),
                                         this->colorInfo().colorSpace(),
                                         this->colorInfo().alphaType());
    GrAAType aaType = fCanUseDynamicMSAA ? GrAAType::kMSAA : this->chooseAAType(GrAA::kNo);
    GrOp::Owner op = DrawMeshOp::Make(fContext,
                                      std::move(paint),
                                      mesh,
                                      std::move(children),
                                      viewMatrix,
                                      aaType,
                                      std::move(xform));
    this->addDrawOp(clip, std::move(op));
}

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

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

    GrAAType aaType = this->chooseAAType(GrAA::kNo);
    GrOp::Owner op = DrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
                                       aaType, xform.size(), xform.data(),
                                       texRect.data(), colors.data());
    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/40041797 - 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

    GrAAType aaType = this->chooseAAType(aa);

    GrOp::Owner op;
#ifndef SK_ENABLE_OPTIMIZE_SIZE
    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());
    }
#endif
    if (!op && style.isSimpleFill()) {
        assert_alive(paint);
        op = FillRRectOp::Make(fContext, this->arenaAlloc(), std::move(paint), viewMatrix, rrect,
                               rrect.rect(), GrAA(aaType != GrAAType::kNone));
    }
#ifndef SK_ENABLE_OPTIMIZE_SIZE
    if (!op && (aaType == GrAAType::kCoverage || fCanUseDynamicMSAA)) {
        assert_alive(paint);
        op = GrOvalOpFactory::MakeRRectOp(
                fContext, std::move(paint), viewMatrix, rrect, stroke, this->caps()->shaderCaps());
    }
#endif
    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;
    }

    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);
        }

        // The ShadowRRectOp still uses 8888 colors, so it might get clamped if the shadow color
        // does not fit in bytes after being transformed to the destination color space. This can
        // happen if the destination color space is smaller than sRGB, which is highly unlikely.
        GrColor ambientColor = SkColorToPMColor4f(rec.fAmbientColor, colorInfo()).toBytes_RGBA();
        if (transparent) {
            // set a large inset to force a fill
            devSpaceInsetWidth = ambientRRect.width();
        }

        GrOp::Owner op = ShadowRRectOp::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.
        if (auto ctmInverse = viewMatrix.invert()) {
            spotOffset = ctmInverse->mapPoint(spotOffset);
        } 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
        SkMatrix shadowTransform;
        shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY);
        SkRRect spotShadowRRect = rrect.transform(shadowTransform).value_or(SkRRect());
        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);
        }

        // The ShadowRRectOp still uses 8888 colors, so it might get clamped if the shadow color
        // does not fit in bytes after being transformed to the destination color space. This can
        // happen if the destination color space is smaller than sRGB, which is highly unlikely.
        GrColor spotColor = SkColorToPMColor4f(rec.fSpotColor, colorInfo()).toBytes_RGBA();
        GrOp::Owner op = ShadowRRectOp::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.setIsVolatile(true);

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

    GrAAType aaType = (this->numSamples() > 1) ? GrAAType::kMSAA : GrAAType::kNone;
    GrOp::Owner op = RegionOp::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;
    }

    GrAAType aaType = this->chooseAAType(aa);

    GrOp::Owner op;
#ifndef SK_ENABLE_OPTIMIZE_SIZE
    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());
    }
#endif
    if (!op && style.isSimpleFill()) {
        // FillRRectOp 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 = FillRRectOp::Make(fContext, this->arenaAlloc(), std::move(paint), viewMatrix,
                               SkRRect::MakeOval(oval), oval, GrAA(aaType != GrAAType::kNone));
    }
#ifndef SK_ENABLE_OPTIMIZE_SIZE
    if (!op && (aaType == GrAAType::kCoverage || fCanUseDynamicMSAA)) {
        assert_alive(paint);
        op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix, oval, style,
                                         this->caps()->shaderCaps());
    }
#endif
    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 SkArc& arc,
                                 const GrStyle& style) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
            GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawArc", fContext);

#ifndef SK_ENABLE_OPTIMIZE_SIZE
    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,
                                                    arc.fOval,
                                                    arc.fStartAngle,
                                                    arc.fSweepAngle,
                                                    arc.isWedge(),
                                                    style,
                                                    shaderCaps);
        if (op) {
            this->addDrawOp(clip, std::move(op));
            return;
        }
        assert_alive(paint);
    }
#endif
    this->drawShapeUsingPathRenderer(clip,
                                     std::move(paint),
                                     aa,
                                     viewMatrix,
                                     GrStyledShape::MakeArc(arc, 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);

    GrOp::Owner op =
              LatticeOp::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) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawDrawable", fContext);
    GrOp::Owner op(DrawableOp::Make(fContext, std::move(drawable), bounds));
    SkASSERT(op);
    this->addOp(std::move(op));
}

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

bool SurfaceDrawContext::mustRenderClip(uint32_t clipStackGenID,
                                        const SkIRect& devClipBounds,
                                        int numClipAnalyticElements) {
    auto 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);

    if (numSemaphores && !this->caps()->backendSemaphoreSupport()) {
        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;
    }

    // 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);
}

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

bool SurfaceDrawContext::drawAndStencilPath(const GrHardClip* clip,
                                            const GrUserStencilSettings* ss,
                                            SkRegion::Op op,
                                            bool invert,
                                            GrAA aa,
                                            const SkMatrix& viewMatrix,
                                            const SkPath& path) {
    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;
    }

    // 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());
    PathRenderer::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;

    using DrawType = PathRendererChain::DrawType;

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

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

skgpu::Budgeted SurfaceDrawContext::isBudgeted() const {
    ASSERT_SINGLE_OWNER

    if (fContext->abandoned()) {
        return skgpu::Budgeted::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 };
    SkPoint p0 = points[0], p1 = points[1];
    if (stroke.getCap() == SkPaint::kSquare_Cap) {
        // Extra extension for square caps
        p0 -= parallel;
        p1 += parallel;
    }

    // If we are using dmsaa or reduced shader mode then attempt to draw with FillRRectOp.
    if (this->caps()->drawInstancedSupport() &&
        (this->alwaysAntialias() ||
         (fContext->priv().caps()->reducedShaderMode() && aa == GrAA::kYes))) {
        SkMatrix localMatrix = SkMatrix::MakeAll(p1.fX - p0.fX, ortho.fX, p0.fX,
                                                 p1.fY - p0.fY, ortho.fY, p0.fY,
                                                 0, 0, 1);
        if (auto op = FillRRectOp::Make(fContext,
                                        this->arenaAlloc(),
                                        std::move(paint),
                                        SkMatrix::Concat(viewMatrix, localMatrix),
                                        SkRRect::MakeRect({0,-1,1,1}),
                                        localMatrix,
                                        GrAA::kYes)) {
            this->addDrawOp(clip, std::move(op));
            return;
        }
    }

    // Order is TL, TR, BR, BL where arbitrarily "down" is p0 to p1 and "right" is positive
    SkPoint corners[4] = { p0 - ortho,
                           p0 + ortho,
                           p1 + ortho,
                           p1 - ortho };

    GrQuadAAFlags edgeAA = (aa == GrAA::kYes) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;

    assert_alive(paint);
    this->fillQuadWithEdgeAA(clip, std::move(paint), 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 ||
                !skcpu::DrawTreatAAStrokeAsHairline(
                        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, &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 = ganesh::StrokeRectOp::MakeNested(fContext, std::move(*paint),
                                                                  viewMatrix, rects);
                if (op) {
                    this->addDrawOp(clip, std::move(op));
                    return true;
                }
                // Fall through to let path renderer handle subpixel nested rects with unequal
                // stroke widths along X/Y.
            }
        }
    }
    return false;
}

void SurfaceDrawContext::drawShapeUsingPathRenderer(const GrClip* clip,
                                                    GrPaint&& paint,
                                                    GrAA aa,
                                                    const SkMatrix& viewMatrix,
                                                    GrStyledShape&& shape,
                                                    bool attemptDrawSimple) {
    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);

    PathRenderer::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;
    using DrawType = PathRendererChain::DrawType;

    PathRenderer* pr = nullptr;

    if (!shape.style().strokeRec().isFillStyle() && !shape.isEmpty()) {
        // Give the tessellation path renderer a chance to claim this stroke before we simplify it.
        PathRenderer* tess = this->drawingManager()->getTessellationPathRenderer();
        if (tess && tess->canDrawPath(canDrawArgs) == PathRenderer::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 && shape.style().applies()) {
        shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
        if (shape.isEmpty()) {
            return;
        }
        pr = this->drawingManager()->getPathRenderer(canDrawArgs, kDisallowSWPathRenderer,
                                                     DrawType::kColor);
    }

    if (!pr) {
        // Fall back on SW renderer as a last resort.
        if (GrAATypeIsHW(aaType)) {
            // No point in trying SW renderer with MSAA.
            aaType = GrAAType::kCoverage;
            canDrawArgs.fAAType = aaType;
        }
        // This can only fail if a) AA type is MSAA or the style is not applied (already checked),
        // or b) the SW renderer's proxy provider is null, which should never happen.
        pr = this->drawingManager()->getSoftwarePathRenderer();
        SkASSERT(pr->canDrawPath(canDrawArgs) != PathRenderer::CanDrawPath::kNo);
#if GR_PATH_RENDERER_SPEW
        SkDebugf("falling back to: %s\n", pr->name());
#endif
    }

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

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 && defined(GPU_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 OpsTask
    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 OpsTask.
    // However, if using dynamic MSAA, the new OpsTask 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
        // OpsTask.
        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->caps()->dmsaaResolveCanBeUsedAsTextureInSameRenderPass()) {
        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(),
                                     skgpu::Mipmapped::kNo,
                                     copyRect,
                                     fit,
                                     skgpu::Budgeted::kYes,
                                     /*label=*/{},
                                     restrictions.fRectsMustMatch);
    SkASSERT(copy);

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

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

}  // namespace skgpu::ganesh
