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