/*
 * 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_stack.back();
    m_stack.push_back(copy);
}

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

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

void RiveRenderer::modulateOpacity(float opacity)
{
    m_stack.back().modulatedOpacity =
        std::max(0.0f, m_stack.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_stack.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_stack.back().matrix.findMaxScale();
        if (paint->getFeather() * matrixMaxScale > 1)
        {
            clipAndPushDraw(gpu::PathDraw::Make(
                m_context,
                m_stack.back().matrix,
                path->makeSoftenedCopyForFeathering(paint->getFeather(),
                                                    matrixMaxScale),
                path->getFillRule(),
                paint,
                m_stack.back().modulatedOpacity,
                &m_scratchPath));
            return;
        }
    }

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

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

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

    if (path->getRawPath().empty())
    {
        m_stack.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_stack.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_stack.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_stack.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_stack.back().overallClipPixelBounds.empty())
        {
            const Mat2D& m = m_stack.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_stack.back().overallClipPixelBounds.empty())
    {
        return;
    }

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

    clipAndPushDraw(gpu::DrawUniquePtr(
        m_context->make<gpu::ImageMeshDraw>(gpu::Draw::FULLSCREEN_PIXEL_BOUNDS,
                                            m_stack.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_stack.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_stack.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
                                &m_scratchPath,
                                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
