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

#ifndef skgpu_graphite_DrawOrder_DEFINED
#define skgpu_graphite_DrawOrder_DEFINED

#include "include/core/SkTypes.h"

namespace skgpu::graphite {

// Helper to encapsulate an unsigned number and enforce that it can only be used to create a
// monotonic sequence. The template argument 'Sequence' is used to define different sequences
// enforced by the compiler. For simplicity, and current needs within Graphite, it's assumed the
// entire sequence can be indexed by uint16_t.
template<typename Sequence>
class MonotonicValue {
public:
    static constexpr MonotonicValue First() { return 0;      }
    static constexpr MonotonicValue Last()  { return 0xffff; }

    MonotonicValue() = default;
    MonotonicValue(const MonotonicValue& o) = default;

    MonotonicValue& operator=(const MonotonicValue& o) = default;

    bool operator< (MonotonicValue o) const { return fIndex <  o.fIndex; }
    bool operator<=(MonotonicValue o) const { return fIndex <= o.fIndex; }

    bool operator> (MonotonicValue o) const { return fIndex >  o.fIndex; }
    bool operator>=(MonotonicValue o) const { return fIndex >= o.fIndex; }

    bool operator==(MonotonicValue o) const { return fIndex == o.fIndex; }
    bool operator!=(MonotonicValue o) const { return fIndex != o.fIndex; }

    uint16_t bits() const { return fIndex; }

    // Get the next value in the sequence after this one
    MonotonicValue next() const { return fIndex + 1; }

private:
    friend class DrawOrder; // For depth/stencil co-opting

    constexpr MonotonicValue(uint16_t index) : fIndex(index) {}

    uint16_t fIndex;
};

/**
 * CompressedPaintersOrder is an ordinal number that allows draw commands to be re-ordered so long
 * as when they are executed, the read/writes to the color|depth attachments respect the original
 * painter's order. Logical draws with the same CompressedPaintersOrder can be assumed to be
 * executed in any order, however that may have been determined (e.g. BoundsManager or relying on
 * a depth test during rasterization).
 */
struct CompressedPaintersOrderSequence {};
using CompressedPaintersOrder = MonotonicValue<CompressedPaintersOrderSequence>;

/**
 * Each DisjointStencilIndex specifies an implicit set of non-overlapping draws. Assuming that two
 * draws have the same CompressedPaintersOrder and the same DisjointStencilIndex, their substeps
 * for multi-pass rendering (stencil-then-cover, etc.) can be intermingled with each other and
 * produce the same results as if each draw's substeps were executed in order before moving on to
 * the next draw's.
 *
 * Ordering within a set can be entirely arbitrary (i.e. all stencil steps can go before all cover
 * steps). Ordering between sets is also arbitrary since all draws share the same
 * CompressedPaintersOrder, so long as one set is entirely drawn before the next.
 *
 * Two draws that have different CompressedPaintersOrders but the same DisjointStencilIndex are
 * unrelated, they may or may not overlap. The painters order scopes the disjoint sets.
 */
struct DisjointStencilIndexSequence {};
using DisjointStencilIndex = MonotonicValue<DisjointStencilIndexSequence>;

/**
 * Every draw has an associated depth value. The value is constant across the entire draw and is
 * not related to any varying Z coordinate induced by a 4x4 transform. The painter's depth is stored
 * in the depth attachment and the GREATER depth test is used to reject or accept pixels/samples
 * relative to what has already been rendered into the depth attachment. This allows draws that do
 * not depend on the previous color to be radically re-ordered relative to their original painter's
 * order while producing correct results.
 */
struct PaintersDepthSequence {};
using PaintersDepth = MonotonicValue<PaintersDepthSequence>;

/**
 * DrawOrder aggregates the three separate sequences that Graphite uses to re-order draws and their
 * substeps as much as possible while preserving the painter's order semantics of the Skia API.
 *
 * To build the full DrawOrder for a draw, start with its assigned PaintersDepth (i.e. the original
 * painter's order of the draw call). From there, the DrawOrder can be updated to reflect
 * dependencies on previous draws, either from depth-only clip draws or because the draw is
 * transparent and must blend with the previous color values. Lastly, once the
 * CompressedPaintersOrder is finalized, the DrawOrder can be updated to reflect whether or not
 * the draw will involve the stencil buffer--and if so, specify the disjoint stencil set it
 * belongs to.
 *
 * The original and effective order that draws are executed in is defined by the PaintersDepth.
 * However, the actual execution order is defined by first the CompressedPaintersOrder and then
 * the DisjointStencilIndex. This means that draws with much higher depths can be executed earlier
 * if painter's order compression allows for it.
 */
class DrawOrder {
public:
    // The first PaintersDepth is reserved for clearing the depth attachment; any draw using this
    // depth will always fail the depth test.
    inline static constexpr PaintersDepth kClearDepth = PaintersDepth::First();
    // The first CompressedPaintersOrder is reserved to indicate there is no previous draw that
    // must come before a draw.
    inline static constexpr
            CompressedPaintersOrder kNoIntersection = CompressedPaintersOrder::First();
    // The last DisjointStencilIndex is reserved to indicate an unassigned stencil set.
    // This automatically orders stencil-less B2F draws after draws that use the stencil and after
    // draws that are sorted F2B (packed into stencil index with reverseDepthAsStencil()).
    inline static constexpr DisjointStencilIndex kUnassigned = DisjointStencilIndex::Last();

    explicit DrawOrder(PaintersDepth originalOrder)
            : fPaintOrder(kNoIntersection)
            , fStencilIndex(kUnassigned)
            , fDepth(originalOrder) {}

    DrawOrder(PaintersDepth originalOrder, CompressedPaintersOrder compressedOrder)
            : fPaintOrder(compressedOrder)
            , fStencilIndex(kUnassigned)
            , fDepth(originalOrder) {}

    CompressedPaintersOrder paintOrder()   const { return fPaintOrder;   }
    DisjointStencilIndex    stencilIndex() const { return fStencilIndex; }
    PaintersDepth           depth()        const { return fDepth;        }

    // While the PaintersDepth is a monotonically increasing value, the depth buffer prefers to
    // use LESS and LEQUAL comparisons starting with a clear value of 1.f, so we normalize and flip
    // the floating point value to count down from 1.0.
    float depthAsFloat() const {
        return 1.f - fDepth.bits() / (float) PaintersDepth::Last().bits();
    }

    // Coopt the stencil index to encode the draw's actual painter's depth in decreasing order,
    // for use enforcing F2B order (since the compressed painter's order handles B2F).
    DrawOrder& reverseDepthAsStencil() {
        SkASSERT(fStencilIndex == kUnassigned); // can't have a real stencil index
        fStencilIndex = DisjointStencilIndex::Last().bits() - fDepth.bits();
        return *this;
    }

    DrawOrder& dependsOnPaintersOrder(CompressedPaintersOrder prevDraw) {
        // A draw must be ordered after all previous draws that it depends on
        CompressedPaintersOrder next = prevDraw.next();
        if (fPaintOrder < next) {
            fPaintOrder = next;
        }
        return *this;
    }

    DrawOrder& dependsOnStencil(DisjointStencilIndex disjointSet) {
        // Stencil usage should only be set once
        SkASSERT(fStencilIndex == kUnassigned);
        fStencilIndex = disjointSet;
        return *this;
    }

private:
    CompressedPaintersOrder fPaintOrder;
    DisjointStencilIndex    fStencilIndex;
    PaintersDepth           fDepth;
};

} // namespace skgpu::graphite

#endif // skgpu_graphite_DrawOrder_DEFINED
