1 /*
2  * Copyright 2019 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 GrRecordingContext_DEFINED
9 #define GrRecordingContext_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "include/private/GrImageContext.h"
13 #include "include/private/SkTArray.h"
14 
15 #if GR_GPU_STATS && GR_TEST_UTILS
16 #include <map>
17 #include <string>
18 #endif
19 
20 class GrAuditTrail;
21 class GrBackendFormat;
22 class GrDrawingManager;
23 class GrOnFlushCallbackObject;
24 class GrMemoryPool;
25 class GrProgramDesc;
26 class GrProgramInfo;
27 class GrProxyProvider;
28 class GrRecordingContextPriv;
29 class GrSubRunAllocator;
30 class GrSurfaceContext;
31 class GrSurfaceProxy;
32 class GrTextBlobCache;
33 class GrThreadSafeCache;
34 class SkArenaAlloc;
35 class SkJSONWriter;
36 
37 #if GR_TEST_UTILS
38 class SkString;
39 #endif
40 
41 class GrRecordingContext : public GrImageContext {
42 public:
43     ~GrRecordingContext() override;
44 
defaultBackendFormat(SkColorType ct,GrRenderable renderable)45     SK_API GrBackendFormat defaultBackendFormat(SkColorType ct, GrRenderable renderable) const {
46         return INHERITED::defaultBackendFormat(ct, renderable);
47     }
48 
49     /**
50      * Reports whether the GrDirectContext associated with this GrRecordingContext is abandoned.
51      * When called on a GrDirectContext it may actively check whether the underlying 3D API
52      * device/context has been disconnected before reporting the status. If so, calling this
53      * method will transition the GrDirectContext to the abandoned state.
54      */
abandoned()55     bool abandoned() override { return INHERITED::abandoned(); }
56 
57     /*
58      * Can a SkSurface be created with the given color type. To check whether MSAA is supported
59      * use maxSurfaceSampleCountForColorType().
60      */
colorTypeSupportedAsSurface(SkColorType colorType)61     SK_API bool colorTypeSupportedAsSurface(SkColorType colorType) const {
62         if (kR16G16_unorm_SkColorType == colorType ||
63             kA16_unorm_SkColorType == colorType ||
64             kA16_float_SkColorType == colorType ||
65             kR16G16_float_SkColorType == colorType ||
66             kR16G16B16A16_unorm_SkColorType == colorType ||
67             kGray_8_SkColorType == colorType) {
68             return false;
69         }
70 
71         return this->maxSurfaceSampleCountForColorType(colorType) > 0;
72     }
73 
74     /**
75      * Gets the maximum supported texture size.
76      */
77     SK_API int maxTextureSize() const;
78 
79     /**
80      * Gets the maximum supported render target size.
81      */
82     SK_API int maxRenderTargetSize() const;
83 
84     /**
85      * Can a SkImage be created with the given color type.
86      */
87     SK_API bool colorTypeSupportedAsImage(SkColorType) const;
88 
89     /**
90      * Gets the maximum supported sample count for a color type. 1 is returned if only non-MSAA
91      * rendering is supported for the color type. 0 is returned if rendering to this color type
92      * is not supported at all.
93      */
94     SK_API int maxSurfaceSampleCountForColorType(SkColorType) const;
95 
96     // Provides access to functions that aren't part of the public API.
97     GrRecordingContextPriv priv();
98     const GrRecordingContextPriv priv() const;  // NOLINT(readability-const-return-type)
99 
100     // The collection of specialized memory arenas for different types of data recorded by a
101     // GrRecordingContext. Arenas does not maintain ownership of the pools it groups together.
102     class Arenas {
103     public:
104         Arenas(SkArenaAlloc*, GrSubRunAllocator*);
105 
106         // For storing pipelines and other complex data as-needed by ops
recordTimeAllocator()107         SkArenaAlloc* recordTimeAllocator() { return fRecordTimeAllocator; }
108 
109         // For storing GrTextBlob SubRuns
recordTimeSubRunAllocator()110         GrSubRunAllocator* recordTimeSubRunAllocator() { return fRecordTimeSubRunAllocator; }
111 
112     private:
113         SkArenaAlloc* fRecordTimeAllocator;
114         GrSubRunAllocator* fRecordTimeSubRunAllocator;
115     };
116 
117 protected:
118     friend class GrRecordingContextPriv;    // for hidden functions
119     friend class SkDeferredDisplayList;     // for OwnedArenas
120     friend class SkDeferredDisplayListPriv; // for ProgramData
121 
122     // Like Arenas, but preserves ownership of the underlying pools.
123     class OwnedArenas {
124     public:
125         OwnedArenas(bool ddlRecording);
126         ~OwnedArenas();
127 
128         Arenas get();
129 
130         OwnedArenas& operator=(OwnedArenas&&);
131 
132     private:
133         bool fDDLRecording;
134         std::unique_ptr<SkArenaAlloc> fRecordTimeAllocator;
135         std::unique_ptr<GrSubRunAllocator> fRecordTimeSubRunAllocator;
136     };
137 
138     GrRecordingContext(sk_sp<GrContextThreadSafeProxy>, bool ddlRecording);
139 
140     bool init() override;
141 
142     void abandonContext() override;
143 
144     GrDrawingManager* drawingManager();
145 
146     // There is no going back from this method. It should only be called to control the timing
147     // during abandon or destruction of the context.
148     void destroyDrawingManager();
149 
arenas()150     Arenas arenas() { return fArenas.get(); }
151     // This entry point should only be used for DDL creation where we want the ops' lifetime to
152     // match that of the DDL.
153     OwnedArenas&& detachArenas();
154 
proxyProvider()155     GrProxyProvider* proxyProvider() { return fProxyProvider.get(); }
proxyProvider()156     const GrProxyProvider* proxyProvider() const { return fProxyProvider.get(); }
157 
158     struct ProgramData {
159         ProgramData(std::unique_ptr<const GrProgramDesc>, const GrProgramInfo*);
160         ProgramData(ProgramData&&);                     // for SkTArray
161         ProgramData(const ProgramData&) = delete;
162         ~ProgramData();
163 
descProgramData164         const GrProgramDesc& desc() const { return *fDesc; }
infoProgramData165         const GrProgramInfo& info() const { return *fInfo; }
166 
167     private:
168         // TODO: store the GrProgramDescs in the 'fRecordTimeData' arena
169         std::unique_ptr<const GrProgramDesc> fDesc;
170         // The program infos should be stored in 'fRecordTimeData' so do not need to be ref
171         // counted or deleted in the destructor.
172         const GrProgramInfo* fInfo = nullptr;
173     };
174 
175     // This entry point gives the recording context a chance to cache the provided
176     // programInfo. The DDL context takes this opportunity to store programInfos as a sidecar
177     // to the DDL.
recordProgramInfo(const GrProgramInfo *)178     virtual void recordProgramInfo(const GrProgramInfo*) {}
179     // This asks the recording context to return any programInfos it may have collected
180     // via the 'recordProgramInfo' call. It is up to the caller to ensure that the lifetime
181     // of the programInfos matches the intended use. For example, in DDL-record mode it
182     // is known that all the programInfos will have been allocated in an arena with the
183     // same lifetime at the DDL itself.
detachProgramData(SkTArray<ProgramData> *)184     virtual void detachProgramData(SkTArray<ProgramData>*) {}
185 
186     GrTextBlobCache* getTextBlobCache();
187     const GrTextBlobCache* getTextBlobCache() const;
188 
189     GrThreadSafeCache* threadSafeCache();
190     const GrThreadSafeCache* threadSafeCache() const;
191 
192     /**
193      * Registers an object for flush-related callbacks. (See GrOnFlushCallbackObject.)
194      *
195      * NOTE: the drawing manager tracks this object as a raw pointer; it is up to the caller to
196      * ensure its lifetime is tied to that of the context.
197      */
198     void addOnFlushCallbackObject(GrOnFlushCallbackObject*);
199 
auditTrail()200     GrAuditTrail* auditTrail() { return fAuditTrail.get(); }
201 
asRecordingContext()202     GrRecordingContext* asRecordingContext() override { return this; }
203 
204     class Stats {
205     public:
206         Stats() = default;
207 
208 #if GR_GPU_STATS
reset()209         void reset() { *this = {}; }
210 
numPathMasksGenerated()211         int numPathMasksGenerated() const { return fNumPathMasksGenerated; }
incNumPathMasksGenerated()212         void incNumPathMasksGenerated() { fNumPathMasksGenerated++; }
213 
numPathMaskCacheHits()214         int numPathMaskCacheHits() const { return fNumPathMaskCacheHits; }
incNumPathMasksCacheHits()215         void incNumPathMasksCacheHits() { fNumPathMaskCacheHits++; }
216 
217 #if GR_TEST_UTILS
218         void dump(SkString* out);
219         void dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values);
220 #endif
221 
222     private:
223         int fNumPathMasksGenerated{0};
224         int fNumPathMaskCacheHits{0};
225 
226 #else // GR_GPU_STATS
incNumPathMasksGenerated()227         void incNumPathMasksGenerated() {}
incNumPathMasksCacheHits()228         void incNumPathMasksCacheHits() {}
229 
230 #if GR_TEST_UTILS
dump(SkString *)231         void dump(SkString*) {}
dumpKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values)232         void dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) {}
233 #endif
234 #endif // GR_GPU_STATS
235     } fStats;
236 
237 #if GR_GPU_STATS && GR_TEST_UTILS
238     struct DMSAAStats {
239         void dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) const;
240         void dump() const;
241         void merge(const DMSAAStats&);
242         int fNumRenderPasses = 0;
243         int fNumMultisampleRenderPasses = 0;
244         std::map<std::string, int> fTriggerCounts;
245     };
246 
247     DMSAAStats fDMSAAStats;
248 #endif
249 
stats()250     Stats* stats() { return &fStats; }
stats()251     const Stats* stats() const { return &fStats; }
252     void dumpJSON(SkJSONWriter*) const;
253 
254 private:
255     // Delete last in case other objects call it during destruction.
256     std::unique_ptr<GrAuditTrail>     fAuditTrail;
257 
258     OwnedArenas                       fArenas;
259 
260     std::unique_ptr<GrDrawingManager> fDrawingManager;
261     std::unique_ptr<GrProxyProvider>  fProxyProvider;
262 
263 #if GR_TEST_UTILS
264     int fSuppressWarningMessages = 0;
265 #endif
266 
267     using INHERITED = GrImageContext;
268 };
269 
270 /**
271  * Safely cast a possibly-null base context to direct context.
272  */
GrAsDirectContext(GrContext_Base * base)273 static inline GrDirectContext* GrAsDirectContext(GrContext_Base* base) {
274     return base ? base->asDirectContext() : nullptr;
275 }
276 
277 #endif
278