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 #ifdef SKIA_OHOS
101 //OH ISSUE :cache small Texture on UnUni devices
102 auto context = fProxyProvider->getfImageContext();
103 bool clearSmallTexture = true;
104 if (context) {
105 clearSmallTexture = context->priv().options().clearSmallTexture;
106 auto direct = context->asDirectContext();
107 if (direct) {
108 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
109 if (resourceProvider) {
110 invalidGpuResource = resourceProvider->findByUniqueKey<GrGpuResource>(fUniqueKey);
111 }
112 }
113 }
114 // less than 1024 Bytes resources will be delated
115 if (invalidGpuResource && clearSmallTexture && invalidGpuResource->gpuMemorySize() < 1024) {
116 fProxyProvider->processInvalidUniqueKey(
117 fUniqueKey, this, GrProxyProvider::InvalidateGPUResource::kYes);
118 } else {
119 fProxyProvider->processInvalidUniqueKey(
120 fUniqueKey, this, GrProxyProvider::InvalidateGPUResource::kNo);
121 }
122 #else
123 auto direct = fProxyProvider->getfImageContext()->asDirectContext();
124 if (direct) {
125 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
126 if (resourceProvider) {
127 invalidGpuResource = resourceProvider->findByUniqueKey<GrGpuResource>(fUniqueKey);
128 }
129 }
130 // less than 1024 Bytes resources will be delated
131 if (invalidGpuResource && invalidGpuResource->gpuMemorySize() < 1024) {
132 fProxyProvider->processInvalidUniqueKey(
133 fUniqueKey, this, GrProxyProvider::InvalidateGPUResource::kYes);
134 } else {
135 fProxyProvider->processInvalidUniqueKey(
136 fUniqueKey, this, GrProxyProvider::InvalidateGPUResource::kNo);
137 }
138 #endif
139 } else {
140 SkASSERT(!fProxyProvider);
141 }
142 }
143
instantiate(GrResourceProvider * resourceProvider)144 bool GrTextureProxy::instantiate(GrResourceProvider* resourceProvider) {
145 if (this->isLazy()) {
146 return false;
147 }
148 if (!this->instantiateImpl(resourceProvider, 1, GrRenderable::kNo, fMipmapped,
149 fUniqueKey.isValid() ? &fUniqueKey : nullptr)) {
150 return false;
151 }
152
153 SkASSERT(!this->peekRenderTarget());
154 SkASSERT(this->peekTexture());
155 return true;
156 }
157
createSurface(GrResourceProvider * resourceProvider) const158 sk_sp<GrSurface> GrTextureProxy::createSurface(GrResourceProvider* resourceProvider) const {
159 sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, 1, GrRenderable::kNo,
160 fMipmapped);
161 if (!surface) {
162 return nullptr;
163 }
164
165 if (fUserCacheTaget) {
166 if (!(surface->getUniqueKey().isValid()) && !(surface->resourcePriv().getScratchKey().isValid())) {
167 surface->resourcePriv().userRegisterResource();
168 }
169 }
170
171 SkASSERT(!surface->asRenderTarget());
172 SkASSERT(surface->asTexture());
173 return surface;
174 }
175
setDeferredUploader(std::unique_ptr<GrDeferredProxyUploader> uploader)176 void GrTextureProxyPriv::setDeferredUploader(std::unique_ptr<GrDeferredProxyUploader> uploader) {
177 SkASSERT(!fTextureProxy->fDeferredUploader);
178 fTextureProxy->fDeferredUploader = std::move(uploader);
179 }
180
scheduleUpload(GrOpFlushState * flushState)181 void GrTextureProxyPriv::scheduleUpload(GrOpFlushState* flushState) {
182 // The texture proxy's contents may already have been uploaded or instantiation may have failed
183 if (fTextureProxy->fDeferredUploader && fTextureProxy->isInstantiated()) {
184 fTextureProxy->fDeferredUploader->scheduleUpload(flushState, fTextureProxy);
185 }
186 }
187
resetDeferredUploader()188 void GrTextureProxyPriv::resetDeferredUploader() {
189 SkASSERT(fTextureProxy->fDeferredUploader);
190 fTextureProxy->fDeferredUploader.reset();
191 }
192
mipmapped() const193 GrMipmapped GrTextureProxy::mipmapped() const {
194 if (this->isInstantiated()) {
195 return this->peekTexture()->mipmapped();
196 }
197 return fMipmapped;
198 }
199
onUninstantiatedGpuMemorySize() const200 size_t GrTextureProxy::onUninstantiatedGpuMemorySize() const {
201 return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
202 /*colorSamplesPerPixel=*/1, this->proxyMipmapped(),
203 !this->priv().isExact());
204 }
205
ProxiesAreCompatibleAsDynamicState(const GrSurfaceProxy * first,const GrSurfaceProxy * second)206 bool GrTextureProxy::ProxiesAreCompatibleAsDynamicState(const GrSurfaceProxy* first,
207 const GrSurfaceProxy* second) {
208 // In order to be compatible, the proxies should also have the same texture type. This is
209 // checked explicitly since the GrBackendFormat == operator does not compare texture type
210 return first->backendFormat().textureType() == second->backendFormat().textureType() &&
211 first->backendFormat() == second->backendFormat();
212 }
213
setUniqueKey(GrProxyProvider * proxyProvider,const GrUniqueKey & key)214 void GrTextureProxy::setUniqueKey(GrProxyProvider* proxyProvider, const GrUniqueKey& key) {
215 SkASSERT(key.isValid());
216 SkASSERT(!fUniqueKey.isValid()); // proxies can only ever get one uniqueKey
217
218 if (fTarget && fSyncTargetKey) {
219 if (!fTarget->getUniqueKey().isValid()) {
220 fTarget->resourcePriv().setUniqueKey(key);
221 }
222 SkASSERT(fTarget->getUniqueKey() == key);
223 }
224
225 fUniqueKey = key;
226 fProxyProvider = proxyProvider;
227 }
228
clearUniqueKey()229 void GrTextureProxy::clearUniqueKey() {
230 fUniqueKey.reset();
231 fProxyProvider = nullptr;
232 }
233
callbackDesc() const234 GrSurfaceProxy::LazySurfaceDesc GrTextureProxy::callbackDesc() const {
235 SkISize dims;
236 SkBackingFit fit;
237 if (this->isFullyLazy()) {
238 fit = SkBackingFit::kApprox;
239 dims = {-1, -1};
240 } else {
241 fit = this->isFunctionallyExact() ? SkBackingFit::kExact : SkBackingFit::kApprox;
242 dims = this->dimensions();
243 }
244 return {
245 dims,
246 fit,
247 GrRenderable::kNo,
248 fMipmapped,
249 1,
250 this->backendFormat(),
251 this->textureType(),
252 this->isProtected(),
253 this->isBudgeted(),
254 };
255 }
256
257 #ifdef SK_DEBUG
onValidateSurface(const GrSurface * surface)258 void GrTextureProxy::onValidateSurface(const GrSurface* surface) {
259 SkASSERT(!surface->asRenderTarget());
260
261 // Anything that is checked here should be duplicated in GrTextureRenderTargetProxy's version
262 SkASSERT(surface->asTexture());
263 // It is possible to fulfill a non-mipmapped proxy with a mipmapped texture.
264 SkASSERT(GrMipmapped::kNo == this->proxyMipmapped() ||
265 GrMipmapped::kYes == surface->asTexture()->mipmapped());
266
267 SkASSERT(surface->asTexture()->textureType() == this->textureType());
268
269 GrInternalSurfaceFlags proxyFlags = fSurfaceFlags;
270 GrInternalSurfaceFlags surfaceFlags = surface->flags();
271 SkASSERT(((int)proxyFlags & kGrInternalTextureFlagsMask) ==
272 ((int)surfaceFlags & kGrInternalTextureFlagsMask));
273 }
274
275 #endif
276
277