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