/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "src/gpu/graphite/Device.h"

#include "include/core/SkAlphaType.h"
#include "include/core/SkArc.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkClipOp.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRegion.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkStrokeRec.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkVertices.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/GraphiteTypes.h"
#include "include/gpu/graphite/Image.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Surface.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "include/private/base/SingleOwner.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkArenaAlloc.h"
#include "src/base/SkVx.h"
#include "src/core/SkBlendModePriv.h"
#include "src/core/SkBlenderBase.h"
#include "src/core/SkImageFilterTypes.h"  // IWYU pragma: keep
#include "src/core/SkPaintPriv.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkRRectPriv.h"
#include "src/core/SkRectPriv.h"
#include "src/core/SkSpecialImage.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkTraceEvent.h"
#include "src/core/SkVerticesPriv.h"
#include "src/gpu/BlurUtils.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/Swizzle.h"
#include "src/gpu/TiledTextureUtils.h"
#include "src/gpu/graphite/AtlasProvider.h"
#include "src/gpu/graphite/AtlasTypes.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ContextOptionsPriv.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/DrawContext.h"
#include "src/gpu/graphite/DrawList.h"
#include "src/gpu/graphite/DrawParams.h"
#include "src/gpu/graphite/DrawTypes.h"
#include "src/gpu/graphite/Image_Base_Graphite.h"
#include "src/gpu/graphite/Image_Graphite.h"
#include "src/gpu/graphite/KeyContext.h"
#include "src/gpu/graphite/Log.h"
#include "src/gpu/graphite/PaintParams.h"
#include "src/gpu/graphite/PathAtlas.h"
#include "src/gpu/graphite/RasterPathAtlas.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/Renderer.h"
#include "src/gpu/graphite/RendererProvider.h"
#include "src/gpu/graphite/SpecialImage_Graphite.h"
#include "src/gpu/graphite/TextureFormat.h"
#include "src/gpu/graphite/TextureInfoPriv.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/TextureProxyView.h"
#include "src/gpu/graphite/TextureUtils.h"
#include "src/gpu/graphite/geom/AnalyticBlurMask.h"
#include "src/gpu/graphite/geom/BoundsManager.h"
#include "src/gpu/graphite/geom/CoverageMaskShape.h"
#include "src/gpu/graphite/geom/EdgeAAQuad.h"
#include "src/gpu/graphite/geom/Geometry.h"
#include "src/gpu/graphite/geom/IntersectionTree.h"
#include "src/gpu/graphite/geom/NonMSAAClip.h"
#include "src/gpu/graphite/geom/Shape.h"
#include "src/gpu/graphite/geom/SubRunData.h"
#include "src/gpu/graphite/geom/Transform.h"
#include "src/gpu/graphite/task/Task.h"
#include "src/gpu/graphite/task/UploadTask.h"
#include "src/gpu/graphite/text/GlyphData.h"
#include "src/image/SkImage_Base.h"
#include "src/text/gpu/SlugImpl.h"
#include "src/text/gpu/SubRunContainer.h"
#include "src/text/gpu/TextBlobRedrawCoordinator.h"
#include "src/text/gpu/VertexFiller.h"

#include <algorithm>
#include <atomic>
#include <cstddef>
#include <functional>
#include <optional>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>

using RescaleGamma       = SkImage::RescaleGamma;
using RescaleMode        = SkImage::RescaleMode;
using ReadPixelsCallback = SkImage::ReadPixelsCallback;
using ReadPixelsContext  = SkImage::ReadPixelsContext;

#if defined(GPU_TEST_UTILS)
int gOverrideMaxTextureSizeGraphite = 0;
// Allows tests to check how many tiles were drawn on the most recent call to
// Device::drawAsTiledImageRect. This is an atomic because we can write to it from
// multiple threads during "normal" operations. However, the tests that actually
// read from it are done single-threaded.
std::atomic<int> gNumTilesDrawnGraphite{0};
#endif

namespace skgpu::graphite {

class Recording;
enum class TextureFormat : uint8_t;

#define ASSERT_SINGLE_OWNER SkASSERT(fRecorder); SKGPU_ASSERT_SINGLE_OWNER(fRecorder->singleOwner())

namespace {

const SkStrokeRec& DefaultFillStyle() {
    static const SkStrokeRec kFillStyle(SkStrokeRec::kFill_InitStyle);
    return kFillStyle;
}

/** If the paint can be reduced to a solid flood-fill, determine the correct color to fill with. */
std::optional<SkColor4f> extract_paint_color(const PaintParams& paint,
                                             const SkColorInfo& dstColorInfo) {
    SkBlendMode bm = paint.finalBlendMode();
    // Since we don't depend on the dst, a dst-out blend mode implies source is
    // opaque, which causes dst-out to behave like clear.
    if (bm == SkBlendMode::kClear || bm == SkBlendMode::kDstOut) {
        return SkColors::kTransparent;
    }

    // PaintParams has already consolidated constant shaders or images and applied color filters to
    // constant input colors. If the paint still has any of those fields, then we can't extract it.
    if (paint.shader() || paint.imageShader() || paint.colorFilter()) {
        return std::nullopt;
    }

    // However, PaintParams converted the color in sRGB and we need to return this in the
    // destination color space.
    return PaintParams::Color4fPrepForDst(paint.color(), dstColorInfo);
}

// Returns a local rect that has been adjusted such that when it's rasterized with `localToDevice`
// it will be pixel aligned. If this adjustment is not possible (due to transform type or precision)
// then this returns the original local rect unmodified.
//
// If `strokeWidth` is null, it's assumed to be a filled rectangle. If it's not null, on input it
// should hold the stroke width (or 0 for a hairline). After this returns, the stroke width may
// have been adjusted so that outer and inner stroked edges are pixel aligned (in which case the
// underlying rectangle geometry probably won't be pixel aligned).
//
// A best effort is made to align the stroke edges when there's a non-uniform scale factor that
// prevents exactly aligning both X and Y axes.
Rect snap_rect_to_pixels(const Transform& localToDevice,
                         const Rect& rect,
                         float* strokeWidth=nullptr) {
    if (localToDevice.type() > Transform::Type::kRectStaysRect) {
        return rect;
    }

    Rect snappedDeviceRect;
    if (!strokeWidth) {
        // Just a fill, use round() to emulate non-AA rasterization (vs. roundOut() to get the
        // covering bounds). This matches how ClipStack treats clipRects with PixelSnapping::kYes.
        snappedDeviceRect = localToDevice.mapRect(rect).round();
    } else if (strokeWidth) {
        if (*strokeWidth == 0.f) {
            // Hairline case needs to be outset by 1/2 device pixels *before* rounding, and then
            // inset by 1/2px to get the base shape while leaving the stroke width as 0.
            snappedDeviceRect = localToDevice.mapRect(rect);
            snappedDeviceRect.outset(0.5f).round().inset(0.5f);
        } else {
            // For regular strokes, outset by the stroke radius *before* mapping to device space,
            // and then round.
            snappedDeviceRect = localToDevice.mapRect(rect.makeOutset(0.5f*(*strokeWidth))).round();

            // devScales.x() holds scale factor affecting device-space X axis (so max of |m00| or
            // |m01|) and y() holds the device Y axis scale (max of |m10| or |m11|).
            skvx::float2 devScales = max(abs(skvx::float2(localToDevice.matrix().rc(0,0),
                                                          localToDevice.matrix().rc(1,0))),
                                         abs(skvx::float2(localToDevice.matrix().rc(0,1),
                                                          localToDevice.matrix().rc(1,1))));
            skvx::float2 devStrokeWidth = max(round(*strokeWidth * devScales), 1.f);

            // Prioritize the axis that has the largest device-space radius (any error from a
            // non-uniform scale factor will go into the inner edge of the opposite axis).
            // During animating scale factors, preserving the large axis leads to better behavior.
            if (devStrokeWidth.x() > devStrokeWidth.y()) {
                *strokeWidth = devStrokeWidth.x() / devScales.x();
            } else {
                *strokeWidth = devStrokeWidth.y() / devScales.y();
            }

            snappedDeviceRect.inset(0.5f * devScales * (*strokeWidth));
        }
    }

    // Map back to local space so that it can be drawn with appropriate coord interpolation.
    Rect snappedLocalRect = localToDevice.inverseMapRect(snappedDeviceRect);
    // If the transform has an extreme scale factor or large translation, it's possible for floating
    // point precision to round `snappedLocalRect` in such a way that re-transforming it by the
    // local-to-device matrix no longer matches the expected device bounds.
    if (snappedDeviceRect.nearlyEquals(localToDevice.mapRect(snappedLocalRect))) {
        return snappedLocalRect;
    } else {
        // In this case we will just return the original geometry and the pixels will show
        // fractional coverage.
        return rect;
    }
}

// If possible, snaps `dstRect` such that its device-space transformation lands on pixel bounds,
// and then updates `srcRect` to match the original src-to-dst coordinate mapping.
void snap_src_and_dst_rect_to_pixels(const Transform& localToDevice,
                                     SkRect* srcRect,
                                     SkRect* dstRect) {
    if (localToDevice.type() > Transform::Type::kRectStaysRect) {
        return;
    }

    // Assume snapping will succeed and always update 'src' to match; in the event snapping
    // returns the original dst rect, then the recalculated src rect is a no-op.
    SkMatrix dstToSrc = SkMatrix::RectToRectOrIdentity(*dstRect, *srcRect);
    *dstRect = snap_rect_to_pixels(localToDevice, *dstRect).asSkRect();
    *srcRect = dstToSrc.mapRect(*dstRect);
}

// Returns the inner bounds of `geometry` that is known to have full coverage. This does not worry
// about identifying draws that are equivalent pixel aligned and thus entirely full coverage, as
// that should have been caught earlier and used a coverage-less renderer from the beginning.
//
// An empty Rect is returned if there is no available inner bounds, or if it's not worth performing.
Rect get_inner_bounds(const Geometry& geometry, const Transform& localToDevice) {
    auto applyAAInset = [&](Rect rect) {
        // If the aa inset is too large, rect becomes empty and the inner bounds draw is
        // automatically skipped
        float aaInset = localToDevice.localAARadius(rect);
        rect.inset(aaInset);
        // Only add a second draw if it will have a reasonable number of covered pixels; otherwise
        // we are just adding draws to sort and pipelines to switch around.
        static constexpr float kInnerFillArea = 64*64;
        // Approximate the device-space area based on the minimum scale factor of the transform.
        float scaleFactor = sk_ieee_float_divide(1.f, aaInset);
        return scaleFactor*rect.area() >= kInnerFillArea ? rect : Rect::InfiniteInverted();
    };

    if (geometry.isEdgeAAQuad()) {
        const EdgeAAQuad& quad = geometry.edgeAAQuad();
        if (quad.isRect()) {
            return applyAAInset(quad.bounds());
        }
        // else currently we don't have a function to calculate the largest interior axis aligned
        // bounding box of a quadrilateral so skip the inner fill draw.
    } else if (geometry.isShape()) {
        const Shape& shape = geometry.shape();
        if (shape.isRect()) {
            return applyAAInset(shape.rect());
        } else if (shape.isRRect()) {
            return applyAAInset(SkRRectPriv::InnerBounds(shape.rrect()));
        }
    }

    return Rect::InfiniteInverted();
}

SkIRect rect_to_pixelbounds(const Rect& r) {
    return r.makeRoundOut().asSkIRect();
}

bool is_pixel_aligned(const Rect& r, const Transform& t) {
    if (t.type() <= Transform::Type::kRectStaysRect) {
        Rect devRect = t.mapRect(r);
        return devRect.nearlyEquals(devRect.makeRound(), Shape::kDefaultPixelTolerance);
    }

    return false;
}

bool is_simple_shape(const Shape& shape, const Transform& localToDevice, SkStrokeRec::Style type) {
    if (shape.isFloodFill()) {
        return true; // Always supported
    } else if (!shape.inverted() && type != SkStrokeRec::kStrokeAndFill_Style) {
        // A filled line renders nothing but that should be caught earlier, so the actual branches
        // in this function can be simplified.
        SkASSERT(!shape.isLine() || type != SkStrokeRec::kFill_Style);

        if (shape.isRRect() && type == SkStrokeRec::kStroke_Style) {
            // Non-hairline stroked round rects require the corner radii to be circular to be
            // compatible with the shared Renderer.
            const float tol =
                    localToDevice.localAARadius(shape.bounds()) * Shape::kDefaultPixelTolerance;
            return SkRRectPriv::AllCornersRelativelyCircular(shape.rrect(), tol);
        } else if (shape.isRRect() || shape.isRect() || shape.isLine()) {
            // There are no restrictions on filled or hairline [r]rects and lines.
            return true;
        } // Fallthrough
    }

    // Requires path rendering
    return false;
}

class ScopedDrawBuilder {
public:
    explicit ScopedDrawBuilder(Recorder* recorder)
            : fRecorder(recorder),
              fKeyAndDataBuilder(fRecorder->priv().popOrCreateKeyAndDataBuilder()) {
        SkASSERT(fKeyAndDataBuilder);
        SkDEBUGCODE(this->gatherer()->checkReset());
        SkDEBUGCODE(this->builder()->checkReset());
    }

