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 #include "src/gpu/ganesh/GrTextureRenderTargetProxy.h"
9
10 #include "src/gpu/ganesh/GrCaps.h"
11 #include "src/gpu/ganesh/GrRenderTarget.h"
12 #include "src/gpu/ganesh/GrSurface.h"
13 #include "src/gpu/ganesh/GrSurfaceProxyPriv.h"
14 #include "src/gpu/ganesh/GrTexture.h"
15 #include "src/gpu/ganesh/GrTextureProxyPriv.h"
16
17 #ifdef SK_DEBUG
18 #include "include/gpu/GrDirectContext.h"
19 #include "src/gpu/ganesh/GrDirectContextPriv.h"
20 #endif
21
22 // Deferred version
23 // This class is virtually derived from GrSurfaceProxy (via both GrTextureProxy and
24 // GrRenderTargetProxy) so its constructor must be explicitly called.
GrTextureRenderTargetProxy(const GrCaps & caps,const GrBackendFormat & format,SkISize dimensions,int sampleCnt,GrMipmapped mipmapped,GrMipmapStatus mipmapStatus,SkBackingFit fit,skgpu::Budgeted budgeted,GrProtected isProtected,GrInternalSurfaceFlags surfaceFlags,UseAllocator useAllocator,GrDDLProvider creatingProvider,std::string_view label)25 GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps,
26 const GrBackendFormat& format,
27 SkISize dimensions,
28 int sampleCnt,
29 GrMipmapped mipmapped,
30 GrMipmapStatus mipmapStatus,
31 SkBackingFit fit,
32 skgpu::Budgeted budgeted,
33 GrProtected isProtected,
34 GrInternalSurfaceFlags surfaceFlags,
35 UseAllocator useAllocator,
36 GrDDLProvider creatingProvider,
37 std::string_view label)
38 : GrSurfaceProxy(
39 format, dimensions, fit, budgeted, isProtected, surfaceFlags, useAllocator, label)
40 // for now textures w/ data are always wrapped
41 , GrRenderTargetProxy(caps,
42 format,
43 dimensions,
44 sampleCnt,
45 fit,
46 budgeted,
47 isProtected,
48 surfaceFlags,
49 useAllocator,
50 label)
51 , GrTextureProxy(format,
52 dimensions,
53 mipmapped,
54 mipmapStatus,
55 fit,
56 budgeted,
57 isProtected,
58 surfaceFlags,
59 useAllocator,
60 creatingProvider,
61 label) {
62 this->initSurfaceFlags(caps);
63 }
64
65 // Lazy-callback version
GrTextureRenderTargetProxy(const GrCaps & caps,LazyInstantiateCallback && callback,const GrBackendFormat & format,SkISize dimensions,int sampleCnt,GrMipmapped mipmapped,GrMipmapStatus mipmapStatus,SkBackingFit fit,skgpu::Budgeted budgeted,GrProtected isProtected,GrInternalSurfaceFlags surfaceFlags,UseAllocator useAllocator,GrDDLProvider creatingProvider,std::string_view label)66 GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps,
67 LazyInstantiateCallback&& callback,
68 const GrBackendFormat& format,
69 SkISize dimensions,
70 int sampleCnt,
71 GrMipmapped mipmapped,
72 GrMipmapStatus mipmapStatus,
73 SkBackingFit fit,
74 skgpu::Budgeted budgeted,
75 GrProtected isProtected,
76 GrInternalSurfaceFlags surfaceFlags,
77 UseAllocator useAllocator,
78 GrDDLProvider creatingProvider,
79 std::string_view label)
80 : GrSurfaceProxy(std::move(callback),
81 format,
82 dimensions,
83 fit,
84 budgeted,
85 isProtected,
86 surfaceFlags,
87 useAllocator,
88 label)
89 // Since we have virtual inheritance, we initialize GrSurfaceProxy directly. Send null
90 // callbacks to the texture and RT proxies simply to route to the appropriate constructors.
91 , GrRenderTargetProxy(LazyInstantiateCallback(),
92 format,
93 dimensions,
94 sampleCnt,
95 fit,
96 budgeted,
97 isProtected,
98 surfaceFlags,
99 useAllocator,
100 WrapsVkSecondaryCB::kNo,
101 label)
102 , GrTextureProxy(LazyInstantiateCallback(),
103 format,
104 dimensions,
105 mipmapped,
106 mipmapStatus,
107 fit,
108 budgeted,
109 isProtected,
110 surfaceFlags,
111 useAllocator,
112 creatingProvider,
113 label) {
114 this->initSurfaceFlags(caps);
115 }
116
117 // Wrapped version
118 // This class is virtually derived from GrSurfaceProxy (via both GrTextureProxy and
119 // GrRenderTargetProxy) so its constructor must be explicitly called.
GrTextureRenderTargetProxy(sk_sp<GrSurface> surf,UseAllocator useAllocator,GrDDLProvider creatingProvider)120 GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(sk_sp<GrSurface> surf,
121 UseAllocator useAllocator,
122 GrDDLProvider creatingProvider)
123 : GrSurfaceProxy(surf, SkBackingFit::kExact, useAllocator)
124 , GrRenderTargetProxy(surf, useAllocator)
125 , GrTextureProxy(surf, useAllocator, creatingProvider) {
126 SkASSERT(surf->asTexture());
127 SkASSERT(surf->asRenderTarget());
128 SkASSERT(fSurfaceFlags == fTarget->flags());
129 SkASSERT((this->numSamples() <= 1 ||
130 fTarget->getContext()->priv().caps()->msaaResolvesAutomatically()) !=
131 this->requiresManualMSAAResolve());
132 }
133
initSurfaceFlags(const GrCaps & caps)134 void GrTextureRenderTargetProxy::initSurfaceFlags(const GrCaps& caps) {
135 // FBO 0 should never be wrapped as a texture render target.
136 SkASSERT(!this->glRTFBOIDIs0());
137 if (this->numSamples() > 1 && !caps.msaaResolvesAutomatically()) {
138 // MSAA texture-render-targets always require manual resolve if we are not using a
139 // multisampled-render-to-texture extension.
140 //
141 // NOTE: This is the only instance where we need to set the manual resolve flag on a proxy.
142 // Any other proxies that require manual resolve (e.g., wrapRenderableBackendTexture() with
143 // a sample count) will be wrapped, and the wrapped version of the GrSurface constructor
144 // will automatically get the manual resolve flag when copying the target GrSurface's flags.
145 fSurfaceFlags |= GrInternalSurfaceFlags::kRequiresManualMSAAResolve;
146 }
147 }
148
onUninstantiatedGpuMemorySize() const149 size_t GrTextureRenderTargetProxy::onUninstantiatedGpuMemorySize() const {
150 int colorSamplesPerPixel = this->numSamples();
151 if (colorSamplesPerPixel > 1) {
152 // Add one to account for the resolve buffer.
153 ++colorSamplesPerPixel;
154 }
155
156 // TODO: do we have enough information to improve this worst case estimate?
157 return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
158 colorSamplesPerPixel, this->proxyMipmapped(),
159 !this->priv().isExact());
160 }
161
instantiate(GrResourceProvider * resourceProvider)162 bool GrTextureRenderTargetProxy::instantiate(GrResourceProvider* resourceProvider) {
163 if (this->isLazy()) {
164 return false;
165 }
166
167 const skgpu::UniqueKey& key = this->getUniqueKey();
168
169 if (!this->instantiateImpl(resourceProvider, this->numSamples(), GrRenderable::kYes,
170 this->mipmapped(), key.isValid() ? &key : nullptr)) {
171 return false;
172 }
173 if (key.isValid()) {
174 SkASSERT(key == this->getUniqueKey());
175 }
176
177 SkASSERT(this->peekRenderTarget());
178 SkASSERT(this->peekTexture());
179
180 return true;
181 }
182
createSurface(GrResourceProvider * resourceProvider) const183 sk_sp<GrSurface> GrTextureRenderTargetProxy::createSurface(
184 GrResourceProvider* resourceProvider) const {
185 sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, this->numSamples(),
186 GrRenderable::kYes, this->mipmapped());
187 if (!surface) {
188 return nullptr;
189 }
190 SkASSERT(surface->asRenderTarget());
191 SkASSERT(surface->asTexture());
192
193 return surface;
194 }
195
callbackDesc() const196 GrSurfaceProxy::LazySurfaceDesc GrTextureRenderTargetProxy::callbackDesc() const {
197 SkISize dims;
198 SkBackingFit fit;
199 if (this->isFullyLazy()) {
200 fit = SkBackingFit::kApprox;
201 dims = {-1, -1};
202 } else {
203 fit = this->isFunctionallyExact() ? SkBackingFit::kExact : SkBackingFit::kApprox;
204 dims = this->dimensions();
205 }
206 return {
207 dims,
208 fit,
209 GrRenderable::kYes,
210 this->mipmapped(),
211 this->numSamples(),
212 this->backendFormat(),
213 this->textureType(),
214 this->isProtected(),
215 this->isBudgeted(),
216 this->getLabel(),
217 };
218 }
219
220 #ifdef SK_DEBUG
onValidateSurface(const GrSurface * surface)221 void GrTextureRenderTargetProxy::onValidateSurface(const GrSurface* surface) {
222 // Anything checked here should also be checking the GrTextureProxy version
223 SkASSERT(surface->asTexture());
224 SkASSERT(GrMipmapped::kNo == this->proxyMipmapped() ||
225 GrMipmapped::kYes == surface->asTexture()->mipmapped());
226
227 // Anything checked here should also be checking the GrRenderTargetProxy version
228 SkASSERT(surface->asRenderTarget());
229 SkASSERT(surface->asRenderTarget()->numSamples() == this->numSamples());
230
231 SkASSERT(surface->asTexture()->textureType() == this->textureType());
232
233 GrInternalSurfaceFlags proxyFlags = fSurfaceFlags;
234 GrInternalSurfaceFlags surfaceFlags = surface->flags();
235
236 // Only non-RT textures can be read only.
237 SkASSERT(!(proxyFlags & GrInternalSurfaceFlags::kReadOnly));
238 SkASSERT(!(surfaceFlags & GrInternalSurfaceFlags::kReadOnly));
239
240 SkASSERT(((int)proxyFlags & kGrInternalTextureRenderTargetFlagsMask) ==
241 ((int)surfaceFlags & kGrInternalTextureRenderTargetFlagsMask));
242
243 // We manually check the kVkRTSupportsInputAttachment since we only require it on the surface if
244 // the proxy has it set. If the proxy doesn't have the flag it is legal for the surface to
245 // have the flag.
246 if (proxyFlags & GrInternalSurfaceFlags::kVkRTSupportsInputAttachment) {
247 SkASSERT(surfaceFlags & GrInternalSurfaceFlags::kVkRTSupportsInputAttachment);
248 }
249 }
250 #endif
251
252