/*
 * Copyright 2026 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/DrawListLayer.h"

#include "include/core/SkTypes.h"
#include "include/gpu/graphite/Recorder.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/graphite/DrawPass.h"
#include "src/gpu/graphite/DrawWriter.h"
#include "src/gpu/graphite/KeyContext.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/Renderer.h"
#include "src/gpu/graphite/geom/Geometry.h"

namespace skgpu::graphite {

void DrawListLayer::reset(LoadOp loadOp, SkColor4f color) {
    DrawListBase::reset(loadOp, color);

    fStorage.reset();
    fLayers.reset();
    fDrawCount = 0;
    fOrderCounter = CompressedPaintersOrder::First();
}

// Draws affected by depth only draws we call "clipped draws."
//
// Clipped draws must come *after* all depth only draws that affect them, and they must come *after*
// any preceding draws from the same renderstep. To accomodate this:
//      1) When recording the depth only draws, a pointer marking the latest layer inserted into is
//         passed between each draw. If a later draws inserts after an earlier draw, the pointer is
//         overwritten. This ensures that the pointer is always the *latest* layer.
//      2) How the pointer is used depends on the property of clipped draw:
//         - Clipped draws which do not dependOnDst use this as the start of the traversal, then
//           proceed FORWARDS until finding a suitable layer.
//         - Clipped draws which do dependOnDst must stop when encountering any shading intersecting
//           draw. Thus, forwards traversal becomes impractical because the draw must exhaustively
//           search layers to the tail to ensure that there are no intersections. Instead,
//           these draws must take the normal BACKWARDS traversal.
//      3) Each clipped draw updates the starting layer to the layer that it inserted into. Because
//         the stopLayer is treated exclusively, a sucessor renderstep stops its traversal before
//         the stopLayer, thus preserving the relative ordering between the draws. (Note: will be
//         changed in future CL, so kind of stub comment)
std::pair<Layer*, BindingList*> DrawListLayer::searchBackwards(
        const RenderStep* step,
        const LayerKey& key,
        SkEnumBitMask<BoundsFlags> testMask,
        const DrawParams* drawParams,
        CompressedPaintersOrder stop) {
    Layer* targetLayer = nullptr;
    BindingList* targetMatch = nullptr;
    BindingList* forwardMerge = nullptr;

    // Forward merging attempts to pull an earlier, compatible draw out of the current layer and
    // push it into a newly created layer to improve pipeline/texture batching.
    //
    // 1. Draw Type Restrictions (Single Renderstep & No Depth-Only):
    //    Forward merging is strictly limited to single-renderstep shading draws. We explicitly
    //    forbid depth-only draws (which pass `false` for `canForwardMerge`), and the single-step
    //    requirement inherently excludes stencil draws. If we allowed multi-step renderers to
    //    forward merge, we would risk pulling a parent renderstep forward and over its
    //    already-inserted child.
    //
    // 2. Directional & Spatial Validity:
    //    Because we evaluate bindings backwards (tail to head), any binding matches found prior to
    //    intersecting a draw are executed *after* that intersecting draw. Furthermore, because
    //    standard shading draws within the same layer are guaranteed by the `test()` logic to be
    //    mutually disjoint, the matched draw does not overlap with any of the later bindings we
    //    evaluated and skipped. Therefore, it is visually safe to extract this disjoint match and
    //    defer its execution to a new, subsequent layer without violating the Painter's Algorithm.
    //
    // 3. The Tail-Only Restriction:
    //    We strictly limit forward merging to the *tail* of the layer list. If we allowed forward
    //    merging from a middle layer, we would be forced to insert the newly generated target layer
    //    into the middle of the list. This would break the structural invariant that
    //    `Layer::fOrder` strictly increases with the physical list order; this invariant necessary
    //    to ensure that a draw is inserted after *ALL* depth-only clip draws that affect it.
    bool canForwardMerge = key.isSimpleShading();

    Layer* current = fLayers.tail();
    for (int limit = kMaxSearchLimit; limit > 0 && current; --limit) {
        auto [result, match] = current->test(drawParams->drawBounds(), key, testMask);

        if (result & BoundsTestResult::kAllowedInLayer) {
            // Allowed in the layer, so remember it. In complex scenes, we want to search deeper
            // in the layer list than just the first compatible overlap we encounter. Stopping early
            // reduces search time but fragments batching. Inserting early blocks subsequent draws
            // from reaching those denser, later candidates (particularly when this is a clip draw
            // as that propagates into the stop layer for subsequent draws).
            targetLayer = current;
            targetMatch = match;
        } else if (match && canForwardMerge) {
            SkASSERT(result == BoundsTestResult::kBlocked &&
                     !SkToBool(key.fFlags & BoundsFlags::kMustBeDisjoint) &&
                     current == fLayers.tail());
            forwardMerge = match;
        }

        if (!SkToBool(result & BoundsTestResult::kAllowedBeforeLayer) || current->fOrder == stop) {
            break;
        } else {
            current = current->fPrev;
            canForwardMerge = false;

            // To support deeper searches while mitigating search time, if we found a matching
            // BindingList then we penalize the remaining search limit by subtracting half of
            // kMaxSearchLimit. Ultimately this is an imprecise heuristic. In an ideal world, we
            // would maximize batching by exhaustively searching to the end of the list, but that
            // would degrade insertion performance to O(n^2).
            if (match) {
                limit -= kMaxSearchLimit >> 1;
            }
        }
    }

    SkASSERT(!targetLayer || targetLayer->fOrder >= stop);

    if (!targetLayer) {
        fOrderCounter = fOrderCounter.next();
        targetLayer = fStorage.make<Layer>(fOrderCounter);
        if (forwardMerge) {
            SkASSERT(current);
            SkASSERT(current == fLayers.tail());
            current->fBindings.remove(forwardMerge);
            targetLayer->fBindings.addToHead(forwardMerge);
            targetMatch = forwardMerge;
        }
        fLayers.addToTail(targetLayer);
    }

    if (!targetMatch) {
        targetMatch = targetLayer->addNewBinding(&fStorage, nullptr, key, step);
    } else {
        SkASSERT(targetLayer->fBindings.isInList(targetMatch));
    }

    return {targetLayer, targetMatch};
}

BindingList* DrawListLayer::findOrCreateBindingInLayer(Layer* layer,
                                                       BindingList* parent,
                                                       const RenderStep* step,
                                                       const LayerKey& key) {
    // If we're recording a new step in the layer, there better have been a draw that searched
    // backwards for the layer first!
    SkASSERT(layer);
    // If we have a parent step's BindingList to insert before, it must be in `layer`.
    SkASSERT(!parent || layer->fBindings.isInList(parent));

    BindingList* targetMatch = nullptr;

    // If we don't have a parent, search through all bindings of the layer as this is the first time
    // through the layer. If we do have a parent, search through the preceding bindings (exclusive).
    if (!parent || parent->fPrev) {
        targetMatch = layer->searchBinding(key, parent ? parent->fPrev : nullptr);
    } // else there are no preceding bindings so we know we have to add a new one

    if (!targetMatch) {
        targetMatch = layer->addNewBinding(&fStorage, parent, key, step);
    }
    return targetMatch;
}

// Layer has dual purpose here:
//  1) (Producer) If recording a depth only draw, the pointer is set to the *latest* layer inserted.
//  2) (Consumer) If recording a clipped draw, the pointer is the latest layer inserted into across
//     *all depth only draws* which affect this draw. Thus, it is the earliest possible layer that
//     the clipped draw could be inserted into, so it is used as the starting point for a *forward*
//     search.
std::pair<DrawParams*, Layer*> DrawListLayer::recordDraw(const Renderer* renderer,
                                                         const Transform& localToDevice,
                                                         const Geometry& geometry,
                                                         const Clip& clip,
                                                         DrawOrder ordering,
                                                         UniquePaintParamsID paintID,
                                                         SkEnumBitMask<DstUsage> dstUsage,
                                                         BarrierType barrierBeforeDraws,
                                                         PipelineDataGatherer* gatherer,
                                                         const StrokeStyle* stroke,
                                                         Layer* lastInsertion) {
    SkASSERT(localToDevice.valid());
    SkASSERT(!geometry.isEmpty() && !clip.drawBounds().isEmptyNegativeOrNaN());

    // `testMask` limits what we test against when searching backwards, which is based on the
    // Renderer's aggregate requirements so that the layer we find will be valid for all steps. This
    // is particularly important for stencil-based renderers, which consist of a non-shading
    // "producer" step, which writes into the stencil buffer, and shading "consumer" render steps
    // which test against the stencil mask and clear the buffer afterwards. This guarantees
    // atomicity within a single layer, where the last step finds a safe layer and all earlier steps
    // are explicitly inserted before that. This minimizes pipeline switches as rendering can
    // proceed through the steps in bulk.
    SkEnumBitMask<BoundsFlags> testMask;
    if (SkToBool(renderer->depthStencilFlags() & DepthStencilFlags::kStencil)) {
        testMask |= BoundsFlags::kStencil;
    }
    // Draws that blend must respect painter's order, and clipping depth-only draws cannot be
    // ordered in front of shading draws.
    const bool isDepthOnly = !paintID.isValid();
    const bool dependsOnDst = SkToBool(dstUsage & DstUsage::kDependsOnDst);
    if (dependsOnDst || isDepthOnly) {
        testMask |= BoundsFlags::kColor;
    }

    // In simple situations, we can allow overlaps within a BindingList and let GPU rasterization
    // resolve the rendering order automatically. This does not apply if barriers are required,
    // and it does not apply when the Renderer has multiple steps (must keep the sets of draws in
    // each step disjoint so there isn't interference).
    SkEnumBitMask<BoundsFlags> baseLayerMask = BoundsFlags::kNone;
    if (barrierBeforeDraws != BarrierType::kNone || renderer->numRenderSteps() > 1) {
        baseLayerMask |= BoundsFlags::kMustBeDisjoint;
    }

    // Currently, the draw params are created once per record draw call, and the pointer is passed
    // to each draw call. This is storage effecient but will still introduce some pointer chasing,
    // because the params will likely no longer be on the same cache line for successor render
    // steps. We should test whether it is faster for each step to hold a copy of the params except
    // in the case of clipped draws (which must share a copy because they are mutated later).
    DrawParams* drawParams = fStorage.make<DrawParams>(this->deduplicateTransform(localToDevice),
                                                       geometry,
                                                       clip,
                                                       ordering,
                                                       stroke,
                                                       barrierBeforeDraws);

    Layer* insertionLayer = nullptr;
    BindingList* lastStepBinding = nullptr;
    // If we're an easy draw, jump to the latestInsertion layer since we don't have to test
    if (testMask == BoundsFlags::kNone && baseLayerMask == BoundsFlags::kNone) {
        insertionLayer = lastInsertion ? lastInsertion : fLayers.head();
    }

    fRenderStepCount += renderer->numRenderSteps();
    for (int stepIndex = renderer->numRenderSteps() - 1; stepIndex >= 0; --stepIndex) {
        const RenderStep* const step = renderer->steps()[stepIndex];

        gatherer->markOffsetAndAlign(step->performsShading(), step->uniformAlignment());

        GraphicsPipelineCache::Index pipelineIndex = fPipelineCache.insert(
                {step->renderStepID(),
                 step->performsShading() ? paintID : UniquePaintParamsID::Invalid()});

        step->writeUniformsAndTextures(*drawParams, gatherer);

        auto [combinedUniforms, combinedTextures] =
                gatherer->endCombinedData(step->performsShading());

        UniformDataCache::Index uniformIndex = combinedUniforms
                                                       ? fUniformDataCache.insert(combinedUniforms)
                                                       : UniformDataCache::kInvalidIndex;
        TextureDataCache::Index textureBindingIndex =
                combinedTextures ? fTextureDataCache.insert(combinedTextures)
                                 : TextureDataCache::kInvalidIndex;


        // `layerMask` defines what this draw will block in new draws from going backwards. This is
        // per-step so that stencil-only draws can be grouped between shading and clip draws.
        SkEnumBitMask<BoundsFlags> layerMask = baseLayerMask;
        if (step->depthStencilFlags() & DepthStencilFlags::kStencil) {
            layerMask |= BoundsFlags::kStencil;
        }
        if (step->performsShading() && paintID.isValid()) {
            // NOTE: This is not dependsOnDst because it represents what is written by the draw,
            // not what might be read for blending the draw.
            layerMask |= BoundsFlags::kColor;
        }

        LayerKey key{pipelineIndex,
                     textureBindingIndex,
                     fStorageBufferSupport ? UniformDataCache::kInvalidIndex : uniformIndex,
                     layerMask};

        if (!insertionLayer) {
            // Since we don't have a layer yet, search from the most recent layer back.
            CompressedPaintersOrder stop = lastInsertion ? lastInsertion->fOrder
                                                         : DrawOrder::kNoIntersection;
            std::tie(insertionLayer, lastStepBinding) = this->searchBackwards(step,
                                                                              key,
                                                                              testMask,
                                                                              drawParams,
                                                                              stop);
        } else {
            // Put the earlier steps in the same layer (valid because we used BoundsFlags for the
            // whole Renderer).
            lastStepBinding = this->findOrCreateBindingInLayer(insertionLayer,
                                                               lastStepBinding,
                                                               step,
                                                               key);
        }

        SkASSERT(lastStepBinding);
        lastStepBinding->addDraw(fStorage.make<Draw>(drawParams, uniformIndex),
                                     /*backToFront=*/dependsOnDst);

        gatherer->rewindForRenderStep();
    }

    fDrawCount++;
    fPassBounds.join(clip.drawBounds());
    fRequiresMSAA |= renderer->requiresMSAA();
    fDepthStencilFlags |= renderer->depthStencilFlags();
    if (dstUsage & DstUsage::kDstReadRequired) {
        // For paints that read from the dst, update the bounds. It may later be determined that the
        // DstReadStrategy does not require them, but they are inexpensive to track.
        fDstReadBounds.join(clip.drawBounds());
    }

