• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ContextID()190         ContextID() : fID(SK_InvalidUniqueID) {}
191 
192         bool operator==(const ContextID& that) const { return fID == that.fID; }
193         bool operator!=(const ContextID& that) const { return !(*this == that); }
194 
makeInvalid()195         void makeInvalid() { fID = SK_InvalidUniqueID; }
isValid()196         bool isValid() const { return fID != SK_InvalidUniqueID; }
197 
198     private:
ContextID(uint32_t id)199         constexpr ContextID(uint32_t id) : fID(id) {}
200         uint32_t fID;
201     };
202 
contextID()203     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 
singleOwner()227     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     std::unique_ptr<Recorder> makeInternalRecorder() const;
236 
237     template <typename SrcPixels> struct AsyncParams;
238 
239     template <typename ReadFn, typename... ExtraArgs>
240     void asyncRescaleAndReadImpl(ReadFn Context::* asyncRead,
241                                  SkImage::RescaleGamma rescaleGamma,
242                                  SkImage::RescaleMode rescaleMode,
243                                  const AsyncParams<SkImage>&,
244                                  ExtraArgs...);
245 
246     // Recorder is optional and will be used if drawing operations are required. If no Recorder is
247     // provided but drawing operations are needed, a new Recorder will be created automatically.
248     void asyncReadPixels(std::unique_ptr<Recorder>, const AsyncParams<SkImage>&);
249     void asyncReadPixelsYUV420(std::unique_ptr<Recorder>,
250                                const AsyncParams<SkImage>&,
251                                SkYUVColorSpace);
252 
253     // Like asyncReadPixels() except it performs no fallbacks, and requires that the texture be
254     // readable. However, the texture does not need to be sampleable.
255     void asyncReadTexture(std::unique_ptr<Recorder>,
256                           const AsyncParams<TextureProxy>&,
257                           const SkColorInfo& srcColorInfo);
258 
259     // Inserts a texture to buffer transfer task, used by asyncReadPixels methods. If the
260     // Recorder is non-null, tasks will be added to the Recorder's list; otherwise the transfer
261     // tasks will be added to the queue manager directly.
262     PixelTransferResult transferPixels(Recorder*,
263                                        const TextureProxy* srcProxy,
264                                        const SkColorInfo& srcColorInfo,
265                                        const SkColorInfo& dstColorInfo,
266                                        const SkIRect& srcRect);
267 
268     // If the recorder is non-null, it will be snapped and inserted with the assumption that the
269     // copy tasks (and possibly preparatory draw tasks) have already been added to the Recording.
270     void finalizeAsyncReadPixels(std::unique_ptr<Recorder>,
271                                  SkSpan<PixelTransferResult>,
272                                  SkImage::ReadPixelsCallback callback,
273                                  SkImage::ReadPixelsContext callbackContext);
274 
275     sk_sp<SharedContext> fSharedContext;
276     std::unique_ptr<ResourceProvider> fResourceProvider;
277     std::unique_ptr<QueueManager> fQueueManager;
278     std::unique_ptr<ClientMappedBufferManager> fMappedBufferManager;
279 
280     // In debug builds we guard against improper thread handling. This guard is passed to the
281     // ResourceCache for the Context.
282     mutable SingleOwner fSingleOwner;
283 
284 #if defined(GRAPHITE_TEST_UTILS)
285     // In test builds a Recorder may track the Context that was used to create it.
286     bool fStoreContextRefInRecorder = false;
287     // If this tracking is on, to allow the client to safely delete this Context or its Recorders
288     // in any order we must also track the Recorders created here.
289     std::vector<Recorder*> fTrackedRecorders;
290 #endif
291 
292     // Needed for MessageBox handling
293     const ContextID fContextID;
294 };
295 
296 } // namespace skgpu::graphite
297 
298 #endif // skgpu_graphite_Context_DEFINED
299