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 "GrCaps.h" 12 #include "SkMatrix.h" 13 #include "SkPathEffect.h" 14 #include "SkTypes.h" 15 #include "../private/GrAuditTrail.h" 16 #include "../private/GrSingleOwner.h" 17 #include "GrContextOptions.h" 18 19 class GrAtlasGlyphCache; 20 class GrBackendFormat; 21 class GrBackendSemaphore; 22 class GrContextPriv; 23 class GrContextThreadSafeProxy; 24 class GrDrawingManager; 25 struct GrDrawOpAtlasConfig; 26 class GrFragmentProcessor; 27 struct GrGLInterface; 28 class GrGpu; 29 class GrIndexBuffer; 30 struct GrMockOptions; 31 class GrOvalRenderer; 32 class GrPath; 33 class GrProxyProvider; 34 class GrRenderTargetContext; 35 class GrResourceEntry; 36 class GrResourceCache; 37 class GrResourceProvider; 38 class GrSamplerState; 39 class GrSurfaceProxy; 40 class GrSwizzle; 41 class GrTextBlobCache; 42 class GrTextContext; 43 class GrTextureProxy; 44 class GrVertexBuffer; 45 struct GrVkBackendContext; 46 47 class SkImage; 48 class SkSurfaceCharacterization; 49 class SkSurfaceProps; 50 class SkTaskGroup; 51 class SkTraceMemoryDump; 52 53 class SK_API GrContext : public SkRefCnt { 54 public: 55 /** 56 * Creates a GrContext for a backend context. 57 */ 58 static GrContext* Create(GrBackend, GrBackendContext, const GrContextOptions& options); 59 static GrContext* Create(GrBackend, GrBackendContext); 60 61 static sk_sp<GrContext> MakeGL(sk_sp<const GrGLInterface>, const GrContextOptions&); 62 static sk_sp<GrContext> MakeGL(sk_sp<const GrGLInterface>); 63 // Deprecated 64 static sk_sp<GrContext> MakeGL(const GrGLInterface*); 65 static sk_sp<GrContext> MakeGL(const GrGLInterface*, const GrContextOptions&); 66 67 #ifdef SK_VULKAN 68 static sk_sp<GrContext> MakeVulkan(sk_sp<const GrVkBackendContext>, const GrContextOptions&); 69 static sk_sp<GrContext> MakeVulkan(sk_sp<const GrVkBackendContext>); 70 #endif 71 72 #ifdef SK_METAL 73 /** 74 * Makes a GrContext which uses Metal as the backend. The device parameter is an MTLDevice 75 * and queue is an MTLCommandQueue which should be used by the backend. These objects must 76 * have a ref on them which can be transferred to Ganesh which will release the ref when the 77 * GrContext is destroyed. 78 */ 79 static sk_sp<GrContext> MakeMetal(void* device, void* queue, const GrContextOptions& options); 80 static sk_sp<GrContext> MakeMetal(void* device, void* queue); 81 #endif 82 83 static sk_sp<GrContext> MakeMock(const GrMockOptions*, const GrContextOptions&); 84 static sk_sp<GrContext> MakeMock(const GrMockOptions*); 85 86 virtual ~GrContext(); 87 88 sk_sp<GrContextThreadSafeProxy> threadSafeProxy(); 89 90 /** 91 * The GrContext normally assumes that no outsider is setting state 92 * within the underlying 3D API's context/device/whatever. This call informs 93 * the context that the state was modified and it should resend. Shouldn't 94 * be called frequently for good performance. 95 * The flag bits, state, is dpendent on which backend is used by the 96 * context, either GL or D3D (possible in future). 97 */ 98 void resetContext(uint32_t state = kAll_GrBackendState); 99 100 /** 101 * Callback function to allow classes to cleanup on GrContext destruction. 102 * The 'info' field is filled in with the 'info' passed to addCleanUp. 103 */ 104 typedef void (*PFCleanUpFunc)(const GrContext* context, void* info); 105 106 /** 107 * Add a function to be called from within GrContext's destructor. 108 * This gives classes a chance to free resources held on a per context basis. 109 * The 'info' parameter will be stored and passed to the callback function. 110 */ addCleanUp(PFCleanUpFunc cleanUp,void * info)111 void addCleanUp(PFCleanUpFunc cleanUp, void* info) { 112 CleanUpData* entry = fCleanUpData.push(); 113 114 entry->fFunc = cleanUp; 115 entry->fInfo = info; 116 } 117 118 /** 119 * Abandons all GPU resources and assumes the underlying backend 3D API context is no longer 120 * usable. Call this if you have lost the associated GPU context, and thus internal texture, 121 * buffer, etc. references/IDs are now invalid. Calling this ensures that the destructors of the 122 * GrContext and any of its created resource objects will not make backend 3D API calls. Content 123 * rendered but not previously flushed may be lost. After this function is called all subsequent 124 * calls on the GrContext will fail or be no-ops. 125 * 126 * The typical use case for this function is that the underlying 3D context was lost and further 127 * API calls may crash. 128 */ 129 void abandonContext(); 130 131 /** 132 * This is similar to abandonContext() however the underlying 3D context is not yet lost and 133 * the GrContext will cleanup all allocated resources before returning. After returning it will 134 * assume that the underlying context may no longer be valid. 135 * 136 * The typical use case for this function is that the client is going to destroy the 3D context 137 * but can't guarantee that GrContext will be destroyed first (perhaps because it may be ref'ed 138 * elsewhere by either the client or Skia objects). 139 */ 140 void releaseResourcesAndAbandonContext(); 141 142 /////////////////////////////////////////////////////////////////////////// 143 // Resource Cache 144 145 /** 146 * Return the current GPU resource cache limits. 147 * 148 * @param maxResources If non-null, returns maximum number of resources that 149 * can be held in the cache. 150 * @param maxResourceBytes If non-null, returns maximum number of bytes of 151 * video memory that can be held in the cache. 152 */ 153 void getResourceCacheLimits(int* maxResources, size_t* maxResourceBytes) const; 154 155 /** 156 * Gets the current GPU resource cache usage. 157 * 158 * @param resourceCount If non-null, returns the number of resources that are held in the 159 * cache. 160 * @param maxResourceBytes If non-null, returns the total number of bytes of video memory held 161 * in the cache. 162 */ 163 void getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const; 164 165 /** 166 * Gets the number of bytes in the cache consumed by purgeable (e.g. unlocked) resources. 167 */ 168 size_t getResourceCachePurgeableBytes() const; 169 170 /** 171 * Specify the GPU resource cache limits. If the current cache exceeds either 172 * of these, it will be purged (LRU) to keep the cache within these limits. 173 * 174 * @param maxResources The maximum number of resources that can be held in 175 * the cache. 176 * @param maxResourceBytes The maximum number of bytes of video memory 177 * that can be held in the cache. 178 */ 179 void setResourceCacheLimits(int maxResources, size_t maxResourceBytes); 180 181 /** 182 * Frees GPU created by the context. Can be called to reduce GPU memory 183 * pressure. 184 */ 185 void freeGpuResources(); 186 187 /** 188 * Purge all the unlocked resources from the cache. 189 * This entry point is mainly meant for timing texture uploads 190 * and is not defined in normal builds of Skia. 191 */ 192 void purgeAllUnlockedResources(); 193 194 /** 195 * Purge GPU resources that haven't been used in the past 'msNotUsed' milliseconds or are 196 * otherwise marked for deletion, regardless of whether the context is under budget. 197 */ 198 void performDeferredCleanup(std::chrono::milliseconds msNotUsed); 199 200 // Temporary compatibility API for Android. purgeResourcesNotUsedInMs(std::chrono::milliseconds msNotUsed)201 void purgeResourcesNotUsedInMs(std::chrono::milliseconds msNotUsed) { 202 this->performDeferredCleanup(msNotUsed); 203 } 204 205 /** 206 * Purge unlocked resources from the cache until the the provided byte count has been reached 207 * or we have purged all unlocked resources. The default policy is to purge in LRU order, but 208 * can be overridden to prefer purging scratch resources (in LRU order) prior to purging other 209 * resource types. 210 * 211 * @param maxBytesToPurge the desired number of bytes to be purged. 212 * @param preferScratchResources If true scratch resources will be purged prior to other 213 * resource types. 214 */ 215 void purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources); 216 217 /** Access the context capabilities */ caps()218 const GrCaps* caps() const { return fCaps.get(); } 219 220 /** 221 * Can a SkImage be created with the given color type. 222 */ 223 bool colorTypeSupportedAsImage(SkColorType) const; 224 225 /** 226 * Can a SkSurface be created with the given color type. To check whether MSAA is supported 227 * use maxSurfaceSampleCountForColorType(). 228 */ colorTypeSupportedAsSurface(SkColorType colorType)229 bool colorTypeSupportedAsSurface(SkColorType colorType) const { 230 return this->maxSurfaceSampleCountForColorType(colorType) > 0; 231 } 232 233 /** 234 * Gets the maximum supported sample count for a color type. 1 is returned if only non-MSAA 235 * rendering is supported for the color type. 0 is returned if rendering to this color type 236 * is not supported at all. 237 */ 238 int maxSurfaceSampleCountForColorType(SkColorType) const; 239 240 /* 241 * Create a new render target context backed by a deferred-style 242 * GrRenderTargetProxy. We guarantee that "asTextureProxy" will succeed for 243 * renderTargetContexts created via this entry point. 244 */ 245 sk_sp<GrRenderTargetContext> makeDeferredRenderTargetContext( 246 SkBackingFit fit, 247 int width, int height, 248 GrPixelConfig config, 249 sk_sp<SkColorSpace> colorSpace, 250 int sampleCnt = 1, 251 GrMipMapped = GrMipMapped::kNo, 252 GrSurfaceOrigin origin = kBottomLeft_GrSurfaceOrigin, 253 const SkSurfaceProps* surfaceProps = nullptr, 254 SkBudgeted = SkBudgeted::kYes); 255 /* 256 * This method will attempt to create a renderTargetContext that has, at least, the number of 257 * channels and precision per channel as requested in 'config' (e.g., A8 and 888 can be 258 * converted to 8888). It may also swizzle the channels (e.g., BGRA -> RGBA). 259 * SRGB-ness will be preserved. 260 */ 261 sk_sp<GrRenderTargetContext> makeDeferredRenderTargetContextWithFallback( 262 SkBackingFit fit, 263 int width, int height, 264 GrPixelConfig config, 265 sk_sp<SkColorSpace> colorSpace, 266 int sampleCnt = 1, 267 GrMipMapped = GrMipMapped::kNo, 268 GrSurfaceOrigin origin = kBottomLeft_GrSurfaceOrigin, 269 const SkSurfaceProps* surfaceProps = nullptr, 270 SkBudgeted budgeted = SkBudgeted::kYes); 271 272 /////////////////////////////////////////////////////////////////////////// 273 // Misc. 274 275 /** 276 * Call to ensure all drawing to the context has been issued to the underlying 3D API. 277 */ 278 void flush(); 279 280 /** 281 * Call to ensure all drawing to the context has been issued to the underlying 3D API. After 282 * issuing all commands, numSemaphore semaphores will be signaled by the gpu. The client passes 283 * in an array of numSemaphores GrBackendSemaphores. In general these GrBackendSemaphore's can 284 * be either initialized or not. If they are initialized, the backend uses the passed in 285 * semaphore. If it is not initialized, a new semaphore is created and the GrBackendSemaphore 286 * object is initialized with that semaphore. 287 * 288 * The client will own and be responsible for deleting the underlying semaphores that are stored 289 * and returned in initialized GrBackendSemaphore objects. The GrBackendSemaphore objects 290 * themselves can be deleted as soon as this function returns. 291 * 292 * If the backend API is OpenGL only uninitialized GrBackendSemaphores are supported. 293 * If the backend API is Vulkan either initialized or unitialized semaphores are supported. 294 * If unitialized, the semaphores which are created will be valid for use only with the VkDevice 295 * with which they were created. 296 * 297 * If this call returns GrSemaphoresSubmited::kNo, the GPU backend will not have created or 298 * added any semaphores to signal on the GPU. Thus the client should not have the GPU wait on 299 * any of the semaphores. However, any pending commands to the context will still be flushed. 300 */ 301 GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores, 302 GrBackendSemaphore signalSemaphores[]); 303 304 /** 305 * An ID associated with this context, guaranteed to be unique. 306 */ uniqueID()307 uint32_t uniqueID() { return fUniqueID; } 308 309 /////////////////////////////////////////////////////////////////////////// 310 // Functions intended for internal use only. 311 bool abandoned() const; 312 313 /** Reset GPU stats */ 314 void resetGpuStats() const ; 315 316 /** Prints cache stats to the string if GR_CACHE_STATS == 1. */ 317 void dumpCacheStats(SkString*) const; 318 void dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) const; 319 void printCacheStats() const; 320 321 /** Prints GPU stats to the string if GR_GPU_STATS == 1. */ 322 void dumpGpuStats(SkString*) const; 323 void dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) const; 324 void printGpuStats() const; 325 326 /** Returns a string with detailed information about the context & GPU, in JSON format. */ 327 SkString dump() const; 328 329 /** Specify the TextBlob cache limit. If the current cache exceeds this limit it will purge. 330 this is for testing only */ 331 void setTextBlobCacheLimit_ForTesting(size_t bytes); 332 333 /** Specify the sizes of the GrAtlasTextContext atlases. The configs pointer below should be 334 to an array of 3 entries */ 335 void setTextContextAtlasSizes_ForTesting(const GrDrawOpAtlasConfig* configs); 336 337 /** Enumerates all cached GPU resources and dumps their memory to traceMemoryDump. */ 338 void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const; 339 340 /** Get pointer to atlas texture for given mask format. Note that this wraps an 341 actively mutating texture in an SkImage. This could yield unexpected results 342 if it gets cached or used more generally. */ 343 sk_sp<SkImage> getFontAtlasImage_ForTesting(GrMaskFormat format, unsigned int index = 0); 344 getAuditTrail()345 GrAuditTrail* getAuditTrail() { return &fAuditTrail; } 346 getPersistentCache()347 GrContextOptions::PersistentCache* getPersistentCache() { return fPersistentCache; } 348 349 /** This is only useful for debug purposes */ 350 SkDEBUGCODE(GrSingleOwner* debugSingleOwner() const { return &fSingleOwner; } ) 351 352 // Provides access to functions that aren't part of the public API. 353 GrContextPriv contextPriv(); 354 const GrContextPriv contextPriv() const; 355 356 protected: 357 GrContext(GrContextThreadSafeProxy*); 358 GrContext(GrBackend); 359 360 private: 361 sk_sp<GrGpu> fGpu; 362 sk_sp<const GrCaps> fCaps; 363 GrResourceCache* fResourceCache; 364 GrResourceProvider* fResourceProvider; 365 GrProxyProvider* fProxyProvider; 366 367 sk_sp<GrContextThreadSafeProxy> fThreadSafeProxy; 368 369 GrAtlasGlyphCache* fAtlasGlyphCache; 370 std::unique_ptr<GrTextBlobCache> fTextBlobCache; 371 372 bool fDisableGpuYUVConversion; 373 bool fSharpenMipmappedTextures; 374 bool fDidTestPMConversions; 375 // true if the PM/UPM conversion succeeded; false otherwise 376 bool fPMUPMConversionsRoundTrip; 377 378 // In debug builds we guard against improper thread handling 379 // This guard is passed to the GrDrawingManager and, from there to all the 380 // GrRenderTargetContexts. It is also passed to the GrResourceProvider and SkGpuDevice. 381 mutable GrSingleOwner fSingleOwner; 382 383 std::unique_ptr<SkTaskGroup> fTaskGroup; 384 385 struct CleanUpData { 386 PFCleanUpFunc fFunc; 387 void* fInfo; 388 }; 389 390 SkTDArray<CleanUpData> fCleanUpData; 391 392 const uint32_t fUniqueID; 393 394 std::unique_ptr<GrDrawingManager> fDrawingManager; 395 396 GrAuditTrail fAuditTrail; 397 398 const GrBackend fBackend; 399 400 GrContextOptions::PersistentCache* fPersistentCache; 401 402 // TODO: have the GrClipStackClip use renderTargetContexts and rm this friending 403 friend class GrContextPriv; 404 405 bool init(const GrContextOptions&); // init must be called after either constructor. 406 407 /** 408 * These functions create premul <-> unpremul effects. If the second argument is 'true', they 409 * use the specialized round-trip effects from GrConfigConversionEffect, otherwise they 410 * create effects that do naive multiply or divide. 411 */ 412 std::unique_ptr<GrFragmentProcessor> createPMToUPMEffect(std::unique_ptr<GrFragmentProcessor>, 413 bool useConfigConversionEffect); 414 std::unique_ptr<GrFragmentProcessor> createUPMToPMEffect(std::unique_ptr<GrFragmentProcessor>, 415 bool useConfigConversionEffect); 416 417 /** 418 * Returns true if createPMtoUPMEffect and createUPMToPMEffect will succeed for non-sRGB 8888 419 * configs. In other words, did we find a pair of round-trip preserving conversion effects? 420 */ 421 bool validPMUPMConversionExists(); 422 423 /** 424 * A callback similar to the above for use by the TextBlobCache 425 * TODO move textblob draw calls below context so we can use the call above. 426 */ 427 static void TextBlobCacheOverBudgetCB(void* data); 428 429 typedef SkRefCnt INHERITED; 430 }; 431 432 /** 433 * Can be used to perform actions related to the generating GrContext in a thread safe manner. The 434 * proxy does not access the 3D API (e.g. OpenGL) that backs the generating GrContext. 435 */ 436 class GrContextThreadSafeProxy : public SkRefCnt { 437 public: matches(GrContext * context)438 bool matches(GrContext* context) const { return context->uniqueID() == fContextUniqueID; } 439 440 /** 441 * Create a surface characterization for a DDL that will be replayed into the GrContext 442 * that created this proxy. On failure the resulting characterization will be invalid (i.e., 443 * "!c.isValid()"). 444 * 445 * @param cacheMaxResourceBytes The max resource bytes limit that will be in effect when the 446 * DDL created with this characterization is replayed. 447 * Note: the contract here is that the DDL will be created as 448 * if it had a full 'cacheMaxResourceBytes' to use. If replayed 449 * into a GrContext that already has locked GPU memory, the 450 * replay can exceed the budget. To rephrase, all resource 451 * allocation decisions are made at record time and at playback 452 * time the budget limits will be ignored. 453 * @param ii The image info specifying properties of the SkSurface that 454 * the DDL created with this characterization will be replayed 455 * into. 456 * Note: Ganesh doesn't make use of the SkImageInfo's alphaType 457 * @param backendFormat Information about the format of the GPU surface that will 458 * back the SkSurface upon replay 459 * @param sampleCount The sample count of the SkSurface that the DDL created with 460 * this characterization will be replayed into 461 * @param origin The origin of the SkSurface that the DDL created with this 462 * characterization will be replayed into 463 * @param surfaceProps The surface properties of the SkSurface that the DDL created 464 * with this characterization will be replayed into 465 * @param isMipMapped Will the surface the DDL will be replayed into have space 466 * allocated for mipmaps? 467 */ 468 SkSurfaceCharacterization createCharacterization( 469 size_t cacheMaxResourceBytes, 470 const SkImageInfo& ii, const GrBackendFormat& backendFormat, 471 int sampleCount, GrSurfaceOrigin origin, 472 const SkSurfaceProps& surfaceProps, 473 bool isMipMapped); 474 475 private: 476 // DDL TODO: need to add unit tests for backend & maybe options GrContextThreadSafeProxy(sk_sp<const GrCaps> caps,uint32_t uniqueID,GrBackend backend,const GrContextOptions & options)477 GrContextThreadSafeProxy(sk_sp<const GrCaps> caps, 478 uint32_t uniqueID, 479 GrBackend backend, 480 const GrContextOptions& options) 481 : fCaps(std::move(caps)) 482 , fContextUniqueID(uniqueID) 483 , fBackend(backend) 484 , fOptions(options) { 485 } 486 487 sk_sp<const GrCaps> fCaps; 488 const uint32_t fContextUniqueID; 489 const GrBackend fBackend; 490 const GrContextOptions fOptions; 491 492 friend class GrContext; 493 friend class GrContextPriv; 494 friend class SkImage; 495 496 typedef SkRefCnt INHERITED; 497 }; 498 499 #endif 500