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

#ifndef GrOpList_DEFINED
#define GrOpList_DEFINED

#include "GrColor.h"
#include "GrGpuResourceRef.h"
#include "SkRefCnt.h"
#include "SkTDArray.h"


// Turn on/off the explicit distribution of GPU resources at flush time
//#define MDB_ALLOC_RESOURCES 1

// Turn on/off the sorting of opLists at flush time
//#define ENABLE_MDB_SORT 1

class GrAuditTrail;
class GrCaps;
class GrOpFlushState;
class GrPrepareCallback;
class GrRenderTargetOpList;
class GrResourceAllocator;
class GrResourceProvider;
class GrSurfaceProxy;
class GrTextureProxy;
class GrTextureOpList;

struct SkIPoint;
struct SkIRect;

class GrOpList : public SkRefCnt {
public:
    GrOpList(GrResourceProvider*, GrSurfaceProxy*, GrAuditTrail*);
    ~GrOpList() override;

    // These three methods are invoked at flush time
    bool instantiate(GrResourceProvider* resourceProvider);
    void prepare(GrOpFlushState* flushState);
    bool execute(GrOpFlushState* flushState) { return this->onExecute(flushState); }

    virtual bool copySurface(const GrCaps& caps,
                             GrSurfaceProxy* dst,
                             GrSurfaceProxy* src,
                             const SkIRect& srcRect,
                             const SkIPoint& dstPoint) = 0;

    virtual void makeClosed(const GrCaps&) {
        if (!this->isClosed()) {
            this->setFlag(kClosed_Flag);
            fTarget.removeRef();
        }
    }

    virtual void reset();

    void addPrepareCallback(std::unique_ptr<GrPrepareCallback> callback);

    // TODO: in an MDB world, where the OpLists don't allocate GPU resources, it seems like
    // these could go away
    virtual void abandonGpuResources() = 0;
    virtual void freeGpuResources() = 0;

    bool isClosed() const { return this->isSetFlag(kClosed_Flag); }

    /*
     * Notify this GrOpList that it relies on the contents of 'dependedOn'
     */
    void addDependency(GrSurfaceProxy* dependedOn, const GrCaps& caps);

    /*
     * Does this opList depend on 'dependedOn'?
     */
    bool dependsOn(GrOpList* dependedOn) const {
        for (int i = 0; i < fDependencies.count(); ++i) {
            if (fDependencies[i] == dependedOn) {
                return true;
            }
        }

        return false;
    }

    /*
     * Safely cast this GrOpList to a GrTextureOpList (if possible).
     */
    virtual GrTextureOpList* asTextureOpList() { return nullptr; }

    /*
     * Safely case this GrOpList to a GrRenderTargetOpList (if possible).
     */
    virtual GrRenderTargetOpList* asRenderTargetOpList() { return nullptr; }

    int32_t uniqueID() const { return fUniqueID; }

    /*
     * Dump out the GrOpList dependency DAG
     */
    SkDEBUGCODE(virtual void dump() const;)

    SkDEBUGCODE(virtual int numOps() const = 0;)
    SkDEBUGCODE(virtual int numClips() const { return 0; })

    // TODO: it would be nice for this to be hidden
    void setStencilLoadOp(GrLoadOp loadOp) { fStencilLoadOp = loadOp; }

protected:
    SkDEBUGCODE(bool isInstantiated() const;)

    GrSurfaceProxyRef fTarget;
    GrAuditTrail*     fAuditTrail;

    GrLoadOp          fColorLoadOp    = GrLoadOp::kLoad;
    GrColor           fLoadClearColor = 0x0;
    GrLoadOp          fStencilLoadOp  = GrLoadOp::kLoad;

private:
    friend class GrDrawingManager; // for resetFlag, TopoSortTraits & gatherProxyIntervals

    // Feed proxy usage intervals to the GrResourceAllocator class
    virtual void gatherProxyIntervals(GrResourceAllocator*) const = 0;

    static uint32_t CreateUniqueID();

    enum Flags {
        kClosed_Flag    = 0x01,   //!< This GrOpList can't accept any more ops

        kWasOutput_Flag = 0x02,   //!< Flag for topological sorting
        kTempMark_Flag  = 0x04,   //!< Flag for topological sorting
    };

    void setFlag(uint32_t flag) {
        fFlags |= flag;
    }

    void resetFlag(uint32_t flag) {
        fFlags &= ~flag;
    }

    bool isSetFlag(uint32_t flag) const {
        return SkToBool(fFlags & flag);
    }

    struct TopoSortTraits {
        static void Output(GrOpList* dt, int /* index */) {
            dt->setFlag(GrOpList::kWasOutput_Flag);
        }
        static bool WasOutput(const GrOpList* dt) {
            return dt->isSetFlag(GrOpList::kWasOutput_Flag);
        }
        static void SetTempMark(GrOpList* dt) {
            dt->setFlag(GrOpList::kTempMark_Flag);
        }
        static void ResetTempMark(GrOpList* dt) {
            dt->resetFlag(GrOpList::kTempMark_Flag);
        }
        static bool IsTempMarked(const GrOpList* dt) {
            return dt->isSetFlag(GrOpList::kTempMark_Flag);
        }
        static int NumDependencies(const GrOpList* dt) {
            return dt->fDependencies.count();
        }
        static GrOpList* Dependency(GrOpList* dt, int index) {
            return dt->fDependencies[index];
        }
    };

    virtual void onPrepare(GrOpFlushState* flushState) = 0;
    virtual bool onExecute(GrOpFlushState* flushState) = 0;

    void addDependency(GrOpList* dependedOn);

    uint32_t               fUniqueID;
    uint32_t               fFlags;

    // 'this' GrOpList relies on the output of the GrOpLists in 'fDependencies'
    SkSTArray<1, GrOpList*, true> fDependencies;

    // These are used rarely, most clients never produce any
    SkTArray<std::unique_ptr<GrPrepareCallback>> fPrepareCallbacks;

    typedef SkRefCnt INHERITED;
};

#endif
