blob: 7b938b1a077a8d230f01ec61de295ffc891086e1 [file] [log] [blame]
robertphillips76948d42016-05-04 12:47:41 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#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"
robertphillips76948d42016-05-04 12:47:41 -070017
Robert Phillips37430132016-11-09 06:50:43 -050018class GrCaps;
Robert Phillips292a6b22019-02-14 14:49:02 -050019class GrContext_Base;
Robert Phillipsc589b0b2017-04-17 07:53:07 -040020class GrOpList;
Robert Phillipsd44146b2019-02-15 14:44:28 -050021class GrRecordingContext;
Brian Osman45580d32016-11-23 09:37:01 -050022class GrRenderTargetOpList;
23class GrRenderTargetProxy;
Brian Osman32342f02017-03-04 08:12:46 -050024class GrResourceProvider;
Robert Phillipsd46697a2017-01-25 12:10:37 -050025class GrSurfaceContext;
Robert Phillips757914d2017-01-25 15:48:30 -050026class GrSurfaceProxyPriv;
Brian Osman45580d32016-11-23 09:37:01 -050027class GrTextureOpList;
robertphillips76948d42016-05-04 12:47:41 -070028class GrTextureProxy;
robertphillips76948d42016-05-04 12:47:41 -070029
Robert Phillipsc7635fa2016-10-28 13:25:24 -040030// This class replicates the functionality GrIORef<GrSurface> but tracks the
31// utilitization for later resource allocation (for the deferred case) and
32// forwards on the utilization in the wrapped case
33class GrIORefProxy : public SkNoncopyable {
34public:
35 void ref() const {
36 this->validate();
37
38 ++fRefCnt;
39 if (fTarget) {
40 fTarget->ref();
41 }
42 }
43
44 void unref() const {
45 this->validate();
46
47 if (fTarget) {
48 fTarget->unref();
49 }
50
Robert Phillipsb6deea82017-05-11 14:14:30 -040051 --fRefCnt;
Robert Phillips3d4cac52019-06-11 08:08:08 -040052 this->didRemoveRef();
Robert Phillipsc7635fa2016-10-28 13:25:24 -040053 }
54
Chris Daltona32a3c32017-12-05 10:05:21 -070055#ifdef SK_DEBUG
56 bool isUnique_debugOnly() const { // For asserts.
Robert Phillips3d4cac52019-06-11 08:08:08 -040057 SkASSERT(fRefCnt >= 0);
58 return 1 == fRefCnt;
Chris Daltona32a3c32017-12-05 10:05:21 -070059 }
60#endif
61
Robert Phillips4bc70112018-03-01 10:24:02 -050062 void release() {
Robert Phillipse4aae342018-03-14 10:26:57 -040063 // In the current hybrid world, the proxy and backing surface are ref/unreffed in
Brian Salomon0d606762019-01-25 09:58:38 -050064 // synchrony. Each ref we've added or removed to the proxy was mirrored to the backing
65 // surface. Though, that backing surface could be owned by other proxies as well. Remove
66 // a ref from the backing surface for each ref the proxy has since we are about to remove
67 // our pointer to the surface. If this proxy is reinstantiated then all the proxy's refs
68 // get transferred to the (possibly new) backing surface.
69 for (int refs = fRefCnt; refs; --refs) {
Robert Phillipse4aae342018-03-14 10:26:57 -040070 fTarget->unref();
71 }
Robert Phillips4bc70112018-03-01 10:24:02 -050072 fTarget = nullptr;
73 }
74
Robert Phillipsc7635fa2016-10-28 13:25:24 -040075 void validate() const {
Robert Phillipsb6deea82017-05-11 14:14:30 -040076#ifdef SK_DEBUG
Robert Phillips3d4cac52019-06-11 08:08:08 -040077 SkASSERT(fRefCnt >= 1);
robertphillips1125a032016-11-16 11:17:17 -080078
79 if (fTarget) {
robertphillips1125a032016-11-16 11:17:17 -080080 // The backing GrSurface can have more refs than the proxy if the proxy
81 // started off wrapping an external resource (that came in with refs).
82 // The GrSurface should never have fewer refs than the proxy however.
83 SkASSERT(fTarget->fRefCnt >= fRefCnt);
84 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -040085#endif
86 }
87
robertphillips1125a032016-11-16 11:17:17 -080088 int32_t getBackingRefCnt_TestOnly() const;
Brian Salomoncf75b002017-08-16 10:42:09 -040089
Robert Phillipsc7635fa2016-10-28 13:25:24 -040090protected:
Robert Phillips3d4cac52019-06-11 08:08:08 -040091 GrIORefProxy() : fTarget(nullptr), fRefCnt(1) {}
92 GrIORefProxy(sk_sp<GrSurface> surface) : fRefCnt(1) {
Robert Phillipsc7635fa2016-10-28 13:25:24 -040093 // Since we're manually forwarding on refs & unrefs we don't want sk_sp doing
94 // anything extra.
95 fTarget = surface.release();
96 }
97 virtual ~GrIORefProxy() {
98 // We don't unref 'fTarget' here since the 'unref' method will already
Robert Phillips4bc70112018-03-01 10:24:02 -050099 // have forwarded on the unref call that got us here.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400100 }
101
Brian Salomon01ceae92019-04-02 11:49:54 -0400102 // Privileged method that allows going from ref count = 0 to ref count = 1.
Brian Salomon2c791fc2019-04-02 11:52:03 -0400103 void addInitialRef(GrResourceCache* cache) const {
Brian Salomon01ceae92019-04-02 11:49:54 -0400104 this->validate();
105 ++fRefCnt;
106 if (fTarget) {
Brian Salomon2c791fc2019-04-02 11:52:03 -0400107 fTarget->proxyAccess().ref(cache);
Brian Salomon01ceae92019-04-02 11:49:54 -0400108 }
109 }
110
robertphillips1125a032016-11-16 11:17:17 -0800111 // This GrIORefProxy was deferred before but has just been instantiated. To
112 // make all the reffing & unreffing work out we now need to transfer any deferred
113 // refs & unrefs to the new GrSurface
114 void transferRefs() {
115 SkASSERT(fTarget);
Brian Salomon2c791fc2019-04-02 11:52:03 -0400116 // Make sure we're going to take some ownership of our target.
Robert Phillips3d4cac52019-06-11 08:08:08 -0400117 SkASSERT(fRefCnt > 0);
robertphillips1125a032016-11-16 11:17:17 -0800118
Brian Salomon2c791fc2019-04-02 11:52:03 -0400119 SkASSERT(fTarget->fRefCnt > 0);
120 SkASSERT(fRefCnt >= 0);
121 // Don't xfer the proxy's creation ref. If we're going to subtract a ref do it via unref()
122 // so that proper cache notifications occur.
123 if (!fRefCnt) {
124 fTarget->unref();
125 } else {
126 fTarget->fRefCnt += (fRefCnt - 1);
127 }
robertphillips1125a032016-11-16 11:17:17 -0800128 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400129
Robert Phillips5f78adf2019-04-22 12:41:39 -0400130 int32_t internalGetProxyRefCnt() const { return fRefCnt; }
Robert Phillips3d4cac52019-06-11 08:08:08 -0400131 int32_t internalGetTotalRefs() const { return fRefCnt; }
Robert Phillips715d08c2018-07-18 13:56:48 -0400132
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400133 // For deferred proxies this will be null. For wrapped proxies it will point to the
134 // wrapped resource.
135 GrSurface* fTarget;
robertphillips1125a032016-11-16 11:17:17 -0800136
137private:
138 // This class is used to manage conversion of refs to pending reads/writes.
Brian Salomonee783962018-08-01 09:55:10 -0400139 template <typename> friend class GrProxyRef;
robertphillips1125a032016-11-16 11:17:17 -0800140
Robert Phillips3d4cac52019-06-11 08:08:08 -0400141 void didRemoveRef() const {
142 if (0 == fRefCnt) {
Robert Phillipsb6deea82017-05-11 14:14:30 -0400143 delete this;
144 }
robertphillips1125a032016-11-16 11:17:17 -0800145 }
146
147 mutable int32_t fRefCnt;
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400148};
149
150class GrSurfaceProxy : public GrIORefProxy {
robertphillips76948d42016-05-04 12:47:41 -0700151public:
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400152 /**
153 * Some lazy proxy callbacks want to set their own (or no key) on the GrSurfaces they return.
154 * Others want the GrSurface's key to be kept in sync with the proxy's key. This enum controls
155 * the key relationship between proxies and their targets.
156 */
157 enum class LazyInstantiationKeyMode {
158 /**
159 * Don't key the GrSurface with the proxy's key. The lazy instantiation callback is free to
160 * return a GrSurface that already has a unique key unrelated to the proxy's key.
161 */
162 kUnsynced,
163 /**
164 * Keep the GrSurface's unique key in sync with the proxy's unique key. The GrSurface
165 * returned from the lazy instantiation callback must not have a unique key or have the same
166 * same unique key as the proxy. If the proxy is later assigned a key it is in turn assigned
167 * to the GrSurface.
168 */
169 kSynced
170 };
171
172 struct LazyInstantiationResult {
173 LazyInstantiationResult() = default;
174 LazyInstantiationResult(const LazyInstantiationResult&) = default;
175 LazyInstantiationResult(LazyInstantiationResult&& that) = default;
176 LazyInstantiationResult(sk_sp<GrSurface> surf,
177 LazyInstantiationKeyMode mode = LazyInstantiationKeyMode::kSynced)
178 : fSurface(std::move(surf)), fKeyMode(mode) {}
179 LazyInstantiationResult(sk_sp<GrTexture> tex)
180 : LazyInstantiationResult(sk_sp<GrSurface>(std::move(tex))) {}
181
182 LazyInstantiationResult& operator=(const LazyInstantiationResult&) = default;
183 LazyInstantiationResult& operator=(LazyInstantiationResult&&) = default;
184
185 sk_sp<GrSurface> fSurface;
186 LazyInstantiationKeyMode fKeyMode = LazyInstantiationKeyMode::kSynced;
187 };
188
189 using LazyInstantiateCallback = std::function<LazyInstantiationResult(GrResourceProvider*)>;
190
Greg Daniel457469c2018-02-08 15:05:44 -0500191 enum class LazyInstantiationType {
Brian Salomon967df202018-12-07 11:15:53 -0500192 kSingleUse, // Instantiation callback is allowed to be called only once.
193 kMultipleUse, // Instantiation callback can be called multiple times.
Brian Salomon876a0172019-03-08 11:12:14 -0500194 kDeinstantiate, // Instantiation callback can be called multiple times,
195 // but we will deinstantiate the proxy after every flush.
Greg Daniel457469c2018-02-08 15:05:44 -0500196 };
197
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500198 enum class LazyState {
Greg Daniel0a375db2018-02-01 12:21:39 -0500199 kNot, // The proxy is instantiated or does not have a lazy callback
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500200 kPartially, // The proxy has a lazy callback but knows basic information about itself.
201 kFully, // The proxy has a lazy callback and also doesn't know its width, height, etc.
202 };
203
204 LazyState lazyInstantiationState() const {
Greg Daniel0a375db2018-02-01 12:21:39 -0500205 if (fTarget || !SkToBool(fLazyInstantiateCallback)) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500206 return LazyState::kNot;
207 } else {
208 if (fWidth <= 0) {
209 SkASSERT(fHeight <= 0);
210 return LazyState::kFully;
211 } else {
212 SkASSERT(fHeight > 0);
213 return LazyState::kPartially;
214 }
215 }
216 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700217
218 GrPixelConfig config() const { return fConfig; }
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500219 int width() const {
220 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
221 return fWidth;
222 }
223 int height() const {
224 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
225 return fHeight;
226 }
Brian Salomon7eae3e02018-08-07 14:02:38 +0000227
228 SkISize isize() const { return {fWidth, fHeight}; }
229
Chris Dalton706a6ff2017-11-29 22:01:06 -0700230 int worstCaseWidth() const;
231 int worstCaseHeight() const;
Brian Salomond8eb7b62018-05-25 10:08:05 -0400232 /**
233 * Helper that gets the width and height of the surface as a bounding rectangle.
234 */
235 SkRect getBoundsRect() const {
236 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
237 return SkRect::MakeIWH(this->width(), this->height());
238 }
239 /**
240 * Helper that gets the worst case width and height of the surface as a bounding rectangle.
241 */
242 SkRect getWorstCaseBoundsRect() const {
243 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
244 return SkRect::MakeIWH(this->worstCaseWidth(), this->worstCaseHeight());
245 }
246
robertphillips76948d42016-05-04 12:47:41 -0700247 GrSurfaceOrigin origin() const {
Brian Salomonbb5711a2017-05-17 13:49:59 -0400248 SkASSERT(kTopLeft_GrSurfaceOrigin == fOrigin || kBottomLeft_GrSurfaceOrigin == fOrigin);
249 return fOrigin;
robertphillips76948d42016-05-04 12:47:41 -0700250 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700251
Greg Daniel4065d452018-11-16 15:43:41 -0500252 const GrBackendFormat& backendFormat() const { return fFormat; }
253
Robert Phillips294870f2016-11-11 12:38:40 -0500254 class UniqueID {
255 public:
Robert Phillips7ee385e2017-03-30 08:02:11 -0400256 static UniqueID InvalidID() {
257 return UniqueID(uint32_t(SK_InvalidUniqueID));
258 }
259
Robert Phillips294870f2016-11-11 12:38:40 -0500260 // wrapped
261 explicit UniqueID(const GrGpuResource::UniqueID& id) : fID(id.asUInt()) { }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700262 // deferred and lazy-callback
Robert Phillips294870f2016-11-11 12:38:40 -0500263 UniqueID() : fID(GrGpuResource::CreateUniqueID()) { }
264
265 uint32_t asUInt() const { return fID; }
266
267 bool operator==(const UniqueID& other) const {
268 return fID == other.fID;
269 }
270 bool operator!=(const UniqueID& other) const {
271 return !(*this == other);
272 }
273
Robert Phillips7ee385e2017-03-30 08:02:11 -0400274 void makeInvalid() { fID = SK_InvalidUniqueID; }
Robert Phillips294870f2016-11-11 12:38:40 -0500275 bool isInvalid() const { return SK_InvalidUniqueID == fID; }
276
277 private:
Robert Phillips7ee385e2017-03-30 08:02:11 -0400278 explicit UniqueID(uint32_t id) : fID(id) {}
279
280 uint32_t fID;
Robert Phillips294870f2016-11-11 12:38:40 -0500281 };
282
283 /*
284 * The contract for the uniqueID is:
285 * for wrapped resources:
286 * the uniqueID will match that of the wrapped resource
287 *
288 * for deferred resources:
289 * the uniqueID will be different from the real resource, when it is allocated
290 * the proxy's uniqueID will not change across the instantiate call
291 *
292 * the uniqueIDs of the proxies and the resources draw from the same pool
293 *
294 * What this boils down to is that the uniqueID of a proxy can be used to consistently
295 * track/identify a proxy but should never be used to distinguish between
296 * resources and proxies - beware!
297 */
298 UniqueID uniqueID() const { return fUniqueID; }
robertphillips76948d42016-05-04 12:47:41 -0700299
Robert Phillips159e3c62017-06-19 12:02:00 -0400300 UniqueID underlyingUniqueID() const {
301 if (fTarget) {
302 return UniqueID(fTarget->uniqueID());
303 }
304
305 return fUniqueID;
306 }
307
Robert Phillips10d17212019-04-24 14:09:10 -0400308 virtual bool instantiate(GrResourceProvider*) = 0;
Robert Phillips37430132016-11-09 06:50:43 -0500309
Brian Salomon967df202018-12-07 11:15:53 -0500310 void deinstantiate();
Robert Phillips4bc70112018-03-01 10:24:02 -0500311
robertphillips76948d42016-05-04 12:47:41 -0700312 /**
Brian Salomon7d94bb52018-10-12 14:37:19 -0400313 * Proxies that are already instantiated and whose backing surface cannot be recycled to
314 * instantiate other proxies do not need to be considered by GrResourceAllocator.
315 */
316 bool canSkipResourceAllocator() const;
317
318 /**
robertphillips76948d42016-05-04 12:47:41 -0700319 * @return the texture proxy associated with the surface proxy, may be NULL.
320 */
321 virtual GrTextureProxy* asTextureProxy() { return nullptr; }
322 virtual const GrTextureProxy* asTextureProxy() const { return nullptr; }
323
324 /**
325 * @return the render target proxy associated with the surface proxy, may be NULL.
326 */
327 virtual GrRenderTargetProxy* asRenderTargetProxy() { return nullptr; }
328 virtual const GrRenderTargetProxy* asRenderTargetProxy() const { return nullptr; }
329
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400330 bool isInstantiated() const { return SkToBool(fTarget); }
331
332 // If the proxy is already instantiated, return its backing GrTexture; if not, return null.
333 GrSurface* peekSurface() const { return fTarget; }
334
335 // If this is a texture proxy and the proxy is already instantiated, return its backing
336 // GrTexture; if not, return null.
337 GrTexture* peekTexture() const { return fTarget ? fTarget->asTexture() : nullptr; }
338
339 // If this is a render target proxy and the proxy is already instantiated, return its backing
340 // GrRenderTarget; if not, return null.
341 GrRenderTarget* peekRenderTarget() const {
342 return fTarget ? fTarget->asRenderTarget() : nullptr;
343 }
344
robertphillips13a7eee2016-08-31 15:06:24 -0700345 /**
346 * Does the resource count against the resource budget?
347 */
348 SkBudgeted isBudgeted() const { return fBudgeted; }
349
Brian Salomonc67c31c2018-12-06 10:00:03 -0500350 /**
351 * The pixel values of this proxy's surface cannot be modified (e.g. doesn't support write
Brian Salomon9cadc312018-12-05 15:09:19 -0500352 * pixels or MIP map level regen). Read-only proxies also bypass interval tracking and
353 * assignment in GrResourceAllocator.
Brian Salomonc67c31c2018-12-06 10:00:03 -0500354 */
355 bool readOnly() const { return fSurfaceFlags & GrInternalSurfaceFlags::kReadOnly; }
356
Robert Phillipsf2361d22016-10-25 14:20:06 -0400357 void setLastOpList(GrOpList* opList);
358 GrOpList* getLastOpList() { return fLastOpList; }
359
Brian Osman45580d32016-11-23 09:37:01 -0500360 GrRenderTargetOpList* getLastRenderTargetOpList();
361 GrTextureOpList* getLastTextureOpList();
362
Robert Phillips8bc06d02016-11-01 17:28:40 -0400363 /**
Robert Phillipsf5442bb2017-04-17 14:18:34 -0400364 * Retrieves the amount of GPU memory that will be or currently is used by this resource
Robert Phillips8bc06d02016-11-01 17:28:40 -0400365 * in bytes. It is approximate since we aren't aware of additional padding or copies made
366 * by the driver.
367 *
368 * @return the amount of GPU memory used in bytes
369 */
370 size_t gpuMemorySize() const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500371 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Brian Salomonbb5711a2017-05-17 13:49:59 -0400372 if (fTarget) {
373 return fTarget->gpuMemorySize();
374 }
Robert Phillips8bc06d02016-11-01 17:28:40 -0400375 if (kInvalidGpuMemorySize == fGpuMemorySize) {
Brian Salomonbb5711a2017-05-17 13:49:59 -0400376 fGpuMemorySize = this->onUninstantiatedGpuMemorySize();
Robert Phillips8bc06d02016-11-01 17:28:40 -0400377 SkASSERT(kInvalidGpuMemorySize != fGpuMemorySize);
378 }
379 return fGpuMemorySize;
380 }
381
Greg Daniel46cfbc62019-06-07 11:43:30 -0400382 enum class RectsMustMatch : bool {
383 kNo = false,
384 kYes = true
385 };
386
Robert Phillipse2f7d182016-12-15 09:23:05 -0500387 // Helper function that creates a temporary SurfaceContext to perform the copy
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500388 // The copy is is not a render target and not multisampled.
Robert Phillipsd44146b2019-02-15 14:44:28 -0500389 static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped,
Greg Daniel46cfbc62019-06-07 11:43:30 -0400390 SkIRect srcRect, SkBackingFit, SkBudgeted,
391 RectsMustMatch = RectsMustMatch::kNo);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500392
393 // Copy the entire 'src'
Robert Phillipsd44146b2019-02-15 14:44:28 -0500394 static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped,
395 SkBackingFit, SkBudgeted);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500396
Robert Phillipseaa86252016-11-08 13:49:39 +0000397 bool isWrapped_ForTesting() const;
398
Robert Phillips292a6b22019-02-14 14:49:02 -0500399 SkDEBUGCODE(void validate(GrContext_Base*) const;)
Brian Osman45580d32016-11-23 09:37:01 -0500400
Robert Phillips757914d2017-01-25 15:48:30 -0500401 // Provides access to functions that aren't part of the public API.
Robert Phillips420c4cf2017-09-28 09:00:45 -0400402 inline GrSurfaceProxyPriv priv();
403 inline const GrSurfaceProxyPriv priv() const;
Robert Phillips757914d2017-01-25 15:48:30 -0500404
Brian Salomon01ceae92019-04-02 11:49:54 -0400405 /**
406 * Provides privileged access to select callers to be able to add a ref to a GrSurfaceProxy
407 * with zero refs.
408 */
409 class FirstRefAccess;
410 inline FirstRefAccess firstRefAccess();
411
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400412 GrInternalSurfaceFlags testingOnly_getFlags() const;
413
robertphillips76948d42016-05-04 12:47:41 -0700414protected:
robertphillips8abb3702016-08-31 14:04:06 -0700415 // Deferred version
Greg Daniel4065d452018-11-16 15:43:41 -0500416 GrSurfaceProxy(const GrBackendFormat& format, const GrSurfaceDesc& desc,
417 GrSurfaceOrigin origin, SkBackingFit fit,
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400418 SkBudgeted budgeted, GrInternalSurfaceFlags surfaceFlags)
Greg Daniel4065d452018-11-16 15:43:41 -0500419 : GrSurfaceProxy(nullptr, LazyInstantiationType::kSingleUse, format, desc, origin, fit,
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400420 budgeted, surfaceFlags) {
Robert Phillips294870f2016-11-11 12:38:40 -0500421 // Note: this ctor pulls a new uniqueID from the same pool at the GrGpuResources
robertphillips8abb3702016-08-31 14:04:06 -0700422 }
423
Chris Dalton706a6ff2017-11-29 22:01:06 -0700424 // Lazy-callback version
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400425 GrSurfaceProxy(LazyInstantiateCallback&&, LazyInstantiationType,
Greg Daniel4065d452018-11-16 15:43:41 -0500426 const GrBackendFormat& format, const GrSurfaceDesc&, GrSurfaceOrigin,
427 SkBackingFit, SkBudgeted, GrInternalSurfaceFlags);
Chris Dalton706a6ff2017-11-29 22:01:06 -0700428
Brian Salomonc67c31c2018-12-06 10:00:03 -0500429 // Wrapped version.
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400430 GrSurfaceProxy(sk_sp<GrSurface>, GrSurfaceOrigin, SkBackingFit);
robertphillips76948d42016-05-04 12:47:41 -0700431
Robert Phillipsf2361d22016-10-25 14:20:06 -0400432 virtual ~GrSurfaceProxy();
433
Robert Phillips757914d2017-01-25 15:48:30 -0500434 friend class GrSurfaceProxyPriv;
435
436 // Methods made available via GrSurfaceProxyPriv
Robert Phillips5f78adf2019-04-22 12:41:39 -0400437 bool ignoredByResourceAllocator() const { return fIgnoredByResourceAllocator; }
438 void setIgnoredByResourceAllocator() { fIgnoredByResourceAllocator = true; }
439
440 int32_t getProxyRefCnt() const { return this->internalGetProxyRefCnt(); }
441 int32_t getTotalRefs() const { return this->internalGetTotalRefs(); }
Robert Phillips715d08c2018-07-18 13:56:48 -0400442
Robert Phillips57aa3672017-07-21 11:38:13 -0400443 void computeScratchKey(GrScratchKey*) const;
444
Robert Phillips5af44de2017-07-18 14:49:38 -0400445 virtual sk_sp<GrSurface> createSurface(GrResourceProvider*) const = 0;
446 void assign(sk_sp<GrSurface> surface);
447
Robert Phillips65048132017-08-10 08:44:49 -0400448 sk_sp<GrSurface> createSurfaceImpl(GrResourceProvider*, int sampleCnt, bool needsStencil,
Robert Phillips10d17212019-04-24 14:09:10 -0400449 GrSurfaceDescFlags, GrMipMapped) const;
Robert Phillips5af44de2017-07-18 14:49:38 -0400450
Chris Daltonf91b7552019-04-29 16:21:18 -0600451 // Once the size of a fully-lazy proxy is decided, and before it gets instantiated, the client
452 // can use this optional method to specify the proxy's size. (A proxy's size can be less than
453 // the GPU surface that backs it. e.g., SkBackingFit::kApprox.) Otherwise, the proxy's size will
454 // be set to match the underlying GPU surface upon instantiation.
455 void setLazySize(int width, int height) {
456 SkASSERT(GrSurfaceProxy::LazyState::kFully == this->lazyInstantiationState());
457 SkASSERT(width > 0 && height > 0);
458 fWidth = width;
459 fHeight = height;
460 }
461
Robert Phillips65048132017-08-10 08:44:49 -0400462 bool instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt, bool needsStencil,
Robert Phillips10d17212019-04-24 14:09:10 -0400463 GrSurfaceDescFlags descFlags, GrMipMapped, const GrUniqueKey*);
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400464
Greg Daniele3204862018-04-16 11:24:10 -0400465 // In many cases these flags aren't actually known until the proxy has been instantiated.
466 // However, Ganesh frequently needs to change its behavior based on these settings. For
467 // internally create proxies we will know these properties ahead of time. For wrapped
468 // proxies we will copy the properties off of the GrSurface. For lazy proxies we force the
469 // call sites to provide the required information ahead of time. At instantiation time
470 // we verify that the assumed properties match the actual properties.
471 GrInternalSurfaceFlags fSurfaceFlags;
472
Chris Dalton706a6ff2017-11-29 22:01:06 -0700473private:
Greg Daniel4065d452018-11-16 15:43:41 -0500474 // For wrapped resources, 'fFormat', 'fConfig', 'fWidth', 'fHeight', and 'fOrigin; will always
475 // be filled in from the wrapped resource.
476 GrBackendFormat fFormat;
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400477 GrPixelConfig fConfig;
478 int fWidth;
479 int fHeight;
480 GrSurfaceOrigin fOrigin;
481 SkBackingFit fFit; // always kApprox for lazy-callback resources
482 // always kExact for wrapped resources
483 mutable SkBudgeted fBudgeted; // always kYes for lazy-callback resources
484 // set from the backing resource for wrapped resources
485 // mutable bc of SkSurface/SkImage wishy-washiness
Robert Phillipsa4c41b32017-03-15 13:02:45 -0400486
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400487 const UniqueID fUniqueID; // set from the backing resource for wrapped resources
robertphillips76948d42016-05-04 12:47:41 -0700488
Chris Dalton706a6ff2017-11-29 22:01:06 -0700489 LazyInstantiateCallback fLazyInstantiateCallback;
Greg Daniel457469c2018-02-08 15:05:44 -0500490 // If this is set to kSingleuse, then after one call to fLazyInstantiateCallback we will cleanup
491 // the lazy callback and then delete it. This will allow for any refs and resources being held
492 // by the standard function to be released. This is specifically useful in non-dll cases where
493 // we make lazy proxies and instantiate them immediately.
494 // Note: This is ignored if fLazyInstantiateCallback is null.
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400495 LazyInstantiationType fLazyInstantiationType;
Greg Daniel849dce12018-04-24 14:32:53 -0400496
497 SkDEBUGCODE(void validateSurface(const GrSurface*);)
498 SkDEBUGCODE(virtual void onValidateSurface(const GrSurface*) = 0;)
Chris Dalton706a6ff2017-11-29 22:01:06 -0700499
Robert Phillips8bc06d02016-11-01 17:28:40 -0400500 static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);
Robert Phillips29e52f12016-11-03 10:19:14 -0400501 SkDEBUGCODE(size_t getRawGpuMemorySize_debugOnly() const { return fGpuMemorySize; })
502
Brian Salomonbb5711a2017-05-17 13:49:59 -0400503 virtual size_t onUninstantiatedGpuMemorySize() const = 0;
Robert Phillips29e52f12016-11-03 10:19:14 -0400504
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400505 bool fNeedsClear;
Robert Phillips5f78adf2019-04-22 12:41:39 -0400506 bool fIgnoredByResourceAllocator = false;
Brian Salomond17b4a62017-05-23 16:53:47 -0400507
Robert Phillips8bc06d02016-11-01 17:28:40 -0400508 // This entry is lazily evaluated so, when the proxy wraps a resource, the resource
509 // will be called but, when the proxy is deferred, it will compute the answer itself.
510 // If the proxy computes its own answer that answer is checked (in debug mode) in
511 // the instantiation method.
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400512 mutable size_t fGpuMemorySize;
Robert Phillips8bc06d02016-11-01 17:28:40 -0400513
Robert Phillipsf2361d22016-10-25 14:20:06 -0400514 // The last opList that wrote to or is currently going to write to this surface
Robert Phillipsb6deea82017-05-11 14:14:30 -0400515 // The opList can be closed (e.g., no surface context is currently bound
516 // to this proxy).
Robert Phillipsf2361d22016-10-25 14:20:06 -0400517 // This back-pointer is required so that we can add a dependancy between
518 // the opList used to create the current contents of this surface
519 // and the opList of a destination surface to which this one is being drawn or copied.
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400520 // This pointer is unreffed. OpLists own a ref on their surface proxies.
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400521 GrOpList* fLastOpList;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400522
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400523 typedef GrIORefProxy INHERITED;
robertphillips76948d42016-05-04 12:47:41 -0700524};
525
Brian Salomon01ceae92019-04-02 11:49:54 -0400526class GrSurfaceProxy::FirstRefAccess {
527private:
Brian Salomon2c791fc2019-04-02 11:52:03 -0400528 void ref(GrResourceCache* cache) { fProxy->addInitialRef(cache); }
Brian Salomon01ceae92019-04-02 11:49:54 -0400529
530 FirstRefAccess(GrSurfaceProxy* proxy) : fProxy(proxy) {}
531
532 // No taking addresses of this type.
533 const FirstRefAccess* operator&() const = delete;
534 FirstRefAccess* operator&() = delete;
535
536 GrSurfaceProxy* fProxy;
537
538 friend class GrSurfaceProxy;
539 friend class GrProxyProvider;
540 friend class GrDeinstantiateProxyTracker;
541};
542
543inline GrSurfaceProxy::FirstRefAccess GrSurfaceProxy::firstRefAccess() {
544 return FirstRefAccess(this);
545}
546
robertphillips76948d42016-05-04 12:47:41 -0700547#endif