diff options
-rw-r--r-- | include/gpu/GrBackendSurface.h | 1 | ||||
-rw-r--r-- | src/gpu/GrBackendTextureImageGenerator.cpp | 97 | ||||
-rw-r--r-- | src/gpu/GrBackendTextureImageGenerator.h | 3 | ||||
-rw-r--r-- | src/gpu/GrTextureProxy.cpp | 1 | ||||
-rw-r--r-- | tests/GrMipMappedTest.cpp | 4 |
5 files changed, 74 insertions, 32 deletions
diff --git a/include/gpu/GrBackendSurface.h b/include/gpu/GrBackendSurface.h index f2381c2d0d..4cc6da3566 100644 --- a/include/gpu/GrBackendSurface.h +++ b/include/gpu/GrBackendSurface.h @@ -85,6 +85,7 @@ private: // Friending for access to the GrPixelConfig friend class SkImage; friend class SkSurface; + friend class GrBackendTextureImageGenerator; friend class GrGpu; friend class GrGLGpu; friend class GrVkGpu; diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp index 36dc139cab..efd366e63d 100644 --- a/src/gpu/GrBackendTextureImageGenerator.cpp +++ b/src/gpu/GrBackendTextureImageGenerator.cpp @@ -13,6 +13,7 @@ #include "GrRenderTargetContext.h" #include "GrResourceCache.h" #include "GrResourceProvider.h" +#include "GrResourceProviderPriv.h" #include "GrSemaphore.h" #include "GrTexture.h" #include "GrTexturePriv.h" @@ -63,6 +64,7 @@ GrBackendTextureImageGenerator::GrBackendTextureImageGenerator(const SkImageInfo , fRefHelper(new RefHelper(texture, owningContextID)) , fSemaphore(std::move(semaphore)) , fBackendTexture(backendTex) + , fConfig(backendTex.config()) , fSurfaceOrigin(origin) { } GrBackendTextureImageGenerator::~GrBackendTextureImageGenerator() { @@ -89,46 +91,81 @@ sk_sp<GrTextureProxy> GrBackendTextureImageGenerator::onGenerateTexture( return nullptr; } - sk_sp<GrTexture> tex; - uint32_t expectedID = SK_InvalidGenID; if (!fRefHelper->fBorrowingContextID.compare_exchange(&expectedID, context->uniqueID())) { if (fRefHelper->fBorrowingContextID != context->uniqueID()) { // Some other context is currently borrowing the texture. We aren't allowed to use it. return nullptr; } - } else { - if (fSemaphore && !fSemaphore->hasSubmittedWait()) { - context->getGpu()->waitSemaphore(fSemaphore); - } - } - - if (fRefHelper->fBorrowedTexture) { - // If a client re-draws the same image multiple times, the texture we return will be cached - // and re-used. If they draw a subset, though, we may be re-called. In that case, we want - // to re-use the borrowed texture we've previously created. - tex = sk_ref_sp(fRefHelper->fBorrowedTexture); - SkASSERT(tex); - } else { - // We just gained access to the texture. If we're on the original context, we could use the - // original texture, but we'd have no way of detecting that it's no longer in-use. So we - // always make a wrapped copy, where the release proc informs us that the context is done - // with it. This is unfortunate - we'll have two texture objects referencing the same GPU - // object. However, no client can ever see the original texture, so this should be safe. - tex = context->contextPriv().resourceProvider()->wrapBackendTexture( - fBackendTexture, kBorrow_GrWrapOwnership); - if (!tex) { - return nullptr; - } - fRefHelper->fBorrowedTexture = tex.get(); - - tex->setRelease(ReleaseRefHelper_TextureReleaseProc, fRefHelper); - fRefHelper->ref(); } SkASSERT(fRefHelper->fBorrowingContextID == context->uniqueID()); - sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(std::move(tex), fSurfaceOrigin); + GrSurfaceDesc desc; + desc.fOrigin = fSurfaceOrigin; + desc.fWidth = fBackendTexture.width(); + desc.fHeight = fBackendTexture.height(); + desc.fConfig = fConfig; + GrMipMapped mipMapped = fBackendTexture.hasMipMaps() ? GrMipMapped::kYes : GrMipMapped::kNo; + + // Must make copies of member variables to capture in the lambda since this image generator may + // be deleted before we actuallly execute the lambda. + GrSurfaceOrigin surfaceOrigin = fSurfaceOrigin; + sk_sp<GrSemaphore> semaphore = fSemaphore; + GrBackendTexture backendTexture = fBackendTexture; + RefHelper* refHelper = fRefHelper; + refHelper->ref(); + + sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeLazy( + [refHelper, semaphore, backendTexture, surfaceOrigin] + (GrResourceProvider* resourceProvider, GrSurfaceOrigin* outOrigin) { + if (!resourceProvider) { + // If we get here then we never created a texture to pass the refHelper ref off + // to. Thus we must unref it ourselves. + refHelper->unref(); + return sk_sp<GrTexture>(); + } + + if (semaphore && !semaphore->hasSubmittedWait()) { + resourceProvider->priv().gpu()->waitSemaphore(semaphore); + } + + sk_sp<GrTexture> tex; + if (refHelper->fBorrowedTexture) { + // If a client re-draws the same image multiple times, the texture we return + // will be cached and re-used. If they draw a subset, though, we may be + // re-called. In that case, we want to re-use the borrowed texture we've + // previously created. + tex = sk_ref_sp(refHelper->fBorrowedTexture); + SkASSERT(tex); + // The texture is holding onto a ref to the refHelper so since we have a ref to + // the texture we don't need to hold a ref to the refHelper. This unref's the + // ref we grabbed on refHelper in the lambda capture for this proxy. + refHelper->unref(); + } else { + // We just gained access to the texture. If we're on the original context, we + // could use the original texture, but we'd have no way of detecting that it's + // no longer in-use. So we always make a wrapped copy, where the release proc + // informs us that the context is done with it. This is unfortunate - we'll have + // two texture objects referencing the same GPU object. However, no client can + // ever see the original texture, so this should be safe. + tex = resourceProvider->wrapBackendTexture(backendTexture, + kBorrow_GrWrapOwnership); + if (!tex) { + refHelper->unref(); + return sk_sp<GrTexture>(); + } + refHelper->fBorrowedTexture = tex.get(); + + // By setting this release proc on the texture we are passing our ref on the + // refHelper to the texture. + tex->setRelease(ReleaseRefHelper_TextureReleaseProc, refHelper); + } + + *outOrigin = surfaceOrigin; + return tex; + + }, desc, mipMapped, SkBackingFit::kExact, SkBudgeted::kNo); if (0 == origin.fX && 0 == origin.fY && info.width() == fBackendTexture.width() && info.height() == fBackendTexture.height() && diff --git a/src/gpu/GrBackendTextureImageGenerator.h b/src/gpu/GrBackendTextureImageGenerator.h index ef96e6a238..f13a59345a 100644 --- a/src/gpu/GrBackendTextureImageGenerator.h +++ b/src/gpu/GrBackendTextureImageGenerator.h @@ -54,7 +54,7 @@ private: : fOriginalTexture(texture) , fOwningContextID(owningContextID) , fBorrowedTexture(nullptr) - , fBorrowingContextID(SK_InvalidGenID) { } + , fBorrowingContextID(SK_InvalidGenID) {} ~RefHelper(); @@ -73,6 +73,7 @@ private: sk_sp<GrSemaphore> fSemaphore; GrBackendTexture fBackendTexture; + GrPixelConfig fConfig; GrSurfaceOrigin fSurfaceOrigin; typedef SkImageGenerator INHERITED; diff --git a/src/gpu/GrTextureProxy.cpp b/src/gpu/GrTextureProxy.cpp index 68153dd50b..9eca5d9876 100644 --- a/src/gpu/GrTextureProxy.cpp +++ b/src/gpu/GrTextureProxy.cpp @@ -148,7 +148,6 @@ void GrTextureProxy::clearUniqueKey() { #ifdef SK_DEBUG void GrTextureProxy::validateLazyTexture(const GrTexture* texture) { SkASSERT(!texture->asRenderTarget()); - SkASSERT(GrMipMapped::kNo == this->mipMapped()); } #endif diff --git a/tests/GrMipMappedTest.cpp b/tests/GrMipMappedTest.cpp index 04bcca7c4d..df1e8ee901 100644 --- a/tests/GrMipMappedTest.cpp +++ b/tests/GrMipMappedTest.cpp @@ -155,6 +155,10 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, return; } + if (GrSurfaceProxy::LazyState::kNot != genProxy->lazyInstantiationState()) { + genProxy->priv().doLazyInstantiation(context->contextPriv().resourceProvider()); + } + REPORTER_ASSERT(reporter, genProxy->priv().isInstantiated()); GrTexture* genTexture = genProxy->priv().peekTexture(); |