From 0ba8648844b975177de2d416aa4c114fa913cb43 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Fri, 16 Feb 2024 18:27:51 +0100 Subject: [PATCH 1/3] video: unify output rendering --- src/backends/metal/video.rs | 16 +++++----------- src/backends/x.rs | 17 ++++------------- src/state.rs | 26 +++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 5b977135..03f15e06 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -380,22 +380,16 @@ impl MetalConnector { if let Some(node) = self.state.root.outputs.get(&self.connector_id) { let mut rr = self.render_result.borrow_mut(); let render_fb = buffer.render_fb(); - render_fb.render_node( - &*node, - &self.state, - Some(node.global.pos.get()), - Some(&mut rr), - node.preferred_scale.get(), + self.state.present_output( + &node, + &render_fb, + &buffer.render_tex, + &mut rr, !self.cursor_enabled.get(), ); if let Some(tex) = &buffer.dev_tex { buffer.dev_fb.copy_texture(tex, 0, 0); } - for fr in rr.frame_requests.drain(..) { - fr.send_done(); - let _ = fr.client.remove_obj(&*fr); - } - node.perform_screencopies(&*render_fb, &buffer.render_tex); } changes.change_object(plane.id, |c| { c.change(plane.fb_id, buffer.drm.id().0 as _); diff --git a/src/backends/x.rs b/src/backends/x.rs index 7a5812df..5af0103d 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -57,7 +57,6 @@ use { collections::VecDeque, error::Error, future::pending, - ops::DerefMut, rc::Rc, }, thiserror::Error, @@ -733,21 +732,13 @@ impl XBackend { image.last_serial.set(serial); if let Some(node) = self.state.root.outputs.get(&output.id) { - let mut rr = self.render_result.borrow_mut(); - let fb = image.fb.get(); - fb.render_node( + self.state.present_output( &*node, - &self.state, - Some(node.global.pos.get()), - Some(rr.deref_mut()), - node.preferred_scale.get(), + &image.fb.get(), + &image.tex.get(), + &mut self.render_result.borrow_mut(), true, ); - for fr in rr.frame_requests.drain(..) { - fr.send_done(); - let _ = fr.client.remove_obj(&*fr); - } - node.perform_screencopies(&*fb, &image.tex.get()); } let pp = PresentPixmap { diff --git a/src/state.rs b/src/state.rs index e2c466c0..8ee7eda0 100644 --- a/src/state.rs +++ b/src/state.rs @@ -14,7 +14,7 @@ use { dbus::Dbus, drm_feedback::DrmFeedback, forker::ForkerProxy, - gfx_api::{GfxContext, GfxError}, + gfx_api::{GfxContext, GfxError, GfxFramebuffer, GfxTexture}, gfx_apis::create_gfx_context, globals::{Globals, GlobalsError, WaylandGlobal}, ifs::{ @@ -36,6 +36,7 @@ use { leaks::Tracker, logger::Logger, rect::Rect, + renderer::RenderResult, scale::Scale, theme::Theme, tree::{ @@ -730,4 +731,27 @@ impl State { f(tester); } } + + pub fn present_output( + &self, + output: &OutputNode, + fb: &Rc, + tex: &Rc, + rr: &mut RenderResult, + render_hw_cursor: bool, + ) { + fb.render_node( + &*output, + self, + Some(output.global.pos.get()), + Some(rr), + output.preferred_scale.get(), + render_hw_cursor, + ); + for fr in rr.frame_requests.drain(..) { + fr.send_done(); + let _ = fr.client.remove_obj(&*fr); + } + output.perform_screencopies(&**fb, tex); + } } From d4fc672fb3c6e97e779b483880baf3b8cac6fb34 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Fri, 16 Feb 2024 19:15:03 +0100 Subject: [PATCH 2/3] tree: move output scale to global --- src/backends/x.rs | 2 +- src/compositor.rs | 1 - src/config/handler.rs | 2 +- src/ifs/wl_output.rs | 2 ++ src/ifs/wl_seat.rs | 2 +- src/ifs/wl_surface.rs | 2 +- src/ifs/wl_surface/wp_fractional_scale_v1.rs | 2 +- src/renderer.rs | 2 +- src/state.rs | 4 ++-- src/tasks/connector.rs | 7 +++---- src/tree/output.rs | 7 +++---- 11 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/backends/x.rs b/src/backends/x.rs index 5af0103d..ce3b46de 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -733,7 +733,7 @@ impl XBackend { if let Some(node) = self.state.root.outputs.get(&output.id) { self.state.present_output( - &*node, + &node, &image.fb.get(), &image.tex.get(), &mut self.render_result.borrow_mut(), diff --git a/src/compositor.rs b/src/compositor.rs index 4a46c67e..05ab43cf 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -392,7 +392,6 @@ fn create_dummy_output(state: &Rc) { scroll: Default::default(), pointer_positions: Default::default(), lock_surface: Default::default(), - preferred_scale: Cell::new(Scale::from_int(1)), hardware_cursor: Default::default(), update_render_data_scheduled: Cell::new(false), screencasts: Default::default(), diff --git a/src/config/handler.rs b/src/config/handler.rs index 48020c12..e9445e09 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -717,7 +717,7 @@ impl ConfigProxyHandler { fn handle_connector_get_scale(&self, connector: Connector) -> Result<(), CphError> { let connector = self.get_output(connector)?; self.respond(Response::ConnectorGetScale { - scale: connector.node.preferred_scale.get().to_f64(), + scale: connector.node.global.preferred_scale.get().to_f64(), }); Ok(()) } diff --git a/src/ifs/wl_output.rs b/src/ifs/wl_output.rs index 0d69f0c5..b487a3f2 100644 --- a/src/ifs/wl_output.rs +++ b/src/ifs/wl_output.rs @@ -74,6 +74,7 @@ pub struct WlOutputGlobal { pub pending_captures: LinkedList>, pub destroyed: Cell, pub legacy_scale: Cell, + pub preferred_scale: Cell, } #[derive(Eq, PartialEq)] @@ -120,6 +121,7 @@ impl WlOutputGlobal { pending_captures: Default::default(), destroyed: Cell::new(false), legacy_scale: Cell::new(1), + preferred_scale: Cell::new(crate::scale::Scale::from_int(1)), } } diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 42552223..21991b38 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -265,7 +265,7 @@ impl WlSeatGlobal { for output in self.state.root.outputs.lock().values() { if let Some(hc) = output.hardware_cursor.get() { let render = render | output.hardware_cursor_needs_render.take(); - let scale = output.preferred_scale.get(); + let scale = output.global.preferred_scale.get(); let extents = cursor.extents_at_scale(scale); if render { let (max_width, max_height) = hc.max_size(); diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 7f0c6cd8..81f68c5d 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -438,7 +438,7 @@ impl WlSurface { } output.global.send_enter(self); old.global.send_leave(self); - if old.preferred_scale.get() != output.preferred_scale.get() { + if old.global.preferred_scale.get() != output.global.preferred_scale.get() { self.on_scale_change(); } let children = self.children.borrow_mut(); diff --git a/src/ifs/wl_surface/wp_fractional_scale_v1.rs b/src/ifs/wl_surface/wp_fractional_scale_v1.rs index 922e2625..a7237e5d 100644 --- a/src/ifs/wl_surface/wp_fractional_scale_v1.rs +++ b/src/ifs/wl_surface/wp_fractional_scale_v1.rs @@ -39,7 +39,7 @@ impl WpFractionalScaleV1 { pub fn send_preferred_scale(&self) { self.client.event(PreferredScale { self_id: self.id, - scale: self.surface.output.get().preferred_scale.get().0, + scale: self.surface.output.get().global.preferred_scale.get().0, }); } diff --git a/src/renderer.rs b/src/renderer.rs index 7d1901d8..b3972c01 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -139,7 +139,7 @@ impl Renderer<'_> { let c = theme.colors.attention_requested_background.get(); self.base .fill_boxes2(&rd.attention_requested_workspaces, &c, x, y); - let scale = output.preferred_scale.get(); + let scale = output.global.preferred_scale.get(); for title in &rd.titles { let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y); self.base diff --git a/src/state.rs b/src/state.rs index 8ee7eda0..8892bf87 100644 --- a/src/state.rs +++ b/src/state.rs @@ -741,11 +741,11 @@ impl State { render_hw_cursor: bool, ) { fb.render_node( - &*output, + output, self, Some(output.global.pos.get()), Some(rr), - output.preferred_scale.get(), + output.global.preferred_scale.get(), render_hw_cursor, ); for fr in rr.frame_requests.drain(..) { diff --git a/src/tasks/connector.rs b/src/tasks/connector.rs index 02494733..447b5eaa 100644 --- a/src/tasks/connector.rs +++ b/src/tasks/connector.rs @@ -2,7 +2,6 @@ use { crate::{ backend::{Connector, ConnectorEvent, ConnectorId, MonitorInfo}, ifs::wl_output::WlOutputGlobal, - scale::Scale, state::{ConnectorData, OutputData, State}, tree::{OutputNode, OutputRenderData}, utils::{asyncevent::AsyncEvent, clonecell::CloneCell}, @@ -124,14 +123,13 @@ impl ConnectorHandler { scroll: Default::default(), pointer_positions: Default::default(), lock_surface: Default::default(), - preferred_scale: Cell::new(Scale::from_int(1)), hardware_cursor: Default::default(), jay_outputs: Default::default(), screencasts: Default::default(), update_render_data_scheduled: Cell::new(false), hardware_cursor_needs_render: Cell::new(false), }); - self.state.add_output_scale(on.preferred_scale.get()); + self.state.add_output_scale(on.global.preferred_scale.get()); let mode = info.initial_mode; let output_data = Rc::new(OutputData { connector: self.data.clone(), @@ -278,7 +276,8 @@ impl ConnectorHandler { if let Some(dev) = &self.data.drm_dev { dev.connectors.remove(&self.id); } - self.state.remove_output_scale(on.preferred_scale.get()); + self.state + .remove_output_scale(on.global.preferred_scale.get()); let _ = self.state.remove_global(&*global); } } diff --git a/src/tree/output.rs b/src/tree/output.rs index 750e33bd..8898501d 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -59,7 +59,6 @@ pub struct OutputNode { pub scroll: Scroller, pub pointer_positions: CopyHashMap, pub lock_surface: CloneCell>>, - pub preferred_scale: Cell, pub hardware_cursor: CloneCell>>, pub hardware_cursor_needs_render: Cell, pub update_render_data_scheduled: Cell, @@ -111,7 +110,7 @@ impl OutputNode { } pub fn set_preferred_scale(self: &Rc, scale: Scale) { - let old_scale = self.preferred_scale.replace(scale); + let old_scale = self.global.preferred_scale.replace(scale); if scale == old_scale { return; } @@ -152,7 +151,7 @@ impl OutputNode { let font = self.state.theme.font.borrow_mut(); let theme = &self.state.theme; let th = theme.sizes.title_height.get(); - let scale = self.preferred_scale.get(); + let scale = self.global.preferred_scale.get(); let scale = if scale != 1 { Some(scale.to_f64()) } else { @@ -410,7 +409,7 @@ impl OutputNode { let mode = self.global.mode.get(); let mut width = mode.width; let mut height = mode.height; - let scale = self.preferred_scale.get(); + let scale = self.global.preferred_scale.get(); if scale != 1 { let scale = scale.to_f64(); width = (width as f64 / scale).round() as _; From 4d8e744c2f7d424bfba80f77f17c9b7a6a4361b7 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Fri, 16 Feb 2024 19:12:50 +0100 Subject: [PATCH 3/3] video: render hardware cursor in screencasts --- src/ifs/jay_screencast.rs | 17 +++++++++++-- src/ifs/wl_output.rs | 17 +++++++++++-- src/state.rs | 50 ++++++++++++++++++++++++++++++++++++--- src/tree/output.rs | 12 +++++++--- 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/src/ifs/jay_screencast.rs b/src/ifs/jay_screencast.rs index 9149c335..112a8a99 100644 --- a/src/ifs/jay_screencast.rs +++ b/src/ifs/jay_screencast.rs @@ -149,7 +149,12 @@ impl JayScreencast { }); } - pub fn copy_texture(&self, on: &OutputNode, texture: &Rc) { + pub fn copy_texture( + &self, + on: &OutputNode, + texture: &Rc, + render_hardware_cursors: bool, + ) { if !self.running.get() { return; } @@ -165,7 +170,15 @@ impl JayScreencast { let mut buffer = self.buffers.borrow_mut(); for (idx, buffer) in buffer.deref_mut().iter_mut().enumerate() { if buffer.free { - buffer.fb.copy_texture(texture, 0, 0); + self.client.state.perform_screencopy( + texture, + &buffer.fb, + on.global.preferred_scale.get(), + on.global.pos.get(), + render_hardware_cursors, + 0, + 0, + ); self.client.event(Ready { self_id: self.id, idx: idx as _, diff --git a/src/ifs/wl_output.rs b/src/ifs/wl_output.rs index b487a3f2..f1e3a70b 100644 --- a/src/ifs/wl_output.rs +++ b/src/ifs/wl_output.rs @@ -202,7 +202,12 @@ impl WlOutputGlobal { Ok(()) } - pub fn perform_screencopies(&self, fb: &dyn GfxFramebuffer, tex: &Rc) { + pub fn perform_screencopies( + &self, + fb: &dyn GfxFramebuffer, + tex: &Rc, + render_hardware_cursors: bool, + ) { if self.pending_captures.is_empty() { return; } @@ -278,7 +283,15 @@ impl WlOutputGlobal { continue; } }; - fb.copy_texture(tex, -capture.rect.x1(), -capture.rect.y1()); + self.state.perform_screencopy( + tex, + &fb, + self.preferred_scale.get(), + self.pos.get(), + render_hardware_cursors, + -capture.rect.x1(), + -capture.rect.y1(), + ); } if capture.with_damage.get() { capture.send_damage(); diff --git a/src/state.rs b/src/state.rs index 8892bf87..7db7be9e 100644 --- a/src/state.rs +++ b/src/state.rs @@ -13,6 +13,7 @@ use { cursor::{Cursor, ServerCursors}, dbus::Dbus, drm_feedback::DrmFeedback, + fixed::Fixed, forker::ForkerProxy, gfx_api::{GfxContext, GfxError, GfxFramebuffer, GfxTexture}, gfx_apis::create_gfx_context, @@ -36,9 +37,9 @@ use { leaks::Tracker, logger::Logger, rect::Rect, - renderer::RenderResult, + renderer::{renderer_base::RendererBase, RenderResult, Renderer}, scale::Scale, - theme::Theme, + theme::{Color, Theme}, tree::{ ContainerNode, ContainerSplit, Direction, DisplayNode, FloatNode, Node, NodeIds, NodeVisitorBase, OutputNode, PlaceholderNode, ToplevelNode, WorkspaceNode, @@ -752,6 +753,49 @@ impl State { fr.send_done(); let _ = fr.client.remove_obj(&*fr); } - output.perform_screencopies(&**fb, tex); + output.perform_screencopies(&**fb, tex, !render_hw_cursor); + } + + pub fn perform_screencopy( + &self, + src: &Rc, + target: &Rc, + scale: Scale, + position: Rect, + render_hardware_cursors: bool, + x_off: i32, + y_off: i32, + ) { + let mut ops = target.take_render_ops(); + let (width, height) = target.size(); + let mut renderer = Renderer { + base: RendererBase { + ops: &mut ops, + scaled: scale != 1, + scale, + scalef: scale.to_f64(), + }, + state: self, + result: None, + logical_extents: position.at_point(0, 0), + physical_extents: Rect::new_sized(0, 0, width, height).unwrap(), + }; + renderer + .base + .render_texture(src, x_off, y_off, None, None, scale, None); + if render_hardware_cursors { + for seat in self.globals.lock_seats().values() { + if let Some(cursor) = seat.get_cursor() { + let (mut x, mut y) = seat.get_position(); + if seat.hardware_cursor() { + x = x + x_off - Fixed::from_int(position.x1()); + y = y + y_off - Fixed::from_int(position.y1()); + cursor.render(&mut renderer, x, y); + } + } + } + } + let clear = target.format().has_alpha.then_some(&Color::TRANSPARENT); + target.render(ops, clear); } } diff --git a/src/tree/output.rs b/src/tree/output.rs index 8898501d..98667201 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -78,15 +78,21 @@ pub async fn output_render_data(state: Rc) { } impl OutputNode { - pub fn perform_screencopies(&self, fb: &dyn GfxFramebuffer, tex: &Rc) { + pub fn perform_screencopies( + &self, + fb: &dyn GfxFramebuffer, + tex: &Rc, + render_hardware_cursor: bool, + ) { if let Some(workspace) = self.workspace.get() { if !workspace.capture.get() { return; } } - self.global.perform_screencopies(fb, tex); + self.global + .perform_screencopies(fb, tex, render_hardware_cursor); for sc in self.screencasts.lock().values() { - sc.copy_texture(self, tex); + sc.copy_texture(self, tex, render_hardware_cursor); } }