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
19GrTextureProxy::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
40GrTextureProxy::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
63GrTextureProxy::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
79GrTextureProxy::~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
95bool 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
109sk_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
121void GrTextureProxyPriv::setDeferredUploader(std::unique_ptr<GrDeferredProxyUploader> uploader) {
122 SkASSERT(!fTextureProxy->fDeferredUploader);
123 fTextureProxy->fDeferredUploader = std::move(uploader);
124}
125
126void 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
133void GrTextureProxyPriv::resetDeferredUploader() {
134 SkASSERT(fTextureProxy->fDeferredUploader);
135 fTextureProxy->fDeferredUploader.reset();
136}
137
138GrMipmapped GrTextureProxy::mipmapped() const {
139 if (this->isInstantiated()) {
140 return this->peekTexture()->mipmapped();
141 }
142 return fMipmapped;
143}
144
145size_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
150bool 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
158void 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
173void GrTextureProxy::clearUniqueKey() {
174 fUniqueKey.reset();
175 fProxyProvider = nullptr;
176}
177
178GrSurfaceProxy::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
201void 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