Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

anvil: fix vulkan fifo mode #1629

Merged
merged 3 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 93 additions & 84 deletions anvil/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,41 +781,29 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
let mut clients: HashMap<ClientId, Client> = HashMap::new();
self.space.elements().for_each(|window| {
window.with_surfaces(|surface, states| {
let clear_commit_timer = surface_primary_scanout_output(surface, states)
.map(|primary_output| &primary_output == output)
.unwrap_or(true);

if clear_commit_timer {
if let Some(mut commit_timer_state) = states
.data_map
.get::<CommitTimerBarrierStateUserData>()
.map(|commit_timer| commit_timer.lock().unwrap())
{
commit_timer_state.signal_until(frame_target);
let client = surface.client().unwrap();
clients.insert(client.id(), client);
}
if let Some(mut commit_timer_state) = states
.data_map
.get::<CommitTimerBarrierStateUserData>()
.map(|commit_timer| commit_timer.lock().unwrap())
{
commit_timer_state.signal_until(frame_target);
let client = surface.client().unwrap();
clients.insert(client.id(), client);
}
});
});

let map = smithay::desktop::layer_map_for_output(output);
for layer_surface in map.layers() {
layer_surface.with_surfaces(|surface, states| {
let clear_commit_timer = surface_primary_scanout_output(surface, states)
.map(|primary_output| &primary_output == output)
.unwrap_or(true);

if clear_commit_timer {
if let Some(mut commit_timer_state) = states
.data_map
.get::<CommitTimerBarrierStateUserData>()
.map(|commit_timer| commit_timer.lock().unwrap())
{
commit_timer_state.signal_until(frame_target);
let client = surface.client().unwrap();
clients.insert(client.id(), client);
}
if let Some(mut commit_timer_state) = states
.data_map
.get::<CommitTimerBarrierStateUserData>()
.map(|commit_timer| commit_timer.lock().unwrap())
{
commit_timer_state.signal_until(frame_target);
let client = surface.client().unwrap();
clients.insert(client.id(), client);
}
});
}
Expand All @@ -825,40 +813,28 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {

if let CursorImageStatus::Surface(ref surface) = self.cursor_status {
with_surfaces_surface_tree(surface, |surface, states| {
let clear_commit_timer = surface_primary_scanout_output(surface, states)
.map(|primary_output| &primary_output == output)
.unwrap_or(true);

if clear_commit_timer {
if let Some(mut commit_timer_state) = states
.data_map
.get::<CommitTimerBarrierStateUserData>()
.map(|commit_timer| commit_timer.lock().unwrap())
{
commit_timer_state.signal_until(frame_target);
let client = surface.client().unwrap();
clients.insert(client.id(), client);
}
if let Some(mut commit_timer_state) = states
.data_map
.get::<CommitTimerBarrierStateUserData>()
.map(|commit_timer| commit_timer.lock().unwrap())
{
commit_timer_state.signal_until(frame_target);
let client = surface.client().unwrap();
clients.insert(client.id(), client);
}
});
}

if let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) {
with_surfaces_surface_tree(surface, |surface, states| {
let clear_commit_timer = surface_primary_scanout_output(surface, states)
.map(|primary_output| &primary_output == output)
.unwrap_or(true);

if clear_commit_timer {
if let Some(mut commit_timer_state) = states
.data_map
.get::<CommitTimerBarrierStateUserData>()
.map(|commit_timer| commit_timer.lock().unwrap())
{
commit_timer_state.signal_until(frame_target);
let client = surface.client().unwrap();
clients.insert(client.id(), client);
}
if let Some(mut commit_timer_state) = states
.data_map
.get::<CommitTimerBarrierStateUserData>()
.map(|commit_timer| commit_timer.lock().unwrap())
{
commit_timer_state.signal_until(frame_target);
let client = surface.client().unwrap();
clients.insert(client.id(), client);
}
});
}
Expand All @@ -884,13 +860,7 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {

self.space.elements().for_each(|window| {
window.with_surfaces(|surface, states| {
let primary_scanout_output = update_surface_primary_scanout_output(
surface,
output,
states,
render_element_states,
default_primary_scanout_output_compare,
);
let primary_scanout_output = surface_primary_scanout_output(surface, states);

if let Some(output) = primary_scanout_output.as_ref() {
with_fractional_scale(states, |fraction_scale| {
Expand Down Expand Up @@ -935,13 +905,7 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
let map = smithay::desktop::layer_map_for_output(output);
for layer_surface in map.layers() {
layer_surface.with_surfaces(|surface, states| {
let primary_scanout_output = update_surface_primary_scanout_output(
surface,
output,
states,
render_element_states,
default_primary_scanout_output_compare,
);
let primary_scanout_output = surface_primary_scanout_output(surface, states);

if let Some(output) = primary_scanout_output.as_ref() {
with_fractional_scale(states, |fraction_scale| {
Expand Down Expand Up @@ -987,13 +951,7 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {

if let CursorImageStatus::Surface(ref surface) = self.cursor_status {
with_surfaces_surface_tree(surface, |surface, states| {
let primary_scanout_output = update_surface_primary_scanout_output(
surface,
output,
states,
render_element_states,
default_primary_scanout_output_compare,
);
let primary_scanout_output = surface_primary_scanout_output(surface, states);

if let Some(output) = primary_scanout_output.as_ref() {
with_fractional_scale(states, |fraction_scale| {
Expand Down Expand Up @@ -1024,13 +982,7 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {

if let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) {
with_surfaces_surface_tree(surface, |surface, states| {
let primary_scanout_output = update_surface_primary_scanout_output(
surface,
output,
states,
render_element_states,
default_primary_scanout_output_compare,
);
let primary_scanout_output = surface_primary_scanout_output(surface, states);

if let Some(output) = primary_scanout_output.as_ref() {
with_fractional_scale(states, |fraction_scale| {
Expand Down Expand Up @@ -1065,6 +1017,63 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
}
}
}

pub fn update_primary_scanout_output(
space: &Space<WindowElement>,
output: &Output,
dnd_icon: &Option<DndIcon>,
cursor_status: &CursorImageStatus,
render_element_states: &RenderElementStates,
) {
space.elements().for_each(|window| {
window.with_surfaces(|surface, states| {
update_surface_primary_scanout_output(
surface,
output,
states,
render_element_states,
default_primary_scanout_output_compare,
);
});
});
let map = smithay::desktop::layer_map_for_output(output);
for layer_surface in map.layers() {
layer_surface.with_surfaces(|surface, states| {
update_surface_primary_scanout_output(
surface,
output,
states,
render_element_states,
default_primary_scanout_output_compare,
);
});
}

if let CursorImageStatus::Surface(ref surface) = cursor_status {
with_surfaces_surface_tree(surface, |surface, states| {
update_surface_primary_scanout_output(
surface,
output,
states,
render_element_states,
default_primary_scanout_output_compare,
);
});
}

if let Some(surface) = dnd_icon.as_ref().map(|icon| &icon.surface) {
with_surfaces_surface_tree(surface, |surface, states| {
update_surface_primary_scanout_output(
surface,
output,
states,
render_element_states,
default_primary_scanout_output_compare,
);
});
}
}

#[derive(Debug, Clone)]
pub struct SurfaceDmabufFeedback {
pub render_feedback: DmabufFeedback,
Expand Down
33 changes: 13 additions & 20 deletions anvil/src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
drawing::*,
render::*,
shell::WindowElement,
state::{take_presentation_feedback, AnvilState, Backend},
state::{take_presentation_feedback, update_primary_scanout_output, AnvilState, Backend},
};
use crate::{
shell::WindowRenderElement,
Expand Down Expand Up @@ -1147,20 +1147,17 @@ impl AnvilState<UdevData> {
.frame_submitted()
.map_err(Into::<SwapBuffersError>::into);

let Some(frame_duration) = output
.current_mode()
.map(|mode| Duration::from_secs_f64(1_000f64 / mode.refresh as f64))
else {
return;
};

let schedule_render = match submit_result {
Ok(user_data) => {
if let Some(mut feedback) = user_data.flatten() {
feedback.presented(
clock,
output
.current_mode()
.map(|mode| {
Refresh::fixed(Duration::from_secs_f64(1_000f64 / mode.refresh as f64))
})
.unwrap_or(Refresh::Unknown),
seq as u64,
flags,
);
feedback.presented(clock, Refresh::fixed(frame_duration), seq as u64, flags);
}

true
Expand Down Expand Up @@ -1189,12 +1186,7 @@ impl AnvilState<UdevData> {
};

if schedule_render {
let output_refresh = match output.current_mode() {
Some(mode) => mode.refresh,
None => return,
};

let next_frame_target = clock + Duration::from_millis(1_000_000 / output_refresh as u64);
let next_frame_target = clock + frame_duration;

// What are we trying to solve by introducing a delay here:
//
Expand Down Expand Up @@ -1224,8 +1216,7 @@ impl AnvilState<UdevData> {
//
// A more complete solution could work on a sliding window analyzing past repaints
// and do some prediction for the next repaint.
let repaint_delay =
Duration::from_millis(((1_000_000f32 / output_refresh as f32) * 0.6f32) as u64);
let repaint_delay = Duration::from_secs_f64(frame_duration.as_secs_f64() * 0.6f64);

let timer = if self.backend_data.primary_gpu != surface.render_node {
// However, if we need to do a copy, that might not be enough.
Expand Down Expand Up @@ -1541,6 +1532,8 @@ fn render_surface<'a>(
_ => unreachable!(),
})?;

update_primary_scanout_output(space, output, dnd_icon, cursor_status, &states);

if rendered {
let output_presentation_feedback = take_presentation_feedback(output, space, &states);
surface
Expand Down
Loading