    ~ScopedDrawBuilder() {
        SkASSERT(fKeyAndDataBuilder && fRecorder);
        // The PipelineDataGatherer must be reset before being returned to the pool for reuse.
        this->gatherer()->resetForDraw();
        fRecorder->priv().pushKeyAndDataBuilder(std::move(fKeyAndDataBuilder));
    }

    PipelineDataGatherer* gatherer() { return &fKeyAndDataBuilder->first; }
    PaintParamsKeyBuilder* builder() { return &fKeyAndDataBuilder->second; }

    ScopedDrawBuilder(const ScopedDrawBuilder&) = delete;
    ScopedDrawBuilder& operator=(const ScopedDrawBuilder&) = delete;

private:
    Recorder* fRecorder;
    std::unique_ptr<KeyAndDataBuilder> fKeyAndDataBuilder;
};

} // anonymous namespace

/**
 * IntersectionTreeSet controls multiple IntersectionTrees to organize all add rectangles into
 * disjoint sets. For a given CompressedPaintersOrder and bounds, it returns the smallest
 * DisjointStencilIndex that guarantees the bounds are disjoint from all other draws that use the
 * same painters order and stencil index.
 */
class Device::IntersectionTreeSet {
public:
    IntersectionTreeSet() = default;

    DisjointStencilIndex add(CompressedPaintersOrder drawOrder, Rect rect) {
        auto& trees = fTrees[drawOrder];
        DisjointStencilIndex stencil = DisjointStencilIndex::First();
        for (auto&& tree : trees) {
            if (tree->add(rect)) {
                return stencil;
            }
            stencil = stencil.next(); // advance to the next tree's index
        }

        // If here, no existing intersection tree can hold the rect so add a new one
        SkASSERT(stencil != DrawOrder::kUnassigned);
        IntersectionTree* newTree = this->makeTree();
        SkAssertResult(newTree->add(rect));
        trees.push_back(newTree);
        return stencil;
    }

    void reset() {
        fTrees.clear();
        fTreeStore.reset();
    }

private:
    struct Hash {
        size_t operator()(const CompressedPaintersOrder& o) const noexcept { return o.bits(); }
    };

    IntersectionTree* makeTree() {
        return fTreeStore.make<IntersectionTree>();
    }

    // Each compressed painters order defines a barrier around draws so each order's set of draws
    // are independent, even if they may intersect. Within each order, the list of trees holds the
    // IntersectionTrees representing each disjoint set.
    // TODO: This organization of trees is logically convenient but may need to be optimized based
    // on real world data (e.g. how sparse is the map, how long is each vector of trees,...)
    std::unordered_map<CompressedPaintersOrder, std::vector<IntersectionTree*>, Hash> fTrees;
    SkSTArenaAllocWithReset<4 * sizeof(IntersectionTree)> fTreeStore;
};

sk_sp<Device> Device::Make(Recorder* recorder,
                           const SkImageInfo& ii,
                           skgpu::Budgeted budgeted,
                           Mipmapped mipmapped,
                           SkBackingFit backingFit,
                           const SkSurfaceProps& props,
                           LoadOp initialLoadOp,
                           std::string_view label,
                           bool registerWithRecorder) {
    SkASSERT(!(mipmapped == Mipmapped::kYes && backingFit == SkBackingFit::kApprox));
    if (!recorder) {
        return nullptr;
    }

    const Caps* caps = recorder->priv().caps();
    SkISize backingDimensions = backingFit == SkBackingFit::kApprox ? GetApproxSize(ii.dimensions())
                                                                    : ii.dimensions();
    auto textureInfo = caps->getDefaultSampledTextureInfo(ii.colorType(),
                                                          mipmapped,
                                                          recorder->priv().isProtected(),
                                                          Renderable::kYes);

    return Make(recorder,
                TextureProxy::Make(caps, recorder->priv().resourceProvider(),
                                   backingDimensions, textureInfo, label, budgeted),
                ii.dimensions(),
                ii.colorInfo(),
                props,
                initialLoadOp,
                registerWithRecorder);
}

sk_sp<Device> Device::Make(Recorder* recorder,
                           sk_sp<TextureProxy> target,
                           SkISize deviceSize,
                           const SkColorInfo& colorInfo,
                           const SkSurfaceProps& props,
                           LoadOp initialLoadOp,
                           bool registerWithRecorder) {
    if (!recorder || !target) {
        return nullptr;
    }

    // DrawContext::Make ensures `target` can be rendered into, but if the path strategy might
    // require MSAA, then we need to make sure a multisampled attachment can also be created later.
    // - This would also apply for compute renderers that have to write directly to `target`, but
    //   the current versions of compute render into separate compute-compatible textures instead.
    const Caps* caps = recorder->priv().caps();
    switch (recorder->priv().rendererProvider()->pathRendererStrategy()) {
        case PathRendererStrategy::kTessellationAndSmallAtlas:
            [[fallthrough]];
        case PathRendererStrategy::kTessellation:
            if (caps->getCompatibleMSAASampleCount(target->textureInfo()) <= SampleCount::k1) {
                return nullptr;
            }
            break;

        case PathRendererStrategy::kCPUSparseStripsMSAA8:
        case PathRendererStrategy::kRasterAtlas:
        case PathRendererStrategy::kComputeAnalyticAA:
        case PathRendererStrategy::kComputeMSAA16:
        case PathRendererStrategy::kComputeMSAA8:
            // No additional support required
            break;
    }

    sk_sp<DrawContext> dc = DrawContext::Make(recorder->priv().caps(),
                                              std::move(target),
                                              deviceSize,
                                              colorInfo,
                                              props);
    if (!dc) {
        return nullptr;
    } else if (initialLoadOp == LoadOp::kClear) {
        dc->clear(SkColors::kTransparent);
    } else if (initialLoadOp == LoadOp::kDiscard) {
        dc->discard();
    } // else kLoad is the default initial op for a DrawContext

    sk_sp<Device> device{new Device(recorder, std::move(dc))};
    if (registerWithRecorder) {
        // We don't register the device with the recorder until after the constructor has returned.
        recorder->registerDevice(device);
    } else {
        // Since it's not registered, it should go out of scope before nextRecordingID() changes
        // from what is saved to fScopedRecordingID.
        SkDEBUGCODE(device->fScopedRecordingID = recorder->priv().nextRecordingID();)
    }
    return device;
}

// These default tuning numbers for the HybridBoundsManager were chosen from looking at performance
// and accuracy curves produced by the BoundsManagerBench for random draw bounding boxes. This
// config will use brute force for the first 64 draw calls to the Device and then switch to a grid
// that is dynamically sized to produce cells that are 16x16, up to a grid that's 32x32 cells.
// This seemed like a sweet spot balancing accuracy for low-draw count surfaces and overhead for
// high-draw count and high-resolution surfaces. With the 32x32 grid limit, cell size will increase
// above 16px when the surface dimension goes above 512px.
// TODO: These could be exposed as context options or surface options, and we may want to have
// different strategies in place for a base device vs. a layer's device.
static constexpr int kGridCellSize = 16;
static constexpr int kMaxBruteForceN = 64;
static constexpr int kMaxGridSize = 32;

Device::Device(Recorder* recorder, sk_sp<DrawContext> dc)
        : SkDevice(dc->imageInfo(), dc->surfaceProps())
        , fRecorder(recorder)
        , fDC(std::move(dc))
        , fClip(this)
        , fColorDepthBoundsManager(std::make_unique<HybridBoundsManager>(
                  fDC->imageInfo().dimensions(), kGridCellSize, kMaxBruteForceN, kMaxGridSize))
        , fDisjointStencilSet(std::make_unique<IntersectionTreeSet>())
        , fCachedLocalToDevice(SkM44())
        , fCurrentDepth(DrawOrder::kClearDepth)
        , fSubRunControl(recorder->priv().caps()->getSubRunControl(
                fDC->surfaceProps().isUseDeviceIndependentFonts())) {
    SkASSERT(SkToBool(fDC) && SkToBool(fRecorder));
}

Device::~Device() {
    // The Device should have been marked immutable before it's destroyed, or the Recorder was the
    // last holder of a reference to it and de-registered the device as part of its cleanup.
    // However, if the Device was not registered with the recorder (i.e. a scratch device) we don't
    // require that its recorder be adandoned. Scratch devices must either have been marked
    // immutable or be destroyed before the recorder has been snapped.
    SkASSERT(!fRecorder || fScopedRecordingID != 0);
#if defined(SK_DEBUG)
    if (fScopedRecordingID != 0 && fRecorder) {
        SkASSERT(fScopedRecordingID == fRecorder->priv().nextRecordingID());
    }
    // else it wasn't a scratch device, or it was a scratch device that was marked immutable so its
    // lifetime was validated when setImmutable() was called.
#endif
}

#if defined(GPU_TEST_UTILS)

int Device::testingOnly_pendingRenderSteps() const {
    return fDC->pendingRenderSteps();
}

#endif

void Device::setImmutable() {
    if (fRecorder) {
        // Push any pending work to the Recorder now. setImmutable() is only called by the
        // destructor of a client-owned Surface, or explicitly in layer/filtering workflows. In
        // both cases this is restricted to the Recorder's thread. This is in contrast to ~Device(),
        // which might be called from another thread if it was linked to an Image used in multiple
        // recorders.
        this->flushPendingWork(/*drawContext=*/nullptr);
        fRecorder->deregisterDevice(this);
        // Abandoning the recorder ensures that there are no further operations that can be recorded
        // and is relied on by Image::notifyInUse() to detect when it can unlink from a Device.
        this->abandonRecorder();
    }
}

bool Device::notifyInUse(Recorder* recorder, DrawContext* drawContext) {
    if (this->isScratchDevice()) {
        if (fLastTask) {
            // Increment the pending read count for the device's target
            recorder->priv().addPendingRead(this->target());
            if (drawContext) {
                // Add a reference to the device's drawTask to `drawContext` if that's provided.
                drawContext->recordDependency(fLastTask);
            } else {
                // If there's no `drawContext` this notify represents a copy, so for now append the
                // task to the root task list since that is where the subsequent copy task will go
                // as well.
                recorder->priv().add(fLastTask);
            }
        } else {
            // If there's no draw task yet, there are two possible scenarios:
            //
            // 1) the device is being drawn into a child scratch device (backdrop filter or
            //    init-from-prev layer), and the child will later on be drawn back into the device's
            //    `drawContext`. In this case `device` should already have performed an internal
            //    flush and have no pending work, and not yet be marked immutable. The correct
            //    action at this point in time is to do nothing: the final task order in the
            //    device's DrawTask will be pre-notified tasks into the device's target, then the
            //    child's DrawTask when it's drawn back into `device`, and then any post tasks that
            //    further modify the `device`'s target.
            // 2) the scratch device was flushed to a drawContext's local task list, resulting in no
            //    pending work but also no lastTask. The correct action is again to do nothing. In
            //    this case, it is also possible that the device was not registered with the
            //    recorder.
            SkASSERT(!fRecorder || fRecorder == recorder);
        }

        // Scratch devices are often already marked immutable, but they are also the way in which
        // Image finds the last snapped DrawTask so we don't unlink scratch devices. The scratch
        // image view will be short-lived as well, or the device will transition to a non-scratch
        // device in a future Recording and then it will be unlinked then. Thus, we always return
        // false for scratch devices so they are not unlinked from their images.
        return false;
    } else {
        // Automatic flushing of image views only happens when mixing reads and writes on the
        // originating Recorder. Draws of the view on another Recorder will always see the texture
        // content dependent on how Recordings are inserted.
        if (fRecorder == recorder) {
            // Non-scratch devices push their tasks to the root task list to maintain an order
            // consistent with the client-triggering actions. Because of this, there's no need to
            // add references to the `drawContext` that the device is being drawn into.
            this->flushPendingWork(/*drawContext=*/nullptr);

            if (drawContext) {
                // But if we are being drawn into another context, remember that there is an
                // outstanding dependency on the current state of this device, in which case it's
                // next flush must also flush those other devices before its new tasks are added.
                fMustFlushDependencies = true;
            }
        }
        // Return true (to unlink with the image) if the non-scratch surface is immutable since this
        // Device cannot record any more commands that will modify its texture.
        return !SkToBool(fRecorder) || this->unique();
    }
}

bool Device::hasPendingReads(const TextureProxy* texture) const {
    return fRecorder && fDC->readsTexture(texture);
}

const Transform& Device::localToDeviceTransform() {
    if (this->checkLocalToDeviceDirty()) {
        fCachedLocalToDevice = Transform{this->localToDevice44()};
    }
    return fCachedLocalToDevice;
}

SkStrikeDeviceInfo Device::strikeDeviceInfo() const {
    return {this->surfaceProps(), this->scalerContextFlags(), &fSubRunControl};
}

sk_sp<SkDevice> Device::createDevice(const CreateInfo& info, const SkPaint*) {
    // TODO: Inspect the paint and create info to determine if there's anything that has to be
    // modified to support inline subpasses.
    SkSurfaceProps props =
        this->surfaceProps().cloneWithPixelGeometry(info.fPixelGeometry);

    // Skia's convention is to only clear a device if it is non-opaque.
    LoadOp initialLoadOp = info.fInfo.isOpaque() ? LoadOp::kDiscard : LoadOp::kClear;

    std::string label = this->target()->label();
    if (label.empty()) {
        label = "ChildDevice";
    } else {
        label += "_ChildDevice";
    }

    return Make(fRecorder,
                info.fInfo,
                skgpu::Budgeted::kYes,
                Mipmapped::kNo,
                SkBackingFit::kApprox,
                props,
                initialLoadOp,
                label);
}

sk_sp<SkSurface> Device::makeSurface(const SkImageInfo& ii, const SkSurfaceProps& props) {
    return SkSurfaces::RenderTarget(fRecorder, ii, Mipmapped::kNo, &props);
}

// Although we have a drawContext here, we pass a nullptr to both flushPendingWork and Image::Copy
// so that tasks end up on the root task list.
sk_sp<Image> Device::makeImageCopy(const SkIRect& subset,
                                   Budgeted budgeted,
                                   Mipmapped mipmapped,
                                   SkBackingFit backingFit) {
    ASSERT_SINGLE_OWNER
    this->flushPendingWork(/*drawContext=*/nullptr);

    const SkColorInfo& colorInfo = this->imageInfo().colorInfo();
    TextureProxyView srcView = this->readSurfaceView();
    if (!srcView) {
        // readSurfaceView() returns an empty view when the target is not texturable. Create an
        // equivalent view for the blitting operation.
        Swizzle readSwizzle = fRecorder->priv().caps()->getReadSwizzle(
                colorInfo.colorType(), this->target()->textureInfo());
        srcView = {sk_ref_sp(this->target()), readSwizzle};
    }
    std::string label = this->target()->label();
    if (label.empty()) {
        label = "CopyDeviceTexture";
    } else {
        label += "_DeviceCopy";
    }

    return Image::Copy(fRecorder, /*drawContext=*/nullptr, srcView, colorInfo, subset, budgeted,
                       mipmapped, backingFit, label);
}

bool Device::onReadPixels(const SkPixmap& pm, int srcX, int srcY) {
#if defined(GPU_TEST_UTILS)
    // This testing-only function should only be called before the Device has detached from its
    // Recorder, since it's accessed via the test-held Surface.
    ASSERT_SINGLE_OWNER
    if (Context* context = fRecorder->priv().context()) {
        // Add all previous commands generated to the command buffer.
        // If the client snaps later they'll only get post-read commands in their Recording,
        // but since they're doing a readPixels in the middle that shouldn't be unexpected.
        std::unique_ptr<Recording> recording = fRecorder->snap();
        if (!recording) {
            return false;
        }
        InsertRecordingInfo info;
        info.fRecording = recording.get();
        if (!context->insertRecording(info)) {
            return false;
        }
        return context->priv().readPixels(pm, fDC->target(), this->imageInfo(), srcX, srcY);
    }
#endif
    // We have no access to a context to do a read pixels here.
    return false;
}

bool Device::onWritePixels(const SkPixmap& src, int x, int y) {
    ASSERT_SINGLE_OWNER
    // TODO: we may need to share this in a more central place to handle uploads
    // to backend textures

    const TextureProxy* target = fDC->target();

    // TODO: add mipmap support for createBackendTexture

    if (src.colorType() == kUnknown_SkColorType) {
        return false;
    }

    // If one alpha type is unknown and the other isn't, it's too underspecified.
    if ((src.alphaType() == kUnknown_SkAlphaType) !=
        (this->imageInfo().alphaType() == kUnknown_SkAlphaType)) {
        return false;
    }

    // TODO: canvas2DFastPath?

    if (!fRecorder->priv().caps()->isCopyableDst(target->textureInfo())) {
        auto image = SkImages::RasterFromPixmap(src, nullptr, nullptr);
        image = SkImages::TextureFromImage(fRecorder, image.get());
        if (!image) {
            return false;
        }

        SkPaint paint;
        paint.setBlendMode(SkBlendMode::kSrc);
        this->drawImageRect(image.get(),
                            /*src=*/nullptr,
                            SkRect::MakeXYWH(x, y, src.width(), src.height()),
                            SkFilterMode::kNearest,
                            paint,
                            SkCanvas::kFast_SrcRectConstraint);
        return true;
    }

    // TODO: check for flips and either handle here or pass info to UploadTask

    // Determine rect to copy
    SkIRect dstRect = SkIRect::MakePtSize({x, y}, src.dimensions());
    if (!target->isFullyLazy() && !dstRect.intersect(SkIRect::MakeSize(target->dimensions()))) {
        return false;
    }

    // Set up copy location
    const void* addr = src.addr(dstRect.fLeft - x, dstRect.fTop - y);
    std::vector<MipLevel> levels;
    levels.push_back({addr, src.rowBytes()});

    // The writePixels() still respects painter's order, so flush everything to tasks before this
    // recording the upload for the pixel data.
    this->internalFlush();
    // The new upload will be executed before any new draws are recorded and also ensures that
    // the next call to flushDeviceToRecorder() will produce a non-null DrawTask. If this Device's
    // target is mipmapped, mipmap generation tasks will be added automatically at that point.
    const UploadSource uploadSource = UploadSource::Make(fRecorder->priv().caps(),
                                                         *fDC->refTarget(),
                                                         src.info().colorInfo(),
                                                         this->imageInfo().colorInfo(),
                                                         levels,
                                                         dstRect);
    if (!uploadSource.isValid()) {
        return false;
    }
    return fDC->recordUpload(fRecorder,
                             fDC->refTarget(),
                             src.info().colorInfo(),
                             this->imageInfo().colorInfo(),
                             uploadSource,
                             dstRect,
                             nullptr);
}


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

bool Device::isClipAntiAliased() const {
    // All clips are AA'ed unless it's wide-open, empty, or a device-rect with integer coordinates
    ClipStack::ClipState type = fClip.clipState();
    if (type == ClipStack::ClipState::kWideOpen || type == ClipStack::ClipState::kEmpty) {
        return false;
    } else if (type == ClipStack::ClipState::kDeviceRect) {
        const ClipStack::Element rect = *fClip.begin();
        SkASSERT(rect.fShape.isRect() && rect.fLocalToDevice.type() == Transform::Type::kIdentity);
        return rect.fShape.rect() != rect.fShape.rect().makeRoundOut();
    } else {
        return true;
    }
}

SkIRect Device::devClipBounds() const {
    return rect_to_pixelbounds(fClip.conservativeBounds());
}

// TODO: This is easy enough to support, but do we still need this API in Skia at all?
void Device::android_utils_clipAsRgn(SkRegion* region) const {
    SkIRect bounds = this->devClipBounds();
    // Assume wide open and then perform intersect/difference operations reducing the region
    region->setRect(bounds);
    const SkRegion deviceBounds(bounds);
    for (const ClipStack::Element& e : fClip) {
        SkRegion tmp;
        if (e.fShape.isRect() && e.fLocalToDevice.type() == Transform::Type::kIdentity) {
            tmp.setRect(rect_to_pixelbounds(e.fShape.rect()));
        } else {
            SkPath tmpPath = e.fShape.asPath().makeTransform(e.fLocalToDevice);
            tmp.setPath(tmpPath, deviceBounds);
        }

        region->op(tmp, (SkRegion::Op) e.fOp);
    }
}

void Device::clipRect(const SkRect& rect, SkClipOp op, bool aa) {
    SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference);
    auto snapping = aa ? ClipStack::PixelSnapping::kNo : ClipStack::PixelSnapping::kYes;
    fClip.clipShape(this->localToDeviceTransform(), Shape{rect}, op, snapping);
}

