it: test explicit sync
This commit is contained in:
parent
6448a14fb1
commit
3b0757ee53
22 changed files with 419 additions and 166 deletions
|
|
@ -24,6 +24,9 @@ pub mod test_single_pixel_buffer_manager;
|
||||||
pub mod test_subcompositor;
|
pub mod test_subcompositor;
|
||||||
pub mod test_subsurface;
|
pub mod test_subsurface;
|
||||||
pub mod test_surface;
|
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_viewport;
|
||||||
pub mod test_viewporter;
|
pub mod test_viewporter;
|
||||||
pub mod test_xdg_activation;
|
pub mod test_xdg_activation;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,13 @@ pub struct TestCompositor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestCompositor {
|
impl TestCompositor {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn create_surface(&self) -> Result<Rc<TestSurface>, TestError> {
|
pub async fn create_surface(&self) -> Result<Rc<TestSurface>, TestError> {
|
||||||
let id = self.tran.id();
|
let id = self.tran.id();
|
||||||
self.tran.send(CreateSurface {
|
self.tran.send(CreateSurface {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,14 @@ pub struct TestCursorShapeManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestCursorShapeManager {
|
impl TestCursorShapeManager {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn destroy(&self) -> TestResult {
|
pub fn destroy(&self) -> TestResult {
|
||||||
if !self.destroyed.replace(true) {
|
if !self.destroyed.replace(true) {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,13 @@ pub struct TestDataDeviceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestDataDeviceManager {
|
impl TestDataDeviceManager {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_data_source(&self) -> TestResult<Rc<TestDataSource>> {
|
pub fn create_data_source(&self) -> TestResult<Rc<TestDataSource>> {
|
||||||
let data_source = Rc::new(TestDataSource {
|
let data_source = Rc::new(TestDataSource {
|
||||||
id: self.tran.id(),
|
id: self.tran.id(),
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,15 @@ pub struct TestExtForeignToplevelList {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestExtForeignToplevelList {
|
impl TestExtForeignToplevelList {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
toplevels: RefCell::new(vec![]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn stop(&self) -> TestResult {
|
pub fn stop(&self) -> TestResult {
|
||||||
self.tran.send(Stop { self_id: self.id })?;
|
self.tran.send(Stop { self_id: self.id })?;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,14 @@ pub struct TestJayCompositor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestJayCompositor {
|
impl TestJayCompositor {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
client_id: Cell::new(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_client_id(&self) -> Result<ClientId, TestError> {
|
pub async fn get_client_id(&self) -> Result<ClientId, TestError> {
|
||||||
if self.client_id.is_none() {
|
if self.client_id.is_none() {
|
||||||
self.tran.send(GetClientId { self_id: self.id })?;
|
self.tran.send(GetClientId { self_id: self.id })?;
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ use {
|
||||||
test_ext_foreign_toplevel_list::TestExtForeignToplevelList,
|
test_ext_foreign_toplevel_list::TestExtForeignToplevelList,
|
||||||
test_jay_compositor::TestJayCompositor, test_shm::TestShm,
|
test_jay_compositor::TestJayCompositor, test_shm::TestShm,
|
||||||
test_single_pixel_buffer_manager::TestSinglePixelBufferManager,
|
test_single_pixel_buffer_manager::TestSinglePixelBufferManager,
|
||||||
test_subcompositor::TestSubcompositor, test_viewporter::TestViewporter,
|
test_subcompositor::TestSubcompositor, test_syncobj_manager::TestSyncobjManager,
|
||||||
test_xdg_activation::TestXdgActivation, test_xdg_base::TestXdgWmBase,
|
test_viewporter::TestViewporter, test_xdg_activation::TestXdgActivation,
|
||||||
|
test_xdg_base::TestXdgWmBase,
|
||||||
},
|
},
|
||||||
test_object::TestObject,
|
test_object::TestObject,
|
||||||
test_transport::TestTransport,
|
test_transport::TestTransport,
|
||||||
|
|
@ -20,10 +21,7 @@ use {
|
||||||
utils::{buffd::MsgParser, clonecell::CloneCell, copyhashmap::CopyHashMap},
|
utils::{buffd::MsgParser, clonecell::CloneCell, copyhashmap::CopyHashMap},
|
||||||
wire::{wl_registry::*, WlRegistryId, WlSeat},
|
wire::{wl_registry::*, WlRegistryId, WlSeat},
|
||||||
},
|
},
|
||||||
std::{
|
std::rc::Rc,
|
||||||
cell::{Cell, RefCell},
|
|
||||||
rc::Rc,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct TestGlobal {
|
pub struct TestGlobal {
|
||||||
|
|
@ -44,6 +42,7 @@ pub struct TestRegistrySingletons {
|
||||||
pub ext_foreign_toplevel_list_v1: u32,
|
pub ext_foreign_toplevel_list_v1: u32,
|
||||||
pub wl_data_device_manager: u32,
|
pub wl_data_device_manager: u32,
|
||||||
pub wp_cursor_shape_manager_v1: u32,
|
pub wp_cursor_shape_manager_v1: u32,
|
||||||
|
pub wp_linux_drm_syncobj_manager_v1: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestRegistry {
|
pub struct TestRegistry {
|
||||||
|
|
@ -62,6 +61,7 @@ pub struct TestRegistry {
|
||||||
pub foreign_toplevel_list: CloneCell<Option<Rc<TestExtForeignToplevelList>>>,
|
pub foreign_toplevel_list: CloneCell<Option<Rc<TestExtForeignToplevelList>>>,
|
||||||
pub data_device_manager: CloneCell<Option<Rc<TestDataDeviceManager>>>,
|
pub data_device_manager: CloneCell<Option<Rc<TestDataDeviceManager>>>,
|
||||||
pub cursor_shape_manager: CloneCell<Option<Rc<TestCursorShapeManager>>>,
|
pub cursor_shape_manager: CloneCell<Option<Rc<TestCursorShapeManager>>>,
|
||||||
|
pub syncobj_manager: CloneCell<Option<Rc<TestSyncobjManager>>>,
|
||||||
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
|
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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<Rc<$ty>, 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 {
|
impl TestRegistry {
|
||||||
pub async fn get_singletons(&self) -> Result<Rc<TestRegistrySingletons>, TestError> {
|
pub async fn get_singletons(&self) -> Result<Rc<TestRegistrySingletons>, TestError> {
|
||||||
singleton!(self.singletons);
|
singleton!(self.singletons);
|
||||||
|
|
@ -81,7 +95,7 @@ impl TestRegistry {
|
||||||
macro_rules! singleton {
|
macro_rules! singleton {
|
||||||
($($name:ident,)*) => {{
|
($($name:ident,)*) => {{
|
||||||
$(
|
$(
|
||||||
let mut $name = 0;
|
let mut $name = u32::MAX;
|
||||||
)*
|
)*
|
||||||
for global in self.globals.lock().values() {
|
for global in self.globals.lock().values() {
|
||||||
match global.interface.as_str() {
|
match global.interface.as_str() {
|
||||||
|
|
@ -93,12 +107,7 @@ impl TestRegistry {
|
||||||
}
|
}
|
||||||
Rc::new(TestRegistrySingletons {
|
Rc::new(TestRegistrySingletons {
|
||||||
$(
|
$(
|
||||||
$name: {
|
$name,
|
||||||
if $name == 0 {
|
|
||||||
bail!("Compositor did not send {} singleton", stringify!($name));
|
|
||||||
}
|
|
||||||
$name
|
|
||||||
},
|
|
||||||
)*
|
)*
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
|
|
@ -115,164 +124,72 @@ impl TestRegistry {
|
||||||
ext_foreign_toplevel_list_v1,
|
ext_foreign_toplevel_list_v1,
|
||||||
wl_data_device_manager,
|
wl_data_device_manager,
|
||||||
wp_cursor_shape_manager_v1,
|
wp_cursor_shape_manager_v1,
|
||||||
|
wp_linux_drm_syncobj_manager_v1,
|
||||||
};
|
};
|
||||||
self.singletons.set(Some(singletons.clone()));
|
self.singletons.set(Some(singletons.clone()));
|
||||||
Ok(singletons)
|
Ok(singletons)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_jay_compositor(&self) -> Result<Rc<TestJayCompositor>, TestError> {
|
create_singleton!(
|
||||||
singleton!(self.jay_compositor);
|
get_jay_compositor,
|
||||||
let singletons = self.get_singletons().await?;
|
jay_compositor,
|
||||||
singleton!(self.jay_compositor);
|
jay_compositor,
|
||||||
let jc = Rc::new(TestJayCompositor {
|
1,
|
||||||
id: self.tran.id(),
|
TestJayCompositor
|
||||||
tran: self.tran.clone(),
|
);
|
||||||
client_id: Default::default(),
|
create_singleton!(get_compositor, compositor, wl_compositor, 6, TestCompositor);
|
||||||
});
|
create_singleton!(
|
||||||
self.bind(&jc, singletons.jay_compositor, 1)?;
|
get_subcompositor,
|
||||||
self.jay_compositor.set(Some(jc.clone()));
|
subcompositor,
|
||||||
Ok(jc)
|
wl_subcompositor,
|
||||||
}
|
1,
|
||||||
|
TestSubcompositor
|
||||||
pub async fn get_compositor(&self) -> Result<Rc<TestCompositor>, TestError> {
|
);
|
||||||
singleton!(self.compositor);
|
create_singleton!(get_shm, shm, wl_shm, 1, TestShm);
|
||||||
let singletons = self.get_singletons().await?;
|
create_singleton!(
|
||||||
singleton!(self.compositor);
|
get_spbm,
|
||||||
let jc = Rc::new(TestCompositor {
|
spbm,
|
||||||
id: self.tran.id(),
|
wp_single_pixel_buffer_manager_v1,
|
||||||
tran: self.tran.clone(),
|
1,
|
||||||
});
|
TestSinglePixelBufferManager
|
||||||
self.bind(&jc, singletons.wl_compositor, 6)?;
|
);
|
||||||
self.compositor.set(Some(jc.clone()));
|
create_singleton!(get_viewporter, viewporter, wp_viewporter, 1, TestViewporter);
|
||||||
Ok(jc)
|
create_singleton!(
|
||||||
}
|
get_activation,
|
||||||
|
activation,
|
||||||
pub async fn get_subcompositor(&self) -> Result<Rc<TestSubcompositor>, TestError> {
|
xdg_activation_v1,
|
||||||
singleton!(self.subcompositor);
|
1,
|
||||||
let singletons = self.get_singletons().await?;
|
TestXdgActivation
|
||||||
singleton!(self.subcompositor);
|
);
|
||||||
let jc = Rc::new(TestSubcompositor {
|
create_singleton!(get_xdg, xdg, xdg_wm_base, 6, TestXdgWmBase);
|
||||||
id: self.tran.id(),
|
create_singleton!(
|
||||||
tran: self.tran.clone(),
|
get_foreign_toplevel_list,
|
||||||
destroyed: Cell::new(false),
|
foreign_toplevel_list,
|
||||||
});
|
ext_foreign_toplevel_list_v1,
|
||||||
self.bind(&jc, singletons.wl_subcompositor, 1)?;
|
1,
|
||||||
self.subcompositor.set(Some(jc.clone()));
|
TestExtForeignToplevelList
|
||||||
Ok(jc)
|
);
|
||||||
}
|
create_singleton!(
|
||||||
|
get_data_device_manager,
|
||||||
pub async fn get_shm(&self) -> Result<Rc<TestShm>, TestError> {
|
data_device_manager,
|
||||||
singleton!(self.shm);
|
wl_data_device_manager,
|
||||||
let singletons = self.get_singletons().await?;
|
3,
|
||||||
singleton!(self.shm);
|
TestDataDeviceManager
|
||||||
let jc = Rc::new(TestShm {
|
);
|
||||||
id: self.tran.id(),
|
create_singleton!(
|
||||||
tran: self.tran.clone(),
|
get_cursor_shape_manager,
|
||||||
formats: Default::default(),
|
cursor_shape_manager,
|
||||||
formats_awaited: Cell::new(false),
|
wp_cursor_shape_manager_v1,
|
||||||
});
|
1,
|
||||||
self.bind(&jc, singletons.wl_shm, 1)?;
|
TestCursorShapeManager
|
||||||
self.shm.set(Some(jc.clone()));
|
);
|
||||||
Ok(jc)
|
create_singleton!(
|
||||||
}
|
get_syncobj_manager,
|
||||||
|
syncobj_manager,
|
||||||
pub async fn get_spbm(&self) -> Result<Rc<TestSinglePixelBufferManager>, TestError> {
|
wp_linux_drm_syncobj_manager_v1,
|
||||||
singleton!(self.spbm);
|
1,
|
||||||
let singletons = self.get_singletons().await?;
|
TestSyncobjManager
|
||||||
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<Rc<TestViewporter>, 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<Rc<TestXdgActivation>, 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<Rc<TestXdgWmBase>, 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<Rc<TestExtForeignToplevelList>, 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<Rc<TestDataDeviceManager>, 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<Rc<TestCursorShapeManager>, 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bind<O: TestObject>(
|
pub fn bind<O: TestObject>(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,15 @@ pub struct TestShm {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestShm {
|
impl TestShm {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
formats: Default::default(),
|
||||||
|
formats_awaited: Cell::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn formats(&self) -> &CopyHashMap<u32, ()> {
|
pub async fn formats(&self) -> &CopyHashMap<u32, ()> {
|
||||||
if !self.formats_awaited.replace(true) {
|
if !self.formats_awaited.replace(true) {
|
||||||
self.tran.sync().await;
|
self.tran.sync().await;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,13 @@ pub struct TestSinglePixelBufferManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestSinglePixelBufferManager {
|
impl TestSinglePixelBufferManager {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_buffer(&self, color: Color) -> TestResult<Rc<TestBuffer>> {
|
pub fn create_buffer(&self, color: Color) -> TestResult<Rc<TestBuffer>> {
|
||||||
let obj = Rc::new(TestBuffer {
|
let obj = Rc::new(TestBuffer {
|
||||||
id: self.tran.id(),
|
id: self.tran.id(),
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,14 @@ pub struct TestSubcompositor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestSubcompositor {
|
impl TestSubcompositor {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn destroy(&self) -> Result<(), TestError> {
|
pub fn destroy(&self) -> Result<(), TestError> {
|
||||||
if !self.destroyed.replace(true) {
|
if !self.destroyed.replace(true) {
|
||||||
self.tran.send(Destroy { self_id: self.id })?;
|
self.tran.send(Destroy { self_id: self.id })?;
|
||||||
|
|
|
||||||
81
src/it/test_ifs/test_syncobj_manager.rs
Normal file
81
src/it/test_ifs/test_syncobj_manager.rs
Normal file
|
|
@ -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<TestTransport>,
|
||||||
|
pub destroyed: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestSyncobjManager {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> 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<Rc<TestSyncobjSurface>> {
|
||||||
|
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<Rc<TestSyncobjTimeline>> {
|
||||||
|
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 {}
|
||||||
57
src/it/test_ifs/test_syncobj_surface.rs
Normal file
57
src/it/test_ifs/test_syncobj_surface.rs
Normal file
|
|
@ -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<TestTransport>,
|
||||||
|
pub destroyed: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {}
|
||||||
34
src/it/test_ifs/test_syncobj_timeline.rs
Normal file
34
src/it/test_ifs/test_syncobj_timeline.rs
Normal file
|
|
@ -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<TestTransport>,
|
||||||
|
pub destroyed: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {}
|
||||||
|
|
@ -17,6 +17,13 @@ pub struct TestViewporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestViewporter {
|
impl TestViewporter {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_viewport(&self, surface: &TestSurface) -> TestResult<Rc<TestViewport>> {
|
pub fn get_viewport(&self, surface: &TestSurface) -> TestResult<Rc<TestViewport>> {
|
||||||
let obj = Rc::new(TestViewport {
|
let obj = Rc::new(TestViewport {
|
||||||
id: self.tran.id(),
|
id: self.tran.id(),
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,14 @@ pub struct TestXdgActivation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestXdgActivation {
|
impl TestXdgActivation {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn destroy(&self) -> Result<(), TestError> {
|
pub fn destroy(&self) -> Result<(), TestError> {
|
||||||
if !self.destroyed.replace(true) {
|
if !self.destroyed.replace(true) {
|
||||||
self.tran.send(Destroy { self_id: self.id })?;
|
self.tran.send(Destroy { self_id: self.id })?;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,14 @@ pub struct TestXdgWmBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestXdgWmBase {
|
impl TestXdgWmBase {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn destroy(&self) -> Result<(), TestError> {
|
pub fn destroy(&self) -> Result<(), TestError> {
|
||||||
if !self.destroyed.replace(true) {
|
if !self.destroyed.replace(true) {
|
||||||
self.tran.send(Destroy { self_id: self.id })?;
|
self.tran.send(Destroy { self_id: self.id })?;
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ impl TestTransport {
|
||||||
foreign_toplevel_list: Default::default(),
|
foreign_toplevel_list: Default::default(),
|
||||||
data_device_manager: Default::default(),
|
data_device_manager: Default::default(),
|
||||||
cursor_shape_manager: Default::default(),
|
cursor_shape_manager: Default::default(),
|
||||||
|
syncobj_manager: Default::default(),
|
||||||
seats: Default::default(),
|
seats: Default::default(),
|
||||||
});
|
});
|
||||||
self.send(wl_display::GetRegistry {
|
self.send(wl_display::GetRegistry {
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ mod t0027_input_region;
|
||||||
mod t0028_top_level_restacking;
|
mod t0028_top_level_restacking;
|
||||||
mod t0029_double_click_float;
|
mod t0029_double_click_float;
|
||||||
mod t0030_cursor_shape;
|
mod t0030_cursor_shape;
|
||||||
|
mod t0031_syncobj;
|
||||||
|
|
||||||
pub trait TestCase: Sync {
|
pub trait TestCase: Sync {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
|
@ -110,5 +111,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> {
|
||||||
t0028_top_level_restacking,
|
t0028_top_level_restacking,
|
||||||
t0029_double_click_float,
|
t0029_double_click_float,
|
||||||
t0030_cursor_shape,
|
t0030_cursor_shape,
|
||||||
|
t0031_syncobj,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
65
src/it/tests/t0031_syncobj.rs
Normal file
65
src/it/tests/t0031_syncobj.rs
Normal file
|
|
@ -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<TestRun>) -> TestResult {
|
||||||
|
let _ds = run.create_default_setup().await?;
|
||||||
|
|
||||||
|
struct Waiter(Cell<bool>);
|
||||||
|
impl SyncObjWaiter for Waiter {
|
||||||
|
fn done(self: Rc<Self>, 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(())
|
||||||
|
}
|
||||||
|
|
@ -194,6 +194,7 @@ impl<T> Drop for RevLinkedListIter<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
#[must_use]
|
||||||
pub struct LinkedNode<T> {
|
pub struct LinkedNode<T> {
|
||||||
data: NonNull<NodeData<T>>,
|
data: NonNull<NodeData<T>>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,11 @@ impl SyncObj {
|
||||||
importers: Default::default(),
|
importers: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(feature = "it"), allow(dead_code))]
|
||||||
|
pub fn fd(&self) -> &Rc<OwnedFd> {
|
||||||
|
&self.fd
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for SyncObj {
|
impl Drop for SyncObj {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ pub trait SyncObjWaiter {
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
struct JobId(u64);
|
struct JobId(u64);
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub struct WaitForSyncObjHandle {
|
pub struct WaitForSyncObjHandle {
|
||||||
inner: Rc<Inner>,
|
inner: Rc<Inner>,
|
||||||
id: JobId,
|
id: JobId,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue