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

#ifndef SurfaceDrawContext_v1_DEFINED
#define SurfaceDrawContext_v1_DEFINED

#include "include/core/SkCanvas.h"
#include "include/core/SkDrawable.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSurface.h"
#include "include/core/SkSurfaceProps.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/core/SkDevice.h"
#include "src/gpu/ganesh/GrPaint.h"
#include "src/gpu/ganesh/GrRenderTargetProxy.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/gpu/ganesh/GrXferProcessor.h"
#include "src/gpu/ganesh/SurfaceFillContext.h"
#include "src/gpu/ganesh/geometry/GrQuad.h"
#include "src/gpu/ganesh/ops/OpsTask.h"

class GrBackendSemaphore;
class GrClip;
class GrColorSpaceXform;
class GrDrawOp;
class GrDstProxyView;
class GrHardClip;
class GrOp;
struct GrQuadSetEntry;
class GrRenderTarget;
class GrStyledShape;
class GrStyle;
class GrTextureProxy;
struct GrTextureSetEntry;
struct GrUserStencilSettings;
struct SkDrawShadowRec;
struct SkIPoint;
struct SkIRect;
class SkLatticeIter;
class SkMatrixProvider;
class SkMatrix;
class SkPaint;
class SkPath;
struct SkPoint;
struct SkRect;
class SkRegion;
class SkRRect;
struct SkRSXform;
class SkTextBlob;
class SkVertices;

namespace sktext {
class GlyphRunList;
}

namespace skgpu::ganesh {

/**
 * A helper object to orchestrate commands (draws, etc...) for GrSurfaces that are GrRenderTargets.
 */
class SurfaceDrawContext final : public SurfaceFillContext {
public:
    static std::unique_ptr<SurfaceDrawContext> Make(GrRecordingContext*,
                                                    GrColorType,
                                                    sk_sp<GrSurfaceProxy>,
                                                    sk_sp<SkColorSpace>,
                                                    GrSurfaceOrigin,
                                                    const SkSurfaceProps&);

    /* Uses the default texture format for the color type */
    static std::unique_ptr<SurfaceDrawContext> Make(GrRecordingContext*,
                                                    GrColorType,
                                                    sk_sp<SkColorSpace>,
                                                    SkBackingFit,
                                                    SkISize dimensions,
                                                    const SkSurfaceProps&,
                                                    std::string_view label,
                                                    int sampleCnt = 1,
                                                    skgpu::Mipmapped = skgpu::Mipmapped::kNo,
                                                    skgpu::Protected = skgpu::Protected::kNo,
                                                    GrSurfaceOrigin = kBottomLeft_GrSurfaceOrigin,
                                                    skgpu::Budgeted = skgpu::Budgeted::kYes);

    /**
     * Takes custom swizzles rather than determining swizzles from color type and format.
     * It will have color type kUnknown.
     */
    static std::unique_ptr<SurfaceDrawContext> Make(GrRecordingContext*,
                                                    sk_sp<SkColorSpace>,
                                                    SkBackingFit,
                                                    SkISize dimensions,
                                                    const GrBackendFormat&,
                                                    int sampleCnt,
                                                    skgpu::Mipmapped,
                                                    skgpu::Protected,
                                                    skgpu::Swizzle readSwizzle,
                                                    skgpu::Swizzle writeSwizzle,
                                                    GrSurfaceOrigin,
                                                    skgpu::Budgeted,
                                                    const SkSurfaceProps&,
                                                    std::string_view label);

    // Same as previous factory but will try to use fallback GrColorTypes if the one passed in
    // fails. The fallback GrColorType will have at least the number of channels and precision per
    // channel as the passed in GrColorType. It may also swizzle the changes (e.g., BGRA -> RGBA).
    // SRGB-ness will be preserved.
    static std::unique_ptr<SurfaceDrawContext> MakeWithFallback(
            GrRecordingContext*,
            GrColorType,
            sk_sp<SkColorSpace>,
            SkBackingFit,
            SkISize dimensions,
            const SkSurfaceProps&,
            int sampleCnt = 1,
            skgpu::Mipmapped = skgpu::Mipmapped::kNo,
            skgpu::Protected = skgpu::Protected::kNo,
            GrSurfaceOrigin = kBottomLeft_GrSurfaceOrigin,
            skgpu::Budgeted = skgpu::Budgeted::kYes);

