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