void Device::clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
    SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference);
    auto snapping = aa ? ClipStack::PixelSnapping::kNo : ClipStack::PixelSnapping::kYes;
    fClip.clipShape(this->localToDeviceTransform(), Shape{rrect}, op, snapping);
}

void Device::clipPath(const SkPath& path, SkClipOp op, bool aa) {
    SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference);
    // TODO: Ensure all path inspection is handled here or in SkCanvas, and that non-AA rects as
    // paths are routed appropriately.
    // TODO: Must also detect paths that are lines so the clip stack can be set to empty
    fClip.clipShape(this->localToDeviceTransform(), Shape{path}, op);
}

void Device::onClipShader(sk_sp<SkShader> shader) {
    fClip.clipShader(std::move(shader));
}

// TODO: Is clipRegion() on the deprecation chopping block. If not it should be...
void Device::clipRegion(const SkRegion& globalRgn, SkClipOp op) {
    SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference);

    Transform globalToDevice{this->globalToDevice()};

    if (globalRgn.isEmpty()) {
        fClip.clipShape(globalToDevice, Shape{}, op);
    } else if (globalRgn.isRect()) {
        fClip.clipShape(globalToDevice, Shape{SkRect::Make(globalRgn.getBounds())}, op,
                        ClipStack::PixelSnapping::kYes);
    } else {
        // TODO: Can we just iterate the region and do non-AA rects for each chunk?
        SkPath path = globalRgn.getBoundaryPath();
        fClip.clipShape(globalToDevice, Shape{path}, op);
    }
}

void Device::replaceClip(const SkIRect& rect) {
    // ReplaceClip() is currently not intended to be supported in Graphite since it's only used
    // for emulating legacy clip ops in Android Framework, and apps/devices that require that
    // should not use Graphite. However, if it needs to be supported, we could probably implement
    // it by:
    //  1. Flush all pending clip element depth draws.
    //  2. Draw a fullscreen rect to the depth attachment using a Z value greater than what's
    //     been used so far.
    //  3. Make sure all future "unclipped" draws use this Z value instead of 0 so they aren't
    //     sorted before the depth reset.
    //  4. Make sure all prior elements are inactive so they can't affect subsequent draws.
    //
    // For now, just ignore it.
}

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

void Device::drawPaint(const SkPaint& paint) {
    ASSERT_SINGLE_OWNER

    Shape inverseFill; // defaults to empty
    inverseFill.setInverted(true);
    // An empty shape with an inverse fill completely floods the clip
    SkASSERT(inverseFill.isFloodFill());

    this->drawGeometry(this->localToDeviceTransform(),
                       Geometry(inverseFill),
                       PaintParams(paint),
                       DefaultFillStyle());
}

void Device::drawRect(const SkRect& r, const SkPaint& paint) {
    Rect rectToDraw(r);
    SkStrokeRec style(paint);
    if (!paint.isAntiAlias()) {
        // Graphite assumes everything is anti-aliased. In the case of axis-aligned non-aa requested
        // rectangles, we snap the local geometry to land on pixel boundaries to emulate non-aa.
        if (style.isFillStyle()) {
            rectToDraw = snap_rect_to_pixels(this->localToDeviceTransform(), rectToDraw);
        } else {
            const bool strokeAndFill = style.getStyle() == SkStrokeRec::kStrokeAndFill_Style;
            float strokeWidth = style.getWidth();
            rectToDraw = snap_rect_to_pixels(this->localToDeviceTransform(),
                                             rectToDraw, &strokeWidth);
            style.setStrokeStyle(strokeWidth, strokeAndFill);
        }
    }
    this->drawGeometryWithPathEffect(this->localToDeviceTransform(),
                                     Geometry(Shape(rectToDraw)),
                                     PaintParams(paint),
                                     style,
                                     paint.getPathEffect());
}

void Device::drawVertices(const SkVertices* vertices, sk_sp<SkBlender> blender,
                          const SkPaint& paint, bool skipColorXform)  {
    // A null blender is normally equivalent to SrcOver; coerce it to non-null so that nullity
    // can be used by PaintParamsKeyBuilder to know when to add primitive blending blocks.
    // Use null for the primitive blender if `vertices` does not have per-vertex colors.
    const SkBlender* primitiveBlender =
            !vertices->priv().hasColors() ? nullptr :
                                  blender ? blender.get()
                                          : GetBlendModeSingleton(SkBlendMode::kSrcOver);
    this->drawGeometry(this->localToDeviceTransform(),
                       Geometry(sk_ref_sp(vertices)),
                       PaintParams(paint, primitiveBlender, skipColorXform),
                       DefaultFillStyle());
}

bool Device::drawAsTiledImageRect(SkCanvas* canvas,
                                  const SkImage* image,
                                  const SkRect* src,
                                  const SkRect& dst,
                                  const SkSamplingOptions& sampling,
                                  const SkPaint& paint,
                                  SkCanvas::SrcRectConstraint constraint) {
    auto recorder = canvas->recorder();
    if (!recorder) {
        return false;
    }
    SkASSERT(src);

    // For Graphite this is a pretty loose heuristic. The Recorder-local cache size (relative
    // to the large image's size) is used as a proxy for how conservative we should be when
    // allocating tiles. Since the tiles will actually be owned by the client (via an
    // ImageProvider) they won't actually add any memory pressure directly to Graphite.
    size_t cacheSize = recorder->priv().getResourceCacheLimit();
    size_t maxTextureSize = recorder->priv().caps()->maxTextureSize();

#if defined(GPU_TEST_UTILS)
    if (gOverrideMaxTextureSizeGraphite) {
        maxTextureSize = gOverrideMaxTextureSizeGraphite;
    }
    gNumTilesDrawnGraphite.store(0, std::memory_order_relaxed);
#endif

    // DrawAsTiledImageRect produces per-edge AA quads, which do not participate in non-AA pixel
    // snapping emulation. To match an un-tiled drawImageRect, round the src and dst geometry
    // before any tiling occurs.
    SkRect finalSrc = *src;
    SkRect finalDst = dst;
    if (!paint.isAntiAlias()) {
        snap_src_and_dst_rect_to_pixels(this->localToDeviceTransform(),
                                        &finalSrc, &finalDst);
    }

    [[maybe_unused]] auto [wasTiled, numTiles] =
            skgpu::TiledTextureUtils::DrawAsTiledImageRect(canvas,
                                                           image,
                                                           finalSrc,
                                                           finalDst,
                                                           SkCanvas::kAll_QuadAAFlags,
                                                           sampling,
                                                           &paint,
                                                           constraint,
                                                           /* sharpenMM= */ true,
                                                           cacheSize,
                                                           maxTextureSize);
#if defined(GPU_TEST_UTILS)
    gNumTilesDrawnGraphite.store(numTiles, std::memory_order_relaxed);
#endif
    return wasTiled;
}

