xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrTextureRenderTargetProxy.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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