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