    // Creates a SurfaceDrawContext that wraps the passed in GrBackendTexture.
    static std::unique_ptr<SurfaceDrawContext> MakeFromBackendTexture(
            GrRecordingContext*,
            GrColorType,
            sk_sp<SkColorSpace>,
            const GrBackendTexture&,
            int sampleCnt,
            GrSurfaceOrigin,
            const SkSurfaceProps&,
            sk_sp<skgpu::RefCntedCallback> releaseHelper);

    SurfaceDrawContext(GrRecordingContext*,
                       GrSurfaceProxyView readView,
                       GrSurfaceProxyView writeView,
                       GrColorType,
                       sk_sp<SkColorSpace>,
                       const SkSurfaceProps&);

    ~SurfaceDrawContext() override;

    /**
     *  Draw everywhere (respecting the clip) with the paint.
     */
    void drawPaint(const GrClip*, GrPaint&&, const SkMatrix& viewMatrix);

    /**
     * Draw the rect using a paint.
     * @param paint        describes how to color pixels.
     * @param GrAA         Controls whether rect is antialiased
     * @param viewMatrix   transformation matrix
     * @param style        The style to apply. Null means fill. Currently path effects are not
     *                     allowed.
     * The rects coords are used to access the paint (through texture matrix)
     */
    void drawRect(const GrClip*,
                  GrPaint&& paint,
                  GrAA,
                  const SkMatrix& viewMatrix,
                  const SkRect&,
                  const GrStyle* style = nullptr);

    /**
     * Maps a rectangle of shader coordinates to a rectangle and fills that rectangle.
     *
     * @param GrPaint      describes how to color pixels.
     * @param GrAA         Controls whether rect is antialiased
     * @param SkMatrix     transformation matrix which applies to rectToDraw
     * @param rectToDraw   the rectangle to draw
     * @param localRect    the rectangle of shader coordinates applied to rectToDraw
     */
    void fillRectToRect(const GrClip*,
                        GrPaint&&,
                        GrAA,
                        const SkMatrix&,
                        const SkRect& rectToDraw,
                        const SkRect& localRect);

    /**
     * Fills a block of pixels with a paint and a localMatrix, respecting the clip.
     */
    void fillPixelsWithLocalMatrix(const GrClip* clip,
                                   GrPaint&& paint,
                                   const SkIRect& bounds,
                                   const SkMatrix& localMatrix) {
        SkRect rect = SkRect::Make(bounds);
        DrawQuad quad{GrQuad::MakeFromRect(rect, SkMatrix::I()),
                      GrQuad::MakeFromRect(rect, localMatrix), GrQuadAAFlags::kNone};
        this->drawFilledQuad(clip, std::move(paint), &quad);
    }

    /**
     * Creates an op that draws a fill rect with per-edge control over anti-aliasing.
     *
     * This is a specialized version of fillQuadWithEdgeAA, but is kept separate since knowing
     * the geometry is a rectangle affords more optimizations.
     */
    void fillRectWithEdgeAA(const GrClip* clip, GrPaint&& paint, GrQuadAAFlags edgeAA,
                            const SkMatrix& viewMatrix, const SkRect& rect,
                            const SkRect* optionalLocalRect = nullptr) {
        if (edgeAA == GrQuadAAFlags::kAll) {
            this->fillRectToRect(clip, std::move(paint), GrAA::kYes, viewMatrix, rect,
                                 (optionalLocalRect) ? *optionalLocalRect : rect);
            return;
        }
        const SkRect& localRect = optionalLocalRect ? *optionalLocalRect : rect;
        DrawQuad quad{GrQuad::MakeFromRect(rect, viewMatrix), GrQuad(localRect), edgeAA};
        this->drawFilledQuad(clip, std::move(paint), &quad);
    }

