Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GrSurfaceProxy.h
Go to the documentation of this file.
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"
13#include "include/core/SkSize.h"
17#include "include/gpu/GrTypes.h"
21#include "src/gpu/ResourceKey.h"
24
25#include <atomic>
26#include <cstddef>
27#include <cstdint>
28#include <functional>
29#include <string>
30#include <string_view>
31#include <utility>
32
33class GrCaps;
34class GrContext_Base;
36class GrRenderTarget;
38class GrRenderTask;
41class GrTexture;
42class GrTextureProxy;
43enum class SkBackingFit;
44namespace skgpu {
45enum class Budgeted : bool;
46enum class Mipmapped : bool;
47}
48
49class GrSurfaceProxy : public SkNVRefCnt<GrSurfaceProxy> {
50public:
51 virtual ~GrSurfaceProxy();
52
53 /**
54 * Indicates "resolutions" that need to be done on a surface before its pixels can be accessed.
55 * If both types of resolve are requested, the MSAA resolve will happen first.
56 */
57 enum class ResolveFlags {
58 kNone = 0,
59 kMSAA = 1 << 0, // Blit and resolve an internal MSAA render buffer into the texture.
60 kMipMaps = 1 << 1, // Regenerate all mipmap levels.
61 };
62
63 /**
64 * Some lazy proxy callbacks want to set their own (or no key) on the GrSurfaces they return.
65 * Others want the GrSurface's key to be kept in sync with the proxy's key. This enum controls
66 * the key relationship between proxies and their targets.
67 */
69 /**
70 * Don't key the GrSurface with the proxy's key. The lazy instantiation callback is free to
71 * return a GrSurface that already has a unique key unrelated to the proxy's key.
72 */
74 /**
75 * Keep the GrSurface's unique key in sync with the proxy's unique key. The GrSurface
76 * returned from the lazy instantiation callback must not have a unique key or have the same
77 * same unique key as the proxy. If the proxy is later assigned a key it is in turn assigned
78 * to the GrSurface.
79 */
81 };
82
83 /**
84 * Specifies the expected properties of the GrSurface returned by a lazy instantiation
85 * callback. The dimensions will be negative in the case of a fully lazy proxy.
86 */
99
105 bool releaseCallback = true,
108
111
114 /**
115 * Should the callback be disposed of after it has returned or preserved until the proxy
116 * is freed. Only honored if fSurface is not-null. If it is null the callback is preserved.
117 */
118 bool fReleaseCallback = true;
119 };
120
123
124 enum class UseAllocator {
125 /**
126 * This proxy will be instantiated outside the allocator (e.g. for proxies that are
127 * instantiated in on-flush callbacks).
128 */
129 kNo = false,
130 /**
131 * GrResourceAllocator should instantiate this proxy.
132 */
133 kYes = true,
134 };
135
136 bool isLazy() const { return !this->isInstantiated() && SkToBool(fLazyInstantiateCallback); }
137
138 bool isFullyLazy() const {
139 bool result = fDimensions.width() < 0;
140 SkASSERT(result == (fDimensions.height() < 0));
141 SkASSERT(!result || this->isLazy());
142 return result;
143 }
144
146 SkASSERT(!this->isFullyLazy());
147 return fDimensions;
148 }
149 int width() const { return this->dimensions().width(); }
150 int height() const { return this->dimensions().height(); }
151
153
154 /**
155 * Helper that gets the width and height of the proxy as a bounding rectangle.
156 */
157 SkRect getBoundsRect() const { return SkRect::Make(this->dimensions()); }
158
159 /* A perhaps faster check for this->dimensions() == this->backingStoreDimensions(). */
160 bool isFunctionallyExact() const;
161
162 /**
163 * Helper that gets the dimensions the backing GrSurface will have as a bounding rectangle.
164 */
168
172
173 const GrBackendFormat& backendFormat() const { return fFormat; }
174
175 bool isFormatCompressed(const GrCaps*) const;
176
177 class UniqueID {
178 public:
180 return UniqueID(uint32_t(SK_InvalidUniqueID));
181 }
182
183 // wrapped
184 explicit UniqueID(const GrGpuResource::UniqueID& id) : fID(id.asUInt()) { }
185 // deferred and lazy-callback
186 UniqueID() : fID(GrGpuResource::CreateUniqueID()) { }
187
188 uint32_t asUInt() const { return fID; }
189
190 bool operator==(const UniqueID& other) const {
191 return fID == other.fID;
192 }
193 bool operator!=(const UniqueID& other) const {
194 return !(*this == other);
195 }
196
198 bool isInvalid() const { return SK_InvalidUniqueID == fID; }
199
200 private:
201 explicit UniqueID(uint32_t id) : fID(id) {}
202
203 uint32_t fID;
204 };
205
206 /*
207 * The contract for the uniqueID is:
208 * for wrapped resources:
209 * the uniqueID will match that of the wrapped resource
210 *
211 * for deferred resources:
212 * the uniqueID will be different from the real resource, when it is allocated
213 * the proxy's uniqueID will not change across the instantiate call
214 *
215 * the uniqueIDs of the proxies and the resources draw from the same pool
216 *
217 * What this boils down to is that the uniqueID of a proxy can be used to consistently
218 * track/identify a proxy but should never be used to distinguish between
219 * resources and proxies - beware!
220 */
221 UniqueID uniqueID() const { return fUniqueID; }
222
224 if (fTarget) {
225 return UniqueID(fTarget->uniqueID());
226 }
227
228 return fUniqueID;
229 }
230
231 virtual bool instantiate(GrResourceProvider*) = 0;
232
233 void deinstantiate();
234
235 /**
236 * Proxies that are already instantiated and whose backing surface cannot be recycled to
237 * instantiate other proxies do not need to be considered by GrResourceAllocator.
238 */
239 bool canSkipResourceAllocator() const;
240
241 /**
242 * @return the texture proxy associated with the surface proxy, may be NULL.
243 */
244 virtual GrTextureProxy* asTextureProxy() { return nullptr; }
245 virtual const GrTextureProxy* asTextureProxy() const { return nullptr; }
246
247 /**
248 * @return the render target proxy associated with the surface proxy, may be NULL.
249 */
250 virtual GrRenderTargetProxy* asRenderTargetProxy() { return nullptr; }
251 virtual const GrRenderTargetProxy* asRenderTargetProxy() const { return nullptr; }
252
253 /** @return The unique key for this proxy. May be invalid. */
254 virtual const skgpu::UniqueKey& getUniqueKey() const {
255 // Base class never has a valid unique key.
256 static const skgpu::UniqueKey kInvalidKey;
257 return kInvalidKey;
258 }
259
260 bool isInstantiated() const { return SkToBool(fTarget); }
261
262 /** Called when this task becomes a target of a GrRenderTask. */
263 void isUsedAsTaskTarget() { ++fTaskTargetCount; }
264
265 /** How many render tasks has this proxy been the target of? */
266 int getTaskTargetCount() const { return fTaskTargetCount; }
267
268 // If the proxy is already instantiated, return its backing GrTexture; if not, return null.
269 GrSurface* peekSurface() const { return fTarget.get(); }
270
271 // If this is a texture proxy and the proxy is already instantiated, return its backing
272 // GrTexture; if not, return null.
273 GrTexture* peekTexture() const { return fTarget ? fTarget->asTexture() : nullptr; }
274
275 // If this is a render target proxy and the proxy is already instantiated, return its backing
276 // GrRenderTarget; if not, return null.
278 return fTarget ? fTarget->asRenderTarget() : nullptr;
279 }
280
281 /**
282 * Does the resource count against the resource budget?
283 */
284 skgpu::Budgeted isBudgeted() const { return fBudgeted; }
285
286 /**
287 * The pixel values of this proxy's surface cannot be modified (e.g. doesn't support write
288 * pixels or MIP map level regen). Read-only proxies also bypass interval tracking and
289 * assignment in GrResourceAllocator.
290 */
295
296 /**
297 * This means surface is a multisampled render target, and internally holds a non-msaa texture
298 * for resolving into. The render target resolves itself by blitting into this internal texture.
299 * (asTexture() might or might not return the internal texture, but if it does, we always
300 * resolve the render target before accessing this texture's data.)
301 */
305
306 /**
307 * Retrieves the amount of GPU memory that will be or currently is used by this resource
308 * in bytes. It is approximate since we aren't aware of additional padding or copies made
309 * by the driver.
310 *
311 * @return the amount of GPU memory used in bytes
312 */
313 size_t gpuMemorySize() const {
314 SkASSERT(!this->isFullyLazy());
315 if (kInvalidGpuMemorySize == fGpuMemorySize) {
316 fGpuMemorySize = this->onUninstantiatedGpuMemorySize();
317 SkASSERT(kInvalidGpuMemorySize != fGpuMemorySize);
318 }
319 return fGpuMemorySize;
320 }
321
322 std::string_view getLabel() const { return fLabel; }
323
324 enum class RectsMustMatch : bool {
325 kNo = false,
326 kYes = true
327 };
328
329 // Helper function that creates a temporary SurfaceContext to perform the copy
330 // The copy is is not a render target and not multisampled.
331 //
332 // The intended use of this copy call is simply to copy exact pixel values from one proxy to a
333 // new one. Thus, there isn't a need for a swizzle when doing the copy. The format of the copy
334 // will be the same as the src. Therefore, the copy can be used in a view with the same swizzle
335 // as the original for use with a given color type.
336 //
337 // Optionally gets the render task that performs the copy. If it is later determined that the
338 // copy is not neccessaru then the task can be marked skippable using GrRenderTask::canSkip() and
339 // the copy will be elided.
344 SkIRect srcRect,
347 std::string_view label,
349 sk_sp<GrRenderTask>* outTask = nullptr);
350
351 // Same as above Copy but copies the entire 'src'
358 std::string_view label,
359 sk_sp<GrRenderTask>* outTask = nullptr);
360
361#if defined(GR_TEST_UTILS)
362 int32_t testingOnly_getBackingRefCnt() const;
363 GrInternalSurfaceFlags testingOnly_getFlags() const;
364 SkString dump() const;
365#endif
366
367#ifdef SK_DEBUG
368 void validate(GrContext_Base*) const;
369 SkString getDebugName() {
370 return fDebugName.isEmpty() ? SkStringPrintf("%u", this->uniqueID().asUInt()) : fDebugName;
371 }
372 void setDebugName(SkString name) { fDebugName = std::move(name); }
373#endif
374
375 // Provides access to functions that aren't part of the public API.
376 inline GrSurfaceProxyPriv priv();
377 inline const GrSurfaceProxyPriv priv() const; // NOLINT(readability-const-return-type)
378
379 bool isDDLTarget() const { return fIsDDLTarget; }
380
381 GrProtected isProtected() const { return fIsProtected; }
382
383 bool isPromiseProxy() { return fIsPromiseProxy; }
384
385protected:
386 // Deferred version - takes a new UniqueID from the shared resource/proxy pool.
388 SkISize,
394 std::string_view label);
395 // Lazy-callback version - takes a new UniqueID from the shared resource/proxy pool.
397 const GrBackendFormat&,
398 SkISize,
404 std::string_view label);
405
406 // Wrapped version - shares the UniqueID of the passed surface.
407 // Takes UseAllocator because even though this is already instantiated it still can participate
408 // in allocation by having its backing resource recycled to other uninstantiated proxies or
409 // not depending on UseAllocator.
411
412 friend class GrSurfaceProxyPriv;
413
414 // Methods made available via GrSurfaceProxyPriv
415 bool ignoredByResourceAllocator() const { return fIgnoredByResourceAllocator; }
416 void setIgnoredByResourceAllocator() { fIgnoredByResourceAllocator = true; }
417
418 void computeScratchKey(const GrCaps&, skgpu::ScratchKey*) const;
419
422
424 int sampleCnt,
426 skgpu::Mipmapped) const;
427
428 // Once the dimensions of a fully-lazy proxy are decided, and before it gets instantiated, the
429 // client can use this optional method to specify the proxy's dimensions. (A proxy's dimensions
430 // can be less than the GPU surface that backs it. e.g., SkBackingFit::kApprox.) Otherwise,
431 // the proxy's dimensions will be set to match the underlying GPU surface upon instantiation.
433 SkASSERT(this->isFullyLazy());
434 SkASSERT(!dimensions.isEmpty());
435 fDimensions = dimensions;
436 }
437
438 bool instantiateImpl(GrResourceProvider* resourceProvider,
439 int sampleCnt,
442 const skgpu::UniqueKey*);
443
444 // For deferred proxies this will be null until the proxy is instantiated.
445 // For wrapped proxies it will point to the wrapped resource.
447
448 // In many cases these flags aren't actually known until the proxy has been instantiated.
449 // However, Ganesh frequently needs to change its behavior based on these settings. For
450 // internally create proxies we will know these properties ahead of time. For wrapped
451 // proxies we will copy the properties off of the GrSurface. For lazy proxies we force the
452 // call sites to provide the required information ahead of time. At instantiation time
453 // we verify that the assumed properties match the actual properties.
455
456private:
457 // For wrapped resources, 'fFormat' and 'fDimensions' will always be filled in from the
458 // wrapped resource.
459 const GrBackendFormat fFormat;
460 SkISize fDimensions;
461
462 SkBackingFit fFit; // always kApprox for lazy-callback resources
463 // always kExact for wrapped resources
464 mutable skgpu::Budgeted fBudgeted; // always kYes for lazy-callback resources
465 // set from the backing resource for wrapped resources
466 // mutable bc of SkSurface/SkImage wishy-washiness
467 // Only meaningful if fLazyInstantiateCallback is non-null.
468 UseAllocator fUseAllocator;
469
470 const UniqueID fUniqueID; // set from the backing resource for wrapped resources
471
472 LazyInstantiateCallback fLazyInstantiateCallback;
473
474 SkDEBUGCODE(void validateSurface(const GrSurface*);)
475 SkDEBUGCODE(virtual void onValidateSurface(const GrSurface*) = 0;)
476
477 static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);
478 SkDEBUGCODE(size_t getRawGpuMemorySize_debugOnly() const { return fGpuMemorySize; })
479
480 virtual size_t onUninstantiatedGpuMemorySize() const = 0;
481
482 virtual LazySurfaceDesc callbackDesc() const = 0;
483
484 bool fIgnoredByResourceAllocator = false;
485 bool fIsDDLTarget = false;
486 bool fIsPromiseProxy = false;
487 GrProtected fIsProtected;
488
489 int fTaskTargetCount = 0;
490
491 const std::string fLabel;
492
493 // This entry is lazily evaluated so, when the proxy wraps a resource, the resource
494 // will be called but, when the proxy is deferred, it will compute the answer itself.
495 // If the proxy computes its own answer that answer is checked (in debug mode) in
496 // the instantiation method. The image may be shared between threads, hence atomic.
497 mutable std::atomic<size_t> fGpuMemorySize{kInvalidGpuMemorySize};
498 SkDEBUGCODE(SkString fDebugName;)
499};
500
502
503#endif
GrTextureType
GrInternalSurfaceFlags
#define GR_MAKE_BITFIELD_CLASS_OPS(X)
Definition GrTypes.h:42
GrSurfaceOrigin
Definition GrTypes.h:147
#define SkASSERT(cond)
Definition SkAssert.h:116
SkBackingFit
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
SK_API SkString static SkString SkStringPrintf()
Definition SkString.h:287
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
static constexpr uint32_t SK_InvalidUniqueID
Definition SkTypes.h:196
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
UniqueID uniqueID() const
UniqueID(const GrGpuResource::UniqueID &id)
bool operator==(const UniqueID &other) const
bool operator!=(const UniqueID &other) const
static UniqueID InvalidID()
void setIgnoredByResourceAllocator()
SkISize backingStoreDimensions() const
UniqueID underlyingUniqueID() const
virtual const skgpu::UniqueKey & getUniqueKey() const
int getTaskTargetCount() const
GrProtected isProtected() const
virtual GrRenderTargetProxy * asRenderTargetProxy()
SkRect backingStoreBoundsRect() const
const GrBackendFormat & backendFormat() const
virtual ~GrSurfaceProxy()
bool instantiateImpl(GrResourceProvider *resourceProvider, int sampleCnt, GrRenderable, skgpu::Mipmapped, const skgpu::UniqueKey *)
bool readOnly() const
virtual bool instantiate(GrResourceProvider *)=0
bool requiresManualMSAAResolve() const
bool isDDLTarget() const
bool framebufferOnly() const
size_t gpuMemorySize() const
GrSurfaceProxyPriv priv()
bool isLazy() const
std::string_view getLabel() const
bool isFormatCompressed(const GrCaps *) const
GrTexture * peekTexture() const
SkRect getBoundsRect() const
bool isFullyLazy() const
int width() const
skgpu::Budgeted isBudgeted() const
static sk_sp< GrSurfaceProxy > Copy(GrRecordingContext *, sk_sp< GrSurfaceProxy > src, GrSurfaceOrigin, skgpu::Mipmapped, SkIRect srcRect, SkBackingFit, skgpu::Budgeted, std::string_view label, RectsMustMatch=RectsMustMatch::kNo, sk_sp< GrRenderTask > *outTask=nullptr)
SkDEBUGCODE(size_t getRawGpuMemorySize_debugOnly() const { return fGpuMemorySize;}) virtual size_t onUninstantiatedGpuMemorySize() const =0
virtual LazySurfaceDesc callbackDesc() const =0
SkISize dimensions() const
void computeScratchKey(const GrCaps &, skgpu::ScratchKey *) const
std::function< LazyCallbackResult(GrResourceProvider *, const LazySurfaceDesc &)> LazyInstantiateCallback
virtual GrTextureProxy * asTextureProxy()
GrSurface * peekSurface() const
bool canSkipResourceAllocator() const
virtual const GrRenderTargetProxy * asRenderTargetProxy() const
virtual sk_sp< GrSurface > createSurface(GrResourceProvider *) const =0
bool ignoredByResourceAllocator() const
bool isInstantiated() const
virtual const GrTextureProxy * asTextureProxy() const
bool isFunctionallyExact() const
void setLazyDimensions(SkISize dimensions)
void assign(sk_sp< GrSurface > surface)
SkIRect backingStoreBoundsIRect() const
int height() const
sk_sp< GrSurface > createSurfaceImpl(GrResourceProvider *, int sampleCnt, GrRenderable, skgpu::Mipmapped) const
sk_sp< GrSurface > fTarget
void isUsedAsTaskTarget()
GrInternalSurfaceFlags fSurfaceFlags
SkDEBUGCODE(void validateSurface(const GrSurface *);) SkDEBUGCODE(virtual void onValidateSurface(const GrSurface *)=0
UniqueID uniqueID() const
GrRenderTarget * peekRenderTarget() const
virtual GrTexture * asTexture()
Definition GrSurface.h:59
virtual GrRenderTarget * asRenderTarget()
Definition GrSurface.h:65
bool isEmpty() const
Definition SkString.h:130
T * get() const
Definition SkRefCnt.h:303
VkSurfaceKHR surface
Definition main.cc:49
GAsyncResult * result
const char * name
Definition fuchsia.cc:50
Budgeted
Definition GpuTypes.h:35
Renderable
Definition GpuTypes.h:69
Mipmapped
Definition GpuTypes.h:53
Protected
Definition GpuTypes.h:61
LazyCallbackResult & operator=(LazyCallbackResult &&)=default
LazyInstantiationKeyMode fKeyMode
LazyCallbackResult(LazyCallbackResult &&that)=default
LazyCallbackResult & operator=(const LazyCallbackResult &)=default
LazyCallbackResult(const LazyCallbackResult &)=default
const GrBackendFormat & fFormat
static constexpr SkIRect MakeSize(const SkISize &size)
Definition SkRect.h:66
bool isEmpty() const
Definition SkSize.h:31
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37
static SkRect Make(const SkISize &size)
Definition SkRect.h:669
const uintptr_t id