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