Prepare for cherry-pick

This commit is contained in:
Ottatop 2023-09-08 22:08:56 -05:00
parent 7dabc4d22c
commit bef6d92176
3 changed files with 96 additions and 67 deletions

View file

@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-or-later
use std::time::Duration;
use itertools::{Either, Itertools};
use smithay::{
desktop::layer_map_for_output,
desktop::{layer_map_for_output, utils::surface_primary_scanout_output},
output::Output,
reexports::wayland_server::Resource,
utils::{IsAlive, Logical, Point, Rectangle, Size},
@ -57,7 +59,7 @@ impl State {
pub fn update_windows(&mut self, output: &Output) {
let Some(layout) = output.with_state(|state| {
state.focused_tags().next().cloned().map(|tag| tag.layout())
state.focused_tags().next().map(|tag| tag.layout())
}) else { return };
let (windows_on_foc_tags, mut windows_not_on_foc_tags): (Vec<_>, _) =
@ -68,6 +70,7 @@ impl State {
})
});
// Don't unmap windows on other outputs
windows_not_on_foc_tags.retain(|win| win.output(self) == Some(output.clone()));
let tiled_windows = windows_on_foc_tags
@ -122,12 +125,19 @@ impl State {
WindowElement::Wayland(win) => {
// If the above didn't cause any change to size or other state, simply
// map the window.
if !win.toplevel().has_pending_changes() {
let current_state = win.toplevel().current_state();
let is_pending = win
.toplevel()
.with_pending_state(|state| state.size != current_state.size);
// for whatever reason vscode on wayland likes to have pending state
// (like tiled states) but not commit, so we check for just the size
// here
if !is_pending {
tracing::debug!("No pending changes");
state.loc_request_state = LocationRequestState::Idle;
non_pending_wins.push((loc, window.clone()));
// TODO: wait for windows with pending state to ack and commit
// self.space.map_element(window.clone(), loc, false);
} else {
tracing::debug!("Pending changes");
let serial = win.toplevel().send_configure();
state.loc_request_state =
LocationRequestState::Requested(serial, loc);
@ -149,81 +159,100 @@ impl State {
});
}
BLOCKER_COUNTER.store(1, std::sync::atomic::Ordering::SeqCst);
tracing::debug!(
"blocker {}",
BLOCKER_COUNTER.load(std::sync::atomic::Ordering::SeqCst)
);
let start_time = self.clock.now();
// BLOCKER_COUNTER.store(1, std::sync::atomic::Ordering::SeqCst);
// tracing::debug!(
// "blocker {}",
// BLOCKER_COUNTER.load(std::sync::atomic::Ordering::SeqCst)
// );
// Pause rendering. Here we'll wait until all windows have ack'ed and committed,
// then resume rendering. This prevents flickering because some windows will commit before
// others.
//
// This *will* cause everything to freeze for a few frames, but it should'nt impact
// This *will* cause everything to freeze for a few frames, but it shouldn't impact
// anything meaningfully.
self.pause_rendering = true;
for (_loc, win) in pending_wins.iter() {
if let Some(surf) = win.wl_surface() {
tracing::debug!("adding blocker");
compositor::add_blocker(&surf, crate::window::WindowBlocker);
}
}
// for (_loc, win) in pending_wins.iter() {
// if let Some(surf) = win.wl_surface() {
// tracing::debug!("adding blocker");
// compositor::add_blocker(&surf, crate::window::WindowBlocker);
// }
// }
let pending_wins_clone = pending_wins.clone();
// schedule on all idle
self.schedule(
move |_data| {
pending_wins_clone.iter().all(|(_, win)| {
win.with_state(|state| state.loc_request_state.is_acknowledged())
})
},
move |data| {
// remove and trigger blockers
BLOCKER_COUNTER.store(0, std::sync::atomic::Ordering::SeqCst);
tracing::debug!(
"blocker {}",
BLOCKER_COUNTER.load(std::sync::atomic::Ordering::SeqCst)
);
for client in pending_wins
move |_dt| {
// tracing::debug!("Waiting for all to be idle");
let all_idle = pending_wins
.iter()
.filter_map(|(_, win)| win.wl_surface()?.client())
{
data.state
.client_compositor_state(&client)
.blocker_cleared(&mut data.state, &data.display.handle())
}
.filter(|(_, win)| win.alive())
.all(|(_, win)| win.with_state(|state| state.loc_request_state.is_idle()));
// schedule on all idle
data.state.schedule(
move |_dt| {
pending_wins
.iter()
.filter(|(_, win)| win.alive())
.all(|(_, win)| {
win.with_state(|state| state.loc_request_state.is_idle())
})
},
move |dt| {
for (loc, win) in non_pending_wins {
dt.state.space.map_element(win, loc, false);
}
for win in windows_not_on_foc_tags {
dt.state.space.unmap_elem(&win);
}
dt.state.pause_rendering = false;
let finish_time =
smithay::utils::Time::elapsed(&start_time, dt.state.clock.now());
tracing::debug!(
"spent {} microseconds not rendering",
finish_time.as_micros()
);
},
);
all_idle
},
move |dt| {
for (loc, win) in non_pending_wins {
dt.state.space.map_element(win, loc, false);
}
for win in windows_not_on_foc_tags {
dt.state.space.unmap_elem(&win);
}
dt.state.pause_rendering = false;
},
);
// self.schedule(
// move |_data| {
// // tracing::debug!("Waiting for all to ack");
// pending_wins_clone.iter().all(|(_, win)| {
// win.with_state(|state| state.loc_request_state.is_acknowledged())
// })
// },
// move |data| {
// // remove and trigger blockers
// BLOCKER_COUNTER.store(0, std::sync::atomic::Ordering::SeqCst);
// tracing::debug!(
// "blocker {}",
// BLOCKER_COUNTER.load(std::sync::atomic::Ordering::SeqCst)
// );
// for client in pending_wins
// .iter()
// .filter_map(|(_, win)| win.wl_surface()?.client())
// {
// data.state
// .client_compositor_state(&client)
// .blocker_cleared(&mut data.state, &data.display.handle())
// }
//
// // schedule on all idle
// data.state.schedule(
// move |_dt| {
// // tracing::debug!("Waiting for all to be idle");
// let all_idle =
// pending_wins
// .iter()
// .filter(|(_, win)| win.alive())
// .all(|(_, win)| {
// win.with_state(|state| state.loc_request_state.is_idle())
// });
//
// all_idle
// },
// move |dt| {
// for (loc, win) in non_pending_wins {
// dt.state.space.map_element(win, loc, false);
// }
// for win in windows_not_on_foc_tags {
// dt.state.space.unmap_elem(&win);
// }
// dt.state.pause_rendering = false;
// },
// );
// },
// );
}
}

View file

@ -8,7 +8,7 @@
//! While Pinnacle is not a library, this documentation serves to guide those who want to
//! contribute or learn how building something like this works.
#![deny(unused_imports)] // gonna force myself to keep stuff clean
// #![deny(unused_imports)] // gonna force myself to keep stuff clean
#![warn(clippy::unwrap_used)]
use clap::Parser;

View file

@ -11,7 +11,7 @@ use smithay::{
take_presentation_feedback_surface_tree, under_from_surface_tree,
with_surfaces_surface_tree, OutputPresentationFeedback,
},
Space, Window, WindowSurfaceType,
Window, WindowSurfaceType,
},
input::{
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
@ -23,7 +23,7 @@ use smithay::{
wayland_protocols::wp::presentation_time::server::wp_presentation_feedback,
wayland_server::protocol::wl_surface::WlSurface,
},
utils::{user_data::UserDataMap, IsAlive, Logical, Point, Rectangle, Serial, Size},
utils::{user_data::UserDataMap, IsAlive, Logical, Point, Rectangle, Serial},
wayland::{
compositor::{self, Blocker, BlockerState, SurfaceData},
dmabuf::DmabufFeedback,