/src/skia/include/gpu/graphite/Context.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2021 Google LLC |
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 skgpu_graphite_Context_DEFINED |
9 | | #define skgpu_graphite_Context_DEFINED |
10 | | |
11 | | #include "include/core/SkImage.h" |
12 | | #include "include/core/SkRefCnt.h" |
13 | | #include "include/core/SkShader.h" |
14 | | #include "include/gpu/graphite/ContextOptions.h" |
15 | | #include "include/gpu/graphite/GraphiteTypes.h" |
16 | | #include "include/gpu/graphite/Recorder.h" |
17 | | #include "include/private/base/SingleOwner.h" |
18 | | |
19 | | #include <chrono> |
20 | | #include <functional> |
21 | | #include <memory> |
22 | | |
23 | | class SkColorSpace; |
24 | | class SkRuntimeEffect; |
25 | | class SkTraceMemoryDump; |
26 | | |
27 | | namespace skgpu::graphite { |
28 | | |
29 | | class BackendTexture; |
30 | | class Buffer; |
31 | | class ClientMappedBufferManager; |
32 | | class Context; |
33 | | class ContextPriv; |
34 | | class GlobalCache; |
35 | | class PaintOptions; |
36 | | class PlotUploadTracker; |
37 | | class QueueManager; |
38 | | class Recording; |
39 | | class ResourceProvider; |
40 | | class SharedContext; |
41 | | class TextureProxy; |
42 | | |
43 | | class SK_API Context final { |
44 | | public: |
45 | | Context(const Context&) = delete; |
46 | | Context(Context&&) = delete; |
47 | | Context& operator=(const Context&) = delete; |
48 | | Context& operator=(Context&&) = delete; |
49 | | |
50 | | ~Context(); |
51 | | |
52 | | BackendApi backend() const; |
53 | | |
54 | | std::unique_ptr<Recorder> makeRecorder(const RecorderOptions& = {}); |
55 | | |
56 | | bool insertRecording(const InsertRecordingInfo&); |
57 | | bool submit(SyncToCpu = SyncToCpu::kNo); |
58 | | |
59 | | /** Returns true if there is work that was submitted to the GPU that has not finished. */ |
60 | | bool hasUnfinishedGpuWork() const; |
61 | | |
62 | | void asyncRescaleAndReadPixels(const SkImage* image, |
63 | | const SkImageInfo& dstImageInfo, |
64 | | const SkIRect& srcRect, |
65 | | SkImage::RescaleGamma rescaleGamma, |
66 | | SkImage::RescaleMode rescaleMode, |
67 | | SkImage::ReadPixelsCallback callback, |
68 | | SkImage::ReadPixelsContext context); |
69 | | |
70 | | void asyncRescaleAndReadPixels(const SkSurface* surface, |
71 | | const SkImageInfo& dstImageInfo, |
72 | | const SkIRect& srcRect, |
73 | | SkImage::RescaleGamma rescaleGamma, |
74 | | SkImage::RescaleMode rescaleMode, |
75 | | SkImage::ReadPixelsCallback callback, |
76 | | SkImage::ReadPixelsContext context); |
77 | | |
78 | | void asyncRescaleAndReadPixelsYUV420(const SkImage*, |
79 | | SkYUVColorSpace yuvColorSpace, |
80 | | sk_sp<SkColorSpace> dstColorSpace, |
81 | | const SkIRect& srcRect, |
82 | | const SkISize& dstSize, |
83 | | SkImage::RescaleGamma rescaleGamma, |
84 | | SkImage::RescaleMode rescaleMode, |
85 | | SkImage::ReadPixelsCallback callback, |
86 | | SkImage::ReadPixelsContext context); |
87 | | |
88 | | void asyncRescaleAndReadPixelsYUV420(const SkSurface*, |
89 | | SkYUVColorSpace yuvColorSpace, |
90 | | sk_sp<SkColorSpace> dstColorSpace, |
91 | | const SkIRect& srcRect, |
92 | | const SkISize& dstSize, |
93 | | SkImage::RescaleGamma rescaleGamma, |
94 | | SkImage::RescaleMode rescaleMode, |
95 | | SkImage::ReadPixelsCallback callback, |
96 | | SkImage::ReadPixelsContext context); |
97 | | |
98 | | void asyncRescaleAndReadPixelsYUVA420(const SkImage*, |
99 | | SkYUVColorSpace yuvColorSpace, |
100 | | sk_sp<SkColorSpace> dstColorSpace, |
101 | | const SkIRect& srcRect, |
102 | | const SkISize& dstSize, |
103 | | SkImage::RescaleGamma rescaleGamma, |
104 | | SkImage::RescaleMode rescaleMode, |
105 | | SkImage::ReadPixelsCallback callback, |
106 | | SkImage::ReadPixelsContext context); |
107 | | |
108 | | void asyncRescaleAndReadPixelsYUVA420(const SkSurface*, |
109 | | SkYUVColorSpace yuvColorSpace, |
110 | | sk_sp<SkColorSpace> dstColorSpace, |
111 | | const SkIRect& srcRect, |
112 | | const SkISize& dstSize, |
113 | | SkImage::RescaleGamma rescaleGamma, |
114 | | SkImage::RescaleMode rescaleMode, |
115 | | SkImage::ReadPixelsCallback callback, |
116 | | SkImage::ReadPixelsContext context); |
117 | | |
118 | | /** |
119 | | * Checks whether any asynchronous work is complete and if so calls related callbacks. |
120 | | */ |
121 | | void checkAsyncWorkCompletion(); |
122 | | |
123 | | /** |
124 | | * Called to delete the passed in BackendTexture. This should only be called if the |
125 | | * BackendTexture was created by calling Recorder::createBackendTexture on a Recorder created |
126 | | * from this Context. If the BackendTexture is not valid or does not match the BackendApi of the |
127 | | * Context then nothing happens. |
128 | | * |
129 | | * Otherwise this will delete/release the backend object that is wrapped in the BackendTexture. |
130 | | * The BackendTexture will be reset to an invalid state and should not be used again. |
131 | | */ |
132 | | void deleteBackendTexture(const BackendTexture&); |
133 | | |
134 | | /** |
135 | | * Frees GPU resources created and held by the Context. Can be called to reduce GPU memory |
136 | | * pressure. Any resources that are still in use (e.g. being used by work submitted to the GPU) |
137 | | * will not be deleted by this call. If the caller wants to make sure all resources are freed, |
138 | | * then they should first make sure to submit and wait on any outstanding work. |
139 | | */ |
140 | | void freeGpuResources(); |
141 | | |
142 | | /** |
143 | | * Purge GPU resources on the Context that haven't been used in the past 'msNotUsed' |
144 | | * milliseconds or are otherwise marked for deletion, regardless of whether the context is under |
145 | | * budget. |
146 | | */ |
147 | | void performDeferredCleanup(std::chrono::milliseconds msNotUsed); |
148 | | |
149 | | /** |
150 | | * Returns the number of bytes of the Context's gpu memory cache budget that are currently in |
151 | | * use. |
152 | | */ |
153 | | size_t currentBudgetedBytes() const; |
154 | | |
155 | | /** |
156 | | * Returns the size of Context's gpu memory cache budget in bytes. |
157 | | */ |
158 | | size_t maxBudgetedBytes() const; |
159 | | |
160 | | /** |
161 | | * Enumerates all cached GPU resources owned by the Context and dumps their memory to |
162 | | * traceMemoryDump. |
163 | | */ |
164 | | void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const; |
165 | | |
166 | | /** |
167 | | * Returns true if the backend-specific context has gotten into an unrecoverarble, lost state |
168 | | * (e.g. if we've gotten a VK_ERROR_DEVICE_LOST in the Vulkan backend). |
169 | | */ |
170 | | bool isDeviceLost() const; |
171 | | |
172 | | /** |
173 | | * Returns the maximum texture dimension supported by the underlying backend. |
174 | | */ |
175 | | int maxTextureSize() const; |
176 | | |
177 | | /* |
178 | | * Does this context support protected content? |
179 | | */ |
180 | | bool supportsProtectedContent() const; |
181 | | |
182 | | // Provides access to functions that aren't part of the public API. |
183 | | ContextPriv priv(); |
184 | | const ContextPriv priv() const; // NOLINT(readability-const-return-type) |
185 | | |
186 | | class ContextID { |
187 | | public: |
188 | | static Context::ContextID Next(); |
189 | | |
190 | 0 | ContextID() : fID(SK_InvalidUniqueID) {} |
191 | | |
192 | 0 | bool operator==(const ContextID& that) const { return fID == that.fID; } |
193 | 0 | bool operator!=(const ContextID& that) const { return !(*this == that); } |
194 | | |
195 | 0 | void makeInvalid() { fID = SK_InvalidUniqueID; } |
196 | 0 | bool isValid() const { return fID != SK_InvalidUniqueID; } |
197 | | |
198 | | private: |
199 | 0 | constexpr ContextID(uint32_t id) : fID(id) {} |
200 | | uint32_t fID; |
201 | | }; |
202 | | |
203 | 0 | ContextID contextID() const { return fContextID; } |
204 | | |
205 | | protected: |
206 | | Context(sk_sp<SharedContext>, std::unique_ptr<QueueManager>, const ContextOptions&); |
207 | | |
208 | | private: |
209 | | friend class ContextPriv; |
210 | | friend class ContextCtorAccessor; |
211 | | |
212 | | struct PixelTransferResult { |
213 | | using ConversionFn = void(void* dst, const void* mappedBuffer); |
214 | | // If null then the transfer could not be performed. Otherwise this buffer will contain |
215 | | // the pixel data when the transfer is complete. |
216 | | sk_sp<Buffer> fTransferBuffer; |
217 | | // Size of the read. |
218 | | SkISize fSize; |
219 | | // RowBytes for transfer buffer data |
220 | | size_t fRowBytes; |
221 | | // If this is null then the transfer buffer will contain the data in the requested |
222 | | // color type. Otherwise, when the transfer is done this must be called to convert |
223 | | // from the transfer buffer's color type to the requested color type. |
224 | | std::function<ConversionFn> fPixelConverter; |
225 | | }; |
226 | | |
227 | 0 | SingleOwner* singleOwner() const { return &fSingleOwner; } |
228 | | |
229 | | // Must be called in Make() to handle one-time GPU setup operations that can possibly fail and |
230 | | // require Context::Make() to return a nullptr. |
231 | | bool finishInitialization(); |
232 | | |
233 | | void checkForFinishedWork(SyncToCpu); |
234 | | |
235 | | void asyncRescaleAndReadPixelsYUV420Impl(const SkImage*, |
236 | | SkYUVColorSpace yuvColorSpace, |
237 | | bool readAlpha, |
238 | | sk_sp<SkColorSpace> dstColorSpace, |
239 | | const SkIRect& srcRect, |
240 | | const SkISize& dstSize, |
241 | | SkImage::RescaleGamma rescaleGamma, |
242 | | SkImage::RescaleMode rescaleMode, |
243 | | SkImage::ReadPixelsCallback callback, |
244 | | SkImage::ReadPixelsContext context); |
245 | | |
246 | | void asyncReadPixels(const TextureProxy* textureProxy, |
247 | | const SkImageInfo& srcImageInfo, |
248 | | const SkColorInfo& dstColorInfo, |
249 | | const SkIRect& srcRect, |
250 | | SkImage::ReadPixelsCallback callback, |
251 | | SkImage::ReadPixelsContext context); |
252 | | |
253 | | void asyncReadPixelsYUV420(Recorder*, |
254 | | const SkImage*, |
255 | | SkYUVColorSpace yuvColorSpace, |
256 | | bool readAlpha, |
257 | | const SkIRect& srcRect, |
258 | | SkImage::ReadPixelsCallback callback, |
259 | | SkImage::ReadPixelsContext context); |
260 | | |
261 | | void finalizeAsyncReadPixels(SkSpan<PixelTransferResult>, |
262 | | SkImage::ReadPixelsCallback callback, |
263 | | SkImage::ReadPixelsContext callbackContext); |
264 | | |
265 | | // Inserts a texture to buffer transfer task, used by asyncReadPixels methods |
266 | | PixelTransferResult transferPixels(const TextureProxy*, |
267 | | const SkImageInfo& srcImageInfo, |
268 | | const SkColorInfo& dstColorInfo, |
269 | | const SkIRect& srcRect); |
270 | | |
271 | | sk_sp<SharedContext> fSharedContext; |
272 | | std::unique_ptr<ResourceProvider> fResourceProvider; |
273 | | std::unique_ptr<QueueManager> fQueueManager; |
274 | | std::unique_ptr<ClientMappedBufferManager> fMappedBufferManager; |
275 | | |
276 | | // In debug builds we guard against improper thread handling. This guard is passed to the |
277 | | // ResourceCache for the Context. |
278 | | mutable SingleOwner fSingleOwner; |
279 | | |
280 | | #if defined(GRAPHITE_TEST_UTILS) |
281 | | // In test builds a Recorder may track the Context that was used to create it. |
282 | | bool fStoreContextRefInRecorder = false; |
283 | | // If this tracking is on, to allow the client to safely delete this Context or its Recorders |
284 | | // in any order we must also track the Recorders created here. |
285 | | std::vector<Recorder*> fTrackedRecorders; |
286 | | #endif |
287 | | |
288 | | // Needed for MessageBox handling |
289 | | const ContextID fContextID; |
290 | | }; |
291 | | |
292 | | } // namespace skgpu::graphite |
293 | | |
294 | | #endif // skgpu_graphite_Context_DEFINED |