it: add frame callback test
This commit is contained in:
parent
fbef86e928
commit
8a5f1e1e37
3 changed files with 111 additions and 2 deletions
|
|
@ -3,14 +3,14 @@ use {
|
||||||
ifs::wl_surface::WlSurface,
|
ifs::wl_surface::WlSurface,
|
||||||
it::{
|
it::{
|
||||||
test_error::{TestError, TestResult},
|
test_error::{TestError, TestResult},
|
||||||
test_ifs::test_region::TestRegion,
|
test_ifs::{test_callback::TestCallback, test_region::TestRegion},
|
||||||
test_object::TestObject,
|
test_object::TestObject,
|
||||||
test_transport::TestTransport,
|
test_transport::TestTransport,
|
||||||
test_utils::test_expected_event::TEEH,
|
test_utils::test_expected_event::TEEH,
|
||||||
testrun::ParseFull,
|
testrun::ParseFull,
|
||||||
},
|
},
|
||||||
utils::buffd::MsgParser,
|
utils::buffd::MsgParser,
|
||||||
wire::{WlBufferId, WlSurfaceId, wl_surface::*},
|
wire::{WlBufferId, WlCallbackId, WlSurfaceId, wl_surface::*},
|
||||||
},
|
},
|
||||||
std::{cell::Cell, rc::Rc},
|
std::{cell::Cell, rc::Rc},
|
||||||
};
|
};
|
||||||
|
|
@ -89,6 +89,22 @@ impl TestSurface {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn frame(&self) -> Result<Rc<TestCallback>, TestError> {
|
||||||
|
let id: WlCallbackId = self.tran.id();
|
||||||
|
let callback = Rc::new(TestCallback {
|
||||||
|
id,
|
||||||
|
_tran: self.tran.clone(),
|
||||||
|
handler: Cell::new(None),
|
||||||
|
done: Cell::new(false),
|
||||||
|
});
|
||||||
|
self.tran.add_obj(callback.clone())?;
|
||||||
|
self.tran.send(Frame {
|
||||||
|
self_id: self.id,
|
||||||
|
callback: callback.id,
|
||||||
|
})?;
|
||||||
|
Ok(callback)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn commit(&self) -> Result<(), TestError> {
|
pub fn commit(&self) -> Result<(), TestError> {
|
||||||
self.tran.send(Commit { self_id: self.id })?;
|
self.tran.send(Commit { self_id: self.id })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ mod t0044_stacked_focus;
|
||||||
mod t0045_content_type;
|
mod t0045_content_type;
|
||||||
mod t0046_buffer_release;
|
mod t0046_buffer_release;
|
||||||
mod t0047_surface_damage;
|
mod t0047_surface_damage;
|
||||||
|
mod t0048_frame_callback;
|
||||||
|
|
||||||
pub trait TestCase: Sync {
|
pub trait TestCase: Sync {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
|
@ -144,5 +145,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> {
|
||||||
t0045_content_type,
|
t0045_content_type,
|
||||||
t0046_buffer_release,
|
t0046_buffer_release,
|
||||||
t0047_surface_damage,
|
t0047_surface_damage,
|
||||||
|
t0048_frame_callback,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
91
src/it/tests/t0048_frame_callback.rs
Normal file
91
src/it/tests/t0048_frame_callback.rs
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
use {
|
||||||
|
crate::it::{test_error::TestResult, testrun::TestRun},
|
||||||
|
std::rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
|
testcase!();
|
||||||
|
|
||||||
|
/// Test wl_surface.frame callbacks
|
||||||
|
/// This test verifies that the compositor sends wl_callback.done events after the vblank event.
|
||||||
|
/// According to the Wayland protocol, frame callbacks should be fired to indicate when
|
||||||
|
/// it's a good time to start drawing the next frame, and they should be posted after
|
||||||
|
/// the compositor has finished presenting the previous frame (i.e., after vblank).
|
||||||
|
async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
|
run.backend.install_default()?;
|
||||||
|
let client = run.create_client().await?;
|
||||||
|
|
||||||
|
// Create a visible window so frame callbacks can be triggered
|
||||||
|
let window = client.create_window().await?;
|
||||||
|
window.map().await?;
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
|
// Test 1: Basic frame callback functionality
|
||||||
|
let surface = &window.surface.surface;
|
||||||
|
let callback1 = surface.frame()?;
|
||||||
|
surface.commit()?;
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
|
// Manually trigger vblank event to simulate frame completion
|
||||||
|
let connector_id = run.backend.default_connector.id;
|
||||||
|
|
||||||
|
// Trigger vblank manually - this processes frame callbacks
|
||||||
|
run.state.vblank(connector_id);
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
|
// The frame callback should have been fired after vblank
|
||||||
|
tassert!(callback1.done.get());
|
||||||
|
|
||||||
|
// Test 2: Multiple frame callbacks
|
||||||
|
let callback2 = surface.frame()?;
|
||||||
|
let callback3 = surface.frame()?;
|
||||||
|
surface.commit()?;
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
|
// Before triggering vblank, callbacks should not be done yet
|
||||||
|
tassert!(!callback2.done.get());
|
||||||
|
tassert!(!callback3.done.get());
|
||||||
|
|
||||||
|
// Trigger vblank manually - this processes frame callbacks
|
||||||
|
run.state.vblank(connector_id);
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
|
// Both callbacks should be done after vblank
|
||||||
|
tassert!(callback2.done.get());
|
||||||
|
tassert!(callback3.done.get());
|
||||||
|
|
||||||
|
// Test 3: Frame callbacks on invisible surface should not be processed
|
||||||
|
// Create a new surface but don't make it visible
|
||||||
|
let invisible_surface = client.comp.create_surface().await?;
|
||||||
|
let buffer = client
|
||||||
|
.spbm
|
||||||
|
.create_buffer(crate::theme::Color::from_srgb(255, 0, 0))?;
|
||||||
|
invisible_surface.attach(buffer.id)?;
|
||||||
|
|
||||||
|
let callback_invisible = invisible_surface.frame()?;
|
||||||
|
invisible_surface.commit()?;
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
|
// Trigger vblank manually - this processes frame callbacks
|
||||||
|
run.state.vblank(connector_id);
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
|
// Frame callback on invisible surface should not be processed
|
||||||
|
tassert!(!callback_invisible.done.get());
|
||||||
|
|
||||||
|
// Test 4: Frame callback timing - verify they happen after vblank
|
||||||
|
let callback_timing = surface.frame()?;
|
||||||
|
surface.commit()?;
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
|
// The callback should not be done immediately after commit
|
||||||
|
tassert!(!callback_timing.done.get());
|
||||||
|
|
||||||
|
// Trigger vblank manually - this processes frame callbacks
|
||||||
|
run.state.vblank(connector_id);
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
|
// Now it should be done
|
||||||
|
tassert!(callback_timing.done.get());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue