diff options
-rw-r--r-- | include/gpu/GrTypes.h | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 14 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 1 | ||||
-rw-r--r-- | src/gpu/vk/GrVkTexture.cpp | 11 | ||||
-rw-r--r-- | src/gpu/vk/GrVkTextureRenderTarget.cpp | 1 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.cpp | 10 | ||||
-rw-r--r-- | tests/CrossContextImageTest.cpp | 17 | ||||
-rw-r--r-- | tests/ResourceCacheTest.cpp | 21 |
8 files changed, 63 insertions, 15 deletions
diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h index 654febd3ca..62e8a791b3 100644 --- a/include/gpu/GrTypes.h +++ b/include/gpu/GrTypes.h @@ -676,6 +676,9 @@ enum GrWrapOwnership { /** Skia will assume ownership of the resource and free it. */ kAdopt_GrWrapOwnership, + + /** Skia will assume ownership of the resource, free it, and reuse it within the cache. */ + kAdoptAndCache_GrWrapOwnership, }; /** diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index d7af9de287..3924a5a84e 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -520,6 +520,7 @@ sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, // next line relies on GrBackendTextureDesc's flags matching GrTexture's bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag); + SkASSERT(!renderTarget || kAdoptAndCache_GrWrapOwnership != ownership); // Not supported GrGLTexture::IDDesc idDesc; idDesc.fInfo = *info; @@ -546,10 +547,10 @@ sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, return nullptr; } - if (kAdopt_GrWrapOwnership == ownership) { - idDesc.fOwnership = GrBackendObjectOwnership::kOwned; - } else { + if (kBorrow_GrWrapOwnership == ownership) { idDesc.fOwnership = GrBackendObjectOwnership::kBorrowed; + } else { + idDesc.fOwnership = GrBackendObjectOwnership::kOwned; } GrSurfaceDesc surfDesc; @@ -575,7 +576,12 @@ sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, } return GrGLTextureRenderTarget::MakeWrapped(this, surfDesc, idDesc, rtIDDesc); } - return GrGLTexture::MakeWrapped(this, surfDesc, idDesc); + + if (kAdoptAndCache_GrWrapOwnership == ownership) { + return sk_sp<GrTexture>(new GrGLTexture(this, SkBudgeted::kYes, surfDesc, idDesc)); + } else { + return GrGLTexture::MakeWrapped(this, surfDesc, idDesc); + } } sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc){ diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index 81fb089087..6412a55d0c 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -779,6 +779,7 @@ sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, surfDesc.fConfig = desc.fConfig; surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount()); bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag); + SkASSERT(!renderTarget || kAdoptAndCache_GrWrapOwnership != ownership); // Not supported // In GL, Chrome assumes all textures are BottomLeft // In VK, we don't have this restriction surfDesc.fOrigin = resolve_origin(desc.fOrigin); diff --git a/src/gpu/vk/GrVkTexture.cpp b/src/gpu/vk/GrVkTexture.cpp index a8f1bf00dc..fb6b94fbc9 100644 --- a/src/gpu/vk/GrVkTexture.cpp +++ b/src/gpu/vk/GrVkTexture.cpp @@ -96,10 +96,13 @@ sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu, return nullptr; } - GrVkImage::Wrapped wrapped = kBorrow_GrWrapOwnership == ownership ? GrVkImage::kBorrowed_Wrapped - : GrVkImage::kAdopted_Wrapped; - - return sk_sp<GrVkTexture>(new GrVkTexture(gpu, kWrapped, desc, *info, imageView, wrapped)); + if (kAdoptAndCache_GrWrapOwnership == ownership) { + return sk_sp<GrVkTexture>(new GrVkTexture(gpu, SkBudgeted::kYes, desc, *info, imageView)); + } else { + GrVkImage::Wrapped wrapped = kBorrow_GrWrapOwnership == ownership + ? GrVkImage::kBorrowed_Wrapped : GrVkImage::kAdopted_Wrapped; + return sk_sp<GrVkTexture>(new GrVkTexture(gpu, kWrapped, desc, *info, imageView, wrapped)); + } } GrVkTexture::~GrVkTexture() { diff --git a/src/gpu/vk/GrVkTextureRenderTarget.cpp b/src/gpu/vk/GrVkTextureRenderTarget.cpp index cfa63be8af..1d7d75683f 100644 --- a/src/gpu/vk/GrVkTextureRenderTarget.cpp +++ b/src/gpu/vk/GrVkTextureRenderTarget.cpp @@ -143,6 +143,7 @@ GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(GrVkGpu* gpu, SkASSERT(info); // Wrapped textures require both image and allocation (because they can be mapped) SkASSERT(VK_NULL_HANDLE != info->fImage && VK_NULL_HANDLE != info->fAlloc.fMemory); + SkASSERT(kAdoptAndCache_GrWrapOwnership != ownership); // Not supported GrVkImage::Wrapped wrapped = kBorrow_GrWrapOwnership == ownership ? GrVkImage::kBorrowed_Wrapped : GrVkImage::kAdopted_Wrapped; diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp index a3649acf19..ffa7d9ed9f 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -264,7 +264,8 @@ static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx, const GrBackend tex->setRelease(releaseProc, releaseCtx); } - const SkBudgeted budgeted = SkBudgeted::kNo; + const SkBudgeted budgeted = (kAdoptAndCache_GrWrapOwnership == ownership) + ? SkBudgeted::kYes : SkBudgeted::kNo; return sk_make_sp<SkImage_Gpu>(kNeedNewImageUniqueID, at, std::move(tex), std::move(colorSpace), budgeted); } @@ -476,8 +477,11 @@ sk_sp<SkImage> SkImage::MakeFromCrossContextImageData( ccid->fTextureData->attachToContext(context); } - return MakeFromAdoptedTexture(context, ccid->fDesc, ccid->fAlphaType, - std::move(ccid->fColorSpace)); + // This texture was created by Ganesh on another thread (see MakeFromEncoded, above). + // Thus, we can import it back into our cache and treat it as our own (again). + GrWrapOwnership ownership = kAdoptAndCache_GrWrapOwnership; + return new_wrapped_texture_common(context, ccid->fDesc, ccid->fAlphaType, + std::move(ccid->fColorSpace), ownership, nullptr, nullptr); } sk_sp<SkImage> SkImage::makeNonTextureImage() const { diff --git a/tests/CrossContextImageTest.cpp b/tests/CrossContextImageTest.cpp index e37b095c93..82eb2d591e 100644 --- a/tests/CrossContextImageTest.cpp +++ b/tests/CrossContextImageTest.cpp @@ -140,9 +140,24 @@ DEF_GPUTEST(CrossContextImage_SharedContextSameThread, reporter, /*factory*/) { REPORTER_ASSERT(reporter, ccid != nullptr); ContextInfo info2 = factory.getSharedContextInfo(info.grContext()); - auto image = SkImage::MakeFromCrossContextImageData(info2.grContext(), std::move(ccid)); + GrContext* ctx2 = info2.grContext(); + int resourceCountBefore = 0, resourceCountAfter = 0; + size_t resourceBytesBefore = 0, resourceBytesAfter = 0; + if (ctx2) { + ctx2->getResourceCacheUsage(&resourceCountBefore, &resourceBytesBefore); + } + + auto image = SkImage::MakeFromCrossContextImageData(ctx2, std::move(ccid)); REPORTER_ASSERT(reporter, image != nullptr); + if (ctx2) { + // MakeFromCrossContextImageData should have imported the texture back into our + // cache, so we should see an uptick. + ctx2->getResourceCacheUsage(&resourceCountAfter, &resourceBytesAfter); + REPORTER_ASSERT(reporter, resourceCountAfter == resourceCountBefore + 1); + REPORTER_ASSERT(reporter, resourceBytesAfter > resourceBytesBefore); + } + // JPEG encode -> decode won't round trip the image perfectly assert_equal(reporter, testImage.get(), image.get(), SkEncodedImageFormat::kJPEG == format ? 2 : 0); diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp index a2064ae557..24545369cb 100644 --- a/tests/ResourceCacheTest.cpp +++ b/tests/ResourceCacheTest.cpp @@ -208,12 +208,13 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceCacheWrappedResources, reporter, ctxI return; } - GrBackendObject texHandles[2]; + GrBackendObject texHandles[3]; static const int kW = 100; static const int kH = 100; texHandles[0] = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH, kRGBA_8888_GrPixelConfig); texHandles[1] = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH, kRGBA_8888_GrPixelConfig); + texHandles[2] = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH, kRGBA_8888_GrPixelConfig); context->resetContext(); @@ -230,26 +231,40 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceCacheWrappedResources, reporter, ctxI sk_sp<GrTexture> adopted(context->resourceProvider()->wrapBackendTexture( desc, kAdopt_GrWrapOwnership)); - REPORTER_ASSERT(reporter, borrowed != nullptr && adopted != nullptr); - if (!borrowed || !adopted) { + desc.fTextureHandle = texHandles[2]; + sk_sp<GrTexture> adoptedAndCached(context->resourceProvider()->wrapBackendTexture( + desc, kAdoptAndCache_GrWrapOwnership)); + + REPORTER_ASSERT(reporter, borrowed != nullptr && adopted != nullptr && + adoptedAndCached != nullptr); + if (!borrowed || !adopted || !adoptedAndCached) { return; } borrowed.reset(nullptr); adopted.reset(nullptr); + adoptedAndCached.reset(nullptr); context->flush(); bool borrowedIsAlive = gpu->isTestingOnlyBackendTexture(texHandles[0]); bool adoptedIsAlive = gpu->isTestingOnlyBackendTexture(texHandles[1]); + bool adoptedAndCachedIsAlive = gpu->isTestingOnlyBackendTexture(texHandles[2]); REPORTER_ASSERT(reporter, borrowedIsAlive); REPORTER_ASSERT(reporter, !adoptedIsAlive); + REPORTER_ASSERT(reporter, adoptedAndCachedIsAlive); // Still alive because it's in the cache gpu->deleteTestingOnlyBackendTexture(texHandles[0], !borrowedIsAlive); gpu->deleteTestingOnlyBackendTexture(texHandles[1], !adoptedIsAlive); + // We can't delete texHandles[2] - we've given control of the lifetime to the context/cache context->resetContext(); + + // Purge the cache. This should force texHandles[2] to be deleted + context->getResourceCache()->purgeAllUnlocked(); + adoptedAndCachedIsAlive = gpu->isTestingOnlyBackendTexture(texHandles[2]); + REPORTER_ASSERT(reporter, !adoptedAndCachedIsAlive); } class TestResource : public GrGpuResource { |