void Device::drawOval(const SkRect& oval, const SkPaint& paint) {
    if (paint.getPathEffect()) {
        // Dashing requires that the oval path starts on the right side and travels clockwise. This
        // is the default for the SkPath::Oval constructor, as used by SkBitmapDevice.
        this->drawGeometryWithPathEffect(this->localToDeviceTransform(),
                                         Geometry(Shape(SkPath::Oval(oval))),
                                         PaintParams(paint),
                                         SkStrokeRec(paint),
                                         paint.getPathEffect());
    } else {
        // TODO: This has wasted effort from the SkCanvas level since it instead converts rrects
        // that happen to be ovals into this, only for us to go right back to rrect.
        this->drawRRect(SkRRect::MakeOval(oval), paint);
    }
}

void Device::drawArc(const SkArc& arc, const SkPaint& paint) {
    // For sweeps >= 360°, simple fills and simple strokes without the center point or square caps
    // are ovals. Culling these here simplifies the path processing in Shape.
    if (!paint.getPathEffect() &&
        SkScalarAbs(arc.sweepAngle()) >= 360.f &&
        (paint.getStyle() == SkPaint::kFill_Style ||
         (paint.getStyle() == SkPaint::kStroke_Style &&
          // square caps can stick out from the shape so we can't do this with an rrect draw
          paint.getStrokeCap() != SkPaint::kSquare_Cap &&
          // wedge cases with strokes will draw lines to the center
          !arc.isWedge()))) {
        this->drawRRect(SkRRect::MakeOval(arc.oval()), paint);
    } else {
        this->drawGeometryWithPathEffect(this->localToDeviceTransform(),
                                         Geometry(Shape(arc)),
                                         PaintParams(paint),
                                         SkStrokeRec(paint),
                                         paint.getPathEffect());
    }
}

void Device::drawRRect(const SkRRect& rr, const SkPaint& paint) {
    Shape rrectToDraw;
    SkStrokeRec style(paint);

    if (paint.isAntiAlias()) {
        rrectToDraw.setRRect(rr);
    } else {
        // Snap the horizontal and vertical edges of the rounded rectangle to pixel edges to match
        // the behavior of drawRect(rr.bounds()), to partially emulate non-AA rendering while
        // preserving the anti-aliasing of the curved corners.
        Rect snappedBounds;
        if (style.isFillStyle()) {
            snappedBounds = snap_rect_to_pixels(this->localToDeviceTransform(), rr.rect());
        } else {
            const bool strokeAndFill = style.getStyle() == SkStrokeRec::kStrokeAndFill_Style;
            float strokeWidth = style.getWidth();
            snappedBounds = snap_rect_to_pixels(this->localToDeviceTransform(),
                                                rr.rect(), &strokeWidth);
            style.setStrokeStyle(strokeWidth, strokeAndFill);
        }

        SkRRect snappedRRect;
        snappedRRect.setRectRadii(snappedBounds.asSkRect(), rr.radii().data());
        rrectToDraw.setRRect(snappedRRect);
    }

    this->drawGeometryWithPathEffect(this->localToDeviceTransform(),
                                     Geometry(rrectToDraw),
                                     PaintParams(paint),
                                     style,
                                     paint.getPathEffect());
}

void Device::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
    // If there's a path effect or inverse fill, fall back to path rendering
    if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
        this->SkDevice::drawDRRect(outer, inner, paint);
        return;
    }

    // This holds the positive insets from `outer` to `inner`
    Rect strokeRect{outer.rect()};
    skvx::float4 gap = Rect(inner.rect()).vals() - strokeRect.vals();
    const float tolerance = Shape::kDefaultPixelTolerance *
                            this->localToDeviceTransform().localAARadius(strokeRect);
    const float strokeWidth = gap[0];
    if (!all((gap > tolerance) & (abs(gap - strokeWidth) <= tolerance))) {
        // Either not approximately equal insets on all sides, or it would create a hairline stroke
        // which is something that should be requested via paint style.
        //
        // But we can try subtracting inner from outer if they are both rectangular to see if it
        // leaves a valid filled rect.
        SkRect diff;
        if (outer.isRect() && inner.isRect() &&
            SkRectPriv::Subtract(outer.rect(), inner.rect(), &diff)) {
            this->drawRect(diff, paint);
            return;
        }

        // Fall through to the draw+clip handling
    } else {
        // The shape is possibly expressible as a stroked [r]rect.
        const float strokeRadius = 0.5f * strokeWidth;
        strokeRect.inset(strokeRadius);

        SkPaint strokePaint = paint;
        strokePaint.setStroke(true);
        strokePaint.setStrokeWidth(strokeWidth);
        strokePaint.setStrokeCap(SkPaint::kButt_Cap);
        strokePaint.setStrokeMiter(4.f); // large enough to not trigger bevels for 90 degree corners

        // Check the corners to see if they are equivalent to a stroked round rect. If `outer` has
        // rounded corners, they must be circular and be at least `strokeRadius`. An outer corner
        // can have a 0 radius if we assume a miter join style, but if an outer corner is exactly
        // the stroke radius then we have to use a round join style. The matching corners of `inner`
        // must also be rounded, and be exactly strokeWidth less, or they must be 0 if the
        // difference would be negative.
        int validCorners = 0;
        int rectCorners = 0;
        SkVector strokeCorners[4];
        std::optional<SkPaint::Join> requiredJoin;
        for (int i = 0; i < 4; ++i) {
            SkVector outerCornerRadii = outer.radii((SkRRect::Corner) i);
            SkVector innerCornerRadii = inner.radii((SkRRect::Corner) i);

            float strokeCorner;
            if (!SkRRectPriv::IsRelativelyCircular(outerCornerRadii.fX,
                                                   outerCornerRadii.fY,
                                                   tolerance)) {
                // Not circular; a stroked ellipse is not just a larger ellipse
                break;
            } else if (SkScalarNearlyZero(outerCornerRadii.fX, tolerance)) {
                // A rectangular outer corner requires miter joins
                if (requiredJoin.has_value() && *requiredJoin != SkPaint::kMiter_Join) {
                    break;
                }
                requiredJoin = SkPaint::kMiter_Join;
                strokeCorner = 0.f;
                rectCorners++;
            } else {
                strokeCorner = outerCornerRadii.fX - strokeRadius;
                if (strokeCorner < -tolerance) {
                    // Corner is rounded but less than the stroke radius, which isn't representable
                    break;
                } else if (strokeCorner <= tolerance) {
                    // Corner is rounded to the stroke radius, which can only be represented as an
                    // underlying rect corner and round join
                    if (requiredJoin.has_value() && *requiredJoin != SkPaint::kRound_Join) {
                        break;
                    }
                    requiredJoin = SkPaint::kRound_Join;
                    strokeCorner = 0.f;
                    rectCorners++;
                }
            }

            float expectedInnerRadius = std::max(0.f, strokeCorner - strokeRadius);
            if (!SkRRectPriv::IsRelativelyCircular(innerCornerRadii.fX,
                                                   expectedInnerRadius,
                                                   tolerance) ||
                !SkRRectPriv::IsRelativelyCircular(innerCornerRadii.fY,
                                                   expectedInnerRadius,
                                                   tolerance)) {
                // Inner corner doesn't match expectation
                break;
            }

            strokeCorners[i] = {strokeCorner, strokeCorner};
            validCorners++;
        }

        if (validCorners == 4) {
            strokePaint.setStrokeJoin(requiredJoin.value_or(SkPaint::kRound_Join));
            if (rectCorners == 4) {
                this->drawRect(strokeRect.asSkRect(), strokePaint);
            } else {
                SkRRect strokeRRect;
                strokeRRect.setRectRadii(strokeRect.asSkRect(), strokeCorners);
                this->drawRRect(strokeRRect, strokePaint);
            }
            return;
        }
        // Otherwise fall through to draw+clip handling
    }

    // To avoid path rendering, treat DRRects as a drawRRect(outer) with a clipRRect(inner, kDiff)
    fClip.save();
    fClip.clipShape(this->localToDeviceTransform(),
                    inner.isRect() ? Shape{inner.rect()} : Shape{inner},
                    SkClipOp::kDifference,
                    paint.isAntiAlias() ? ClipStack::PixelSnapping::kNo
                                        : ClipStack::PixelSnapping::kYes);
    if (outer.isRect()) {
        this->drawRect(outer.rect(), paint);
    } else {
        this->drawRRect(outer, paint);
    }
    fClip.restore();
}

void Device::drawPath(const SkPath& path, const SkPaint& paint) {
    // Alternatively, we could move this analysis to SkCanvas. Also, we could consider applying the
    // path effect, being careful about starting point and direction.
    if (!paint.getPathEffect() && !path.isInverseFillType()) {
        SkPoint linePts[2];
        if (path.isLine(linePts)) {
            // A line has zero area, so stroke and stroke-and-fill are equivalent
            if (paint.getStyle() != SkPaint::kFill_Style) {
                this->drawPoints(SkCanvas::kLines_PointMode, linePts, paint);
            } // and if it's fill, nothing is drawn
            return;
        }
        if (SkRect oval; path.isOval(&oval)) {
            this->drawOval(oval, paint);
            return;
        }
        if (SkRRect rrect; path.isRRect(&rrect)) {
            this->drawRRect(rrect, paint);
            return;
        }
        // For rects, if the path is not explicitly closed and the paint style is stroked then it
        // represents a rectangle with only 3 sides rasterized (and with any caps). If it's filled
        // or is closed+stroked, then the path renders identically to the rectangle.
        bool isClosed = false;
        if (SkRect rect; path.isRect(&rect, &isClosed) &&
            (paint.getStyle() == SkPaint::kFill_Style || isClosed)) {
            this->drawRect(rect, paint);
            return;
        }
        // Detect filled nested rect contours
        SkRect rects[2];
        SkPathDirection dirs[2];
        if (paint.getStyle() == SkPaint::kFill_Style &&
            SkPathPriv::IsNestedFillRects(path, rects, dirs)) {
            // For winding fills with contours going the same direction, there isn't any cutout
            if (path.getFillType() == SkPathFillType::kWinding && dirs[0] == dirs[1]) {
                this->drawRect(rects[0], paint);
                return;
            } else {
                // The inner is cut out from the outer rect. Delegate to drawDRRect.
                this->drawDRRect(SkRRect::MakeRect(rects[0]), SkRRect::MakeRect(rects[1]), paint);
                return;
            }
        }
    }

    // Full path rendering required
    this->drawGeometryWithPathEffect(this->localToDeviceTransform(),
                                     Geometry(Shape(path)),
                                     PaintParams(paint),
                                     SkStrokeRec(paint),
                                     paint.getPathEffect());
}

void Device::drawPoints(SkCanvas::PointMode mode, SkSpan<const SkPoint> points,
                        const SkPaint& paint) {
    if (points.empty()) {
        return;
    }
    size_t count = points.size();

    SkStrokeRec stroke(paint, SkPaint::kStroke_Style);
    size_t next = 0;
    if (mode == SkCanvas::kPoints_PointMode) {
        // Treat kPoints mode as stroking zero-length path segments, which produce caps so that
        // both hairlines and round vs. square geometry are handled entirely on the GPU.
        // TODO: SkCanvas should probably do the butt to square cap correction.
        if (paint.getStrokeCap() == SkPaint::kButt_Cap) {
            stroke.setStrokeParams(SkPaint::kSquare_Cap,
                                   paint.getStrokeJoin(),
                                   paint.getStrokeMiter());
        }
    } else {
        next = 1;
        count--;
    }

    const PaintParams paintParams(paint);
    size_t inc = mode == SkCanvas::kLines_PointMode ? 2 : 1;
    for (size_t i = 0; i < count; i += inc) {
        this->drawGeometryWithPathEffect(this->localToDeviceTransform(),
                                         Geometry(Shape(points[i], points[i + next])),
                                         paintParams,
                                         stroke,
                                         paint.getPathEffect());
    }
}

