1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h" 11cb93a386Sopenharmony_ci#include "include/core/SkImage.h" 12cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 13cb93a386Sopenharmony_ci#include "include/private/GrImageContext.h" 14cb93a386Sopenharmony_ci#include "include/private/GrResourceKey.h" 15cb93a386Sopenharmony_ci#include "include/private/GrSingleOwner.h" 16cb93a386Sopenharmony_ci#include "include/private/SkImageInfoPriv.h" 17cb93a386Sopenharmony_ci#include "src/core/SkAutoPixmapStorage.h" 18cb93a386Sopenharmony_ci#include "src/core/SkCompressedDataUtils.h" 19cb93a386Sopenharmony_ci#include "src/core/SkImagePriv.h" 20cb93a386Sopenharmony_ci#include "src/core/SkMipmap.h" 21cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h" 22cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h" 23cb93a386Sopenharmony_ci#include "src/gpu/GrContextThreadSafeProxyPriv.h" 24cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 25cb93a386Sopenharmony_ci#include "src/gpu/GrImageContextPriv.h" 26cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h" 27cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h" 28cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxy.h" 29cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxyPriv.h" 30cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h" 31cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxyCacheAccess.h" 32cb93a386Sopenharmony_ci#include "src/gpu/GrTextureRenderTargetProxy.h" 33cb93a386Sopenharmony_ci#include "src/gpu/SkGr.h" 34cb93a386Sopenharmony_ci#include "src/image/SkImage_Base.h" 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci#ifdef SK_VULKAN 37cb93a386Sopenharmony_ci#include "include/gpu/vk/GrVkTypes.h" 38cb93a386Sopenharmony_ci#endif 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fImageContext->priv().singleOwner()) 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ciGrProxyProvider::GrProxyProvider(GrImageContext* imageContext) : fImageContext(imageContext) {} 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ciGrProxyProvider::~GrProxyProvider() { 45cb93a386Sopenharmony_ci if (this->renderingDirectly()) { 46cb93a386Sopenharmony_ci // In DDL-mode a proxy provider can still have extant uniquely keyed proxies (since 47cb93a386Sopenharmony_ci // they need their unique keys to, potentially, find a cached resource when the 48cb93a386Sopenharmony_ci // DDL is played) but, in non-DDL-mode they should all have been cleaned up by this point. 49cb93a386Sopenharmony_ci SkASSERT(!fUniquelyKeyedProxies.count()); 50cb93a386Sopenharmony_ci } 51cb93a386Sopenharmony_ci} 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_cibool GrProxyProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) { 54cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 55cb93a386Sopenharmony_ci SkASSERT(key.isValid()); 56cb93a386Sopenharmony_ci if (this->isAbandoned() || !proxy) { 57cb93a386Sopenharmony_ci return false; 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci // Only the proxyProvider that created a proxy should be assigning unique keys to it. 61cb93a386Sopenharmony_ci SkASSERT(this->isDDLProvider() == proxy->creatingProvider()); 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ci#ifdef SK_DEBUG 64cb93a386Sopenharmony_ci { 65cb93a386Sopenharmony_ci auto direct = fImageContext->asDirectContext(); 66cb93a386Sopenharmony_ci if (direct) { 67cb93a386Sopenharmony_ci GrResourceCache* resourceCache = direct->priv().getResourceCache(); 68cb93a386Sopenharmony_ci // If there is already a GrResource with this key then the caller has violated the 69cb93a386Sopenharmony_ci // normal usage pattern of uniquely keyed resources (e.g., they have created one w/o 70cb93a386Sopenharmony_ci // first seeing if it already existed in the cache). 71cb93a386Sopenharmony_ci SkASSERT(!resourceCache->findAndRefUniqueResource(key)); 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci#endif 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci SkASSERT(!fUniquelyKeyedProxies.find(key)); // multiple proxies can't get the same key 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci proxy->cacheAccess().setUniqueKey(this, key); 79cb93a386Sopenharmony_ci SkASSERT(proxy->getUniqueKey() == key); 80cb93a386Sopenharmony_ci fUniquelyKeyedProxies.add(proxy); 81cb93a386Sopenharmony_ci return true; 82cb93a386Sopenharmony_ci} 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_citemplate <class T> 85cb93a386Sopenharmony_cisk_sp<T> GrProxyProvider::assignTagToProxy(sk_sp<T> proxy) { 86cb93a386Sopenharmony_ci if (!proxy) { 87cb93a386Sopenharmony_ci return proxy; 88cb93a386Sopenharmony_ci } 89cb93a386Sopenharmony_ci auto direct = fImageContext->priv().asDirectContext(); 90cb93a386Sopenharmony_ci if (direct) { 91cb93a386Sopenharmony_ci proxy->setGrProxyTag(direct->getCurrentGrResourceTag()); 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci return proxy; 94cb93a386Sopenharmony_ci} 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_civoid GrProxyProvider::adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface* surf) { 97cb93a386Sopenharmony_ci SkASSERT(surf->getUniqueKey().isValid()); 98cb93a386Sopenharmony_ci proxy->cacheAccess().setUniqueKey(this, surf->getUniqueKey()); 99cb93a386Sopenharmony_ci SkASSERT(proxy->getUniqueKey() == surf->getUniqueKey()); 100cb93a386Sopenharmony_ci // multiple proxies can't get the same key 101cb93a386Sopenharmony_ci SkASSERT(!fUniquelyKeyedProxies.find(surf->getUniqueKey())); 102cb93a386Sopenharmony_ci fUniquelyKeyedProxies.add(proxy); 103cb93a386Sopenharmony_ci} 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_civoid GrProxyProvider::removeUniqueKeyFromProxy(GrTextureProxy* proxy) { 106cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 107cb93a386Sopenharmony_ci SkASSERT(proxy); 108cb93a386Sopenharmony_ci SkASSERT(proxy->getUniqueKey().isValid()); 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci if (this->isAbandoned()) { 111cb93a386Sopenharmony_ci return; 112cb93a386Sopenharmony_ci } 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ci this->processInvalidUniqueKey(proxy->getUniqueKey(), proxy, InvalidateGPUResource::kYes); 115cb93a386Sopenharmony_ci} 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::findProxyByUniqueKey(const GrUniqueKey& key) { 118cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci if (this->isAbandoned()) { 121cb93a386Sopenharmony_ci return nullptr; 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key); 125cb93a386Sopenharmony_ci if (proxy) { 126cb93a386Sopenharmony_ci return sk_ref_sp(proxy); 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci return nullptr; 129cb93a386Sopenharmony_ci} 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ci#if GR_TEST_UTILS 134cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy( 135cb93a386Sopenharmony_ci SkISize dimensions, 136cb93a386Sopenharmony_ci const GrBackendFormat& format, 137cb93a386Sopenharmony_ci GrRenderable renderable, 138cb93a386Sopenharmony_ci int renderTargetSampleCnt, 139cb93a386Sopenharmony_ci SkBackingFit fit, 140cb93a386Sopenharmony_ci SkBudgeted budgeted, 141cb93a386Sopenharmony_ci GrProtected isProtected) { 142cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 143cb93a386Sopenharmony_ci if (this->isAbandoned()) { 144cb93a386Sopenharmony_ci return nullptr; 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci auto direct = fImageContext->asDirectContext(); 147cb93a386Sopenharmony_ci if (!direct) { 148cb93a386Sopenharmony_ci return nullptr; 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci if (this->caps()->isFormatCompressed(format)) { 152cb93a386Sopenharmony_ci // TODO: Allow this to go to GrResourceProvider::createCompressedTexture() once we no longer 153cb93a386Sopenharmony_ci // rely on GrColorType to get a swizzle for the proxy. 154cb93a386Sopenharmony_ci return nullptr; 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci GrResourceProvider* resourceProvider = direct->priv().resourceProvider(); 158cb93a386Sopenharmony_ci sk_sp<GrTexture> tex; 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci if (SkBackingFit::kApprox == fit) { 161cb93a386Sopenharmony_ci tex = resourceProvider->createApproxTexture(dimensions, 162cb93a386Sopenharmony_ci format, 163cb93a386Sopenharmony_ci format.textureType(), 164cb93a386Sopenharmony_ci renderable, 165cb93a386Sopenharmony_ci renderTargetSampleCnt, 166cb93a386Sopenharmony_ci isProtected); 167cb93a386Sopenharmony_ci } else { 168cb93a386Sopenharmony_ci tex = resourceProvider->createTexture(dimensions, 169cb93a386Sopenharmony_ci format, 170cb93a386Sopenharmony_ci format.textureType(), 171cb93a386Sopenharmony_ci renderable, 172cb93a386Sopenharmony_ci renderTargetSampleCnt, 173cb93a386Sopenharmony_ci GrMipmapped::kNo, 174cb93a386Sopenharmony_ci budgeted, 175cb93a386Sopenharmony_ci isProtected); 176cb93a386Sopenharmony_ci } 177cb93a386Sopenharmony_ci if (!tex) { 178cb93a386Sopenharmony_ci return nullptr; 179cb93a386Sopenharmony_ci } 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ci return this->createWrapped(std::move(tex), UseAllocator::kYes); 182cb93a386Sopenharmony_ci} 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy( 185cb93a386Sopenharmony_ci SkISize dimensions, 186cb93a386Sopenharmony_ci GrColorType colorType, 187cb93a386Sopenharmony_ci GrRenderable renderable, 188cb93a386Sopenharmony_ci int renderTargetSampleCnt, 189cb93a386Sopenharmony_ci SkBackingFit fit, 190cb93a386Sopenharmony_ci SkBudgeted budgeted, 191cb93a386Sopenharmony_ci GrProtected isProtected) { 192cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 193cb93a386Sopenharmony_ci if (this->isAbandoned()) { 194cb93a386Sopenharmony_ci return nullptr; 195cb93a386Sopenharmony_ci } 196cb93a386Sopenharmony_ci auto format = this->caps()->getDefaultBackendFormat(colorType, renderable); 197cb93a386Sopenharmony_ci return this->testingOnly_createInstantiatedProxy(dimensions, 198cb93a386Sopenharmony_ci format, 199cb93a386Sopenharmony_ci renderable, 200cb93a386Sopenharmony_ci renderTargetSampleCnt, 201cb93a386Sopenharmony_ci fit, 202cb93a386Sopenharmony_ci budgeted, 203cb93a386Sopenharmony_ci isProtected); 204cb93a386Sopenharmony_ci} 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createWrapped(sk_sp<GrTexture> tex) { 207cb93a386Sopenharmony_ci return this->createWrapped(std::move(tex), UseAllocator::kYes); 208cb93a386Sopenharmony_ci} 209cb93a386Sopenharmony_ci#endif 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::createWrapped(sk_sp<GrTexture> tex, 212cb93a386Sopenharmony_ci UseAllocator useAllocator) { 213cb93a386Sopenharmony_ci#ifdef SK_DEBUG 214cb93a386Sopenharmony_ci if (tex->getUniqueKey().isValid()) { 215cb93a386Sopenharmony_ci SkASSERT(!this->findProxyByUniqueKey(tex->getUniqueKey())); 216cb93a386Sopenharmony_ci } 217cb93a386Sopenharmony_ci#endif 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci if (tex->asRenderTarget()) { 220cb93a386Sopenharmony_ci return assignTagToProxy( 221cb93a386Sopenharmony_ci sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), useAllocator, this->isDDLProvider()))); 222cb93a386Sopenharmony_ci } else { 223cb93a386Sopenharmony_ci return assignTagToProxy( 224cb93a386Sopenharmony_ci sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), useAllocator, 225cb93a386Sopenharmony_ci this->isDDLProvider()))); 226cb93a386Sopenharmony_ci } 227cb93a386Sopenharmony_ci} 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::findOrCreateProxyByUniqueKey(const GrUniqueKey& key, 230cb93a386Sopenharmony_ci UseAllocator useAllocator) { 231cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ci if (this->isAbandoned()) { 234cb93a386Sopenharmony_ci return nullptr; 235cb93a386Sopenharmony_ci } 236cb93a386Sopenharmony_ci 237cb93a386Sopenharmony_ci sk_sp<GrTextureProxy> result = this->findProxyByUniqueKey(key); 238cb93a386Sopenharmony_ci if (result) { 239cb93a386Sopenharmony_ci return result; 240cb93a386Sopenharmony_ci } 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_ci auto direct = fImageContext->asDirectContext(); 243cb93a386Sopenharmony_ci if (!direct) { 244cb93a386Sopenharmony_ci return nullptr; 245cb93a386Sopenharmony_ci } 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci GrResourceCache* resourceCache = direct->priv().getResourceCache(); 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_ci GrGpuResource* resource = resourceCache->findAndRefUniqueResource(key); 250cb93a386Sopenharmony_ci if (!resource) { 251cb93a386Sopenharmony_ci return nullptr; 252cb93a386Sopenharmony_ci } 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_ci sk_sp<GrTexture> texture(static_cast<GrSurface*>(resource)->asTexture()); 255cb93a386Sopenharmony_ci SkASSERT(texture); 256cb93a386Sopenharmony_ci 257cb93a386Sopenharmony_ci result = this->createWrapped(std::move(texture), useAllocator); 258cb93a386Sopenharmony_ci SkASSERT(result->getUniqueKey() == key); 259cb93a386Sopenharmony_ci // createWrapped should've added this for us 260cb93a386Sopenharmony_ci SkASSERT(fUniquelyKeyedProxies.find(key)); 261cb93a386Sopenharmony_ci return result; 262cb93a386Sopenharmony_ci} 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_ciGrSurfaceProxyView GrProxyProvider::findCachedProxyWithColorTypeFallback(const GrUniqueKey& key, 265cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 266cb93a386Sopenharmony_ci GrColorType ct, 267cb93a386Sopenharmony_ci int sampleCnt) { 268cb93a386Sopenharmony_ci auto proxy = this->findOrCreateProxyByUniqueKey(key); 269cb93a386Sopenharmony_ci if (!proxy) { 270cb93a386Sopenharmony_ci return {}; 271cb93a386Sopenharmony_ci } 272cb93a386Sopenharmony_ci const GrCaps* caps = fImageContext->priv().caps(); 273cb93a386Sopenharmony_ci 274cb93a386Sopenharmony_ci // Assume that we used a fallback color type if and only if the proxy is renderable. 275cb93a386Sopenharmony_ci if (proxy->asRenderTargetProxy()) { 276cb93a386Sopenharmony_ci GrBackendFormat expectedFormat; 277cb93a386Sopenharmony_ci std::tie(ct, expectedFormat) = caps->getFallbackColorTypeAndFormat(ct, sampleCnt); 278cb93a386Sopenharmony_ci SkASSERT(expectedFormat == proxy->backendFormat()); 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci GrSwizzle swizzle = caps->getReadSwizzle(proxy->backendFormat(), ct); 281cb93a386Sopenharmony_ci return {std::move(proxy), origin, swizzle}; 282cb93a386Sopenharmony_ci} 283cb93a386Sopenharmony_ci 284cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::createProxyFromBitmap(const SkBitmap& bitmap, 285cb93a386Sopenharmony_ci GrMipmapped mipMapped, 286cb93a386Sopenharmony_ci SkBackingFit fit, 287cb93a386Sopenharmony_ci SkBudgeted budgeted) { 288cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 289cb93a386Sopenharmony_ci SkASSERT(fit == SkBackingFit::kExact || mipMapped == GrMipmapped::kNo); 290cb93a386Sopenharmony_ci 291cb93a386Sopenharmony_ci if (this->isAbandoned()) { 292cb93a386Sopenharmony_ci return nullptr; 293cb93a386Sopenharmony_ci } 294cb93a386Sopenharmony_ci 295cb93a386Sopenharmony_ci if (!SkImageInfoIsValid(bitmap.info())) { 296cb93a386Sopenharmony_ci return nullptr; 297cb93a386Sopenharmony_ci } 298cb93a386Sopenharmony_ci 299cb93a386Sopenharmony_ci ATRACE_ANDROID_FRAMEWORK("Upload %sTexture [%ux%u]", 300cb93a386Sopenharmony_ci GrMipmapped::kYes == mipMapped ? "MipMap " : "", 301cb93a386Sopenharmony_ci bitmap.width(), bitmap.height()); 302cb93a386Sopenharmony_ci 303cb93a386Sopenharmony_ci // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap 304cb93a386Sopenharmony_ci // even if its mutable. In ddl, if the bitmap is mutable then we must make a copy since the 305cb93a386Sopenharmony_ci // upload of the data to the gpu can happen at anytime and the bitmap may change by then. 306cb93a386Sopenharmony_ci SkBitmap copyBitmap = bitmap; 307cb93a386Sopenharmony_ci if (!this->renderingDirectly() && !bitmap.isImmutable()) { 308cb93a386Sopenharmony_ci copyBitmap.allocPixels(); 309cb93a386Sopenharmony_ci if (!bitmap.readPixels(copyBitmap.pixmap())) { 310cb93a386Sopenharmony_ci return nullptr; 311cb93a386Sopenharmony_ci } 312cb93a386Sopenharmony_ci copyBitmap.setImmutable(); 313cb93a386Sopenharmony_ci } 314cb93a386Sopenharmony_ci 315cb93a386Sopenharmony_ci sk_sp<GrTextureProxy> proxy; 316cb93a386Sopenharmony_ci if (mipMapped == GrMipmapped::kNo || 317cb93a386Sopenharmony_ci 0 == SkMipmap::ComputeLevelCount(copyBitmap.width(), copyBitmap.height())) { 318cb93a386Sopenharmony_ci proxy = this->createNonMippedProxyFromBitmap(copyBitmap, fit, budgeted); 319cb93a386Sopenharmony_ci } else { 320cb93a386Sopenharmony_ci proxy = this->createMippedProxyFromBitmap(copyBitmap, budgeted); 321cb93a386Sopenharmony_ci } 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_ci if (!proxy) { 324cb93a386Sopenharmony_ci return nullptr; 325cb93a386Sopenharmony_ci } 326cb93a386Sopenharmony_ci 327cb93a386Sopenharmony_ci auto direct = fImageContext->asDirectContext(); 328cb93a386Sopenharmony_ci if (direct) { 329cb93a386Sopenharmony_ci GrResourceProvider* resourceProvider = direct->priv().resourceProvider(); 330cb93a386Sopenharmony_ci 331cb93a386Sopenharmony_ci // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however 332cb93a386Sopenharmony_ci // we're better off instantiating the proxy immediately here. 333cb93a386Sopenharmony_ci if (!proxy->priv().doLazyInstantiation(resourceProvider)) { 334cb93a386Sopenharmony_ci return nullptr; 335cb93a386Sopenharmony_ci } 336cb93a386Sopenharmony_ci } 337cb93a386Sopenharmony_ci return assignTagToProxy(proxy); 338cb93a386Sopenharmony_ci} 339cb93a386Sopenharmony_ci 340cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::createNonMippedProxyFromBitmap(const SkBitmap& bitmap, 341cb93a386Sopenharmony_ci SkBackingFit fit, 342cb93a386Sopenharmony_ci SkBudgeted budgeted) { 343cb93a386Sopenharmony_ci auto dims = bitmap.dimensions(); 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_ci auto colorType = SkColorTypeToGrColorType(bitmap.colorType()); 346cb93a386Sopenharmony_ci GrBackendFormat format = this->caps()->getDefaultBackendFormat(colorType, GrRenderable::kNo); 347cb93a386Sopenharmony_ci if (!format.isValid()) { 348cb93a386Sopenharmony_ci return nullptr; 349cb93a386Sopenharmony_ci } 350cb93a386Sopenharmony_ci 351cb93a386Sopenharmony_ci sk_sp<GrTextureProxy> proxy = this->createLazyProxy( 352cb93a386Sopenharmony_ci [bitmap](GrResourceProvider* resourceProvider, const LazySurfaceDesc& desc) { 353cb93a386Sopenharmony_ci SkASSERT(desc.fMipmapped == GrMipmapped::kNo); 354cb93a386Sopenharmony_ci GrMipLevel mipLevel = {bitmap.getPixels(), bitmap.rowBytes(), nullptr}; 355cb93a386Sopenharmony_ci auto colorType = SkColorTypeToGrColorType(bitmap.colorType()); 356cb93a386Sopenharmony_ci return LazyCallbackResult(resourceProvider->createTexture( 357cb93a386Sopenharmony_ci desc.fDimensions, 358cb93a386Sopenharmony_ci desc.fFormat, 359cb93a386Sopenharmony_ci desc.fTextureType, 360cb93a386Sopenharmony_ci colorType, 361cb93a386Sopenharmony_ci desc.fRenderable, 362cb93a386Sopenharmony_ci desc.fSampleCnt, 363cb93a386Sopenharmony_ci desc.fBudgeted, 364cb93a386Sopenharmony_ci desc.fFit, 365cb93a386Sopenharmony_ci desc.fProtected, 366cb93a386Sopenharmony_ci mipLevel)); 367cb93a386Sopenharmony_ci }, 368cb93a386Sopenharmony_ci format, dims, GrMipmapped::kNo, GrMipmapStatus::kNotAllocated, 369cb93a386Sopenharmony_ci GrInternalSurfaceFlags::kNone, fit, budgeted, GrProtected::kNo, UseAllocator::kYes); 370cb93a386Sopenharmony_ci 371cb93a386Sopenharmony_ci if (!proxy) { 372cb93a386Sopenharmony_ci return nullptr; 373cb93a386Sopenharmony_ci } 374cb93a386Sopenharmony_ci SkASSERT(proxy->dimensions() == bitmap.dimensions()); 375cb93a386Sopenharmony_ci return proxy; 376cb93a386Sopenharmony_ci} 377cb93a386Sopenharmony_ci 378cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::createMippedProxyFromBitmap(const SkBitmap& bitmap, 379cb93a386Sopenharmony_ci SkBudgeted budgeted) { 380cb93a386Sopenharmony_ci SkASSERT(this->caps()->mipmapSupport()); 381cb93a386Sopenharmony_ci 382cb93a386Sopenharmony_ci auto colorType = SkColorTypeToGrColorType(bitmap.colorType()); 383cb93a386Sopenharmony_ci GrBackendFormat format = this->caps()->getDefaultBackendFormat(colorType, GrRenderable::kNo); 384cb93a386Sopenharmony_ci if (!format.isValid()) { 385cb93a386Sopenharmony_ci return nullptr; 386cb93a386Sopenharmony_ci } 387cb93a386Sopenharmony_ci 388cb93a386Sopenharmony_ci sk_sp<SkMipmap> mipmaps(SkMipmap::Build(bitmap.pixmap(), nullptr)); 389cb93a386Sopenharmony_ci if (!mipmaps) { 390cb93a386Sopenharmony_ci return nullptr; 391cb93a386Sopenharmony_ci } 392cb93a386Sopenharmony_ci 393cb93a386Sopenharmony_ci auto dims = bitmap.dimensions(); 394cb93a386Sopenharmony_ci 395cb93a386Sopenharmony_ci sk_sp<GrTextureProxy> proxy = this->createLazyProxy( 396cb93a386Sopenharmony_ci [bitmap, mipmaps](GrResourceProvider* resourceProvider, const LazySurfaceDesc& desc) { 397cb93a386Sopenharmony_ci const int mipLevelCount = mipmaps->countLevels() + 1; 398cb93a386Sopenharmony_ci std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]); 399cb93a386Sopenharmony_ci auto colorType = SkColorTypeToGrColorType(bitmap.colorType()); 400cb93a386Sopenharmony_ci 401cb93a386Sopenharmony_ci texels[0].fPixels = bitmap.getPixels(); 402cb93a386Sopenharmony_ci texels[0].fRowBytes = bitmap.rowBytes(); 403cb93a386Sopenharmony_ci 404cb93a386Sopenharmony_ci for (int i = 1; i < mipLevelCount; ++i) { 405cb93a386Sopenharmony_ci SkMipmap::Level generatedMipLevel; 406cb93a386Sopenharmony_ci mipmaps->getLevel(i - 1, &generatedMipLevel); 407cb93a386Sopenharmony_ci texels[i].fPixels = generatedMipLevel.fPixmap.addr(); 408cb93a386Sopenharmony_ci texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes(); 409cb93a386Sopenharmony_ci SkASSERT(texels[i].fPixels); 410cb93a386Sopenharmony_ci SkASSERT(generatedMipLevel.fPixmap.colorType() == bitmap.colorType()); 411cb93a386Sopenharmony_ci } 412cb93a386Sopenharmony_ci return LazyCallbackResult(resourceProvider->createTexture( 413cb93a386Sopenharmony_ci desc.fDimensions, 414cb93a386Sopenharmony_ci desc.fFormat, 415cb93a386Sopenharmony_ci desc.fTextureType, 416cb93a386Sopenharmony_ci colorType, 417cb93a386Sopenharmony_ci GrRenderable::kNo, 418cb93a386Sopenharmony_ci 1, 419cb93a386Sopenharmony_ci desc.fBudgeted, 420cb93a386Sopenharmony_ci GrMipMapped::kYes, 421cb93a386Sopenharmony_ci GrProtected::kNo, 422cb93a386Sopenharmony_ci texels.get())); 423cb93a386Sopenharmony_ci }, 424cb93a386Sopenharmony_ci format, dims, GrMipmapped::kYes, GrMipmapStatus::kValid, GrInternalSurfaceFlags::kNone, 425cb93a386Sopenharmony_ci SkBackingFit::kExact, budgeted, GrProtected::kNo, UseAllocator::kYes); 426cb93a386Sopenharmony_ci 427cb93a386Sopenharmony_ci if (!proxy) { 428cb93a386Sopenharmony_ci return nullptr; 429cb93a386Sopenharmony_ci } 430cb93a386Sopenharmony_ci 431cb93a386Sopenharmony_ci SkASSERT(proxy->dimensions() == bitmap.dimensions()); 432cb93a386Sopenharmony_ci 433cb93a386Sopenharmony_ci return proxy; 434cb93a386Sopenharmony_ci} 435cb93a386Sopenharmony_ci 436cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrBackendFormat& format, 437cb93a386Sopenharmony_ci SkISize dimensions, 438cb93a386Sopenharmony_ci GrRenderable renderable, 439cb93a386Sopenharmony_ci int renderTargetSampleCnt, 440cb93a386Sopenharmony_ci GrMipmapped mipMapped, 441cb93a386Sopenharmony_ci SkBackingFit fit, 442cb93a386Sopenharmony_ci SkBudgeted budgeted, 443cb93a386Sopenharmony_ci GrProtected isProtected, 444cb93a386Sopenharmony_ci GrInternalSurfaceFlags surfaceFlags, 445cb93a386Sopenharmony_ci GrSurfaceProxy::UseAllocator useAllocator) { 446cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 447cb93a386Sopenharmony_ci if (this->isAbandoned()) { 448cb93a386Sopenharmony_ci return nullptr; 449cb93a386Sopenharmony_ci } 450cb93a386Sopenharmony_ci 451cb93a386Sopenharmony_ci const GrCaps* caps = this->caps(); 452cb93a386Sopenharmony_ci 453cb93a386Sopenharmony_ci if (caps->isFormatCompressed(format)) { 454cb93a386Sopenharmony_ci // Deferred proxies for compressed textures are not supported. 455cb93a386Sopenharmony_ci return nullptr; 456cb93a386Sopenharmony_ci } 457cb93a386Sopenharmony_ci 458cb93a386Sopenharmony_ci if (GrMipmapped::kYes == mipMapped) { 459cb93a386Sopenharmony_ci // SkMipmap doesn't include the base level in the level count so we have to add 1 460cb93a386Sopenharmony_ci int mipCount = SkMipmap::ComputeLevelCount(dimensions.fWidth, dimensions.fHeight) + 1; 461cb93a386Sopenharmony_ci if (1 == mipCount) { 462cb93a386Sopenharmony_ci mipMapped = GrMipmapped::kNo; 463cb93a386Sopenharmony_ci } 464cb93a386Sopenharmony_ci } 465cb93a386Sopenharmony_ci 466cb93a386Sopenharmony_ci if (!caps->validateSurfaceParams(dimensions, 467cb93a386Sopenharmony_ci format, 468cb93a386Sopenharmony_ci renderable, 469cb93a386Sopenharmony_ci renderTargetSampleCnt, 470cb93a386Sopenharmony_ci mipMapped, 471cb93a386Sopenharmony_ci GrTextureType::k2D)) { 472cb93a386Sopenharmony_ci return nullptr; 473cb93a386Sopenharmony_ci } 474cb93a386Sopenharmony_ci GrMipmapStatus mipmapStatus = (GrMipmapped::kYes == mipMapped) 475cb93a386Sopenharmony_ci ? GrMipmapStatus::kDirty 476cb93a386Sopenharmony_ci : GrMipmapStatus::kNotAllocated; 477cb93a386Sopenharmony_ci if (renderable == GrRenderable::kYes) { 478cb93a386Sopenharmony_ci renderTargetSampleCnt = caps->getRenderTargetSampleCount(renderTargetSampleCnt, format); 479cb93a386Sopenharmony_ci SkASSERT(renderTargetSampleCnt); 480cb93a386Sopenharmony_ci GrInternalSurfaceFlags extraFlags = caps->getExtraSurfaceFlagsForDeferredRT(); 481cb93a386Sopenharmony_ci // We know anything we instantiate later from this deferred path will be 482cb93a386Sopenharmony_ci // both texturable and renderable 483cb93a386Sopenharmony_ci return assignTagToProxy(sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy( 484cb93a386Sopenharmony_ci *caps, format, dimensions, renderTargetSampleCnt, mipMapped, mipmapStatus, fit, 485cb93a386Sopenharmony_ci budgeted, isProtected, surfaceFlags | extraFlags, useAllocator, 486cb93a386Sopenharmony_ci this->isDDLProvider()))); 487cb93a386Sopenharmony_ci } 488cb93a386Sopenharmony_ci 489cb93a386Sopenharmony_ci return assignTagToProxy(sk_sp<GrTextureProxy>(new GrTextureProxy(format, dimensions, mipMapped, mipmapStatus, 490cb93a386Sopenharmony_ci fit, budgeted, isProtected, surfaceFlags, 491cb93a386Sopenharmony_ci useAllocator, this->isDDLProvider()))); 492cb93a386Sopenharmony_ci} 493cb93a386Sopenharmony_ci 494cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::createCompressedTextureProxy( 495cb93a386Sopenharmony_ci SkISize dimensions, SkBudgeted budgeted, GrMipmapped mipMapped, GrProtected isProtected, 496cb93a386Sopenharmony_ci SkImage::CompressionType compressionType, sk_sp<SkData> data) { 497cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 498cb93a386Sopenharmony_ci if (this->isAbandoned()) { 499cb93a386Sopenharmony_ci return nullptr; 500cb93a386Sopenharmony_ci } 501cb93a386Sopenharmony_ci 502cb93a386Sopenharmony_ci GrBackendFormat format = this->caps()->getBackendFormatFromCompressionType(compressionType); 503cb93a386Sopenharmony_ci 504cb93a386Sopenharmony_ci if (!this->caps()->isFormatTexturable(format, GrTextureType::k2D)) { 505cb93a386Sopenharmony_ci return nullptr; 506cb93a386Sopenharmony_ci } 507cb93a386Sopenharmony_ci 508cb93a386Sopenharmony_ci GrMipmapStatus mipmapStatus = (GrMipmapped::kYes == mipMapped) ? GrMipmapStatus::kValid 509cb93a386Sopenharmony_ci : GrMipmapStatus::kNotAllocated; 510cb93a386Sopenharmony_ci 511cb93a386Sopenharmony_ci sk_sp<GrTextureProxy> proxy = this->createLazyProxy( 512cb93a386Sopenharmony_ci [data](GrResourceProvider* resourceProvider, const LazySurfaceDesc& desc) { 513cb93a386Sopenharmony_ci return LazyCallbackResult(resourceProvider->createCompressedTexture( 514cb93a386Sopenharmony_ci desc.fDimensions, desc.fFormat, desc.fBudgeted, desc.fMipmapped, 515cb93a386Sopenharmony_ci desc.fProtected, data.get())); 516cb93a386Sopenharmony_ci }, 517cb93a386Sopenharmony_ci format, dimensions, mipMapped, mipmapStatus,GrInternalSurfaceFlags::kReadOnly, 518cb93a386Sopenharmony_ci SkBackingFit::kExact, SkBudgeted::kYes, GrProtected::kNo, UseAllocator::kYes); 519cb93a386Sopenharmony_ci 520cb93a386Sopenharmony_ci if (!proxy) { 521cb93a386Sopenharmony_ci return nullptr; 522cb93a386Sopenharmony_ci } 523cb93a386Sopenharmony_ci 524cb93a386Sopenharmony_ci auto direct = fImageContext->asDirectContext(); 525cb93a386Sopenharmony_ci if (direct) { 526cb93a386Sopenharmony_ci GrResourceProvider* resourceProvider = direct->priv().resourceProvider(); 527cb93a386Sopenharmony_ci // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however 528cb93a386Sopenharmony_ci // we're better off instantiating the proxy immediately here. 529cb93a386Sopenharmony_ci if (!proxy->priv().doLazyInstantiation(resourceProvider)) { 530cb93a386Sopenharmony_ci return nullptr; 531cb93a386Sopenharmony_ci } 532cb93a386Sopenharmony_ci } 533cb93a386Sopenharmony_ci return proxy; 534cb93a386Sopenharmony_ci} 535cb93a386Sopenharmony_ci 536cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::wrapBackendTexture(const GrBackendTexture& backendTex, 537cb93a386Sopenharmony_ci GrWrapOwnership ownership, 538cb93a386Sopenharmony_ci GrWrapCacheable cacheable, 539cb93a386Sopenharmony_ci GrIOType ioType, 540cb93a386Sopenharmony_ci sk_sp<GrRefCntedCallback> releaseHelper) { 541cb93a386Sopenharmony_ci SkASSERT(ioType != kWrite_GrIOType); 542cb93a386Sopenharmony_ci 543cb93a386Sopenharmony_ci if (this->isAbandoned()) { 544cb93a386Sopenharmony_ci return nullptr; 545cb93a386Sopenharmony_ci } 546cb93a386Sopenharmony_ci 547cb93a386Sopenharmony_ci // This is only supported on a direct GrContext. 548cb93a386Sopenharmony_ci auto direct = fImageContext->asDirectContext(); 549cb93a386Sopenharmony_ci if (!direct) { 550cb93a386Sopenharmony_ci return nullptr; 551cb93a386Sopenharmony_ci } 552cb93a386Sopenharmony_ci 553cb93a386Sopenharmony_ci GrResourceProvider* resourceProvider = direct->priv().resourceProvider(); 554cb93a386Sopenharmony_ci 555cb93a386Sopenharmony_ci sk_sp<GrTexture> tex = 556cb93a386Sopenharmony_ci resourceProvider->wrapBackendTexture(backendTex, ownership, cacheable, ioType); 557cb93a386Sopenharmony_ci if (!tex) { 558cb93a386Sopenharmony_ci return nullptr; 559cb93a386Sopenharmony_ci } 560cb93a386Sopenharmony_ci 561cb93a386Sopenharmony_ci if (releaseHelper) { 562cb93a386Sopenharmony_ci tex->setRelease(std::move(releaseHelper)); 563cb93a386Sopenharmony_ci } 564cb93a386Sopenharmony_ci 565cb93a386Sopenharmony_ci SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture 566cb93a386Sopenharmony_ci // Make sure we match how we created the proxy with SkBudgeted::kNo 567cb93a386Sopenharmony_ci SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType()); 568cb93a386Sopenharmony_ci 569cb93a386Sopenharmony_ci return assignTagToProxy(sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), UseAllocator::kNo, 570cb93a386Sopenharmony_ci this->isDDLProvider()))); 571cb93a386Sopenharmony_ci} 572cb93a386Sopenharmony_ci 573cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::wrapCompressedBackendTexture( 574cb93a386Sopenharmony_ci const GrBackendTexture& beTex, 575cb93a386Sopenharmony_ci GrWrapOwnership ownership, 576cb93a386Sopenharmony_ci GrWrapCacheable cacheable, 577cb93a386Sopenharmony_ci sk_sp<GrRefCntedCallback> releaseHelper) { 578cb93a386Sopenharmony_ci if (this->isAbandoned()) { 579cb93a386Sopenharmony_ci return nullptr; 580cb93a386Sopenharmony_ci } 581cb93a386Sopenharmony_ci 582cb93a386Sopenharmony_ci // This is only supported on a direct GrContext. 583cb93a386Sopenharmony_ci auto direct = fImageContext->asDirectContext(); 584cb93a386Sopenharmony_ci if (!direct) { 585cb93a386Sopenharmony_ci return nullptr; 586cb93a386Sopenharmony_ci } 587cb93a386Sopenharmony_ci 588cb93a386Sopenharmony_ci GrResourceProvider* resourceProvider = direct->priv().resourceProvider(); 589cb93a386Sopenharmony_ci 590cb93a386Sopenharmony_ci sk_sp<GrTexture> tex = resourceProvider->wrapCompressedBackendTexture(beTex, ownership, 591cb93a386Sopenharmony_ci cacheable); 592cb93a386Sopenharmony_ci if (!tex) { 593cb93a386Sopenharmony_ci return nullptr; 594cb93a386Sopenharmony_ci } 595cb93a386Sopenharmony_ci 596cb93a386Sopenharmony_ci if (releaseHelper) { 597cb93a386Sopenharmony_ci tex->setRelease(std::move(releaseHelper)); 598cb93a386Sopenharmony_ci } 599cb93a386Sopenharmony_ci 600cb93a386Sopenharmony_ci SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture 601cb93a386Sopenharmony_ci // Make sure we match how we created the proxy with SkBudgeted::kNo 602cb93a386Sopenharmony_ci SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType()); 603cb93a386Sopenharmony_ci 604cb93a386Sopenharmony_ci return assignTagToProxy(sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), UseAllocator::kNo, 605cb93a386Sopenharmony_ci this->isDDLProvider()))); 606cb93a386Sopenharmony_ci} 607cb93a386Sopenharmony_ci 608cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture( 609cb93a386Sopenharmony_ci const GrBackendTexture& backendTex, 610cb93a386Sopenharmony_ci int sampleCnt, 611cb93a386Sopenharmony_ci GrWrapOwnership ownership, 612cb93a386Sopenharmony_ci GrWrapCacheable cacheable, 613cb93a386Sopenharmony_ci sk_sp<GrRefCntedCallback> releaseHelper) { 614cb93a386Sopenharmony_ci if (this->isAbandoned()) { 615cb93a386Sopenharmony_ci return nullptr; 616cb93a386Sopenharmony_ci } 617cb93a386Sopenharmony_ci 618cb93a386Sopenharmony_ci // This is only supported on a direct GrContext. 619cb93a386Sopenharmony_ci auto direct = fImageContext->asDirectContext(); 620cb93a386Sopenharmony_ci if (!direct) { 621cb93a386Sopenharmony_ci return nullptr; 622cb93a386Sopenharmony_ci } 623cb93a386Sopenharmony_ci 624cb93a386Sopenharmony_ci const GrCaps* caps = this->caps(); 625cb93a386Sopenharmony_ci 626cb93a386Sopenharmony_ci GrResourceProvider* resourceProvider = direct->priv().resourceProvider(); 627cb93a386Sopenharmony_ci 628cb93a386Sopenharmony_ci sampleCnt = caps->getRenderTargetSampleCount(sampleCnt, backendTex.getBackendFormat()); 629cb93a386Sopenharmony_ci SkASSERT(sampleCnt); 630cb93a386Sopenharmony_ci 631cb93a386Sopenharmony_ci sk_sp<GrTexture> tex = resourceProvider->wrapRenderableBackendTexture( 632cb93a386Sopenharmony_ci backendTex, sampleCnt, ownership, cacheable); 633cb93a386Sopenharmony_ci if (!tex) { 634cb93a386Sopenharmony_ci return nullptr; 635cb93a386Sopenharmony_ci } 636cb93a386Sopenharmony_ci 637cb93a386Sopenharmony_ci if (releaseHelper) { 638cb93a386Sopenharmony_ci tex->setRelease(std::move(releaseHelper)); 639cb93a386Sopenharmony_ci } 640cb93a386Sopenharmony_ci 641cb93a386Sopenharmony_ci SkASSERT(tex->asRenderTarget()); // A GrTextureRenderTarget 642cb93a386Sopenharmony_ci // Make sure we match how we created the proxy with SkBudgeted::kNo 643cb93a386Sopenharmony_ci SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType()); 644cb93a386Sopenharmony_ci 645cb93a386Sopenharmony_ci return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), UseAllocator::kNo, 646cb93a386Sopenharmony_ci this->isDDLProvider())); 647cb93a386Sopenharmony_ci return assignTagToProxy(sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), UseAllocator::kNo, 648cb93a386Sopenharmony_ci this->isDDLProvider()))); 649cb93a386Sopenharmony_ci} 650cb93a386Sopenharmony_ci 651cb93a386Sopenharmony_cisk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendRenderTarget( 652cb93a386Sopenharmony_ci const GrBackendRenderTarget& backendRT, 653cb93a386Sopenharmony_ci sk_sp<GrRefCntedCallback> releaseHelper) { 654cb93a386Sopenharmony_ci if (this->isAbandoned()) { 655cb93a386Sopenharmony_ci return nullptr; 656cb93a386Sopenharmony_ci } 657cb93a386Sopenharmony_ci 658cb93a386Sopenharmony_ci // This is only supported on a direct GrContext. 659cb93a386Sopenharmony_ci auto direct = fImageContext->asDirectContext(); 660cb93a386Sopenharmony_ci if (!direct) { 661cb93a386Sopenharmony_ci return nullptr; 662cb93a386Sopenharmony_ci } 663cb93a386Sopenharmony_ci 664cb93a386Sopenharmony_ci GrResourceProvider* resourceProvider = direct->priv().resourceProvider(); 665cb93a386Sopenharmony_ci 666cb93a386Sopenharmony_ci sk_sp<GrRenderTarget> rt = resourceProvider->wrapBackendRenderTarget(backendRT); 667cb93a386Sopenharmony_ci if (!rt) { 668cb93a386Sopenharmony_ci return nullptr; 669cb93a386Sopenharmony_ci } 670cb93a386Sopenharmony_ci 671cb93a386Sopenharmony_ci if (releaseHelper) { 672cb93a386Sopenharmony_ci rt->setRelease(std::move(releaseHelper)); 673cb93a386Sopenharmony_ci } 674cb93a386Sopenharmony_ci 675cb93a386Sopenharmony_ci SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable 676cb93a386Sopenharmony_ci SkASSERT(!rt->getUniqueKey().isValid()); 677cb93a386Sopenharmony_ci // Make sure we match how we created the proxy with SkBudgeted::kNo 678cb93a386Sopenharmony_ci SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType()); 679cb93a386Sopenharmony_ci return assignTagToProxy(sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(std::move(rt), UseAllocator::kNo))); 680cb93a386Sopenharmony_ci} 681cb93a386Sopenharmony_ci 682cb93a386Sopenharmony_ci#ifdef SK_VULKAN 683cb93a386Sopenharmony_cisk_sp<GrRenderTargetProxy> GrProxyProvider::wrapVulkanSecondaryCBAsRenderTarget( 684cb93a386Sopenharmony_ci const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) { 685cb93a386Sopenharmony_ci if (this->isAbandoned()) { 686cb93a386Sopenharmony_ci return nullptr; 687cb93a386Sopenharmony_ci } 688cb93a386Sopenharmony_ci 689cb93a386Sopenharmony_ci // This is only supported on a direct GrContext. 690cb93a386Sopenharmony_ci auto direct = fImageContext->asDirectContext(); 691cb93a386Sopenharmony_ci if (!direct) { 692cb93a386Sopenharmony_ci return nullptr; 693cb93a386Sopenharmony_ci } 694cb93a386Sopenharmony_ci 695cb93a386Sopenharmony_ci GrResourceProvider* resourceProvider = direct->priv().resourceProvider(); 696cb93a386Sopenharmony_ci 697cb93a386Sopenharmony_ci sk_sp<GrRenderTarget> rt = resourceProvider->wrapVulkanSecondaryCBAsRenderTarget(imageInfo, 698cb93a386Sopenharmony_ci vkInfo); 699cb93a386Sopenharmony_ci if (!rt) { 700cb93a386Sopenharmony_ci return nullptr; 701cb93a386Sopenharmony_ci } 702cb93a386Sopenharmony_ci 703cb93a386Sopenharmony_ci SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable 704cb93a386Sopenharmony_ci SkASSERT(!rt->getUniqueKey().isValid()); 705cb93a386Sopenharmony_ci // This proxy should be unbudgeted because we're just wrapping an external resource 706cb93a386Sopenharmony_ci SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType()); 707cb93a386Sopenharmony_ci 708cb93a386Sopenharmony_ci GrColorType colorType = SkColorTypeToGrColorType(imageInfo.colorType()); 709cb93a386Sopenharmony_ci 710cb93a386Sopenharmony_ci if (!this->caps()->isFormatAsColorTypeRenderable( 711cb93a386Sopenharmony_ci colorType, GrBackendFormat::MakeVk(vkInfo.fFormat), /*sampleCount=*/1)) { 712cb93a386Sopenharmony_ci return nullptr; 713cb93a386Sopenharmony_ci } 714cb93a386Sopenharmony_ci 715cb93a386Sopenharmony_ci return assignTagToProxy(sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy( 716cb93a386Sopenharmony_ci std::move(rt), UseAllocator::kNo, GrRenderTargetProxy::WrapsVkSecondaryCB::kYes))); 717cb93a386Sopenharmony_ci} 718cb93a386Sopenharmony_ci#else 719cb93a386Sopenharmony_cisk_sp<GrRenderTargetProxy> GrProxyProvider::wrapVulkanSecondaryCBAsRenderTarget( 720cb93a386Sopenharmony_ci const SkImageInfo&, const GrVkDrawableInfo&) { 721cb93a386Sopenharmony_ci return nullptr; 722cb93a386Sopenharmony_ci} 723cb93a386Sopenharmony_ci#endif 724cb93a386Sopenharmony_ci 725cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::CreatePromiseProxy(GrContextThreadSafeProxy* threadSafeProxy, 726cb93a386Sopenharmony_ci LazyInstantiateCallback&& callback, 727cb93a386Sopenharmony_ci const GrBackendFormat& format, 728cb93a386Sopenharmony_ci SkISize dimensions, 729cb93a386Sopenharmony_ci GrMipmapped mipMapped) { 730cb93a386Sopenharmony_ci if (threadSafeProxy->priv().abandoned()) { 731cb93a386Sopenharmony_ci return nullptr; 732cb93a386Sopenharmony_ci } 733cb93a386Sopenharmony_ci SkASSERT((dimensions.fWidth <= 0 && dimensions.fHeight <= 0) || 734cb93a386Sopenharmony_ci (dimensions.fWidth > 0 && dimensions.fHeight > 0)); 735cb93a386Sopenharmony_ci 736cb93a386Sopenharmony_ci if (dimensions.fWidth > threadSafeProxy->priv().caps()->maxTextureSize() || 737cb93a386Sopenharmony_ci dimensions.fHeight > threadSafeProxy->priv().caps()->maxTextureSize()) { 738cb93a386Sopenharmony_ci return nullptr; 739cb93a386Sopenharmony_ci } 740cb93a386Sopenharmony_ci // Ganesh assumes that, when wrapping a mipmapped backend texture from a client, that its 741cb93a386Sopenharmony_ci // mipmaps are fully fleshed out. 742cb93a386Sopenharmony_ci GrMipmapStatus mipmapStatus = (GrMipmapped::kYes == mipMapped) ? GrMipmapStatus::kValid 743cb93a386Sopenharmony_ci : GrMipmapStatus::kNotAllocated; 744cb93a386Sopenharmony_ci 745cb93a386Sopenharmony_ci // We pass kReadOnly here since we should treat content of the client's texture as immutable. 746cb93a386Sopenharmony_ci // The promise API provides no way for the client to indicate that the texture is protected. 747cb93a386Sopenharmony_ci auto proxy = sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(callback), 748cb93a386Sopenharmony_ci format, 749cb93a386Sopenharmony_ci dimensions, 750cb93a386Sopenharmony_ci mipMapped, 751cb93a386Sopenharmony_ci mipmapStatus, 752cb93a386Sopenharmony_ci SkBackingFit::kExact, 753cb93a386Sopenharmony_ci SkBudgeted::kNo, 754cb93a386Sopenharmony_ci GrProtected::kNo, 755cb93a386Sopenharmony_ci GrInternalSurfaceFlags::kReadOnly, 756cb93a386Sopenharmony_ci GrSurfaceProxy::UseAllocator::kYes, 757cb93a386Sopenharmony_ci GrDDLProvider::kYes)); 758cb93a386Sopenharmony_ci proxy->priv().setIsPromiseProxy(); 759cb93a386Sopenharmony_ci return proxy; 760cb93a386Sopenharmony_ci} 761cb93a386Sopenharmony_ci 762cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback, 763cb93a386Sopenharmony_ci const GrBackendFormat& format, 764cb93a386Sopenharmony_ci SkISize dimensions, 765cb93a386Sopenharmony_ci GrMipmapped mipMapped, 766cb93a386Sopenharmony_ci GrMipmapStatus mipmapStatus, 767cb93a386Sopenharmony_ci GrInternalSurfaceFlags surfaceFlags, 768cb93a386Sopenharmony_ci SkBackingFit fit, 769cb93a386Sopenharmony_ci SkBudgeted budgeted, 770cb93a386Sopenharmony_ci GrProtected isProtected, 771cb93a386Sopenharmony_ci GrSurfaceProxy::UseAllocator useAllocator) { 772cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 773cb93a386Sopenharmony_ci if (this->isAbandoned()) { 774cb93a386Sopenharmony_ci return nullptr; 775cb93a386Sopenharmony_ci } 776cb93a386Sopenharmony_ci SkASSERT((dimensions.fWidth <= 0 && dimensions.fHeight <= 0) || 777cb93a386Sopenharmony_ci (dimensions.fWidth > 0 && dimensions.fHeight > 0)); 778cb93a386Sopenharmony_ci 779cb93a386Sopenharmony_ci if (!format.isValid() || format.backend() != fImageContext->backend()) { 780cb93a386Sopenharmony_ci return nullptr; 781cb93a386Sopenharmony_ci } 782cb93a386Sopenharmony_ci 783cb93a386Sopenharmony_ci if (dimensions.fWidth > this->caps()->maxTextureSize() || 784cb93a386Sopenharmony_ci dimensions.fHeight > this->caps()->maxTextureSize()) { 785cb93a386Sopenharmony_ci return nullptr; 786cb93a386Sopenharmony_ci } 787cb93a386Sopenharmony_ci 788cb93a386Sopenharmony_ci return assignTagToProxy(sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(callback), 789cb93a386Sopenharmony_ci format, 790cb93a386Sopenharmony_ci dimensions, 791cb93a386Sopenharmony_ci mipMapped, 792cb93a386Sopenharmony_ci mipmapStatus, 793cb93a386Sopenharmony_ci fit, 794cb93a386Sopenharmony_ci budgeted, 795cb93a386Sopenharmony_ci isProtected, 796cb93a386Sopenharmony_ci surfaceFlags, 797cb93a386Sopenharmony_ci useAllocator, 798cb93a386Sopenharmony_ci this->isDDLProvider()))); 799cb93a386Sopenharmony_ci} 800cb93a386Sopenharmony_ci 801cb93a386Sopenharmony_cisk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy( 802cb93a386Sopenharmony_ci LazyInstantiateCallback&& callback, 803cb93a386Sopenharmony_ci const GrBackendFormat& format, 804cb93a386Sopenharmony_ci SkISize dimensions, 805cb93a386Sopenharmony_ci int sampleCnt, 806cb93a386Sopenharmony_ci GrInternalSurfaceFlags surfaceFlags, 807cb93a386Sopenharmony_ci const TextureInfo* textureInfo, 808cb93a386Sopenharmony_ci GrMipmapStatus mipmapStatus, 809cb93a386Sopenharmony_ci SkBackingFit fit, 810cb93a386Sopenharmony_ci SkBudgeted budgeted, 811cb93a386Sopenharmony_ci GrProtected isProtected, 812cb93a386Sopenharmony_ci bool wrapsVkSecondaryCB, 813cb93a386Sopenharmony_ci UseAllocator useAllocator) { 814cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 815cb93a386Sopenharmony_ci if (this->isAbandoned()) { 816cb93a386Sopenharmony_ci return nullptr; 817cb93a386Sopenharmony_ci } 818cb93a386Sopenharmony_ci SkASSERT((dimensions.fWidth <= 0 && dimensions.fHeight <= 0) || 819cb93a386Sopenharmony_ci (dimensions.fWidth > 0 && dimensions.fHeight > 0)); 820cb93a386Sopenharmony_ci 821cb93a386Sopenharmony_ci if (dimensions.fWidth > this->caps()->maxRenderTargetSize() || 822cb93a386Sopenharmony_ci dimensions.fHeight > this->caps()->maxRenderTargetSize()) { 823cb93a386Sopenharmony_ci return nullptr; 824cb93a386Sopenharmony_ci } 825cb93a386Sopenharmony_ci 826cb93a386Sopenharmony_ci if (textureInfo) { 827cb93a386Sopenharmony_ci // Wrapped vulkan secondary command buffers don't support texturing since we won't have an 828cb93a386Sopenharmony_ci // actual VkImage to texture from. 829cb93a386Sopenharmony_ci SkASSERT(!wrapsVkSecondaryCB); 830cb93a386Sopenharmony_ci return assignTagToProxy(sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy( 831cb93a386Sopenharmony_ci *this->caps(), std::move(callback), format, dimensions, sampleCnt, 832cb93a386Sopenharmony_ci textureInfo->fMipmapped, mipmapStatus, fit, budgeted, isProtected, surfaceFlags, 833cb93a386Sopenharmony_ci useAllocator, this->isDDLProvider()))); 834cb93a386Sopenharmony_ci } 835cb93a386Sopenharmony_ci 836cb93a386Sopenharmony_ci GrRenderTargetProxy::WrapsVkSecondaryCB vkSCB = 837cb93a386Sopenharmony_ci wrapsVkSecondaryCB ? GrRenderTargetProxy::WrapsVkSecondaryCB::kYes 838cb93a386Sopenharmony_ci : GrRenderTargetProxy::WrapsVkSecondaryCB::kNo; 839cb93a386Sopenharmony_ci 840cb93a386Sopenharmony_ci return assignTagToProxy(sk_sp<GrRenderTargetProxy>( 841cb93a386Sopenharmony_ci new GrRenderTargetProxy(std::move(callback), format, dimensions, sampleCnt, fit, 842cb93a386Sopenharmony_ci budgeted, isProtected, surfaceFlags, useAllocator, vkSCB))); 843cb93a386Sopenharmony_ci} 844cb93a386Sopenharmony_ci 845cb93a386Sopenharmony_cisk_sp<GrTextureProxy> GrProxyProvider::MakeFullyLazyProxy(LazyInstantiateCallback&& callback, 846cb93a386Sopenharmony_ci const GrBackendFormat& format, 847cb93a386Sopenharmony_ci GrRenderable renderable, 848cb93a386Sopenharmony_ci int renderTargetSampleCnt, 849cb93a386Sopenharmony_ci GrProtected isProtected, 850cb93a386Sopenharmony_ci const GrCaps& caps, 851cb93a386Sopenharmony_ci UseAllocator useAllocator) { 852cb93a386Sopenharmony_ci if (!format.isValid()) { 853cb93a386Sopenharmony_ci return nullptr; 854cb93a386Sopenharmony_ci } 855cb93a386Sopenharmony_ci 856cb93a386Sopenharmony_ci SkASSERT(renderTargetSampleCnt == 1 || renderable == GrRenderable::kYes); 857cb93a386Sopenharmony_ci // TODO: If we ever have callers requesting specific surface flags then we shouldn't use the 858cb93a386Sopenharmony_ci // extra deferred flags here. Instead those callers should all pass in exactly what they want. 859cb93a386Sopenharmony_ci // However, as of today all uses of this essentially create a deferred proxy in the end. 860cb93a386Sopenharmony_ci GrInternalSurfaceFlags surfaceFlags = caps.getExtraSurfaceFlagsForDeferredRT(); 861cb93a386Sopenharmony_ci 862cb93a386Sopenharmony_ci // MakeFullyLazyProxy is only called at flush time so we know these texture proxies are 863cb93a386Sopenharmony_ci // not being created by a DDL provider. 864cb93a386Sopenharmony_ci static constexpr SkISize kLazyDims = {-1, -1}; 865cb93a386Sopenharmony_ci if (GrRenderable::kYes == renderable) { 866cb93a386Sopenharmony_ci return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy( 867cb93a386Sopenharmony_ci caps, std::move(callback), format, kLazyDims, renderTargetSampleCnt, 868cb93a386Sopenharmony_ci GrMipmapped::kNo, GrMipmapStatus::kNotAllocated, SkBackingFit::kApprox, 869cb93a386Sopenharmony_ci SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator, GrDDLProvider::kNo)); 870cb93a386Sopenharmony_ci } else { 871cb93a386Sopenharmony_ci return sk_sp<GrTextureProxy>( 872cb93a386Sopenharmony_ci new GrTextureProxy(std::move(callback), format, kLazyDims, GrMipmapped::kNo, 873cb93a386Sopenharmony_ci GrMipmapStatus::kNotAllocated, SkBackingFit::kApprox, 874cb93a386Sopenharmony_ci SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator, 875cb93a386Sopenharmony_ci GrDDLProvider::kNo)); 876cb93a386Sopenharmony_ci } 877cb93a386Sopenharmony_ci} 878cb93a386Sopenharmony_ci 879cb93a386Sopenharmony_civoid GrProxyProvider::processInvalidUniqueKey(const GrUniqueKey& key, GrTextureProxy* proxy, 880cb93a386Sopenharmony_ci InvalidateGPUResource invalidateGPUResource) { 881cb93a386Sopenharmony_ci this->processInvalidUniqueKeyImpl(key, proxy, invalidateGPUResource, RemoveTableEntry::kYes); 882cb93a386Sopenharmony_ci} 883cb93a386Sopenharmony_ci 884cb93a386Sopenharmony_civoid GrProxyProvider::processInvalidUniqueKeyImpl(const GrUniqueKey& key, GrTextureProxy* proxy, 885cb93a386Sopenharmony_ci InvalidateGPUResource invalidateGPUResource, 886cb93a386Sopenharmony_ci RemoveTableEntry removeTableEntry) { 887cb93a386Sopenharmony_ci SkASSERT(key.isValid()); 888cb93a386Sopenharmony_ci 889cb93a386Sopenharmony_ci if (!proxy) { 890cb93a386Sopenharmony_ci proxy = fUniquelyKeyedProxies.find(key); 891cb93a386Sopenharmony_ci } 892cb93a386Sopenharmony_ci SkASSERT(!proxy || proxy->getUniqueKey() == key); 893cb93a386Sopenharmony_ci 894cb93a386Sopenharmony_ci // Locate the corresponding GrGpuResource (if it needs to be invalidated) before clearing the 895cb93a386Sopenharmony_ci // proxy's unique key. We must do it in this order because 'key' may alias the proxy's key. 896cb93a386Sopenharmony_ci sk_sp<GrGpuResource> invalidGpuResource; 897cb93a386Sopenharmony_ci if (InvalidateGPUResource::kYes == invalidateGPUResource) { 898cb93a386Sopenharmony_ci auto direct = fImageContext->asDirectContext(); 899cb93a386Sopenharmony_ci if (direct) { 900cb93a386Sopenharmony_ci GrResourceProvider* resourceProvider = direct->priv().resourceProvider(); 901cb93a386Sopenharmony_ci invalidGpuResource = resourceProvider->findByUniqueKey<GrGpuResource>(key); 902cb93a386Sopenharmony_ci } 903cb93a386Sopenharmony_ci SkASSERT(!invalidGpuResource || invalidGpuResource->getUniqueKey() == key); 904cb93a386Sopenharmony_ci } 905cb93a386Sopenharmony_ci 906cb93a386Sopenharmony_ci // Note: this method is called for the whole variety of GrGpuResources so often 'key' 907cb93a386Sopenharmony_ci // will not be in 'fUniquelyKeyedProxies'. 908cb93a386Sopenharmony_ci if (proxy) { 909cb93a386Sopenharmony_ci if (removeTableEntry == RemoveTableEntry::kYes) { 910cb93a386Sopenharmony_ci fUniquelyKeyedProxies.remove(key); 911cb93a386Sopenharmony_ci } 912cb93a386Sopenharmony_ci proxy->cacheAccess().clearUniqueKey(); 913cb93a386Sopenharmony_ci } 914cb93a386Sopenharmony_ci 915cb93a386Sopenharmony_ci if (invalidGpuResource) { 916cb93a386Sopenharmony_ci invalidGpuResource->resourcePriv().removeUniqueKey(); 917cb93a386Sopenharmony_ci } 918cb93a386Sopenharmony_ci} 919cb93a386Sopenharmony_ci 920cb93a386Sopenharmony_ciGrDDLProvider GrProxyProvider::isDDLProvider() const { 921cb93a386Sopenharmony_ci return fImageContext->asDirectContext() ? GrDDLProvider::kNo : GrDDLProvider::kYes; 922cb93a386Sopenharmony_ci} 923cb93a386Sopenharmony_ci 924cb93a386Sopenharmony_ciuint32_t GrProxyProvider::contextID() const { 925cb93a386Sopenharmony_ci return fImageContext->priv().contextID(); 926cb93a386Sopenharmony_ci} 927cb93a386Sopenharmony_ci 928cb93a386Sopenharmony_ciconst GrCaps* GrProxyProvider::caps() const { 929cb93a386Sopenharmony_ci return fImageContext->priv().caps(); 930cb93a386Sopenharmony_ci} 931cb93a386Sopenharmony_ci 932cb93a386Sopenharmony_cisk_sp<const GrCaps> GrProxyProvider::refCaps() const { 933cb93a386Sopenharmony_ci return fImageContext->priv().refCaps(); 934cb93a386Sopenharmony_ci} 935cb93a386Sopenharmony_ci 936cb93a386Sopenharmony_cibool GrProxyProvider::isAbandoned() const { 937cb93a386Sopenharmony_ci return fImageContext->priv().abandoned(); 938cb93a386Sopenharmony_ci} 939cb93a386Sopenharmony_ci 940cb93a386Sopenharmony_civoid GrProxyProvider::orphanAllUniqueKeys() { 941cb93a386Sopenharmony_ci fUniquelyKeyedProxies.foreach([&](GrTextureProxy* proxy){ 942cb93a386Sopenharmony_ci proxy->fProxyProvider = nullptr; 943cb93a386Sopenharmony_ci }); 944cb93a386Sopenharmony_ci} 945cb93a386Sopenharmony_ci 946cb93a386Sopenharmony_civoid GrProxyProvider::removeAllUniqueKeys() { 947cb93a386Sopenharmony_ci fUniquelyKeyedProxies.foreach([&](GrTextureProxy* proxy){ 948cb93a386Sopenharmony_ci // It's not safe to remove table entries while iterating with foreach(), 949cb93a386Sopenharmony_ci // but since we're going to remove them all anyway, simply save that for the end. 950cb93a386Sopenharmony_ci this->processInvalidUniqueKeyImpl(proxy->getUniqueKey(), proxy, 951cb93a386Sopenharmony_ci InvalidateGPUResource::kNo, 952cb93a386Sopenharmony_ci RemoveTableEntry::kNo); 953cb93a386Sopenharmony_ci }); 954cb93a386Sopenharmony_ci // Removing all those table entries is safe now. 955cb93a386Sopenharmony_ci fUniquelyKeyedProxies.reset(); 956cb93a386Sopenharmony_ci} 957cb93a386Sopenharmony_ci 958cb93a386Sopenharmony_cibool GrProxyProvider::renderingDirectly() const { 959cb93a386Sopenharmony_ci return fImageContext->asDirectContext(); 960cb93a386Sopenharmony_ci} 961