xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrRenderTargetProxy.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 
8 #include "src/gpu/ganesh/GrRenderTargetProxy.h"
9 
10 #include "include/core/SkSize.h"
11 #include "include/gpu/GpuTypes.h"
12 #include "include/gpu/ganesh/GrBackendSurface.h"
13 #include "include/gpu/ganesh/GrTypes.h"
14 #include "include/private/base/SkTo.h"
15 #include "src/gpu/SkBackingFit.h"
16 #include "src/gpu/ganesh/GrCaps.h"
17 #include "src/gpu/ganesh/GrGpuResourcePriv.h"
18 #include "src/gpu/ganesh/GrRenderTarget.h"
19 #include "src/gpu/ganesh/GrSurface.h"
20 #include "src/gpu/ganesh/GrSurfaceProxyPriv.h"
21 
22 #include <utility>
23 
24 #ifdef SK_DEBUG
25 #include "include/gpu/ganesh/GrDirectContext.h"
26 #include "src/gpu/ganesh/GrDirectContextPriv.h"
27 #endif
28 
29 // Deferred version
30 // TODO: we can probably munge the 'desc' in both the wrapped and deferred
31 // cases to make the sampleConfig/numSamples stuff more rational.
GrRenderTargetProxy(const GrCaps & caps,const GrBackendFormat & format,SkISize dimensions,int sampleCount,SkBackingFit fit,skgpu::Budgeted budgeted,GrProtected isProtected,GrInternalSurfaceFlags surfaceFlags,UseAllocator useAllocator,std::string_view label)32 GrRenderTargetProxy::GrRenderTargetProxy(const GrCaps& caps,
33                                          const GrBackendFormat& format,
34                                          SkISize dimensions,
35                                          int sampleCount,
36                                          SkBackingFit fit,
37                                          skgpu::Budgeted budgeted,
38                                          GrProtected isProtected,
39                                          GrInternalSurfaceFlags surfaceFlags,
40                                          UseAllocator useAllocator,
41                                          std::string_view label)
42         : INHERITED(
43                   format, dimensions, fit, budgeted, isProtected, surfaceFlags, useAllocator, label)
44         , fSampleCnt(sampleCount)
45         , fWrapsVkSecondaryCB(WrapsVkSecondaryCB::kNo) {}
46 
47 // Lazy-callback version
GrRenderTargetProxy(LazyInstantiateCallback && callback,const GrBackendFormat & format,SkISize dimensions,int sampleCount,SkBackingFit fit,skgpu::Budgeted budgeted,GrProtected isProtected,GrInternalSurfaceFlags surfaceFlags,UseAllocator useAllocator,WrapsVkSecondaryCB wrapsVkSecondaryCB,std::string_view label)48 GrRenderTargetProxy::GrRenderTargetProxy(LazyInstantiateCallback&& callback,
49                                          const GrBackendFormat& format,
50                                          SkISize dimensions,
51                                          int sampleCount,
52                                          SkBackingFit fit,
53                                          skgpu::Budgeted budgeted,
54                                          GrProtected isProtected,
55                                          GrInternalSurfaceFlags surfaceFlags,
56                                          UseAllocator useAllocator,
57                                          WrapsVkSecondaryCB wrapsVkSecondaryCB,
58                                          std::string_view label)
59         : INHERITED(std::move(callback),
60                     format,
61                     dimensions,
62                     fit,
63                     budgeted,
64                     isProtected,
65                     surfaceFlags,
66                     useAllocator,
67                     label)
68         , fSampleCnt(sampleCount)
69         , fWrapsVkSecondaryCB(wrapsVkSecondaryCB) {}
70 
71 // Wrapped version
GrRenderTargetProxy(sk_sp<GrSurface> surf,UseAllocator useAllocator,WrapsVkSecondaryCB wrapsVkSecondaryCB)72 GrRenderTargetProxy::GrRenderTargetProxy(sk_sp<GrSurface> surf,
73                                          UseAllocator useAllocator,
74                                          WrapsVkSecondaryCB wrapsVkSecondaryCB)
75         : INHERITED(std::move(surf), SkBackingFit::kExact, useAllocator)
76         , fSampleCnt(fTarget->asRenderTarget()->numSamples())
77         , fWrapsVkSecondaryCB(wrapsVkSecondaryCB) {
78     // The kRequiresManualMSAAResolve flag better not be set if we are not multisampled or if
79     // MSAA resolve should happen automatically.
80     //
81     // From the other side, we don't know enough about the wrapped surface to assert when
82     // kRequiresManualMSAAResolve *should* be set. e.g., The caller might be wrapping a backend
83     // texture as a render target at this point but we wouldn't know it.
84     SkASSERT(!(this->numSamples() <= 1 ||
85                fTarget->getContext()->priv().caps()->msaaResolvesAutomatically()) ||
86              !this->requiresManualMSAAResolve());
87 }
88 
maxWindowRectangles(const GrCaps & caps) const89 int GrRenderTargetProxy::maxWindowRectangles(const GrCaps& caps) const {
90     return this->glRTFBOIDIs0() ? 0 : caps.maxWindowRectangles();
91 }
92 
instantiate(GrResourceProvider * resourceProvider)93 bool GrRenderTargetProxy::instantiate(GrResourceProvider* resourceProvider) {
94     if (this->isLazy()) {
95         return false;
96     }
97     if (!this->instantiateImpl(resourceProvider, fSampleCnt, GrRenderable::kYes,
98                                skgpu::Mipmapped::kNo, nullptr)) {
99         return false;
100     }
101 
102     SkASSERT(this->peekRenderTarget());
103     SkASSERT(!this->peekTexture());
104     return true;
105 }
106 
canUseStencil(const GrCaps & caps) const107 bool GrRenderTargetProxy::canUseStencil(const GrCaps& caps) const {
108     if (caps.avoidStencilBuffers() || this->wrapsVkSecondaryCB()) {
109         return false;
110     }
111     if (!this->isInstantiated()) {
112         if (this->isLazy() && this->backendFormat().backend() == GrBackendApi::kOpenGL) {
113             // It's possible for wrapped GL render targets to not have stencil. We don't currently
114             // have an exact way of knowing whether the target will be able to use stencil, so we do
115             // the best we can: if a lazy GL proxy doesn't have a texture, then it might be a
116             // wrapped target without stencil, so we conservatively block stencil.
117             // FIXME: skbug.com/11943: GrSurfaceCharacterization needs a "canUseStencil" flag.
118             return SkToBool(this->asTextureProxy());
119         } else {
120             // Otherwise the target will definitely not be wrapped. Ganesh is free to attach
121             // stencils on internal render targets.
122             return true;
123         }
124     }
125     // Just ask the actual target if we can use stencil.
126     GrRenderTarget* rt = this->peekRenderTarget();
127     // The dmsaa attachment (if any) always supports stencil. The real question is whether the
128     // non-dmsaa attachment supports stencil.
129     bool useMSAASurface = rt->numSamples() > 1;
130     return rt->getStencilAttachment(useMSAASurface) ||
131            rt->canAttemptStencilAttachment(useMSAASurface);
132 }
133 
createSurface(GrResourceProvider * resourceProvider) const134 sk_sp<GrSurface> GrRenderTargetProxy::createSurface(GrResourceProvider* resourceProvider) const {
135     sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, fSampleCnt,
136                                                        GrRenderable::kYes, skgpu::Mipmapped::kNo);
137     if (!surface) {
138         return nullptr;
139     }
140     SkASSERT(surface->asRenderTarget());
141     SkASSERT(!surface->asTexture());
142     return surface;
143 }
144 
onUninstantiatedGpuMemorySize() const145 size_t GrRenderTargetProxy::onUninstantiatedGpuMemorySize() const {
146     int colorSamplesPerPixel = this->numSamples();
147     if (colorSamplesPerPixel > 1) {
148         // Add one for the resolve buffer.
149         ++colorSamplesPerPixel;
150     }
151 
152     // TODO: do we have enough information to improve this worst case estimate?
153     return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
154                                   colorSamplesPerPixel, skgpu::Mipmapped::kNo,
155                                   !this->priv().isExact());
156 }
157 
refsWrappedObjects() const158 bool GrRenderTargetProxy::refsWrappedObjects() const {
159     if (!this->isInstantiated()) {
160         return false;
161     }
162 
163     GrSurface* surface = this->peekSurface();
164     return surface->resourcePriv().refsWrappedObjects();
165 }
166 
callbackDesc() const167 GrSurfaceProxy::LazySurfaceDesc GrRenderTargetProxy::callbackDesc() const {
168     // We only expect exactly sized lazy RT proxies.
169     SkASSERT(!this->isFullyLazy());
170     SkASSERT(this->isFunctionallyExact());
171     return {
172             this->dimensions(),
173             SkBackingFit::kExact,
174             GrRenderable::kYes,
175             skgpu::Mipmapped::kNo,
176             this->numSamples(),
177             this->backendFormat(),
178             GrTextureType::kNone,
179             this->isProtected(),
180             this->isBudgeted(),
181             this->getLabel(),
182     };
183 }
184 
185 #ifdef SK_DEBUG
onValidateSurface(const GrSurface * surface)186 void GrRenderTargetProxy::onValidateSurface(const GrSurface* surface) {
187     // We do not check that surface->asTexture returns null since, when replaying DDLs we
188     // can fulfill a renderTarget-only proxy w/ a textureRenderTarget.
189 
190     // Anything that is checked here should be duplicated in GrTextureRenderTargetProxy's version
191     SkASSERT(surface->asRenderTarget());
192     SkASSERT(surface->asRenderTarget()->numSamples() == this->numSamples());
193 
194     GrInternalSurfaceFlags proxyFlags = fSurfaceFlags;
195     GrInternalSurfaceFlags surfaceFlags = surface->flags();
196     if (proxyFlags & GrInternalSurfaceFlags::kGLRTFBOIDIs0 && this->numSamples() == 1) {
197         // Ganesh never internally creates FBO0 proxies or surfaces so this must be a wrapped
198         // proxy. In this case, with no MSAA, rendering to FBO0 is strictly more limited than
199         // rendering to an arbitrary surface so we allow a non-FBO0 surface to be matched with
200         // the proxy.
201         surfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0;
202     }
203     SkASSERT(((int)proxyFlags & kGrInternalRenderTargetFlagsMask) ==
204              ((int)surfaceFlags & kGrInternalRenderTargetFlagsMask));
205 
206     // We manually check the kVkRTSupportsInputAttachment since we only require it on the surface if
207     // the proxy has it set. If the proxy doesn't have the flag it is legal for the surface to
208     // have the flag.
209     if (proxyFlags & GrInternalSurfaceFlags::kVkRTSupportsInputAttachment) {
210         SkASSERT(surfaceFlags & GrInternalSurfaceFlags::kVkRTSupportsInputAttachment);
211     }
212 }
213 #endif
214