Skip to content

Commit 1bfd822

Browse files
msisovChromium LUCI CQ
authored andcommitted
ozone/wayland: do not reset configure state of surface on gpu crash
When gpu crashes and the viz is destroyed, the channel between the host and the viz destroys. This results in calling ClearState and then ResetSurfaceContents, which resets the configure state of the surface, while it has not been unmapped. Given that the state has been reset, we cannot submit buffers anymore (even though the channel is established again, new buffers are created and a new frame has been sent). Thus, check the current configuration state of the surface when ResetSurfaceContents is called. PS This state helps us to identify when the surface has been mapped and xdg_surface.ack_configure has been called. Once the state is configured == true, we can submit buffers. Otherwise, it's illegal in Wayland to attach buffers until a surface has been configured. Bug: 1245820 Change-Id: I3fdf9aabaf9769dc28a6d2380d93229bf3931868 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3149776 Commit-Queue: Maksim Sisov <[email protected]> Reviewed-by: Robert Kroeger <[email protected]> Cr-Commit-Position: refs/heads/main@{#919823}
1 parent 28b58f5 commit 1bfd822

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,14 @@ class WaylandBufferManagerHost::Surface {
244244
}
245245
MaybeProcessSubmittedBuffers();
246246

247-
// ResetSurfaceContents happens upon WaylandWindow::Hide call, which
247+
// 1) ResetSurfaceContents happens upon WaylandWindow::Hide call, which
248248
// destroys xdg_surface, xdg_popup, etc. They are going to be reinitialized
249249
// once WaylandWindow::Show is called. Thus, they will have to be configured
250250
// once again before buffers can be attached.
251-
configured_ = false;
251+
// 2) ResetSurfaceContents can also be called if gpu crashed and a channel
252+
// has been destroyed. Thus, the surface's configure state has to be
253+
// verified at this point.
254+
configured_ = wayland_surface_->root_window()->IsSurfaceConfigured();
252255

253256
connection_->ScheduleFlush();
254257
}

ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,87 @@ TEST_P(WaylandBufferManagerTest, FencedRelease) {
18081808
DestroyBufferAndSetTerminateExpectation(widget, kBufferId3, false /*fail*/);
18091809
}
18101810

1811+
// Tests that destroying a channel doesn't result in resetting surface state
1812+
// and buffers can be attached after the channel has been reinitialized.
1813+
TEST_P(WaylandBufferManagerTest,
1814+
CanSubmitBufferAfterChannelDestroyedAndInitialized) {
1815+
constexpr uint32_t kBufferId1 = 1;
1816+
1817+
const gfx::AcceleratedWidget widget = window_->GetWidget();
1818+
const gfx::Rect bounds = window_->GetBounds();
1819+
1820+
auto* mock_surface = server_.GetObject<wl::MockSurface>(
1821+
window_->root_surface()->GetSurfaceId());
1822+
1823+
EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(1);
1824+
EXPECT_CALL(*mock_surface, Frame(_)).Times(1);
1825+
EXPECT_CALL(*mock_surface, Commit()).Times(1);
1826+
1827+
auto mock_surface_gpu =
1828+
std::make_unique<MockSurfaceGpu>(buffer_manager_gpu_.get(), widget);
1829+
1830+
auto* linux_dmabuf = server_.zwp_linux_dmabuf_v1();
1831+
EXPECT_CALL(*linux_dmabuf, CreateParams(_, _, _)).Times(1);
1832+
CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/, kBufferId1);
1833+
1834+
Sync();
1835+
1836+
ProcessCreatedBufferResourcesWithExpectation(1u /* expected size */,
1837+
false /* fail */);
1838+
1839+
EXPECT_CALL(*mock_surface_gpu.get(),
1840+
OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
1841+
.Times(1);
1842+
EXPECT_CALL(*mock_surface_gpu.get(), OnPresentation(kBufferId1, _)).Times(1);
1843+
1844+
buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
1845+
bounds);
1846+
Sync();
1847+
1848+
// Null buffer shall be attached when channel is destroyed.
1849+
EXPECT_CALL(*mock_surface, Attach(nullptr, _, _)).Times(1);
1850+
EXPECT_CALL(*mock_surface, Commit()).Times(1);
1851+
1852+
mock_surface->SendFrameCallback();
1853+
1854+
// After the channel has been destroyed and surface state has been reset, the
1855+
// interface should bind again and it still should be possible to attach
1856+
// buffers as WaylandBufferManagerHost::Surface::ResetSurfaceContents mustn't
1857+
// reset the state of |configured|.
1858+
manager_host_->OnChannelDestroyed();
1859+
manager_host_ = connection_->buffer_manager_host();
1860+
1861+
Sync();
1862+
1863+
auto interface_ptr = manager_host_->BindInterface();
1864+
buffer_manager_gpu_->Initialize(std::move(interface_ptr), {}, false, true,
1865+
false);
1866+
1867+
EXPECT_CALL(*linux_dmabuf, CreateParams(_, _, _)).Times(1);
1868+
CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/, kBufferId1);
1869+
1870+
Sync();
1871+
1872+
ProcessCreatedBufferResourcesWithExpectation(1u /* expected size */,
1873+
false /* fail */);
1874+
1875+
// The buffer must be attached.
1876+
EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(1);
1877+
EXPECT_CALL(*mock_surface, Frame(_)).Times(1);
1878+
EXPECT_CALL(*mock_surface, Commit()).Times(1);
1879+
1880+
EXPECT_CALL(*mock_surface_gpu.get(),
1881+
OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
1882+
.Times(1);
1883+
EXPECT_CALL(*mock_surface_gpu.get(), OnPresentation(kBufferId1, _)).Times(1);
1884+
1885+
buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
1886+
bounds);
1887+
Sync();
1888+
1889+
DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
1890+
}
1891+
18111892
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
18121893
WaylandBufferManagerTest,
18131894
Values(wl::ServerConfig{

0 commit comments

Comments
 (0)