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