1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 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/GrSurfaceProxy.h" 9cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxyPriv.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h" 12cb93a386Sopenharmony_ci#include "src/core/SkMathPriv.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrAttachment.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrGpuResourcePriv.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrImageInfo.h" 17cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h" 18cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h" 19cb93a386Sopenharmony_ci#include "src/gpu/GrSurface.h" 20cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h" 21cb93a386Sopenharmony_ci#include "src/gpu/GrTextureRenderTargetProxy.h" 22cb93a386Sopenharmony_ci#include "src/gpu/SurfaceFillContext.h" 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ci#ifdef SK_DEBUG 25cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 26cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 27cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h" 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_cistatic bool is_valid_lazy(const SkISize& dimensions, SkBackingFit fit) { 30cb93a386Sopenharmony_ci // A "fully" lazy proxy's width and height are not known until instantiation time. 31cb93a386Sopenharmony_ci // So fully lazy proxies are created with width and height < 0. Regular lazy proxies must be 32cb93a386Sopenharmony_ci // created with positive widths and heights. The width and height are set to 0 only after a 33cb93a386Sopenharmony_ci // failed instantiation. The former must be "approximate" fit while the latter can be either. 34cb93a386Sopenharmony_ci return ((dimensions.fWidth < 0 && dimensions.fHeight < 0 && SkBackingFit::kApprox == fit) || 35cb93a386Sopenharmony_ci (dimensions.fWidth > 0 && dimensions.fHeight > 0)); 36cb93a386Sopenharmony_ci} 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_cistatic bool is_valid_non_lazy(SkISize dimensions) { 39cb93a386Sopenharmony_ci return dimensions.fWidth > 0 && dimensions.fHeight > 0; 40cb93a386Sopenharmony_ci} 41cb93a386Sopenharmony_ci#endif 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci// Deferred version 44cb93a386Sopenharmony_ciGrSurfaceProxy::GrSurfaceProxy(const GrBackendFormat& format, 45cb93a386Sopenharmony_ci SkISize dimensions, 46cb93a386Sopenharmony_ci SkBackingFit fit, 47cb93a386Sopenharmony_ci SkBudgeted budgeted, 48cb93a386Sopenharmony_ci GrProtected isProtected, 49cb93a386Sopenharmony_ci GrInternalSurfaceFlags surfaceFlags, 50cb93a386Sopenharmony_ci UseAllocator useAllocator) 51cb93a386Sopenharmony_ci : fSurfaceFlags(surfaceFlags) 52cb93a386Sopenharmony_ci , fFormat(format) 53cb93a386Sopenharmony_ci , fDimensions(dimensions) 54cb93a386Sopenharmony_ci , fFit(fit) 55cb93a386Sopenharmony_ci , fBudgeted(budgeted) 56cb93a386Sopenharmony_ci , fUseAllocator(useAllocator) 57cb93a386Sopenharmony_ci , fIsProtected(isProtected) { 58cb93a386Sopenharmony_ci SkASSERT(fFormat.isValid()); 59cb93a386Sopenharmony_ci SkASSERT(is_valid_non_lazy(dimensions)); 60cb93a386Sopenharmony_ci} 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci// Lazy-callback version 63cb93a386Sopenharmony_ciGrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, 64cb93a386Sopenharmony_ci const GrBackendFormat& format, 65cb93a386Sopenharmony_ci SkISize dimensions, 66cb93a386Sopenharmony_ci SkBackingFit fit, 67cb93a386Sopenharmony_ci SkBudgeted budgeted, 68cb93a386Sopenharmony_ci GrProtected isProtected, 69cb93a386Sopenharmony_ci GrInternalSurfaceFlags surfaceFlags, 70cb93a386Sopenharmony_ci UseAllocator useAllocator) 71cb93a386Sopenharmony_ci : fSurfaceFlags(surfaceFlags) 72cb93a386Sopenharmony_ci , fFormat(format) 73cb93a386Sopenharmony_ci , fDimensions(dimensions) 74cb93a386Sopenharmony_ci , fFit(fit) 75cb93a386Sopenharmony_ci , fBudgeted(budgeted) 76cb93a386Sopenharmony_ci , fUseAllocator(useAllocator) 77cb93a386Sopenharmony_ci , fLazyInstantiateCallback(std::move(callback)) 78cb93a386Sopenharmony_ci , fIsProtected(isProtected) { 79cb93a386Sopenharmony_ci SkASSERT(fFormat.isValid()); 80cb93a386Sopenharmony_ci SkASSERT(fLazyInstantiateCallback); 81cb93a386Sopenharmony_ci SkASSERT(is_valid_lazy(dimensions, fit)); 82cb93a386Sopenharmony_ci} 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci// Wrapped version 85cb93a386Sopenharmony_ciGrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, 86cb93a386Sopenharmony_ci SkBackingFit fit, 87cb93a386Sopenharmony_ci UseAllocator useAllocator) 88cb93a386Sopenharmony_ci : fTarget(std::move(surface)) 89cb93a386Sopenharmony_ci , fSurfaceFlags(fTarget->flags()) 90cb93a386Sopenharmony_ci , fFormat(fTarget->backendFormat()) 91cb93a386Sopenharmony_ci , fDimensions(fTarget->dimensions()) 92cb93a386Sopenharmony_ci , fFit(fit) 93cb93a386Sopenharmony_ci , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted 94cb93a386Sopenharmony_ci ? SkBudgeted::kYes 95cb93a386Sopenharmony_ci : SkBudgeted::kNo) 96cb93a386Sopenharmony_ci , fUseAllocator(useAllocator) 97cb93a386Sopenharmony_ci , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID! 98cb93a386Sopenharmony_ci , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo) { 99cb93a386Sopenharmony_ci SkASSERT(fFormat.isValid()); 100cb93a386Sopenharmony_ci} 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ciGrSurfaceProxy::~GrSurfaceProxy() { 103cb93a386Sopenharmony_ci} 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_cisk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider, 106cb93a386Sopenharmony_ci int sampleCnt, 107cb93a386Sopenharmony_ci GrRenderable renderable, 108cb93a386Sopenharmony_ci GrMipmapped mipMapped) const { 109cb93a386Sopenharmony_ci SkASSERT(mipMapped == GrMipmapped::kNo || fFit == SkBackingFit::kExact); 110cb93a386Sopenharmony_ci SkASSERT(!this->isLazy()); 111cb93a386Sopenharmony_ci SkASSERT(!fTarget); 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci sk_sp<GrSurface> surface; 114cb93a386Sopenharmony_ci if (SkBackingFit::kApprox == fFit) { 115cb93a386Sopenharmony_ci surface = resourceProvider->createApproxTexture(fDimensions, 116cb93a386Sopenharmony_ci fFormat, 117cb93a386Sopenharmony_ci fFormat.textureType(), 118cb93a386Sopenharmony_ci renderable, 119cb93a386Sopenharmony_ci sampleCnt, 120cb93a386Sopenharmony_ci fIsProtected); 121cb93a386Sopenharmony_ci } else { 122cb93a386Sopenharmony_ci surface = resourceProvider->createTexture(fDimensions, 123cb93a386Sopenharmony_ci fFormat, 124cb93a386Sopenharmony_ci fFormat.textureType(), 125cb93a386Sopenharmony_ci renderable, 126cb93a386Sopenharmony_ci sampleCnt, 127cb93a386Sopenharmony_ci mipMapped, 128cb93a386Sopenharmony_ci fBudgeted, 129cb93a386Sopenharmony_ci fIsProtected); 130cb93a386Sopenharmony_ci } 131cb93a386Sopenharmony_ci if (!surface) { 132cb93a386Sopenharmony_ci return nullptr; 133cb93a386Sopenharmony_ci } 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_ci if (fGrProxyTag.isGrTagValid()) { 136cb93a386Sopenharmony_ci surface->setResourceTag(fGrProxyTag); 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci return surface; 139cb93a386Sopenharmony_ci} 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_cibool GrSurfaceProxy::canSkipResourceAllocator() const { 142cb93a386Sopenharmony_ci if (fUseAllocator == UseAllocator::kNo) { 143cb93a386Sopenharmony_ci // Usually an atlas or onFlush proxy 144cb93a386Sopenharmony_ci return true; 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci auto peek = this->peekSurface(); 148cb93a386Sopenharmony_ci if (!peek) { 149cb93a386Sopenharmony_ci return false; 150cb93a386Sopenharmony_ci } 151cb93a386Sopenharmony_ci // If this resource is already allocated and not recyclable then the resource allocator does 152cb93a386Sopenharmony_ci // not need to do anything with it. 153cb93a386Sopenharmony_ci return !peek->resourcePriv().getScratchKey().isValid(); 154cb93a386Sopenharmony_ci} 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_civoid GrSurfaceProxy::assign(sk_sp<GrSurface> surface) { 157cb93a386Sopenharmony_ci SkASSERT(!fTarget && surface); 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_ci SkDEBUGCODE(this->validateSurface(surface.get());) 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_ci fTarget = std::move(surface); 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ci#ifdef SK_DEBUG 164cb93a386Sopenharmony_ci if (this->asRenderTargetProxy()) { 165cb93a386Sopenharmony_ci SkASSERT(fTarget->asRenderTarget()); 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci // In order to give DDL users some flexibility in the destination of there DDLs, 169cb93a386Sopenharmony_ci // a DDL's target proxy can be more conservative (and thus require less memory) 170cb93a386Sopenharmony_ci // than the actual GrSurface used to fulfill it. 171cb93a386Sopenharmony_ci if (!this->isDDLTarget() && kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) { 172cb93a386Sopenharmony_ci // TODO(11373): Can this check be exact? 173cb93a386Sopenharmony_ci SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly()); 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci#endif 176cb93a386Sopenharmony_ci} 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_cibool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt, 179cb93a386Sopenharmony_ci GrRenderable renderable, GrMipmapped mipMapped, 180cb93a386Sopenharmony_ci const GrUniqueKey* uniqueKey) { 181cb93a386Sopenharmony_ci SkASSERT(!this->isLazy()); 182cb93a386Sopenharmony_ci if (fTarget) { 183cb93a386Sopenharmony_ci if (uniqueKey && uniqueKey->isValid()) { 184cb93a386Sopenharmony_ci SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey); 185cb93a386Sopenharmony_ci } 186cb93a386Sopenharmony_ci return true; 187cb93a386Sopenharmony_ci } 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, sampleCnt, renderable, 190cb93a386Sopenharmony_ci mipMapped); 191cb93a386Sopenharmony_ci if (!surface) { 192cb93a386Sopenharmony_ci return false; 193cb93a386Sopenharmony_ci } 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci // If there was an invalidation message pending for this key, we might have just processed it, 196cb93a386Sopenharmony_ci // causing the key (stored on this proxy) to become invalid. 197cb93a386Sopenharmony_ci if (uniqueKey && uniqueKey->isValid()) { 198cb93a386Sopenharmony_ci resourceProvider->assignUniqueKeyToResource(*uniqueKey, surface.get()); 199cb93a386Sopenharmony_ci } 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_ci this->assign(std::move(surface)); 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_ci return true; 204cb93a386Sopenharmony_ci} 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_civoid GrSurfaceProxy::deinstantiate() { 207cb93a386Sopenharmony_ci SkASSERT(this->isInstantiated()); 208cb93a386Sopenharmony_ci fTarget = nullptr; 209cb93a386Sopenharmony_ci} 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_civoid GrSurfaceProxy::computeScratchKey(const GrCaps& caps, GrScratchKey* key) const { 212cb93a386Sopenharmony_ci SkASSERT(!this->isFullyLazy()); 213cb93a386Sopenharmony_ci GrRenderable renderable = GrRenderable::kNo; 214cb93a386Sopenharmony_ci int sampleCount = 1; 215cb93a386Sopenharmony_ci if (const auto* rtp = this->asRenderTargetProxy()) { 216cb93a386Sopenharmony_ci renderable = GrRenderable::kYes; 217cb93a386Sopenharmony_ci sampleCount = rtp->numSamples(); 218cb93a386Sopenharmony_ci } 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ci const GrTextureProxy* tp = this->asTextureProxy(); 221cb93a386Sopenharmony_ci GrMipmapped mipMapped = GrMipmapped::kNo; 222cb93a386Sopenharmony_ci if (tp) { 223cb93a386Sopenharmony_ci mipMapped = tp->mipmapped(); 224cb93a386Sopenharmony_ci } 225cb93a386Sopenharmony_ci 226cb93a386Sopenharmony_ci GrTexture::ComputeScratchKey(caps, this->backendFormat(), this->backingStoreDimensions(), 227cb93a386Sopenharmony_ci renderable, sampleCount, mipMapped, fIsProtected, key); 228cb93a386Sopenharmony_ci} 229cb93a386Sopenharmony_ci 230cb93a386Sopenharmony_ciSkISize GrSurfaceProxy::backingStoreDimensions() const { 231cb93a386Sopenharmony_ci SkASSERT(!this->isFullyLazy()); 232cb93a386Sopenharmony_ci if (fTarget) { 233cb93a386Sopenharmony_ci return fTarget->dimensions(); 234cb93a386Sopenharmony_ci } 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_ci if (SkBackingFit::kExact == fFit) { 237cb93a386Sopenharmony_ci return fDimensions; 238cb93a386Sopenharmony_ci } 239cb93a386Sopenharmony_ci return GrResourceProvider::MakeApprox(fDimensions); 240cb93a386Sopenharmony_ci} 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_cibool GrSurfaceProxy::isFunctionallyExact() const { 243cb93a386Sopenharmony_ci SkASSERT(!this->isFullyLazy()); 244cb93a386Sopenharmony_ci return fFit == SkBackingFit::kExact || 245cb93a386Sopenharmony_ci fDimensions == GrResourceProvider::MakeApprox(fDimensions); 246cb93a386Sopenharmony_ci} 247cb93a386Sopenharmony_ci 248cb93a386Sopenharmony_cibool GrSurfaceProxy::isFormatCompressed(const GrCaps* caps) const { 249cb93a386Sopenharmony_ci return caps->isFormatCompressed(this->backendFormat()); 250cb93a386Sopenharmony_ci} 251cb93a386Sopenharmony_ci 252cb93a386Sopenharmony_ci#ifdef SK_DEBUG 253cb93a386Sopenharmony_civoid GrSurfaceProxy::validate(GrContext_Base* context) const { 254cb93a386Sopenharmony_ci if (fTarget) { 255cb93a386Sopenharmony_ci SkASSERT(fTarget->getContext()->priv().matches(context)); 256cb93a386Sopenharmony_ci } 257cb93a386Sopenharmony_ci} 258cb93a386Sopenharmony_ci#endif 259cb93a386Sopenharmony_ci 260cb93a386Sopenharmony_cisk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrRecordingContext* rContext, 261cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> src, 262cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 263cb93a386Sopenharmony_ci GrMipmapped mipMapped, 264cb93a386Sopenharmony_ci SkIRect srcRect, 265cb93a386Sopenharmony_ci SkBackingFit fit, 266cb93a386Sopenharmony_ci SkBudgeted budgeted, 267cb93a386Sopenharmony_ci RectsMustMatch rectsMustMatch, 268cb93a386Sopenharmony_ci sk_sp<GrRenderTask>* outTask) { 269cb93a386Sopenharmony_ci SkASSERT(!src->isFullyLazy()); 270cb93a386Sopenharmony_ci int width; 271cb93a386Sopenharmony_ci int height; 272cb93a386Sopenharmony_ci 273cb93a386Sopenharmony_ci SkIPoint dstPoint; 274cb93a386Sopenharmony_ci if (rectsMustMatch == RectsMustMatch::kYes) { 275cb93a386Sopenharmony_ci width = src->width(); 276cb93a386Sopenharmony_ci height = src->height(); 277cb93a386Sopenharmony_ci dstPoint = {srcRect.fLeft, srcRect.fTop}; 278cb93a386Sopenharmony_ci } else { 279cb93a386Sopenharmony_ci width = srcRect.width(); 280cb93a386Sopenharmony_ci height = srcRect.height(); 281cb93a386Sopenharmony_ci dstPoint = {0, 0}; 282cb93a386Sopenharmony_ci } 283cb93a386Sopenharmony_ci 284cb93a386Sopenharmony_ci if (!srcRect.intersect(SkIRect::MakeSize(src->dimensions()))) { 285cb93a386Sopenharmony_ci return {}; 286cb93a386Sopenharmony_ci } 287cb93a386Sopenharmony_ci auto format = src->backendFormat().makeTexture2D(); 288cb93a386Sopenharmony_ci SkASSERT(format.isValid()); 289cb93a386Sopenharmony_ci 290cb93a386Sopenharmony_ci if (src->backendFormat().textureType() != GrTextureType::kExternal) { 291cb93a386Sopenharmony_ci GrImageInfo info(GrColorType::kUnknown, kUnknown_SkAlphaType, nullptr, {width, height}); 292cb93a386Sopenharmony_ci auto dstContext = rContext->priv().makeSC(info, 293cb93a386Sopenharmony_ci format, 294cb93a386Sopenharmony_ci fit, 295cb93a386Sopenharmony_ci origin, 296cb93a386Sopenharmony_ci GrRenderable::kNo, 297cb93a386Sopenharmony_ci 1, 298cb93a386Sopenharmony_ci mipMapped, 299cb93a386Sopenharmony_ci src->isProtected(), 300cb93a386Sopenharmony_ci budgeted); 301cb93a386Sopenharmony_ci sk_sp<GrRenderTask> copyTask; 302cb93a386Sopenharmony_ci if (dstContext && (copyTask = dstContext->copy(src, srcRect, dstPoint))) { 303cb93a386Sopenharmony_ci if (outTask) { 304cb93a386Sopenharmony_ci *outTask = std::move(copyTask); 305cb93a386Sopenharmony_ci } 306cb93a386Sopenharmony_ci return dstContext->asSurfaceProxyRef(); 307cb93a386Sopenharmony_ci } 308cb93a386Sopenharmony_ci } 309cb93a386Sopenharmony_ci if (src->asTextureProxy()) { 310cb93a386Sopenharmony_ci auto dstContext = rContext->priv().makeSFC(kUnknown_SkAlphaType, 311cb93a386Sopenharmony_ci nullptr, 312cb93a386Sopenharmony_ci {width, height}, 313cb93a386Sopenharmony_ci fit, 314cb93a386Sopenharmony_ci format, 315cb93a386Sopenharmony_ci 1, 316cb93a386Sopenharmony_ci mipMapped, 317cb93a386Sopenharmony_ci src->isProtected(), 318cb93a386Sopenharmony_ci GrSwizzle::RGBA(), 319cb93a386Sopenharmony_ci GrSwizzle::RGBA(), 320cb93a386Sopenharmony_ci origin, 321cb93a386Sopenharmony_ci budgeted); 322cb93a386Sopenharmony_ci GrSurfaceProxyView view(std::move(src), origin, GrSwizzle::RGBA()); 323cb93a386Sopenharmony_ci if (dstContext && dstContext->blitTexture(std::move(view), srcRect, dstPoint)) { 324cb93a386Sopenharmony_ci if (outTask) { 325cb93a386Sopenharmony_ci *outTask = dstContext->refRenderTask(); 326cb93a386Sopenharmony_ci } 327cb93a386Sopenharmony_ci return dstContext->asSurfaceProxyRef(); 328cb93a386Sopenharmony_ci } 329cb93a386Sopenharmony_ci } 330cb93a386Sopenharmony_ci // Can't use backend copies or draws. 331cb93a386Sopenharmony_ci return nullptr; 332cb93a386Sopenharmony_ci} 333cb93a386Sopenharmony_ci 334cb93a386Sopenharmony_cisk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, 335cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> src, 336cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 337cb93a386Sopenharmony_ci GrMipmapped mipMapped, 338cb93a386Sopenharmony_ci SkBackingFit fit, 339cb93a386Sopenharmony_ci SkBudgeted budgeted, 340cb93a386Sopenharmony_ci sk_sp<GrRenderTask>* outTask) { 341cb93a386Sopenharmony_ci SkASSERT(!src->isFullyLazy()); 342cb93a386Sopenharmony_ci auto rect = SkIRect::MakeSize(src->dimensions()); 343cb93a386Sopenharmony_ci return Copy(context, 344cb93a386Sopenharmony_ci std::move(src), 345cb93a386Sopenharmony_ci origin, 346cb93a386Sopenharmony_ci mipMapped, 347cb93a386Sopenharmony_ci rect, 348cb93a386Sopenharmony_ci fit, 349cb93a386Sopenharmony_ci budgeted, 350cb93a386Sopenharmony_ci RectsMustMatch::kNo, 351cb93a386Sopenharmony_ci outTask); 352cb93a386Sopenharmony_ci} 353cb93a386Sopenharmony_ci 354cb93a386Sopenharmony_ci#if GR_TEST_UTILS 355cb93a386Sopenharmony_ciint32_t GrSurfaceProxy::testingOnly_getBackingRefCnt() const { 356cb93a386Sopenharmony_ci if (fTarget) { 357cb93a386Sopenharmony_ci return fTarget->testingOnly_getRefCnt(); 358cb93a386Sopenharmony_ci } 359cb93a386Sopenharmony_ci 360cb93a386Sopenharmony_ci return -1; // no backing GrSurface 361cb93a386Sopenharmony_ci} 362cb93a386Sopenharmony_ci 363cb93a386Sopenharmony_ciGrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const { 364cb93a386Sopenharmony_ci return fSurfaceFlags; 365cb93a386Sopenharmony_ci} 366cb93a386Sopenharmony_ci 367cb93a386Sopenharmony_ciSkString GrSurfaceProxy::dump() const { 368cb93a386Sopenharmony_ci SkString tmp; 369cb93a386Sopenharmony_ci 370cb93a386Sopenharmony_ci tmp.appendf("proxyID: %d - surfaceID: %d", 371cb93a386Sopenharmony_ci this->uniqueID().asUInt(), 372cb93a386Sopenharmony_ci this->peekSurface() ? this->peekSurface()->uniqueID().asUInt() 373cb93a386Sopenharmony_ci : -1); 374cb93a386Sopenharmony_ci return tmp; 375cb93a386Sopenharmony_ci} 376cb93a386Sopenharmony_ci 377cb93a386Sopenharmony_ci#endif 378cb93a386Sopenharmony_ci 379cb93a386Sopenharmony_civoid GrSurfaceProxyPriv::exactify(bool allocatedCaseOnly) { 380cb93a386Sopenharmony_ci SkASSERT(!fProxy->isFullyLazy()); 381cb93a386Sopenharmony_ci if (this->isExact()) { 382cb93a386Sopenharmony_ci return; 383cb93a386Sopenharmony_ci } 384cb93a386Sopenharmony_ci 385cb93a386Sopenharmony_ci SkASSERT(SkBackingFit::kApprox == fProxy->fFit); 386cb93a386Sopenharmony_ci 387cb93a386Sopenharmony_ci if (fProxy->fTarget) { 388cb93a386Sopenharmony_ci // The kApprox but already instantiated case. Setting the proxy's width & height to 389cb93a386Sopenharmony_ci // the instantiated width & height could have side-effects going forward, since we're 390cb93a386Sopenharmony_ci // obliterating the area of interest information. This call (exactify) only used 391cb93a386Sopenharmony_ci // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be 392cb93a386Sopenharmony_ci // used for additional draws. 393cb93a386Sopenharmony_ci fProxy->fDimensions = fProxy->fTarget->dimensions(); 394cb93a386Sopenharmony_ci return; 395cb93a386Sopenharmony_ci } 396cb93a386Sopenharmony_ci 397cb93a386Sopenharmony_ci#ifndef SK_CRIPPLE_TEXTURE_REUSE 398cb93a386Sopenharmony_ci // In the post-implicit-allocation world we can't convert this proxy to be exact fit 399cb93a386Sopenharmony_ci // at this point. With explicit allocation switching this to exact will result in a 400cb93a386Sopenharmony_ci // different allocation at flush time. With implicit allocation, allocation would occur 401cb93a386Sopenharmony_ci // at draw time (rather than flush time) so this pathway was encountered less often (if 402cb93a386Sopenharmony_ci // at all). 403cb93a386Sopenharmony_ci if (allocatedCaseOnly) { 404cb93a386Sopenharmony_ci return; 405cb93a386Sopenharmony_ci } 406cb93a386Sopenharmony_ci#endif 407cb93a386Sopenharmony_ci 408cb93a386Sopenharmony_ci // The kApprox uninstantiated case. Making this proxy be exact should be okay. 409cb93a386Sopenharmony_ci // It could mess things up if prior decisions were based on the approximate size. 410cb93a386Sopenharmony_ci fProxy->fFit = SkBackingFit::kExact; 411cb93a386Sopenharmony_ci // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has 412cb93a386Sopenharmony_ci // already been computed we want to leave it alone so that amount will be removed when 413cb93a386Sopenharmony_ci // the special image goes away. If it hasn't been computed yet it might as well compute the 414cb93a386Sopenharmony_ci // exact amount. 415cb93a386Sopenharmony_ci} 416cb93a386Sopenharmony_ci 417cb93a386Sopenharmony_cibool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) { 418cb93a386Sopenharmony_ci SkASSERT(fProxy->isLazy()); 419cb93a386Sopenharmony_ci 420cb93a386Sopenharmony_ci sk_sp<GrSurface> surface; 421cb93a386Sopenharmony_ci if (const auto& uniqueKey = fProxy->getUniqueKey(); uniqueKey.isValid()) { 422cb93a386Sopenharmony_ci // First try to reattach to a cached version if the proxy is uniquely keyed 423cb93a386Sopenharmony_ci surface = resourceProvider->findByUniqueKey<GrSurface>(uniqueKey); 424cb93a386Sopenharmony_ci } 425cb93a386Sopenharmony_ci 426cb93a386Sopenharmony_ci bool syncKey = true; 427cb93a386Sopenharmony_ci bool releaseCallback = false; 428cb93a386Sopenharmony_ci if (!surface) { 429cb93a386Sopenharmony_ci auto result = fProxy->fLazyInstantiateCallback(resourceProvider, fProxy->callbackDesc()); 430cb93a386Sopenharmony_ci surface = std::move(result.fSurface); 431cb93a386Sopenharmony_ci syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced; 432cb93a386Sopenharmony_ci releaseCallback = surface && result.fReleaseCallback; 433cb93a386Sopenharmony_ci } 434cb93a386Sopenharmony_ci if (!surface) { 435cb93a386Sopenharmony_ci fProxy->fDimensions.setEmpty(); 436cb93a386Sopenharmony_ci return false; 437cb93a386Sopenharmony_ci } 438cb93a386Sopenharmony_ci 439cb93a386Sopenharmony_ci if (fProxy->isFullyLazy()) { 440cb93a386Sopenharmony_ci // This was a fully lazy proxy. We need to fill in the width & height. For partially 441cb93a386Sopenharmony_ci // lazy proxies we must preserve the original width & height since that indicates 442cb93a386Sopenharmony_ci // the content area. 443cb93a386Sopenharmony_ci fProxy->fDimensions = surface->dimensions(); 444cb93a386Sopenharmony_ci } 445cb93a386Sopenharmony_ci 446cb93a386Sopenharmony_ci SkASSERT(fProxy->width() <= surface->width()); 447cb93a386Sopenharmony_ci SkASSERT(fProxy->height() <= surface->height()); 448cb93a386Sopenharmony_ci 449cb93a386Sopenharmony_ci if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) { 450cb93a386Sopenharmony_ci texProxy->setTargetKeySync(syncKey); 451cb93a386Sopenharmony_ci if (syncKey) { 452cb93a386Sopenharmony_ci const GrUniqueKey& key = texProxy->getUniqueKey(); 453cb93a386Sopenharmony_ci if (key.isValid()) { 454cb93a386Sopenharmony_ci if (!surface->asTexture()->getUniqueKey().isValid()) { 455cb93a386Sopenharmony_ci // If 'surface' is newly created, attach the unique key 456cb93a386Sopenharmony_ci resourceProvider->assignUniqueKeyToResource(key, surface.get()); 457cb93a386Sopenharmony_ci } else { 458cb93a386Sopenharmony_ci // otherwise we had better have reattached to a cached version 459cb93a386Sopenharmony_ci SkASSERT(surface->asTexture()->getUniqueKey() == key); 460cb93a386Sopenharmony_ci } 461cb93a386Sopenharmony_ci } else { 462cb93a386Sopenharmony_ci SkASSERT(!surface->getUniqueKey().isValid()); 463cb93a386Sopenharmony_ci } 464cb93a386Sopenharmony_ci } 465cb93a386Sopenharmony_ci } 466cb93a386Sopenharmony_ci 467cb93a386Sopenharmony_ci this->assign(std::move(surface)); 468cb93a386Sopenharmony_ci if (releaseCallback) { 469cb93a386Sopenharmony_ci fProxy->fLazyInstantiateCallback = nullptr; 470cb93a386Sopenharmony_ci } 471cb93a386Sopenharmony_ci 472cb93a386Sopenharmony_ci return true; 473cb93a386Sopenharmony_ci} 474cb93a386Sopenharmony_ci 475cb93a386Sopenharmony_ci#ifdef SK_DEBUG 476cb93a386Sopenharmony_civoid GrSurfaceProxy::validateSurface(const GrSurface* surface) { 477cb93a386Sopenharmony_ci SkASSERTF(surface->backendFormat() == fFormat, "%s != %s", 478cb93a386Sopenharmony_ci surface->backendFormat().toStr().c_str(), fFormat.toStr().c_str()); 479cb93a386Sopenharmony_ci 480cb93a386Sopenharmony_ci this->onValidateSurface(surface); 481cb93a386Sopenharmony_ci} 482cb93a386Sopenharmony_ci#endif 483