1 /*
2  * Copyright 2015 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 GrDrawingManager_DEFINED
9 #define GrDrawingManager_DEFINED
10 
11 #include "GrDeferredUpload.h"
12 #include "GrPathRenderer.h"
13 #include "GrPathRendererChain.h"
14 #include "GrResourceCache.h"
15 #include "SkTArray.h"
16 #include "text/GrTextContext.h"
17 
18 class GrContext;
19 class GrCoverageCountingPathRenderer;
20 class GrOnFlushCallbackObject;
21 class GrOpFlushState;
22 class GrRenderTargetContext;
23 class GrRenderTargetProxy;
24 class GrSingleOWner;
25 class GrRenderTargetOpList;
26 class GrSoftwarePathRenderer;
27 class GrTextureContext;
28 class GrTextureOpList;
29 class SkDeferredDisplayList;
30 
31 // The GrDrawingManager allocates a new GrRenderTargetContext for each GrRenderTarget
32 // but all of them still land in the same GrOpList!
33 //
34 // In the future this class will allocate a new GrRenderTargetContext for
35 // each GrRenderTarget/GrOpList and manage the DAG.
36 class GrDrawingManager {
37 public:
38     ~GrDrawingManager();
39 
40     bool wasAbandoned() const { return fAbandoned; }
41     void freeGpuResources();
42 
43     sk_sp<GrRenderTargetContext> makeRenderTargetContext(sk_sp<GrSurfaceProxy>,
44                                                          sk_sp<SkColorSpace>,
45                                                          const SkSurfaceProps*,
46                                                          bool managedOpList = true);
47     sk_sp<GrTextureContext> makeTextureContext(sk_sp<GrSurfaceProxy>, sk_sp<SkColorSpace>);
48 
49     // The caller automatically gets a ref on the returned opList. It must
50     // be balanced by an unref call.
51     // A managed opList is controlled by the drawing manager (i.e., sorted & flushed with the
52     // other). An unmanaged one is created and used by the onFlushCallback.
53     sk_sp<GrRenderTargetOpList> newRTOpList(GrRenderTargetProxy* rtp, bool managedOpList);
54     sk_sp<GrTextureOpList> newTextureOpList(GrTextureProxy* textureProxy);
55 
56     GrContext* getContext() { return fContext; }
57 
58     GrTextContext* getTextContext();
59 
60     GrPathRenderer* getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
61                                     bool allowSW,
62                                     GrPathRendererChain::DrawType drawType,
63                                     GrPathRenderer::StencilSupport* stencilSupport = nullptr);
64 
65     GrPathRenderer* getSoftwarePathRenderer();
66 
67     // Returns a direct pointer to the coverage counting path renderer, or null if it is not
68     // supported and turned on.
69     GrCoverageCountingPathRenderer* getCoverageCountingPathRenderer();
70 
71     void flushIfNecessary();
72 
73     static bool ProgramUnitTest(GrContext* context, int maxStages, int maxLevels);
74 
75     GrSemaphoresSubmitted prepareSurfaceForExternalIO(GrSurfaceProxy*,
76                                                       int numSemaphores,
77                                                       GrBackendSemaphore backendSemaphores[]);
78 
79     void addOnFlushCallbackObject(GrOnFlushCallbackObject*);
80     void testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject*);
81 
82     void moveOpListsToDDL(SkDeferredDisplayList* ddl);
83     void copyOpListsFromDDL(const SkDeferredDisplayList*, GrRenderTargetProxy* newDest);
84 
85 private:
86     // This class encapsulates maintenance and manipulation of the drawing manager's DAG of opLists.
87     class OpListDAG {
88     public:
89         OpListDAG(bool explicitlyAllocating, GrContextOptions::Enable sortOpLists);
90         ~OpListDAG();
91 
92         // Currently, when explicitly allocating resources, this call will topologically sort the
93         // opLists.
94         // MDB TODO: remove once incremental opList sorting is enabled
95         void prepForFlush();
96 
97         void closeAll(const GrCaps* caps);
98 
99         // A yucky combination of closeAll and reset
100         void cleanup(const GrCaps* caps);
101 
102         void gatherIDs(SkSTArray<8, uint32_t, true>* idArray) const;
103 
104         void reset();
105 
106         // These calls forceably remove an opList from the DAG. They are problematic bc they just
107         // remove the opList but don't cleanup any refering pointers (i.e., dependency pointers
108         // in the DAG). They work right now bc they are only called at flush time, after the
109         // topological sort is complete (so the dangling pointers aren't used).
110         void removeOpList(int index);
111         void removeOpLists(int startIndex, int stopIndex);
112 
113         bool empty() const { return fOpLists.empty(); }
114         int numOpLists() const { return fOpLists.count(); }
115 
116         GrOpList* opList(int index) { return fOpLists[index].get(); }
117         const GrOpList* opList(int index) const { return fOpLists[index].get(); }
118 
119         GrOpList* back() { return fOpLists.back().get(); }
120         const GrOpList* back() const { return fOpLists.back().get(); }
121 
122         void add(sk_sp<GrOpList>);
123         void add(const SkTArray<sk_sp<GrOpList>>&);
124 
125         void swap(SkTArray<sk_sp<GrOpList>>* opLists);
126 
127         bool sortingOpLists() const { return fSortOpLists; }
128 
129     private:
130         SkTArray<sk_sp<GrOpList>> fOpLists;
131         bool                      fSortOpLists;
132     };
133 
134     GrDrawingManager(GrContext*, const GrPathRendererChain::Options&,
135                      const GrTextContext::Options&, GrSingleOwner*,
136                      bool explicitlyAllocating, GrContextOptions::Enable sortRenderTargets,
137                      GrContextOptions::Enable reduceOpListSplitting);
138 
139     void abandon();
140     void cleanup();
141 
142     // return true if any opLists were actually executed; false otherwise
143     bool executeOpLists(int startIndex, int stopIndex, GrOpFlushState*, int* numOpListsExecuted);
144 
145     GrSemaphoresSubmitted flush(GrSurfaceProxy* proxy,
146                                 int numSemaphores = 0,
147                                 GrBackendSemaphore backendSemaphores[] = nullptr);
148 
149     SkDEBUGCODE(void validate() const);
150 
151     friend class GrContext;  // for access to: ctor, abandon, reset & flush
152     friend class GrContextPriv; // access to: flush
153     friend class GrOnFlushResourceProvider; // this is just a shallow wrapper around this class
154 
155     static const int kNumPixelGeometries = 5; // The different pixel geometries
156     static const int kNumDFTOptions = 2;      // DFT or no DFT
157 
158     GrContext*                        fContext;
159     GrPathRendererChain::Options      fOptionsForPathRendererChain;
160     GrTextContext::Options            fOptionsForTextContext;
161 
162     std::unique_ptr<char[]>           fVertexBufferSpace;
163     std::unique_ptr<char[]>           fIndexBufferSpace;
164     // In debug builds we guard against improper thread handling
165     GrSingleOwner*                    fSingleOwner;
166 
167     bool                              fAbandoned;
168     OpListDAG                         fDAG;
169     GrOpList*                         fActiveOpList = nullptr;
170     // These are the IDs of the opLists currently being flushed (in internalFlush)
171     SkSTArray<8, uint32_t, true>      fFlushingOpListIDs;
172     // These are the new opLists generated by the onFlush CBs
173     SkSTArray<8, sk_sp<GrOpList>>     fOnFlushCBOpLists;
174 
175     std::unique_ptr<GrTextContext>    fTextContext;
176 
177     std::unique_ptr<GrPathRendererChain> fPathRendererChain;
178     sk_sp<GrSoftwarePathRenderer>     fSoftwarePathRenderer;
179 
180     GrTokenTracker                    fTokenTracker;
181     bool                              fFlushing;
182     bool                              fReduceOpListSplitting;
183 
184     SkTArray<GrOnFlushCallbackObject*> fOnFlushCBObjects;
185 };
186 
187 #endif
188