    /**
     * Similar to fillRectWithEdgeAA but draws an arbitrary 2D convex quadrilateral transformed
     * by 'viewMatrix', with per-edge control over anti-aliasing. The quad should follow the
     * ordering used by SkRect::toQuad(), which determines how the edge AA is applied:
     *  - "top" = points [0] and [1]
     *  - "right" = points[1] and [2]
     *  - "bottom" = points[2] and [3]
     *  - "left" = points[3] and [0]
     *
     * The last argument, 'optionalLocalQuad', can be null if no separate local coordinates are
     * necessary.
     */
    void fillQuadWithEdgeAA(const GrClip* clip, GrPaint&& paint, GrQuadAAFlags edgeAA,
                            const SkMatrix& viewMatrix, const SkPoint points[4],
                            const SkPoint optionalLocalPoints[4]) {
        const SkPoint* localPoints = optionalLocalPoints ? optionalLocalPoints : points;
        DrawQuad quad{GrQuad::MakeFromSkQuad(points, viewMatrix),
                      GrQuad::MakeFromSkQuad(localPoints, SkMatrix::I()), edgeAA};
        this->drawFilledQuad(clip, std::move(paint), &quad);
    }

    // TODO(michaelludwig) - remove if the bulk API is not useful for SkiaRenderer
    void drawQuadSet(const GrClip* clip, GrPaint&& paint, const SkMatrix& viewMatrix,
                     const GrQuadSetEntry[], int cnt);

    /**
     * Creates an op that draws a subrectangle of a texture. The passed color is modulated by the
     * texture's color. 'srcRect' specifies the rectangle of the texture to draw. 'dstRect'
     * specifies the rectangle to draw in local coords which will be transformed by 'viewMatrix' to
     * device space.
     */
    void drawTexture(const GrClip*,
                     GrSurfaceProxyView,
                     SkAlphaType,
                     GrSamplerState::Filter,
                     GrSamplerState::MipmapMode,
                     SkBlendMode,
                     const SkPMColor4f&,
                     const SkRect& srcRect,
                     const SkRect& dstRect,
                     GrQuadAAFlags,
                     SkCanvas::SrcRectConstraint,
                     const SkMatrix&,
                     sk_sp<GrColorSpaceXform>);

