• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 GrSurfaceProxy_DEFINED
9 #define GrSurfaceProxy_DEFINED
10 
11 #include "include/core/SkRect.h"
12 #include "include/gpu/GrBackendSurface.h"
13 #include "include/gpu/GrGpuResource.h"
14 #include "include/gpu/GrSurface.h"
15 #include "include/gpu/GrTexture.h"
16 #include "include/private/SkNoncopyable.h"
17 #include "src/gpu/GrSwizzle.h"
18 
19 class GrCaps;
20 class GrContext_Base;
21 class GrRecordingContext;
22 class GrRenderTargetOpList;
23 class GrRenderTargetProxy;
24 class GrRenderTask;
25 class GrResourceProvider;
26 class GrSurfaceContext;
27 class GrSurfaceProxyPriv;
28 class GrTextureOpList;
29 class GrTextureProxy;
30 
31 // This is basically SkRefCntBase except Ganesh uses internalGetProxyRefCnt for more than asserts.
32 class GrIORefProxy : public SkNoncopyable {
33 public:
GrIORefProxy()34     GrIORefProxy() : fRefCnt(1) {}
35 
~GrIORefProxy()36     virtual ~GrIORefProxy() {}
37 
unique()38     bool unique() const {
39         SkASSERT(fRefCnt > 0);
40         return 1 == fRefCnt;
41     }
42 
ref()43     void ref() const {
44         SkASSERT(fRefCnt > 0);
45         ++fRefCnt;
46     }
47 
unref()48     void unref() const {
49         SkASSERT(fRefCnt > 0);
50         --fRefCnt;
51         if (0 == fRefCnt) {
52             delete this;
53         }
54     }
55 
56 protected:
internalGetProxyRefCnt()57     int32_t internalGetProxyRefCnt() const { return fRefCnt; }
58 
59 private:
60     mutable int32_t fRefCnt;
61 };
62 
63 class GrSurfaceProxy : public GrIORefProxy {
64 public:
65     /**
66      * Some lazy proxy callbacks want to set their own (or no key) on the GrSurfaces they return.
67      * Others want the GrSurface's key to be kept in sync with the proxy's key. This enum controls
68      * the key relationship between proxies and their targets.
69      */
70     enum class LazyInstantiationKeyMode {
71         /**
72          * Don't key the GrSurface with the proxy's key. The lazy instantiation callback is free to
73          * return a GrSurface that already has a unique key unrelated to the proxy's key.
74          */
75         kUnsynced,
76         /**
77          * Keep the GrSurface's unique key in sync with the proxy's unique key. The GrSurface
78          * returned from the lazy instantiation callback must not have a unique key or have the same
79          * same unique key as the proxy. If the proxy is later assigned a key it is in turn assigned
80          * to the GrSurface.
81          */
82         kSynced
83     };
84 
85     struct LazyInstantiationResult {
86         LazyInstantiationResult() = default;
87         LazyInstantiationResult(const LazyInstantiationResult&) = default;
88         LazyInstantiationResult(LazyInstantiationResult&& that) = default;
89         LazyInstantiationResult(sk_sp<GrSurface> surf,
90                                 LazyInstantiationKeyMode mode = LazyInstantiationKeyMode::kSynced)
fSurfaceLazyInstantiationResult91                 : fSurface(std::move(surf)), fKeyMode(mode) {}
LazyInstantiationResultLazyInstantiationResult92         LazyInstantiationResult(sk_sp<GrTexture> tex)
93                 : LazyInstantiationResult(sk_sp<GrSurface>(std::move(tex))) {}
94 
95         LazyInstantiationResult& operator=(const LazyInstantiationResult&) = default;
96         LazyInstantiationResult& operator=(LazyInstantiationResult&&) = default;
97 
98         sk_sp<GrSurface> fSurface;
99         LazyInstantiationKeyMode fKeyMode = LazyInstantiationKeyMode::kSynced;
100     };
101 
102     using LazyInstantiateCallback = std::function<LazyInstantiationResult(GrResourceProvider*)>;
103 
104     enum class LazyInstantiationType {
105         kSingleUse,      // Instantiation callback is allowed to be called only once.
106         kMultipleUse,    // Instantiation callback can be called multiple times.
107         kDeinstantiate,  // Instantiation callback can be called multiple times,
108                          // but we will deinstantiate the proxy after every flush.
109     };
110 
111     enum class LazyState {
112         kNot,       // The proxy is instantiated or does not have a lazy callback
113         kPartially, // The proxy has a lazy callback but knows basic information about itself.
114         kFully,     // The proxy has a lazy callback and also doesn't know its width, height, etc.
115     };
116 
lazyInstantiationState()117     LazyState lazyInstantiationState() const {
118         if (this->isInstantiated() || !SkToBool(fLazyInstantiateCallback)) {
119             return LazyState::kNot;
120         } else {
121             if (fWidth <= 0) {
122                 SkASSERT(fHeight <= 0);
123                 return LazyState::kFully;
124             } else {
125                 SkASSERT(fHeight > 0);
126                 return LazyState::kPartially;
127             }
128         }
129     }
130 
config()131     GrPixelConfig config() const { return fConfig; }
width()132     int width() const {
133         SkASSERT(LazyState::kFully != this->lazyInstantiationState());
134         return fWidth;
135     }
height()136     int height() const {
137         SkASSERT(LazyState::kFully != this->lazyInstantiationState());
138         return fHeight;
139     }
140 
isize()141     SkISize isize() const { return {fWidth, fHeight}; }
142 
143     int worstCaseWidth() const;
144     int worstCaseHeight() const;
145     /**
146      * Helper that gets the width and height of the surface as a bounding rectangle.
147      */
getBoundsRect()148     SkRect getBoundsRect() const {
149         SkASSERT(LazyState::kFully != this->lazyInstantiationState());
150         return SkRect::MakeIWH(this->width(), this->height());
151     }
152     /**
153      * Helper that gets the worst case width and height of the surface as a bounding rectangle.
154      */
getWorstCaseBoundsRect()155     SkRect getWorstCaseBoundsRect() const {
156         SkASSERT(LazyState::kFully != this->lazyInstantiationState());
157         return SkRect::MakeIWH(this->worstCaseWidth(), this->worstCaseHeight());
158     }
159 
origin()160     GrSurfaceOrigin origin() const {
161         SkASSERT(kTopLeft_GrSurfaceOrigin == fOrigin || kBottomLeft_GrSurfaceOrigin == fOrigin);
162         return fOrigin;
163     }
164 
textureSwizzle()165     const GrSwizzle& textureSwizzle() const { return fTextureSwizzle; }
166 
backendFormat()167     const GrBackendFormat& backendFormat() const { return fFormat; }
168 
169     class UniqueID {
170     public:
InvalidID()171         static UniqueID InvalidID() {
172             return UniqueID(uint32_t(SK_InvalidUniqueID));
173         }
174 
175         // wrapped
UniqueID(const GrGpuResource::UniqueID & id)176         explicit UniqueID(const GrGpuResource::UniqueID& id) : fID(id.asUInt()) { }
177         // deferred and lazy-callback
UniqueID()178         UniqueID() : fID(GrGpuResource::CreateUniqueID()) { }
179 
asUInt()180         uint32_t asUInt() const { return fID; }
181 
182         bool operator==(const UniqueID& other) const {
183             return fID == other.fID;
184         }
185         bool operator!=(const UniqueID& other) const {
186             return !(*this == other);
187         }
188 
makeInvalid()189         void makeInvalid() { fID = SK_InvalidUniqueID; }
isInvalid()190         bool isInvalid() const { return SK_InvalidUniqueID == fID; }
191 
192     private:
UniqueID(uint32_t id)193         explicit UniqueID(uint32_t id) : fID(id) {}
194 
195         uint32_t fID;
196     };
197 
198     /*
199      * The contract for the uniqueID is:
200      *   for wrapped resources:
201      *      the uniqueID will match that of the wrapped resource
202      *
203      *   for deferred resources:
204      *      the uniqueID will be different from the real resource, when it is allocated
205      *      the proxy's uniqueID will not change across the instantiate call
206      *
207      *    the uniqueIDs of the proxies and the resources draw from the same pool
208      *
209      * What this boils down to is that the uniqueID of a proxy can be used to consistently
210      * track/identify a proxy but should never be used to distinguish between
211      * resources and proxies - beware!
212      */
uniqueID()213     UniqueID uniqueID() const { return fUniqueID; }
214 
underlyingUniqueID()215     UniqueID underlyingUniqueID() const {
216         if (fTarget) {
217             return UniqueID(fTarget->uniqueID());
218         }
219 
220         return fUniqueID;
221     }
222 
223     virtual bool instantiate(GrResourceProvider*) = 0;
224 
225     void deinstantiate();
226 
227     /**
228      * Proxies that are already instantiated and whose backing surface cannot be recycled to
229      * instantiate other proxies do not need to be considered by GrResourceAllocator.
230      */
231     bool canSkipResourceAllocator() const;
232 
233     /**
234      * @return the texture proxy associated with the surface proxy, may be NULL.
235      */
asTextureProxy()236     virtual GrTextureProxy* asTextureProxy() { return nullptr; }
asTextureProxy()237     virtual const GrTextureProxy* asTextureProxy() const { return nullptr; }
238 
239     /**
240      * @return the render target proxy associated with the surface proxy, may be NULL.
241      */
asRenderTargetProxy()242     virtual GrRenderTargetProxy* asRenderTargetProxy() { return nullptr; }
asRenderTargetProxy()243     virtual const GrRenderTargetProxy* asRenderTargetProxy() const { return nullptr; }
244 
isInstantiated()245     bool isInstantiated() const { return SkToBool(fTarget); }
246 
247     // If the proxy is already instantiated, return its backing GrTexture; if not, return null.
peekSurface()248     GrSurface* peekSurface() const { return fTarget.get(); }
249 
250     // If this is a texture proxy and the proxy is already instantiated, return its backing
251     // GrTexture; if not, return null.
peekTexture()252     GrTexture* peekTexture() const { return fTarget ? fTarget->asTexture() : nullptr; }
253 
254     // If this is a render target proxy and the proxy is already instantiated, return its backing
255     // GrRenderTarget; if not, return null.
peekRenderTarget()256     GrRenderTarget* peekRenderTarget() const {
257         return fTarget ? fTarget->asRenderTarget() : nullptr;
258     }
259 
260     /**
261      * Does the resource count against the resource budget?
262      */
isBudgeted()263     SkBudgeted isBudgeted() const { return fBudgeted; }
264 
265     /**
266      * The pixel values of this proxy's surface cannot be modified (e.g. doesn't support write
267      * pixels or MIP map level regen). Read-only proxies also bypass interval tracking and
268      * assignment in GrResourceAllocator.
269      */
readOnly()270     bool readOnly() const { return fSurfaceFlags & GrInternalSurfaceFlags::kReadOnly; }
271 
272     void setLastRenderTask(GrRenderTask*);
getLastRenderTask()273     GrRenderTask* getLastRenderTask() { return fLastRenderTask; }
274 
275     GrRenderTargetOpList* getLastRenderTargetOpList();
276     GrTextureOpList* getLastTextureOpList();
277 
278     /**
279      * Retrieves the amount of GPU memory that will be or currently is used by this resource
280      * in bytes. It is approximate since we aren't aware of additional padding or copies made
281      * by the driver.
282      *
283      * @return the amount of GPU memory used in bytes
284      */
gpuMemorySize()285     size_t gpuMemorySize() const {
286         SkASSERT(LazyState::kFully != this->lazyInstantiationState());
287         if (fTarget) {
288             return fTarget->gpuMemorySize();
289         }
290         if (kInvalidGpuMemorySize == fGpuMemorySize) {
291             fGpuMemorySize = this->onUninstantiatedGpuMemorySize();
292             SkASSERT(kInvalidGpuMemorySize != fGpuMemorySize);
293         }
294         return fGpuMemorySize;
295     }
296 
297     enum class RectsMustMatch : bool {
298         kNo = false,
299         kYes = true
300     };
301 
302     // Helper function that creates a temporary SurfaceContext to perform the copy
303     // The copy is is not a render target and not multisampled.
304     static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped,
305                                       SkIRect srcRect, SkBackingFit, SkBudgeted,
306                                       RectsMustMatch = RectsMustMatch::kNo);
307 
308     // Copy the entire 'src'
309     static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped,
310                                       SkBackingFit, SkBudgeted);
311 
312 #if GR_TEST_UTILS
313     int32_t testingOnly_getBackingRefCnt() const;
314     GrInternalSurfaceFlags testingOnly_getFlags() const;
315 #endif
316 
317     SkDEBUGCODE(void validate(GrContext_Base*) const;)
318 
319     // Provides access to functions that aren't part of the public API.
320     inline GrSurfaceProxyPriv priv();
321     inline const GrSurfaceProxyPriv priv() const;
322 
323     // Returns true if we are working with protected content.
isProtected()324     bool isProtected() const { return fIsProtected == GrProtected::kYes; }
325 
326 protected:
327     // Deferred version
GrSurfaceProxy(const GrBackendFormat & format,const GrSurfaceDesc & desc,GrRenderable renderable,GrSurfaceOrigin origin,const GrSwizzle & textureSwizzle,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected,GrInternalSurfaceFlags surfaceFlags)328     GrSurfaceProxy(const GrBackendFormat& format, const GrSurfaceDesc& desc,
329                    GrRenderable renderable, GrSurfaceOrigin origin, const GrSwizzle& textureSwizzle,
330                    SkBackingFit fit, SkBudgeted budgeted, GrProtected isProtected,
331                    GrInternalSurfaceFlags surfaceFlags)
332             : GrSurfaceProxy(nullptr, LazyInstantiationType::kSingleUse, format, desc, renderable,
333                              origin, textureSwizzle, fit, budgeted, isProtected, surfaceFlags) {
334         // Note: this ctor pulls a new uniqueID from the same pool at the GrGpuResources
335     }
336 
337     // Lazy-callback version
338     GrSurfaceProxy(LazyInstantiateCallback&&, LazyInstantiationType, const GrBackendFormat& format,
339                    const GrSurfaceDesc&, GrRenderable, GrSurfaceOrigin,
340                    const GrSwizzle& textureSwizzle, SkBackingFit, SkBudgeted, GrProtected,
341                    GrInternalSurfaceFlags);
342 
343     // Wrapped version.
344     GrSurfaceProxy(sk_sp<GrSurface>, GrSurfaceOrigin, const GrSwizzle& textureSwizzle,
345                    SkBackingFit);
346 
347     ~GrSurfaceProxy() override;
348 
349     friend class GrSurfaceProxyPriv;
350 
351     // Methods made available via GrSurfaceProxyPriv
ignoredByResourceAllocator()352     bool ignoredByResourceAllocator() const { return fIgnoredByResourceAllocator; }
setIgnoredByResourceAllocator()353     void setIgnoredByResourceAllocator() { fIgnoredByResourceAllocator = true; }
354 
getProxyRefCnt()355     int32_t getProxyRefCnt() const { return this->internalGetProxyRefCnt(); }
356 
357     void computeScratchKey(GrScratchKey*) const;
358 
359     virtual sk_sp<GrSurface> createSurface(GrResourceProvider*) const = 0;
360     void assign(sk_sp<GrSurface> surface);
361 
362     sk_sp<GrSurface> createSurfaceImpl(GrResourceProvider*, int sampleCnt,
363                                        int minStencilSampleCount, GrRenderable, GrMipMapped) const;
364 
365     // Once the size of a fully-lazy proxy is decided, and before it gets instantiated, the client
366     // can use this optional method to specify the proxy's size. (A proxy's size can be less than
367     // the GPU surface that backs it. e.g., SkBackingFit::kApprox.) Otherwise, the proxy's size will
368     // be set to match the underlying GPU surface upon instantiation.
setLazySize(int width,int height)369     void setLazySize(int width, int height) {
370         SkASSERT(GrSurfaceProxy::LazyState::kFully == this->lazyInstantiationState());
371         SkASSERT(width > 0 && height > 0);
372         fWidth = width;
373         fHeight = height;
374     }
375 
376     bool instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
377                          int minStencilSampleCount, GrRenderable, GrMipMapped, const GrUniqueKey*);
378 
379     // For deferred proxies this will be null until the proxy is instantiated.
380     // For wrapped proxies it will point to the wrapped resource.
381     sk_sp<GrSurface>       fTarget;
382 
383     // In many cases these flags aren't actually known until the proxy has been instantiated.
384     // However, Ganesh frequently needs to change its behavior based on these settings. For
385     // internally create proxies we will know these properties ahead of time. For wrapped
386     // proxies we will copy the properties off of the GrSurface. For lazy proxies we force the
387     // call sites to provide the required information ahead of time. At instantiation time
388     // we verify that the assumed properties match the actual properties.
389     GrInternalSurfaceFlags fSurfaceFlags;
390 
391 private:
392     // For wrapped resources, 'fFormat', 'fConfig', 'fWidth', 'fHeight', and 'fOrigin; will always
393     // be filled in from the wrapped resource.
394     GrBackendFormat        fFormat;
395     GrPixelConfig          fConfig;
396     int                    fWidth;
397     int                    fHeight;
398     GrSurfaceOrigin        fOrigin;
399     GrSwizzle              fTextureSwizzle;
400 
401     SkBackingFit           fFit;      // always kApprox for lazy-callback resources
402                                       // always kExact for wrapped resources
403     mutable SkBudgeted     fBudgeted; // always kYes for lazy-callback resources
404                                       // set from the backing resource for wrapped resources
405                                       // mutable bc of SkSurface/SkImage wishy-washiness
406 
407     const UniqueID         fUniqueID; // set from the backing resource for wrapped resources
408 
409     LazyInstantiateCallback fLazyInstantiateCallback;
410     // If this is set to kSingleuse, then after one call to fLazyInstantiateCallback we will cleanup
411     // the lazy callback and then delete it. This will allow for any refs and resources being held
412     // by the standard function to be released. This is specifically useful in non-dll cases where
413     // we make lazy proxies and instantiate them immediately.
414     // Note: This is ignored if fLazyInstantiateCallback is null.
415     LazyInstantiationType  fLazyInstantiationType;
416 
417     SkDEBUGCODE(void validateSurface(const GrSurface*);)
418     SkDEBUGCODE(virtual void onValidateSurface(const GrSurface*) = 0;)
419 
420     static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);
421     SkDEBUGCODE(size_t getRawGpuMemorySize_debugOnly() const { return fGpuMemorySize; })
422 
423     virtual size_t onUninstantiatedGpuMemorySize() const = 0;
424 
425     bool                   fIgnoredByResourceAllocator = false;
426     GrProtected            fIsProtected;
427 
428     // This entry is lazily evaluated so, when the proxy wraps a resource, the resource
429     // will be called but, when the proxy is deferred, it will compute the answer itself.
430     // If the proxy computes its own answer that answer is checked (in debug mode) in
431     // the instantiation method.
432     mutable size_t         fGpuMemorySize;
433 
434     // The last opList that wrote to or is currently going to write to this surface
435     // The opList can be closed (e.g., no surface context is currently bound
436     // to this proxy).
437     // This back-pointer is required so that we can add a dependancy between
438     // the opList used to create the current contents of this surface
439     // and the opList of a destination surface to which this one is being drawn or copied.
440     // This pointer is unreffed. GrRenderTasks own a ref on their surface proxies.
441     GrRenderTask*          fLastRenderTask;
442 
443     typedef GrIORefProxy INHERITED;
444 };
445 
446 #endif
447