void Device::drawEdgeAAQuad(const SkRect& rect,
                            const SkPoint clip[4],
                            SkCanvas::QuadAAFlags aaFlags,
                            const SkColor4f& color,
                            SkBlendMode mode) {
    // NOTE: We do not snap edge AA quads that are fully non-AA because we need their edges to seam
    // with quads that have mixed edge flags (so both need to match the GPU rasterization, not our
    // CPU rounding).
    SkEnumBitMask<EdgeAAQuad::Flags> flags = static_cast<EdgeAAQuad::Flags>(aaFlags);
    EdgeAAQuad quad = clip ? EdgeAAQuad(clip, flags) : EdgeAAQuad(rect, flags);
    this->drawGeometry(this->localToDeviceTransform(),
                       Geometry(quad),
                       PaintParams(color, mode),
                       DefaultFillStyle());
}

void Device::drawEdgeAAImageSet(const SkCanvas::ImageSetEntry set[], int count,
                                const SkPoint dstClips[], const SkMatrix preViewMatrices[],
                                const SkSamplingOptions& sampling, const SkPaint& paint,
                                SkCanvas::SrcRectConstraint constraint) {
    SkASSERT(count > 0);

    const Transform& localToDevice = this->localToDeviceTransform();
    // SkPaint paintWithShader(paint);
    int dstClipIndex = 0;
    for (int i = 0; i < count; ++i) {
        // If the entry is clipped by 'dstClips', that must be provided
        SkASSERT(!set[i].fHasClip || dstClips);
        // Similarly, if it has an extra transform, those must be provided
        SkASSERT(set[i].fMatrixIndex < 0 || preViewMatrices);

        // See SkImageShader::MakeForDrawRect, as this behavior is consistent but avoids
        // allocating SkShader objects or having to modify the SkPaint.
        // Adjust `dst` such that it only samples from the portion of fSrcRect that overlaps with
        // the image bounds. This "decal" effect is applied geometrically to what is drawn so that
        // actual texture tiling can be clamped to the src rect.
        const SkRect imageBounds = SkRect::Make(set[i].fImage->bounds());
        SkRect dstToDraw = set[i].fDstRect;
        SkRect subset = set[i].fSrcRect;
        SkMatrix localMatrix = SkMatrix::RectToRectOrIdentity(subset, dstToDraw);
        if (!imageBounds.contains(subset)) {
            if (subset.intersect(imageBounds)) {
                // Update dst to match the smaller src
                dstToDraw = localMatrix.mapRect(subset);
            } else {
                dstToDraw.setEmpty();
            }
        }
        if (dstToDraw.isEmpty()) {
            continue; // Nothing to draw for this set entry
        }

        PaintParams::SimpleImage imageShader{set[i].fImage.get(),
                                             &localMatrix,
                                             constraint == SkCanvas::kStrict_SrcRectConstraint ?
                                                    subset : imageBounds,
                                             sampling};

        // NOTE: See drawEdgeAAQuad for details, we do not snap non-AA quads.
        SkEnumBitMask<EdgeAAQuad::Flags> flags = static_cast<EdgeAAQuad::Flags>(set[i].fAAFlags);
        EdgeAAQuad quad = set[i].fHasClip ? EdgeAAQuad(dstClips + dstClipIndex, flags)
                                          : EdgeAAQuad(dstToDraw, flags);

        // TODO: Calling drawGeometry() for each entry re-evaluates the clip stack every time, which
        // is consistent with Ganesh's behavior. It also matches the behavior if edge-AA images were
        // submitted one at a time by SkiaRenderer (a nice client simplification). However, we
        // should explore the performance trade off with doing one bulk evaluation for the whole set
        const SkMatrix* xtraXform = set[i].fMatrixIndex < 0 ? nullptr
                                                            : &preViewMatrices[set[i].fMatrixIndex];
        this->drawGeometry(xtraXform ?  localToDevice.concat(SkM44(*xtraXform)) : localToDevice,
                           Geometry(quad),
                           PaintParams(paint, imageShader, set[i].fAlpha),
                           DefaultFillStyle());

        dstClipIndex += 4 * set[i].fHasClip;
    }
}

void Device::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
                           const SkSamplingOptions& sampling, const SkPaint& paint,
                           SkCanvas::SrcRectConstraint constraint) {
    SkCanvas::ImageSetEntry single{sk_ref_sp(image),
                                   src ? *src : SkRect::Make(image->bounds()),
                                   dst,
                                   /*alpha=*/1.f,
                                   SkCanvas::kAll_QuadAAFlags};
    // While this delegates to drawEdgeAAImageSet() for the image shading logic, semantically a
    // drawImageRect()'s non-AA behavior should match that of drawRect() so we snap dst (and update
    // src to match) if needed before hand.
    if (!paint.isAntiAlias()) {
        snap_src_and_dst_rect_to_pixels(this->localToDeviceTransform(),
                                        &single.fSrcRect, &single.fDstRect);
    }
    this->drawEdgeAAImageSet(&single, 1, nullptr, nullptr, sampling, paint, constraint);
}

sktext::gpu::AtlasDrawDelegate Device::atlasDelegate() {
    return [&](const sktext::gpu::AtlasSubRun* subRun,
               SkPoint drawOrigin,
               const SkPaint& paint,
               sk_sp<SkRefCnt> subRunStorage,
               sktext::gpu::RendererData rendererData) {
        this->drawAtlasSubRun(subRun, drawOrigin, paint, std::move(subRunStorage), rendererData);
    };
}

void Device::onDrawGlyphRunList(SkCanvas* canvas,
                                const sktext::GlyphRunList& glyphRunList,
                                const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    fRecorder->priv().textBlobCache()->drawGlyphRunList(canvas,
                                                        this->localToDevice(),
                                                        glyphRunList,
                                                        paint,
                                                        this->strikeDeviceInfo(),
                                                        this->atlasDelegate());
}

void Device::drawAtlasSubRun(const sktext::gpu::AtlasSubRun* subRun,
                             SkPoint drawOrigin,
                             const SkPaint& paint,
                             sk_sp<SkRefCnt> subRunStorage,
                             sktext::gpu::RendererData rendererData) {
    ASSERT_SINGLE_OWNER

    // For color emoji, the shading behaves similarly to how drawImageRects override the shader
    // via a SimpleImage. However, for text, the "image" is coming from the atlas and RenderStep as
    // a primitive color and is combined with the paint color using the primitive blender, so we
    // construct the PaintParams to explicitly ignore the paint's set shader. For regular and LCD
    // text, the mask image provides coverage so there is no primitive blender.
    const SkBlender* primitiveBlender = subRun->maskFormat() == MaskFormat::kARGB ?
            GetBlendModeSingleton(SkBlendMode::kDstIn) : nullptr;
    const PaintParams paintParams(paint,
                                  primitiveBlender,
                                  /*skipColorXform=*/false,
                                  /*ignoreShader=*/SkToBool(primitiveBlender));
    const bool useGammaCorrectDistanceTable = this->imageInfo().colorSpace() &&
                                              this->imageInfo().colorSpace()->gammaIsLinear();
    const Transform& localToDevice = this->localToDeviceTransform();

    const int subRunEnd = subRun->glyphCount();

    if (!subRun->glyphVector().hasBackendData()) {
        subRun->glyphVector().initBackendData<GlyphData>(this->recorder()->priv().strikeCache(),
                                                         subRun->maskFormat());
    }

    auto& glyphData = subRun->glyphVector().accessBackendData<GlyphData>();

    for (int subRunCursor = 0; subRunCursor < subRunEnd;) {
        // For the remainder of the run, add any atlas uploads to the Recorder's TextAtlasManager
        auto [ok, glyphsRegenerated] = glyphData.regenerateAtlas(subRunCursor,
                                                                 subRunEnd,
                                                                 subRun->glyphVector(),
                                                                 subRun->maskFormat(),
                                                                 subRun->glyphSrcPadding(),
                                                                 this->recorder());

        // There was a problem allocating the glyph in the atlas. Bail.
        if (!ok) {
            return;
        }
        if (glyphsRegenerated) {
            auto [bounds, maskToDevice] =
                    subRun->vertexFiller().boundsAndDeviceMatrix(localToDevice, drawOrigin);

            this->drawGeometry(Transform{SkM44{maskToDevice}},
                               Geometry(SubRunData(subRun,
                                                   subRunStorage,
                                                   bounds,
                                                   localToDevice.inverse(),
                                                   subRunCursor,
                                                   glyphsRegenerated,
                                                   SkPaintPriv::ComputeLuminanceColor(paint),
                                                   useGammaCorrectDistanceTable,
                                                   this->surfaceProps().pixelGeometry(),
                                                   fRecorder,
                                                   rendererData)),
                               paintParams,
                               DefaultFillStyle());
        }
        subRunCursor += glyphsRegenerated;

        if (subRunCursor < subRunEnd) {
            // Flush if not all the glyphs are handled because the atlas is out of space.
            // We flush every Device because the glyphs that are being flushed/referenced are not
            // necessarily specific to this Device. This addresses both multiple SkSurfaces within
            // a Recorder, and nested layers.
            TRACE_EVENT_INSTANT0("skia.gpu", "Glyph atlas full", TRACE_EVENT_SCOPE_NAME_THREAD);
            fRecorder->priv().flushTrackedDevices(SK_DUMP_TASKS_CODE("Device::drawAtlasSubRun"));
        }
    }
}

void Device::drawGeometryWithPathEffect(const Transform& localToDevice,
                                        Geometry&& geometry,
                                        const PaintParams& paint,
                                        SkStrokeRec style,
                                        const SkPathEffect* pathEffect) {
    // Path effects are applied on the CPU, which may modify the geometry to draw.
    // TODO(b/238757903): Handle dashing on the GPU when possible (e.g. straight lines)
    if (pathEffect && localToDevice.valid()) {
        // Apply the path effect before anything else, which if we are applying here, means that we
        // are dealing with a Shape. drawVertices (and a SkVertices geometry) should pass in
        // kIgnorePathEffect per SkCanvas spec. Text geometry also should pass in kIgnorePathEffect
        // because the path effect is applied per glyph by the SkStrikeSpec already.
        SkASSERT(geometry.isShape());

        // TODO: If asADash() returns true and the base path matches the dashing fast path, then
        // that should be detected now as well. Maybe add dashPath to Device so canvas can handle it
        float maxScaleFactor = localToDevice.maxScaleFactor();
        if (localToDevice.type() == Transform::Type::kPerspective) {
            auto bounds = geometry.bounds();
            float tl = std::get<1>(localToDevice.scaleFactors({bounds.left(), bounds.top()}));
            float tr = std::get<1>(localToDevice.scaleFactors({bounds.right(), bounds.top()}));
            float br = std::get<1>(localToDevice.scaleFactors({bounds.right(), bounds.bot()}));
            float bl = std::get<1>(localToDevice.scaleFactors({bounds.left(), bounds.bot()}));
            maxScaleFactor = std::max(std::max(tl, tr), std::max(bl, br));
        }

        style.setResScale(maxScaleFactor);
        SkPathBuilder builder;
        if (pathEffect->filterPath(&builder, geometry.shape().asPath(),
                                   &style, nullptr, localToDevice)) {
            SkPath dst = builder.detach();
            dst.setIsVolatile(true);
            geometry.setShape(Shape(dst));
        } else {
            SKGPU_LOG_W("Path effect failed to apply, drawing original path.");
        }

        // Fallthrough, remaining code assumes the effect has been applied to `geometry` and `style`
    }

    this->drawGeometry(localToDevice, std::move(geometry), paint, style);
}

