1 /* 2 * Copyright 2010 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 GrContext_DEFINED 9 #define GrContext_DEFINED 10 11 #include "include/core/SkMatrix.h" 12 #include "include/core/SkPathEffect.h" 13 #include "include/core/SkTypes.h" 14 #include "include/gpu/GrBackendSurface.h" 15 #include "include/gpu/GrContextOptions.h" 16 #include "include/gpu/GrGpuResource.h" 17 #include "include/private/GrRecordingContext.h" 18 19 // We shouldn't need this but currently Android is relying on this being include transitively. 20 #include "include/core/SkUnPreMultiply.h" 21 22 class GrAtlasManager; 23 class GrBackendSemaphore; 24 class GrCaps; 25 class GrContextPriv; 26 class GrContextThreadSafeProxy; 27 class GrFragmentProcessor; 28 struct GrGLInterface; 29 class GrGpu; 30 struct GrMockOptions; 31 class GrPath; 32 class GrRenderTargetContext; 33 class GrResourceCache; 34 class GrResourceProvider; 35 class GrSamplerState; 36 class GrSkSLFPFactoryCache; 37 class GrSurfaceProxy; 38 class GrSwizzle; 39 class GrTextContext; 40 class GrTextureProxy; 41 struct GrVkBackendContext; 42 43 class SkImage; 44 class SkSurfaceCharacterization; 45 class SkSurfaceProps; 46 class SkTaskGroup; 47 class SkTraceMemoryDump; 48 49 class SK_API GrContext : public GrRecordingContext { 50 public: 51 /** 52 * Creates a GrContext for a backend context. If no GrGLInterface is provided then the result of 53 * GrGLMakeNativeInterface() is used if it succeeds. 54 */ 55 static sk_sp<GrContext> MakeGL(sk_sp<const GrGLInterface>, const GrContextOptions&); 56 static sk_sp<GrContext> MakeGL(sk_sp<const GrGLInterface>); 57 static sk_sp<GrContext> MakeGL(const GrContextOptions&); 58 static sk_sp<GrContext> MakeGL(); 59 60 static sk_sp<GrContext> MakeVulkan(const GrVkBackendContext&, const GrContextOptions&); 61 static sk_sp<GrContext> MakeVulkan(const GrVkBackendContext&); 62 63 #ifdef SK_METAL 64 /** 65 * Makes a GrContext which uses Metal as the backend. The device parameter is an MTLDevice 66 * and queue is an MTLCommandQueue which should be used by the backend. These objects must 67 * have a ref on them which can be transferred to Ganesh which will release the ref when the 68 * GrContext is destroyed. 69 */ 70 static sk_sp<GrContext> MakeMetal(void* device, void* queue, const GrContextOptions& options); 71 static sk_sp<GrContext> MakeMetal(void* device, void* queue); 72 #endif 73 74 #ifdef SK_DAWN 75 static sk_sp<GrContext> MakeDawn(const dawn::Device& device, const GrContextOptions& options); 76 static sk_sp<GrContext> MakeDawn(const dawn::Device& device); 77 #endif 78 79 static sk_sp<GrContext> MakeMock(const GrMockOptions*, const GrContextOptions&); 80 static sk_sp<GrContext> MakeMock(const GrMockOptions*); 81 82 ~GrContext() override; 83 84 sk_sp<GrContextThreadSafeProxy> threadSafeProxy(); 85 86 /** 87 * The GrContext normally assumes that no outsider is setting state 88 * within the underlying 3D API's context/device/whatever. This call informs 89 * the context that the state was modified and it should resend. Shouldn't 90 * be called frequently for good performance. 91 * The flag bits, state, is dpendent on which backend is used by the 92 * context, either GL or D3D (possible in future). 93 */ 94 void resetContext(uint32_t state = kAll_GrBackendState); 95 96 /** 97 * If the backend is GrBackendApi::kOpenGL, then all texture unit/target combinations for which 98 * the GrContext has modified the bound texture will have texture id 0 bound. This does not 99 * flush the GrContext. Calling resetContext() does not change the set that will be bound 100 * to texture id 0 on the next call to resetGLTextureBindings(). After this is called 101 * all unit/target combinations are considered to have unmodified bindings until the GrContext 102 * subsequently modifies them (meaning if this is called twice in a row with no intervening 103 * GrContext usage then the second call is a no-op.) 104 */ 105 void resetGLTextureBindings(); 106 107 /** 108 * Abandons all GPU resources and assumes the underlying backend 3D API context is no longer 109 * usable. Call this if you have lost the associated GPU context, and thus internal texture, 110 * buffer, etc. references/IDs are now invalid. Calling this ensures that the destructors of the 111 * GrContext and any of its created resource objects will not make backend 3D API calls. Content 112 * rendered but not previously flushed may be lost. After this function is called all subsequent 113 * calls on the GrContext will fail or be no-ops. 114 * 115 * The typical use case for this function is that the underlying 3D context was lost and further 116 * API calls may crash. 117 */ 118 void abandonContext() override; 119 120 /** 121 * Returns true if the context was abandoned. 122 */ 123 using GrImageContext::abandoned; 124 125 /** 126 * This is similar to abandonContext() however the underlying 3D context is not yet lost and 127 * the GrContext will cleanup all allocated resources before returning. After returning it will 128 * assume that the underlying context may no longer be valid. 129 * 130 * The typical use case for this function is that the client is going to destroy the 3D context 131 * but can't guarantee that GrContext will be destroyed first (perhaps because it may be ref'ed 132 * elsewhere by either the client or Skia objects). 133 */ 134 virtual void releaseResourcesAndAbandonContext(); 135 136 /////////////////////////////////////////////////////////////////////////// 137 // Resource Cache 138 139 /** 140 * Return the current GPU resource cache limits. 141 * 142 * @param maxResources If non-null, returns maximum number of resources that 143 * can be held in the cache. 144 * @param maxResourceBytes If non-null, returns maximum number of bytes of 145 * video memory that can be held in the cache. 146 */ 147 void getResourceCacheLimits(int* maxResources, size_t* maxResourceBytes) const; 148 149 /** 150 * Gets the current GPU resource cache usage. 151 * 152 * @param resourceCount If non-null, returns the number of resources that are held in the 153 * cache. 154 * @param maxResourceBytes If non-null, returns the total number of bytes of video memory held 155 * in the cache. 156 */ 157 void getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const; 158 159 /** 160 * Gets the number of bytes in the cache consumed by purgeable (e.g. unlocked) resources. 161 */ 162 size_t getResourceCachePurgeableBytes() const; 163 164 /** 165 * Specify the GPU resource cache limits. If the current cache exceeds either 166 * of these, it will be purged (LRU) to keep the cache within these limits. 167 * 168 * @param maxResources The maximum number of resources that can be held in 169 * the cache. 170 * @param maxResourceBytes The maximum number of bytes of video memory 171 * that can be held in the cache. 172 */ 173 void setResourceCacheLimits(int maxResources, size_t maxResourceBytes); 174 175 /** 176 * Frees GPU created by the context. Can be called to reduce GPU memory 177 * pressure. 178 */ 179 virtual void freeGpuResources(); 180 181 /** 182 * Purge GPU resources that haven't been used in the past 'msNotUsed' milliseconds or are 183 * otherwise marked for deletion, regardless of whether the context is under budget. 184 */ 185 void performDeferredCleanup(std::chrono::milliseconds msNotUsed); 186 187 // Temporary compatibility API for Android. purgeResourcesNotUsedInMs(std::chrono::milliseconds msNotUsed)188 void purgeResourcesNotUsedInMs(std::chrono::milliseconds msNotUsed) { 189 this->performDeferredCleanup(msNotUsed); 190 } 191 192 /** 193 * Purge unlocked resources from the cache until the the provided byte count has been reached 194 * or we have purged all unlocked resources. The default policy is to purge in LRU order, but 195 * can be overridden to prefer purging scratch resources (in LRU order) prior to purging other 196 * resource types. 197 * 198 * @param maxBytesToPurge the desired number of bytes to be purged. 199 * @param preferScratchResources If true scratch resources will be purged prior to other 200 * resource types. 201 */ 202 void purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources); 203 204 /** 205 * This entry point is intended for instances where an app has been backgrounded or 206 * suspended. 207 * If 'scratchResourcesOnly' is true all unlocked scratch resources will be purged but the 208 * unlocked resources with persistent data will remain. If 'scratchResourcesOnly' is false 209 * then all unlocked resources will be purged. 210 * In either case, after the unlocked resources are purged a separate pass will be made to 211 * ensure that resource usage is under budget (i.e., even if 'scratchResourcesOnly' is true 212 * some resources with persistent data may be purged to be under budget). 213 * 214 * @param scratchResourcesOnly If true only unlocked scratch resources will be purged prior 215 * enforcing the budget requirements. 216 */ 217 void purgeUnlockedResources(bool scratchResourcesOnly); 218 void purgeUnlockedResourcesByTag(bool scratchResourcesOnly, const GrGpuResourceTag tag); purgeUnlockAndSafeCacheGpuResources()219 void purgeUnlockAndSafeCacheGpuResources() { 220 return; 221 } 222 223 /** 224 * Gets the maximum supported texture size. 225 */ 226 int maxTextureSize() const; 227 228 /** 229 * Gets the maximum supported render target size. 230 */ 231 int maxRenderTargetSize() const; 232 233 /** 234 * Can a SkImage be created with the given color type. 235 */ 236 bool colorTypeSupportedAsImage(SkColorType) const; 237 238 /** 239 * Can a SkSurface be created with the given color type. To check whether MSAA is supported 240 * use maxSurfaceSampleCountForColorType(). 241 */ colorTypeSupportedAsSurface(SkColorType colorType)242 bool colorTypeSupportedAsSurface(SkColorType colorType) const { 243 return this->maxSurfaceSampleCountForColorType(colorType) > 0; 244 } 245 246 /** 247 * Gets the maximum supported sample count for a color type. 1 is returned if only non-MSAA 248 * rendering is supported for the color type. 0 is returned if rendering to this color type 249 * is not supported at all. 250 */ 251 int maxSurfaceSampleCountForColorType(SkColorType) const; 252 253 /////////////////////////////////////////////////////////////////////////// 254 // Misc. 255 256 257 /** 258 * Inserts a list of GPU semaphores that the current GPU-backed API must wait on before 259 * executing any more commands on the GPU. Skia will take ownership of the underlying semaphores 260 * and delete them once they have been signaled and waited on. If this call returns false, then 261 * the GPU back-end will not wait on any passed in semaphores, and the client will still own the 262 * semaphores. 263 */ 264 bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores); 265 266 /** 267 * Call to ensure all drawing to the context has been issued to the underlying 3D API. 268 */ flush()269 void flush() { 270 this->flush(GrFlushInfo(), GrPrepareForExternalIORequests()); 271 } 272 273 /** 274 * Call to ensure all drawing to the context has been issued to the underlying 3D API. 275 * 276 * If this call returns GrSemaphoresSubmitted::kNo, the GPU backend will not have created or 277 * added any semaphores to signal on the GPU. Thus the client should not have the GPU wait on 278 * any of the semaphores passed in with the GrFlushInfo. However, any pending commands to the 279 * context will still be flushed. It should be emphasized that a return value of 280 * GrSemaphoresSubmitted::kNo does not mean the flush did not happen. It simply means there were 281 * no semaphores submitted to the GPU. A caller should only take this as a failure if they 282 * passed in semaphores to be submitted. 283 */ flush(const GrFlushInfo & info)284 GrSemaphoresSubmitted flush(const GrFlushInfo& info) { 285 return this->flush(info, GrPrepareForExternalIORequests()); 286 } 287 288 /** 289 * Call to ensure all drawing to the context has been issued to the underlying 3D API. 290 * 291 * If this call returns GrSemaphoresSubmitted::kNo, the GPU backend will not have created or 292 * added any semaphores to signal on the GPU. Thus the client should not have the GPU wait on 293 * any of the semaphores passed in with the GrFlushInfo. However, any pending commands to the 294 * context will still be flushed. It should be emphasized that a return value of 295 * GrSemaphoresSubmitted::kNo does not mean the flush did not happen. It simply means there were 296 * no semaphores submitted to the GPU. A caller should only take this as a failure if they 297 * passed in semaphores to be submitted. 298 * 299 * If the GrPrepareForExternalIORequests contains valid gpu backed SkSurfaces or SkImages, Skia 300 * will put the underlying backend objects into a state that is ready for external uses. See 301 * declaration of GrPreopareForExternalIORequests for more details. 302 */ 303 GrSemaphoresSubmitted flush(const GrFlushInfo&, const GrPrepareForExternalIORequests&); 304 305 /** 306 * Deprecated. 307 */ 308 GrSemaphoresSubmitted flush(GrFlushFlags flags, int numSemaphores, 309 GrBackendSemaphore signalSemaphores[], 310 GrGpuFinishedProc finishedProc = nullptr, 311 GrGpuFinishedContext finishedContext = nullptr) { 312 GrFlushInfo info; 313 info.fFlags = flags; 314 info.fNumSemaphores = numSemaphores; 315 info.fSignalSemaphores = signalSemaphores; 316 info.fFinishedProc = finishedProc; 317 info.fFinishedContext = finishedContext; 318 return this->flush(info); 319 } 320 321 /** 322 * Deprecated. 323 */ flushAndSignalSemaphores(int numSemaphores,GrBackendSemaphore signalSemaphores[])324 GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores, 325 GrBackendSemaphore signalSemaphores[]) { 326 GrFlushInfo info; 327 info.fNumSemaphores = numSemaphores; 328 info.fSignalSemaphores = signalSemaphores; 329 return this->flush(info); 330 } 331 332 /** 333 * Checks whether any asynchronous work is complete and if so calls related callbacks. 334 */ 335 void checkAsyncWorkCompletion(); 336 337 // Provides access to functions that aren't part of the public API. 338 GrContextPriv priv(); 339 const GrContextPriv priv() const; 340 341 /** Enumerates all cached GPU resources and dumps their memory to traceMemoryDump. */ 342 // Chrome is using this! 343 void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const; 344 void dumpMemoryStatisticsByTag(SkTraceMemoryDump* traceMemoryDump, GrGpuResourceTag tag) const; 345 346 bool supportsDistanceFieldText() const; 347 348 void storeVkPipelineCacheData(); 349 350 static size_t ComputeTextureSize(SkColorType type, int width, int height, GrMipMapped, 351 bool useNextPow2 = false); 352 353 /* 354 * Retrieve the default GrBackendFormat for a given SkColorType and renderability. 355 * It is guaranteed that this backend format will be the one used by the following 356 * SkColorType and SkSurfaceCharacterization-based createBackendTexture methods. 357 * 358 * The caller should check that the returned format is valid. 359 */ defaultBackendFormat(SkColorType ct,GrRenderable renderable)360 GrBackendFormat defaultBackendFormat(SkColorType ct, GrRenderable renderable) const { 361 return INHERITED::defaultBackendFormat(ct, renderable); 362 } 363 364 /* 365 * The explicitly allocated backend texture API allows clients to use Skia to create backend 366 * objects outside of Skia proper (i.e., Skia's caching system will not know about them.) 367 * 368 * It is the client's responsibility to delete all these objects (using deleteBackendTexture) 369 * before deleting the GrContext used to create them. Additionally, clients should only 370 * delete these objects on the thread for which that GrContext is active. 371 * 372 * The client is responsible for ensuring synchronization between different uses 373 * of the backend object (i.e., wrapping it in a surface, rendering to it, deleting the 374 * surface, rewrapping it in a image and drawing the image will require explicit 375 * sychronization on the client's part). 376 */ 377 378 // If possible, create an uninitialized backend texture. The client should ensure that the 379 // returned backend texture is valid. 380 // For the Vulkan backend the layout of the created VkImage will be: 381 // VK_IMAGE_LAYOUT_UNDEFINED. 382 GrBackendTexture createBackendTexture(int width, int height, 383 const GrBackendFormat&, 384 GrMipMapped, 385 GrRenderable, 386 GrProtected = GrProtected::kNo); 387 388 // If possible, create an uninitialized backend texture. The client should ensure that the 389 // returned backend texture is valid. 390 // If successful, the created backend texture will be compatible with the provided 391 // SkColorType. 392 // For the Vulkan backend the layout of the created VkImage will be: 393 // VK_IMAGE_LAYOUT_UNDEFINED. 394 GrBackendTexture createBackendTexture(int width, int height, 395 SkColorType, 396 GrMipMapped, 397 GrRenderable, 398 GrProtected = GrProtected::kNo); 399 400 401 // If possible, create an uninitialized backend texture that is compatible with the 402 // provided characterization. The client should ensure that the returned backend texture 403 // is valid. 404 // For the Vulkan backend the layout of the created VkImage will be: 405 // VK_IMAGE_LAYOUT_UNDEFINED. 406 GrBackendTexture createBackendTexture(const SkSurfaceCharacterization& characterization); 407 408 // If possible, create a backend texture initialized to a particular color. The client should 409 // ensure that the returned backend texture is valid. 410 // For the Vulkan backend the layout of the created VkImage will be: 411 // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL if renderable is kNo 412 // and VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL if renderable is kYes 413 GrBackendTexture createBackendTexture(int width, int height, 414 const GrBackendFormat&, 415 const SkColor4f& color, 416 GrMipMapped, 417 GrRenderable, 418 GrProtected = GrProtected::kNo); 419 420 // If possible, create a backend texture initialized to a particular color. The client should 421 // ensure that the returned backend texture is valid. 422 // If successful, the created backend texture will be compatible with the provided 423 // SkColorType. 424 // For the Vulkan backend the layout of the created VkImage will be: 425 // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL if renderable is kNo 426 // and VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL if renderable is kYes 427 GrBackendTexture createBackendTexture(int width, int height, 428 SkColorType, 429 const SkColor4f& color, 430 GrMipMapped, 431 GrRenderable, 432 GrProtected = GrProtected::kNo); 433 434 // If possible, create a backend texture initialized to a particular color that is 435 // compatible with the provided characterization. The client should ensure that the 436 // returned backend texture is valid. 437 // For the Vulkan backend the layout of the created VkImage will be: 438 // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 439 GrBackendTexture createBackendTexture(const SkSurfaceCharacterization& characterization, 440 const SkColor4f& color); 441 442 void deleteBackendTexture(GrBackendTexture); 443 444 #ifdef SK_ENABLE_DUMP_GPU 445 /** Returns a string with detailed information about the context & GPU, in JSON format. */ 446 SkString dump() const; 447 #endif 448 449 450 /** 451 * Set current resource tag for gpu cache recycle. 452 */ 453 void setCurrentGrResourceTag(const GrGpuResourceTag tag); 454 455 /** 456 * Get current resource tag for gpu cache recycle. 457 */ 458 GrGpuResourceTag getCurrentGrResourceTag() const; 459 460 /** 461 * Releases GrGpuResource objects and removes them from the cache by tag. 462 */ 463 void releaseByTag(const GrGpuResourceTag tag); 464 465 protected: 466 GrContext(GrBackendApi, const GrContextOptions&, int32_t contextID = SK_InvalidGenID); 467 468 bool init(sk_sp<const GrCaps>, sk_sp<GrSkSLFPFactoryCache>) override; 469 asDirectContext()470 GrContext* asDirectContext() override { return this; } 471 472 virtual GrAtlasManager* onGetAtlasManager() = 0; 473 474 sk_sp<GrContextThreadSafeProxy> fThreadSafeProxy; 475 476 private: 477 // fTaskGroup must appear before anything that uses it (e.g. fGpu), so that it is destroyed 478 // after all of its users. Clients of fTaskGroup will generally want to ensure that they call 479 // wait() on it as they are being destroyed, to avoid the possibility of pending tasks being 480 // invoked after objects they depend upon have already been destroyed. 481 std::unique_ptr<SkTaskGroup> fTaskGroup; 482 sk_sp<GrGpu> fGpu; 483 GrResourceCache* fResourceCache; 484 GrResourceProvider* fResourceProvider; 485 486 bool fDidTestPMConversions; 487 // true if the PM/UPM conversion succeeded; false otherwise 488 bool fPMUPMConversionsRoundTrip; 489 490 GrContextOptions::PersistentCache* fPersistentCache; 491 GrContextOptions::ShaderErrorHandler* fShaderErrorHandler; 492 493 // TODO: have the GrClipStackClip use renderTargetContexts and rm this friending 494 friend class GrContextPriv; 495 496 /** 497 * These functions create premul <-> unpremul effects, using the specialized round-trip effects 498 * from GrConfigConversionEffect. 499 */ 500 std::unique_ptr<GrFragmentProcessor> createPMToUPMEffect(std::unique_ptr<GrFragmentProcessor>); 501 std::unique_ptr<GrFragmentProcessor> createUPMToPMEffect(std::unique_ptr<GrFragmentProcessor>); 502 503 typedef GrRecordingContext INHERITED; 504 }; 505 506 #endif 507