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