From 3b0757ee53bfe49357772114110c975f4be99681 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Tue, 2 Apr 2024 21:03:33 +0200 Subject: [PATCH] it: test explicit sync --- src/it/test_ifs.rs | 3 + src/it/test_ifs/test_compositor.rs | 7 + src/it/test_ifs/test_cursor_shape_manager.rs | 8 + src/it/test_ifs/test_data_device_manager.rs | 7 + .../test_ext_foreign_toplevel_list.rs | 9 + src/it/test_ifs/test_jay_compositor.rs | 8 + src/it/test_ifs/test_registry.rs | 249 ++++++------------ src/it/test_ifs/test_shm.rs | 9 + .../test_single_pixel_buffer_manager.rs | 7 + src/it/test_ifs/test_subcompositor.rs | 8 + src/it/test_ifs/test_syncobj_manager.rs | 81 ++++++ src/it/test_ifs/test_syncobj_surface.rs | 57 ++++ src/it/test_ifs/test_syncobj_timeline.rs | 34 +++ src/it/test_ifs/test_viewporter.rs | 7 + src/it/test_ifs/test_xdg_activation.rs | 8 + src/it/test_ifs/test_xdg_base.rs | 8 + src/it/test_transport.rs | 1 + src/it/tests.rs | 2 + src/it/tests/t0031_syncobj.rs | 65 +++++ src/utils/linkedlist.rs | 1 + src/video/drm/sync_obj.rs | 5 + src/video/drm/wait_for_sync_obj.rs | 1 + 22 files changed, 419 insertions(+), 166 deletions(-) create mode 100644 src/it/test_ifs/test_syncobj_manager.rs create mode 100644 src/it/test_ifs/test_syncobj_surface.rs create mode 100644 src/it/test_ifs/test_syncobj_timeline.rs create mode 100644 src/it/tests/t0031_syncobj.rs diff --git a/src/it/test_ifs.rs b/src/it/test_ifs.rs index 67c3f59c..6b4c9896 100644 --- a/src/it/test_ifs.rs +++ b/src/it/test_ifs.rs @@ -24,6 +24,9 @@ pub mod test_single_pixel_buffer_manager; pub mod test_subcompositor; pub mod test_subsurface; pub mod test_surface; +pub mod test_syncobj_manager; +pub mod test_syncobj_surface; +pub mod test_syncobj_timeline; pub mod test_viewport; pub mod test_viewporter; pub mod test_xdg_activation; diff --git a/src/it/test_ifs/test_compositor.rs b/src/it/test_ifs/test_compositor.rs index 1c9076b5..f8512a79 100644 --- a/src/it/test_ifs/test_compositor.rs +++ b/src/it/test_ifs/test_compositor.rs @@ -20,6 +20,13 @@ pub struct TestCompositor { } impl TestCompositor { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + } + } + pub async fn create_surface(&self) -> Result, TestError> { let id = self.tran.id(); self.tran.send(CreateSurface { diff --git a/src/it/test_ifs/test_cursor_shape_manager.rs b/src/it/test_ifs/test_cursor_shape_manager.rs index fb5f4dc3..5f61fae9 100644 --- a/src/it/test_ifs/test_cursor_shape_manager.rs +++ b/src/it/test_ifs/test_cursor_shape_manager.rs @@ -20,6 +20,14 @@ pub struct TestCursorShapeManager { } impl TestCursorShapeManager { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + destroyed: Cell::new(false), + } + } + #[allow(dead_code)] pub fn destroy(&self) -> TestResult { if !self.destroyed.replace(true) { diff --git a/src/it/test_ifs/test_data_device_manager.rs b/src/it/test_ifs/test_data_device_manager.rs index 285ecaff..c2c838ef 100644 --- a/src/it/test_ifs/test_data_device_manager.rs +++ b/src/it/test_ifs/test_data_device_manager.rs @@ -20,6 +20,13 @@ pub struct TestDataDeviceManager { } impl TestDataDeviceManager { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + } + } + pub fn create_data_source(&self) -> TestResult> { let data_source = Rc::new(TestDataSource { id: self.tran.id(), diff --git a/src/it/test_ifs/test_ext_foreign_toplevel_list.rs b/src/it/test_ifs/test_ext_foreign_toplevel_list.rs index cff7f979..ca0dc137 100644 --- a/src/it/test_ifs/test_ext_foreign_toplevel_list.rs +++ b/src/it/test_ifs/test_ext_foreign_toplevel_list.rs @@ -24,6 +24,15 @@ pub struct TestExtForeignToplevelList { } impl TestExtForeignToplevelList { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + destroyed: Cell::new(false), + toplevels: RefCell::new(vec![]), + } + } + #[allow(dead_code)] pub fn stop(&self) -> TestResult { self.tran.send(Stop { self_id: self.id })?; diff --git a/src/it/test_ifs/test_jay_compositor.rs b/src/it/test_ifs/test_jay_compositor.rs index aea1265f..bd0570db 100644 --- a/src/it/test_ifs/test_jay_compositor.rs +++ b/src/it/test_ifs/test_jay_compositor.rs @@ -25,6 +25,14 @@ pub struct TestJayCompositor { } impl TestJayCompositor { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + client_id: Cell::new(None), + } + } + pub async fn get_client_id(&self) -> Result { if self.client_id.is_none() { self.tran.send(GetClientId { self_id: self.id })?; diff --git a/src/it/test_ifs/test_registry.rs b/src/it/test_ifs/test_registry.rs index 890e1468..98332137 100644 --- a/src/it/test_ifs/test_registry.rs +++ b/src/it/test_ifs/test_registry.rs @@ -10,8 +10,9 @@ use { test_ext_foreign_toplevel_list::TestExtForeignToplevelList, test_jay_compositor::TestJayCompositor, test_shm::TestShm, test_single_pixel_buffer_manager::TestSinglePixelBufferManager, - test_subcompositor::TestSubcompositor, test_viewporter::TestViewporter, - test_xdg_activation::TestXdgActivation, test_xdg_base::TestXdgWmBase, + test_subcompositor::TestSubcompositor, test_syncobj_manager::TestSyncobjManager, + test_viewporter::TestViewporter, test_xdg_activation::TestXdgActivation, + test_xdg_base::TestXdgWmBase, }, test_object::TestObject, test_transport::TestTransport, @@ -20,10 +21,7 @@ use { utils::{buffd::MsgParser, clonecell::CloneCell, copyhashmap::CopyHashMap}, wire::{wl_registry::*, WlRegistryId, WlSeat}, }, - std::{ - cell::{Cell, RefCell}, - rc::Rc, - }, + std::rc::Rc, }; pub struct TestGlobal { @@ -44,6 +42,7 @@ pub struct TestRegistrySingletons { pub ext_foreign_toplevel_list_v1: u32, pub wl_data_device_manager: u32, pub wp_cursor_shape_manager_v1: u32, + pub wp_linux_drm_syncobj_manager_v1: u32, } pub struct TestRegistry { @@ -62,6 +61,7 @@ pub struct TestRegistry { pub foreign_toplevel_list: CloneCell>>, pub data_device_manager: CloneCell>>, pub cursor_shape_manager: CloneCell>>, + pub syncobj_manager: CloneCell>>, pub seats: CopyHashMap>, } @@ -73,6 +73,20 @@ macro_rules! singleton { }; } +macro_rules! create_singleton { + ($fn:ident, $field:ident, $name:ident, $ver:expr, $ty:ident) => { + pub async fn $fn(&self) -> Result, TestError> { + singleton!(self.$field); + let singletons = self.get_singletons().await?; + singleton!(self.$field); + let jc = Rc::new($ty::new(&self.tran)); + self.bind(&jc, singletons.$name, $ver)?; + self.$field.set(Some(jc.clone())); + Ok(jc) + } + }; +} + impl TestRegistry { pub async fn get_singletons(&self) -> Result, TestError> { singleton!(self.singletons); @@ -81,7 +95,7 @@ impl TestRegistry { macro_rules! singleton { ($($name:ident,)*) => {{ $( - let mut $name = 0; + let mut $name = u32::MAX; )* for global in self.globals.lock().values() { match global.interface.as_str() { @@ -93,12 +107,7 @@ impl TestRegistry { } Rc::new(TestRegistrySingletons { $( - $name: { - if $name == 0 { - bail!("Compositor did not send {} singleton", stringify!($name)); - } - $name - }, + $name, )* }) }} @@ -115,164 +124,72 @@ impl TestRegistry { ext_foreign_toplevel_list_v1, wl_data_device_manager, wp_cursor_shape_manager_v1, + wp_linux_drm_syncobj_manager_v1, }; self.singletons.set(Some(singletons.clone())); Ok(singletons) } - pub async fn get_jay_compositor(&self) -> Result, TestError> { - singleton!(self.jay_compositor); - let singletons = self.get_singletons().await?; - singleton!(self.jay_compositor); - let jc = Rc::new(TestJayCompositor { - id: self.tran.id(), - tran: self.tran.clone(), - client_id: Default::default(), - }); - self.bind(&jc, singletons.jay_compositor, 1)?; - self.jay_compositor.set(Some(jc.clone())); - Ok(jc) - } - - pub async fn get_compositor(&self) -> Result, TestError> { - singleton!(self.compositor); - let singletons = self.get_singletons().await?; - singleton!(self.compositor); - let jc = Rc::new(TestCompositor { - id: self.tran.id(), - tran: self.tran.clone(), - }); - self.bind(&jc, singletons.wl_compositor, 6)?; - self.compositor.set(Some(jc.clone())); - Ok(jc) - } - - pub async fn get_subcompositor(&self) -> Result, TestError> { - singleton!(self.subcompositor); - let singletons = self.get_singletons().await?; - singleton!(self.subcompositor); - let jc = Rc::new(TestSubcompositor { - id: self.tran.id(), - tran: self.tran.clone(), - destroyed: Cell::new(false), - }); - self.bind(&jc, singletons.wl_subcompositor, 1)?; - self.subcompositor.set(Some(jc.clone())); - Ok(jc) - } - - pub async fn get_shm(&self) -> Result, TestError> { - singleton!(self.shm); - let singletons = self.get_singletons().await?; - singleton!(self.shm); - let jc = Rc::new(TestShm { - id: self.tran.id(), - tran: self.tran.clone(), - formats: Default::default(), - formats_awaited: Cell::new(false), - }); - self.bind(&jc, singletons.wl_shm, 1)?; - self.shm.set(Some(jc.clone())); - Ok(jc) - } - - pub async fn get_spbm(&self) -> Result, TestError> { - singleton!(self.spbm); - let singletons = self.get_singletons().await?; - singleton!(self.spbm); - let jc = Rc::new(TestSinglePixelBufferManager { - id: self.tran.id(), - tran: self.tran.clone(), - }); - self.bind(&jc, singletons.wp_single_pixel_buffer_manager_v1, 1)?; - self.spbm.set(Some(jc.clone())); - Ok(jc) - } - - pub async fn get_viewporter(&self) -> Result, TestError> { - singleton!(self.viewporter); - let singletons = self.get_singletons().await?; - singleton!(self.viewporter); - let jc = Rc::new(TestViewporter { - id: self.tran.id(), - tran: self.tran.clone(), - }); - self.bind(&jc, singletons.wp_viewporter, 1)?; - self.viewporter.set(Some(jc.clone())); - Ok(jc) - } - - pub async fn get_activation(&self) -> Result, TestError> { - singleton!(self.activation); - let singletons = self.get_singletons().await?; - singleton!(self.activation); - let jc = Rc::new(TestXdgActivation { - id: self.tran.id(), - tran: self.tran.clone(), - destroyed: Cell::new(false), - }); - self.bind(&jc, singletons.xdg_activation_v1, 1)?; - self.activation.set(Some(jc.clone())); - Ok(jc) - } - - pub async fn get_xdg(&self) -> Result, TestError> { - singleton!(self.xdg); - let singletons = self.get_singletons().await?; - singleton!(self.xdg); - let jc = Rc::new(TestXdgWmBase { - id: self.tran.id(), - tran: self.tran.clone(), - destroyed: Cell::new(false), - }); - self.bind(&jc, singletons.xdg_wm_base, 6)?; - self.xdg.set(Some(jc.clone())); - Ok(jc) - } - - pub async fn get_foreign_toplevel_list( - &self, - ) -> Result, TestError> { - singleton!(self.foreign_toplevel_list); - let singletons = self.get_singletons().await?; - singleton!(self.foreign_toplevel_list); - let jc = Rc::new(TestExtForeignToplevelList { - id: self.tran.id(), - tran: self.tran.clone(), - destroyed: Cell::new(false), - toplevels: RefCell::new(vec![]), - }); - self.bind(&jc, singletons.ext_foreign_toplevel_list_v1, 1)?; - self.foreign_toplevel_list.set(Some(jc.clone())); - Ok(jc) - } - - pub async fn get_data_device_manager(&self) -> Result, TestError> { - singleton!(self.data_device_manager); - let singletons = self.get_singletons().await?; - singleton!(self.data_device_manager); - let jc = Rc::new(TestDataDeviceManager { - id: self.tran.id(), - tran: self.tran.clone(), - }); - self.bind(&jc, singletons.wl_data_device_manager, 3)?; - self.data_device_manager.set(Some(jc.clone())); - Ok(jc) - } - - pub async fn get_cursor_shape_manager(&self) -> Result, TestError> { - singleton!(self.cursor_shape_manager); - let singletons = self.get_singletons().await?; - singleton!(self.cursor_shape_manager); - let jc = Rc::new(TestCursorShapeManager { - id: self.tran.id(), - tran: self.tran.clone(), - destroyed: Cell::new(false), - }); - self.bind(&jc, singletons.wp_cursor_shape_manager_v1, 1)?; - self.cursor_shape_manager.set(Some(jc.clone())); - Ok(jc) - } + create_singleton!( + get_jay_compositor, + jay_compositor, + jay_compositor, + 1, + TestJayCompositor + ); + create_singleton!(get_compositor, compositor, wl_compositor, 6, TestCompositor); + create_singleton!( + get_subcompositor, + subcompositor, + wl_subcompositor, + 1, + TestSubcompositor + ); + create_singleton!(get_shm, shm, wl_shm, 1, TestShm); + create_singleton!( + get_spbm, + spbm, + wp_single_pixel_buffer_manager_v1, + 1, + TestSinglePixelBufferManager + ); + create_singleton!(get_viewporter, viewporter, wp_viewporter, 1, TestViewporter); + create_singleton!( + get_activation, + activation, + xdg_activation_v1, + 1, + TestXdgActivation + ); + create_singleton!(get_xdg, xdg, xdg_wm_base, 6, TestXdgWmBase); + create_singleton!( + get_foreign_toplevel_list, + foreign_toplevel_list, + ext_foreign_toplevel_list_v1, + 1, + TestExtForeignToplevelList + ); + create_singleton!( + get_data_device_manager, + data_device_manager, + wl_data_device_manager, + 3, + TestDataDeviceManager + ); + create_singleton!( + get_cursor_shape_manager, + cursor_shape_manager, + wp_cursor_shape_manager_v1, + 1, + TestCursorShapeManager + ); + create_singleton!( + get_syncobj_manager, + syncobj_manager, + wp_linux_drm_syncobj_manager_v1, + 1, + TestSyncobjManager + ); pub fn bind( &self, diff --git a/src/it/test_ifs/test_shm.rs b/src/it/test_ifs/test_shm.rs index b78eb862..37d494ab 100644 --- a/src/it/test_ifs/test_shm.rs +++ b/src/it/test_ifs/test_shm.rs @@ -23,6 +23,15 @@ pub struct TestShm { } impl TestShm { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + formats: Default::default(), + formats_awaited: Cell::new(false), + } + } + pub async fn formats(&self) -> &CopyHashMap { if !self.formats_awaited.replace(true) { self.tran.sync().await; diff --git a/src/it/test_ifs/test_single_pixel_buffer_manager.rs b/src/it/test_ifs/test_single_pixel_buffer_manager.rs index a5652419..cd49b701 100644 --- a/src/it/test_ifs/test_single_pixel_buffer_manager.rs +++ b/src/it/test_ifs/test_single_pixel_buffer_manager.rs @@ -16,6 +16,13 @@ pub struct TestSinglePixelBufferManager { } impl TestSinglePixelBufferManager { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + } + } + pub fn create_buffer(&self, color: Color) -> TestResult> { let obj = Rc::new(TestBuffer { id: self.tran.id(), diff --git a/src/it/test_ifs/test_subcompositor.rs b/src/it/test_ifs/test_subcompositor.rs index c3d9cf80..4b8be7aa 100644 --- a/src/it/test_ifs/test_subcompositor.rs +++ b/src/it/test_ifs/test_subcompositor.rs @@ -16,6 +16,14 @@ pub struct TestSubcompositor { } impl TestSubcompositor { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + destroyed: Cell::new(false), + } + } + pub fn destroy(&self) -> Result<(), TestError> { if !self.destroyed.replace(true) { self.tran.send(Destroy { self_id: self.id })?; diff --git a/src/it/test_ifs/test_syncobj_manager.rs b/src/it/test_ifs/test_syncobj_manager.rs new file mode 100644 index 00000000..315ab421 --- /dev/null +++ b/src/it/test_ifs/test_syncobj_manager.rs @@ -0,0 +1,81 @@ +use { + crate::{ + it::{ + test_error::TestResult, + test_ifs::{ + test_surface::TestSurface, test_syncobj_surface::TestSyncobjSurface, + test_syncobj_timeline::TestSyncobjTimeline, + }, + test_object::TestObject, + test_transport::TestTransport, + }, + video::drm::sync_obj::SyncObj, + wire::{wp_linux_drm_syncobj_manager_v1::*, WpLinuxDrmSyncobjManagerV1Id}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestSyncobjManager { + pub id: WpLinuxDrmSyncobjManagerV1Id, + pub tran: Rc, + pub destroyed: Cell, +} + +impl TestSyncobjManager { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + destroyed: Cell::new(false), + } + } + + pub fn destroy(&self) -> TestResult { + if !self.destroyed.replace(true) { + self.tran.send(Destroy { self_id: self.id })?; + } + Ok(()) + } + + pub fn get_surface(&self, surface: &TestSurface) -> TestResult> { + let obj = Rc::new(TestSyncobjSurface { + id: self.tran.id(), + tran: self.tran.clone(), + destroyed: Cell::new(false), + }); + self.tran.add_obj(obj.clone())?; + self.tran.send(GetSurface { + self_id: self.id, + id: obj.id, + surface: surface.id, + })?; + Ok(obj) + } + + pub fn import_timeline(&self, syncobj: &SyncObj) -> TestResult> { + let obj = Rc::new(TestSyncobjTimeline { + id: self.tran.id(), + tran: self.tran.clone(), + destroyed: Cell::new(false), + }); + self.tran.add_obj(obj.clone())?; + self.tran.send(ImportTimeline { + self_id: self.id, + id: obj.id, + fd: syncobj.fd().clone(), + })?; + Ok(obj) + } +} + +impl Drop for TestSyncobjManager { + fn drop(&mut self) { + let _ = self.destroy(); + } +} + +test_object! { + TestSyncobjManager, WpLinuxDrmSyncobjManagerV1; +} + +impl TestObject for TestSyncobjManager {} diff --git a/src/it/test_ifs/test_syncobj_surface.rs b/src/it/test_ifs/test_syncobj_surface.rs new file mode 100644 index 00000000..8dfd913c --- /dev/null +++ b/src/it/test_ifs/test_syncobj_surface.rs @@ -0,0 +1,57 @@ +use { + crate::{ + it::{ + test_error::TestResult, test_ifs::test_syncobj_timeline::TestSyncobjTimeline, + test_object::TestObject, test_transport::TestTransport, + }, + wire::{wp_linux_drm_syncobj_surface_v1::*, WpLinuxDrmSyncobjSurfaceV1Id}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestSyncobjSurface { + pub id: WpLinuxDrmSyncobjSurfaceV1Id, + pub tran: Rc, + pub destroyed: Cell, +} + +impl TestSyncobjSurface { + pub fn destroy(&self) -> TestResult { + if !self.destroyed.replace(true) { + self.tran.send(Destroy { self_id: self.id })?; + } + Ok(()) + } + + pub fn set_acquire_point(&self, tl: &TestSyncobjTimeline, point: u64) -> TestResult { + self.tran.send(SetAcquirePoint { + self_id: self.id, + timeline: tl.id, + point_hi: (point >> 32) as _, + point_lo: point as _, + })?; + Ok(()) + } + + pub fn set_release_point(&self, tl: &TestSyncobjTimeline, point: u64) -> TestResult { + self.tran.send(SetReleasePoint { + self_id: self.id, + timeline: tl.id, + point_hi: (point >> 32) as _, + point_lo: point as _, + })?; + Ok(()) + } +} + +impl Drop for TestSyncobjSurface { + fn drop(&mut self) { + let _ = self.destroy(); + } +} + +test_object! { + TestSyncobjSurface, WpLinuxDrmSyncobjSurfaceV1; +} + +impl TestObject for TestSyncobjSurface {} diff --git a/src/it/test_ifs/test_syncobj_timeline.rs b/src/it/test_ifs/test_syncobj_timeline.rs new file mode 100644 index 00000000..929bee26 --- /dev/null +++ b/src/it/test_ifs/test_syncobj_timeline.rs @@ -0,0 +1,34 @@ +use { + crate::{ + it::{test_error::TestError, test_object::TestObject, test_transport::TestTransport}, + wire::{wp_linux_drm_syncobj_timeline_v1::*, WpLinuxDrmSyncobjTimelineV1Id}, + }, + std::{cell::Cell, rc::Rc}, +}; + +pub struct TestSyncobjTimeline { + pub id: WpLinuxDrmSyncobjTimelineV1Id, + pub tran: Rc, + pub destroyed: Cell, +} + +impl TestSyncobjTimeline { + pub fn destroy(&self) -> Result<(), TestError> { + if !self.destroyed.replace(true) { + self.tran.send(Destroy { self_id: self.id })?; + } + Ok(()) + } +} + +impl Drop for TestSyncobjTimeline { + fn drop(&mut self) { + let _ = self.destroy(); + } +} + +test_object! { + TestSyncobjTimeline, WpLinuxDrmSyncobjTimelineV1; +} + +impl TestObject for TestSyncobjTimeline {} diff --git a/src/it/test_ifs/test_viewporter.rs b/src/it/test_ifs/test_viewporter.rs index d3023b9e..61420efa 100644 --- a/src/it/test_ifs/test_viewporter.rs +++ b/src/it/test_ifs/test_viewporter.rs @@ -17,6 +17,13 @@ pub struct TestViewporter { } impl TestViewporter { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + } + } + pub fn get_viewport(&self, surface: &TestSurface) -> TestResult> { let obj = Rc::new(TestViewport { id: self.tran.id(), diff --git a/src/it/test_ifs/test_xdg_activation.rs b/src/it/test_ifs/test_xdg_activation.rs index 6cc6aa86..dd55e4f8 100644 --- a/src/it/test_ifs/test_xdg_activation.rs +++ b/src/it/test_ifs/test_xdg_activation.rs @@ -20,6 +20,14 @@ pub struct TestXdgActivation { } impl TestXdgActivation { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + destroyed: Cell::new(false), + } + } + pub fn destroy(&self) -> Result<(), TestError> { if !self.destroyed.replace(true) { self.tran.send(Destroy { self_id: self.id })?; diff --git a/src/it/test_ifs/test_xdg_base.rs b/src/it/test_ifs/test_xdg_base.rs index 0ab5324c..5d50c6dc 100644 --- a/src/it/test_ifs/test_xdg_base.rs +++ b/src/it/test_ifs/test_xdg_base.rs @@ -17,6 +17,14 @@ pub struct TestXdgWmBase { } impl TestXdgWmBase { + pub fn new(tran: &Rc) -> Self { + Self { + id: tran.id(), + tran: tran.clone(), + destroyed: Cell::new(false), + } + } + pub fn destroy(&self) -> Result<(), TestError> { if !self.destroyed.replace(true) { self.tran.send(Destroy { self_id: self.id })?; diff --git a/src/it/test_transport.rs b/src/it/test_transport.rs index afeb1a7d..630e8805 100644 --- a/src/it/test_transport.rs +++ b/src/it/test_transport.rs @@ -63,6 +63,7 @@ impl TestTransport { foreign_toplevel_list: Default::default(), data_device_manager: Default::default(), cursor_shape_manager: Default::default(), + syncobj_manager: Default::default(), seats: Default::default(), }); self.send(wl_display::GetRegistry { diff --git a/src/it/tests.rs b/src/it/tests.rs index 8f5e10f5..6dd4aec4 100644 --- a/src/it/tests.rs +++ b/src/it/tests.rs @@ -61,6 +61,7 @@ mod t0027_input_region; mod t0028_top_level_restacking; mod t0029_double_click_float; mod t0030_cursor_shape; +mod t0031_syncobj; pub trait TestCase: Sync { fn name(&self) -> &'static str; @@ -110,5 +111,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> { t0028_top_level_restacking, t0029_double_click_float, t0030_cursor_shape, + t0031_syncobj, } } diff --git a/src/it/tests/t0031_syncobj.rs b/src/it/tests/t0031_syncobj.rs new file mode 100644 index 00000000..a0889ca5 --- /dev/null +++ b/src/it/tests/t0031_syncobj.rs @@ -0,0 +1,65 @@ +use { + crate::{ + it::{test_error::TestResult, testrun::TestRun}, + theme::Color, + utils::errorfmt::ErrorFmt, + video::drm::{sync_obj::SyncObjPoint, wait_for_sync_obj::SyncObjWaiter, DrmError}, + }, + std::{cell::Cell, rc::Rc}, +}; + +testcase!(); + +async fn test(run: Rc) -> TestResult { + let _ds = run.create_default_setup().await?; + + struct Waiter(Cell); + impl SyncObjWaiter for Waiter { + fn done(self: Rc, result: Result<(), DrmError>) { + result.unwrap(); + self.0.set(true); + } + } + let waiter = Rc::new(Waiter(Cell::new(false))); + + let eng = run.state.render_ctx.get().unwrap(); + let syncobj = match eng.sync_obj_ctx().create_sync_obj() { + Ok(s) => Rc::new(s), + Err(e) => { + log::warn!("Cannot test explicit sync on this system: {}", ErrorFmt(e)); + return Ok(()); + } + }; + let _wait_handle = + run.state + .wait_for_sync_obj + .wait(&syncobj, SyncObjPoint(2), true, waiter.clone())?; + + let client = run.create_client().await?; + + let buf1 = client.spbm.create_buffer(Color::SOLID_BLACK)?; + let buf2 = client.spbm.create_buffer(Color::SOLID_BLACK)?; + + let syncobj_manager = client.registry.get_syncobj_manager().await?; + let timeline = syncobj_manager.import_timeline(&syncobj)?; + + let win = client.create_window().await?; + let sync = syncobj_manager.get_surface(&win.surface)?; + win.surface.attach(buf1.id)?; + sync.set_acquire_point(&timeline, 1)?; + sync.set_release_point(&timeline, 2)?; + win.surface.commit()?; + sync.destroy()?; + win.surface.attach(buf2.id)?; + win.surface.commit()?; + + client.sync().await; + tassert_eq!(waiter.0.get(), false); + + eng.sync_obj_ctx().signal(&syncobj, SyncObjPoint(1))?; + + client.sync().await; + tassert_eq!(waiter.0.get(), true); + + Ok(()) +} diff --git a/src/utils/linkedlist.rs b/src/utils/linkedlist.rs index ab44af81..c3866757 100644 --- a/src/utils/linkedlist.rs +++ b/src/utils/linkedlist.rs @@ -194,6 +194,7 @@ impl Drop for RevLinkedListIter { } #[repr(transparent)] +#[must_use] pub struct LinkedNode { data: NonNull>, } diff --git a/src/video/drm/sync_obj.rs b/src/video/drm/sync_obj.rs index 5f5a7d0d..3eb8e355 100644 --- a/src/video/drm/sync_obj.rs +++ b/src/video/drm/sync_obj.rs @@ -52,6 +52,11 @@ impl SyncObj { importers: Default::default(), } } + + #[cfg_attr(not(feature = "it"), allow(dead_code))] + pub fn fd(&self) -> &Rc { + &self.fd + } } impl Drop for SyncObj { diff --git a/src/video/drm/wait_for_sync_obj.rs b/src/video/drm/wait_for_sync_obj.rs index b4d10bed..a01788f2 100644 --- a/src/video/drm/wait_for_sync_obj.rs +++ b/src/video/drm/wait_for_sync_obj.rs @@ -27,6 +27,7 @@ pub trait SyncObjWaiter { #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] struct JobId(u64); +#[must_use] pub struct WaitForSyncObjHandle { inner: Rc, id: JobId,