/*
 * Copyright 2022 Rive
 */

#include "rive/renderer/rive_renderer.hpp"

#include "rive_render_paint.hpp"
#include "rive_render_path.hpp"
#include "rive/math/math_types.hpp"
#include "rive/math/simd.hpp"
#include "rive/renderer/rive_render_image.hpp"
#include "rive/profiler/profiler_macros.h"

namespace rive
{
bool RiveRenderer::IsAABB(const RawPath& path, AABB* result)
{
    RIVE_PROF_SCOPE_L(3)
    // Any quadrilateral begins with a move plus 3 lines.
    constexpr static size_t kAABBVerbCount = 4;
    constexpr static PathVerb aabbVerbs[kAABBVerbCount] = {PathVerb::move,
                                                           PathVerb::line,
                                                           PathVerb::line,
                                                           PathVerb::line};
    Span<const PathVerb> verbs = path.verbs();
    if (verbs.count() < kAABBVerbCount ||
        memcmp(verbs.data(), aabbVerbs, sizeof(aabbVerbs)) != 0)
    {
        return false;
    }

    // Only accept extra verbs and points if every point after the quadrilateral
    // is equal to p0.
    Span<const Vec2D> pts = path.points();
    for (size_t i = 4; i < pts.count(); ++i)
    {
        if (pts[i] != pts[0])
        {
            return false;
        }
    }

    // We have a quadrilateral! Now check if it is an axis-aligned rectangle.
    float4 corners = {pts[0].x, pts[0].y, pts[2].x, pts[2].y};
    float4 oppositeCorners = {pts[1].x, pts[1].y, pts[3].x, pts[3].y};
    if (simd::all(corners == oppositeCorners.zyxw) ||
        simd::all(corners == oppositeCorners.xwzy))
    {
        float4 r = simd::join(simd::min(corners.xy, corners.zw),
                              simd::max(corners.xy, corners.zw));
        simd::store(result, r);
        return true;
    }
    return false;
}

RiveRenderer::ClipElement::ClipElement(const Mat2D& matrix_,
                                       const RiveRenderPath* path_,
                                       FillRule fillRule_,
                                       IAABB pixelBounds_)
{
    reset(matrix_, path_, fillRule_, pixelBounds_);
}

RiveRenderer::ClipElement::~ClipElement() {}

void RiveRenderer::ClipElement::reset(const Mat2D& matrix_,
                                      const RiveRenderPath* path_,
                                      FillRule fillRule_,
                                      IAABB pixelBounds_)
{
    matrix = matrix_;
    rawPathMutationID = path_->getRawPathMutationID();
    pathBounds = path_->getBounds();
    path = ref_rcp(path_);
    fillRule = fillRule_;
    clipID = 0; // This gets initialized lazily.
    pixelBounds = pixelBounds_;
}

bool RiveRenderer::ClipElement::isEquivalent(const Mat2D& matrix_,
                                             const RiveRenderPath* path_) const
{
    return matrix_ == matrix &&
           path_->getRawPathMutationID() == rawPathMutationID &&
           path_->getFillRule() == fillRule;
}

RiveRenderer::RiveRenderer(gpu::RenderContext* context) : m_context(context) {}

RiveRenderer::~RiveRenderer() {}

void RiveRenderer::save()
{
    // Copy the back of the stack before pushing, in case the vector grows and
    // invalidates the reference.
    RenderState copy = m_renderStateStack.back();
    m_renderStateStack.push_back(copy);
}

void RiveRenderer::restore()
{
    assert(m_renderStateStack.size() > 1);
    assert(m_renderStateStack.back().clipStackHeight >=
           m_renderStateStack[m_renderStateStack.size() - 2].clipStackHeight);
    m_renderStateStack.pop_back();
}

void RiveRenderer::transform(const Mat2D& matrix)
{
    m_renderStateStack.back().matrix =
        m_renderStateStack.back().matrix * matrix;
}

void RiveRenderer::modulateOpacity(float opacity)
{
    m_renderStateStack.back().modulatedOpacity =
        std::max(0.0f, m_renderStateStack.back().modulatedOpacity * opacity);
}

void RiveRenderer::drawPath(RenderPath* renderPath, RenderPaint* renderPaint)
{
    RIVE_PROF_SCOPE_L(2)
    LITE_RTTI_CAST_OR_RETURN(path, RiveRenderPath*, renderPath);
    LITE_RTTI_CAST_OR_RETURN(paint, RiveRenderPaint*, renderPaint);

    if (path->getRawPath().empty())
    {
        return;
    }

    if (paint->getIsStroked() && m_context->frameDescriptor().strokesDisabled)
    {
        return;
    }
    if (!paint->getIsStroked() && m_context->frameDescriptor().fillsDisabled)
    {
        return;
    }
    if (paint->getIsStroked() &&
        // Use inverse logic to ensure we abort when stroke thickness is NaN.
        !(paint->getThickness() > 0))
    {
        return;
    }
    // Use inverse logic to ensure we abort when stroke thickness is NaN.
    if (!(paint->getFeather() >= 0))
    {
        return;
    }
    if (m_renderStateStack.back().overallClipPixelBounds.empty())
    {
        return;
    }

    if (paint->getFeather() != 0 && !paint->getIsStroked())
    {
        if (path->getFillRule() != FillRule::clockwise &&
            !m_context->frameDescriptor().clockwiseFillOverride)
        {
            // Don't draw feathered fills that aren't clockwise.
            return;
        }
        float matrixMaxScale = m_renderStateStack.back().matrix.findMaxScale();
        if (paint->getFeather() * matrixMaxScale > 1)
        {
            clipAndPushDraw(gpu::PathDraw::Make(
                m_context,
                m_renderStateStack.back().matrix,
                path->makeSoftenedCopyForFeathering(paint->getFeather(),
                                                    matrixMaxScale),
                path->getFillRule(),
                paint,
                m_renderStateStack.back().modulatedOpacity));
            return;
        }
    }

    clipAndPushDraw(
        gpu::PathDraw::Make(m_context,
                            m_renderStateStack.back().matrix,
                            ref_rcp(path),
                            path->getFillRule(),
                            paint,
                            m_renderStateStack.back().modulatedOpacity));
}

void RiveRenderer::clipPath(RenderPath* renderPath)
{
    RIVE_PROF_SCOPE_L(2)
    LITE_RTTI_CAST_OR_RETURN(path, RiveRenderPath*, renderPath);

    if (m_renderStateStack.back().overallClipPixelBounds.empty())
    {
        return;
    }

    if (path->getRawPath().empty())
    {
        m_renderStateStack.back().overallClipPixelBounds = {};
        return;
    }

    // First try to handle axis-aligned rectangles using the "ENABLE_CLIP_RECT"
    // shader feature. Multiple axis-aligned rectangles can be intersected into
    // a single rectangle if their matrices are compatible.
    AABB clipRectCandidate;
    if (m_context->frameSupportsClipRects() &&
        IsAABB(path->getRawPath(), &clipRectCandidate))
    {
        clipRectImpl(clipRectCandidate, path);
    }
    else
    {
        clipPathImpl(path);
    }
}

// Finds a new rect, if such a rect exists, such that:
//
//     currentMatrix * rect == newMatrix * newRect
//
// Returns true if *rect was replaced with newRect.
static bool transform_rect_to_new_space(AABB* rect,
                                        const Mat2D& currentMatrix,
                                        const Mat2D& newMatrix)
{
    if (currentMatrix == newMatrix)
    {
        return true;
    }
    Mat2D currentToNew;
    if (!newMatrix.invert(&currentToNew))
    {
        return false;
    }
    currentToNew = currentToNew * currentMatrix;
    float maxSkew = fmaxf(fabsf(currentToNew.xy()), fabsf(currentToNew.yx()));
    float maxScale = fmaxf(fabsf(currentToNew.xx()), fabsf(currentToNew.yy()));
    if (maxSkew > math::EPSILON && maxScale > math::EPSILON)
    {
        // Transforming this rect to the new view matrix would turn it into
        // something that isn't a rect.
        return false;
    }
    Vec2D pts[2] = {{rect->left(), rect->top()},
                    {rect->right(), rect->bottom()}};
    currentToNew.mapPoints(pts, pts, 2);
    float4 p = simd::load4f(pts);
    float2 topLeft = simd::min(p.xy, p.zw);
    float2 botRight = simd::max(p.xy, p.zw);
    *rect = {topLeft.x, topLeft.y, botRight.x, botRight.y};
    return true;
}

void RiveRenderer::clipRectImpl(AABB rect, const RiveRenderPath* originalPath)
{
    RIVE_PROF_SCOPE_L(3)

    auto& renderState = m_renderStateStack.back();
    bool hasClipRect = renderState.clipRectInverseMatrix != nullptr;
    if (rect.isEmptyOrNaN())
    {
        renderState.overallClipPixelBounds = {};
        return;
    }

    // If there already is a clipRect, we can only accept another one by
    // intersecting it with the existing one. This means the new rect must be
    // axis-aligned with the existing clipRect.
    if (hasClipRect && !transform_rect_to_new_space(&rect,
                                                    renderState.matrix,
                                                    renderState.clipRectMatrix))
    {
        // 'rect' is not axis-aligned with the existing clipRect. Fall back to
        // clipPath.
        clipPathImpl(originalPath);
        return;
    }

    if (!hasClipRect)
    {
        // There wasn't an existing clipRect. This is the one!
        renderState.clipRect = rect;
        renderState.clipRectMatrix = renderState.matrix;
    }
    else
    {
        // Both rects are in the same space now. Intersect the two
        // geometrically.
        float4 a = simd::load4f(&renderState.clipRect);
        float4 b = simd::load4f(&rect);
        float4 intersection =
            simd::join(simd::max(a.xy, b.xy), simd::min(a.zw, b.zw));
        simd::store(&renderState.clipRect, intersection);
    }

    // Grab the pixel bounds of the new combined (intersected) clip rect
    renderState.clipRectPixelBounds =
        renderState.clipRectMatrix.mapBoundingBox(renderState.clipRect)
            .roundOut();

    renderState.overallClipPixelBounds =
        renderState.overallClipPixelBounds.intersect(
            renderState.clipRectPixelBounds);

    renderState.clipRectInverseMatrix =
        m_context->make<gpu::ClipRectInverseMatrix>(renderState.clipRectMatrix,
                                                    renderState.clipRect);
}

void RiveRenderer::clipPathImpl(const RiveRenderPath* path)
{
    RIVE_PROF_SCOPE_L(3)
    auto& renderState = m_renderStateStack.back();
    if (path->getBounds().isEmptyOrNaN())
    {
        renderState.overallClipPixelBounds = {};
        return;
    }
    // Only write a new clip element if this path isn't already on the stack
    // from before. e.g.:
    //
    //     clipPath(samePath);
    //     restore();
    //     save();
    //     clipPath(samePath); // <-- reuse the ClipElement (and clipID!)
    //     already in m_clipStack.
    //
    const size_t clipStackHeight = renderState.clipStackHeight;
    assert(m_clipStack.size() >= clipStackHeight);
    if (m_clipStack.size() == clipStackHeight ||
        !m_clipStack[clipStackHeight].isEquivalent(renderState.matrix, path))
    {
        // Calculate the pixel bounds for this clip path before we push it into
        // the stack to ensure that we even need to do so
        const auto pixelBounds =
            renderState.matrix.mapBoundingBox(path->getRawPath().points())
                .roundOut();
        renderState.overallClipPixelBounds =
            renderState.overallClipPixelBounds.intersect(pixelBounds);
        if (renderState.overallClipPixelBounds.empty())
        {
            // Nothing can draw under this, so no need to add to the stack.
            return;
        }

        m_clipStack.resize(clipStackHeight);
        m_clipStack.emplace_back(renderState.matrix,
                                 path,
                                 path->getFillRule(),
                                 pixelBounds);
    }
    else
    {
        // We are going to reuse the element that is already in the clip stack,
        // but need to re-update the overall clip pixel bounds.
        renderState.overallClipPixelBounds =
            renderState.overallClipPixelBounds.intersect(
                m_clipStack[clipStackHeight].pixelBounds);
        if (renderState.overallClipPixelBounds.empty())
        {
            // Nothing can draw under this, so no need to increment the stack
            // height.
            return;
        }
    }

    renderState.clipStackHeight = clipStackHeight + 1;
}

void RiveRenderer::drawImage(const RenderImage* renderImage,
                             ImageSampler imageSampler,
                             BlendMode blendMode,
                             float opacity)
{
    RIVE_PROF_SCOPE_L(2)
    LITE_RTTI_CAST_OR_RETURN(image, const RiveRenderImage*, renderImage);

    rcp<gpu::Texture> imageTexture = image->refTexture();
    if (imageTexture == nullptr)
    {
        // imageTexture may be null if the backend uses a custom factory and/or
        // updates out-of-band assets asynchronously. If there's no texture yet,
        // just don't draw anything.
        return;
    }

    // Apply modulated opacity (clamp to prevent negative values)
    float finalOpacity =
        std::max(0.0f, opacity * m_renderStateStack.back().modulatedOpacity);

    // Scale the view matrix so we can draw this image as the rect [0, 0, 1, 1].
    save();
    scale(image->width(), image->height());

    if (!m_context->frameSupportsImagePaintForPaths())
    {
        // Fall back on ImageRectDraw if the current frame doesn't support
        // drawing paths with image paints.
        if (!m_renderStateStack.back().overallClipPixelBounds.empty())
        {
            const Mat2D& m = m_renderStateStack.back().matrix;
            clipAndPushDraw(
                gpu::DrawUniquePtr(m_context->make<gpu::ImageRectDraw>(
                    m_context,
                    m.mapBoundingBox(AABB{0, 0, 1, 1}).roundOut(),
                    m,
                    blendMode,
                    std::move(imageTexture),
                    imageSampler,
                    finalOpacity)));
        }
    }
    else
    {
        // Implement drawImage() as drawPath() with a rectangular path and an
        // image paint.
        if (m_unitRectPath == nullptr)
        {
            m_unitRectPath = make_rcp<RiveRenderPath>();
            m_unitRectPath->line({1, 0});
            m_unitRectPath->line({1, 1});
            m_unitRectPath->line({0, 1});
        }

        RiveRenderPaint paint;
        paint.image(std::move(imageTexture), finalOpacity);
        paint.blendMode(blendMode);
        paint.imageSampler(imageSampler);
        drawPath(m_unitRectPath.get(), &paint);
    }

    restore();
}

void RiveRenderer::drawImageMesh(const RenderImage* renderImage,
                                 ImageSampler imageSampler,
                                 rcp<RenderBuffer> vertices_f32,
                                 rcp<RenderBuffer> uvCoords_f32,
                                 rcp<RenderBuffer> indices_u16,
                                 uint32_t vertexCount,
                                 uint32_t indexCount,
                                 BlendMode blendMode,
                                 float opacity)
{
    RIVE_PROF_SCOPE_L(2)
    LITE_RTTI_CAST_OR_RETURN(image, const RiveRenderImage*, renderImage);

    rcp<gpu::Texture> imageTexture = image->refTexture();
    if (imageTexture == nullptr)
    {
        // imageTexture may be null if the backend uses a custom factory and/or
        // updates out-of-band assets asynchronously. If there's no texture yet,
        // just don't draw anything.
        return;
    }

    assert(vertices_f32);
    assert(uvCoords_f32);
    assert(indices_u16);

    if (m_renderStateStack.back().overallClipPixelBounds.empty())
    {
        return;
    }

    // Apply modulated opacity (clamp to prevent negative values)
    float finalOpacity =
        std::max(0.0f, opacity * m_renderStateStack.back().modulatedOpacity);

    clipAndPushDraw(gpu::DrawUniquePtr(
        m_context->make<gpu::ImageMeshDraw>(gpu::Draw::FULLSCREEN_PIXEL_BOUNDS,
                                            m_renderStateStack.back().matrix,
                                            blendMode,
                                            std::move(imageTexture),
                                            imageSampler,
                                            std::move(vertices_f32),
                                            std::move(uvCoords_f32),
                                            std::move(indices_u16),
                                            indexCount,
                                            finalOpacity)));
}

void RiveRenderer::clipAndPushDraw(gpu::DrawUniquePtr draw)
{
    RIVE_PROF_SCOPE_L(3)
    assert(!m_renderStateStack.back().overallClipPixelBounds.empty());
    if (draw.get() == nullptr)
    {
        return;
    }
    if (m_context->isOutsideCurrentFrame(draw->pixelBounds()))
    {
        return;
    }

    // Make two attempts to issue the draw: once on the context as-is and once
    // with a clean flush.
    for (int i = 0; i < 2; ++i)
    {
        // Always make sure we begin this loop with the internal draw batch
        // empty, and clear it when we're done.
        struct AutoResetInternalDrawBatch
        {
        public:
            AutoResetInternalDrawBatch(RiveRenderer* renderer) :
                m_renderer(renderer)
            {
                assert(m_renderer->m_internalDrawBatch.empty());
            }
            ~AutoResetInternalDrawBatch()
            {
                m_renderer->m_internalDrawBatch.clear();
            }

        private:
            RiveRenderer* m_renderer;
        };

        AutoResetInternalDrawBatch aridb(this);

        auto applyClipResult = applyClip(draw.get());
        if (applyClipResult == ApplyClipResult::failure)
        {
            // There wasn't room in the GPU buffers for this path draw. Flush
            // and try again.
            m_context->logicalFlush();
            continue;
        }
        else if (applyClipResult == ApplyClipResult::fullyClipped)
        {
            return;
        }

        m_internalDrawBatch.push_back(std::move(draw));
        if (!m_context->pushDraws(m_internalDrawBatch.data(),
                                  m_internalDrawBatch.size()))
        {
            // There wasn't room in the GPU buffers for this path draw. Flush
            // and try again.
            m_context->logicalFlush();
            // Reclaim "draw" because we will use it again on the next
            // iteration.
            draw = std::move(m_internalDrawBatch.back());
            assert(draw != nullptr);
            m_internalDrawBatch.pop_back();
            continue;
        }

        // Success!
        return;
    }

    // We failed to process the draw. Release its refs.
    fprintf(stderr,
            "RiveRenderer::clipAndPushDraw failed. The draw and/or clip stack "
            "are too complex.\n");
}

// Used by clipping in clockwiseAtomic mode.
//
// Returns the inverse of a path, meaning, regions that were filled in the old
// path are now empty, and empty regions in the old path are now filled.
//
// NOTE: A true inverse path would expand infinitely in all directions, but this
// function limits it by the provided "bounds".
//
// NOTE: The returned path is always clockwise, even if the given path was not.
// If the given path is not clockwise, we attempt to convert it to clockwise
// based on its dominant winding direction. This may or may not be accurate.
static rcp<RiveRenderPath> invertClockwisePath(const RiveRenderPath* path,
                                               FillRule pathFillRule,
                                               const Mat2D& viewMatrix,
                                               IAABB bounds)
{
    auto inversePath = make_rcp<RiveRenderPath>();
    inversePath->fillRule(FillRule::clockwise);
    Mat2D viewInverseMatrix;
    if (viewMatrix.invert(&viewInverseMatrix))
    {
        // Add the pre-viewMatrix "bounds" rect to the new path.
        std::array<Vec2D, 4> boundsVertices = {
            Vec2D(bounds.left, bounds.top),
            Vec2D(bounds.right, bounds.top),
            Vec2D(bounds.right, bounds.bottom),
            Vec2D(bounds.left, bounds.bottom),
        };
        viewInverseMatrix.mapPoints(boundsVertices.data(),
                                    boundsVertices.data(),
                                    4);
        inversePath->move(boundsVertices[0]);
        if (const float viewMatrixDeterminant =
                viewMatrix[0] * viewMatrix[3] - viewMatrix[2] * viewMatrix[1];
            viewMatrixDeterminant >= 0)
        {
            inversePath->line(boundsVertices[1]);
            inversePath->line(boundsVertices[2]);
            inversePath->line(boundsVertices[3]);
        }
        else
        {
            inversePath->line(boundsVertices[3]);
            inversePath->line(boundsVertices[2]);
            inversePath->line(boundsVertices[1]);
        }
        // Subtract the given path out of the bounds rect.
        if (pathFillRule == FillRule::clockwise || path->getCoarseArea() >= 0)
        {
            inversePath->addRenderPathBackwards(path, Mat2D());
        }
        else
        {
            inversePath->addRenderPath(path, Mat2D());
        }
    }
    return inversePath;
}

RiveRenderer::ApplyClipResult RiveRenderer::applyClip(gpu::Draw* draw)
{
    RIVE_PROF_SCOPE_L(3)
    auto& renderState = m_renderStateStack.back();

    draw->setClipRect(renderState.clipRectInverseMatrix,
                      renderState.overallClipPixelBounds);

    if (draw->clippedPixelBounds().empty() ||
        m_context->isOutsideCurrentFrame(draw->clippedPixelBounds()))
    {
        // Either this draw is outside of the current frame (in which case it's
        // not visible) or it was completely clipped by the current overall clip
        // bounds.
        return ApplyClipResult::fullyClipped;
    }

    const size_t clipStackHeight = renderState.clipStackHeight;
    if (clipStackHeight == 0)
    {
        assert(draw->clipID() == 0);
        return ApplyClipResult::success;
    }

    // Find which clip element in the stack (if any) is currently rendered to
    // the clip buffer.
    size_t clipIdxCurrentlyInClipBuffer = -1; // i.e., "none".
    if (m_context->getClipContentID() != 0)
    {
        for (size_t i = clipStackHeight - 1; i != -1; --i)
        {
            if (m_clipStack[i].clipID == m_context->getClipContentID())
            {
                clipIdxCurrentlyInClipBuffer = i;
                break;
            }
        }
    }

    // Draw the necessary updates to the clip buffer (i.e., draw every clip
    // element after clipIdxCurrentlyInClipBuffer).
    uint32_t parentClipID =
        clipIdxCurrentlyInClipBuffer == -1
            ? 0 // The next clip to be drawn is not nested.
            : m_clipStack[clipIdxCurrentlyInClipBuffer].clipID;
    if (m_context->frameInterlockMode() ==
            gpu::InterlockMode::clockwiseAtomic ||
        m_context->frameInterlockMode() == gpu::InterlockMode::msaa)
    {
        if (parentClipID == 0 && m_context->getClipContentID() != 0)
        {
            // Time for a new stencil clip! Erase the clip currently in the
            // stencil buffer before we draw the new one.
            auto stencilClipClear =
                gpu::DrawUniquePtr(m_context->make<gpu::ClipReset>(
                    m_context,
                    m_context->getClipContentID(),
                    gpu::DrawContents::none,
                    gpu::ClipReset::ResetAction::clearPreviousClip));
            if (!m_context->isOutsideCurrentFrame(
                    stencilClipClear->pixelBounds()))
            {
                m_internalDrawBatch.push_back(std::move(stencilClipClear));
            }
        }
    }

    for (size_t i = clipIdxCurrentlyInClipBuffer + 1; i < clipStackHeight; ++i)
    {
        ClipElement& clip = m_clipStack[i];
        assert(clip.pathBounds == clip.path->getBounds());

        IAABB clipDrawBounds;
        RiveRenderPaint clipUpdatePaint;
        clipUpdatePaint.clipUpdate(
            /*clip THIS clipDraw against:*/ parentClipID);

        rcp clipPath = clip.path;
        FillRule clipFillRule = clip.fillRule;
        std::optional pixelBounds = clip.pixelBounds;

        if (m_context->frameInterlockMode() ==
                gpu::InterlockMode::clockwiseAtomic &&
            parentClipID != 0)
        {
            // clockwiseAtomic implements nested clips by erasing the inverse
            // of the inner path from the outer clip.
            clipPath = invertClockwisePath(
                clipPath.get(),
                clipFillRule,
                clip.matrix,
                m_context->getClipContentBounds(parentClipID));
            clipFillRule = FillRule::clockwise;

            // Clear this because the inverted path has different pixel bounds
            // (as it now contains the clip content bounds as a box around the
            // path)
            pixelBounds = std::nullopt;
        }

        gpu::DrawUniquePtr clipDraw =
            gpu::PathDraw::Make(m_context,
                                clip.matrix,
                                std::move(clipPath),
                                clipFillRule,
                                &clipUpdatePaint,
                                1.0f, // no opacity modulation for clips
                                pixelBounds);

        // We have already validated that the clip path is within the screen
        //  bounds, so this should never return null (which is the "this is
        //  offscreen" result).
        assert(clipDraw != nullptr);

        clipDrawBounds = clipDraw->pixelBounds();

        // Generate a new clipID every time we (re-)render an element to the
        // clip buffer. (Each embodiment of the element needs its own
        // separate readBounds.)
        {
            // if we have a parent, use its current adjusted write bounds as its
            // outer bounds, otherwise limit it to the screen area.
            // TODO: This should take into account any clip rect that might be
            // applied.
            const auto outerBounds =
                (parentClipID != 0)
                    ? m_context->getTightenedClipBounds(parentClipID)
                    : AABBu16::MakeWH(
                          m_context->frameDescriptor().renderTargetWidth,
                          m_context->frameDescriptor().renderTargetHeight);

            // Trim the draw bounds to the outer bounds as the initial minimal
            // clip bounds (we shouldn't need to write to or read from anywhere
            // that is outside of the screen or a parent clip's box, if one
            // exists).
            const auto tightenedBounds = outerBounds.intersect(clipDrawBounds);

            // If there is a parent clip, the next element up the clip stack
            // should have its ID.
            assert(parentClipID == 0 ||
                   (i != 0 && m_clipStack[i - 1].clipID == parentClipID));

            clip.clipID = m_context->generateClipID(clipDrawBounds,
                                                    parentClipID,
                                                    tightenedBounds);
        }
        assert(clip.clipID != m_context->getClipContentID());
        if (clip.clipID == 0)
        {
            return ApplyClipResult::failure; // The context is out of
                                             // clipIDs. We will flush and
                                             // try again.
        }
        clipDraw->setClipID(clip.clipID);

        gpu::DrawContents clipDrawContents = clipDraw->drawContents();
        if (!m_context->isOutsideCurrentFrame(clipDrawBounds))
        {
            m_internalDrawBatch.push_back(std::move(clipDraw));
        }

        if (parentClipID != 0)
        {
            if (m_context->frameInterlockMode() == gpu::InterlockMode::msaa)
            {
                // When drawing nested stencil clips, we need to intersect them,
                // which involves erasing the region of the current clip in the
                // stencil buffer that is outside the the one we just drew.
                auto stencilClipIntersect =
                    gpu::DrawUniquePtr(m_context->make<gpu::ClipReset>(
                        m_context,
                        parentClipID,
                        clipDrawContents,
                        gpu::ClipReset::ResetAction::intersectPreviousClip));
                if (!m_context->isOutsideCurrentFrame(
                        stencilClipIntersect->pixelBounds()))
                {
                    m_internalDrawBatch.push_back(
                        std::move(stencilClipIntersect));
                }
            }
        }

        parentClipID = clip.clipID; // Nest the next clip (if any) inside the
                                    // one we just rendered.
    }

    assert(parentClipID == m_clipStack[clipStackHeight - 1].clipID);
    draw->setClipID(parentClipID);
    m_context->setClipContentID(parentClipID);

    return ApplyClipResult::success;
}
} // namespace rive
