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