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