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