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/GrTextureProxy.h"
9 #include "src/gpu/GrTextureProxyPriv.h"
10
11 #include "include/gpu/GrDirectContext.h"
12 #include "src/gpu/GrDeferredProxyUploader.h"
13 #include "src/gpu/GrDirectContextPriv.h"
14 #include "src/gpu/GrGpuResourcePriv.h"
15 #include "src/gpu/GrProxyProvider.h"
16 #include "src/gpu/GrSurface.h"
17 #include "src/gpu/GrTexture.h"
18
19 // Deferred version - no data
GrTextureProxy(const GrBackendFormat & format,SkISize dimensions,GrMipmapped mipMapped,GrMipmapStatus mipmapStatus,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected,GrInternalSurfaceFlags surfaceFlags,UseAllocator useAllocator,GrDDLProvider creatingProvider)20 GrTextureProxy::GrTextureProxy(const GrBackendFormat& format,
21 SkISize dimensions,
22 GrMipmapped mipMapped,
23 GrMipmapStatus mipmapStatus,
24 SkBackingFit fit,
25 SkBudgeted budgeted,
26 GrProtected isProtected,
27 GrInternalSurfaceFlags surfaceFlags,
28 UseAllocator useAllocator,
29 GrDDLProvider creatingProvider)
30 : INHERITED(format, dimensions, fit, budgeted, isProtected, surfaceFlags, useAllocator)
31 , fMipmapped(mipMapped)
32 , fMipmapStatus(mipmapStatus)
33 SkDEBUGCODE(, fInitialMipmapStatus(fMipmapStatus))
34 , fCreatingProvider(creatingProvider)
35 , fProxyProvider(nullptr)
36 , fDeferredUploader(nullptr) {
37 SkASSERT(!(fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly));
38 if (this->textureType() == GrTextureType::kExternal) {
39 fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
40 }
41 }
42
43 // Lazy-callback version
GrTextureProxy(LazyInstantiateCallback && callback,const GrBackendFormat & format,SkISize dimensions,GrMipmapped mipMapped,GrMipmapStatus mipmapStatus,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected,GrInternalSurfaceFlags surfaceFlags,UseAllocator useAllocator,GrDDLProvider creatingProvider)44 GrTextureProxy::GrTextureProxy(LazyInstantiateCallback&& callback,
45 const GrBackendFormat& format,
46 SkISize dimensions,
47 GrMipmapped mipMapped,
48 GrMipmapStatus mipmapStatus,
49 SkBackingFit fit,
50 SkBudgeted budgeted,
51 GrProtected isProtected,
52 GrInternalSurfaceFlags surfaceFlags,
53 UseAllocator useAllocator,
54 GrDDLProvider creatingProvider)
55 : INHERITED(std::move(callback), format, dimensions, fit, budgeted, isProtected,
56 surfaceFlags, useAllocator)
57 , fMipmapped(mipMapped)
58 , fMipmapStatus(mipmapStatus)
59 SkDEBUGCODE(, fInitialMipmapStatus(fMipmapStatus))
60 , fCreatingProvider(creatingProvider)
61 , fProxyProvider(nullptr)
62 , fDeferredUploader(nullptr) {
63 SkASSERT(!(fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly));
64 if (this->textureType() == GrTextureType::kExternal) {
65 fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
66 }
67 }
68
69 // Wrapped version
GrTextureProxy(sk_sp<GrSurface> surf,UseAllocator useAllocator,GrDDLProvider creatingProvider)70 GrTextureProxy::GrTextureProxy(sk_sp<GrSurface> surf,
71 UseAllocator useAllocator,
72 GrDDLProvider creatingProvider)
73 : INHERITED(std::move(surf), SkBackingFit::kExact, useAllocator)
74 , fMipmapped(fTarget->asTexture()->mipmapped())
75 , fMipmapStatus(fTarget->asTexture()->mipmapStatus())
76 SkDEBUGCODE(, fInitialMipmapStatus(fMipmapStatus))
77 , fCreatingProvider(creatingProvider)
78 , fProxyProvider(nullptr)
79 , fDeferredUploader(nullptr) {
80 if (fTarget->getUniqueKey().isValid()) {
81 fProxyProvider = fTarget->asTexture()->getContext()->priv().proxyProvider();
82 fProxyProvider->adoptUniqueKeyFromSurface(this, fTarget.get());
83 }
84 if (this->textureType() == GrTextureType::kExternal) {
85 fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
86 }
87 }
88
~GrTextureProxy()89 GrTextureProxy::~GrTextureProxy() {
90 // Due to the order of cleanup the GrSurface this proxy may have wrapped may have gone away
91 // at this point. Zero out the pointer so the cache invalidation code doesn't try to use it.
92 fTarget = nullptr;
93
94 // In DDL-mode, uniquely keyed proxies keep their key even after their originating
95 // proxy provider has gone away. In that case there is noone to send the invalid key
96 // message to (Note: in this case we don't want to remove its cached resource).
97 if (fUniqueKey.isValid() && fProxyProvider) {
98 fProxyProvider->processInvalidUniqueKey(fUniqueKey, this,
99 GrProxyProvider::InvalidateGPUResource::kNo);
100 } else {
101 SkASSERT(!fProxyProvider);
102 }
103 }
104
instantiate(GrResourceProvider * resourceProvider)105 bool GrTextureProxy::instantiate(GrResourceProvider* resourceProvider) {
106 if (this->isLazy()) {
107 return false;
108 }
109 if (!this->instantiateImpl(resourceProvider, 1, GrRenderable::kNo, fMipmapped,
110 fUniqueKey.isValid() ? &fUniqueKey : nullptr)) {
111 return false;
112 }
113
114 SkASSERT(!this->peekRenderTarget());
115 SkASSERT(this->peekTexture());
116 return true;
117 }
118
createSurface(GrResourceProvider * resourceProvider) const119 sk_sp<GrSurface> GrTextureProxy::createSurface(GrResourceProvider* resourceProvider) const {
120 sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, 1, GrRenderable::kNo,
121 fMipmapped);
122 if (!surface) {
123 return nullptr;
124 }
125
126 if (fUserCacheTaget) {
127 if (!(surface->getUniqueKey().isValid()) && !(surface->resourcePriv().getScratchKey().isValid())) {
128 surface->resourcePriv().userRegisterResource();
129 }
130 }
131
132 SkASSERT(!surface->asRenderTarget());
133 SkASSERT(surface->asTexture());
134 return surface;
135 }
136
setDeferredUploader(std::unique_ptr<GrDeferredProxyUploader> uploader)137 void GrTextureProxyPriv::setDeferredUploader(std::unique_ptr<GrDeferredProxyUploader> uploader) {
138 SkASSERT(!fTextureProxy->fDeferredUploader);
139 fTextureProxy->fDeferredUploader = std::move(uploader);
140 }
141
scheduleUpload(GrOpFlushState * flushState)142 void GrTextureProxyPriv::scheduleUpload(GrOpFlushState* flushState) {
143 // The texture proxy's contents may already have been uploaded or instantiation may have failed
144 if (fTextureProxy->fDeferredUploader && fTextureProxy->isInstantiated()) {
145 fTextureProxy->fDeferredUploader->scheduleUpload(flushState, fTextureProxy);
146 }
147 }
148
resetDeferredUploader()149 void GrTextureProxyPriv::resetDeferredUploader() {
150 SkASSERT(fTextureProxy->fDeferredUploader);
151 fTextureProxy->fDeferredUploader.reset();
152 }
153
mipmapped() const154 GrMipmapped GrTextureProxy::mipmapped() const {
155 if (this->isInstantiated()) {
156 return this->peekTexture()->mipmapped();
157 }
158 return fMipmapped;
159 }
160
onUninstantiatedGpuMemorySize() const161 size_t GrTextureProxy::onUninstantiatedGpuMemorySize() const {
162 return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
163 /*colorSamplesPerPixel=*/1, this->proxyMipmapped(),
164 !this->priv().isExact());
165 }
166
ProxiesAreCompatibleAsDynamicState(const GrSurfaceProxy * first,const GrSurfaceProxy * second)167 bool GrTextureProxy::ProxiesAreCompatibleAsDynamicState(const GrSurfaceProxy* first,
168 const GrSurfaceProxy* second) {
169 // In order to be compatible, the proxies should also have the same texture type. This is
170 // checked explicitly since the GrBackendFormat == operator does not compare texture type
171 return first->backendFormat().textureType() == second->backendFormat().textureType() &&
172 first->backendFormat() == second->backendFormat();
173 }
174
setUniqueKey(GrProxyProvider * proxyProvider,const GrUniqueKey & key)175 void GrTextureProxy::setUniqueKey(GrProxyProvider* proxyProvider, const GrUniqueKey& key) {
176 SkASSERT(key.isValid());
177 SkASSERT(!fUniqueKey.isValid()); // proxies can only ever get one uniqueKey
178
179 if (fTarget && fSyncTargetKey) {
180 if (!fTarget->getUniqueKey().isValid()) {
181 fTarget->resourcePriv().setUniqueKey(key);
182 }
183 SkASSERT(fTarget->getUniqueKey() == key);
184 }
185
186 fUniqueKey = key;
187 fProxyProvider = proxyProvider;
188 }
189
clearUniqueKey()190 void GrTextureProxy::clearUniqueKey() {
191 fUniqueKey.reset();
192 fProxyProvider = nullptr;
193 }
194
callbackDesc() const195 GrSurfaceProxy::LazySurfaceDesc GrTextureProxy::callbackDesc() const {
196 SkISize dims;
197 SkBackingFit fit;
198 if (this->isFullyLazy()) {
199 fit = SkBackingFit::kApprox;
200 dims = {-1, -1};
201 } else {
202 fit = this->isFunctionallyExact() ? SkBackingFit::kExact : SkBackingFit::kApprox;
203 dims = this->dimensions();
204 }
205 return {
206 dims,
207 fit,
208 GrRenderable::kNo,
209 fMipmapped,
210 1,
211 this->backendFormat(),
212 this->textureType(),
213 this->isProtected(),
214 this->isBudgeted(),
215 };
216 }
217
218 #ifdef SK_DEBUG
onValidateSurface(const GrSurface * surface)219 void GrTextureProxy::onValidateSurface(const GrSurface* surface) {
220 SkASSERT(!surface->asRenderTarget());
221
222 // Anything that is checked here should be duplicated in GrTextureRenderTargetProxy's version
223 SkASSERT(surface->asTexture());
224 // It is possible to fulfill a non-mipmapped proxy with a mipmapped texture.
225 SkASSERT(GrMipmapped::kNo == this->proxyMipmapped() ||
226 GrMipmapped::kYes == surface->asTexture()->mipmapped());
227
228 SkASSERT(surface->asTexture()->textureType() == this->textureType());
229
230 GrInternalSurfaceFlags proxyFlags = fSurfaceFlags;
231 GrInternalSurfaceFlags surfaceFlags = surface->flags();
232 SkASSERT(((int)proxyFlags & kGrInternalTextureFlagsMask) ==
233 ((int)surfaceFlags & kGrInternalTextureFlagsMask));
234 }
235
236 #endif
237
238