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