/*
 * 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 GrBatchFlushState;
class GrSurface;
class GrSurfaceProxy;

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

    // These two methods are invoked as flush time
    virtual void prepareBatches(GrBatchFlushState* flushState) = 0;
    virtual bool drawBatches(GrBatchFlushState* 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;
    }

    /*
     * 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 batches

        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
