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/GrContextPriv.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.
27GrRenderTargetProxy::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
41GrRenderTargetProxy::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
57GrRenderTargetProxy::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
74int GrRenderTargetProxy::maxWindowRectangles(const GrCaps& caps) const {
75 return this->glRTFBOIDIs0() ? 0 : caps.maxWindowRectangles();
76}
77
78bool 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
92bool 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
101sk_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
112size_t GrRenderTargetProxy::onUninstantiatedGpuMemorySize(const GrCaps& caps) 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(caps, this->backendFormat(), this->dimensions(),
121 colorSamplesPerPixel, GrMipmapped::kNo, !this->priv().isExact());
122}
123
124bool GrRenderTargetProxy::refsWrappedObjects() const {
125 if (!this->isInstantiated()) {
126 return false;
127 }
128
129 GrSurface* surface = this->peekSurface();
130 return surface->resourcePriv().refsWrappedObjects();
131}
132
133GrSurfaceProxy::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
150void 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#endif
171