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

#include "GrShape.h"
#include "SkTInternalLList.h"
#include "ccpr/GrCCSTLList.h"
#include "ccpr/GrCCPathCache.h"
#include "ops/GrDrawOp.h"

class GrCCAtlas;
class GrCCPerFlushResources;
struct GrCCPerFlushResourceSpecs;
struct GrCCPerOpListPaths;
class GrOnFlushResourceProvider;
class GrRecordingContext;

/**
 * This is the Op that draws paths to the actual canvas, using atlases generated by CCPR.
 */
class GrCCDrawPathsOp : public GrDrawOp {
public:
    DEFINE_OP_CLASS_ID
    SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrCCDrawPathsOp);

    static std::unique_ptr<GrCCDrawPathsOp> Make(GrRecordingContext*, const SkIRect& clipIBounds,
                                                 const SkMatrix&, const GrShape&, GrPaint&&);
    ~GrCCDrawPathsOp() override;

    const char* name() const override { return "GrCCDrawPathsOp"; }
    FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
    GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrFSAAType,
                                      GrClampType) override;
    CombineResult onCombineIfPossible(GrOp*, const GrCaps&) override;
    void visitProxies(const VisitProxyFunc& fn, VisitorType) const override {
        fProcessors.visitProxies(fn);
    }
    void onPrepare(GrOpFlushState*) override {}

    void addToOwningPerOpListPaths(sk_sp<GrCCPerOpListPaths> owningPerOpListPaths);

    // Makes decisions about how to draw each path (cached, copied, rendered, etc.), and
    // increments/fills out the corresponding GrCCPerFlushResourceSpecs.
    void accountForOwnPaths(GrCCPathCache*, GrOnFlushResourceProvider*, GrCCPerFlushResourceSpecs*);

    // Allows the caller to decide whether to actually do the suggested copies from cached 16-bit
    // coverage count atlases, and into 8-bit literal coverage atlases. Purely to save space.
    enum class DoCopiesToA8Coverage : bool {
        kNo = false,
        kYes = true
    };

    // Allocates the GPU resources indicated by accountForOwnPaths(), in preparation for drawing. If
    // DoCopiesToA8Coverage is kNo, the paths slated for copy will instead be left in their 16-bit
    // coverage count atlases.
    //
    // NOTE: If using DoCopiesToA8Coverage::kNo, it is the caller's responsibility to have called
    // cancelCopies() on the GrCCPerFlushResourceSpecs, prior to making this call.
    void setupResources(GrCCPathCache*, GrOnFlushResourceProvider*, GrCCPerFlushResources*,
                        DoCopiesToA8Coverage);

    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;

private:
    friend class GrOpMemoryPool;

    static std::unique_ptr<GrCCDrawPathsOp> InternalMake(GrRecordingContext*,
                                                         const SkIRect& clipIBounds,
                                                         const SkMatrix&, const GrShape&,
                                                         float strokeDevWidth,
                                                         const SkRect& conservativeDevBounds,
                                                         GrPaint&&);

    GrCCDrawPathsOp(const SkMatrix&, const GrShape&, float strokeDevWidth,
                    const SkIRect& shapeConservativeIBounds, const SkIRect& maskDevIBounds,
                    const SkRect& conservativeDevBounds, GrPaint&&);

    void recordInstance(GrTextureProxy* atlasProxy, int instanceIdx);

    const SkMatrix fViewMatrixIfUsingLocalCoords;

    class SingleDraw {
    public:
        SingleDraw(const SkMatrix&, const GrShape&, float strokeDevWidth,
                   const SkIRect& shapeConservativeIBounds, const SkIRect& maskDevIBounds,
                   const SkPMColor4f&);

        // See the corresponding methods in GrCCDrawPathsOp.
        GrProcessorSet::Analysis finalize(
                const GrCaps&, const GrAppliedClip*, GrFSAAType, GrClampType, GrProcessorSet*);
        void accountForOwnPath(GrCCPathCache*, GrOnFlushResourceProvider*,
                               GrCCPerFlushResourceSpecs*);
        void setupResources(GrCCPathCache*, GrOnFlushResourceProvider*, GrCCPerFlushResources*,
                            DoCopiesToA8Coverage, GrCCDrawPathsOp*);

    private:
        bool shouldCachePathMask(int maxRenderTargetSize) const;

        SkMatrix fMatrix;
        GrShape fShape;
        float fStrokeDevWidth;
        const SkIRect fShapeConservativeIBounds;
        SkIRect fMaskDevIBounds;
        SkPMColor4f fColor;

        GrCCPathCache::OnFlushEntryRef fCacheEntry;
        SkIVector fCachedMaskShift;
        bool fDoCopyToA8Coverage = false;
        bool fDoCachePathMask = false;

        SingleDraw* fNext = nullptr;

        friend class GrCCSTLList<SingleDraw>;  // To access fNext.
    };

    // Declare fOwningPerOpListPaths first, before fDraws. The draws use memory allocated by
    // fOwningPerOpListPaths, so it must not be unreffed until after fDraws is destroyed.
    sk_sp<GrCCPerOpListPaths> fOwningPerOpListPaths;

    GrCCSTLList<SingleDraw> fDraws;
    SkDEBUGCODE(int fNumDraws = 1);

    GrProcessorSet fProcessors;

    struct InstanceRange {
        GrTextureProxy* fAtlasProxy;
        int fEndInstanceIdx;
    };

    SkSTArray<2, InstanceRange, true> fInstanceRanges;
    int fBaseInstance SkDEBUGCODE(= -1);
};

#endif
