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 "GrRenderTargetProxy.h"
9 
10 #include "GrCaps.h"
11 #include "GrGpuResourcePriv.h"
12 #include "GrRenderTargetOpList.h"
13 #include "GrRenderTargetPriv.h"
14 #include "GrResourceProvider.h"
15 #include "GrTextureRenderTargetProxy.h"
16 #include "SkMathPriv.h"
17 
18 // Deferred version
19 // TODO: we can probably munge the 'desc' in both the wrapped and deferred
20 // cases to make the sampleConfig/numSamples stuff more rational.
GrRenderTargetProxy(const GrCaps & caps,const GrSurfaceDesc & desc,SkBackingFit fit,SkBudgeted budgeted,uint32_t flags)21 GrRenderTargetProxy::GrRenderTargetProxy(const GrCaps& caps, const GrSurfaceDesc& desc,
22                                          SkBackingFit fit, SkBudgeted budgeted, uint32_t flags)
23         : INHERITED(desc, fit, budgeted, flags)
24         , fSampleCnt(desc.fSampleCnt)
25         , fNeedsStencil(false)
26         , fRenderTargetFlags(GrRenderTargetFlags::kNone) {
27     // Since we know the newly created render target will be internal, we are able to precompute
28     // what the flags will ultimately end up being.
29     if (caps.usesMixedSamples() && fSampleCnt > 1) {
30         fRenderTargetFlags |= GrRenderTargetFlags::kMixedSampled;
31     }
32     if (caps.maxWindowRectangles() > 0) {
33         fRenderTargetFlags |= GrRenderTargetFlags::kWindowRectsSupport;
34     }
35 }
36 
37 // Lazy-callback version
GrRenderTargetProxy(LazyInstantiateCallback && callback,LazyInstantiationType lazyType,const GrSurfaceDesc & desc,SkBackingFit fit,SkBudgeted budgeted,uint32_t flags,GrRenderTargetFlags renderTargetFlags)38 GrRenderTargetProxy::GrRenderTargetProxy(LazyInstantiateCallback&& callback,
39                                          LazyInstantiationType lazyType,
40                                          const GrSurfaceDesc& desc,
41                                          SkBackingFit fit, SkBudgeted budgeted,
42                                          uint32_t flags,
43                                          GrRenderTargetFlags renderTargetFlags)
44         : INHERITED(std::move(callback), lazyType, desc, fit, budgeted, flags)
45         , fSampleCnt(desc.fSampleCnt)
46         , fNeedsStencil(false)
47         , fRenderTargetFlags(renderTargetFlags) {
48     SkASSERT(SkToBool(kRenderTarget_GrSurfaceFlag & desc.fFlags));
49 }
50 
51 // Wrapped version
GrRenderTargetProxy(sk_sp<GrSurface> surf,GrSurfaceOrigin origin)52 GrRenderTargetProxy::GrRenderTargetProxy(sk_sp<GrSurface> surf, GrSurfaceOrigin origin)
53         : INHERITED(std::move(surf), origin, SkBackingFit::kExact)
54         , fSampleCnt(fTarget->asRenderTarget()->numStencilSamples())
55         , fNeedsStencil(false)
56         , fRenderTargetFlags(fTarget->asRenderTarget()->renderTargetPriv().flags()) {
57 }
58 
maxWindowRectangles(const GrCaps & caps) const59 int GrRenderTargetProxy::maxWindowRectangles(const GrCaps& caps) const {
60     return (fRenderTargetFlags & GrRenderTargetFlags::kWindowRectsSupport)
61                    ? caps.maxWindowRectangles()
62                    : 0;
63 }
64 
instantiate(GrResourceProvider * resourceProvider)65 bool GrRenderTargetProxy::instantiate(GrResourceProvider* resourceProvider) {
66     if (LazyState::kNot != this->lazyInstantiationState()) {
67         return false;
68     }
69     static constexpr GrSurfaceFlags kFlags = kRenderTarget_GrSurfaceFlag;
70 
71     if (!this->instantiateImpl(resourceProvider, fSampleCnt, fNeedsStencil, kFlags,
72                                GrMipMapped::kNo, nullptr)) {
73         return false;
74     }
75     SkASSERT(fTarget->asRenderTarget());
76     SkASSERT(!fTarget->asTexture());
77     // Check that our a priori computation matched the ultimate reality
78     SkASSERT(fRenderTargetFlags == fTarget->asRenderTarget()->renderTargetPriv().flags());
79 
80     return true;
81 }
82 
createSurface(GrResourceProvider * resourceProvider) const83 sk_sp<GrSurface> GrRenderTargetProxy::createSurface(GrResourceProvider* resourceProvider) const {
84     static constexpr GrSurfaceFlags kFlags = kRenderTarget_GrSurfaceFlag;
85 
86     sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, fSampleCnt, fNeedsStencil,
87                                                        kFlags, GrMipMapped::kNo);
88     if (!surface) {
89         return nullptr;
90     }
91     SkASSERT(surface->asRenderTarget());
92     SkASSERT(!surface->asTexture());
93     // Check that our a priori computation matched the ultimate reality
94     SkASSERT(fRenderTargetFlags == surface->asRenderTarget()->renderTargetPriv().flags());
95 
96     return surface;
97 }
98 
onUninstantiatedGpuMemorySize() const99 size_t GrRenderTargetProxy::onUninstantiatedGpuMemorySize() const {
100     int colorSamplesPerPixel = this->numColorSamples();
101     if (colorSamplesPerPixel > 1) {
102         // Add one for the resolve buffer.
103         ++colorSamplesPerPixel;
104     }
105 
106     // TODO: do we have enough information to improve this worst case estimate?
107     return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
108                                   colorSamplesPerPixel, GrMipMapped::kNo, !this->priv().isExact());
109 }
110 
refsWrappedObjects() const111 bool GrRenderTargetProxy::refsWrappedObjects() const {
112     if (!fTarget) {
113         return false;
114     }
115 
116     return fTarget->resourcePriv().refsWrappedObjects();
117 }
118 
119 #ifdef SK_DEBUG
validateLazySurface(const GrSurface * surface)120 void GrRenderTargetProxy::validateLazySurface(const GrSurface* surface) {
121     SkASSERT(!surface->asTexture());
122 
123     // Anything that is checked here should be duplicated in GrTextureRenderTargetProxy's version
124     SkASSERT(surface->asRenderTarget());
125     SkASSERT(surface->asRenderTarget()->numStencilSamples() == this->numStencilSamples());
126 }
127 #endif
128