void Device::drawGeometry(const Transform& localToDevice,
                          Geometry&& geometry,
                          const PaintParams& paint,
                          SkStrokeRec style) {
    ASSERT_SINGLE_OWNER

    if (!localToDevice.valid()) {
        // If the transform is not invertible or not finite then drawing isn't well defined.
        SKGPU_LOG_W("Skipping draw with non-invertible/non-finite transform.");
        return;
    }

    // TODO: The tessellating and atlas path renderers haven't implemented perspective yet, so
    // transform to device space so we draw something approximately correct (barring local coord
    // issues).
    if (geometry.isShape() && localToDevice.type() == Transform::Type::kPerspective &&
        !is_simple_shape(geometry.shape(), localToDevice, style.getStyle())) {
        SkPath devicePath = geometry.shape().asPath().makeTransform(localToDevice.matrix().asM33());
        devicePath.setIsVolatile(true);
        // TODO(b/452415460): This fallback breaks perspective interpolation for local coords and
        // it causes strokes to render in device space.
        this->drawGeometry(Transform::Identity(), Geometry(Shape(devicePath)), paint, style);
        return;
    }

    ScopedDrawBuilder scopedDrawBuilder(fRecorder);

    // Calculate the clipped bounds of the draw and determine the clip elements that affect the
    // draw without updating the clip stack.
    ClipStack::ElementList clipElements;
    Clip clip = fClip.visitClipStackForDraw(localToDevice,
                                            &geometry,
                                            style,
                                            &clipElements);
    if (clip.isClippedOut()) {
        // Clipped out, so don't record anything.
        return;
    }

    // We assume that we will receive a renderer, or a PathAtlas. If it's a PathAtlas, then we
    // assume that the renderer chosen in PathAtlas::addShape() will have single-channel coverage,
    // require AA bounds outsetting, and have a single renderStep. The clip's draw bounds are passed
    // in for heuristics, so it's fine if it doesn't include the AA outsetting we add for some
    // analytic coverage renderers.
    auto [renderer, pathAtlas] = this->chooseRenderer(localToDevice,
                                                      geometry,
                                                      style,
                                                      clip.transformedShapeBounds());
    if (!renderer && !pathAtlas) {
        SKGPU_LOG_W("Skipping draw with no supported renderer or PathAtlas.");
        return;
    }

    // Update the pixel bounds of the draw to include any outsets done by the renderer (or that
    // must be included in the pixels required when using an atlas). This is important so that
    // all bounds overlap checks take into account pixels touched by rasterization, even if the
    // calculated coverage for a pixel is 0.
    if (!renderer || renderer->outsetBoundsForAA()) {
        clip.outsetBoundsForAA();
    }

    // A renderer that emits a primitive color should only be used by a drawX() call that sets a
    // non-null primitive blender.
    SkASSERT(SkToBool(paint.primitiveBlender()) == (renderer && renderer->emitsPrimitiveColor()));

    ShadingParams shading{fRecorder->priv().caps(),
                          paint,
                          clip.nonMSAAClip(),
                          clip.shader(),
                          renderer ? renderer->coverage() : Coverage::kSingleChannel,
                          TextureInfoPriv::ViewFormat(fDC->target()->textureInfo())};

    // Some shapes and styles combine multiple draws so the total render step count is split between
    // the main renderer and possibly a secondaryRenderer. As we can't be sure whether a secondary
    // renderer is required prior to getting the dstUsage from shading.toKey(), we pessimistically
    // assume it's required for needsFlushBeforeDraw().
    int numNewRenderSteps = 1;
    SkStrokeRec::Style styleType = style.getStyle();
    if (renderer) {
        numNewRenderSteps = renderer->numRenderSteps();
        if (styleType == SkStrokeRec::kStrokeAndFill_Style) {
            numNewRenderSteps +=
                fRecorder->priv().rendererProvider()->tessellatedStrokes()->numRenderSteps();
        } else if (style.isFillStyle() && renderer->useNonAAInnerFill()) {
            numNewRenderSteps +=
                fRecorder->priv().rendererProvider()->nonAABounds()->numRenderSteps();
        }
    }

    // Decide if we have any reason to flush pending work. A flush may be necessary for two reasons:
    //      1) A flush is required before updating the clip state or making any permanent changes to
    //         a path atlas, since otherwise clip operations and/or atlas entries for the current
    //         draw will be flushed.
    //      2) A flush is required before shading.toKey() is called so that child tasks required by
    //         this draw are associated with the DrawContext after any instead of being added as a
    //         child of the current draw. See "Layer" tests in NotifyInUseTest.cpp.
    DstReadStrategy dstReadStrategy = shading.dstReadRequired() ?
                                      fDC->dstReadStrategy() : DstReadStrategy::kNoneRequired;
    // TODO (thomsmit): Adjust this when the draw limit is removed.
    const bool needsFlush = this->needsFlushBeforeDraw(numNewRenderSteps, dstReadStrategy);
    if (needsFlush) {
        if (pathAtlas != nullptr) {
            // We need to flush work for all devices associated with the current Recorder.
            // Otherwise we may end up with outstanding draws that depend on past atlas state.
            fRecorder->priv().flushTrackedDevices(
                    SK_DUMP_TASKS_CODE("Device::drawGeometry Flush Before Draw"));
        } else {
            this->flushPendingWork(/*drawContext=*/nullptr);
        }
    }

    // Determine the paint ID and collect the paint uniforms now before anything has been recorded.
    // The paint may reference an SkPicture or a Graphite-backed dynamic SkImage that can trigger
    // a flush of the Recorder.
    KeyContext keyContext{fRecorder,
                          fDC.get(),
                          fRecorder->priv().floatStorageManager(),
                          scopedDrawBuilder.builder(),
                          scopedDrawBuilder.gatherer(),
                          localToDevice.matrix(),
                          fDC->colorInfo(),
                          geometry.isShape() || geometry.isEdgeAAQuad()
                                ? KeyGenFlags::kDefault
                                : KeyGenFlags::kDisableSamplingOptimization,
                          paint.color()};
    auto keyResult = shading.toKey(keyContext);
    if (!keyResult) {
        // Converting the SkPaint to a pipeline and set of uniform values + sampled textures failed.
        SKGPU_LOG_W("Key context creation failed in Device::drawGeometry, draw dropped!");
        return;
    }
    auto [paintID, dstUsage] = *keyResult;

    // If we are unclipped, do not depend on the dst, and cover the target, then we can adjust
    // load ops of the renderpass to more optimally handle the draw (and avoid redundant clears).
    // NOTE: We skip this for fully-lazy render targets because the load ops may impact a larger
    // area than the Device's theoretical bounds.
    const bool overwritesAllPixels = dstUsage == DstUsage::kNone &&
                                     geometry.isShape() &&
                                     geometry.shape().isFloodFill() &&
                                     !fDC->target()->isFullyLazy() &&
                                     clipElements.empty() &&
                                     clip.scissor().contains(this->bounds());
    if (overwritesAllPixels) {
        if (std::optional<SkColor4f> color = extract_paint_color(paint, fDC->colorInfo())) {
            // Fullscreen clear, so nothing has to be rendered at all
            fDC->clear(*color);
            return;
        } else {
            // This paint does not depend on the destination and covers the entire surface, so
            // discard everything previously recorded and proceed with the draw. However, if we are
            // here because of a paint with src-over blending that just happens to be opaque, the
            // discarded dst can still be accessed. For non-floating point formats, that is fine,
            // but float formats can have NaNs after a discard that cause blending to fail. To
            // avoid that scenario, we clear to a known value instead.
            if (paint.finalBlendMode() == SkBlendMode::kSrcOver &&
                TextureFormatIsFloatingPoint(
                        TextureInfoPriv::ViewFormat(fDC->target()->textureInfo()))) {
                fDC->clear(SkColors::kMagenta); // This color doesn't matter
            } else {
                fDC->discard();
            }
            // But then continue to render the flood fill with shading
        }
    }

    // If an atlas path renderer was chosen we need to insert the shape into the atlas and schedule
    // it to be drawn.
    std::optional<PathAtlas::MaskAndOrigin> atlasMask;  // only used if `pathAtlas != nullptr`
    if (pathAtlas != nullptr) {
        Rect clippedShapeBounds = clip.transformedShapeBounds().makeIntersect(clip.scissor());
        if (clippedShapeBounds.area() >= 0.8f * clip.transformedShapeBounds().area()) {
            // The clip isn't excluding very much of the original shape, so store the entire path
            // in the atlas to avoid redundant entries with slightly different clips.
            clippedShapeBounds = clip.transformedShapeBounds();
        }
        std::tie(renderer, atlasMask) = pathAtlas->addShape(clippedShapeBounds,
                                                            geometry.shape(),
                                                            localToDevice,
                                                            style);

        // If there was no space in the atlas and we haven't flushed already, then flush pending
        // work to clear up space in the atlas. If we had already flushed once (which would have
        // cleared the atlas) then the atlas is too small for this shape.
        if (!atlasMask && !needsFlush) {
            // We need to flush work for all devices associated with the current Recorder.
            // Otherwise we may end up with outstanding draws that depend on past atlas state.
            fRecorder->priv().flushTrackedDevices(
                    SK_DUMP_TASKS_CODE("Device::drawGeometry Atlas Flush"));

            // Try inserting the shape again.
            std::tie(renderer, atlasMask) = pathAtlas->addShape(clippedShapeBounds,
                                                                geometry.shape(),
                                                                localToDevice,
                                                                style);
        }

        if (!atlasMask) {
            SKGPU_LOG_E("Failed to add shape to atlas!");
            // TODO(b/285195175): This can happen if the atlas is not large enough or a compatible
            // atlas texture cannot be created. Handle the first case in `chooseRenderer` and make
            // sure that the atlas path renderer is not chosen if the path is larger than the atlas
            // texture.
            return;
        }
        // Since addShape() was successful we should have a valid Renderer now.
        SkASSERT(renderer && renderer->numRenderSteps() == 1 && !renderer->emitsPrimitiveColor());
        fAtlasedPathCount++;
    }

#if defined(SK_DEBUG)
    // Renderers and their component RenderSteps have flexibility in defining their
    // DepthStencilSettings. However, the clipping and ordering managed between Device and ClipStack
    // requires that only LESS or LEQUAL depth tests are used for draws recorded through the
    // client-facing, painters-order-oriented API. We assert here vs. in Renderer's constructor to
    // allow internal-oriented Renderers that are never selected for a "regular" draw call to have
    // more flexibility in their settings.
    SkASSERT(renderer);
    for (const RenderStep* step : renderer->steps()) {
        auto dss = step->depthStencilSettings();
        SkASSERT((!step->performsShading() || dss.fDepthTestEnabled) &&
                 (!dss.fDepthTestEnabled ||
                  dss.fDepthCompareOp == CompareOp::kLess ||
                  dss.fDepthCompareOp == CompareOp::kLEqual));
    }
#endif

    // Update the clip stack after issuing a flush (if it was needed). A draw will be recorded after
    // this point.
    DrawOrder order(fCurrentDepth.next());
    auto [clipOrder, latestDepthLayer] = fClip.updateClipStateForDraw(
            clip, clipElements, fColorDepthBoundsManager.get(), order.depth());

    // A draw's order always depends on the clips that must be drawn before it
    order.dependsOnPaintersOrder(clipOrder);
    bool useDrawListLayer = fRecorder->priv().caps()->useDrawListLayer();
    if (!useDrawListLayer) {
        // If a draw is not opaque, it must be drawn after the most recent draw it intersects with
        // in order to blend correctly.
        if (dstUsage & DstUsage::kDependsOnDst) {
            CompressedPaintersOrder prevDraw =
                fColorDepthBoundsManager->getMostRecentDraw(clip.drawBounds());
            order.dependsOnPaintersOrder(prevDraw);
        }

        // Now that the base paint order and draw bounds are finalized, if the Renderer relies on
        // the stencil attachment, we compute a secondary sorting field to allow disjoint draws to
        // reorder the RenderSteps across draws instead of in sequence for each draw.
        if (renderer->depthStencilFlags() & DepthStencilFlags::kStencil) {
            DisjointStencilIndex setIndex = fDisjointStencilSet->add(order.paintOrder(),
                                                                     clip.drawBounds());
            order.dependsOnStencil(setIndex);
        } else if (!(dstUsage & DstUsage::kDependsOnDst) &&
                style.isFillStyle() &&
                ((geometry.isEdgeAAQuad() && geometry.edgeAAQuad().isRect()) ||
                    (geometry.isShape() && geometry.shape().isRect()))) {
            // Sort this draw front to back since it will not blend against what came before it. We
            // could do this for all opaque/non-blending draws but that can hurt the performance of
            // the std::sort in DrawPass::Make if it has to effectively reverse a large list. For
            // now, limit it to filled rectangles (here and for the later non-AA inner fill).
            order.reverseDepthAsStencil();
        }
    }

    // If an atlas path renderer was chosen, then record a single CoverageMaskShape draw.
    // The shape will be scheduled to be rendered or uploaded into the atlas during the
    // next invocation of flushPendingWork().
    if (pathAtlas != nullptr) {
        // Record the draw as a fill since stroking is handled by the atlas render/upload.
        SkASSERT(atlasMask.has_value());
        auto [mask, origin] = *atlasMask;
        fDC->recordDraw(renderer, Transform::Translate(origin.fX, origin.fY), Geometry(mask), clip,
                        order, paintID, dstUsage, scopedDrawBuilder.gatherer(), /*stroke=*/nullptr,
                        latestDepthLayer);
    } else {
        if (styleType != SkStrokeRec::kFill_Style) {
            // For stroke-and-fill, 'renderer' is used for the fill and we always use the
            // TessellatedStrokes renderer; for stroke and hairline, 'renderer' is used.
            StrokeStyle stroke(style.getWidth(), style.getMiter(), style.getJoin(), style.getCap());
            fDC->recordDraw(styleType == SkStrokeRec::kStrokeAndFill_Style
                                   ? fRecorder->priv().rendererProvider()->tessellatedStrokes()
                                   : renderer,
                            localToDevice, geometry, clip, order, paintID, dstUsage,
                            scopedDrawBuilder.gatherer(), &stroke, latestDepthLayer);
        } else if ((dstUsage & DstUsage::kDstOnlyUsedByRenderer) && renderer->useNonAAInnerFill()) {
            // Possibly record an additional draw using the non-AA bounds renderer to fill the
            // interior with a renderer that can disable blending entirely.
            Rect innerFillBounds = get_inner_bounds(geometry, localToDevice);
            if (!innerFillBounds.isEmptyNegativeOrNaN()) {
                DrawOrder orderWithoutCoverage{order.depth()};
                orderWithoutCoverage.dependsOnPaintersOrder(clipOrder);
                // The regular draw has analytic coverage, so isn't being sorted front to back, but
                // we do want to sort the inner fill to maximize overdraw reduction
                orderWithoutCoverage.reverseDepthAsStencil();
                fDC->recordDraw(fRecorder->priv().rendererProvider()->nonAABounds(), localToDevice,
                                Geometry(Shape(innerFillBounds)), clip, orderWithoutCoverage,
                                paintID, DstUsage::kNone, scopedDrawBuilder.gatherer(),
                                /*stroke=*/nullptr, latestDepthLayer);
                // Force the coverage draw to come after the non-AA draw in order to benefit from
                // early depth testing.
                order.dependsOnPaintersOrder(orderWithoutCoverage.paintOrder());
            }
        }

        if (styleType == SkStrokeRec::kFill_Style ||
            styleType == SkStrokeRec::kStrokeAndFill_Style) {
            fDC->recordDraw(renderer, localToDevice, geometry, clip, order, paintID, dstUsage,
                            scopedDrawBuilder.gatherer(), /*stroke=*/nullptr, latestDepthLayer);
        }
    }

    if (!useDrawListLayer) {
        fColorDepthBoundsManager->recordDraw(clip.drawBounds(), order.paintOrder());
    }
    fCurrentDepth = order.depth();

    // TODO(b/238758897): When we enable layer elision that depends on draws not overlapping, we
    // can use the `getMostRecentDraw()` query to determine that, although that will mean querying
    // even if the draw does not depend on dst (so should be only be used when the Device is an
    // elision candidate).
}

