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 <set>
12 #include "include/core/SkSurface.h"
13 #include "include/private/SkTArray.h"
14 #include "src/gpu/GrBufferAllocPool.h"
15 #include "src/gpu/GrDeferredUpload.h"
16 #include "src/gpu/GrPathRenderer.h"
17 #include "src/gpu/GrPathRendererChain.h"
18 #include "src/gpu/GrResourceCache.h"
19 #include "src/gpu/text/GrTextContext.h"
20 
21 class GrCoverageCountingPathRenderer;
22 class GrOnFlushCallbackObject;
23 class GrOpFlushState;
24 class GrOpsTask;
25 class GrRecordingContext;
26 class GrRenderTargetContext;
27 class GrRenderTargetProxy;
28 class GrSoftwarePathRenderer;
29 class GrTextureContext;
30 class GrTextureResolveRenderTask;
31 class SkDeferredDisplayList;
32 
33 class GrDrawingManager {
34 public:
35     ~GrDrawingManager();
36 
37     void freeGpuResources();
38 
39     std::unique_ptr<GrRenderTargetContext> makeRenderTargetContext(sk_sp<GrSurfaceProxy>,
40                                                                    GrColorType,
41                                                                    sk_sp<SkColorSpace>,
42                                                                    const SkSurfaceProps*,
43                                                                    bool managedOpsTask = true);
44     std::unique_ptr<GrTextureContext> makeTextureContext(sk_sp<GrSurfaceProxy>,
45                                                          GrColorType,
46                                                          SkAlphaType,
47                                                          sk_sp<SkColorSpace>);
48 
49     // A managed opsTask is controlled by the drawing manager (i.e., sorted & flushed with the
50     // others). An unmanaged one is created and used by the onFlushCallback.
51     sk_sp<GrOpsTask> newOpsTask(sk_sp<GrRenderTargetProxy>, bool managedOpsTask);
52 
53     // Create a render task that can resolve MSAA and/or regenerate mipmap levels on proxies. This
54     // method will only add the new render task to the list. It is up to the caller to call
55     // addProxy() on the returned object.
56     GrTextureResolveRenderTask* newTextureResolveRenderTask(const GrCaps&);
57 
58     // Create a new render task that will cause the gpu to wait on semaphores before executing any
59     // more RenderTasks that target proxy. It is possible for this wait to also block additional
60     // work (even to other proxies) that has already been recorded or will be recorded later. The
61     // only guarantee is that future work to the passed in proxy will wait on the semaphores to be
62     // signaled.
63     void newWaitRenderTask(sk_sp<GrSurfaceProxy> proxy, std::unique_ptr<sk_sp<GrSemaphore>[]>,
64                            int numSemaphores);
65 
66     // Create a new render task which copies the pixels from the srcProxy into the dstBuffer. This
67     // is used to support the asynchronous readback API. The srcRect is the region of the srcProxy
68     // to be copied. The surfaceColorType says how we should interpret the data when reading back
69     // from the source. DstColorType describes how the data should be stored in the dstBuffer.
70     // DstOffset is the offset into the dstBuffer where we will start writing data.
71     void newTransferFromRenderTask(sk_sp<GrSurfaceProxy> srcProxy, const SkIRect& srcRect,
72                                    GrColorType surfaceColorType, GrColorType dstColorType,
73                                    sk_sp<GrGpuBuffer> dstBuffer, size_t dstOffset);
74 
75     // Creates a new render task which copies a pixel rectangle from srcProxy into dstProxy. The src
76     // pixels copied are specified by srcRect. They are copied to a rect of the same size in
77     // dstProxy with top left at dstPoint. If the src rect is clipped by the src bounds then  pixel
78     // values in the dst rect corresponding to the area clipped by the src rect are not overwritten.
79     // This method is not guaranteed to succeed depending on the type of surface, formats, etc, and
80     // the backend-specific limitations.
81     bool newCopyRenderTask(sk_sp<GrSurfaceProxy> srcProxy, const SkIRect& srcRect,
82                            sk_sp<GrSurfaceProxy> dstProxy, const SkIPoint& dstPoint);
83 
getContext()84     GrRecordingContext* getContext() { return fContext; }
85 
86     GrTextContext* getTextContext();
87 
88     GrPathRenderer* getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
89                                     bool allowSW,
90                                     GrPathRendererChain::DrawType drawType,
91                                     GrPathRenderer::StencilSupport* stencilSupport = nullptr);
92 
93     GrPathRenderer* getSoftwarePathRenderer();
94 
95     // Returns a direct pointer to the coverage counting path renderer, or null if it is not
96     // supported and turned on.
97     GrCoverageCountingPathRenderer* getCoverageCountingPathRenderer();
98 
99     void flushIfNecessary();
100 
101     static bool ProgramUnitTest(GrContext* context, int maxStages, int maxLevels);
102 
103     GrSemaphoresSubmitted flushSurfaces(GrSurfaceProxy* proxies[],
104                                         int cnt,
105                                         SkSurface::BackendSurfaceAccess access,
106                                         const GrFlushInfo& info);
flushSurface(GrSurfaceProxy * proxy,SkSurface::BackendSurfaceAccess access,const GrFlushInfo & info)107     GrSemaphoresSubmitted flushSurface(GrSurfaceProxy* proxy,
108                                        SkSurface::BackendSurfaceAccess access,
109                                        const GrFlushInfo& info) {
110         return this->flushSurfaces(&proxy, 1, access, info);
111     }
112 
113     void addOnFlushCallbackObject(GrOnFlushCallbackObject*);
114 
115 #if GR_TEST_UTILS
116     void testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject*);
117 #endif
118 
119     void moveRenderTasksToDDL(SkDeferredDisplayList* ddl);
120     void copyRenderTasksFromDDL(const SkDeferredDisplayList*, GrRenderTargetProxy* newDest);
121 
122 private:
123     // This class encapsulates maintenance and manipulation of the drawing manager's DAG of
124     // renderTasks.
125     class RenderTaskDAG {
126     public:
127         RenderTaskDAG(bool sortRenderTasks);
128         ~RenderTaskDAG();
129 
130         // Currently, when explicitly allocating resources, this call will topologically sort the
131         // GrRenderTasks.
132         // MDB TODO: remove once incremental GrRenderTask sorting is enabled
133         void prepForFlush();
134 
135         void closeAll(const GrCaps* caps);
136 
137         // A yucky combination of closeAll and reset
138         void cleanup(const GrCaps* caps);
139 
140         void gatherIDs(SkSTArray<8, uint32_t, true>* idArray) const;
141 
142         void reset();
143 
144         // These calls forceably remove a GrRenderTask from the DAG. They are problematic bc they
145         // just remove the GrRenderTask but don't cleanup any refering pointers (i.e., dependency
146         // pointers in the DAG). They work right now bc they are only called at flush time, after
147         // the topological sort is complete (so the dangling pointers aren't used).
148         void removeRenderTask(int index);
149         void removeRenderTasks(int startIndex, int stopIndex);
150 
empty()151         bool empty() const { return fRenderTasks.empty(); }
numRenderTasks()152         int numRenderTasks() const { return fRenderTasks.count(); }
153 
154         bool isUsed(GrSurfaceProxy*) const;
155 
renderTask(int index)156         GrRenderTask* renderTask(int index) { return fRenderTasks[index].get(); }
renderTask(int index)157         const GrRenderTask* renderTask(int index) const { return fRenderTasks[index].get(); }
158 
back()159         GrRenderTask* back() { return fRenderTasks.back().get(); }
back()160         const GrRenderTask* back() const { return fRenderTasks.back().get(); }
161 
162         GrRenderTask* add(sk_sp<GrRenderTask>);
163         GrRenderTask* addBeforeLast(sk_sp<GrRenderTask>);
164         void add(const SkTArray<sk_sp<GrRenderTask>>&);
165 
166         void swap(SkTArray<sk_sp<GrRenderTask>>* renderTasks);
167 
sortingRenderTasks()168         bool sortingRenderTasks() const { return fSortRenderTasks; }
169 
170     private:
171         SkTArray<sk_sp<GrRenderTask>> fRenderTasks;
172         bool                          fSortRenderTasks;
173     };
174 
175     GrDrawingManager(GrRecordingContext*, const GrPathRendererChain::Options&,
176                      const GrTextContext::Options&,
177                      bool sortRenderTasks,
178                      bool reduceOpsTaskSplitting);
179 
180     bool wasAbandoned() const;
181 
182     void cleanup();
183 
184     // Closes the target's dependent render tasks (or, if not in sorting/opsTask-splitting-reduction
185     // mode, closes fActiveOpsTask) in preparation for us opening a new opsTask that will write to
186     // 'target'.
187     void closeRenderTasksForNewRenderTask(GrSurfaceProxy* target);
188 
189     // return true if any GrRenderTasks were actually executed; false otherwise
190     bool executeRenderTasks(int startIndex, int stopIndex, GrOpFlushState*,
191                             int* numRenderTasksExecuted);
192 
193     GrSemaphoresSubmitted flush(GrSurfaceProxy* proxies[],
194                                 int numProxies,
195                                 SkSurface::BackendSurfaceAccess access,
196                                 const GrFlushInfo&,
197                                 const GrPrepareForExternalIORequests&);
198 
199     SkDEBUGCODE(void validate() const);
200 
201     friend class GrContext; // access to: flush & cleanup
202     friend class GrContextPriv; // access to: flush
203     friend class GrOnFlushResourceProvider; // this is just a shallow wrapper around this class
204     friend class GrRecordingContext;  // access to: ctor
205     friend class SkImage; // for access to: flush
206 
207     static const int kNumPixelGeometries = 5; // The different pixel geometries
208     static const int kNumDFTOptions = 2;      // DFT or no DFT
209 
210     GrRecordingContext*               fContext;
211     GrPathRendererChain::Options      fOptionsForPathRendererChain;
212     GrTextContext::Options            fOptionsForTextContext;
213     // This cache is used by both the vertex and index pools. It reuses memory across multiple
214     // flushes.
215     sk_sp<GrBufferAllocPool::CpuBufferCache> fCpuBufferCache;
216 
217     RenderTaskDAG                     fDAG;
218     GrOpsTask*                        fActiveOpsTask = nullptr;
219     // These are the IDs of the opsTask currently being flushed (in internalFlush)
220     SkSTArray<8, uint32_t, true>      fFlushingRenderTaskIDs;
221     // These are the new renderTasks generated by the onFlush CBs
222     SkSTArray<4, sk_sp<GrRenderTask>> fOnFlushRenderTasks;
223 
224     std::unique_ptr<GrTextContext>    fTextContext;
225 
226     std::unique_ptr<GrPathRendererChain> fPathRendererChain;
227     sk_sp<GrSoftwarePathRenderer>     fSoftwarePathRenderer;
228 
229     GrTokenTracker                    fTokenTracker;
230     bool                              fFlushing;
231     bool                              fReduceOpsTaskSplitting;
232 
233     SkTArray<GrOnFlushCallbackObject*> fOnFlushCBObjects;
234 
addDDLTarget(GrSurfaceProxy * proxy)235     void addDDLTarget(GrSurfaceProxy* proxy) { fDDLTargets.insert(proxy); }
isDDLTarget(GrSurfaceProxy * proxy)236     bool isDDLTarget(GrSurfaceProxy* proxy) { return fDDLTargets.find(proxy) != fDDLTargets.end(); }
clearDDLTargets()237     void clearDDLTargets() { fDDLTargets.clear(); }
238 
239     // We play a trick with lazy proxies to retarget the base target of a DDL to the SkSurface
240     // it is replayed on. Because of this remapping we need to explicitly store the targets of
241     // DDL replaying.
242     // Note: we do not expect a whole lot of these per flush
243     std::set<GrSurfaceProxy*> fDDLTargets;
244 };
245 
246 #endif
247