/*
 * 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 <map>
#include "GrAllocator.h"
#include "GrOnFlushResourceProvider.h"
#include "GrPathRenderer.h"
#include "SkTInternalLList.h"
#include "ccpr/GrCCAtlas.h"
#include "ccpr/GrCCPathParser.h"
#include "ccpr/GrCCPathProcessor.h"
#include "ops/GrDrawOp.h"

/**
 * This is a path renderer that draws antialiased paths by counting coverage in an offscreen
 * buffer. (See GrCCCoverageProcessor, GrCCPathProcessor)
 *
 * 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 RTPendingPaths;

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

    ~GrCoverageCountingPathRenderer() override {
        // Ensure no Ops exist that could have a dangling pointer back into this class.
        SkASSERT(fRTPendingPathsMap.empty());
        SkASSERT(0 == fPendingDrawOpsCount);
    }

    // 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;

        struct SingleDraw {
            SkIRect fClipIBounds;
            SkMatrix fMatrix;
            SkPath fPath;
            GrColor fColor;
            SingleDraw* fNext = nullptr;
        };

        const SingleDraw* head() const {
            SkASSERT(fInstanceCount >= 1);
            return &fHeadDraw;
        }

        SkDEBUGCODE(int numSkippedInstances_debugOnly() const { return fNumSkippedInstances; })

        // GrDrawOp overrides.
        const char* name() const override { return "GrCoverageCountingPathRenderer::DrawPathsOp"; }
        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 visitProxies(const VisitProxyFunc& func) const override {
            fProcessors.visitProxies(func);
        }
        void onPrepare(GrOpFlushState*) override {}
        void onExecute(GrOpFlushState*) override;

        int setupResources(GrOnFlushResourceProvider*,
                           GrCCPathProcessor::Instance* pathInstanceData, int pathInstanceIdx);

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

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

        void addAtlasBatch(const GrCCAtlas* 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;
        RTPendingPaths* fOwningRTPendingPaths;
        int fBaseInstance;
        SkDEBUGCODE(int fInstanceCount);
        SkDEBUGCODE(int fNumSkippedInstances);
        SkSTArray<1, AtlasBatch, true> fAtlasBatches;

        typedef GrDrawOp INHERITED;
    };

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

    // These are keyed by SkPath generation ID, and store which device-space paths are accessed and
    // where by clip FPs in a given opList. A single ClipPath can be referenced by multiple FPs. At
    // flush time their coverage count masks are packed into atlas(es) alongside normal DrawPathOps.
    class ClipPath {
    public:
        ClipPath() = default;
        ClipPath(const ClipPath&) = delete;

        ~ClipPath() {
            // Ensure no clip FPs exist with a dangling pointer back into this class.
            SkASSERT(!fAtlasLazyProxy || fAtlasLazyProxy->isUnique_debugOnly());
            // Ensure no lazy proxy callbacks exist with a dangling pointer back into this class.
            SkASSERT(fHasAtlasTransform);
        }

        bool isUninitialized() const { return !fAtlasLazyProxy; }
        void init(GrProxyProvider* proxyProvider,
                  const SkPath& deviceSpacePath, const SkIRect& accessRect,
                  int rtWidth, int rtHeight);
        void addAccess(const SkIRect& accessRect) {
            SkASSERT(!this->isUninitialized());
            fAccessRect.join(accessRect);
        }

        GrTextureProxy* atlasLazyProxy() const {
            SkASSERT(!this->isUninitialized());
            return fAtlasLazyProxy.get();
        }
        const SkPath& deviceSpacePath() const {
            SkASSERT(!this->isUninitialized());
            return fDeviceSpacePath;
        }
        const SkIRect& pathDevIBounds() const {
            SkASSERT(!this->isUninitialized());
            return fPathDevIBounds;
        }
        void placePathInAtlas(GrCoverageCountingPathRenderer*, GrOnFlushResourceProvider*,
                              GrCCPathParser*);

        const SkVector& atlasScale() const {
            SkASSERT(fHasAtlasTransform);
            return fAtlasScale;
        }
        const SkVector& atlasTranslate() const {
            SkASSERT(fHasAtlasTransform);
            return fAtlasTranslate;
        }

    private:
        sk_sp<GrTextureProxy> fAtlasLazyProxy;
        SkPath fDeviceSpacePath;
        SkIRect fPathDevIBounds;
        SkIRect fAccessRect;

        const GrCCAtlas* fAtlas = nullptr;
        int16_t fAtlasOffsetX;
        int16_t fAtlasOffsetY;
        SkDEBUGCODE(bool fHasAtlas = false);

        SkVector fAtlasScale;
        SkVector fAtlasTranslate;
        SkDEBUGCODE(bool fHasAtlasTransform = false);
    };

    std::unique_ptr<GrFragmentProcessor> makeClipProcessor(GrProxyProvider*, uint32_t oplistID,
                                                           const SkPath& deviceSpacePath,
                                                           const SkIRect& accessRect,
                                                           int rtWidth, int rtHeight);

    // 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;

private:
    GrCoverageCountingPathRenderer(bool drawCachablePaths)
            : fDrawCachablePaths(drawCachablePaths) {}

    GrCCAtlas* placeParsedPathInAtlas(GrOnFlushResourceProvider*, const SkIRect& accessRect,
                                      const SkIRect& pathIBounds, int16_t* atlasOffsetX,
                                      int16_t* atlasOffsetY);

    struct RTPendingPaths {
        ~RTPendingPaths() {
            // Ensure there are no surviving DrawPathsOps with a dangling pointer into this class.
            if (!fDrawOps.isEmpty()) {
                SK_ABORT("CCPR DrawPathsOp(s) not deleted during flush");
            }
            // Clip lazy proxies also reference this class from their callbacks, but those callbacks
            // are only invoked at flush time while we are still alive. (Unlike DrawPathsOps, that
            // unregister themselves upon destruction.) So it shouldn't matter if any clip proxies
            // are still around.
        }

        SkTInternalLList<DrawPathsOp> fDrawOps;
        std::map<uint32_t, ClipPath> fClipPaths;
        GrSTAllocator<256, DrawPathsOp::SingleDraw> fDrawsAllocator;
    };

    // A map from render target ID to the individual render target's pending paths.
    std::map<uint32_t, RTPendingPaths> fRTPendingPathsMap;
    SkDEBUGCODE(int fPendingDrawOpsCount = 0);

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

    const bool fDrawCachablePaths;
};

#endif
