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