From ed0beb8ff50f8582ae24109165819b89dde18369 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Thu, 28 Apr 2022 20:33:24 +0200 Subject: [PATCH] autocommit 2022-04-28 20:33:24 CEST --- src/backends/metal/video.rs | 66 +--------------------------- src/backends/x.rs | 22 ++++++++-- src/compositor.rs | 1 + src/ifs/wl_output.rs | 73 +++++++++++++++++++++++++++++-- src/ifs/wl_seat.rs | 1 + src/ifs/wl_seat/event_handling.rs | 1 + src/ifs/wl_seat/pointer_owner.rs | 4 ++ src/state.rs | 2 + src/tasks/connector.rs | 1 + src/tree/container.rs | 23 +++++++++- 10 files changed, 122 insertions(+), 72 deletions(-) diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 0d0ddc1f..04384e22 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -7,13 +7,9 @@ use { backends::metal::{DrmId, MetalBackend, MetalError}, edid::Descriptor, format::{Format, XRGB8888}, - ifs::{ - wl_buffer::WlBufferStorage, - wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC}, - }, + ifs::wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC}, render::{Framebuffer, RenderContext, RenderResult, Texture}, state::State, - time::Time, utils::{ asyncevent::AsyncEvent, bitflags::BitflagsExt, clonecell::CloneCell, debug_fn::debug_fn, errorfmt::ErrorFmt, numcell::NumCell, oserror::OsError, @@ -37,7 +33,6 @@ use { cell::{Cell, RefCell}, ffi::CString, fmt::{Debug, Formatter}, - ops::Deref, rc::Rc, }, uapi::c, @@ -199,64 +194,7 @@ impl MetalConnector { fr.send_done(); let _ = fr.client.remove_obj(&*fr); } - if !node.global.pending_captures.is_empty() { - let now = Time::now().unwrap(); - let mut captures = vec![]; - for capture in node.global.pending_captures.iter() { - captures.push(capture.deref().clone()); - let wl_buffer = match capture.buffer.take() { - Some(b) => b, - _ => { - log::warn!("Capture frame is pending but has no buffer attached"); - capture.send_failed(); - continue; - } - }; - if wl_buffer.destroyed() { - capture.send_failed(); - continue; - } - let rect = capture.rect; - if let WlBufferStorage::Shm { mem, .. } = &wl_buffer.storage { - let res = mem.access(|mem| { - buffer.fb.copy_to_shm( - rect.x1(), - rect.y1(), - rect.width(), - rect.height(), - XRGB8888, - mem, - ); - }); - if let Err(e) = res { - capture.client.error(e); - } - // capture.send_flags(FLAGS_Y_INVERT); - } else { - let fb = match wl_buffer.famebuffer.get() { - Some(fb) => fb, - _ => { - log::warn!("Capture buffer has no framebuffer"); - capture.send_failed(); - continue; - } - }; - fb.copy_texture( - &self.state, - &buffer.tex, - -capture.rect.x1(), - -capture.rect.y1(), - ); - } - if capture.with_damage.get() { - capture.send_damage(); - } - capture.send_ready(now.0.tv_sec as _, now.0.tv_nsec as _); - } - for capture in captures { - capture.output_link.take(); - } - } + node.global.perform_screencopies(&buffer.fb, &buffer.tex); } let mut changes = self.master.change(); changes.change_object(plane.id, |c| { diff --git a/src/backends/x.rs b/src/backends/x.rs index c1aa2ac1..40d13404 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -9,7 +9,7 @@ use { fixed::Fixed, format::XRGB8888, ifs::wl_seat::PX_PER_SCROLL, - render::{Framebuffer, RenderContext, RenderError, RenderResult}, + render::{Framebuffer, RenderContext, RenderError, RenderResult, Texture}, state::State, utils::{ clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell, @@ -87,8 +87,12 @@ pub enum XBackendError { ImportBuffer(#[source] XconError), #[error("Could not create an EGL context")] CreateEgl(#[source] RenderError), - #[error("Could not create a framebuffer from a dma-buf")] + #[error("Could not create an EGL image from a dma-buf")] + CreateImage(#[source] RenderError), + #[error("Could not create a framebuffer from an EGL image")] CreateFramebuffer(#[source] RenderError), + #[error("Could not create a texture from an EGL image")] + CreateTexture(#[source] RenderError), #[error("Could not select input events")] CannotSelectInputEvents(#[source] XconError), #[error("Could not select present events")] @@ -356,10 +360,18 @@ impl XBackend { assert!(dma.planes.len() == 1); let plane = dma.planes.first().unwrap(); let size = plane.stride * dma.height as u32; - let fb = match self.ctx.dmabuf_fb(dma) { + let img = match self.ctx.dmabuf_img(dma) { + Ok(f) => f, + Err(e) => return Err(XBackendError::CreateImage(e)), + }; + let fb = match img.to_framebuffer() { Ok(f) => f, Err(e) => return Err(XBackendError::CreateFramebuffer(e)), }; + let tex = match img.to_texture() { + Ok(f) => f, + Err(e) => return Err(XBackendError::CreateTexture(e)), + }; let pixmap = { let pfb = Dri3PixmapFromBuffer { pixmap: self.c.generate_id()?, @@ -380,6 +392,7 @@ impl XBackend { *image = Some(XImage { pixmap: Cell::new(pixmap), fb: CloneCell::new(fb), + tex: CloneCell::new(tex), idle: Cell::new(true), render_on_idle: Cell::new(false), last_serial: Cell::new(0), @@ -689,6 +702,7 @@ impl XBackend { fr.send_done(); let _ = fr.client.remove_obj(&*fr); } + node.global.perform_screencopies(&fb, &image.tex.get()); } let pp = PresentPixmap { @@ -862,6 +876,7 @@ impl XBackend { pixmap: old.pixmap.get(), }); old.fb.set(new.fb.get()); + old.tex.set(new.tex.get()); old.pixmap.set(new.pixmap.get()); } output.events.push(ConnectorEvent::ModeChanged(Mode { @@ -892,6 +907,7 @@ struct XOutput { struct XImage { pixmap: Cell, fb: CloneCell>, + tex: CloneCell>, idle: Cell, render_on_idle: Cell, last_serial: Cell, diff --git a/src/compositor.rs b/src/compositor.rs index fbaf3461..aabfbdb9 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -286,6 +286,7 @@ fn create_dummy_output(state: &Rc) { id: state.node_ids.next(), global: Rc::new(WlOutputGlobal::new( state.globals.name(), + state, &Rc::new(ConnectorData { connector: Rc::new(DummyOutput { id: state.connector_ids.next(), diff --git a/src/ifs/wl_output.rs b/src/ifs/wl_output.rs index 5c3088a7..6ea60d59 100644 --- a/src/ifs/wl_output.rs +++ b/src/ifs/wl_output.rs @@ -2,12 +2,18 @@ use { crate::{ backend, client::{Client, ClientError, ClientId}, + format::XRGB8888, globals::{Global, GlobalName}, - ifs::{zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1, zxdg_output_v1::ZxdgOutputV1}, + ifs::{ + wl_buffer::WlBufferStorage, zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1, + zxdg_output_v1::ZxdgOutputV1, + }, leaks::Tracker, object::Object, rect::Rect, - state::ConnectorData, + render::{Framebuffer, Texture}, + state::{ConnectorData, State}, + time::Time, tree::OutputNode, utils::{ buffd::{MsgParser, MsgParserError}, @@ -21,6 +27,7 @@ use { std::{ cell::{Cell, RefCell}, collections::hash_map::Entry, + ops::Deref, rc::Rc, }, thiserror::Error, @@ -59,7 +66,8 @@ const MODE_CURRENT: u32 = 1; const MODE_PREFERRED: u32 = 2; pub struct WlOutputGlobal { - name: GlobalName, + pub name: GlobalName, + pub state: Rc, pub connector: Rc, pub pos: Cell, pub manufacturer: String, @@ -76,6 +84,7 @@ pub struct WlOutputGlobal { impl WlOutputGlobal { pub fn new( name: GlobalName, + state: &Rc, connector: &Rc, x1: i32, mode: &backend::Mode, @@ -86,6 +95,7 @@ impl WlOutputGlobal { ) -> Self { Self { name, + state: state.clone(), connector: connector.clone(), pos: Cell::new(Rect::new_sized(x1, 0, mode.width, mode.height).unwrap()), manufacturer: manufacturer.to_string(), @@ -152,6 +162,63 @@ impl WlOutputGlobal { } Ok(()) } + + pub fn perform_screencopies(&self, fb: &Framebuffer, tex: &Texture) { + if self.pending_captures.is_empty() { + return; + } + let now = Time::now().unwrap(); + let mut captures = vec![]; + for capture in self.pending_captures.iter() { + captures.push(capture.deref().clone()); + let wl_buffer = match capture.buffer.take() { + Some(b) => b, + _ => { + log::warn!("Capture frame is pending but has no buffer attached"); + capture.send_failed(); + continue; + } + }; + if wl_buffer.destroyed() { + capture.send_failed(); + continue; + } + let rect = capture.rect; + if let WlBufferStorage::Shm { mem, .. } = &wl_buffer.storage { + let res = mem.access(|mem| { + fb.copy_to_shm( + rect.x1(), + rect.y1(), + rect.width(), + rect.height(), + XRGB8888, + mem, + ); + }); + if let Err(e) = res { + capture.client.error(e); + } + // capture.send_flags(FLAGS_Y_INVERT); + } else { + let fb = match wl_buffer.famebuffer.get() { + Some(fb) => fb, + _ => { + log::warn!("Capture buffer has no framebuffer"); + capture.send_failed(); + continue; + } + }; + fb.copy_texture(&self.state, tex, -capture.rect.x1(), -capture.rect.y1()); + } + if capture.with_damage.get() { + capture.send_damage(); + } + capture.send_ready(now.0.tv_sec as _, now.0.tv_nsec as _); + } + for capture in captures { + capture.output_link.take(); + } + } } global_base!(WlOutputGlobal, WlOutput, WlOutputError); diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index b67c8917..6e1a9e87 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -188,6 +188,7 @@ impl WlSeatGlobal { seat.tree_changed.triggered().await; seat.state.tree_changed_sent.set(false); seat.changes.or_assign(CHANGE_TREE); + // log::info!("tree_changed"); seat.apply_changes(); } }); diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index 0154dc0f..03a2a071 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -422,6 +422,7 @@ impl WlSeatGlobal { } pub fn trigger_tree_changed(&self) { + // log::info!("trigger_tree_changed"); self.tree_changed.trigger(); } diff --git a/src/ifs/wl_seat/pointer_owner.rs b/src/ifs/wl_seat/pointer_owner.rs index d255a7a9..d96023f3 100644 --- a/src/ifs/wl_seat/pointer_owner.rs +++ b/src/ifs/wl_seat/pointer_owner.rs @@ -260,6 +260,7 @@ impl PointerOwner for GrabPointerOwner { self.buttons.remove(&button); if self.buttons.is_empty() { self.node.node_seat_state().remove_pointer_grab(seat); + // log::info!("button"); seat.tree_changed.trigger(); seat.pointer_owner .owner @@ -284,6 +285,7 @@ impl PointerOwner for GrabPointerOwner { let (x, y) = seat.pos.get(); let pos = self.node.node_absolute_position(); let (x_int, y_int) = pos.translate(x.round_down(), y.round_down()); + // log::info!("apply_changes"); self.node .clone() .node_on_pointer_motion(seat, x.apply_fract(x_int), y.apply_fract(y_int)); @@ -400,6 +402,7 @@ impl PointerOwner for DndPointerOwner { seat.pointer_owner .owner .set(seat.pointer_owner.default.clone()); + // log::info!("button2"); seat.tree_changed.trigger(); } @@ -472,6 +475,7 @@ impl PointerOwner for DndPointerOwner { seat.pointer_owner .owner .set(seat.pointer_owner.default.clone()); + // log::info!("cancel_dnd"); seat.tree_changed.trigger(); } diff --git a/src/state.rs b/src/state.rs index 96c9d4bd..6e91596a 100644 --- a/src/state.rs +++ b/src/state.rs @@ -175,6 +175,7 @@ impl State { struct Walker; impl NodeVisitorBase for Walker { fn visit_container(&mut self, node: &Rc) { + // log::info!("set_render_ctx"); node.schedule_compute_render_data(); node.node_visit_children(self); } @@ -204,6 +205,7 @@ impl State { } pub fn tree_changed(&self) { + // log::info!("state.tree_changed\n{:?}", Backtrace::new()); if self.tree_changed_sent.replace(true) { return; } diff --git a/src/tasks/connector.rs b/src/tasks/connector.rs index bc82faf3..b63bac6b 100644 --- a/src/tasks/connector.rs +++ b/src/tasks/connector.rs @@ -78,6 +78,7 @@ impl ConnectorHandler { .unwrap_or(0); let global = Rc::new(WlOutputGlobal::new( name, + &self.state, &self.data, x1, &info.initial_mode, diff --git a/src/tree/container.rs b/src/tree/container.rs index 896d3a8b..215f5445 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -315,6 +315,7 @@ impl ContainerNode { if self.mono_child.get().is_some() { self.activate_child(&new_ref); } + // log::info!("add_child"); self.schedule_layout(); self.cancel_seat_ops(); } @@ -328,10 +329,12 @@ impl ContainerNode { pub fn on_spaces_changed(self: &Rc) { self.update_content_size(); + // log::info!("on_spaces_changed"); self.schedule_layout(); } pub fn on_colors_changed(self: &Rc) { + // log::info!("on_colors_changed"); self.schedule_compute_render_data(); } @@ -352,6 +355,7 @@ impl ContainerNode { self.perform_split_layout(); } self.state.tree_changed(); + // log::info!("perform_layout"); self.schedule_compute_render_data(); } @@ -513,8 +517,12 @@ impl ContainerNode { y, op: None, }); - seat_state.x = x; - seat_state.y = y; + let mut changed = false; + changed |= mem::replace(&mut seat_state.x, x) != x; + changed |= mem::replace(&mut seat_state.y, y) != y; + if !changed { + return; + } if let Some(op) = &seat_state.op { match op.kind { SeatOpKind::Move => { @@ -556,6 +564,7 @@ impl ContainerNode { prev.factor.set(prev_factor); op.child.factor.set(child_factor); self.sum_factors.set(sum_factors); + // log::info!("pointer_move"); self.schedule_layout(); } } @@ -708,6 +717,7 @@ impl ContainerNode { } self.mono_child.set(Some(child.clone())); child.node.tl_set_visible(true); + // log::info!("activate_child2"); self.schedule_layout(); } else { } @@ -753,6 +763,7 @@ impl ContainerNode { } } self.mono_child.set(child); + // log::info!("set_mono"); self.schedule_layout(); self.update_title(); } @@ -760,6 +771,7 @@ impl ContainerNode { pub fn set_split(self: &Rc, split: ContainerSplit) { if self.split.replace(split) != split { self.update_content_size(); + // log::info!("set_split"); self.schedule_layout(); self.update_title(); } @@ -856,6 +868,7 @@ impl ContainerNode { true => neighbor.prepend_existing(&cc), false => neighbor.append_existing(&cc), } + // log::info!("move_child"); self.schedule_layout(); return; } @@ -967,6 +980,7 @@ impl Node for ContainerNode { ct.push_str(title); } self.update_title(); + // log::info!("node_child_title_changed"); self.schedule_compute_render_data(); } @@ -1048,6 +1062,7 @@ impl Node for ContainerNode { node.focus_history .set(Some(self.focus_history.add_last(node.clone()))); } + // log::info!("node_child_active_changed"); self.schedule_compute_render_data(); self.parent .get() @@ -1164,6 +1179,7 @@ impl Node for ContainerNode { } fn node_on_pointer_enter(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { + // log::info!("node_on_pointer_enter"); self.pointer_move(seat, x.round_down(), y.round_down()); } @@ -1183,6 +1199,7 @@ impl Node for ContainerNode { } fn node_on_pointer_motion(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { + // log::info!("node_on_pointer_motion"); self.pointer_move(seat, x.round_down(), y.round_down()); } @@ -1293,6 +1310,7 @@ impl ContainingNode for ContainerNode { } self.sum_factors.set(sum); self.update_title(); + // log::info!("cnode_remove_child2"); self.schedule_layout(); self.cancel_seat_ops(); } @@ -1336,6 +1354,7 @@ impl ToplevelNode for ContainerNode { size_changed |= self.height.replace(rect.height()) != rect.height(); if size_changed { self.update_content_size(); + // log::info!("tl_change_extents"); self.perform_layout(); self.cancel_seat_ops(); self.parent