    /**
     * Variant of drawTexture that instead draws the texture applied to 'dstQuad' transformed by
     * 'viewMatrix', using the 'srcQuad' texture coordinates clamped to the optional 'subset'. If
     * 'subset' is null, it's equivalent to using the fast src rect constraint. If 'subset' is
     * provided, the strict src rect constraint is applied using 'subset'.
     */
    void drawTextureQuad(const GrClip* clip,
                         GrSurfaceProxyView view,
                         GrColorType srcColorType,
                         SkAlphaType srcAlphaType,
                         GrSamplerState::Filter filter,
                         GrSamplerState::MipmapMode mm,
                         SkBlendMode mode,
                         const SkPMColor4f& color,
                         const SkPoint srcQuad[4],
                         const SkPoint dstQuad[4],
                         GrQuadAAFlags edgeAA,
                         const SkRect* subset,
                         const SkMatrix& viewMatrix,
                         sk_sp<GrColorSpaceXform> texXform) {
        DrawQuad quad{GrQuad::MakeFromSkQuad(dstQuad, viewMatrix),
                      GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()), edgeAA};
        this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform), filter, mm,
                               color, mode, &quad, subset);
    }

    /**
     * Draws a set of textures with a shared filter, color, view matrix, color xform, and
     * texture color xform. The textures must all have the same GrTextureType and GrConfig.
     *
     * If any entries provide a non-null fDstClip array, it will be read from immediately based on
     * fDstClipCount, so the pointer can become invalid after this returns.
     *
     * 'proxRunCnt' is the number of proxy changes encountered in the entry array. Technically this
     * can be inferred from the array within this function, but the information is already known
     * by SkGpuDevice, so no need to incur another iteration over the array.
     */
    void drawTextureSet(const GrClip*,
                        GrTextureSetEntry[],
                        int cnt,
                        int proxyRunCnt,
                        GrSamplerState::Filter,
                        GrSamplerState::MipmapMode,
                        SkBlendMode mode,
                        SkCanvas::SrcRectConstraint,
                        const SkMatrix& viewMatrix,
                        sk_sp<GrColorSpaceXform> texXform);

    /**
     * Draw a roundrect using a paint.
     *
     * @param paint       describes how to color pixels.
     * @param GrAA        Controls whether rrect is antialiased.
     * @param viewMatrix  transformation matrix
     * @param rrect       the roundrect to draw
     * @param style       style to apply to the rrect. Currently path effects are not allowed.
     */
    void drawRRect(const GrClip*,
                   GrPaint&&,
                   GrAA,
                   const SkMatrix& viewMatrix,
                   const SkRRect& rrect,
                   const GrStyle& style);

    /**
     * Use a fast method to render the ambient and spot shadows for a path.
     * Will return false if not possible for the given path.
     *
     * @param viewMatrix   transformation matrix
     * @param path         the path to shadow
     * @param rec          parameters for shadow rendering
     */
    bool drawFastShadow(const GrClip*,
                        const SkMatrix& viewMatrix,
                        const SkPath& path,
                        const SkDrawShadowRec& rec);

    /**
     * Draws a path.
     *
     * @param paint         describes how to color pixels.
     * @param GrAA          Controls whether the path is antialiased.
     * @param viewMatrix    transformation matrix
     * @param path          the path to draw
     * @param style         style to apply to the path.
     */
    void drawPath(const GrClip*,
                  GrPaint&&,
                  GrAA,
                  const SkMatrix& viewMatrix,
                  const SkPath&,
                  const GrStyle&);

    /**
     * Draws a shape.
     *
     * @param paint         describes how to color pixels.
     * @param GrAA          Controls whether the path is antialiased.
     * @param viewMatrix    transformation matrix
     * @param shape         the shape to draw
     */
    void drawShape(const GrClip*,
                   GrPaint&&,
                   GrAA,
                   const SkMatrix& viewMatrix,
                   GrStyledShape&&);

    /**
     * Draws vertices with a paint.
     *
     * @param   paint            describes how to color pixels.
     * @param   viewMatrix       transformation matrix
     * @param   vertices         specifies the mesh to draw.
     * @param   overridePrimType primitive type to draw. If NULL, derive prim type from vertices.
     * @param   skipColorXform   if true, do not apply a color space transfer function
     */
    void drawVertices(const GrClip*,
                      GrPaint&& paint,
                      const SkMatrixProvider& matrixProvider,
                      sk_sp<SkVertices> vertices,
                      GrPrimitiveType* overridePrimType = nullptr,
                      bool skipColorXform = false);

    /**
     * Draws a custom mesh with a paint.
     *
     * @param   paint            describes how to color pixels.
     * @param   matrixProvider   provides the transformation matrix
     * @param   mesh             the mesh to draw.
     */
    void drawMesh(const GrClip*,
                  GrPaint&& paint,
                  const SkMatrixProvider& matrixProvider,
                  const SkMesh& mesh);

    /**
     * Draws textured sprites from an atlas with a paint. This currently does not support AA for the
     * sprite rectangle edges.
     *
     * @param   paint           describes how to color pixels.
     * @param   viewMatrix      transformation matrix
     * @param   spriteCount     number of sprites.
     * @param   xform           array of compressed transformation data, required.
     * @param   texRect         array of texture rectangles used to access the paint.
     * @param   colors          optional array of per-sprite colors, supercedes
     *                          the paint's color field.
     */
    void drawAtlas(const GrClip*,
                   GrPaint&& paint,
                   const SkMatrix& viewMatrix,
                   int spriteCount,
                   const SkRSXform xform[],
                   const SkRect texRect[],
                   const SkColor colors[]);

    /**
     * Draws a region.
     *
     * @param paint         describes how to color pixels
     * @param viewMatrix    transformation matrix
     * @param aa            should the rects of the region be antialiased.
     * @param region        the region to be drawn
     * @param style         style to apply to the region
     */
    void drawRegion(const GrClip*,
                    GrPaint&& paint,
                    GrAA aa,
                    const SkMatrix& viewMatrix,
                    const SkRegion& region,
                    const GrStyle& style,
                    const GrUserStencilSettings* ss = nullptr);

    /**
     * Draws an oval.
     *
     * @param paint         describes how to color pixels.
     * @param GrAA          Controls whether the oval is antialiased.
     * @param viewMatrix    transformation matrix
     * @param oval          the bounding rect of the oval.
     * @param style         style to apply to the oval. Currently path effects are not allowed.
     */
    void drawOval(const GrClip*,
                  GrPaint&& paint,
                  GrAA,
                  const SkMatrix& viewMatrix,
                  const SkRect& oval,
                  const GrStyle& style);

    /**
     * Draws a partial arc of an oval.
     *
     * @param paint         describes how to color pixels.
     * @param GrGrAA        Controls whether the arc is antialiased.
     * @param viewMatrix    transformation matrix.
     * @param oval          the bounding rect of the oval.
     * @param startAngle    starting angle in degrees.
     * @param sweepAngle    angle to sweep in degrees. Must be in (-360, 360)
     * @param useCenter     true means that the implied path begins at the oval center, connects as
     *                      a line to the point indicated by the start contains the arc indicated by
     *                      the sweep angle. If false the line beginning at the center point is
     *                      omitted.
     * @param style         style to apply to the oval.
     */
    void drawArc(const GrClip*,
                 GrPaint&& paint,
                 GrAA,
                 const SkMatrix& viewMatrix,
                 const SkRect& oval,
                 SkScalar startAngle,
                 SkScalar sweepAngle,
                 bool useCenter,
                 const GrStyle& style);

    /**
     * Draw the image as a set of rects, specified by |iter|.
     */
    void drawImageLattice(const GrClip*,
                          GrPaint&&,
                          const SkMatrix& viewMatrix,
                          GrSurfaceProxyView,
                          SkAlphaType alphaType,
                          sk_sp<GrColorSpaceXform>,
                          GrSamplerState::Filter,
                          std::unique_ptr<SkLatticeIter>,
                          const SkRect& dst);

    /**
     * Draw the text specified by the GlyphRunList.
     *
     * @param viewMatrix      transformationMatrix
     * @param glyphRunList    text, text positions, and paint.
     */
    void drawGlyphRunList(SkCanvas*,
                          const GrClip*,
                          const SkMatrixProvider& viewMatrix,
                          const sktext::GlyphRunList& glyphRunList,
                          SkStrikeDeviceInfo strikeDeviceInfo,
                          const SkPaint& paint);

    /**
     * Adds the necessary signal and wait semaphores and adds the passed in SkDrawable to the
     * command stream.
     */
    void drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>, const SkRect& bounds);

    // called to note the last clip drawn to the stencil buffer.
    // TODO: remove after clipping overhaul.
    void setLastClip(uint32_t clipStackGenID,
                     const SkIRect& devClipBounds,
                     int numClipAnalyticElements);

    // called to determine if we have to render the clip into SB.
    // TODO: remove after clipping overhaul.
    bool mustRenderClip(uint32_t clipStackGenID,
                        const SkIRect& devClipBounds,
                        int numClipAnalyticElements);

    void clearStencilClip(const SkIRect& scissor, bool insideStencilMask) {
        this->internalStencilClear(&scissor, insideStencilMask);
    }

    // While this can take a general clip, since ClipStack relies on this function, it must take
    // care to only provide hard clips or we could get stuck in a loop. The general clip is needed
    // so that path renderers can use this function.
    void stencilRect(const GrClip* clip,
                     const GrUserStencilSettings* ss,
                     GrPaint&& paint,
                     GrAA doStencilMSAA,
                     const SkMatrix& viewMatrix,
                     const SkRect& rect,
                     const SkMatrix* localMatrix = nullptr) {
        // Since this provides stencil settings to drawFilledQuad, it performs a different AA type
        // resolution compared to regular rect draws, which is the main reason it remains separate.
        DrawQuad quad{GrQuad::MakeFromRect(rect, viewMatrix),
                      localMatrix ? GrQuad::MakeFromRect(rect, *localMatrix) : GrQuad(rect),
                      doStencilMSAA == GrAA::kYes ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone};
        this->drawFilledQuad(clip, std::move(paint), &quad, ss);
    }

    // Fills the user stencil bits with a non-zero value at every sample inside the path. This will
    // likely be implemented with a Redbook algorithm, but it is not guaranteed. The samples being
    // rendered to must be zero initially.
    bool stencilPath(const GrHardClip*,
                     GrAA doStencilMSAA,
                     const SkMatrix& viewMatrix,
                     const SkPath&);

    /**
     * Draws a path, either AA or not, and touches the stencil buffer with the user stencil settings
     * for each color sample written.
     */
    bool drawAndStencilPath(const GrHardClip*,
                            const GrUserStencilSettings*,
                            SkRegion::Op op,
                            bool invert,
                            GrAA doStencilMSAA,
                            const SkMatrix& viewMatrix,
                            const SkPath&);

    skgpu::Budgeted isBudgeted() const;

    int maxWindowRectangles() const;

    /*
     * This unique ID will not change for a given SurfaceDrawContext. However, it is _NOT_
     * guaranteed to match the uniqueID of the underlying GrRenderTarget - beware!
     */
    GrSurfaceProxy::UniqueID uniqueID() const { return this->asSurfaceProxy()->uniqueID(); }

    // Allows caller of addDrawOp to know which op list an op will be added to.
    using WillAddOpFn = void(GrOp*, uint32_t opsTaskID);
    // These perform processing specific to GrDrawOp-derived ops before recording them into an
    // op list. Before adding the op to an op list the WillAddOpFn is called. Note that it
    // will not be called in the event that the op is discarded. Moreover, the op may merge into
    // another op after the function is called (either before addDrawOp returns or some time later).
    //
    // If the clip pointer is null, no clipping will be performed.
    void addDrawOp(const GrClip*,
                   GrOp::Owner,
                   const std::function<WillAddOpFn>& = std::function<WillAddOpFn>());
    void addDrawOp(GrOp::Owner op) { this->addDrawOp(nullptr, std::move(op)); }

    bool refsWrappedObjects() const { return this->asRenderTargetProxy()->refsWrappedObjects(); }

    /**
     *  The next time this SurfaceDrawContext is flushed, the gpu will wait on the passed in
     *  semaphores before executing any commands.
     */
    bool waitOnSemaphores(int numSemaphores, const GrBackendSemaphore waitSemaphores[],
                          bool deleteSemaphoresAfterWait);

    int numSamples() const { return this->asRenderTargetProxy()->numSamples(); }
    const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; }
    bool canUseDynamicMSAA() const { return fCanUseDynamicMSAA; }
    bool wrapsVkSecondaryCB() const { return this->asRenderTargetProxy()->wrapsVkSecondaryCB(); }

    bool alwaysAntialias() const {
        return fSurfaceProps.flags() & SkSurfaceProps::kDynamicMSAA_Flag;
    }

    GrAA chooseAA(const SkPaint& paint) {
        return GrAA(paint.isAntiAlias() || this->alwaysAntialias());
    }

    GrAAType chooseAAType(GrAA aa) {
        if (this->numSamples() > 1 || fCanUseDynamicMSAA) {
            // Always trigger DMSAA when it's available. The coverage ops that know how to handle
            // both single and multisample targets without popping will do so without calling
            // chooseAAType.
            return GrAAType::kMSAA;
        }
        return (aa == GrAA::kYes) ? GrAAType::kCoverage : GrAAType::kNone;
    }

    // This entry point should only be called if the backing GPU object is known to be
    // instantiated.
    GrRenderTarget* accessRenderTarget() { return this->asSurfaceProxy()->peekRenderTarget(); }

