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