summarylogtreecommitdiffstats
path: root/0001-ozone-wayland-Complete-submission-of-a-buffer-submit.patch
diff options
context:
space:
mode:
Diffstat (limited to '0001-ozone-wayland-Complete-submission-of-a-buffer-submit.patch')
-rw-r--r--0001-ozone-wayland-Complete-submission-of-a-buffer-submit.patch173
1 files changed, 173 insertions, 0 deletions
diff --git a/0001-ozone-wayland-Complete-submission-of-a-buffer-submit.patch b/0001-ozone-wayland-Complete-submission-of-a-buffer-submit.patch
new file mode 100644
index 000000000000..53da1d5d3118
--- /dev/null
+++ b/0001-ozone-wayland-Complete-submission-of-a-buffer-submit.patch
@@ -0,0 +1,173 @@
+Upstream-Status: Backport
+
+Backported from https://crrev.com/c/1946479
+
+Signed-off-by: Maksim Sisov <msisov@igalia.com>
+---
+From 4c9a7209005ee6c134692932d4c6d784d48ada34 Mon Sep 17 00:00:00 2001
+From: Maksim Sisov <msisov@igalia.com>
+Date: Tue, 3 Dec 2019 08:23:42 +0000
+Subject: [PATCH] ozone/wayland: Complete submission of a buffer submitted more
+ than once
+
+This CL fixes a corner use case that was caught by one of the users
+of Ozone/Wayland.
+
+The problem appeared when the Chromium compositor sent a next frame into
+the same buffer that had just been submitted and a OnSubmission callback
+had been sent to the viz process located WaylandBufferManager. This
+happened only when the remote inspector was attached and the screencast
+was enabled.
+
+In this case, Wayland compositor will not send an OnRelease callback
+and we should not wait for that. Instead, we must complete the
+submission immediately and set the |WaylandBuffer::released|
+member to be false. Once another buffer is committed, Wayland compositor
+will release the previous buffer.
+
+Bug: 1029777
+Change-Id: Ib74c16f41f128298998bc9699f8d9ded3697cd43
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1946479
+Commit-Queue: Maksim Sisov <msisov@igalia.com>
+Reviewed-by: Robert Kroeger <rjkroege@chromium.org>
+Cr-Commit-Position: refs/heads/master@{#720878}
+---
+ .../host/wayland_buffer_manager_host.cc | 22 ++++--
+ .../wayland_buffer_manager_unittest.cc | 78 +++++++++++++++++++
+ 2 files changed, 95 insertions(+), 5 deletions(-)
+
+diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
+index f360f916cae7..c7fc7094475a 100644
+--- a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
++++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
+@@ -231,13 +231,20 @@ class WaylandBufferManagerHost::Surface {
+ DCHECK(buffer);
+ DCHECK(!pending_buffer_);
+
+- // Once the BufferRelease is called, the buffer will be released.
+- DCHECK(buffer->released);
+- buffer->released = false;
+-
+ DCHECK(!submitted_buffer_);
+ submitted_buffer_ = buffer;
+
++ // if the same buffer has been submitted again right after the client
++ // received OnSubmission for that buffer, just verify that the buffer has
++ // not been released by Wayland compositor, which is correct.
++ if (prev_submitted_buffer_ != submitted_buffer_) {
++ // Once the BufferRelease is called, the buffer will be released.
++ DCHECK(buffer->released);
++ buffer->released = false;
++ } else {
++ DCHECK(!buffer->released);
++ }
++
+ AttachAndDamageBuffer(buffer);
+
+ SetupFrameCallback();
+@@ -258,7 +265,12 @@ class WaylandBufferManagerHost::Surface {
+ // If it was the very first frame, the surface has not had a back buffer
+ // before, and Wayland won't release the front buffer until next buffer is
+ // attached. Thus, notify about successful submission immediately.
+- if (!prev_submitted_buffer_)
++ //
++ // As said above, if the client submits the same buffer again, we must
++ // notify the client about the submission immediately as Wayland compositor
++ // is not going to send a release callback for a buffer committed more than
++ // once.
++ if (!prev_submitted_buffer_ || prev_submitted_buffer_ == submitted_buffer_)
+ CompleteSubmission();
+
+ return true;
+diff --git a/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc b/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
+index 3908e2af629c..012e40f5a75a 100644
+--- a/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
++++ b/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
+@@ -477,6 +477,84 @@ TEST_P(WaylandBufferManagerTest, TestCommitBufferConditions) {
+ Sync();
+ }
+
++// This test verifies that submitting the buffer more than once results in
++// OnSubmission callback as Wayland compositor is not supposed to release the
++// buffer committed twice.
++TEST_P(WaylandBufferManagerTest, SubmitSameBufferMultipleTimes) {
++ constexpr uint32_t kBufferId1 = 1;
++ constexpr uint32_t kBufferId2 = 2;
++
++ const gfx::AcceleratedWidget widget = window_->GetWidget();
++ const gfx::Rect bounds = window_->GetBounds();
++
++ MockSurfaceGpu mock_surface_gpu(buffer_manager_gpu_.get(), widget);
++
++ auto* linux_dmabuf = server_.zwp_linux_dmabuf_v1();
++ EXPECT_CALL(*linux_dmabuf, CreateParams(_, _, _)).Times(2);
++ CreateDmabufBasedBufferAndSetTerminateExpecation(false /*fail*/, kBufferId1);
++ CreateDmabufBasedBufferAndSetTerminateExpecation(false /*fail*/, kBufferId2);
++
++ Sync();
++
++ ProcessCreatedBufferResourcesWithExpectation(2u /* expected size */,
++ false /* fail */);
++
++ // All the other expectations must come in order.
++ ::testing::InSequence sequence;
++ EXPECT_CALL(mock_surface_gpu,
++ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
++ .Times(1);
++ ASSERT_TRUE(!connection_->presentation());
++ EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
++
++ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds);
++
++ Sync();
++
++ testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
++
++ auto* mock_surface = server_.GetObject<wl::MockSurface>(widget);
++ mock_surface->SendFrameCallback();
++
++ Sync();
++
++ // Commit second buffer now.
++ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds);
++
++ Sync();
++
++ EXPECT_CALL(mock_surface_gpu,
++ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
++ .Times(1);
++ EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
++
++ mock_surface->ReleasePrevAttachedBuffer();
++ mock_surface->SendFrameCallback();
++
++ Sync();
++
++ testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
++
++ // Now, commit the buffer with the |kBufferId2| again and make sure the
++ // manager manually sends the submission callback as long as the compositor is
++ // not going to release a buffer as it was the same buffer submitted more than
++ // once.
++ EXPECT_CALL(mock_surface_gpu,
++ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
++ .Times(1);
++ EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
++
++ // Commit second buffer now.
++ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds);
++
++ Sync();
++
++ testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
++
++ DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
++ DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
++}
++
+ INSTANTIATE_TEST_SUITE_P(XdgVersionV5Test,
+ WaylandBufferManagerTest,
+ ::testing::Values(kXdgShellV5));
+--
+2.20.1
+