blob: dd5ece1e2c025ca66040f40ea979cda976d13095 [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;
Robert Phillipsf2361d22016-10-25 14:20:06 -040016class GrOpList;
Robert Phillipseaa86252016-11-08 13:49:39 +000017class GrTextureProvider;
robertphillips76948d42016-05-04 12:47:41 -070018class GrTextureProxy;
19class GrRenderTargetProxy;
Robert Phillips37430132016-11-09 06:50:43 -050020class GrTextureProvider;
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
53 SkASSERT(fRefCnt >= 0);
54#endif
55 }
56
57protected:
58 GrIORefProxy() : fRefCnt(1), fTarget(nullptr) {}
59 GrIORefProxy(sk_sp<GrSurface> surface) : fRefCnt(1) {
60 // Since we're manually forwarding on refs & unrefs we don't want sk_sp doing
61 // anything extra.
62 fTarget = surface.release();
63 }
64 virtual ~GrIORefProxy() {
65 // We don't unref 'fTarget' here since the 'unref' method will already
66 // have forwarded on the unref call that got use here.
67 }
68
69 // TODO: add the IO ref counts. Although if we can delay shader creation to flush time
70 // we may not even need to do that.
71 mutable int32_t fRefCnt;
72
73 // For deferred proxies this will be null. For wrapped proxies it will point to the
74 // wrapped resource.
75 GrSurface* fTarget;
76};
77
78class GrSurfaceProxy : public GrIORefProxy {
robertphillips76948d42016-05-04 12:47:41 -070079public:
Robert Phillips37430132016-11-09 06:50:43 -050080 static sk_sp<GrSurfaceProxy> MakeWrapped(sk_sp<GrSurface>);
81
82 static sk_sp<GrSurfaceProxy> MakeDeferred(const GrCaps&, const GrSurfaceDesc&,
83 SkBackingFit, SkBudgeted);
84
85 // TODO: need to refine ownership semantics of 'srcData' if we're in completely
86 // deferred mode
87 static sk_sp<GrSurfaceProxy> MakeDeferred(const GrCaps&, GrTextureProvider*,
88 const GrSurfaceDesc&, SkBudgeted,
89 const void* srcData, size_t rowBytes);
90
robertphillips76948d42016-05-04 12:47:41 -070091 const GrSurfaceDesc& desc() const { return fDesc; }
92
93 GrSurfaceOrigin origin() const {
94 SkASSERT(kTopLeft_GrSurfaceOrigin == fDesc.fOrigin ||
95 kBottomLeft_GrSurfaceOrigin == fDesc.fOrigin);
96 return fDesc.fOrigin;
97 }
98 int width() const { return fDesc.fWidth; }
Robert Phillipsc7635fa2016-10-28 13:25:24 -040099 int height() const { return fDesc.fHeight; }
robertphillips76948d42016-05-04 12:47:41 -0700100 GrPixelConfig config() const { return fDesc.fConfig; }
101
Robert Phillips294870f2016-11-11 12:38:40 -0500102 class UniqueID {
103 public:
104 // wrapped
105 explicit UniqueID(const GrGpuResource::UniqueID& id) : fID(id.asUInt()) { }
106 // deferred
107 UniqueID() : fID(GrGpuResource::CreateUniqueID()) { }
108
109 uint32_t asUInt() const { return fID; }
110
111 bool operator==(const UniqueID& other) const {
112 return fID == other.fID;
113 }
114 bool operator!=(const UniqueID& other) const {
115 return !(*this == other);
116 }
117
118 bool isInvalid() const { return SK_InvalidUniqueID == fID; }
119
120 private:
121 const uint32_t fID;
122 };
123
124 /*
125 * The contract for the uniqueID is:
126 * for wrapped resources:
127 * the uniqueID will match that of the wrapped resource
128 *
129 * for deferred resources:
130 * the uniqueID will be different from the real resource, when it is allocated
131 * the proxy's uniqueID will not change across the instantiate call
132 *
133 * the uniqueIDs of the proxies and the resources draw from the same pool
134 *
135 * What this boils down to is that the uniqueID of a proxy can be used to consistently
136 * track/identify a proxy but should never be used to distinguish between
137 * resources and proxies - beware!
138 */
139 UniqueID uniqueID() const { return fUniqueID; }
robertphillips76948d42016-05-04 12:47:41 -0700140
Robert Phillips37430132016-11-09 06:50:43 -0500141 GrSurface* instantiate(GrTextureProvider* texProvider);
142
robertphillips76948d42016-05-04 12:47:41 -0700143 /**
robertphillips13a7eee2016-08-31 15:06:24 -0700144 * Helper that gets the width and height of the surface as a bounding rectangle.
145 */
146 SkRect getBoundsRect() const { return SkRect::MakeIWH(this->width(), this->height()); }
147
148 /**
robertphillips76948d42016-05-04 12:47:41 -0700149 * @return the texture proxy associated with the surface proxy, may be NULL.
150 */
151 virtual GrTextureProxy* asTextureProxy() { return nullptr; }
152 virtual const GrTextureProxy* asTextureProxy() const { return nullptr; }
153
154 /**
155 * @return the render target proxy associated with the surface proxy, may be NULL.
156 */
157 virtual GrRenderTargetProxy* asRenderTargetProxy() { return nullptr; }
158 virtual const GrRenderTargetProxy* asRenderTargetProxy() const { return nullptr; }
159
robertphillips13a7eee2016-08-31 15:06:24 -0700160 /**
161 * Does the resource count against the resource budget?
162 */
163 SkBudgeted isBudgeted() const { return fBudgeted; }
164
Robert Phillipsf2361d22016-10-25 14:20:06 -0400165 void setLastOpList(GrOpList* opList);
166 GrOpList* getLastOpList() { return fLastOpList; }
167
Robert Phillips8bc06d02016-11-01 17:28:40 -0400168 /**
169 * Retrieves the amount of GPU memory that will be or currently is used by this resource
170 * in bytes. It is approximate since we aren't aware of additional padding or copies made
171 * by the driver.
172 *
173 * @return the amount of GPU memory used in bytes
174 */
175 size_t gpuMemorySize() const {
Robert Phillips8bc06d02016-11-01 17:28:40 -0400176 if (kInvalidGpuMemorySize == fGpuMemorySize) {
177 fGpuMemorySize = this->onGpuMemorySize();
178 SkASSERT(kInvalidGpuMemorySize != fGpuMemorySize);
179 }
180 return fGpuMemorySize;
181 }
182
Robert Phillipseaa86252016-11-08 13:49:39 +0000183 bool isWrapped_ForTesting() const;
184
robertphillips76948d42016-05-04 12:47:41 -0700185protected:
robertphillips8abb3702016-08-31 14:04:06 -0700186 // Deferred version
robertphillips76948d42016-05-04 12:47:41 -0700187 GrSurfaceProxy(const GrSurfaceDesc& desc, SkBackingFit fit, SkBudgeted budgeted)
188 : fDesc(desc)
189 , fFit(fit)
190 , fBudgeted(budgeted)
Robert Phillips8bc06d02016-11-01 17:28:40 -0400191 , fGpuMemorySize(kInvalidGpuMemorySize)
Robert Phillipsf2361d22016-10-25 14:20:06 -0400192 , fLastOpList(nullptr) {
Robert Phillips294870f2016-11-11 12:38:40 -0500193 // Note: this ctor pulls a new uniqueID from the same pool at the GrGpuResources
robertphillips8abb3702016-08-31 14:04:06 -0700194 }
195
196 // Wrapped version
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400197 GrSurfaceProxy(sk_sp<GrSurface> surface, SkBackingFit fit);
robertphillips76948d42016-05-04 12:47:41 -0700198
Robert Phillipsf2361d22016-10-25 14:20:06 -0400199 virtual ~GrSurfaceProxy();
200
robertphillips76948d42016-05-04 12:47:41 -0700201 // For wrapped resources, 'fDesc' will always be filled in from the wrapped resource.
Robert Phillips294870f2016-11-11 12:38:40 -0500202 const GrSurfaceDesc fDesc;
203 const SkBackingFit fFit; // always exact for wrapped resources
204 const SkBudgeted fBudgeted; // set from the backing resource for wrapped resources
205 const UniqueID fUniqueID; // set from the backing resource for wrapped resources
robertphillips76948d42016-05-04 12:47:41 -0700206
Robert Phillips8bc06d02016-11-01 17:28:40 -0400207 static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);
Robert Phillips29e52f12016-11-03 10:19:14 -0400208 SkDEBUGCODE(size_t getRawGpuMemorySize_debugOnly() const { return fGpuMemorySize; })
209
210private:
211 virtual size_t onGpuMemorySize() const = 0;
212
Robert Phillips8bc06d02016-11-01 17:28:40 -0400213 // This entry is lazily evaluated so, when the proxy wraps a resource, the resource
214 // will be called but, when the proxy is deferred, it will compute the answer itself.
215 // If the proxy computes its own answer that answer is checked (in debug mode) in
216 // the instantiation method.
217 mutable size_t fGpuMemorySize;
218
Robert Phillipsf2361d22016-10-25 14:20:06 -0400219 // The last opList that wrote to or is currently going to write to this surface
Brian Osman11052242016-10-27 14:47:55 -0400220 // The opList can be closed (e.g., no render target context is currently bound
Robert Phillipsf2361d22016-10-25 14:20:06 -0400221 // to this renderTarget).
222 // This back-pointer is required so that we can add a dependancy between
223 // the opList used to create the current contents of this surface
224 // and the opList of a destination surface to which this one is being drawn or copied.
225 GrOpList* fLastOpList;
226
Robert Phillips29e52f12016-11-03 10:19:14 -0400227
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400228 typedef GrIORefProxy INHERITED;
robertphillips76948d42016-05-04 12:47:41 -0700229};
230
231#endif