aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
authorGravatar Brian Osman <brianosman@google.com>2017-05-08 15:16:45 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-08 19:56:27 +0000
commit83b1b3db36e8622f4bbc8c391d5c714e258d1e03 (patch)
tree95c4bf6e53bc73f90373fa06dbf6afa8298420e5 /tests
parentaef837a542cd91fba46bc0b3d4571a598710b90e (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. Bug: skia: Change-Id: I6c37b12c8ab5bce94b91190e5f0beb91d31ae81b Reviewed-on: https://skia-review.googlesource.com/14180 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/ImageTest.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 2c4ba8f15b..dc664cf2f0 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -806,6 +806,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 +855,128 @@ 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) {
+ sk_sp<SkData> data = GetResourceAsData("mandrill_128.png");
+ SkASSERT(data.get());
+
+ GrContext* ctx = ctxInfo.grContext();
+
+ // 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*
+
+ // 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");