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