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