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