/*
 * 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 "SkRefCnt.h"
#include "SkTDArray.h"

//#define ENABLE_MDB 1

class GrAuditTrail;
class GrOpFlushState;
class GrRenderTargetOpList;
class GrSurface;
class GrSurfaceProxy;
class GrTextureOpList;

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

    // These two methods are invoked as flush time
    virtual void prepareOps(GrOpFlushState* flushState) = 0;
    virtual bool executeOps(GrOpFlushState* flushState) = 0;

    virtual void makeClosed() {
        // We only close GrOpLists when MDB is enabled. When MDB is disabled there is only
        // ever one GrOpLists and all calls will be funnelled into it.
#ifdef ENABLE_MDB
        this->setFlag(kClosed_Flag);
#endif    
    }

    // TODO: it seems a bit odd that GrOpList has nothing to clear on reset
    virtual void reset() = 0;

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

    // TODO: this entry point is only needed in the non-MDB world. Remove when
    // we make the switch to MDB
    void clearTarget() { fTarget = nullptr; }

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

    /*
     * Notify this GrOpList that it relies on the contents of 'dependedOn'
     */
    void addDependency(GrSurface* dependedOn);

    /*
     * Does this opList depend on 'dependedOn'?
     */
    bool dependsOn(GrOpList* dependedOn) const {
        return fDependencies.find(dependedOn) >= 0;
    }

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

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

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

    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];
        }
    };

    void addDependency(GrOpList* dependedOn);

    SkDEBUGCODE(int                                 fDebugID;)
    uint32_t                                        fFlags;
    GrSurfaceProxy*                                 fTarget;

    // 'this' GrOpList relies on the output of the GrOpLists in 'fDependencies'
    SkTDArray<GrOpList*>                            fDependencies;

protected:
    GrAuditTrail*                                   fAuditTrail;

    typedef SkRefCnt INHERITED;
};

#endif
