shell: Using parking_lot's RwLock for fairness guarantees

This commit is contained in:
Victoria Brekenfeld 2025-05-20 17:41:27 +02:00 committed by Victoria Brekenfeld
parent 8194be30c6
commit 465813c1c5
42 changed files with 247 additions and 396 deletions

View file

@ -307,7 +307,7 @@ impl State {
let connectors = device.enumerate_surfaces()?.added; // There are no removed outputs on newly added devices
let mut wl_outputs = Vec::new();
let mut w = self.common.shell.read().unwrap().global_space().size.w as u32;
let mut w = self.common.shell.read().global_space().size.w as u32;
{
for (conn, maybe_crtc) in connectors {
@ -380,7 +380,7 @@ impl State {
if let Some(device) = backend.drm_devices.get_mut(&drm_node) {
let changes = device.enumerate_surfaces()?;
let mut w = self.common.shell.read().unwrap().global_space().size.w as u32;
let mut w = self.common.shell.read().global_space().size.w as u32;
for conn in changes.removed {
// contains conns with updated crtcs, just drop the surface and re-create
if let Some(pos) = device
@ -577,7 +577,7 @@ impl Device {
position: (u32, u32),
evlh: &LoopHandle<'static, State>,
screen_filter: ScreenFilter,
shell: Arc<RwLock<Shell>>,
shell: Arc<parking_lot::RwLock<Shell>>,
startup_done: Arc<AtomicBool>,
) -> Result<(Output, bool)> {
let output = self
@ -676,7 +676,7 @@ impl Device {
flags: FrameFlags,
renderer: &mut GlMultiRenderer,
clock: &Clock<Monotonic>,
shell: &Arc<RwLock<Shell>>,
shell: &Arc<parking_lot::RwLock<Shell>>,
) -> Result<()> {
for surface in self.surfaces.values_mut() {
surface.allow_frame_flags(flag, flags);
@ -733,7 +733,7 @@ impl Device {
flag: bool,
renderer: &mut GlMultiRenderer,
clock: &Clock<Monotonic>,
shell: &Arc<RwLock<Shell>>,
shell: &Arc<parking_lot::RwLock<Shell>>,
) -> Result<()> {
self.allow_frame_flags(
flag,
@ -749,7 +749,7 @@ impl Device {
flag: bool,
renderer: &mut GlMultiRenderer,
clock: &Clock<Monotonic>,
shell: &Arc<RwLock<Shell>>,
shell: &Arc<parking_lot::RwLock<Shell>>,
) -> Result<()> {
self.allow_frame_flags(
flag,

View file

@ -169,7 +169,7 @@ fn init_libinput(
state.process_input_event(event);
for output in state.common.shell.read().unwrap().outputs() {
for output in state.common.shell.read().outputs() {
state.backend.kms().schedule_render(output);
}
})
@ -592,7 +592,7 @@ impl KmsState {
test_only: bool,
loop_handle: &LoopHandle<'static, State>,
screen_filter: &ScreenFilter,
shell: Arc<RwLock<Shell>>,
shell: Arc<parking_lot::RwLock<Shell>>,
startup_done: Arc<AtomicBool>,
clock: &Clock<Monotonic>,
) -> Result<Vec<Output>, anyhow::Error> {
@ -683,7 +683,7 @@ impl KmsState {
}
// add new ones
let mut w = shell.read().unwrap().global_space().size.w as u32;
let mut w = shell.read().global_space().size.w as u32;
if !test_only {
for (conn, crtc) in new_pairings {
let (output, _) = device.connector_added(

View file

@ -136,7 +136,7 @@ pub struct SurfaceThreadState {
screen_filter: ScreenFilter,
postprocess_textures: HashMap<DrmNode, PostprocessState>,
shell: Arc<RwLock<Shell>>,
shell: Arc<parking_lot::RwLock<Shell>>,
loop_handle: LoopHandle<'static, Self>,
clock: Clock<Monotonic>,
@ -233,7 +233,7 @@ impl Surface {
target_node: DrmNode,
evlh: &LoopHandle<'static, State>,
screen_filter: ScreenFilter,
shell: Arc<RwLock<Shell>>,
shell: Arc<parking_lot::RwLock<Shell>>,
startup_done: Arc<AtomicBool>,
) -> Result<Self> {
let (tx, rx) = channel::<ThreadCommand>();
@ -471,7 +471,7 @@ fn surface_thread(
output: Output,
primary_node: Arc<RwLock<Option<DrmNode>>>,
target_node: DrmNode,
shell: Arc<RwLock<Shell>>,
shell: Arc<parking_lot::RwLock<Shell>>,
active: Arc<AtomicBool>,
screen_filter: ScreenFilter,
thread_sender: Sender<SurfaceCommand>,
@ -839,7 +839,7 @@ impl SurfaceThreadState {
QueueState::WaitingForEstimatedVBlankAndQueued { .. } => unreachable!(),
};
if redraw_needed || self.shell.read().unwrap().animations_going() {
if redraw_needed || self.shell.read().animations_going() {
let vblank_frame = tracy_client::Client::running()
.unwrap()
.non_continuous_frame(self.vblank_frame_name);
@ -866,7 +866,7 @@ impl SurfaceThreadState {
self.frame_callback_seq = self.frame_callback_seq.wrapping_add(1);
if force || self.shell.read().unwrap().animations_going() {
if force || self.shell.read().animations_going() {
self.queue_redraw(false);
} else {
self.send_frame_callbacks();
@ -962,7 +962,7 @@ impl SurfaceThreadState {
.as_ref()
.unwrap_or(&self.target_node),
&self.target_node,
&*self.shell.read().unwrap(),
&*self.shell.read(),
);
let mut renderer = if render_node != self.target_node {
@ -979,7 +979,7 @@ impl SurfaceThreadState {
let mut remove_frame_flags = FrameFlags::empty();
let has_active_fullscreen = {
let shell = self.shell.read().unwrap();
let shell = self.shell.read();
let output = self.mirroring.as_ref().unwrap_or(&self.output);
if let Some((_, workspace)) = shell.workspaces.active(output) {
workspace.get_fullscreen().is_some()
@ -1416,7 +1416,6 @@ impl SurfaceThreadState {
Some((
self.shell
.read()
.unwrap()
.take_presentation_feedback(&self.output, &frame_result.states),
rx,
estimated_presentation,

View file

@ -47,7 +47,6 @@ pub fn init_backend_auto(
.common
.shell
.read()
.unwrap()
.outputs()
.next()
.with_context(|| "Backend initialized without output")
@ -68,7 +67,6 @@ pub fn init_backend_auto(
.common
.shell
.write()
.unwrap()
.seats
.add_seat(initial_seat.clone());
@ -79,7 +77,7 @@ pub fn init_backend_auto(
.accessibility_zoom
.start_on_login
{
state.common.shell.write().unwrap().trigger_zoom(
state.common.shell.write().trigger_zoom(
&initial_seat,
None,
1.0 + (state.common.config.cosmic_conf.accessibility_zoom.increment as f64 / 100.),
@ -117,7 +115,7 @@ pub fn init_backend_auto(
.common
.startup_done
.store(true, std::sync::atomic::Ordering::SeqCst);
for output in state.common.shell.read().unwrap().outputs() {
for output in state.common.shell.read().outputs() {
state.backend.schedule_render(&output);
}
}

View file

@ -5,7 +5,7 @@ use std::{
cell::RefCell,
collections::HashMap,
ops::ControlFlow,
sync::{Arc, RwLock, Weak},
sync::{Arc, Weak},
time::Instant,
};
@ -559,7 +559,7 @@ pub enum ElementFilter {
pub fn output_elements<R>(
_gpu: Option<&DrmNode>,
renderer: &mut R,
shell: &Arc<RwLock<Shell>>,
shell: &Arc<parking_lot::RwLock<Shell>>,
now: Time<Monotonic>,
output: &Output,
cursor_mode: CursorMode,
@ -575,7 +575,7 @@ where
#[cfg(feature = "debug")]
let mut debug_elements = {
let output_geo = output.geometry();
let shell_guard = shell.read().unwrap();
let shell_guard = shell.read();
let seats = shell_guard.seats.iter().cloned().collect::<Vec<_>>();
let debug_active = shell_guard.debug_active;
std::mem::drop(shell_guard);
@ -602,7 +602,7 @@ where
}
};
let shell_guard = shell.read().unwrap();
let shell_guard = shell.read();
let Some((previous_workspace, workspace)) = shell_guard.workspaces.active(output) else {
#[cfg(not(feature = "debug"))]
return Ok(Vec::new());
@ -623,7 +623,7 @@ where
} else {
ElementFilter::All
};
let zoom_state = shell.read().unwrap().zoom_state().cloned();
let zoom_state = shell.read().zoom_state().cloned();
#[allow(unused_mut)]
let workspace_elements = workspace_elements(
@ -652,7 +652,7 @@ where
pub fn workspace_elements<R>(
_gpu: Option<&DrmNode>,
renderer: &mut R,
shell: &Arc<RwLock<Shell>>,
shell: &Arc<parking_lot::RwLock<Shell>>,
zoom_level: Option<&ZoomState>,
now: Time<Monotonic>,
output: &Output,
@ -670,7 +670,7 @@ where
{
let mut elements = Vec::new();
let shell_ref = shell.read().unwrap();
let shell_ref = shell.read();
let seats = shell_ref.seats.iter().cloned().collect::<Vec<_>>();
if seats.is_empty() {
return Ok(Vec::new());
@ -692,7 +692,7 @@ where
element_filter == ElementFilter::ExcludeWorkspaceOverview,
));
let shell = shell.read().unwrap();
let shell = shell.read();
let overview = shell.overview_mode();
let (resize_mode, resize_indicator) = shell.resize_mode();
let resize_indicator = resize_indicator.map(|indicator| (resize_mode, indicator));
@ -1136,7 +1136,7 @@ pub fn render_output<'d, R>(
target: &mut R::Framebuffer<'_>,
damage_tracker: &'d mut OutputDamageTracker,
age: usize,
shell: &Arc<RwLock<Shell>>,
shell: &Arc<parking_lot::RwLock<Shell>>,
now: Time<Monotonic>,
output: &Output,
cursor_mode: CursorMode,
@ -1157,7 +1157,7 @@ where
CosmicMappedRenderElement<R>: RenderElement<R>,
WorkspaceRenderElement<R>: RenderElement<R>,
{
let shell_ref = shell.read().unwrap();
let shell_ref = shell.read();
let (previous_workspace, workspace) = shell_ref
.workspaces
.active(output)
@ -1439,7 +1439,7 @@ pub fn render_workspace<'d, R>(
damage_tracker: &'d mut OutputDamageTracker,
age: usize,
additional_damage: Option<Vec<Rectangle<i32, Logical>>>,
shell: &Arc<RwLock<Shell>>,
shell: &Arc<parking_lot::RwLock<Shell>>,
zoom_level: Option<&ZoomState>,
now: Time<Monotonic>,
output: &Output,

View file

@ -76,7 +76,6 @@ impl WinitState {
let mut output_presentation_feedback = state
.shell
.read()
.unwrap()
.take_presentation_feedback(&self.output, &states);
output_presentation_feedback.presented(
state.clock.now(),
@ -297,7 +296,7 @@ impl State {
// here we can handle special cases for winit inputs
match event {
WinitEvent::Focus(true) => {
for seat in self.common.shell.read().unwrap().seats.iter() {
for seat in self.common.shell.read().seats.iter() {
let devices = seat.user_data().get::<Devices>().unwrap();
if devices.has_device(&WinitVirtualDevice) {
seat.set_active_output(&self.backend.winit().output);

View file

@ -240,7 +240,6 @@ impl Surface {
let mut output_presentation_feedback = state
.shell
.read()
.unwrap()
.take_presentation_feedback(&self.output, &states);
output_presentation_feedback.presented(
state.clock.now(),
@ -520,7 +519,7 @@ impl State {
.unwrap();
let device = event.device();
for seat in self.common.shell.read().unwrap().seats.iter() {
for seat in self.common.shell.read().seats.iter() {
let devices = seat.user_data().get::<Devices>().unwrap();
if devices.has_device(&device) {
seat.set_active_output(&output);
@ -534,7 +533,7 @@ impl State {
self.process_input_event(event);
// TODO actually figure out the output
for output in self.common.shell.read().unwrap().outputs() {
for output in self.common.shell.read().outputs() {
self.backend.x11().schedule_render(output);
}
}