#if defined(SK_DEBUG)
    if (geometry.isCoverageMaskShape()) {
        fCoverageMaskShapeDrawCount++;
    }
#endif

    return {drawParams, insertionLayer};
}

std::unique_ptr<DrawPass> DrawListLayer::snapDrawPass(Recorder* recorder,
                                                      sk_sp<TextureProxy> target,
                                                      const SkImageInfo& targetInfo,
                                                      const DstReadStrategy dstReadStrategy) {
    TRACE_EVENT1_ALWAYS("skia.gpu", TRACE_FUNC, "draw count", fDrawCount);

    std::unique_ptr<DrawPass> drawPass(new DrawPass(target,
                                                    {fLoadOp, StoreOp::kStore},
                                                    fClearColor,
                                                    recorder->priv().refStorageBufferManager()));
    DrawBufferManager* bufferMgr = recorder->priv().drawBufferManager();
    DrawWriter drawWriter(&drawPass->fCommandList, bufferMgr);

    GraphicsPipelineCache::Index lastPipeline = GraphicsPipelineCache::kInvalidIndex;
    const SkIRect targetBounds = SkIRect::MakeSize(targetInfo.dimensions());
    SkIRect lastScissor = targetBounds;

    SkASSERT(drawPass->fTarget->isFullyLazy() ||
             SkIRect::MakeSize(drawPass->fTarget->dimensions()).contains(lastScissor));
    drawPass->fCommandList.setScissor(lastScissor);

    UniformTracker uniformTracker(fStorageBufferSupport);

    const bool rebindTexturesOnPipelineChange = dstReadStrategy == DstReadStrategy::kTextureCopy;
    CompressedPaintersOrder priorDrawPaintOrder{};

    // Accumulate rough pixel area touched by each pipeline
    drawPass->fPipelineDrawAreas.push_back_n(fPipelineCache.count(), 0.f);

    TextureTracker textureBindingTracker(&fTextureDataCache);

    auto recordDraw = [&](const LayerKey& key,
                          const UniformDataCache::Index uniformIndex,
                          const RenderStep* renderStep,
                          const DrawParams& drawParams,
                          bool bindingsAreInvariant) -> bool {
        SkASSERT(renderStep);

        bool pipelineChange = false;
        bool textureBindingsChange = false;

        if (!bindingsAreInvariant) {
            pipelineChange = key.fPipelineIndex != lastPipeline;

            textureBindingsChange =
                    textureBindingTracker.setCurrentTextureBindings(key.fTextureIndex) ||
                    (rebindTexturesOnPipelineChange && pipelineChange &&
                     key.fTextureIndex != TextureDataCache::kInvalidIndex);
        }

        bool uniformBindingChange =
                uniformTracker.writeUniforms(fUniformDataCache, bufferMgr, uniformIndex);

        drawPass->fPipelineDrawAreas[key.fPipelineIndex] += drawParams.drawBounds().area();

        std::optional<SkIRect> newScissor =
                renderStep->getScissor(drawParams, lastScissor, targetBounds);

        if (pipelineChange) {
            drawWriter.newPipelineState(renderStep->primitiveType(),
                                        renderStep->staticDataStride(),
                                        renderStep->appendDataStride(),
                                        renderStep->getRenderStateFlags(),
                                        drawParams.barrierBeforeDraws());
        } else if (uniformBindingChange || textureBindingsChange || newScissor.has_value()) {
            drawWriter.newDynamicState();
        } else if (drawParams.barrierBeforeDraws() != BarrierType::kNone) {
            drawWriter.flush();
        }

        if (pipelineChange) {
            drawPass->fCommandList.bindGraphicsPipeline(key.fPipelineIndex);
            lastPipeline = key.fPipelineIndex;
        }
        if (uniformBindingChange) {
            uniformTracker.bindUniforms(UniformSlot::kCombinedUniforms, &drawPass->fCommandList);
        }
        if (textureBindingsChange) {
            textureBindingTracker.bindTextures(&drawPass->fCommandList);
        }
        if (newScissor.has_value()) {
            drawPass->fCommandList.setScissor(*newScissor);
            lastScissor = *newScissor;
        }

        uint32_t uniformSsboIndex = fStorageBufferSupport ? uniformTracker.ssboIndex() : 0;
        renderStep->writeVertices(&drawWriter, drawParams, uniformSsboIndex);

        if (bufferMgr->hasMappingFailed()) {
            SKIA_LOG_W("Failed to write necessary vertex/instance data for DrawPass, dropping!");
            this->reset(LoadOp::kLoad);
            return false;
        }

        priorDrawPaintOrder = drawParams.order().paintOrder();
        return true;
    };

    for (Layer* layer : fLayers) {
        for (const BindingList* list : layer->fBindings) {
            SkASSERT(!list->fDraws.isEmpty());
            const Draw* current = list->fDraws.head();

            if (!recordDraw(list->fKey,
                            current->fUniformIndex,
                            list->fStep,
                            *current->fDrawParams,
                            false)) {
                return nullptr;
            }
            current = current->fNext;

            while (current) {
                if (!recordDraw(list->fKey,
                                current->fUniformIndex,
                                list->fStep,
                                *current->fDrawParams,
                                true)) {
                    return nullptr;
                }
                current = current->fNext;
            }
        }
    }

    drawWriter.flush();

    drawPass->fBounds = fPassBounds.roundOut().asSkIRect();
    drawPass->fPipelineDescs = fPipelineCache.detach();
    drawPass->fSampledTextures = fTextureDataCache.detachTextures();

    TRACE_EVENT_INSTANT2_ALWAYS("skia.gpu",
                                "DrawPass Stats",
                                TRACE_EVENT_SCOPE_THREAD,
                                "# commands", drawPass->fCommandList.count(),
                                "# textures", drawPass->fSampledTextures.size());

    this->reset(LoadOp::kLoad);

    return drawPass;
}

}  // namespace skgpu::graphite
