diff options
author | Brian Osman <brianosman@google.com> | 2017-05-09 13:19:50 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-05-09 18:45:04 +0000 |
commit | 13dddce65fd87a8175a209a49f35615735a2886a (patch) | |
tree | 0f7d85e7ba8db0b3acc7c0ac2dccd839808856cf /tests | |
parent | 3734c7d9e39cce682c5095a8f187d41223955f5c (diff) |
Added SkImage::MakeCrossContextFromEncoded
Designed for Flutter's threading architecture, with
an eye to being useful to other clients. Under the
hood, uses a new image generator class to lazily wrap
a texture for multiple GrContexts.
Re-land of https://skia-review.googlesource.com/c/14180/
Bug: skia:
Change-Id: I3dd382640629b79b3058f18fee68d043566e43e5
Reviewed-on: https://skia-review.googlesource.com/15895
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/ImageTest.cpp | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp index 2c4ba8f15b..c747b8ea5b 100644 --- a/tests/ImageTest.cpp +++ b/tests/ImageTest.cpp @@ -34,6 +34,7 @@ #if SK_SUPPORT_GPU #include "GrContextPriv.h" #include "GrGpu.h" +#include "GrResourceCache.h" #include "GrTest.h" #endif @@ -806,6 +807,7 @@ struct TextureReleaseChecker { static_cast<TextureReleaseChecker*>(self)->fReleaseCount++; } }; + DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SkImage_NewFromTextureRelease, reporter, ctxInfo) { const int kWidth = 10; const int kHeight = 10; @@ -854,6 +856,135 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SkImage_NewFromTextureRelease, reporter, c ctxInfo.grContext()->getGpu()->deleteTestingOnlyBackendTexture(backendTexHandle); } +DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SkImage_MakeCrossContextRelease, reporter, ctxInfo) { + GrContext* ctx = ctxInfo.grContext(); + + // If we don't have proper support for this feature, the factory will fallback to returning + // codec-backed images. Those will "work", but some of our checks will fail because we expect + // the cross-context images not to work on multiple contexts at once. + if (!ctx->caps()->crossContextTextureSupport()) { + return; + } + + // We test three lifetime patterns for a single context: + // 1) Create image, free image + // 2) Create image, draw, flush, free image + // 3) Create image, draw, free image, flush + // ... and then repeat the last two patterns with drawing on a second* context: + // 4) Create image, draw*, flush*, free image + // 5) Create image, draw*, free iamge, flush* + + sk_sp<SkData> data = GetResourceAsData("mandrill_128.png"); + SkASSERT(data.get()); + + // Case #1: Create image, free image + { + sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr)); + refImg.reset(nullptr); // force a release of the image + } + + SkImageInfo info = SkImageInfo::MakeN32Premul(128, 128); + sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info); + SkCanvas* canvas = surface->getCanvas(); + + // Case #2: Create image, draw, flush, free image + { + sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr)); + + canvas->drawImage(refImg, 0, 0); + canvas->flush(); + + refImg.reset(nullptr); // force a release of the image + } + + // Case #3: Create image, draw, free image, flush + { + sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr)); + + canvas->drawImage(refImg, 0, 0); + refImg.reset(nullptr); // force a release of the image + + canvas->flush(); + } + + // Configure second context + sk_gpu_test::TestContext* testContext = ctxInfo.testContext(); + + GrContextFactory otherFactory; + ContextInfo otherContextInfo = otherFactory.getContextInfo(pick_second_context_type(ctxInfo)); + GrContext* otherCtx = otherContextInfo.grContext(); + sk_gpu_test::TestContext* otherTestContext = otherContextInfo.testContext(); + + surface = SkSurface::MakeRenderTarget(otherCtx, SkBudgeted::kNo, info); + canvas = surface->getCanvas(); + + // Case #4: Create image, draw*, flush*, free image + { + testContext->makeCurrent(); + sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr)); + + otherTestContext->makeCurrent(); + canvas->drawImage(refImg, 0, 0); + canvas->flush(); + + testContext->makeCurrent(); + refImg.reset(nullptr); // force a release of the image + } + + // Case #5: Create image, draw*, free image, flush* + { + testContext->makeCurrent(); + sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr)); + + otherTestContext->makeCurrent(); + canvas->drawImage(refImg, 0, 0); + + testContext->makeCurrent(); + refImg.reset(nullptr); // force a release of the image + + otherTestContext->makeCurrent(); + canvas->flush(); + } + + // Case #6: Verify that only one context can be using the image at a time + { + testContext->makeCurrent(); + sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr)); + + // Any context should be able to borrow the texture at this point + sk_sp<SkColorSpace> texColorSpace; + sk_sp<GrTextureProxy> proxy = as_IB(refImg)->asTextureProxyRef( + ctx, GrSamplerParams::ClampNoFilter(), nullptr, &texColorSpace, nullptr); + REPORTER_ASSERT(reporter, proxy); + + // But once it's borrowed, no other context should be able to borrow + otherTestContext->makeCurrent(); + sk_sp<GrTextureProxy> otherProxy = as_IB(refImg)->asTextureProxyRef( + otherCtx, GrSamplerParams::ClampNoFilter(), nullptr, &texColorSpace, nullptr); + REPORTER_ASSERT(reporter, !otherProxy); + + // Original context (that's already borrowing) should be okay + testContext->makeCurrent(); + sk_sp<GrTextureProxy> proxySecondRef = as_IB(refImg)->asTextureProxyRef( + ctx, GrSamplerParams::ClampNoFilter(), nullptr, &texColorSpace, nullptr); + REPORTER_ASSERT(reporter, proxySecondRef); + + // Releae all refs from the original context + proxy.reset(nullptr); + proxySecondRef.reset(nullptr); + + // Now we should be able to borrow the texture from the other context + otherTestContext->makeCurrent(); + otherProxy = as_IB(refImg)->asTextureProxyRef( + otherCtx, GrSamplerParams::ClampNoFilter(), nullptr, &texColorSpace, nullptr); + REPORTER_ASSERT(reporter, otherProxy); + + // Release everything + otherProxy.reset(nullptr); + refImg.reset(nullptr); + } +} + static void check_images_same(skiatest::Reporter* reporter, const SkImage* a, const SkImage* b) { if (a->width() != b->width() || a->height() != b->height()) { ERRORF(reporter, "Images must have the same size"); |