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

#include "GrAllocator.h"
#include "GrOnFlushResourceProvider.h"
#include "GrPathRenderer.h"
#include "SkTInternalLList.h"
#include "ccpr/GrCCPRAtlas.h"
#include "ccpr/GrCCPRCoverageOp.h"
#include "ops/GrDrawOp.h"
#include <map>

/**
 * This is a path renderer that draws antialiased paths by counting coverage in an offscreen
 * buffer. (See GrCCPRCoverageProcessor, GrCCPRPathProcessor)
 *
 * It also serves as the per-render-target tracker for pending path draws, and at the start of
 * flush, it compiles GPU buffers and renders a "coverage count atlas" for the upcoming paths.
 */
class GrCoverageCountingPathRenderer
    : public GrPathRenderer
    , public GrOnFlushCallbackObject {

    struct RTPendingOps;

public:
    static bool IsSupported(const GrCaps&);
    static sk_sp<GrCoverageCountingPathRenderer> CreateIfSupported(const GrCaps&);

    // GrPathRenderer overrides.
    StencilSupport onGetStencilSupport(const GrShape&) const override {
        return GrPathRenderer::kNoSupport_StencilSupport;
    }
    CanDrawPath onCanDrawPath(const CanDrawPathArgs& args) const override;
    bool onDrawPath(const DrawPathArgs&) final;

    // GrOnFlushCallbackObject overrides.
    void preFlush(GrOnFlushResourceProvider*, const uint32_t* opListIDs, int numOpListIDs,
                  SkTArray<sk_sp<GrRenderTargetContext>>* results) override;
    void postFlush() override;

    // This is the Op that ultimately draws a path into its final destination, using the atlas we
    // generate at flush time.
    class DrawPathsOp : public GrDrawOp {
    public:
        DEFINE_OP_CLASS_ID
        SK_DECLARE_INTERNAL_LLIST_INTERFACE(DrawPathsOp);

        DrawPathsOp(GrCoverageCountingPathRenderer*, const DrawPathArgs&, GrColor);

        const char* name() const override { return "GrCoverageCountingPathRenderer::DrawPathsOp"; }

        void visitProxies(const VisitProxyFunc& func) const override {
            fProcessors.visitProxies(func);
        }

        // GrDrawOp overrides.
        FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
        RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
                                    GrPixelConfigIsClamped) override;
        void wasRecorded(GrRenderTargetOpList*) override;
        bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override;
        void onPrepare(GrOpFlushState*) override {}
        void onExecute(GrOpFlushState*) override;

    private:
        SkPath::FillType getFillType() const {
            SkASSERT(fDebugInstanceCount >= 1);
            return fHeadDraw.fPath.getFillType();
        }

        struct SingleDraw  {
            using ScissorMode = GrCCPRCoverageOpsBuilder::ScissorMode;
            SkIRect       fClipBounds;
            ScissorMode   fScissorMode;
            SkMatrix      fMatrix;
            SkPath        fPath;
            GrColor       fColor;
            SingleDraw*   fNext = nullptr;
        };

        SingleDraw& getOnlyPathDraw() {
            SkASSERT(&fHeadDraw == fTailDraw);
            SkASSERT(1 == fDebugInstanceCount);
            return fHeadDraw;
        }

        struct AtlasBatch {
            const GrCCPRAtlas*   fAtlas;
            int                  fEndInstanceIdx;
        };

        void addAtlasBatch(const GrCCPRAtlas* atlas, int endInstanceIdx) {
            SkASSERT(endInstanceIdx > fBaseInstance);
            SkASSERT(fAtlasBatches.empty() ||
                     endInstanceIdx > fAtlasBatches.back().fEndInstanceIdx);
            fAtlasBatches.push_back() = {atlas, endInstanceIdx};
        }

        GrCoverageCountingPathRenderer* const   fCCPR;
        const uint32_t                          fSRGBFlags;
        GrProcessorSet                          fProcessors;
        SingleDraw                              fHeadDraw;
        SingleDraw*                             fTailDraw;
        RTPendingOps*                           fOwningRTPendingOps;
        int                                     fBaseInstance;
        SkDEBUGCODE(int                         fDebugInstanceCount;)
        SkDEBUGCODE(int                         fDebugSkippedInstances;)
        SkSTArray<1, AtlasBatch, true>          fAtlasBatches;

        friend class GrCoverageCountingPathRenderer;

        typedef GrDrawOp INHERITED;
    };

private:
    GrCoverageCountingPathRenderer() = default;

    void setupPerFlushResources(GrOnFlushResourceProvider*, const uint32_t* opListIDs,
                                int numOpListIDs, SkTArray<sk_sp<GrRenderTargetContext>>* results);

    struct RTPendingOps {
        SkTInternalLList<DrawPathsOp>                 fOpList;
        int                                           fNumTotalPaths = 0;
        int                                           fNumSkPoints = 0;
        int                                           fNumSkVerbs = 0;
        GrSTAllocator<256, DrawPathsOp::SingleDraw>   fDrawsAllocator;
    };

    // Map from render target ID to the individual render target's pending path ops.
    std::map<uint32_t, RTPendingOps>   fRTPendingOpsMap;

    sk_sp<GrBuffer>                    fPerFlushIndexBuffer;
    sk_sp<GrBuffer>                    fPerFlushVertexBuffer;
    sk_sp<GrBuffer>                    fPerFlushInstanceBuffer;
    GrSTAllocator<4, GrCCPRAtlas>      fPerFlushAtlases;
    bool                               fPerFlushResourcesAreValid;
    SkDEBUGCODE(bool                   fFlushing = false;)
};

#endif