void Device::drawClipShape(const Transform& localToDevice,
                           const Shape& shape,
                           const Clip& clip,
                           DrawOrder order) {
    ScopedDrawBuilder scopedDrawBuilder(fRecorder);

    // A clip draw's state is almost fully defined by the ClipStack. The only thing we need to
    // account for is selecting a Renderer and tracking the stencil buffer usage.
    //
    // While kRasterAtlas attempts to route clip elements to an atlas, this can fail, in which case
    // the element may still be rendered into the depth buffer with tessellation (likely w/o AA).
    auto renderer = this->chooseMSAARenderer(shape,
                                             DefaultFillStyle(),
                                             clip.transformedShapeBounds());
    if (!renderer) {
        SKGPU_LOG_W("Skipping clip with no supported path renderer.");
        return;
    } else if (!fRecorder->priv().caps()->useDrawListLayer() &&
               (renderer->depthStencilFlags() & DepthStencilFlags::kStencil)) {
        DisjointStencilIndex setIndex = fDisjointStencilSet->add(order.paintOrder(),
                                                                 clip.drawBounds());
        order.dependsOnStencil(setIndex);
    }

    // This call represents one of the deferred clip shapes that's already pessimistically counted
    // in needsFlushBeforeDraw(), so the DrawContext should have room to add it.
    SkASSERT(fDC->pendingRenderSteps() + renderer->numRenderSteps() < DrawList::kMaxRenderSteps);

    // Anti-aliased clipping requires the renderer to use MSAA to modify the depth per sample, so
    // analytic coverage renderers cannot be used.
    SkASSERT(renderer->coverage() == Coverage::kNone && renderer->requiresMSAA());

    // Clips draws are depth-only (invalid UniquePaintParamsID), and filled (null StrokeStyle).
    // The data gatherer must be reset so that the DrawList can use it for any RenderStep data.
    if (localToDevice.type() == Transform::Type::kPerspective) {
        SkPath devicePath = shape.asPath().makeTransform(localToDevice.matrix().asM33());
        fDC->recordDraw(renderer, Transform::Identity(), Geometry(Shape(devicePath)), clip, order,
                        UniquePaintParamsID::Invalid(), DstUsage::kNone,
                        scopedDrawBuilder.gatherer(), /*stroke=*/nullptr,
                        /*latestDepthLayer=*/nullptr);
    } else {
        fDC->recordDraw(renderer, localToDevice, Geometry(shape), clip, order,
                        UniquePaintParamsID::Invalid(), DstUsage::kNone,
                        scopedDrawBuilder.gatherer(), /*stroke=*/nullptr,
                        /*latestDepthLayer=*/nullptr);
    }
    // This ensures that draws recorded after this clip shape has been popped off the stack will
    // be unaffected by the Z value the clip shape wrote to the depth attachment.
    if (order.depth() > fCurrentDepth) {
        fCurrentDepth = order.depth();
    }
}

// records a draw and returns a backpointer to the drawParams of the draw
std::pair<DrawParams*, Layer*> Device::drawClipShapeImmediate(const Transform& localToDevice,
                                                               const Shape& shape,
                                                               const Clip& clip,
                                                               DrawOrder order) {
    ScopedDrawBuilder scopedDrawBuilder(fRecorder);
    auto renderer = this->chooseMSAARenderer(shape,
                                             DefaultFillStyle(),
                                             clip.transformedShapeBounds());
    if (!renderer) {
        SKGPU_LOG_W("Skipping clip with no supported path renderer.");
        return {nullptr, nullptr};
    }

    if (localToDevice.type() == Transform::Type::kPerspective) {
        SkPath devicePath = shape.asPath().makeTransform(localToDevice.matrix().asM33());
        return fDC->recordDraw(renderer, Transform::Identity(), Geometry(Shape(devicePath)), clip,
                               order, UniquePaintParamsID::Invalid(), DstUsage::kNone,
                               scopedDrawBuilder.gatherer(), /*stroke=*/{},
                               /*latestDepthLayer=*/{});
    } else {
        return fDC->recordDraw(renderer, localToDevice, Geometry(shape), clip, order,
                               UniquePaintParamsID::Invalid(), DstUsage::kNone,
                               scopedDrawBuilder.gatherer(), /*stroke=*/{},
                               /*latestDepthLayer=*/{});
    }
}

void Device::updateNextDepthForClipping(PaintersDepth depth) {
    // This ensures that draws recorded after this clip shape has been popped off the stack will
    // be unaffected by the Z value the clip shape wrote to the depth attachment.
    if (depth > fCurrentDepth) {
        fCurrentDepth = depth;
    }
}

// TODO: Currently all Renderers are always defined, but with config options and caps that may not
// be the case, in which case chooseRenderer() will have to go through compatible choices.
std::pair<const Renderer*, PathAtlas*> Device::chooseRenderer(const Transform& localToDevice,
                                                              const Geometry& geometry,
                                                              const SkStrokeRec& style,
                                                              const Rect& drawBounds) const {
    const RendererProvider* renderers = fRecorder->priv().rendererProvider();
    SkASSERT(renderers);
    SkStrokeRec::Style type = style.getStyle();

    if (geometry.isSubRun()) {
        sktext::gpu::RendererData rendererData = geometry.subRunData().rendererData();
        if (!rendererData.isSDF) {
            return {renderers->bitmapText(rendererData.isLCD, rendererData.maskFormat), nullptr};
        }
        // Even though the SkPaint can request subpixel rendering, we still need to match
        // this with the pixel geometry.
        bool useLCD = rendererData.isLCD &&
                      geometry.subRunData().pixelGeometry() != kUnknown_SkPixelGeometry;
        return {renderers->sdfText(useLCD), nullptr};
    } else if (geometry.isVertices()) {
        SkVerticesPriv info(geometry.vertices()->priv());
        return {renderers->vertices(info.mode(), info.hasColors(), info.hasTexCoords()), nullptr};
    } else if (geometry.isCoverageMaskShape()) {
        // drawCoverageMask() passes in CoverageMaskShapes that reference a provided texture.
        // The CoverageMask renderer can also be chosen later on if the shape is assigned to
        // to be rendered into the PathAtlas, in which case the 2nd return value is non-null.
        return {renderers->coverageMask(), nullptr};
    } else if (geometry.isEdgeAAQuad()) {
        SkASSERT(style.isFillStyle());
        // handled by specialized system, simplified from rects and round rects
        const EdgeAAQuad& quad = geometry.edgeAAQuad();
        if (quad.isRect() && (quad.edgeFlags() == EdgeAAQuad::Flags::kNone
#if !defined(SK_SKIP_PIXELALIGNED_QUAD_CHECK_GRAPHITE)
                              || is_pixel_aligned(quad.bounds(), localToDevice)
#endif
                             )) {
            // For non-AA rectangular quads, it can always use a coverage-less renderer; there's no
            // need to check for pixel alignment to avoid popping if MSAA is turned on because quad
            // tile edges will seam with each in either mode. We also switch to use the cover bounds
            // when the quad is pixel aligned to be consistent with drawRect Renderer handling.
            return {renderers->nonAABounds(), nullptr};
        } else {
            return {renderers->perEdgeAAQuad(), nullptr};
        }
    } else if (geometry.isAnalyticBlur()) {
        return {renderers->analyticBlur(), nullptr};
    } else if (!geometry.isShape()) {
        // We must account for new Geometry types with specific Renderers
        return {nullptr, nullptr};
    }

    const Shape& shape = geometry.shape();
    if (is_simple_shape(shape, localToDevice, type)) {
        SkASSERT(type != SkStrokeRec::kStrokeAndFill_Style); // stroke+fill is *not* simple
        // For pixel-aligned rects, use the the non-AA bounds renderer to avoid triggering any
        // dst-read requirement due to src blending.
        bool pixelAlignedRect = false;
        if (shape.isRect() && style.isFillStyle()) {
            pixelAlignedRect = is_pixel_aligned(shape.rect(), localToDevice);
        }

        if (shape.isEmpty() || pixelAlignedRect) {
            SkASSERT(!shape.isEmpty() || shape.inverted());
            return {renderers->nonAABounds(), nullptr};
        } else {
            return {renderers->analyticRRect(), nullptr};
        }
    }

    if (shape.isArc() &&
        std::abs(shape.arc().sweepAngle()) < 360.f &&
        localToDevice.type() <= Transform::Type::kAffine &&
        SkRRectPriv::IsRelativelyCircular(shape.arc().oval().width(), shape.arc().oval().height(),
                                          Shape::kDefaultPixelTolerance *
                                                localToDevice.localAARadius(drawBounds))) {
        // We aren't perspective, so the point passed to scaleFactors() doesn't matter
        auto [minScale, maxScale] = localToDevice.scaleFactors({0, 0});
        if (SkScalarNearlyEqual(maxScale, minScale)) {
            // Arc support depends on the style.
            SkStrokeRec::Style recStyle = style.getStyle();
            switch (recStyle) {
                case SkStrokeRec::kStrokeAndFill_Style:
                    // This produces a strange result that this op doesn't implement.
                    break;
                case SkStrokeRec::kFill_Style:
                    return {renderers->circularArc(), nullptr};
                case SkStrokeRec::kStroke_Style:
                case SkStrokeRec::kHairline_Style:
                    // Strokes that don't use the center point are supported with butt & round caps.
                    bool isWedge = shape.arc().isWedge();
                    bool isSquareCap = style.getCap() == SkPaint::kSquare_Cap;
                    if (!isWedge && !isSquareCap) {
                        return {renderers->circularArc(), nullptr};
                    }
                    break;
            }
        }
    }

    AtlasProvider* atlasProvider = fRecorder->priv().atlasProvider();
    switch (renderers->pathRendererStrategy()) {
        case PathRendererStrategy::kComputeAnalyticAA:
        case PathRendererStrategy::kComputeMSAA16:
        case PathRendererStrategy::kComputeMSAA8: {
            PathAtlas* atlas = fDC->getComputePathAtlas(fRecorder);
            SkASSERT(atlas);

            // Don't use the compute renderer if it can't handle the shape efficiently.
            if (atlas->isSuitableForAtlasing(drawBounds, fClip.conservativeBounds())) {
                return {nullptr, atlas};
            } // else falls back to tessellation
        } break;

        case PathRendererStrategy::kTessellationAndSmallAtlas: {
            static constexpr int kMaxSmallPathAtlasCount = 256;
            const float minPathSizeForMSAA = fRecorder->priv().caps()->minPathSizeForMSAA();
            if (fAtlasedPathCount < kMaxSmallPathAtlasCount &&
                all(drawBounds.size() <= minPathSizeForMSAA)) {
                // Small paths are rasterized on the CPU for higher quality
                return {nullptr, atlasProvider->getRasterPathAtlas()};
            } // else falls back to tessellation
        } break;

        case PathRendererStrategy::kRasterAtlas:
            // Everything is rasterized on the CPU and packed into the atlas
            return {nullptr, atlasProvider->getRasterPathAtlas()};

        case PathRendererStrategy::kTessellation:
            // Never uses an atlas for rendering, leave it null
            break;

        case PathRendererStrategy::kCPUSparseStripsMSAA8:
            // Atlas in the future
            break;
    }

    // If we got here, it requires tessellated path rendering or an MSAA technique applied to a
    // simple shape (so we interpret them as paths to reduce the number of pipelines we need).
    return {this->chooseMSAARenderer(geometry.shape(), style, drawBounds), nullptr};
}

