Add deferred texture upload API.
Performs thread-safe decoding of SkImage in order to later create a texture-backed SkImage.
The client allocates storage for the data.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1776693002
Review URL: https://codereview.chromium.org/1776693002
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index aaf601d..9dfbe36 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -822,4 +822,75 @@
}
}
+DEF_GPUTEST_FOR_NATIVE_CONTEXT(DeferredTextureImage, reporter, context, glContext) {
+ SkAutoTUnref<GrContextThreadSafeProxy> proxy(context->threadSafeProxy());
+
+ GrContextFactory otherFactory;
+ GrContextFactory::ContextInfo otherContextInfo =
+ otherFactory.getContextInfo(GrContextFactory::kNative_GLContextType);
+
+ glContext->makeCurrent();
+ REPORTER_ASSERT(reporter, proxy);
+ struct {
+ std::function<SkImage *()> fImageFactory;
+ bool fExpectation;
+ } testCases[] = {
+ { create_image, true },
+ { create_codec_image, true },
+ { create_data_image, true },
+ { create_picture_image, false },
+ { [context] { return create_gpu_image(context); }, false },
+ // Create a texture image in a another GrContext.
+ { [glContext, otherContextInfo] {
+ otherContextInfo.fGLContext->makeCurrent();
+ SkImage *otherContextImage = create_gpu_image(otherContextInfo.fGrContext);
+ glContext->makeCurrent();
+ return otherContextImage;
+ }, false },
+ };
+
+
+ for (auto testCase : testCases) {
+ SkAutoTUnref<SkImage> image(testCase.fImageFactory());
+
+ // This isn't currently used in the implementation, just set any old values.
+ SkImage::DeferredTextureImageUsageParams params;
+ params.fQuality = kLow_SkFilterQuality;
+ params.fMatrix = SkMatrix::I();
+
+ size_t size = image->getDeferredTextureImageData(*proxy, ¶ms, 1, nullptr);
+
+ static const char *const kFS[] = { "fail", "succeed" };
+ if (SkToBool(size) != testCase.fExpectation) {
+ ERRORF(reporter, "This image was expected to %s but did not.",
+ kFS[testCase.fExpectation]);
+ }
+ if (size) {
+ void* buffer = sk_malloc_throw(size);
+ void* misaligned = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(buffer) + 3);
+ if (image->getDeferredTextureImageData(*proxy, ¶ms, 1, misaligned)) {
+ ERRORF(reporter, "Should fail when buffer is misaligned.");
+ }
+ if (!image->getDeferredTextureImageData(*proxy, ¶ms, 1, buffer)) {
+ ERRORF(reporter, "deferred image size succeeded but creation failed.");
+ } else {
+ for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
+ SkAutoTUnref<SkImage> newImage(
+ SkImage::NewFromDeferredTextureImageData(context, buffer, budgeted));
+ REPORTER_ASSERT(reporter, SkToBool(newImage));
+ if (newImage) {
+ check_images_same(reporter, image, newImage);
+ }
+ // The other context should not be able to create images from texture data
+ // created by the original context.
+ SkAutoTUnref<SkImage> newImage2(SkImage::NewFromDeferredTextureImageData(
+ otherContextInfo.fGrContext, buffer, budgeted));
+ REPORTER_ASSERT(reporter, !newImage2);
+ glContext->makeCurrent();
+ }
+ }
+ sk_free(buffer);
+ }
+ }
+}
#endif