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 "GrColor.h"
13#include "SkMatrix.h"
14#include "SkPathEffect.h"
15#include "SkTypes.h"
16#include "../private/GrAuditTrail.h"
17#include "../private/GrSingleOwner.h"
18
19class GrAtlasGlyphCache;
20struct GrContextOptions;
21class GrContextPriv;
22class GrContextThreadSafeProxy;
23class GrDrawingManager;
24struct GrDrawOpAtlasConfig;
25class GrRenderTargetContext;
26class GrFragmentProcessor;
27class GrGpu;
28class GrIndexBuffer;
29class GrOvalRenderer;
30class GrPath;
31class GrResourceEntry;
32class GrResourceCache;
33class GrResourceProvider;
34class GrSamplerParams;
35class GrSurfaceProxy;
36class GrTextBlobCache;
37class GrTextContext;
38class GrTextureProxy;
39class GrVertexBuffer;
40class GrSwizzle;
41class SkTraceMemoryDump;
42
43class SkImage;
44class SkSurfaceProps;
45
46class SK_API GrContext : public SkRefCnt {
47public:
48    /**
49     * Creates a GrContext for a backend context.
50     */
51    static GrContext* Create(GrBackend, GrBackendContext, const GrContextOptions& options);
52    static GrContext* Create(GrBackend, GrBackendContext);
53
54#ifdef SK_METAL
55    /**
56     * Makes a GrContext which uses Metal as the backend. The device parameter is an MTLDevice
57     * and queue is an MTLCommandQueue which should be used by the backend. These objects must
58     * have a ref on them which can be transferred to Ganesh which will release the ref when the
59     * GrContext is destroyed.
60     */
61    static sk_sp<GrContext> MakeMetal(void* device, void* queue, const GrContextOptions& options);
62#endif
63
64    virtual ~GrContext();
65
66    sk_sp<GrContextThreadSafeProxy> threadSafeProxy();
67
68    /**
69     * The GrContext normally assumes that no outsider is setting state
70     * within the underlying 3D API's context/device/whatever. This call informs
71     * the context that the state was modified and it should resend. Shouldn't
72     * be called frequently for good performance.
73     * The flag bits, state, is dpendent on which backend is used by the
74     * context, either GL or D3D (possible in future).
75     */
76    void resetContext(uint32_t state = kAll_GrBackendState);
77
78    /**
79     * Callback function to allow classes to cleanup on GrContext destruction.
80     * The 'info' field is filled in with the 'info' passed to addCleanUp.
81     */
82    typedef void (*PFCleanUpFunc)(const GrContext* context, void* info);
83
84    /**
85     * Add a function to be called from within GrContext's destructor.
86     * This gives classes a chance to free resources held on a per context basis.
87     * The 'info' parameter will be stored and passed to the callback function.
88     */
89    void addCleanUp(PFCleanUpFunc cleanUp, void* info) {
90        CleanUpData* entry = fCleanUpData.push();
91
92        entry->fFunc = cleanUp;
93        entry->fInfo = info;
94    }
95
96    /**
97     * Abandons all GPU resources and assumes the underlying backend 3D API context is not longer
98     * usable. Call this if you have lost the associated GPU context, and thus internal texture,
99     * buffer, etc. references/IDs are now invalid. Calling this ensures that the destructors of the
100     * GrContext and any of its created resource objects will not make backend 3D API calls. Content
101     * rendered but not previously flushed may be lost. After this function is called all subsequent
102     * calls on the GrContext will fail or be no-ops.
103     *
104     * The typical use case for this function is that the underlying 3D context was lost and further
105     * API calls may crash.
106     */
107    void abandonContext();
108
109    /**
110     * This is similar to abandonContext() however the underlying 3D context is not yet lost and
111     * the GrContext will cleanup all allocated resources before returning. After returning it will
112     * assume that the underlying context may no longer be valid.
113     *
114     * The typical use case for this function is that the client is going to destroy the 3D context
115     * but can't guarantee that GrContext will be destroyed first (perhaps because it may be ref'ed
116     * elsewhere by either the client or Skia objects).
117     */
118    void releaseResourcesAndAbandonContext();
119
120    ///////////////////////////////////////////////////////////////////////////
121    // Resource Cache
122
123    /**
124     *  Return the current GPU resource cache limits.
125     *
126     *  @param maxResources If non-null, returns maximum number of resources that
127     *                      can be held in the cache.
128     *  @param maxResourceBytes If non-null, returns maximum number of bytes of
129     *                          video memory that can be held in the cache.
130     */
131    void getResourceCacheLimits(int* maxResources, size_t* maxResourceBytes) const;
132
133    /**
134     *  Gets the current GPU resource cache usage.
135     *
136     *  @param resourceCount If non-null, returns the number of resources that are held in the
137     *                       cache.
138     *  @param maxResourceBytes If non-null, returns the total number of bytes of video memory held
139     *                          in the cache.
140     */
141    void getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const;
142
143    /**
144     *  Gets the number of bytes in the cache consumed by purgeable (e.g. unlocked) resources.
145     */
146    size_t getResourceCachePurgeableBytes() const;
147
148    /**
149     *  Specify the GPU resource cache limits. If the current cache exceeds either
150     *  of these, it will be purged (LRU) to keep the cache within these limits.
151     *
152     *  @param maxResources The maximum number of resources that can be held in
153     *                      the cache.
154     *  @param maxResourceBytes The maximum number of bytes of video memory
155     *                          that can be held in the cache.
156     */
157    void setResourceCacheLimits(int maxResources, size_t maxResourceBytes);
158
159    /**
160     * Frees GPU created by the context. Can be called to reduce GPU memory
161     * pressure.
162     */
163    void freeGpuResources();
164
165    /**
166     * Purge all the unlocked resources from the cache.
167     * This entry point is mainly meant for timing texture uploads
168     * and is not defined in normal builds of Skia.
169     */
170    void purgeAllUnlockedResources();
171
172    /**
173     * Purge GPU resources that haven't been used in the past 'ms' milliseconds, regardless of
174     * whether the context is currently under budget.
175     */
176    void purgeResourcesNotUsedInMs(std::chrono::milliseconds ms);
177
178    /**
179     * Purge unlocked resources from the cache until the the provided byte count has been reached
180     * or we have purged all unlocked resources. The default policy is to purge in LRU order, but
181     * can be overridden to prefer purging scratch resources (in LRU order) prior to purging other
182     * resource types.
183     *
184     * @param maxBytesToPurge the desired number of bytes to be purged.
185     * @param preferScratchResources If true scratch resources will be purged prior to other
186     *                               resource types.
187     */
188    void purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources);
189
190    /** Access the context capabilities */
191    const GrCaps* caps() const { return fCaps; }
192
193    /**
194     * Returns the recommended sample count for a render target when using this
195     * context.
196     *
197     * @param  config the configuration of the render target.
198     * @param  dpi the display density in dots per inch.
199     *
200     * @return sample count that should be perform well and have good enough
201     *         rendering quality for the display. Alternatively returns 0 if
202     *         MSAA is not supported or recommended to be used by default.
203     */
204    int getRecommendedSampleCount(GrPixelConfig config, SkScalar dpi) const;
205
206    /*
207     * Create a new render target context backed by a deferred-style
208     * GrRenderTargetProxy. We guarantee that "asTextureProxy" will succeed for
209     * renderTargetContexts created via this entry point.
210     */
211    sk_sp<GrRenderTargetContext> makeDeferredRenderTargetContext(
212                                                 SkBackingFit fit,
213                                                 int width, int height,
214                                                 GrPixelConfig config,
215                                                 sk_sp<SkColorSpace> colorSpace,
216                                                 int sampleCnt = 0,
217                                                 GrSurfaceOrigin origin = kBottomLeft_GrSurfaceOrigin,
218                                                 const SkSurfaceProps* surfaceProps = nullptr,
219                                                 SkBudgeted = SkBudgeted::kYes);
220    /*
221     * This method will attempt to create a renderTargetContext that has, at least, the number of
222     * channels and precision per channel as requested in 'config' (e.g., A8 and 888 can be
223     * converted to 8888). It may also swizzle the channels (e.g., BGRA -> RGBA).
224     * SRGB-ness will be preserved.
225     */
226    sk_sp<GrRenderTargetContext> makeDeferredRenderTargetContextWithFallback(
227                                                 SkBackingFit fit,
228                                                 int width, int height,
229                                                 GrPixelConfig config,
230                                                 sk_sp<SkColorSpace> colorSpace,
231                                                 int sampleCnt = 0,
232                                                 GrSurfaceOrigin origin = kBottomLeft_GrSurfaceOrigin,
233                                                 const SkSurfaceProps* surfaceProps = nullptr,
234                                                 SkBudgeted budgeted = SkBudgeted::kYes);
235
236    ///////////////////////////////////////////////////////////////////////////
237    // Misc.
238
239    /**
240     * Call to ensure all drawing to the context has been issued to the
241     * underlying 3D API.
242     */
243    void flush();
244
245    /**
246     * An ID associated with this context, guaranteed to be unique.
247     */
248    uint32_t uniqueID() { return fUniqueID; }
249
250    ///////////////////////////////////////////////////////////////////////////
251    // Functions intended for internal use only.
252    GrGpu* getGpu() { return fGpu; }
253    const GrGpu* getGpu() const { return fGpu; }
254    GrAtlasGlyphCache* getAtlasGlyphCache() { return fAtlasGlyphCache; }
255    GrTextBlobCache* getTextBlobCache() { return fTextBlobCache.get(); }
256    bool abandoned() const;
257    GrResourceProvider* resourceProvider() { return fResourceProvider; }
258    const GrResourceProvider* resourceProvider() const { return fResourceProvider; }
259    GrResourceCache* getResourceCache() { return fResourceCache; }
260
261    /** Reset GPU stats */
262    void resetGpuStats() const ;
263
264    /** Prints cache stats to the string if GR_CACHE_STATS == 1. */
265    void dumpCacheStats(SkString*) const;
266    void dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) const;
267    void printCacheStats() const;
268
269    /** Prints GPU stats to the string if GR_GPU_STATS == 1. */
270    void dumpGpuStats(SkString*) const;
271    void dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) const;
272    void printGpuStats() const;
273
274    /** Specify the TextBlob cache limit. If the current cache exceeds this limit it will purge.
275        this is for testing only */
276    void setTextBlobCacheLimit_ForTesting(size_t bytes);
277
278    /** Specify the sizes of the GrAtlasTextContext atlases.  The configs pointer below should be
279        to an array of 3 entries */
280    void setTextContextAtlasSizes_ForTesting(const GrDrawOpAtlasConfig* configs);
281
282    /** Enumerates all cached GPU resources and dumps their memory to traceMemoryDump. */
283    void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
284
285    /** Get pointer to atlas texture for given mask format. Note that this wraps an
286        actively mutating texture in an SkImage. This could yield unexpected results
287        if it gets cached or used more generally. */
288    sk_sp<SkImage> getFontAtlasImage_ForTesting(GrMaskFormat format);
289
290    GrAuditTrail* getAuditTrail() { return &fAuditTrail; }
291
292    /** This is only useful for debug purposes */
293    SkDEBUGCODE(GrSingleOwner* debugSingleOwner() const { return &fSingleOwner; } )
294
295    // Provides access to functions that aren't part of the public API.
296    GrContextPriv contextPriv();
297    const GrContextPriv contextPriv() const;
298
299private:
300    GrGpu*                                  fGpu;
301    const GrCaps*                           fCaps;
302    GrResourceCache*                        fResourceCache;
303    GrResourceProvider*                     fResourceProvider;
304
305    sk_sp<GrContextThreadSafeProxy>         fThreadSafeProxy;
306
307    GrAtlasGlyphCache*                      fAtlasGlyphCache;
308    std::unique_ptr<GrTextBlobCache>        fTextBlobCache;
309
310    bool                                    fDisableGpuYUVConversion;
311    bool                                    fDidTestPMConversions;
312    // true if the PM/UPM conversion succeeded; false otherwise
313    bool                                    fPMUPMConversionsRoundTrip;
314
315    // In debug builds we guard against improper thread handling
316    // This guard is passed to the GrDrawingManager and, from there to all the
317    // GrRenderTargetContexts.  It is also passed to the GrResourceProvider and SkGpuDevice.
318    mutable GrSingleOwner                   fSingleOwner;
319
320    struct CleanUpData {
321        PFCleanUpFunc fFunc;
322        void*         fInfo;
323    };
324
325    SkTDArray<CleanUpData>                  fCleanUpData;
326
327    const uint32_t                          fUniqueID;
328
329    std::unique_ptr<GrDrawingManager>       fDrawingManager;
330
331    GrAuditTrail                            fAuditTrail;
332
333    GrBackend                               fBackend;
334
335    // TODO: have the GrClipStackClip use renderTargetContexts and rm this friending
336    friend class GrContextPriv;
337
338    GrContext(); // init must be called after the constructor.
339    bool init(GrBackend, GrBackendContext, const GrContextOptions& options);
340    bool init(const GrContextOptions& options);
341
342    /**
343     * These functions create premul <-> unpremul effects. If the second argument is 'true', they
344     * use the specialized round-trip effects from GrConfigConversionEffect, otherwise they
345     * create effects that do naive multiply or divide.
346     */
347    sk_sp<GrFragmentProcessor> createPMToUPMEffect(sk_sp<GrFragmentProcessor>,
348                                                   bool useConfigConversionEffect);
349    sk_sp<GrFragmentProcessor> createUPMToPMEffect(sk_sp<GrFragmentProcessor>,
350                                                   bool useConfigConversionEffect);
351
352    /**
353     * Returns true if createPMtoUPMEffect and createUPMToPMEffect will succeed for non-sRGB 8888
354     * configs. In other words, did we find a pair of round-trip preserving conversion effects?
355     */
356    bool validPMUPMConversionExists();
357
358    /**
359     * A callback similar to the above for use by the TextBlobCache
360     * TODO move textblob draw calls below context so we can use the call above.
361     */
362    static void TextBlobCacheOverBudgetCB(void* data);
363
364    typedef SkRefCnt INHERITED;
365};
366
367/**
368 * Can be used to perform actions related to the generating GrContext in a thread safe manner. The
369 * proxy does not access the 3D API (e.g. OpenGL) that backs the generating GrContext.
370 */
371class GrContextThreadSafeProxy : public SkRefCnt {
372private:
373    GrContextThreadSafeProxy(sk_sp<const GrCaps> caps, uint32_t uniqueID)
374        : fCaps(std::move(caps))
375        , fContextUniqueID(uniqueID) {}
376
377    sk_sp<const GrCaps> fCaps;
378    uint32_t            fContextUniqueID;
379
380    friend class GrContext;
381    friend class SkImage;
382
383    typedef SkRefCnt INHERITED;
384};
385
386#endif
387