#if GR_TEST_UTILS
    void testingOnly_SetPreserveOpsOnFullClear() { fPreserveOpsOnFullClear_TestingOnly = true; }
#endif

    void drawStrokedLine(const GrClip*, GrPaint&&, GrAA, const SkMatrix&, const SkPoint[2],
                         const SkStrokeRec&);

private:
    enum class QuadOptimization;

    void willReplaceOpsTask(OpsTask* prevTask, OpsTask* nextTask) override;

    OpsTask::CanDiscardPreviousOps canDiscardPreviousOpsOnFullClear() const override;
    void setNeedsStencil();

    void internalStencilClear(const SkIRect* scissor, bool insideStencilMask);

    // 'stencilSettings' are provided merely for decision making purposes; When non-null,
    // optimization strategies that submit special ops are avoided.
    //
    // 'quad' should be the original draw request on input, and will be updated as
    // appropriate depending on the returned optimization level.
    //
    // If kSubmitted is returned, the provided paint was consumed. Otherwise it is left unchanged.
    QuadOptimization attemptQuadOptimization(const GrClip* clip,
                                             const GrUserStencilSettings* stencilSettings,
                                             DrawQuad* quad,
                                             GrPaint* paint);

    // The overall AA policy is determined by the quad's edge flags: kNone is no AA, and anything
    // else uses some form of anti-aliasing. If 'ss' is non-null, that will be MSAA; otherwise it's
    // MSAA or analytic coverage per chooseAAType(). This will always attempt to apply
    // quad optimizations, so all quad/rect public APIs should rely on this function for consistent
    // clipping behavior. 'quad' will be modified in place to reflect final rendered geometry.
    void drawFilledQuad(const GrClip* clip,
                        GrPaint&& paint,
                        DrawQuad* quad,
                        const GrUserStencilSettings* ss = nullptr);

    // Like drawFilledQuad but does not require using a GrPaint or FP for texturing.
    // 'quad' may be modified in place to reflect final geometry.
    void drawTexturedQuad(const GrClip* clip,
                          GrSurfaceProxyView proxyView,
                          SkAlphaType alphaType,
                          sk_sp<GrColorSpaceXform> textureXform,
                          GrSamplerState::Filter filter,
                          GrSamplerState::MipmapMode,
                          const SkPMColor4f& color,
                          SkBlendMode blendMode,
                          DrawQuad* quad,
                          const SkRect* subset = nullptr);

    // Tries to detect if the given shape is a simple, and draws it without path rendering if
    // we know how.
    bool drawSimpleShape(const GrClip*, GrPaint*, GrAA, const SkMatrix&, const GrStyledShape&);

    // If 'attemptDrawSimple' is true, of if the original shape is marked as having been simplfied,
    // this will attempt to re-route through drawSimpleShape() to see if we can avoid path rendering
    // one more time.
    void drawShapeUsingPathRenderer(const GrClip*, GrPaint&&, GrAA, const SkMatrix&,
                                    GrStyledShape&&, bool attemptDrawSimple = false);

    // Makes a copy of the proxy if it is necessary for the draw and places the texture that should
    // be used by GrXferProcessor to access the destination color in 'result'. If the return
    // value is false then a texture copy could not be made.
    //
    // The op should have already had setClippedBounds called on it.
    bool SK_WARN_UNUSED_RESULT setupDstProxyView(const SkRect& opBounds,
                                                 bool opRequiresMSAA,
                                                 GrDstProxyView* result);

    OpsTask* replaceOpsTaskIfModifiesColor();

    const SkSurfaceProps fSurfaceProps;
    const bool fCanUseDynamicMSAA;

    bool fNeedsStencil = false;

#if GR_TEST_UTILS
    bool fPreserveOpsOnFullClear_TestingOnly = false;
#endif
};

}  // namespace skgpu::ganesh

#endif // SurfaceDrawContext_v1_DEFINED
