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

#ifndef GrCCStroker_DEFINED
#define GrCCStroker_DEFINED

#include "GrAllocator.h"
#include "GrMesh.h"
#include "SkNx.h"
#include "ccpr/GrCCStrokeGeometry.h"

class GrBuffer;
class GrCCCoverageProcessor;
class GrOnFlushResourceProvider;
class GrOpFlushState;
class GrPipeline;
class GrPrimitiveProcessor;
class SkMatrix;
class SkPath;
class SkStrokeRec;

/**
 * This class parses stroked SkPaths into a GPU instance buffer, then issues calls to draw their
 * coverage counts.
 */
class GrCCStroker {
public:
    GrCCStroker(int numPaths, int numSkPoints, int numSkVerbs)
            : fGeometry(numSkPoints, numSkVerbs), fPathInfos(numPaths) {}

    // Parses a device-space SkPath into the current batch, using the SkPath's original verbs with
    // 'deviceSpacePts', and the SkStrokeRec's original settings with 'strokeDevWidth'. Accepts an
    // optional post-device-space translate for placement in an atlas.
    //
    // Strokes intended as hairlines must have a strokeDevWidth of 1. Non-hairline strokes can only
    // be drawn with rigid body transforms; affine transformation of the stroke lines themselves is
    // not yet supported.
    void parseDeviceSpaceStroke(const SkPath&, const SkPoint* deviceSpacePts, const SkStrokeRec&,
                                float strokeDevWidth, 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 strokes in the future.
    BatchID closeCurrentBatch();

    // Builds an internal GPU buffer and prepares for calls to drawStrokes(). 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 strokes.
    void drawStrokes(GrOpFlushState*, BatchID, const SkIRect& drawBounds) const;

private:
    static constexpr int kNumScissorModes = 2;
    static constexpr BatchID kEmptyBatchID = -1;
    using Verb = GrCCStrokeGeometry::Verb;
    using InstanceTallies = GrCCStrokeGeometry::InstanceTallies;

    // Every kBeginPath verb has a corresponding PathInfo entry.
    struct PathInfo {
        SkIVector fDevToAtlasOffset;
        float fStrokeRadius;
        GrScissorTest fScissorTest;
    };

    // Defines a sub-batch of stroke instances that have a scissor test and the same scissor rect.
    // Start indices are deduced by looking at the previous ScissorSubBatch.
    struct ScissorSubBatch {
        ScissorSubBatch(GrTAllocator<InstanceTallies>* alloc, const InstanceTallies& startIndices,
                        const SkIRect& scissor)
                : fEndInstances(&alloc->emplace_back(startIndices)), fScissor(scissor) {}
        InstanceTallies* fEndInstances;
        SkIRect fScissor;
    };

    // Defines a batch of stroke instances that can be drawn with drawStrokes(). Start indices are
    // deduced by looking at the previous Batch in the list.
    struct Batch {
        Batch(GrTAllocator<InstanceTallies>* alloc, const InstanceTallies& startNonScissorIndices,
              int startScissorSubBatch)
                : fNonScissorEndInstances(&alloc->emplace_back(startNonScissorIndices))
                , fEndScissorSubBatch(startScissorSubBatch) {}
        InstanceTallies* fNonScissorEndInstances;
        int fEndScissorSubBatch;
    };

    class InstanceBufferBuilder;

    void appendStrokeMeshesToBuffers(int numSegmentsLog2, const Batch&,
                                     const InstanceTallies* startIndices[2],
                                     int startScissorSubBatch, const SkIRect& drawBounds) const;
    void flushBufferedMeshesAsStrokes(const GrPrimitiveProcessor&, GrOpFlushState*, const
                                      GrPipeline&, const SkIRect& drawBounds) const;

    template<int GrCCStrokeGeometry::InstanceTallies::* InstanceType>
    void drawConnectingGeometry(GrOpFlushState*, const GrPipeline&,
                                const GrCCCoverageProcessor&, const Batch&,
                                const InstanceTallies* startIndices[2], int startScissorSubBatch,
                                const SkIRect& drawBounds) const;

    GrCCStrokeGeometry fGeometry;
    SkSTArray<32, PathInfo> fPathInfos;
    SkSTArray<32, Batch> fBatches;
    SkSTArray<32, ScissorSubBatch> fScissorSubBatches;
    int fMaxNumScissorSubBatches = 0;
    bool fHasOpenBatch = false;

    const InstanceTallies fZeroTallies = InstanceTallies();
    GrSTAllocator<128, InstanceTallies> fTalliesAllocator;
    const InstanceTallies* fInstanceCounts[kNumScissorModes] = {&fZeroTallies, &fZeroTallies};

    sk_sp<GrBuffer> fInstanceBuffer;
    // The indices stored in batches are relative to these base instances.
    InstanceTallies fBaseInstances[kNumScissorModes];

    mutable SkSTArray<32, GrMesh> fMeshesBuffer;
    mutable SkSTArray<32, SkIRect> fScissorsBuffer;
};

#endif
