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/GrRecordingContext.h" |
17 | |
18 | // We shouldn't need this but currently Android is relying on this being include transitively. |
19 | #include "include/core/SkUnPreMultiply.h" |
20 | |
21 | class GrAtlasManager; |
22 | class GrBackendSemaphore; |
23 | class GrCaps; |
24 | class GrClientMappedBufferManager; |
25 | class GrContextPriv; |
26 | class GrContextThreadSafeProxy; |
27 | struct GrD3DBackendContext; |
28 | class GrFragmentProcessor; |
29 | struct GrGLInterface; |
30 | class GrGpu; |
31 | struct GrMockOptions; |
32 | class GrPath; |
33 | class GrRenderTargetContext; |
34 | class GrResourceCache; |
35 | class GrResourceProvider; |
36 | class GrSmallPathAtlasMgr; |
37 | class GrStrikeCache; |
38 | class GrSurfaceProxy; |
39 | class GrSwizzle; |
40 | class GrTextureProxy; |
41 | struct GrVkBackendContext; |
42 | |
43 | class SkImage; |
44 | class SkString; |
45 | class SkSurfaceCharacterization; |
46 | class SkSurfaceProps; |
47 | class SkTaskGroup; |
48 | class SkTraceMemoryDump; |
49 | |
50 | class SK_API GrContext : public GrRecordingContext { |
51 | public: |
52 | #ifndef SK_DISABLE_LEGACY_CONTEXT_FACTORIES |
53 | |
54 | #ifdef SK_GL |
55 | /** |
56 | * Creates a GrContext for a backend context. If no GrGLInterface is provided then the result of |
57 | * GrGLMakeNativeInterface() is used if it succeeds. |
58 | */ |
59 | static sk_sp<GrContext> MakeGL(sk_sp<const GrGLInterface>, const GrContextOptions&); |
60 | static sk_sp<GrContext> MakeGL(sk_sp<const GrGLInterface>); |
61 | static sk_sp<GrContext> MakeGL(const GrContextOptions&); |
62 | static sk_sp<GrContext> MakeGL(); |
63 | #endif |
64 | |
65 | #ifdef SK_VULKAN |
66 | /** |
67 | * The Vulkan context (VkQueue, VkDevice, VkInstance) must be kept alive until the returned |
68 | * GrContext is destroyed. This also means that any objects created with this GrContext (e.g. |
69 | * SkSurfaces, SkImages, etc.) must also be released as they may hold refs on the GrContext. |
70 | * Once all these objects and the GrContext are released, then it is safe to delete the vulkan |
71 | * objects. |
72 | */ |
73 | static sk_sp<GrContext> MakeVulkan(const GrVkBackendContext&, const GrContextOptions&); |
74 | static sk_sp<GrContext> MakeVulkan(const GrVkBackendContext&); |
75 | #endif |
76 | |
77 | #ifdef SK_METAL |
78 | /** |
79 | * Makes a GrContext which uses Metal as the backend. The device parameter is an MTLDevice |
80 | * and queue is an MTLCommandQueue which should be used by the backend. These objects must |
81 | * have a ref on them which can be transferred to Ganesh which will release the ref when the |
82 | * GrContext is destroyed. |
83 | */ |
84 | static sk_sp<GrContext> MakeMetal(void* device, void* queue, const GrContextOptions& options); |
85 | static sk_sp<GrContext> MakeMetal(void* device, void* queue); |
86 | #endif |
87 | |
88 | #ifdef SK_DIRECT3D |
89 | /** |
90 | * Makes a GrContext which uses Direct3D as the backend. The Direct3D context |
91 | * must be kept alive until the returned GrContext is first destroyed or abandoned. |
92 | */ |
93 | static sk_sp<GrContext> MakeDirect3D(const GrD3DBackendContext&, |
94 | const GrContextOptions& options); |
95 | static sk_sp<GrContext> MakeDirect3D(const GrD3DBackendContext&); |
96 | #endif |
97 | |
98 | #ifdef SK_DAWN |
99 | static sk_sp<GrContext> MakeDawn(const wgpu::Device& device, const GrContextOptions& options); |
100 | static sk_sp<GrContext> MakeDawn(const wgpu::Device& device); |
101 | #endif |
102 | |
103 | static sk_sp<GrContext> MakeMock(const GrMockOptions*, const GrContextOptions&); |
104 | static sk_sp<GrContext> MakeMock(const GrMockOptions*); |
105 | |
106 | #endif // SK_DISABLE_LEGACY_CONTEXT_FACTORIES |
107 | |
108 | ~GrContext() override; |
109 | |
110 | // TODO: Remove this from public after migrating Chrome. |
111 | sk_sp<GrContextThreadSafeProxy> threadSafeProxy(); |
112 | |
113 | /** |
114 | * The GrContext normally assumes that no outsider is setting state |
115 | * within the underlying 3D API's context/device/whatever. This call informs |
116 | * the context that the state was modified and it should resend. Shouldn't |
117 | * be called frequently for good performance. |
118 | * The flag bits, state, is dpendent on which backend is used by the |
119 | * context, either GL or D3D (possible in future). |
120 | */ |
121 | void resetContext(uint32_t state = kAll_GrBackendState); |
122 | |
123 | /** |
124 | * If the backend is GrBackendApi::kOpenGL, then all texture unit/target combinations for which |
125 | * the GrContext has modified the bound texture will have texture id 0 bound. This does not |
126 | * flush the GrContext. Calling resetContext() does not change the set that will be bound |
127 | * to texture id 0 on the next call to resetGLTextureBindings(). After this is called |
128 | * all unit/target combinations are considered to have unmodified bindings until the GrContext |
129 | * subsequently modifies them (meaning if this is called twice in a row with no intervening |
130 | * GrContext usage then the second call is a no-op.) |
131 | */ |
132 | void resetGLTextureBindings(); |
133 | |
134 | /** |
135 | * Abandons all GPU resources and assumes the underlying backend 3D API context is no longer |
136 | * usable. Call this if you have lost the associated GPU context, and thus internal texture, |
137 | * buffer, etc. references/IDs are now invalid. Calling this ensures that the destructors of the |
138 | * GrContext and any of its created resource objects will not make backend 3D API calls. Content |
139 | * rendered but not previously flushed may be lost. After this function is called all subsequent |
140 | * calls on the GrContext will fail or be no-ops. |
141 | * |
142 | * The typical use case for this function is that the underlying 3D context was lost and further |
143 | * API calls may crash. |
144 | * |
145 | * For Vulkan, even if the device becomes lost, the VkQueue, VkDevice, or VkInstance used to |
146 | * create the GrContext must be kept alive even after abandoning the context. Those objects must |
147 | * live for the lifetime of the GrContext object itself. The reason for this is so that |
148 | * we can continue to delete any outstanding GrBackendTextures/RenderTargets which must be |
149 | * cleaned up even in a device lost state. |
150 | */ |
151 | void abandonContext() override; |
152 | |
153 | /** |
154 | * Returns true if the context was abandoned or if the if the backend specific context has |
155 | * gotten into an unrecoverarble, lost state (e.g. in Vulkan backend if we've gotten a |
156 | * VK_ERROR_DEVICE_LOST). If the backend context is lost, this call will also abandon the |
157 | * GrContext. |
158 | */ |
159 | bool abandoned() override; |
160 | |
161 | /** |
162 | * Checks if the underlying 3D API reported an out-of-memory error. If this returns true it is |
163 | * reset and will return false until another out-of-memory error is reported by the 3D API. If |
164 | * the context is abandoned then this will report false. |
165 | * |
166 | * Currently this is implemented for: |
167 | * |
168 | * OpenGL [ES] - Note that client calls to glGetError() may swallow GL_OUT_OF_MEMORY errors and |
169 | * therefore hide the error from Skia. Also, it is not advised to use this in combination with |
170 | * enabling GrContextOptions::fSkipGLErrorChecks. That option may prevent GrContext from ever |
171 | * checking the GL context for OOM. |
172 | * |
173 | * Vulkan - Reports true if VK_ERROR_OUT_OF_HOST_MEMORY or VK_ERROR_OUT_OF_DEVICE_MEMORY has |
174 | * occurred. |
175 | */ |
176 | bool oomed(); |
177 | |
178 | /** |
179 | * This is similar to abandonContext() however the underlying 3D context is not yet lost and |
180 | * the GrContext will cleanup all allocated resources before returning. After returning it will |
181 | * assume that the underlying context may no longer be valid. |
182 | * |
183 | * The typical use case for this function is that the client is going to destroy the 3D context |
184 | * but can't guarantee that GrContext will be destroyed first (perhaps because it may be ref'ed |
185 | * elsewhere by either the client or Skia objects). |
186 | * |
187 | * For Vulkan, even if the device becomes lost, the VkQueue, VkDevice, or VkInstance used to |
188 | * create the GrContext must be alive before calling releaseResourcesAndAbandonContext. |
189 | */ |
190 | virtual void releaseResourcesAndAbandonContext(); |
191 | |
192 | /////////////////////////////////////////////////////////////////////////// |
193 | // Resource Cache |
194 | |
195 | /** DEPRECATED |
196 | * Return the current GPU resource cache limits. |
197 | * |
198 | * @param maxResources If non-null, will be set to -1. |
199 | * @param maxResourceBytes If non-null, returns maximum number of bytes of |
200 | * video memory that can be held in the cache. |
201 | */ |
202 | void getResourceCacheLimits(int* maxResources, size_t* maxResourceBytes) const; |
203 | |
204 | /** |
205 | * Return the current GPU resource cache limit in bytes. |
206 | */ |
207 | size_t getResourceCacheLimit() const; |
208 | |
209 | /** |
210 | * Gets the current GPU resource cache usage. |
211 | * |
212 | * @param resourceCount If non-null, returns the number of resources that are held in the |
213 | * cache. |
214 | * @param maxResourceBytes If non-null, returns the total number of bytes of video memory held |
215 | * in the cache. |
216 | */ |
217 | void getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const; |
218 | |
219 | /** |
220 | * Gets the number of bytes in the cache consumed by purgeable (e.g. unlocked) resources. |
221 | */ |
222 | size_t getResourceCachePurgeableBytes() const; |
223 | |
224 | /** DEPRECATED |
225 | * Specify the GPU resource cache limits. If the current cache exceeds the maxResourceBytes |
226 | * limit, it will be purged (LRU) to keep the cache within the limit. |
227 | * |
228 | * @param maxResources Unused. |
229 | * @param maxResourceBytes The maximum number of bytes of video memory |
230 | * that can be held in the cache. |
231 | */ |
232 | void setResourceCacheLimits(int maxResources, size_t maxResourceBytes); |
233 | |
234 | /** |
235 | * Specify the GPU resource cache limit. If the cache currently exceeds this limit, |
236 | * it will be purged (LRU) to keep the cache within the limit. |
237 | * |
238 | * @param maxResourceBytes The maximum number of bytes of video memory |
239 | * that can be held in the cache. |
240 | */ |
241 | void setResourceCacheLimit(size_t maxResourceBytes); |
242 | |
243 | /** |
244 | * Frees GPU created by the context. Can be called to reduce GPU memory |
245 | * pressure. |
246 | */ |
247 | virtual void freeGpuResources(); |
248 | |
249 | /** |
250 | * Purge GPU resources that haven't been used in the past 'msNotUsed' milliseconds or are |
251 | * otherwise marked for deletion, regardless of whether the context is under budget. |
252 | */ |
253 | void performDeferredCleanup(std::chrono::milliseconds msNotUsed); |
254 | |
255 | // Temporary compatibility API for Android. |
256 | void purgeResourcesNotUsedInMs(std::chrono::milliseconds msNotUsed) { |
257 | this->performDeferredCleanup(msNotUsed); |
258 | } |
259 | |
260 | /** |
261 | * Purge unlocked resources from the cache until the the provided byte count has been reached |
262 | * or we have purged all unlocked resources. The default policy is to purge in LRU order, but |
263 | * can be overridden to prefer purging scratch resources (in LRU order) prior to purging other |
264 | * resource types. |
265 | * |
266 | * @param maxBytesToPurge the desired number of bytes to be purged. |
267 | * @param preferScratchResources If true scratch resources will be purged prior to other |
268 | * resource types. |
269 | */ |
270 | void purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources); |
271 | |
272 | /** |
273 | * This entry point is intended for instances where an app has been backgrounded or |
274 | * suspended. |
275 | * If 'scratchResourcesOnly' is true all unlocked scratch resources will be purged but the |
276 | * unlocked resources with persistent data will remain. If 'scratchResourcesOnly' is false |
277 | * then all unlocked resources will be purged. |
278 | * In either case, after the unlocked resources are purged a separate pass will be made to |
279 | * ensure that resource usage is under budget (i.e., even if 'scratchResourcesOnly' is true |
280 | * some resources with persistent data may be purged to be under budget). |
281 | * |
282 | * @param scratchResourcesOnly If true only unlocked scratch resources will be purged prior |
283 | * enforcing the budget requirements. |
284 | */ |
285 | void purgeUnlockedResources(bool scratchResourcesOnly); |
286 | |
287 | /** |
288 | * Gets the maximum supported texture size. |
289 | */ |
290 | int maxTextureSize() const; |
291 | |
292 | /** |
293 | * Gets the maximum supported render target size. |
294 | */ |
295 | int maxRenderTargetSize() const; |
296 | |
297 | /** |
298 | * Can a SkImage be created with the given color type. |
299 | */ |
300 | bool colorTypeSupportedAsImage(SkColorType) const; |
301 | |
302 | /** |
303 | * Can a SkSurface be created with the given color type. To check whether MSAA is supported |
304 | * use maxSurfaceSampleCountForColorType(). |
305 | */ |
306 | using GrRecordingContext::colorTypeSupportedAsSurface; |
307 | |
308 | /** |
309 | * Gets the maximum supported sample count for a color type. 1 is returned if only non-MSAA |
310 | * rendering is supported for the color type. 0 is returned if rendering to this color type |
311 | * is not supported at all. |
312 | */ |
313 | using GrRecordingContext::maxSurfaceSampleCountForColorType; |
314 | |
315 | /////////////////////////////////////////////////////////////////////////// |
316 | // Misc. |
317 | |
318 | /** |
319 | * Inserts a list of GPU semaphores that the current GPU-backed API must wait on before |
320 | * executing any more commands on the GPU. If this call returns false, then the GPU back-end |
321 | * will not wait on any passed in semaphores, and the client will still own the semaphores, |
322 | * regardless of the value of deleteSemaphoresAfterWait. |
323 | * |
324 | * If deleteSemaphoresAfterWait is false then Skia will not delete the semaphores. In this case |
325 | * it is the client's responsibility to not destroy or attempt to reuse the semaphores until it |
326 | * knows that Skia has finished waiting on them. This can be done by using finishedProcs on |
327 | * flush calls. |
328 | */ |
329 | bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores, |
330 | bool deleteSemaphoresAfterWait = true); |
331 | |
332 | /** |
333 | * Call to ensure all drawing to the context has been flushed and submitted to the underlying 3D |
334 | * API. This is equivalent to calling GrContext::flush with a default GrFlushInfo followed by |
335 | * GrContext::submit. |
336 | */ |
337 | void flushAndSubmit() { |
338 | this->flush(GrFlushInfo()); |
339 | this->submit(); |
340 | } |
341 | |
342 | /** |
343 | * Call to ensure all drawing to the context has been flushed to underlying 3D API specific |
344 | * objects. A call to GrContext::submit is always required to ensure work is actually sent to |
345 | * the gpu. Some specific API details: |
346 | * GL: Commands are actually sent to the driver, but glFlush is never called. Thus some |
347 | * sync objects from the flush will not be valid until a submission occurs. |
348 | * |
349 | * Vulkan/Metal/D3D/Dawn: Commands are recorded to the backend APIs corresponding command |
350 | * buffer or encoder objects. However, these objects are not sent to the gpu until a |
351 | * submission occurs. |
352 | * |
353 | * If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will be |
354 | * submitted to the gpu during the next submit call (it is possible Skia failed to create a |
355 | * subset of the semaphores). The client should not wait on these semaphores until after submit |
356 | * has been called, and must keep them alive until then. If this call returns |
357 | * GrSemaphoresSubmitted::kNo, the GPU backend will not submit any semaphores to be signaled on |
358 | * the GPU. Thus the client should not have the GPU wait on any of the semaphores passed in with |
359 | * the GrFlushInfo. Regardless of whether semaphores were submitted to the GPU or not, the |
360 | * client is still responsible for deleting any initialized semaphores. |
361 | * Regardleess of semaphore submission the context will still be flushed. It should be |
362 | * emphasized that a return value of GrSemaphoresSubmitted::kNo does not mean the flush did not |
363 | * happen. It simply means there were no semaphores submitted to the GPU. A caller should only |
364 | * take this as a failure if they passed in semaphores to be submitted. |
365 | */ |
366 | GrSemaphoresSubmitted flush(const GrFlushInfo& info); |
367 | |
368 | void flush() { this->flush({}); } |
369 | |
370 | /** |
371 | * Submit outstanding work to the gpu from all previously un-submitted flushes. The return |
372 | * value of the submit will indicate whether or not the submission to the GPU was successful. |
373 | * |
374 | * If the call returns true, all previously passed in semaphores in flush calls will have been |
375 | * submitted to the GPU and they can safely be waited on. The caller should wait on those |
376 | * semaphores or perform some other global synchronization before deleting the semaphores. |
377 | * |
378 | * If it returns false, then those same semaphores will not have been submitted and we will not |
379 | * try to submit them again. The caller is free to delete the semaphores at any time. |
380 | * |
381 | * If the syncCpu flag is true this function will return once the gpu has finished with all |
382 | * submitted work. |
383 | */ |
384 | bool submit(bool syncCpu = false); |
385 | |
386 | /** |
387 | * Checks whether any asynchronous work is complete and if so calls related callbacks. |
388 | */ |
389 | void checkAsyncWorkCompletion(); |
390 | |
391 | // Provides access to functions that aren't part of the public API. |
392 | GrContextPriv priv(); |
393 | const GrContextPriv priv() const; // NOLINT(readability-const-return-type) |
394 | |
395 | /** Enumerates all cached GPU resources and dumps their memory to traceMemoryDump. */ |
396 | // Chrome is using this! |
397 | void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const; |
398 | |
399 | bool supportsDistanceFieldText() const; |
400 | |
401 | void storeVkPipelineCacheData(); |
402 | |
403 | // Returns the gpu memory size of the the texture that backs the passed in SkImage. Returns 0 if |
404 | // the SkImage is not texture backed. For external format textures this will also return 0 as we |
405 | // cannot determine the correct size. |
406 | static size_t ComputeImageSize(sk_sp<SkImage> image, GrMipmapped, bool useNextPow2 = false); |
407 | |
408 | /** |
409 | * Retrieve the default GrBackendFormat for a given SkColorType and renderability. |
410 | * It is guaranteed that this backend format will be the one used by the following |
411 | * SkColorType and SkSurfaceCharacterization-based createBackendTexture methods. |
412 | * |
413 | * The caller should check that the returned format is valid. |
414 | */ |
415 | GrBackendFormat defaultBackendFormat(SkColorType ct, GrRenderable renderable) const { |
416 | return INHERITED::defaultBackendFormat(ct, renderable); |
417 | } |
418 | |
419 | /** |
420 | * The explicitly allocated backend texture API allows clients to use Skia to create backend |
421 | * objects outside of Skia proper (i.e., Skia's caching system will not know about them.) |
422 | * |
423 | * It is the client's responsibility to delete all these objects (using deleteBackendTexture) |
424 | * before deleting the GrContext used to create them. If the backend is Vulkan, the textures must |
425 | * be deleted before abandoning the GrContext as well. Additionally, clients should only delete |
426 | * these objects on the thread for which that GrContext is active. |
427 | * |
428 | * The client is responsible for ensuring synchronization between different uses |
429 | * of the backend object (i.e., wrapping it in a surface, rendering to it, deleting the |
430 | * surface, rewrapping it in a image and drawing the image will require explicit |
431 | * sychronization on the client's part). |
432 | */ |
433 | |
434 | /** |
435 | * If possible, create an uninitialized backend texture. 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_UNDEFINED. |
439 | */ |
440 | GrBackendTexture createBackendTexture(int width, int height, |
441 | const GrBackendFormat&, |
442 | GrMipmapped, |
443 | GrRenderable, |
444 | GrProtected = GrProtected::kNo); |
445 | |
446 | /** |
447 | * If possible, create an uninitialized backend texture. The client should ensure that the |
448 | * returned backend texture is valid. |
449 | * If successful, the created backend texture will be compatible with the provided |
450 | * SkColorType. |
451 | * For the Vulkan backend the layout of the created VkImage will be: |
452 | * VK_IMAGE_LAYOUT_UNDEFINED. |
453 | */ |
454 | GrBackendTexture createBackendTexture(int width, int height, |
455 | SkColorType, |
456 | GrMipmapped, |
457 | GrRenderable, |
458 | GrProtected = GrProtected::kNo); |
459 | |
460 | |
461 | /** |
462 | * If possible, create an uninitialized backend texture that is compatible with the |
463 | * provided characterization. The client should ensure that the returned backend texture |
464 | * is valid. |
465 | * For the Vulkan backend the layout of the created VkImage will be: |
466 | * VK_IMAGE_LAYOUT_UNDEFINED. |
467 | */ |
468 | GrBackendTexture createBackendTexture(const SkSurfaceCharacterization& characterization); |
469 | |
470 | /** |
471 | * If possible, create a backend texture initialized to a particular color. The client should |
472 | * ensure that the returned backend texture is valid. The client can pass in a finishedProc |
473 | * to be notified when the data has been uploaded by the gpu and the texture can be deleted. The |
474 | * client is required to call GrContext::submit to send the upload work to the gpu. The |
475 | * finishedProc will always get called even if we failed to create the GrBackendTexture. |
476 | * For the Vulkan backend the layout of the created VkImage will be: |
477 | * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
478 | */ |
479 | GrBackendTexture createBackendTexture(int width, int height, |
480 | const GrBackendFormat&, |
481 | const SkColor4f& color, |
482 | GrMipmapped, |
483 | GrRenderable, |
484 | GrProtected = GrProtected::kNo, |
485 | GrGpuFinishedProc finishedProc = nullptr, |
486 | GrGpuFinishedContext finishedContext = nullptr); |
487 | |
488 | /** |
489 | * If possible, create a backend texture initialized to a particular color. The client should |
490 | * ensure that the returned backend texture is valid. The client can pass in a finishedProc |
491 | * to be notified when the data has been uploaded by the gpu and the texture can be deleted. The |
492 | * client is required to call GrContext::submit to send the upload work to the gpu. The |
493 | * finishedProc will always get called even if we failed to create the GrBackendTexture. |
494 | * If successful, the created backend texture will be compatible with the provided |
495 | * SkColorType. |
496 | * For the Vulkan backend the layout of the created VkImage will be: |
497 | * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
498 | */ |
499 | GrBackendTexture createBackendTexture(int width, int height, |
500 | SkColorType, |
501 | const SkColor4f& color, |
502 | GrMipmapped, |
503 | GrRenderable, |
504 | GrProtected = GrProtected::kNo, |
505 | GrGpuFinishedProc finishedProc = nullptr, |
506 | GrGpuFinishedContext finishedContext = nullptr); |
507 | |
508 | /** |
509 | * If possible, create a backend texture initialized to a particular color that is |
510 | * compatible with the provided characterization. The client should ensure that the |
511 | * returned backend texture is valid. The client can pass in a finishedProc to be notified when |
512 | * the data has been uploaded by the gpu and the texture can be deleted. The client is required |
513 | * to call GrContext::submit to send the upload work to the gpu. The finishedProc will always |
514 | * get called even if we failed to create the GrBackendTexture. |
515 | * For the Vulkan backend the layout of the created VkImage will be: |
516 | * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL if texturaeble |
517 | * VK_IMAGE_LAYOUT_UNDEFINED if not textureable |
518 | */ |
519 | GrBackendTexture createBackendTexture(const SkSurfaceCharacterization& characterization, |
520 | const SkColor4f& color, |
521 | GrGpuFinishedProc finishedProc = nullptr, |
522 | GrGpuFinishedContext finishedContext = nullptr); |
523 | |
524 | /** |
525 | * If possible, create a backend texture initialized with the provided pixmap data. The client |
526 | * should ensure that the returned backend texture is valid. The client can pass in a |
527 | * finishedProc to be notified when the data has been uploaded by the gpu and the texture can be |
528 | * deleted. The client is required to call GrContext::submit to send the upload work to the gpu. |
529 | * The finishedProc will always get called even if we failed to create the GrBackendTexture. |
530 | * If successful, the created backend texture will be compatible with the provided |
531 | * pixmap(s). Compatible, in this case, means that the backend format will be the result |
532 | * of calling defaultBackendFormat on the base pixmap's colortype. The src data can be deleted |
533 | * when this call returns. |
534 | * If numLevels is 1 a non-mipMapped texture will result. If a mipMapped texture is desired |
535 | * the data for all the mipmap levels must be provided. In the mipmapped case all the |
536 | * colortypes of the provided pixmaps must be the same. Additionally, all the miplevels |
537 | * must be sized correctly (please see SkMipmap::ComputeLevelSize and ComputeLevelCount). |
538 | * Note: the pixmap's alphatypes and colorspaces are ignored. |
539 | * For the Vulkan backend the layout of the created VkImage will be: |
540 | * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
541 | */ |
542 | GrBackendTexture createBackendTexture(const SkPixmap srcData[], int numLevels, |
543 | GrRenderable, GrProtected, |
544 | GrGpuFinishedProc finishedProc = nullptr, |
545 | GrGpuFinishedContext finishedContext = nullptr); |
546 | |
547 | // Helper version of above for a single level. |
548 | GrBackendTexture createBackendTexture(const SkPixmap& srcData, |
549 | GrRenderable renderable, |
550 | GrProtected isProtected, |
551 | GrGpuFinishedProc finishedProc = nullptr, |
552 | GrGpuFinishedContext finishedContext = nullptr) { |
553 | return this->createBackendTexture(&srcData, 1, renderable, isProtected, finishedProc, |
554 | finishedContext); |
555 | } |
556 | |
557 | /** |
558 | * If possible, updates a backend texture to be filled to a particular color. The client should |
559 | * check the return value to see if the update was successful. The client can pass in a |
560 | * finishedProc to be notified when the data has been uploaded by the gpu and the texture can be |
561 | * deleted. The client is required to call GrContext::submit to send the upload work to the gpu. |
562 | * The finishedProc will always get called even if we failed to update the GrBackendTexture. |
563 | * For the Vulkan backend after a successful update the layout of the created VkImage will be: |
564 | * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
565 | */ |
566 | bool updateBackendTexture(const GrBackendTexture&, |
567 | const SkColor4f& color, |
568 | GrGpuFinishedProc finishedProc, |
569 | GrGpuFinishedContext finishedContext); |
570 | |
571 | /** |
572 | * If possible, updates a backend texture to be filled to a particular color. The data in |
573 | * GrBackendTexture and passed in color is interpreted with respect to the passed in |
574 | * SkColorType. The client should check the return value to see if the update was successful. |
575 | * The client can pass in a finishedProc to be notified when the data has been uploaded by the |
576 | * gpu and the texture can be deleted. The client is required to call GrContext::submit to send |
577 | * the upload work to the gpu. The finishedProc will always get called even if we failed to |
578 | * update the GrBackendTexture. |
579 | * For the Vulkan backend after a successful update the layout of the created VkImage will be: |
580 | * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
581 | */ |
582 | bool updateBackendTexture(const GrBackendTexture&, |
583 | SkColorType skColorType, |
584 | const SkColor4f& color, |
585 | GrGpuFinishedProc finishedProc, |
586 | GrGpuFinishedContext finishedContext); |
587 | |
588 | /** |
589 | * If possible, updates a backend texture filled with the provided pixmap data. The client |
590 | * should check the return value to see if the update was successful. The client can pass in a |
591 | * finishedProc to be notified when the data has been uploaded by the gpu and the texture can be |
592 | * deleted. The client is required to call GrContext::submit to send the upload work to the gpu. |
593 | * The finishedProc will always get called even if we failed to create the GrBackendTexture. |
594 | * The backend texture must be compatible with the provided pixmap(s). Compatible, in this case, |
595 | * means that the backend format is compatible with the base pixmap's colortype. The src data |
596 | * can be deleted when this call returns. |
597 | * If the backend texture is mip mapped, the data for all the mipmap levels must be provided. |
598 | * In the mipmapped case all the colortypes of the provided pixmaps must be the same. |
599 | * Additionally, all the miplevels must be sized correctly (please see |
600 | * SkMipmap::ComputeLevelSize and ComputeLevelCount). |
601 | * Note: the pixmap's alphatypes and colorspaces are ignored. |
602 | * For the Vulkan backend after a successful update the layout of the created VkImage will be: |
603 | * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
604 | */ |
605 | bool updateBackendTexture(const GrBackendTexture&, |
606 | const SkPixmap srcData[], |
607 | int numLevels, |
608 | GrGpuFinishedProc finishedProc, |
609 | GrGpuFinishedContext finishedContext); |
610 | |
611 | /** |
612 | * Retrieve the GrBackendFormat for a given SkImage::CompressionType. This is |
613 | * guaranteed to match the backend format used by the following |
614 | * createCompressedsBackendTexture methods that take a CompressionType. |
615 | * The caller should check that the returned format is valid. |
616 | */ |
617 | GrBackendFormat compressedBackendFormat(SkImage::CompressionType compression) const { |
618 | return INHERITED::compressedBackendFormat(compression); |
619 | } |
620 | |
621 | /** |
622 | *If possible, create a compressed backend texture initialized to a particular color. The |
623 | * client should ensure that the returned backend texture is valid. The client can pass in a |
624 | * finishedProc to be notified when the data has been uploaded by the gpu and the texture can be |
625 | * deleted. The client is required to call GrContext::submit to send the upload work to the gpu. |
626 | * The finishedProc will always get called even if we failed to create the GrBackendTexture. |
627 | * For the Vulkan backend the layout of the created VkImage will be: |
628 | * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
629 | */ |
630 | GrBackendTexture createCompressedBackendTexture(int width, int height, |
631 | const GrBackendFormat&, |
632 | const SkColor4f& color, |
633 | GrMipmapped, |
634 | GrProtected = GrProtected::kNo, |
635 | GrGpuFinishedProc finishedProc = nullptr, |
636 | GrGpuFinishedContext finishedContext = nullptr); |
637 | |
638 | GrBackendTexture createCompressedBackendTexture(int width, int height, |
639 | SkImage::CompressionType, |
640 | const SkColor4f& color, |
641 | GrMipmapped, |
642 | GrProtected = GrProtected::kNo, |
643 | GrGpuFinishedProc finishedProc = nullptr, |
644 | GrGpuFinishedContext finishedContext = nullptr); |
645 | |
646 | /** |
647 | * If possible, create a backend texture initialized with the provided raw data. The client |
648 | * should ensure that the returned backend texture is valid. The client can pass in a |
649 | * finishedProc to be notified when the data has been uploaded by the gpu and the texture can be |
650 | * deleted. The client is required to call GrContext::submit to send the upload work to the gpu. |
651 | * The finishedProc will always get called even if we failed to create the GrBackendTexture |
652 | * If numLevels is 1 a non-mipMapped texture will result. If a mipMapped texture is desired |
653 | * the data for all the mipmap levels must be provided. Additionally, all the miplevels |
654 | * must be sized correctly (please see SkMipmap::ComputeLevelSize and ComputeLevelCount). |
655 | * For the Vulkan backend the layout of the created VkImage will be: |
656 | * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
657 | */ |
658 | GrBackendTexture createCompressedBackendTexture(int width, int height, |
659 | const GrBackendFormat&, |
660 | const void* data, size_t dataSize, |
661 | GrMipmapped, |
662 | GrProtected = GrProtected::kNo, |
663 | GrGpuFinishedProc finishedProc = nullptr, |
664 | GrGpuFinishedContext finishedContext = nullptr); |
665 | |
666 | GrBackendTexture createCompressedBackendTexture(int width, int height, |
667 | SkImage::CompressionType, |
668 | const void* data, size_t dataSize, |
669 | GrMipmapped, |
670 | GrProtected = GrProtected::kNo, |
671 | GrGpuFinishedProc finishedProc = nullptr, |
672 | GrGpuFinishedContext finishedContext = nullptr); |
673 | |
674 | /** |
675 | * If possible, updates a backend texture filled with the provided color. If the texture is |
676 | * mipmapped, all levels of the mip chain will be updated to have the supplied color. The client |
677 | * should check the return value to see if the update was successful. The client can pass in a |
678 | * finishedProc to be notified when the data has been uploaded by the gpu and the texture can be |
679 | * deleted. The client is required to call GrContext::submit to send the upload work to the gpu. |
680 | * The finishedProc will always get called even if we failed to create the GrBackendTexture. |
681 | * For the Vulkan backend after a successful update the layout of the created VkImage will be: |
682 | * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
683 | */ |
684 | bool updateCompressedBackendTexture(const GrBackendTexture&, |
685 | const SkColor4f& color, |
686 | GrGpuFinishedProc finishedProc, |
687 | GrGpuFinishedContext finishedContext); |
688 | |
689 | /** |
690 | * If possible, updates a backend texture filled with the provided raw data. The client |
691 | * should check the return value to see if the update was successful. The client can pass in a |
692 | * finishedProc to be notified when the data has been uploaded by the gpu and the texture can be |
693 | * deleted. The client is required to call GrContext::submit to send the upload work to the gpu. |
694 | * The finishedProc will always get called even if we failed to create the GrBackendTexture. |
695 | * If a mipMapped texture is passed in, the data for all the mipmap levels must be provided. |
696 | * Additionally, all the miplevels must be sized correctly (please see |
697 | * SkMipMap::ComputeLevelSize and ComputeLevelCount). |
698 | * For the Vulkan backend after a successful update the layout of the created VkImage will be: |
699 | * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL |
700 | */ |
701 | bool updateCompressedBackendTexture(const GrBackendTexture&, |
702 | const void* data, |
703 | size_t dataSize, |
704 | GrGpuFinishedProc finishedProc, |
705 | GrGpuFinishedContext finishedContext); |
706 | |
707 | /** |
708 | * Updates the state of the GrBackendTexture/RenderTarget to have the passed in |
709 | * GrBackendSurfaceMutableState. All objects that wrap the backend surface (i.e. SkSurfaces and |
710 | * SkImages) will also be aware of this state change. This call does not submit the state change |
711 | * to the gpu, but requires the client to call GrContext::submit to send it to the GPU. The work |
712 | * for this call is ordered linearly with all other calls that require GrContext::submit to be |
713 | * called (e.g updateBackendTexture and flush). If finishedProc is not null then it will be |
714 | * called with finishedContext after the state transition is known to have occurred on the GPU. |
715 | * |
716 | * See GrBackendSurfaceMutableState to see what state can be set via this call. |
717 | */ |
718 | bool setBackendTextureState(const GrBackendTexture&, |
719 | const GrBackendSurfaceMutableState&, |
720 | GrGpuFinishedProc finishedProc = nullptr, |
721 | GrGpuFinishedContext finishedContext = nullptr); |
722 | bool setBackendRenderTargetState(const GrBackendRenderTarget&, |
723 | const GrBackendSurfaceMutableState&, |
724 | GrGpuFinishedProc finishedProc = nullptr, |
725 | GrGpuFinishedContext finishedContext = nullptr); |
726 | |
727 | void deleteBackendTexture(GrBackendTexture); |
728 | |
729 | // This interface allows clients to pre-compile shaders and populate the runtime program cache. |
730 | // The key and data blobs should be the ones passed to the PersistentCache, in SkSL format. |
731 | // |
732 | // Steps to use this API: |
733 | // |
734 | // 1) Create a GrContext as normal, but set fPersistentCache on GrContextOptions to something |
735 | // that will save the cached shader blobs. Set fShaderCacheStrategy to kSkSL. This will |
736 | // ensure that the blobs are SkSL, and are suitable for pre-compilation. |
737 | // 2) Run your application, and save all of the key/data pairs that are fed to the cache. |
738 | // |
739 | // 3) Switch over to shipping your application. Include the key/data pairs from above. |
740 | // 4) At startup (or any convenient time), call precompileShader for each key/data pair. |
741 | // This will compile the SkSL to create a GL program, and populate the runtime cache. |
742 | // |
743 | // This is only guaranteed to work if the context/device used in step #2 are created in the |
744 | // same way as the one used in step #4, and the same GrContextOptions are specified. |
745 | // Using cached shader blobs on a different device or driver are undefined. |
746 | bool precompileShader(const SkData& key, const SkData& data); |
747 | |
748 | #ifdef SK_ENABLE_DUMP_GPU |
749 | /** Returns a string with detailed information about the context & GPU, in JSON format. */ |
750 | SkString dump() const; |
751 | #endif |
752 | |
753 | protected: |
754 | GrContext(sk_sp<GrContextThreadSafeProxy>); |
755 | |
756 | bool init() override; |
757 | |
758 | virtual GrAtlasManager* onGetAtlasManager() = 0; |
759 | virtual GrSmallPathAtlasMgr* onGetSmallPathAtlasMgr() = 0; |
760 | |
761 | private: |
762 | friend class GrDirectContext; // for access to fGpu |
763 | |
764 | // fTaskGroup must appear before anything that uses it (e.g. fGpu), so that it is destroyed |
765 | // after all of its users. Clients of fTaskGroup will generally want to ensure that they call |
766 | // wait() on it as they are being destroyed, to avoid the possibility of pending tasks being |
767 | // invoked after objects they depend upon have already been destroyed. |
768 | std::unique_ptr<SkTaskGroup> fTaskGroup; |
769 | std::unique_ptr<GrStrikeCache> fStrikeCache; |
770 | sk_sp<GrGpu> fGpu; |
771 | GrResourceCache* fResourceCache; |
772 | GrResourceProvider* fResourceProvider; |
773 | |
774 | bool fDidTestPMConversions; |
775 | // true if the PM/UPM conversion succeeded; false otherwise |
776 | bool fPMUPMConversionsRoundTrip; |
777 | |
778 | GrContextOptions::PersistentCache* fPersistentCache; |
779 | GrContextOptions::ShaderErrorHandler* fShaderErrorHandler; |
780 | |
781 | std::unique_ptr<GrClientMappedBufferManager> fMappedBufferManager; |
782 | |
783 | // TODO: have the GrClipStackClip use renderTargetContexts and rm this friending |
784 | friend class GrContextPriv; |
785 | |
786 | typedef GrRecordingContext INHERITED; |
787 | }; |
788 | |
789 | #endif |
790 | |