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) const44 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 */
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) const60 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 // OH ISSUE: check whether the PID is abnormal.
isPidAbnormal() const117 virtual bool isPidAbnormal() const { return false; }
118
119 protected:
120 friend class GrRecordingContextPriv; // for hidden functions
121 friend class SkDeferredDisplayList; // for OwnedArenas
122 friend class SkDeferredDisplayListPriv; // for ProgramData
123
124 // Like Arenas, but preserves ownership of the underlying pools.
125 class OwnedArenas {
126 public:
127 OwnedArenas(bool ddlRecording);
128 ~OwnedArenas();
129
130 Arenas get();
131
132 OwnedArenas& operator=(OwnedArenas&&);
133
134 private:
135 bool fDDLRecording;
136 std::unique_ptr<SkArenaAlloc> fRecordTimeAllocator;
137 std::unique_ptr<GrSubRunAllocator> fRecordTimeSubRunAllocator;
138 };
139
140 GrRecordingContext(sk_sp<GrContextThreadSafeProxy>, bool ddlRecording);
141
142 bool init() override;
143
144 void abandonContext() override;
145
146 GrDrawingManager* drawingManager();
147
148 // There is no going back from this method. It should only be called to control the timing
149 // during abandon or destruction of the context.
150 void destroyDrawingManager();
151
arenas()152 Arenas arenas() { return fArenas.get(); }
153 // This entry point should only be used for DDL creation where we want the ops' lifetime to
154 // match that of the DDL.
155 OwnedArenas&& detachArenas();
156
proxyProvider()157 GrProxyProvider* proxyProvider() { return fProxyProvider.get(); }
proxyProvider() const158 const GrProxyProvider* proxyProvider() const { return fProxyProvider.get(); }
159
160 struct ProgramData {
161 ProgramData(std::unique_ptr<const GrProgramDesc>, const GrProgramInfo*);
162 ProgramData(ProgramData&&); // for SkTArray
163 ProgramData(const ProgramData&) = delete;
164 ~ProgramData();
165
descGrRecordingContext::ProgramData166 const GrProgramDesc& desc() const { return *fDesc; }
infoGrRecordingContext::ProgramData167 const GrProgramInfo& info() const { return *fInfo; }
168
169 private:
170 // TODO: store the GrProgramDescs in the 'fRecordTimeData' arena
171 std::unique_ptr<const GrProgramDesc> fDesc;
172 // The program infos should be stored in 'fRecordTimeData' so do not need to be ref
173 // counted or deleted in the destructor.
174 const GrProgramInfo* fInfo = nullptr;
175 };
176
177 // This entry point gives the recording context a chance to cache the provided
178 // programInfo. The DDL context takes this opportunity to store programInfos as a sidecar
179 // to the DDL.
recordProgramInfo(const GrProgramInfo*)180 virtual void recordProgramInfo(const GrProgramInfo*) {}
181 // This asks the recording context to return any programInfos it may have collected
182 // via the 'recordProgramInfo' call. It is up to the caller to ensure that the lifetime
183 // of the programInfos matches the intended use. For example, in DDL-record mode it
184 // is known that all the programInfos will have been allocated in an arena with the
185 // same lifetime at the DDL itself.
detachProgramData(SkTArray<ProgramData>*)186 virtual void detachProgramData(SkTArray<ProgramData>*) {}
187
188 GrTextBlobCache* getTextBlobCache();
189 const GrTextBlobCache* getTextBlobCache() const;
190
191 GrThreadSafeCache* threadSafeCache();
192 const GrThreadSafeCache* threadSafeCache() const;
193
194 /**
195 * Registers an object for flush-related callbacks. (See GrOnFlushCallbackObject.)
196 *
197 * NOTE: the drawing manager tracks this object as a raw pointer; it is up to the caller to
198 * ensure its lifetime is tied to that of the context.
199 */
200 void addOnFlushCallbackObject(GrOnFlushCallbackObject*);
201
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() const211 int numPathMasksGenerated() const { return fNumPathMasksGenerated; }
incNumPathMasksGenerated()212 void incNumPathMasksGenerated() { fNumPathMasksGenerated++; }
213
numPathMaskCacheHits() const214 int numPathMaskCacheHits() const { return fNumPathMaskCacheHits; }
incNumPathMasksCacheHits()215 void incNumPathMasksCacheHits() { fNumPathMaskCacheHits++; }
216
217 #if GR_TEST_UTILS
218 void dump(SkString* out) const;
219 void dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) const;
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*) const231 void dump(SkString*) const {}
dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) const232 void dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) const {}
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() const251 const Stats* stats() const { return &fStats; }
252 void dumpJSON(SkJSONWriter*) const;
253
254 protected:
255 // Delete last in case other objects call it during destruction.
256 std::unique_ptr<GrAuditTrail> fAuditTrail;
257
258 private:
259 OwnedArenas fArenas;
260
261 std::unique_ptr<GrDrawingManager> fDrawingManager;
262 std::unique_ptr<GrProxyProvider> fProxyProvider;
263
264 #if GR_TEST_UTILS
265 int fSuppressWarningMessages = 0;
266 #endif
267
268 using INHERITED = GrImageContext;
269 };
270
271 /**
272 * Safely cast a possibly-null base context to direct context.
273 */
GrAsDirectContext(GrContext_Base* base)274 static inline GrDirectContext* GrAsDirectContext(GrContext_Base* base) {
275 return base ? base->asDirectContext() : nullptr;
276 }
277
278 #endif
279