blob: 61dc9e1fea4722a039de667b942c385bd457ccdc [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
11#include "GrGpuResource.h"
Robert Phillipsc7635fa2016-10-28 13:25:24 -040012#include "GrSurface.h"
csmartdaltonbf4a8f92016-09-06 10:01:06 -070013#include "SkRect.h"
robertphillips76948d42016-05-04 12:47:41 -070014
Robert Phillips37430132016-11-09 06:50:43 -050015class GrCaps;
Brian Osman45580d32016-11-23 09:37:01 -050016class GrRenderTargetOpList;
17class GrRenderTargetProxy;
18class GrTextureOpList;
Robert Phillipseaa86252016-11-08 13:49:39 +000019class GrTextureProvider;
robertphillips76948d42016-05-04 12:47:41 -070020class GrTextureProxy;
robertphillips76948d42016-05-04 12:47:41 -070021
Robert Phillipsc7635fa2016-10-28 13:25:24 -040022// This class replicates the functionality GrIORef<GrSurface> but tracks the
23// utilitization for later resource allocation (for the deferred case) and
24// forwards on the utilization in the wrapped case
25class GrIORefProxy : public SkNoncopyable {
26public:
27 void ref() const {
28 this->validate();
29
30 ++fRefCnt;
31 if (fTarget) {
32 fTarget->ref();
33 }
34 }
35
36 void unref() const {
37 this->validate();
38
39 if (fTarget) {
40 fTarget->unref();
41 }
42
43 if (!(--fRefCnt)) {
44 delete this;
45 return;
46 }
47
48 this->validate();
49 }
50
51 void validate() const {
52#ifdef SK_DEBUG
robertphillips1125a032016-11-16 11:17:17 -080053 SkASSERT(fRefCnt >= 1);
54 SkASSERT(fPendingReads >= 0);
55 SkASSERT(fPendingWrites >= 0);
56 SkASSERT(fRefCnt + fPendingReads + fPendingWrites >= 1);
57
58 if (fTarget) {
59 SkASSERT(!fPendingReads && !fPendingWrites);
60 // The backing GrSurface can have more refs than the proxy if the proxy
61 // started off wrapping an external resource (that came in with refs).
62 // The GrSurface should never have fewer refs than the proxy however.
63 SkASSERT(fTarget->fRefCnt >= fRefCnt);
64 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -040065#endif
66 }
67
robertphillips1125a032016-11-16 11:17:17 -080068 int32_t getProxyRefCnt_TestOnly() const;
69 int32_t getBackingRefCnt_TestOnly() const;
70 int32_t getPendingReadCnt_TestOnly() const;
71 int32_t getPendingWriteCnt_TestOnly() const;
72
Robert Phillipsc7635fa2016-10-28 13:25:24 -040073protected:
robertphillips1125a032016-11-16 11:17:17 -080074 GrIORefProxy() : fTarget(nullptr), fRefCnt(1), fPendingReads(0), fPendingWrites(0) {}
75 GrIORefProxy(sk_sp<GrSurface> surface) : fRefCnt(1), fPendingReads(0), fPendingWrites(0) {
Robert Phillipsc7635fa2016-10-28 13:25:24 -040076 // Since we're manually forwarding on refs & unrefs we don't want sk_sp doing
77 // anything extra.
78 fTarget = surface.release();
79 }
80 virtual ~GrIORefProxy() {
81 // We don't unref 'fTarget' here since the 'unref' method will already
82 // have forwarded on the unref call that got use here.
83 }
84
robertphillips1125a032016-11-16 11:17:17 -080085 // This GrIORefProxy was deferred before but has just been instantiated. To
86 // make all the reffing & unreffing work out we now need to transfer any deferred
87 // refs & unrefs to the new GrSurface
88 void transferRefs() {
89 SkASSERT(fTarget);
90
91 fTarget->fRefCnt += (fRefCnt-1); // don't xfer the proxy's creation ref
92 fTarget->fPendingReads += fPendingReads;
93 fTarget->fPendingWrites += fPendingWrites;
94
95 fPendingReads = 0;
96 fPendingWrites = 0;
97 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -040098
99 // For deferred proxies this will be null. For wrapped proxies it will point to the
100 // wrapped resource.
101 GrSurface* fTarget;
robertphillips1125a032016-11-16 11:17:17 -0800102
103private:
104 // This class is used to manage conversion of refs to pending reads/writes.
105 friend class GrGpuResourceRef;
106 template <typename, GrIOType> friend class GrPendingIOResource;
107
108 void addPendingRead() const {
109 this->validate();
110
111 if (fTarget) {
112 fTarget->addPendingRead();
113 return;
114 }
115
116 ++fPendingReads;
117 }
118
119 void completedRead() const {
120 this->validate();
121
122 if (fTarget) {
123 fTarget->completedRead();
124 return;
125 }
126
127 SkFAIL("How was the read completed if the Proxy hasn't been instantiated?");
128 }
129
130 void addPendingWrite() const {
131 this->validate();
132
133 if (fTarget) {
134 fTarget->addPendingWrite();
135 return;
136 }
137
138 ++fPendingWrites;
139 }
140
141 void completedWrite() const {
142 this->validate();
143
144 if (fTarget) {
145 fTarget->completedWrite();
146 return;
147 }
148
149 SkFAIL("How was the write completed if the Proxy hasn't been instantiated?");
150 }
151
152 mutable int32_t fRefCnt;
153 mutable int32_t fPendingReads;
154 mutable int32_t fPendingWrites;
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400155};
156
157class GrSurfaceProxy : public GrIORefProxy {
robertphillips76948d42016-05-04 12:47:41 -0700158public:
Robert Phillips37430132016-11-09 06:50:43 -0500159 static sk_sp<GrSurfaceProxy> MakeWrapped(sk_sp<GrSurface>);
160
161 static sk_sp<GrSurfaceProxy> MakeDeferred(const GrCaps&, const GrSurfaceDesc&,
162 SkBackingFit, SkBudgeted);
163
164 // TODO: need to refine ownership semantics of 'srcData' if we're in completely
165 // deferred mode
166 static sk_sp<GrSurfaceProxy> MakeDeferred(const GrCaps&, GrTextureProvider*,
167 const GrSurfaceDesc&, SkBudgeted,
168 const void* srcData, size_t rowBytes);
169
robertphillips76948d42016-05-04 12:47:41 -0700170 const GrSurfaceDesc& desc() const { return fDesc; }
171
172 GrSurfaceOrigin origin() const {
173 SkASSERT(kTopLeft_GrSurfaceOrigin == fDesc.fOrigin ||
174 kBottomLeft_GrSurfaceOrigin == fDesc.fOrigin);
175 return fDesc.fOrigin;
176 }
177 int width() const { return fDesc.fWidth; }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400178 int height() const { return fDesc.fHeight; }
robertphillips76948d42016-05-04 12:47:41 -0700179 GrPixelConfig config() const { return fDesc.fConfig; }
180
Robert Phillips294870f2016-11-11 12:38:40 -0500181 class UniqueID {
182 public:
183 // wrapped
184 explicit UniqueID(const GrGpuResource::UniqueID& id) : fID(id.asUInt()) { }
185 // deferred
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
197 bool isInvalid() const { return SK_InvalidUniqueID == fID; }
198
199 private:
200 const uint32_t fID;
201 };
202
203 /*
204 * The contract for the uniqueID is:
205 * for wrapped resources:
206 * the uniqueID will match that of the wrapped resource
207 *
208 * for deferred resources:
209 * the uniqueID will be different from the real resource, when it is allocated
210 * the proxy's uniqueID will not change across the instantiate call
211 *
212 * the uniqueIDs of the proxies and the resources draw from the same pool
213 *
214 * What this boils down to is that the uniqueID of a proxy can be used to consistently
215 * track/identify a proxy but should never be used to distinguish between
216 * resources and proxies - beware!
217 */
218 UniqueID uniqueID() const { return fUniqueID; }
robertphillips76948d42016-05-04 12:47:41 -0700219
Robert Phillips37430132016-11-09 06:50:43 -0500220 GrSurface* instantiate(GrTextureProvider* texProvider);
221
robertphillips76948d42016-05-04 12:47:41 -0700222 /**
robertphillips13a7eee2016-08-31 15:06:24 -0700223 * Helper that gets the width and height of the surface as a bounding rectangle.
224 */
225 SkRect getBoundsRect() const { return SkRect::MakeIWH(this->width(), this->height()); }
226
227 /**
robertphillips76948d42016-05-04 12:47:41 -0700228 * @return the texture proxy associated with the surface proxy, may be NULL.
229 */
230 virtual GrTextureProxy* asTextureProxy() { return nullptr; }
231 virtual const GrTextureProxy* asTextureProxy() const { return nullptr; }
232
233 /**
234 * @return the render target proxy associated with the surface proxy, may be NULL.
235 */
236 virtual GrRenderTargetProxy* asRenderTargetProxy() { return nullptr; }
237 virtual const GrRenderTargetProxy* asRenderTargetProxy() const { return nullptr; }
238
robertphillips13a7eee2016-08-31 15:06:24 -0700239 /**
240 * Does the resource count against the resource budget?
241 */
242 SkBudgeted isBudgeted() const { return fBudgeted; }
243
Robert Phillipsf2361d22016-10-25 14:20:06 -0400244 void setLastOpList(GrOpList* opList);
245 GrOpList* getLastOpList() { return fLastOpList; }
246
Brian Osman45580d32016-11-23 09:37:01 -0500247 GrRenderTargetOpList* getLastRenderTargetOpList();
248 GrTextureOpList* getLastTextureOpList();
249
Robert Phillips8bc06d02016-11-01 17:28:40 -0400250 /**
251 * Retrieves the amount of GPU memory that will be or currently is used by this resource
252 * in bytes. It is approximate since we aren't aware of additional padding or copies made
253 * by the driver.
254 *
255 * @return the amount of GPU memory used in bytes
256 */
257 size_t gpuMemorySize() const {
Robert Phillips8bc06d02016-11-01 17:28:40 -0400258 if (kInvalidGpuMemorySize == fGpuMemorySize) {
259 fGpuMemorySize = this->onGpuMemorySize();
260 SkASSERT(kInvalidGpuMemorySize != fGpuMemorySize);
261 }
262 return fGpuMemorySize;
263 }
264
Robert Phillipseaa86252016-11-08 13:49:39 +0000265 bool isWrapped_ForTesting() const;
266
Brian Osman45580d32016-11-23 09:37:01 -0500267 SkDEBUGCODE(void validate(GrContext*) const;)
268
robertphillips76948d42016-05-04 12:47:41 -0700269protected:
robertphillips8abb3702016-08-31 14:04:06 -0700270 // Deferred version
robertphillips76948d42016-05-04 12:47:41 -0700271 GrSurfaceProxy(const GrSurfaceDesc& desc, SkBackingFit fit, SkBudgeted budgeted)
272 : fDesc(desc)
273 , fFit(fit)
274 , fBudgeted(budgeted)
Robert Phillips8bc06d02016-11-01 17:28:40 -0400275 , fGpuMemorySize(kInvalidGpuMemorySize)
Robert Phillipsf2361d22016-10-25 14:20:06 -0400276 , fLastOpList(nullptr) {
Robert Phillips294870f2016-11-11 12:38:40 -0500277 // Note: this ctor pulls a new uniqueID from the same pool at the GrGpuResources
robertphillips8abb3702016-08-31 14:04:06 -0700278 }
279
280 // Wrapped version
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400281 GrSurfaceProxy(sk_sp<GrSurface> surface, SkBackingFit fit);
robertphillips76948d42016-05-04 12:47:41 -0700282
Robert Phillipsf2361d22016-10-25 14:20:06 -0400283 virtual ~GrSurfaceProxy();
284
robertphillips76948d42016-05-04 12:47:41 -0700285 // For wrapped resources, 'fDesc' will always be filled in from the wrapped resource.
Robert Phillips294870f2016-11-11 12:38:40 -0500286 const GrSurfaceDesc fDesc;
287 const SkBackingFit fFit; // always exact for wrapped resources
288 const SkBudgeted fBudgeted; // set from the backing resource for wrapped resources
289 const UniqueID fUniqueID; // set from the backing resource for wrapped resources
robertphillips76948d42016-05-04 12:47:41 -0700290
Robert Phillips8bc06d02016-11-01 17:28:40 -0400291 static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);
Robert Phillips29e52f12016-11-03 10:19:14 -0400292 SkDEBUGCODE(size_t getRawGpuMemorySize_debugOnly() const { return fGpuMemorySize; })
293
294private:
295 virtual size_t onGpuMemorySize() const = 0;
296
Robert Phillips8bc06d02016-11-01 17:28:40 -0400297 // This entry is lazily evaluated so, when the proxy wraps a resource, the resource
298 // will be called but, when the proxy is deferred, it will compute the answer itself.
299 // If the proxy computes its own answer that answer is checked (in debug mode) in
300 // the instantiation method.
301 mutable size_t fGpuMemorySize;
302
Robert Phillipsf2361d22016-10-25 14:20:06 -0400303 // The last opList that wrote to or is currently going to write to this surface
Brian Osman11052242016-10-27 14:47:55 -0400304 // The opList can be closed (e.g., no render target context is currently bound
Robert Phillipsf2361d22016-10-25 14:20:06 -0400305 // to this renderTarget).
306 // This back-pointer is required so that we can add a dependancy between
307 // the opList used to create the current contents of this surface
308 // and the opList of a destination surface to which this one is being drawn or copied.
309 GrOpList* fLastOpList;
310
Robert Phillips29e52f12016-11-03 10:19:14 -0400311
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400312 typedef GrIORefProxy INHERITED;
robertphillips76948d42016-05-04 12:47:41 -0700313};
314
315#endif