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