/*
 * 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 tessellate_PathTessellator_DEFINED
#define tessellate_PathTessellator_DEFINED

#include "src/gpu/tessellate/Tessellation.h"

class SkPath;

#if SK_GPU_V1
#include "src/gpu/GrGpuBuffer.h"
#include "src/gpu/GrVertexChunkArray.h"
#include "src/gpu/tessellate/PatchWriter.h"

class GrMeshDrawTarget;
class GrOpFlushState;
#endif

namespace skgpu {

class PatchWriter;

// Prepares GPU data for, and then draws a path's tessellated geometry. Depending on the subclass,
// the caller may or may not be required to draw the path's inner fan separately.
class PathTessellator {
public:
    // This is the maximum number of segments contained in our vertex and index buffers for
    // fixed-count rendering. If rendering in fixed-count mode and a curve requires more segments,
    // it must be chopped.
    constexpr static int kMaxFixedResolveLevel = 5;

    struct PathDrawList {
        PathDrawList(const SkMatrix& pathMatrix,
                     const SkPath& path,
                     const SkPMColor4f& color,
                     PathDrawList* next = nullptr)
                : fPathMatrix(pathMatrix), fPath(path), fColor(color), fNext(next) {}

        SkMatrix fPathMatrix;
        SkPath fPath;
        SkPMColor4f fColor;
        PathDrawList* fNext;

        struct Iter {
            void operator++() { fHead = fHead->fNext; }
            bool operator!=(const Iter& b) const { return fHead != b.fHead; }
            std::tuple<const SkMatrix&, const SkPath&, const SkPMColor4f&> operator*() const {
                return {fHead->fPathMatrix, fHead->fPath, fHead->fColor};
            }
            const PathDrawList* fHead;
        };
        Iter begin() const { return {this}; }
        Iter end() const { return {nullptr}; }
    };

    virtual ~PathTessellator() {}

    PatchAttribs patchAttribs() const { return fAttribs; }

    // Gives an approximate initial buffer size for this class to write patches into. Ideally the
    // whole path will fit into this initial buffer, but if it requires a lot of chopping, the
    // PatchWriter will allocate more buffer(s).
    virtual int patchPreallocCount(int totalCombinedPathVerbCnt) const = 0;

    // Writes out patches to the given PatchWriter, chopping as necessary so the curves all fit in
    // maxTessellationSegments or fewer.
    //
    // Each path's fPathMatrix in the list is applied on the CPU while the geometry is being written
    // out. This is a tool for batching, and is applied in addition to the shader's on-GPU matrix.
    virtual void writePatches(PatchWriter&,
                              int maxTessellationSegments,
                              const SkMatrix& shaderMatrix,
                              const PathDrawList&) = 0;

#if SK_GPU_V1
    // Initializes the internal vertex and index buffers required for drawFixedCount().
    virtual void prepareFixedCountBuffers(GrMeshDrawTarget*) = 0;

    // Called before draw(). Prepares GPU buffers containing the geometry to tessellate.
    void prepare(GrMeshDrawTarget* target,
                 int maxTessellationSegments,
                 const SkMatrix& shaderMatrix,
                 const PathDrawList& pathDrawList,
                 int totalCombinedPathVerbCnt,
                 bool willUseTessellationShaders) {
        if (int patchPreallocCount = this->patchPreallocCount(totalCombinedPathVerbCnt)) {
            PatchWriter patchWriter(target, this, patchPreallocCount);
            this->writePatches(patchWriter, maxTessellationSegments, shaderMatrix, pathDrawList);
        }
        if (!willUseTessellationShaders) {
            this->prepareFixedCountBuffers(target);
        }
    }

    // Issues hardware tessellation draw calls over the patches. The caller is responsible for
    // binding its desired pipeline ahead of time.
    virtual void drawTessellated(GrOpFlushState*) const = 0;

    // Issues fixed-count instanced draw calls over the patches. The caller is responsible for
    // binding its desired pipeline ahead of time.
    virtual void drawFixedCount(GrOpFlushState*) const = 0;

    void draw(GrOpFlushState* flushState, bool willUseTessellationShaders) {
        if (willUseTessellationShaders) {
            this->drawTessellated(flushState);
        } else {
            this->drawFixedCount(flushState);
        }
    }
#endif

    // Returns an upper bound on the number of combined edges there might be from all inner fans in
    // a PathDrawList.
    static int MaxCombinedFanEdgesInPathDrawList(int totalCombinedPathVerbCnt) {
        // Path fans might have an extra edge from an implicit kClose at the end, but they also
        // always begin with kMove. So the max possible number of edges in a single path is equal to
        // the number of verbs. Therefore, the max number of combined fan edges in a PathDrawList is
        // the number of combined path verbs in that PathDrawList.
        return totalCombinedPathVerbCnt;
    }

protected:
    // How many triangles are in a curve with 2^resolveLevel line segments?
    constexpr static int NumCurveTrianglesAtResolveLevel(int resolveLevel) {
        // resolveLevel=0 -> 0 line segments -> 0 triangles
        // resolveLevel=1 -> 2 line segments -> 1 triangle
        // resolveLevel=2 -> 4 line segments -> 3 triangles
        // resolveLevel=3 -> 8 line segments -> 7 triangles
        // ...
        return (1 << resolveLevel) - 1;
    }

    PathTessellator(bool infinitySupport, PatchAttribs attribs) : fAttribs(attribs) {
        if (!infinitySupport) {
            fAttribs |= PatchAttribs::kExplicitCurveType;
        }
    }

    PatchAttribs fAttribs;

    // Calculated during prepare(). If using fixed count, this is the resolveLevel to use on our
    // instanced draws. 2^resolveLevel == numSegments.
    int fFixedResolveLevel = 0;

#if SK_GPU_V1
    friend class PatchWriter;  // To access fVertexChunkArray.

    GrVertexChunkArray fVertexChunkArray;

    // If using fixed-count rendering, these are the vertex and index buffers.
    sk_sp<const GrGpuBuffer> fFixedVertexBuffer;
    sk_sp<const GrGpuBuffer> fFixedIndexBuffer;
#endif
};

}  // namespace skgpu

#endif  // tessellate_PathTessellator_DEFINED
