1
0
Fork 0
forked from wry/wry

autocommit 2022-04-28 20:33:24 CEST

This commit is contained in:
Julian Orth 2022-04-28 20:33:24 +02:00
parent 1242a6c1e1
commit ed0beb8ff5
10 changed files with 122 additions and 72 deletions

View file

@ -7,13 +7,9 @@ use {
backends::metal::{DrmId, MetalBackend, MetalError}, backends::metal::{DrmId, MetalBackend, MetalError},
edid::Descriptor, edid::Descriptor,
format::{Format, XRGB8888}, format::{Format, XRGB8888},
ifs::{ ifs::wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC},
wl_buffer::WlBufferStorage,
wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC},
},
render::{Framebuffer, RenderContext, RenderResult, Texture}, render::{Framebuffer, RenderContext, RenderResult, Texture},
state::State, state::State,
time::Time,
utils::{ utils::{
asyncevent::AsyncEvent, bitflags::BitflagsExt, clonecell::CloneCell, asyncevent::AsyncEvent, bitflags::BitflagsExt, clonecell::CloneCell,
debug_fn::debug_fn, errorfmt::ErrorFmt, numcell::NumCell, oserror::OsError, debug_fn::debug_fn, errorfmt::ErrorFmt, numcell::NumCell, oserror::OsError,
@ -37,7 +33,6 @@ use {
cell::{Cell, RefCell}, cell::{Cell, RefCell},
ffi::CString, ffi::CString,
fmt::{Debug, Formatter}, fmt::{Debug, Formatter},
ops::Deref,
rc::Rc, rc::Rc,
}, },
uapi::c, uapi::c,
@ -199,64 +194,7 @@ impl MetalConnector {
fr.send_done(); fr.send_done();
let _ = fr.client.remove_obj(&*fr); let _ = fr.client.remove_obj(&*fr);
} }
if !node.global.pending_captures.is_empty() { node.global.perform_screencopies(&buffer.fb, &buffer.tex);
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();
}
}
} }
let mut changes = self.master.change(); let mut changes = self.master.change();
changes.change_object(plane.id, |c| { changes.change_object(plane.id, |c| {

View file

@ -9,7 +9,7 @@ use {
fixed::Fixed, fixed::Fixed,
format::XRGB8888, format::XRGB8888,
ifs::wl_seat::PX_PER_SCROLL, ifs::wl_seat::PX_PER_SCROLL,
render::{Framebuffer, RenderContext, RenderError, RenderResult}, render::{Framebuffer, RenderContext, RenderError, RenderResult, Texture},
state::State, state::State,
utils::{ utils::{
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell, clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell,
@ -87,8 +87,12 @@ pub enum XBackendError {
ImportBuffer(#[source] XconError), ImportBuffer(#[source] XconError),
#[error("Could not create an EGL context")] #[error("Could not create an EGL context")]
CreateEgl(#[source] RenderError), 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), CreateFramebuffer(#[source] RenderError),
#[error("Could not create a texture from an EGL image")]
CreateTexture(#[source] RenderError),
#[error("Could not select input events")] #[error("Could not select input events")]
CannotSelectInputEvents(#[source] XconError), CannotSelectInputEvents(#[source] XconError),
#[error("Could not select present events")] #[error("Could not select present events")]
@ -356,10 +360,18 @@ impl XBackend {
assert!(dma.planes.len() == 1); assert!(dma.planes.len() == 1);
let plane = dma.planes.first().unwrap(); let plane = dma.planes.first().unwrap();
let size = plane.stride * dma.height as u32; 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, Ok(f) => f,
Err(e) => return Err(XBackendError::CreateFramebuffer(e)), 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 pixmap = {
let pfb = Dri3PixmapFromBuffer { let pfb = Dri3PixmapFromBuffer {
pixmap: self.c.generate_id()?, pixmap: self.c.generate_id()?,
@ -380,6 +392,7 @@ impl XBackend {
*image = Some(XImage { *image = Some(XImage {
pixmap: Cell::new(pixmap), pixmap: Cell::new(pixmap),
fb: CloneCell::new(fb), fb: CloneCell::new(fb),
tex: CloneCell::new(tex),
idle: Cell::new(true), idle: Cell::new(true),
render_on_idle: Cell::new(false), render_on_idle: Cell::new(false),
last_serial: Cell::new(0), last_serial: Cell::new(0),
@ -689,6 +702,7 @@ impl XBackend {
fr.send_done(); fr.send_done();
let _ = fr.client.remove_obj(&*fr); let _ = fr.client.remove_obj(&*fr);
} }
node.global.perform_screencopies(&fb, &image.tex.get());
} }
let pp = PresentPixmap { let pp = PresentPixmap {
@ -862,6 +876,7 @@ impl XBackend {
pixmap: old.pixmap.get(), pixmap: old.pixmap.get(),
}); });
old.fb.set(new.fb.get()); old.fb.set(new.fb.get());
old.tex.set(new.tex.get());
old.pixmap.set(new.pixmap.get()); old.pixmap.set(new.pixmap.get());
} }
output.events.push(ConnectorEvent::ModeChanged(Mode { output.events.push(ConnectorEvent::ModeChanged(Mode {
@ -892,6 +907,7 @@ struct XOutput {
struct XImage { struct XImage {
pixmap: Cell<u32>, pixmap: Cell<u32>,
fb: CloneCell<Rc<Framebuffer>>, fb: CloneCell<Rc<Framebuffer>>,
tex: CloneCell<Rc<Texture>>,
idle: Cell<bool>, idle: Cell<bool>,
render_on_idle: Cell<bool>, render_on_idle: Cell<bool>,
last_serial: Cell<u32>, last_serial: Cell<u32>,

View file

@ -286,6 +286,7 @@ fn create_dummy_output(state: &Rc<State>) {
id: state.node_ids.next(), id: state.node_ids.next(),
global: Rc::new(WlOutputGlobal::new( global: Rc::new(WlOutputGlobal::new(
state.globals.name(), state.globals.name(),
state,
&Rc::new(ConnectorData { &Rc::new(ConnectorData {
connector: Rc::new(DummyOutput { connector: Rc::new(DummyOutput {
id: state.connector_ids.next(), id: state.connector_ids.next(),

View file

@ -2,12 +2,18 @@ use {
crate::{ crate::{
backend, backend,
client::{Client, ClientError, ClientId}, client::{Client, ClientError, ClientId},
format::XRGB8888,
globals::{Global, GlobalName}, 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, leaks::Tracker,
object::Object, object::Object,
rect::Rect, rect::Rect,
state::ConnectorData, render::{Framebuffer, Texture},
state::{ConnectorData, State},
time::Time,
tree::OutputNode, tree::OutputNode,
utils::{ utils::{
buffd::{MsgParser, MsgParserError}, buffd::{MsgParser, MsgParserError},
@ -21,6 +27,7 @@ use {
std::{ std::{
cell::{Cell, RefCell}, cell::{Cell, RefCell},
collections::hash_map::Entry, collections::hash_map::Entry,
ops::Deref,
rc::Rc, rc::Rc,
}, },
thiserror::Error, thiserror::Error,
@ -59,7 +66,8 @@ const MODE_CURRENT: u32 = 1;
const MODE_PREFERRED: u32 = 2; const MODE_PREFERRED: u32 = 2;
pub struct WlOutputGlobal { pub struct WlOutputGlobal {
name: GlobalName, pub name: GlobalName,
pub state: Rc<State>,
pub connector: Rc<ConnectorData>, pub connector: Rc<ConnectorData>,
pub pos: Cell<Rect>, pub pos: Cell<Rect>,
pub manufacturer: String, pub manufacturer: String,
@ -76,6 +84,7 @@ pub struct WlOutputGlobal {
impl WlOutputGlobal { impl WlOutputGlobal {
pub fn new( pub fn new(
name: GlobalName, name: GlobalName,
state: &Rc<State>,
connector: &Rc<ConnectorData>, connector: &Rc<ConnectorData>,
x1: i32, x1: i32,
mode: &backend::Mode, mode: &backend::Mode,
@ -86,6 +95,7 @@ impl WlOutputGlobal {
) -> Self { ) -> Self {
Self { Self {
name, name,
state: state.clone(),
connector: connector.clone(), connector: connector.clone(),
pos: Cell::new(Rect::new_sized(x1, 0, mode.width, mode.height).unwrap()), pos: Cell::new(Rect::new_sized(x1, 0, mode.width, mode.height).unwrap()),
manufacturer: manufacturer.to_string(), manufacturer: manufacturer.to_string(),
@ -152,6 +162,63 @@ impl WlOutputGlobal {
} }
Ok(()) 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); global_base!(WlOutputGlobal, WlOutput, WlOutputError);

View file

@ -188,6 +188,7 @@ impl WlSeatGlobal {
seat.tree_changed.triggered().await; seat.tree_changed.triggered().await;
seat.state.tree_changed_sent.set(false); seat.state.tree_changed_sent.set(false);
seat.changes.or_assign(CHANGE_TREE); seat.changes.or_assign(CHANGE_TREE);
// log::info!("tree_changed");
seat.apply_changes(); seat.apply_changes();
} }
}); });

View file

@ -422,6 +422,7 @@ impl WlSeatGlobal {
} }
pub fn trigger_tree_changed(&self) { pub fn trigger_tree_changed(&self) {
// log::info!("trigger_tree_changed");
self.tree_changed.trigger(); self.tree_changed.trigger();
} }

View file

@ -260,6 +260,7 @@ impl PointerOwner for GrabPointerOwner {
self.buttons.remove(&button); self.buttons.remove(&button);
if self.buttons.is_empty() { if self.buttons.is_empty() {
self.node.node_seat_state().remove_pointer_grab(seat); self.node.node_seat_state().remove_pointer_grab(seat);
// log::info!("button");
seat.tree_changed.trigger(); seat.tree_changed.trigger();
seat.pointer_owner seat.pointer_owner
.owner .owner
@ -284,6 +285,7 @@ impl PointerOwner for GrabPointerOwner {
let (x, y) = seat.pos.get(); let (x, y) = seat.pos.get();
let pos = self.node.node_absolute_position(); let pos = self.node.node_absolute_position();
let (x_int, y_int) = pos.translate(x.round_down(), y.round_down()); let (x_int, y_int) = pos.translate(x.round_down(), y.round_down());
// log::info!("apply_changes");
self.node self.node
.clone() .clone()
.node_on_pointer_motion(seat, x.apply_fract(x_int), y.apply_fract(y_int)); .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 seat.pointer_owner
.owner .owner
.set(seat.pointer_owner.default.clone()); .set(seat.pointer_owner.default.clone());
// log::info!("button2");
seat.tree_changed.trigger(); seat.tree_changed.trigger();
} }
@ -472,6 +475,7 @@ impl PointerOwner for DndPointerOwner {
seat.pointer_owner seat.pointer_owner
.owner .owner
.set(seat.pointer_owner.default.clone()); .set(seat.pointer_owner.default.clone());
// log::info!("cancel_dnd");
seat.tree_changed.trigger(); seat.tree_changed.trigger();
} }

View file

@ -175,6 +175,7 @@ impl State {
struct Walker; struct Walker;
impl NodeVisitorBase for Walker { impl NodeVisitorBase for Walker {
fn visit_container(&mut self, node: &Rc<ContainerNode>) { fn visit_container(&mut self, node: &Rc<ContainerNode>) {
// log::info!("set_render_ctx");
node.schedule_compute_render_data(); node.schedule_compute_render_data();
node.node_visit_children(self); node.node_visit_children(self);
} }
@ -204,6 +205,7 @@ impl State {
} }
pub fn tree_changed(&self) { pub fn tree_changed(&self) {
// log::info!("state.tree_changed\n{:?}", Backtrace::new());
if self.tree_changed_sent.replace(true) { if self.tree_changed_sent.replace(true) {
return; return;
} }

View file

@ -78,6 +78,7 @@ impl ConnectorHandler {
.unwrap_or(0); .unwrap_or(0);
let global = Rc::new(WlOutputGlobal::new( let global = Rc::new(WlOutputGlobal::new(
name, name,
&self.state,
&self.data, &self.data,
x1, x1,
&info.initial_mode, &info.initial_mode,

View file

@ -315,6 +315,7 @@ impl ContainerNode {
if self.mono_child.get().is_some() { if self.mono_child.get().is_some() {
self.activate_child(&new_ref); self.activate_child(&new_ref);
} }
// log::info!("add_child");
self.schedule_layout(); self.schedule_layout();
self.cancel_seat_ops(); self.cancel_seat_ops();
} }
@ -328,10 +329,12 @@ impl ContainerNode {
pub fn on_spaces_changed(self: &Rc<Self>) { pub fn on_spaces_changed(self: &Rc<Self>) {
self.update_content_size(); self.update_content_size();
// log::info!("on_spaces_changed");
self.schedule_layout(); self.schedule_layout();
} }
pub fn on_colors_changed(self: &Rc<Self>) { pub fn on_colors_changed(self: &Rc<Self>) {
// log::info!("on_colors_changed");
self.schedule_compute_render_data(); self.schedule_compute_render_data();
} }
@ -352,6 +355,7 @@ impl ContainerNode {
self.perform_split_layout(); self.perform_split_layout();
} }
self.state.tree_changed(); self.state.tree_changed();
// log::info!("perform_layout");
self.schedule_compute_render_data(); self.schedule_compute_render_data();
} }
@ -513,8 +517,12 @@ impl ContainerNode {
y, y,
op: None, op: None,
}); });
seat_state.x = x; let mut changed = false;
seat_state.y = y; 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 { if let Some(op) = &seat_state.op {
match op.kind { match op.kind {
SeatOpKind::Move => { SeatOpKind::Move => {
@ -556,6 +564,7 @@ impl ContainerNode {
prev.factor.set(prev_factor); prev.factor.set(prev_factor);
op.child.factor.set(child_factor); op.child.factor.set(child_factor);
self.sum_factors.set(sum_factors); self.sum_factors.set(sum_factors);
// log::info!("pointer_move");
self.schedule_layout(); self.schedule_layout();
} }
} }
@ -708,6 +717,7 @@ impl ContainerNode {
} }
self.mono_child.set(Some(child.clone())); self.mono_child.set(Some(child.clone()));
child.node.tl_set_visible(true); child.node.tl_set_visible(true);
// log::info!("activate_child2");
self.schedule_layout(); self.schedule_layout();
} else { } else {
} }
@ -753,6 +763,7 @@ impl ContainerNode {
} }
} }
self.mono_child.set(child); self.mono_child.set(child);
// log::info!("set_mono");
self.schedule_layout(); self.schedule_layout();
self.update_title(); self.update_title();
} }
@ -760,6 +771,7 @@ impl ContainerNode {
pub fn set_split(self: &Rc<Self>, split: ContainerSplit) { pub fn set_split(self: &Rc<Self>, split: ContainerSplit) {
if self.split.replace(split) != split { if self.split.replace(split) != split {
self.update_content_size(); self.update_content_size();
// log::info!("set_split");
self.schedule_layout(); self.schedule_layout();
self.update_title(); self.update_title();
} }
@ -856,6 +868,7 @@ impl ContainerNode {
true => neighbor.prepend_existing(&cc), true => neighbor.prepend_existing(&cc),
false => neighbor.append_existing(&cc), false => neighbor.append_existing(&cc),
} }
// log::info!("move_child");
self.schedule_layout(); self.schedule_layout();
return; return;
} }
@ -967,6 +980,7 @@ impl Node for ContainerNode {
ct.push_str(title); ct.push_str(title);
} }
self.update_title(); self.update_title();
// log::info!("node_child_title_changed");
self.schedule_compute_render_data(); self.schedule_compute_render_data();
} }
@ -1048,6 +1062,7 @@ impl Node for ContainerNode {
node.focus_history node.focus_history
.set(Some(self.focus_history.add_last(node.clone()))); .set(Some(self.focus_history.add_last(node.clone())));
} }
// log::info!("node_child_active_changed");
self.schedule_compute_render_data(); self.schedule_compute_render_data();
self.parent self.parent
.get() .get()
@ -1164,6 +1179,7 @@ impl Node for ContainerNode {
} }
fn node_on_pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) { fn node_on_pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
// log::info!("node_on_pointer_enter");
self.pointer_move(seat, x.round_down(), y.round_down()); 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<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) { fn node_on_pointer_motion(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
// log::info!("node_on_pointer_motion");
self.pointer_move(seat, x.round_down(), y.round_down()); self.pointer_move(seat, x.round_down(), y.round_down());
} }
@ -1293,6 +1310,7 @@ impl ContainingNode for ContainerNode {
} }
self.sum_factors.set(sum); self.sum_factors.set(sum);
self.update_title(); self.update_title();
// log::info!("cnode_remove_child2");
self.schedule_layout(); self.schedule_layout();
self.cancel_seat_ops(); self.cancel_seat_ops();
} }
@ -1336,6 +1354,7 @@ impl ToplevelNode for ContainerNode {
size_changed |= self.height.replace(rect.height()) != rect.height(); size_changed |= self.height.replace(rect.height()) != rect.height();
if size_changed { if size_changed {
self.update_content_size(); self.update_content_size();
// log::info!("tl_change_extents");
self.perform_layout(); self.perform_layout();
self.cancel_seat_ops(); self.cancel_seat_ops();
self.parent self.parent