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 "include/gpu/GrContext.h"
11#include "src/core/SkMathPriv.h"
12#include "src/gpu/GrCaps.h"
13#include "src/gpu/GrContextPriv.h"
14#include "src/gpu/GrGpuResourcePriv.h"
15#include "src/gpu/GrOpsTask.h"
16#include "src/gpu/GrRenderTargetPriv.h"
17#include "src/gpu/GrResourceProvider.h"
18#include "src/gpu/GrSurfacePriv.h"
19#include "src/gpu/GrTextureRenderTargetProxy.h"
20
21// Deferred version
22// TODO: we can probably munge the 'desc' in both the wrapped and deferred
23// cases to make the sampleConfig/numSamples stuff more rational.
24GrRenderTargetProxy::GrRenderTargetProxy(const GrCaps& caps,
25 const GrBackendFormat& format,
26 SkISize dimensions,
27 int sampleCount,
28 SkBackingFit fit,
29 SkBudgeted budgeted,
30 GrProtected isProtected,
31 GrInternalSurfaceFlags surfaceFlags,
32 UseAllocator useAllocator)
33 : INHERITED(format, dimensions, fit, budgeted, isProtected, surfaceFlags, useAllocator)
34 , fSampleCnt(sampleCount)
35 , fWrapsVkSecondaryCB(WrapsVkSecondaryCB::kNo) {}
36
37// Lazy-callback version
38GrRenderTargetProxy::GrRenderTargetProxy(LazyInstantiateCallback&& callback,
39 const GrBackendFormat& format,
40 SkISize dimensions,
41 int sampleCount,
42 SkBackingFit fit,
43 SkBudgeted budgeted,
44 GrProtected isProtected,
45 GrInternalSurfaceFlags surfaceFlags,
46 UseAllocator useAllocator,
47 WrapsVkSecondaryCB wrapsVkSecondaryCB)
48 : INHERITED(std::move(callback), format, dimensions, fit, budgeted, isProtected,
49 surfaceFlags, useAllocator)
50 , fSampleCnt(sampleCount)
51 , fWrapsVkSecondaryCB(wrapsVkSecondaryCB) {}
52
53// Wrapped version
54GrRenderTargetProxy::GrRenderTargetProxy(sk_sp<GrSurface> surf,
55 UseAllocator useAllocator,
56 WrapsVkSecondaryCB wrapsVkSecondaryCB)
57 : INHERITED(std::move(surf), SkBackingFit::kExact, useAllocator)
58 , fSampleCnt(fTarget->asRenderTarget()->numSamples())
59 , fWrapsVkSecondaryCB(wrapsVkSecondaryCB) {
60 // The kRequiresManualMSAAResolve flag better not be set if we are not multisampled or if
61 // MSAA resolve should happen automatically.
62 //
63 // From the other side, we don't know enough about the wrapped surface to assert when
64 // kRequiresManualMSAAResolve *should* be set. e.g., The caller might be wrapping a backend
65 // texture as a render target at this point but we wouldn't know it.
66 SkASSERT(!(this->numSamples() <= 1 ||
67 fTarget->getContext()->priv().caps()->msaaResolvesAutomatically()) ||
68 !this->requiresManualMSAAResolve());
69}
70
71int GrRenderTargetProxy::maxWindowRectangles(const GrCaps& caps) const {
72 return this->glRTFBOIDIs0() ? 0 : caps.maxWindowRectangles();
73}
74
75bool GrRenderTargetProxy::instantiate(GrResourceProvider* resourceProvider) {
76 if (this->isLazy()) {
77 return false;
78 }
79 if (!this->instantiateImpl(resourceProvider, fSampleCnt, GrRenderable::kYes, GrMipMapped::kNo,
80 nullptr)) {
81 return false;
82 }
83
84 SkASSERT(this->peekRenderTarget());
85 SkASSERT(!this->peekTexture());
86 return true;
87}
88
89bool GrRenderTargetProxy::canChangeStencilAttachment() const {
90 if (!fTarget) {
91 // If we aren't instantiated, then we definitely are an internal render target. Ganesh is
92 // free to change stencil attachments on internal render targets.
93 return true;
94 }
95 return fTarget->asRenderTarget()->canAttemptStencilAttachment();
96}
97
98sk_sp<GrSurface> GrRenderTargetProxy::createSurface(GrResourceProvider* resourceProvider) const {
99 sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, fSampleCnt,
100 GrRenderable::kYes, GrMipMapped::kNo);
101 if (!surface) {
102 return nullptr;
103 }
104 SkASSERT(surface->asRenderTarget());
105 SkASSERT(!surface->asTexture());
106 return surface;
107}
108
109size_t GrRenderTargetProxy::onUninstantiatedGpuMemorySize(const GrCaps& caps) const {
110 int colorSamplesPerPixel = this->numSamples();
111 if (colorSamplesPerPixel > 1) {
112 // Add one 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->dimensions(),
118 colorSamplesPerPixel, GrMipMapped::kNo, !this->priv().isExact());
119}
120
121bool GrRenderTargetProxy::refsWrappedObjects() const {
122 if (!this->isInstantiated()) {
123 return false;
124 }
125
126 GrSurface* surface = this->peekSurface();
127 return surface->resourcePriv().refsWrappedObjects();
128}
129
130#ifdef SK_DEBUG
131void GrRenderTargetProxy::onValidateSurface(const GrSurface* surface) {
132 // We do not check that surface->asTexture returns null since, when replaying DDLs we
133 // can fulfill a renderTarget-only proxy w/ a textureRenderTarget.
134
135 // Anything that is checked here should be duplicated in GrTextureRenderTargetProxy's version
136 SkASSERT(surface->asRenderTarget());
137 SkASSERT(surface->asRenderTarget()->numSamples() == this->numSamples());
138
139 GrInternalSurfaceFlags proxyFlags = fSurfaceFlags;
140 GrInternalSurfaceFlags surfaceFlags = surface->surfacePriv().flags();
141 if (proxyFlags & GrInternalSurfaceFlags::kGLRTFBOIDIs0 && this->numSamples() == 1) {
142 // Ganesh never internally creates FBO0 proxies or surfaces so this must be a wrapped
143 // proxy. In this case, with no MSAA, rendering to FBO0 is strictly more limited than
144 // rendering to an arbitrary surface so we allow a non-FBO0 surface to be matched with
145 // the proxy.
146 surfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0;
147 }
148 SkASSERT(((int)proxyFlags & kGrInternalRenderTargetFlagsMask) ==
149 ((int)surfaceFlags & kGrInternalRenderTargetFlagsMask));
150}
151#endif
152