const Renderer* Device::chooseMSAARenderer(const Shape& shape,
                                           const SkStrokeRec& style,
                                           const Rect& drawBounds) const {
    // TODO: All shapes that select a tessellating path renderer need to be "pre-chopped" if they
    // are large enough to exceed the fixed count tessellation limits. Fills are pre-chopped to the
    // viewport bounds, strokes and stroke-and-fills are pre-chopped to the viewport bounds outset
    // by the stroke radius (hence taking the whole style and not just its type).
    const RendererProvider* renderers = fRecorder->priv().rendererProvider();
    SkStrokeRec::Style type = style.getStyle();

    if (type == SkStrokeRec::kStroke_Style ||
        type == SkStrokeRec::kHairline_Style) {
        // Unlike in Ganesh, the HW stroke tessellator can work with arbitrary paints since the
        // depth test prevents double-blending when there is transparency, thus we can HW stroke
        // any path regardless of its paint.
        // TODO: We treat inverse-filled strokes as regular strokes. We could handle them by
        // stenciling first with the HW stroke tessellator and then covering their bounds, but
        // inverse-filled strokes are not well-specified in our public canvas behavior so we may be
        // able to remove it.
        return renderers->tessellatedStrokes();
    }

    // 'type' could be kStrokeAndFill, but in that case chooseRenderer() is meant to return the
    // fill renderer since tessellatedStrokes() will always be used for the stroke pass.
    if (shape.convex() && !shape.inverted()) {
        // TODO: Ganesh doesn't have a curve+middle-out triangles option for convex paths, but it
        // would be pretty trivial to spin up.
        return renderers->convexTessellatedWedges();
    } else {
        const bool preferWedges =
                // TODO: Combine this heuristic with what is used in PathStencilCoverOp to choose
                // between wedges curves consistently in Graphite and Ganesh.
                (shape.isPath() && shape.path().countVerbs() < 50) ||
                drawBounds.area() <= (256 * 256);

        if (preferWedges) {
            return renderers->stencilTessellatedWedges(shape.fillType());
        } else {
            return renderers->stencilTessellatedCurvesAndTris(shape.fillType());
        }
    }
}

sk_sp<Task> Device::lastDrawTask() const {
    SkASSERT(this->isScratchDevice());
    return fLastTask;
}

void Device::flushPendingWork(DrawContext* drawContext) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);

    // If this is a scratch device being flushed, it should only be flushing into the expected
    // next recording from when the Device was first created.
    SkASSERT(fRecorder);
    SkASSERT(fScopedRecordingID == 0 || fScopedRecordingID == fRecorder->priv().nextRecordingID());

    // Ideally we would just check if `drawTask` was non-null and then call flushTrackedDevices()
    // before we appended `drawTask` afterwards. Unfortunately, internalFlush() is not 100% internal
    // because it can record atlas uploads to the DrawContext. If those uploads were moved to
    // `drawTask` before flushTrackedDevices() is called, any other Devices would incorrectly assume
    // that the uploads would be executed before their tasks, even though that's not the case here.
    if (fDC->modifiesTarget() && fMustFlushDependencies) {
        // If this is a client-owned Device that has also been used as an image in the same Recorder
        // we need flush all tracked devices that have pending reads from this Device, because those
        // need to be resolved *before* `drawTask` would be executed and modify its texture state.
        fMustFlushDependencies = false;
        fRecorder->priv().flushTrackedDevices(this->target());
    }

    // While unbounded recursion is gone, bounded re-entrant flushing is still possible during
    // dependency resolution. We assert *after* the dependency flush to permit this valid re-entry.
    SkASSERT(!fIsFlushing);
    SkDEBUGCODE(fIsFlushing = true;)

    this->internalFlush();
    sk_sp<Task> drawTask = fDC->snapDrawTask();
    if (drawContext) {
        drawContext->recordDependency(std::move(drawTask));
    } else {
        if (this->isScratchDevice()) {
            // TODO(b/323887221): Once shared atlas resources are less brittle, scratch devices
            // won't flush to the recorder at all and will only store the snapped task here.
            fLastTask = drawTask;
        } else {
            // Non-scratch devices do not need to point back to the last snapped task since they are
            // always added to the root task list.
            // TODO: It is currently possible for scratch devices to be flushed and instantiated
            // before their work is finished, meaning they will produce additional tasks to be
            // included in a follow-up Recording:
            // https://chat.google.com/room/AAAA2HlH94I/YU0XdFqX2Uw. However, in this case they no
            // longer appear scratch because the first Recording instantiated the targets. When
            // scratch devices are not actually registered with the Recorder and are only included
            // when they are drawn (e.g. restored), we should be able to assert that `fLastTask` is
            // null.
            fLastTask = nullptr;
        }

        if (drawTask) {
            fRecorder->priv().add(std::move(drawTask));
        }
    }

    SkDEBUGCODE(fIsFlushing = false;)
}

void Device::internalFlush() {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    ASSERT_SINGLE_OWNER

    // Push any pending uploads from the atlas provider that pending draws reference.
    fRecorder->priv().atlasProvider()->recordUploads(fDC.get());

    // Clip shapes are depth-only draws, but aren't recorded in the DrawContext until a flush in
    // order to determine the Z values for each element.
    fClip.recordDeferredClipDraws();

    // Flush all pending items to the internal task list and reset Device tracking state
    fDC->flush(fRecorder);

    fColorDepthBoundsManager->reset();
    fDisjointStencilSet->reset();
    fCurrentDepth = DrawOrder::kClearDepth;
    fAtlasedPathCount = 0;

    // Any cleanup in the AtlasProvider
    fRecorder->priv().atlasProvider()->compact();
}

bool Device::needsFlushBeforeDraw(int numNewRenderSteps, DstReadStrategy dstReadStrategy) {
    // Must also account for the elements in the clip stack that might need to be recorded.
    numNewRenderSteps += fClip.maxDeferredClipDraws() * Renderer::kMaxRenderSteps;
    bool needsFlush =
            // Need flush if we don't have room to record into the current list.
            (DrawList::kMaxRenderSteps - fDC->pendingRenderSteps()) < numNewRenderSteps ||
            // Need flush if this draw needs to copy the dst surface for reading.
            dstReadStrategy == DstReadStrategy::kTextureCopy;

    return needsFlush;
}

void Device::drawSpecial(SkSpecialImage* special,
                         const SkMatrix& localToDevice,
                         const SkSamplingOptions& sampling,
                         const SkPaint& paint,
                         SkCanvas::SrcRectConstraint constraint) {
    SkASSERT(!paint.getMaskFilter() && !paint.getImageFilter());

    sk_sp<SkImage> img = special->asImage();
    if (!img || !as_IB(img)->isGraphiteBacked()) {
        SKGPU_LOG_W("Couldn't get Graphite-backed special image as image");
        return;
    }

    // drawSpecial could be the same as drawEdgeAAImageSet or drawImageRect except that it
    // ignores the currently assigned local-to-device transform and uses the one provided.
    // But because SkSpecialImage guarantees the subset is already contained in the image and it's
    // not empty, we can skip the src/dst correction.
    SkRect src = SkRect::Make(special->subset());
    SkRect dst = SkRect::MakeIWH(special->width(), special->height());
    SkASSERT(img->bounds().contains(src) && !dst.isEmpty());

    SkMatrix localMatrix = *SkMatrix::Rect2Rect(src, dst);
    SkRect subset = constraint == SkCanvas::kStrict_SrcRectConstraint ?
            src : SkRect::Make(img->bounds());
    PaintParams::SimpleImage imageShader{img.get(), &localMatrix, subset, sampling};

    // The image filtering and layer code paths often rely on the paint being non-AA to avoid
    // coverage operations. To stay consistent with the other backends, we use an edge AA "quad"
    // whose flags match the paint's AA request.
    EdgeAAQuad::Flags aaFlags = paint.isAntiAlias() ? EdgeAAQuad::Flags::kAll
                                                    : EdgeAAQuad::Flags::kNone;
    this->drawGeometry(Transform(SkM44(localToDevice)),
                       Geometry(EdgeAAQuad(dst, aaFlags)),
                       PaintParams(paint, imageShader),
                       DefaultFillStyle());
}

void Device::drawCoverageMask(const SkSpecialImage* mask,
                              const SkMatrix& localToDevice,
                              const SkSamplingOptions& sampling,
                              const SkPaint& paint) {
    CoverageMaskShape::MaskInfo maskInfo{/*fTextureOrigin=*/{SkTo<uint16_t>(mask->subset().fLeft),
                                                             SkTo<uint16_t>(mask->subset().fTop)},
                                         /*fMaskSize=*/{SkTo<uint16_t>(mask->width()),
                                                        SkTo<uint16_t>(mask->height())}};

    auto maskProxyView = AsView(mask->asImage());
    if (!maskProxyView) {
        SKGPU_LOG_W("Couldn't get Graphite-backed special image as texture proxy view");
        return;
    }

    // Every other "Image" draw reaches the underlying texture via AddToKey/NotifyInUse, which
    // handles notifying the image and either flushing the linked surface or attaching draw tasks
    // from a scratch device to the current draw context. In this case, 'mask' is very likely to
    // be linked to a scratch device, but we must perform the same notifyInUse manually here because
    // the texture is consumed by the RenderStep and not part of the PaintParams.
    static_cast<Image_Base*>(mask->asImage().get())->notifyInUse(fRecorder, fDC.get());

    // CoverageMaskShape() wraps a Shape when it's used as a PathAtlas, but in this case the
    // original shape has been long lost, so just use a Rect that bounds the image.
    CoverageMaskShape maskShape{Shape{Rect::WH((float)mask->width(), (float)mask->height())},
                                // We store a ref to the textureProxy to keep it alive.
                                maskProxyView.refProxy(),
                                // Use the active local-to-device transform for this since it
                                // determines the local coords for evaluating the skpaint, whereas
                                // the provided 'localToDevice' just places the coverage mask.
                                this->localToDeviceTransform().inverse(),
                                maskInfo};

    this->drawGeometry(Transform(SkM44(localToDevice)),
                       Geometry(maskShape),
                       PaintParams(paint),
                       DefaultFillStyle());
}

sk_sp<SkSpecialImage> Device::snapSpecial(const SkIRect& subset, bool forceCopy) {
    // NOTE: snapSpecial() can be called even after the device has been marked immutable (null
    // recorder), but in those cases it should not be a copy and just returns the image view.
    sk_sp<Image> deviceImage;
    SkIRect finalSubset;
    if (forceCopy || !this->readSurfaceView() || this->readSurfaceView().proxy()->isFullyLazy()) {
        deviceImage = this->makeImageCopy(
                subset, Budgeted::kYes, Mipmapped::kNo, SkBackingFit::kApprox);
        finalSubset = SkIRect::MakeSize(subset.size());
    } else {
        // TODO(b/323886870): For now snapSpecial() force adds the pending work to the recorder's
        // root task list. Once shared atlas management is solved and DrawTasks can be nested in a
        // graph then this can go away in favor of auto-flushing through the image's linked device.
        if (fRecorder) {
            this->flushPendingWork(/*drawContext=*/nullptr);
        }
        deviceImage = Image::WrapDevice(sk_ref_sp(this));
        finalSubset = subset;
    }

    if (!deviceImage) {
        return nullptr;
    }

    // For non-copying "snapSpecial", the semantics are returning an image view of the surface data,
    // and relying on higher-level draw and restore logic for the contents to make sense.
    return SkSpecialImages::MakeGraphite(
            fRecorder, finalSubset, std::move(deviceImage), this->surfaceProps());
}

sk_sp<skif::Backend> Device::createImageFilteringBackend(const SkSurfaceProps& surfaceProps,
                                                         SkColorType colorType) const {
    return skif::MakeGraphiteBackend(fRecorder, surfaceProps, colorType);
}

TextureProxy* Device::target() { return fDC->target(); }

TextureProxyView Device::readSurfaceView() const { return fDC->readSurfaceView(); }

bool Device::isScratchDevice() const {
    // Scratch device status is inferred from whether or not the Device's target is instantiated.
    // By default devices start out un-instantiated unless they are wrapping an existing backend
    // texture (definitely not a scratch scenario), or Surface explicitly instantiates the target
    // before returning to the client (not a scratch scenario).
    //
    // Scratch device targets are instantiated during the prepareResources() phase of
    // Recorder::snap(). Truly scratch devices that have gone out of scope as intended will have
    // already been destroyed at this point. Scratch devices that become longer-lived (linked to
    // a client-owned object) automatically transition to non-scratch usage.
    return !fDC->target()->isInstantiated() && !fDC->target()->isLazy();
}

sk_sp<sktext::gpu::Slug> Device::convertGlyphRunListToSlug(const sktext::GlyphRunList& glyphRunList,
                                                           const SkPaint& paint) {
    return sktext::gpu::SlugImpl::Make(this->localToDevice(),
                                       glyphRunList,
                                       paint,
                                       this->strikeDeviceInfo(),
                                       SkStrikeCache::GlobalStrikeCache());
}

void Device::drawSlug(SkCanvas* canvas, const sktext::gpu::Slug* slug, const SkPaint& paint) {
    auto slugImpl = static_cast<const sktext::gpu::SlugImpl*>(slug);
    slugImpl->subRuns()->draw(canvas, slugImpl->origin(), paint, slugImpl, this->atlasDelegate());
}

bool Device::drawBlurredRRect(const SkRRect& rrect, const SkPaint& paint, float deviceSigma) {
    if (skgpu::BlurIsEffectivelyIdentity(deviceSigma)) {
        this->drawRRect(rrect, paint);
        return true;
    }

    std::optional<AnalyticBlurMask> analyticBlur = AnalyticBlurMask::Make(
            this->recorder(), this->localToDeviceTransform(), deviceSigma, rrect);
    if (!analyticBlur) {
        return false;
    }

    this->drawGeometry(this->localToDeviceTransform(),
                       Geometry(*analyticBlur),
                       PaintParams(paint),
                       SkStrokeRec(paint));
    return true;
}

} // namespace skgpu::graphite
