1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrOpList_DEFINED
9#define GrOpList_DEFINED
10
11#include "GrColor.h"
12#include "GrSurfaceProxyRef.h"
13#include "GrTextureProxy.h"
14#include "SkRefCnt.h"
15#include "SkTDArray.h"
16
17
18// Turn on/off the explicit distribution of GPU resources at flush time
19#ifndef SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION
20   #define SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION
21#endif
22
23// Turn on/off the sorting of opLists at flush time
24#ifndef SK_DISABLE_RENDER_TARGET_SORTING
25   #define SK_DISABLE_RENDER_TARGET_SORTING
26#endif
27
28class GrAuditTrail;
29class GrCaps;
30class GrOpFlushState;
31class GrRenderTargetOpList;
32class GrResourceAllocator;
33class GrResourceProvider;
34class GrSurfaceProxy;
35class GrTextureOpList;
36
37struct SkIPoint;
38struct SkIRect;
39
40class GrOpList : public SkRefCnt {
41public:
42    GrOpList(GrResourceProvider*, GrSurfaceProxy*, GrAuditTrail*);
43    ~GrOpList() override;
44
45    // These four methods are invoked at flush time
46    bool instantiate(GrResourceProvider* resourceProvider);
47    // Instantiates any "threaded" texture proxies that are being prepared elsewhere
48    void instantiateDeferredProxies(GrResourceProvider* resourceProvider);
49    void prepare(GrOpFlushState* flushState);
50    bool execute(GrOpFlushState* flushState) { return this->onExecute(flushState); }
51
52    virtual bool copySurface(const GrCaps& caps,
53                             GrSurfaceProxy* dst,
54                             GrSurfaceProxy* src,
55                             const SkIRect& srcRect,
56                             const SkIPoint& dstPoint) = 0;
57
58    virtual void makeClosed(const GrCaps&) {
59        if (!this->isClosed()) {
60            this->setFlag(kClosed_Flag);
61            fTarget.removeRef();
62        }
63    }
64
65    // Called when this class will survive a flush and needs to truncate its ops and start over.
66    // TODO: ultimately it should be invalid for an op list to survive a flush.
67    // https://bugs.chromium.org/p/skia/issues/detail?id=7111
68    virtual void endFlush();
69
70    bool isClosed() const { return this->isSetFlag(kClosed_Flag); }
71
72    /*
73     * Notify this GrOpList that it relies on the contents of 'dependedOn'
74     */
75    void addDependency(GrSurfaceProxy* dependedOn, const GrCaps& caps);
76
77    /*
78     * Does this opList depend on 'dependedOn'?
79     */
80    bool dependsOn(GrOpList* dependedOn) const {
81        for (int i = 0; i < fDependencies.count(); ++i) {
82            if (fDependencies[i] == dependedOn) {
83                return true;
84            }
85        }
86
87        return false;
88    }
89
90    /*
91     * Safely cast this GrOpList to a GrTextureOpList (if possible).
92     */
93    virtual GrTextureOpList* asTextureOpList() { return nullptr; }
94
95    /*
96     * Safely case this GrOpList to a GrRenderTargetOpList (if possible).
97     */
98    virtual GrRenderTargetOpList* asRenderTargetOpList() { return nullptr; }
99
100    uint32_t uniqueID() const { return fUniqueID; }
101
102    /*
103     * Dump out the GrOpList dependency DAG
104     */
105    SkDEBUGCODE(virtual void dump() const;)
106
107    SkDEBUGCODE(virtual int numOps() const = 0;)
108    SkDEBUGCODE(virtual int numClips() const { return 0; })
109
110    // TODO: it would be nice for this to be hidden
111    void setStencilLoadOp(GrLoadOp loadOp) { fStencilLoadOp = loadOp; }
112
113protected:
114    SkDEBUGCODE(bool isInstantiated() const;)
115
116    GrSurfaceProxyRef fTarget;
117    GrAuditTrail*     fAuditTrail;
118
119    GrLoadOp          fColorLoadOp    = GrLoadOp::kLoad;
120    GrColor           fLoadClearColor = 0x0;
121    GrLoadOp          fStencilLoadOp  = GrLoadOp::kLoad;
122
123    // List of texture proxies whose contents are being prepared on a worker thread
124    SkTArray<GrTextureProxy*, true> fDeferredProxies;
125
126private:
127    friend class GrDrawingManager; // for resetFlag, TopoSortTraits & gatherProxyIntervals
128
129    // Remove all Ops which reference proxies that have not been instantiated.
130    virtual void purgeOpsWithUninstantiatedProxies() = 0;
131
132    // Feed proxy usage intervals to the GrResourceAllocator class
133    virtual void gatherProxyIntervals(GrResourceAllocator*) const = 0;
134
135    static uint32_t CreateUniqueID();
136
137    enum Flags {
138        kClosed_Flag    = 0x01,   //!< This GrOpList can't accept any more ops
139
140        kWasOutput_Flag = 0x02,   //!< Flag for topological sorting
141        kTempMark_Flag  = 0x04,   //!< Flag for topological sorting
142    };
143
144    void setFlag(uint32_t flag) {
145        fFlags |= flag;
146    }
147
148    void resetFlag(uint32_t flag) {
149        fFlags &= ~flag;
150    }
151
152    bool isSetFlag(uint32_t flag) const {
153        return SkToBool(fFlags & flag);
154    }
155
156    struct TopoSortTraits {
157        static void Output(GrOpList* dt, int /* index */) {
158            dt->setFlag(GrOpList::kWasOutput_Flag);
159        }
160        static bool WasOutput(const GrOpList* dt) {
161            return dt->isSetFlag(GrOpList::kWasOutput_Flag);
162        }
163        static void SetTempMark(GrOpList* dt) {
164            dt->setFlag(GrOpList::kTempMark_Flag);
165        }
166        static void ResetTempMark(GrOpList* dt) {
167            dt->resetFlag(GrOpList::kTempMark_Flag);
168        }
169        static bool IsTempMarked(const GrOpList* dt) {
170            return dt->isSetFlag(GrOpList::kTempMark_Flag);
171        }
172        static int NumDependencies(const GrOpList* dt) {
173            return dt->fDependencies.count();
174        }
175        static GrOpList* Dependency(GrOpList* dt, int index) {
176            return dt->fDependencies[index];
177        }
178    };
179
180    virtual void onPrepare(GrOpFlushState* flushState) = 0;
181    virtual bool onExecute(GrOpFlushState* flushState) = 0;
182
183    void addDependency(GrOpList* dependedOn);
184
185    uint32_t               fUniqueID;
186    uint32_t               fFlags;
187
188    // 'this' GrOpList relies on the output of the GrOpLists in 'fDependencies'
189    SkSTArray<1, GrOpList*, true> fDependencies;
190
191    typedef SkRefCnt INHERITED;
192};
193
194#endif
195