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

#ifndef GrCCPathParser_DEFINED
#define GrCCPathParser_DEFINED

#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "src/core/SkPathPriv.h"
#include "src/gpu/GrTriangulator.h"
#include "src/gpu/ccpr/GrAutoMapVertexBuffer.h"
#include "src/gpu/ccpr/GrCCCoverageProcessor.h"
#include "src/gpu/ccpr/GrCCFillGeometry.h"
#include "src/gpu/ops/GrDrawOp.h"

class GrOnFlushResourceProvider;
class SkMatrix;
class SkPath;

/**
 * This class parses SkPaths into CCPR primitives in GPU buffers, then issues calls to draw their
 * coverage counts.
 */
class GrCCFiller {
public:
    enum class Algorithm : bool {
        kCoverageCount,
        kStencilWindingCount
    };

    GrCCFiller(Algorithm, int numPaths, int numSkPoints, int numSkVerbs, int numConicWeights);

    // Parses a device-space SkPath into the current batch, using the SkPath's original verbs and
    // 'deviceSpacePts'. Accepts an optional post-device-space translate for placement in an atlas.
    void parseDeviceSpaceFill(const SkPath&, const SkPoint* deviceSpacePts, GrScissorTest,
                              const SkIRect& clippedDevIBounds, const SkIVector& devToAtlasOffset);

    using BatchID = int;

    // Compiles the outstanding parsed paths into a batch, and returns an ID that can be used to
    // draw their fills in the future.
    BatchID closeCurrentBatch();

    // Builds internal GPU buffers and prepares for calls to drawFills(). Caller must close the
    // current batch before calling this method, and cannot parse new paths afer.
    bool prepareToDraw(GrOnFlushResourceProvider*);

    // Called after prepareToDraw(). Draws the given batch of path fills.
    void drawFills(GrOpFlushState*, GrCCCoverageProcessor*, const GrPipeline&, BatchID,
                   const SkIRect& drawBounds,
                   const GrUserStencilSettings* = &GrUserStencilSettings::kUnused) const;

private:
    static constexpr int kNumScissorModes = 2;
    using PrimitiveTallies = GrCCFillGeometry::PrimitiveTallies;

    // Every kBeginPath verb has a corresponding PathInfo entry.
    class PathInfo {
    public:
        PathInfo(GrScissorTest scissorTest, const SkIVector& devToAtlasOffset)
                : fScissorTest(scissorTest), fDevToAtlasOffset(devToAtlasOffset) {}

        GrScissorTest scissorTest() const { return fScissorTest; }
        const SkIVector& devToAtlasOffset() const { return fDevToAtlasOffset; }

        // An empty tessellation fan is also valid; we use negative count to denote not tessellated.
        bool hasFanTessellation() const { return fFanTessellationCount >= 0; }
        int fanTessellationCount() const {
            SkASSERT(this->hasFanTessellation());
            return fFanTessellationCount;
        }
        const GrTriangulator::WindingVertex* fanTessellation() const {
            SkASSERT(this->hasFanTessellation());
            return fFanTessellation.get();
        }
        void tessellateFan(
                Algorithm, const SkPath& originalPath, const GrCCFillGeometry&, int verbsIdx,
                int ptsIdx, const SkIRect& clippedDevIBounds, PrimitiveTallies* newTriangleCounts);

    private:
        GrScissorTest fScissorTest;
        SkIVector fDevToAtlasOffset;  // Translation from device space to location in atlas.
        int fFanTessellationCount = -1;
        std::unique_ptr<const GrTriangulator::WindingVertex[]> fFanTessellation;
    };

    // Defines a batch of CCPR primitives. Start indices are deduced by looking at the previous
    // Batch in the list.
    struct Batch {
        PrimitiveTallies fEndNonScissorIndices;
        int fEndScissorSubBatchIdx;
        PrimitiveTallies fTotalPrimitiveCounts;
    };

    // Defines a sub-batch that will be drawn with the given scissor rect. Start indices are deduced
    // by looking at the previous ScissorSubBatch in the list.
    struct ScissorSubBatch {
        PrimitiveTallies fEndPrimitiveIndices;
        SkIRect fScissor;
    };

    void emitTessellatedFan(
            const GrTriangulator::WindingVertex*, int numVertices, const Sk2f& devToAtlasOffset,
            GrCCCoverageProcessor::TriPointInstance::Ordering,
            GrCCCoverageProcessor::TriPointInstance*, GrCCCoverageProcessor::QuadPointInstance*,
            GrCCFillGeometry::PrimitiveTallies*);
    void drawPrimitives(GrOpFlushState*, const GrCCCoverageProcessor&, const GrPipeline&,
                        const GrUserStencilSettings*, BatchID,
                        int PrimitiveTallies::*instanceType, const SkIRect& drawBounds) const;

    const Algorithm fAlgorithm;
    GrCCFillGeometry fGeometry;
    SkSTArray<32, PathInfo, true> fPathInfos;
    SkSTArray<32, Batch, true> fBatches;
    SkSTArray<32, ScissorSubBatch, true> fScissorSubBatches;
    PrimitiveTallies fTotalPrimitiveCounts[kNumScissorModes];
    int fMaxMeshesPerDraw = 0;

    GrAutoMapVertexBuffer fInstanceBuffer;
    PrimitiveTallies fBaseInstances[kNumScissorModes];
};

#endif
