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/GrOpsTask.h"
14 #include "src/gpu/GrRenderTarget.h"
15 #include "src/gpu/GrResourceProvider.h"
16 #include "src/gpu/GrSurface.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 
canChangeStencilAttachment() const92 bool GrRenderTargetProxy::canChangeStencilAttachment() const {
93     if (!fTarget) {
94         // If we aren't instantiated, then we definitely are an internal render target. Ganesh is
95         // free to change stencil attachments on internal render targets.
96         return true;
97     }
98     return fTarget->asRenderTarget()->canAttemptStencilAttachment();
99 }
100 
createSurface(GrResourceProvider * resourceProvider) const101 sk_sp<GrSurface> GrRenderTargetProxy::createSurface(GrResourceProvider* resourceProvider) const {
102     sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, fSampleCnt,
103                                                        GrRenderable::kYes, GrMipmapped::kNo);
104     if (!surface) {
105         return nullptr;
106     }
107     SkASSERT(surface->asRenderTarget());
108     SkASSERT(!surface->asTexture());
109     return surface;
110 }
111 
onUninstantiatedGpuMemorySize() const112 size_t GrRenderTargetProxy::onUninstantiatedGpuMemorySize() const {
113     int colorSamplesPerPixel = this->numSamples();
114     if (colorSamplesPerPixel > 1) {
115         // Add one for the resolve buffer.
116         ++colorSamplesPerPixel;
117     }
118 
119     // TODO: do we have enough information to improve this worst case estimate?
120     return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
121                                   colorSamplesPerPixel, GrMipmapped::kNo, !this->priv().isExact());
122 }
123 
refsWrappedObjects() const124 bool GrRenderTargetProxy::refsWrappedObjects() const {
125     if (!this->isInstantiated()) {
126         return false;
127     }
128 
129     GrSurface* surface = this->peekSurface();
130     return surface->resourcePriv().refsWrappedObjects();
131 }
132 
callbackDesc() const133 GrSurfaceProxy::LazySurfaceDesc GrRenderTargetProxy::callbackDesc() const {
134     // We only expect exactly sized lazy RT proxies.
135     SkASSERT(!this->isFullyLazy());
136     SkASSERT(this->isFunctionallyExact());
137     return {
138             this->dimensions(),
139             SkBackingFit::kExact,
140             GrRenderable::kYes,
141             GrMipmapped::kNo,
142             this->numSamples(),
143             this->backendFormat(),
144             this->isProtected(),
145             this->isBudgeted(),
146     };
147 }
148 
149 #ifdef SK_DEBUG
onValidateSurface(const GrSurface * surface)150 void GrRenderTargetProxy::onValidateSurface(const GrSurface* surface) {
151     // We do not check that surface->asTexture returns null since, when replaying DDLs we
152     // can fulfill a renderTarget-only proxy w/ a textureRenderTarget.
153 
154     // Anything that is checked here should be duplicated in GrTextureRenderTargetProxy's version
155     SkASSERT(surface->asRenderTarget());
156     SkASSERT(surface->asRenderTarget()->numSamples() == this->numSamples());
157 
158     GrInternalSurfaceFlags proxyFlags = fSurfaceFlags;
159     GrInternalSurfaceFlags surfaceFlags = surface->flags();
160     if (proxyFlags & GrInternalSurfaceFlags::kGLRTFBOIDIs0 && this->numSamples() == 1) {
161         // Ganesh never internally creates FBO0 proxies or surfaces so this must be a wrapped
162         // proxy. In this case, with no MSAA, rendering to FBO0 is strictly more limited than
163         // rendering to an arbitrary surface so we allow a non-FBO0 surface to be matched with
164         // the proxy.
165         surfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0;
166     }
167     SkASSERT(((int)proxyFlags & kGrInternalRenderTargetFlagsMask) ==
168              ((int)surfaceFlags & kGrInternalRenderTargetFlagsMask));
169 
170     // We manually check the kVkRTSupportsInputAttachment since we only require it on the surface if
171     // the proxy has it set. If the proxy doesn't have the flag it is legal for the surface to
172     // have the flag.
173     if (proxyFlags & GrInternalSurfaceFlags::kVkRTSupportsInputAttachment) {
174         SkASSERT(surfaceFlags & GrInternalSurfaceFlags::kVkRTSupportsInputAttachment);
175     }
176 }
177 #endif
178