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