/*
 * 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 "GrMesh.h"
#include "GrNonAtomicRef.h"
#include "SkPath.h"
#include "SkPathPriv.h"
#include "SkRect.h"
#include "SkRefCnt.h"
#include "GrTessellator.h"
#include "ccpr/GrCCCoverageProcessor.h"
#include "ccpr/GrCCGeometry.h"
#include "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 GrCCPathParser : public GrNonAtomicRef<GrCCPathParser> {
public:
    // Indicates whether a path should enforce a scissor clip when rendering its mask. (Specified
    // as an int because these values get used directly as indices into arrays.)
    enum class ScissorMode : int { kNonScissored = 0, kScissored = 1 };
    static constexpr int kNumScissorModes = 2;

    struct PathStats {
        int fMaxPointsPerPath = 0;
        int fNumTotalSkPoints = 0;
        int fNumTotalSkVerbs = 0;
        int fNumTotalConicWeights = 0;

        void statPath(const SkPath&);
    };

    GrCCPathParser(int numPaths, const PathStats&);

    ~GrCCPathParser() {
        // Enforce the contract that the client always calls saveParsedPath or discardParsedPath.
        SkASSERT(!fParsingPath);
    }

    using CoverageCountBatchID = int;

    // Parses an SkPath into a temporary staging area. The path will not be included in the current
    // batch until there is a matching call to saveParsedPath. The user must complement this with a
    // following call to either saveParsedPath or discardParsedPath.
    //
    // Returns two tight bounding boxes: device space and "45 degree" (| 1 -1 | * devCoords) space.
    //                                                                 | 1  1 |
    void parsePath(const SkMatrix&, const SkPath&, SkRect* devBounds, SkRect* devBounds45);

    // Parses a device-space SkPath into a temporary staging area. The path will not be included in
    // the current batch until there is a matching call to saveParsedPath. The user must complement
    // this with a following call to either saveParsedPath or discardParsedPath.
    void parseDeviceSpacePath(const SkPath&);

    // Commits the currently-parsed path from staging to the current batch, and specifies whether
    // the mask should be rendered with a scissor in effect. Accepts an optional post-device-space
    // translate for placement in an atlas.
    void saveParsedPath(ScissorMode, const SkIRect& clippedDevIBounds, int16_t atlasOffsetX,
                        int16_t atlasOffsetY);
    void discardParsedPath();

    // Compiles the outstanding saved paths into a batch, and returns an ID that can be used to draw
    // their coverage counts in the future.
    CoverageCountBatchID closeCurrentBatch();

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

    // Called after finalize. Draws the given batch of parsed paths.
    void drawCoverageCount(GrOpFlushState*, CoverageCountBatchID, const SkIRect& drawBounds) const;

private:
    using PrimitiveTallies = GrCCGeometry::PrimitiveTallies;

    // Every kBeginPath verb has a corresponding PathInfo entry.
    class PathInfo {
    public:
        PathInfo(ScissorMode scissorMode, int16_t offsetX, int16_t offsetY)
                : fScissorMode(scissorMode), fAtlasOffsetX(offsetX), fAtlasOffsetY(offsetY) {}

        ScissorMode scissorMode() const { return fScissorMode; }
        int16_t atlasOffsetX() const { return fAtlasOffsetX; }
        int16_t atlasOffsetY() const { return fAtlasOffsetY; }

        // 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 GrTessellator::WindingVertex* fanTessellation() const {
            SkASSERT(this->hasFanTessellation());
            return fFanTessellation.get();
        }

        void adoptFanTessellation(const GrTessellator::WindingVertex* vertices, int count) {
            SkASSERT(count >= 0);
            fFanTessellation.reset(vertices);
            fFanTessellationCount = count;
        }

    private:
        ScissorMode fScissorMode;
        int16_t fAtlasOffsetX, fAtlasOffsetY;
        int fFanTessellationCount = -1;
        std::unique_ptr<const GrTessellator::WindingVertex[]> fFanTessellation;
    };

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

    // Defines a sub-batch from CoverageCountBatch 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 parsePath(const SkPath&, const SkPoint* deviceSpacePts);
    void endContourIfNeeded(bool insideContour);

    void drawPrimitives(GrOpFlushState*, const GrPipeline&, CoverageCountBatchID,
                        GrCCCoverageProcessor::PrimitiveType, int PrimitiveTallies::*instanceType,
                        const SkIRect& drawBounds) const;

    // Staging area for the path being parsed.
    SkDEBUGCODE(int fParsingPath = false);
    const SkAutoSTArray<32, SkPoint> fLocalDevPtsBuffer;
    int fCurrPathPointsIdx;
    int fCurrPathVerbsIdx;
    PrimitiveTallies fCurrPathPrimitiveCounts;

    GrCCGeometry fGeometry;
    SkSTArray<32, PathInfo, true> fPathsInfo;
    SkSTArray<32, CoverageCountBatch, true> fCoverageCountBatches;
    SkSTArray<32, ScissorSubBatch, true> fScissorSubBatches;
    PrimitiveTallies fTotalPrimitiveCounts[kNumScissorModes];
    int fMaxMeshesPerDraw = 0;

    sk_sp<GrBuffer> fInstanceBuffer;
    PrimitiveTallies fBaseInstances[kNumScissorModes];
    mutable SkSTArray<32, GrMesh> fMeshesScratchBuffer;
    mutable SkSTArray<32, GrPipeline::DynamicState> fDynamicStatesScratchBuffer;
};

inline void GrCCPathParser::PathStats::statPath(const SkPath& path) {
    fMaxPointsPerPath = SkTMax(fMaxPointsPerPath, path.countPoints());
    fNumTotalSkPoints += path.countPoints();
    fNumTotalSkVerbs += path.countVerbs();
    fNumTotalConicWeights += SkPathPriv::ConicWeightCnt(path);
}

#endif
