/*
 * 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&,
                                                                   bool drawCachablePaths);

    ~GrCoverageCountingPathRenderer() override {
        // Ensure nothing exists that could have a dangling pointer back into this class.
        SkASSERT(fRTPendingOpsMap.empty());
        SkASSERT(0 == fPendingDrawOpsCount);
    }

    // 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(GrDeferredUploadToken, const uint32_t* opListIDs, int numOpListIDs) 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);
        ~DrawPathsOp() override;

        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  {
            SkIRect       fClipIBounds;
            SkMatrix      fMatrix;
            SkPath        fPath;
            GrColor       fColor;
            SingleDraw*   fNext = nullptr;
        };

        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(bool drawCachablePaths)
            : fDrawCachablePaths(drawCachablePaths) {}

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

    struct RTPendingOps {
        SkTInternalLList<DrawPathsOp>                 fOpList;
        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;
    SkDEBUGCODE(int                    fPendingDrawOpsCount = 0;)

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

    const bool                         fDrawCachablePaths;
};

#endif
