Correctly pass screenshot fences to transaction callbacks
In some instances, a screenshot may be captured before a layer has a
release callback registered. This can happen when a new buffer has
not yet been transacted before a screenshot is captured. This causes the
screenshot fence to be dropped and the possibility of tearing when
capturing a screenshot while continuously rendering.
To resolve this, buffer screenshot fences into a list of future fences
when there is no callback registered, and merge those fences when
dispatching the release callback.
Bug: 302703346
Test: SurfaceViewTests#testMovingWhiteSurfaceView 100 times
Change-Id: I91aec3cdb0973092d48cd77e59dd3999e9d9e847
diff --git a/libs/ftl/future_test.cpp b/libs/ftl/future_test.cpp
index 5a245b6..1140639 100644
--- a/libs/ftl/future_test.cpp
+++ b/libs/ftl/future_test.cpp
@@ -102,4 +102,42 @@
decrement_thread.join();
}
+TEST(Future, WaitFor) {
+ using namespace std::chrono_literals;
+ {
+ auto future = ftl::yield(42);
+ // Check that we can wait_for multiple times without invalidating the future
+ EXPECT_EQ(future.wait_for(1s), std::future_status::ready);
+ EXPECT_EQ(future.wait_for(1s), std::future_status::ready);
+ EXPECT_EQ(future.get(), 42);
+ }
+
+ {
+ std::condition_variable cv;
+ std::mutex m;
+ bool ready = false;
+
+ std::packaged_task<int32_t()> get_int([&] {
+ std::unique_lock lk(m);
+ cv.wait(lk, [&] { return ready; });
+ return 24;
+ });
+
+ auto get_future = ftl::Future(get_int.get_future());
+ std::thread get_thread(std::move(get_int));
+
+ EXPECT_EQ(get_future.wait_for(0s), std::future_status::timeout);
+ {
+ std::unique_lock lk(m);
+ ready = true;
+ }
+ cv.notify_one();
+
+ EXPECT_EQ(get_future.wait_for(1s), std::future_status::ready);
+ EXPECT_EQ(get_future.get(), 24);
+
+ get_thread.join();
+ }
+}
+
} // namespace android::test