1
0
Fork 0
forked from wry/wry

Merge pull request #94 from mahkoh/jorth/fix-screencopies

video: unify output rendering
This commit is contained in:
mahkoh 2024-02-16 19:28:28 +01:00 committed by GitHub
commit 439befcf78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 132 additions and 48 deletions

View file

@ -380,22 +380,16 @@ impl MetalConnector {
if let Some(node) = self.state.root.outputs.get(&self.connector_id) { if let Some(node) = self.state.root.outputs.get(&self.connector_id) {
let mut rr = self.render_result.borrow_mut(); let mut rr = self.render_result.borrow_mut();
let render_fb = buffer.render_fb(); let render_fb = buffer.render_fb();
render_fb.render_node( self.state.present_output(
&*node, &node,
&self.state, &render_fb,
Some(node.global.pos.get()), &buffer.render_tex,
Some(&mut rr), &mut rr,
node.preferred_scale.get(),
!self.cursor_enabled.get(), !self.cursor_enabled.get(),
); );
if let Some(tex) = &buffer.dev_tex { if let Some(tex) = &buffer.dev_tex {
buffer.dev_fb.copy_texture(tex, 0, 0); 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| { changes.change_object(plane.id, |c| {
c.change(plane.fb_id, buffer.drm.id().0 as _); c.change(plane.fb_id, buffer.drm.id().0 as _);

View file

@ -57,7 +57,6 @@ use {
collections::VecDeque, collections::VecDeque,
error::Error, error::Error,
future::pending, future::pending,
ops::DerefMut,
rc::Rc, rc::Rc,
}, },
thiserror::Error, thiserror::Error,
@ -733,21 +732,13 @@ impl XBackend {
image.last_serial.set(serial); image.last_serial.set(serial);
if let Some(node) = self.state.root.outputs.get(&output.id) { if let Some(node) = self.state.root.outputs.get(&output.id) {
let mut rr = self.render_result.borrow_mut(); self.state.present_output(
let fb = image.fb.get(); &node,
fb.render_node( &image.fb.get(),
&*node, &image.tex.get(),
&self.state, &mut self.render_result.borrow_mut(),
Some(node.global.pos.get()),
Some(rr.deref_mut()),
node.preferred_scale.get(),
true, 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 { let pp = PresentPixmap {

View file

@ -392,7 +392,6 @@ fn create_dummy_output(state: &Rc<State>) {
scroll: Default::default(), scroll: Default::default(),
pointer_positions: Default::default(), pointer_positions: Default::default(),
lock_surface: Default::default(), lock_surface: Default::default(),
preferred_scale: Cell::new(Scale::from_int(1)),
hardware_cursor: Default::default(), hardware_cursor: Default::default(),
update_render_data_scheduled: Cell::new(false), update_render_data_scheduled: Cell::new(false),
screencasts: Default::default(), screencasts: Default::default(),

View file

@ -717,7 +717,7 @@ impl ConfigProxyHandler {
fn handle_connector_get_scale(&self, connector: Connector) -> Result<(), CphError> { fn handle_connector_get_scale(&self, connector: Connector) -> Result<(), CphError> {
let connector = self.get_output(connector)?; let connector = self.get_output(connector)?;
self.respond(Response::ConnectorGetScale { self.respond(Response::ConnectorGetScale {
scale: connector.node.preferred_scale.get().to_f64(), scale: connector.node.global.preferred_scale.get().to_f64(),
}); });
Ok(()) Ok(())
} }

View file

@ -149,7 +149,12 @@ impl JayScreencast {
}); });
} }
pub fn copy_texture(&self, on: &OutputNode, texture: &Rc<dyn GfxTexture>) { pub fn copy_texture(
&self,
on: &OutputNode,
texture: &Rc<dyn GfxTexture>,
render_hardware_cursors: bool,
) {
if !self.running.get() { if !self.running.get() {
return; return;
} }
@ -165,7 +170,15 @@ impl JayScreencast {
let mut buffer = self.buffers.borrow_mut(); let mut buffer = self.buffers.borrow_mut();
for (idx, buffer) in buffer.deref_mut().iter_mut().enumerate() { for (idx, buffer) in buffer.deref_mut().iter_mut().enumerate() {
if buffer.free { 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.client.event(Ready {
self_id: self.id, self_id: self.id,
idx: idx as _, idx: idx as _,

View file

@ -74,6 +74,7 @@ pub struct WlOutputGlobal {
pub pending_captures: LinkedList<Rc<ZwlrScreencopyFrameV1>>, pub pending_captures: LinkedList<Rc<ZwlrScreencopyFrameV1>>,
pub destroyed: Cell<bool>, pub destroyed: Cell<bool>,
pub legacy_scale: Cell<u32>, pub legacy_scale: Cell<u32>,
pub preferred_scale: Cell<crate::scale::Scale>,
} }
#[derive(Eq, PartialEq)] #[derive(Eq, PartialEq)]
@ -120,6 +121,7 @@ impl WlOutputGlobal {
pending_captures: Default::default(), pending_captures: Default::default(),
destroyed: Cell::new(false), destroyed: Cell::new(false),
legacy_scale: Cell::new(1), legacy_scale: Cell::new(1),
preferred_scale: Cell::new(crate::scale::Scale::from_int(1)),
} }
} }
@ -200,7 +202,12 @@ impl WlOutputGlobal {
Ok(()) Ok(())
} }
pub fn perform_screencopies(&self, fb: &dyn GfxFramebuffer, tex: &Rc<dyn GfxTexture>) { pub fn perform_screencopies(
&self,
fb: &dyn GfxFramebuffer,
tex: &Rc<dyn GfxTexture>,
render_hardware_cursors: bool,
) {
if self.pending_captures.is_empty() { if self.pending_captures.is_empty() {
return; return;
} }
@ -276,7 +283,15 @@ impl WlOutputGlobal {
continue; 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() { if capture.with_damage.get() {
capture.send_damage(); capture.send_damage();

View file

@ -265,7 +265,7 @@ impl WlSeatGlobal {
for output in self.state.root.outputs.lock().values() { for output in self.state.root.outputs.lock().values() {
if let Some(hc) = output.hardware_cursor.get() { if let Some(hc) = output.hardware_cursor.get() {
let render = render | output.hardware_cursor_needs_render.take(); 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); let extents = cursor.extents_at_scale(scale);
if render { if render {
let (max_width, max_height) = hc.max_size(); let (max_width, max_height) = hc.max_size();

View file

@ -438,7 +438,7 @@ impl WlSurface {
} }
output.global.send_enter(self); output.global.send_enter(self);
old.global.send_leave(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(); self.on_scale_change();
} }
let children = self.children.borrow_mut(); let children = self.children.borrow_mut();

View file

@ -39,7 +39,7 @@ impl WpFractionalScaleV1 {
pub fn send_preferred_scale(&self) { pub fn send_preferred_scale(&self) {
self.client.event(PreferredScale { self.client.event(PreferredScale {
self_id: self.id, self_id: self.id,
scale: self.surface.output.get().preferred_scale.get().0, scale: self.surface.output.get().global.preferred_scale.get().0,
}); });
} }

View file

@ -139,7 +139,7 @@ impl Renderer<'_> {
let c = theme.colors.attention_requested_background.get(); let c = theme.colors.attention_requested_background.get();
self.base self.base
.fill_boxes2(&rd.attention_requested_workspaces, &c, x, y); .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 { for title in &rd.titles {
let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y); let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y);
self.base self.base

View file

@ -13,8 +13,9 @@ use {
cursor::{Cursor, ServerCursors}, cursor::{Cursor, ServerCursors},
dbus::Dbus, dbus::Dbus,
drm_feedback::DrmFeedback, drm_feedback::DrmFeedback,
fixed::Fixed,
forker::ForkerProxy, forker::ForkerProxy,
gfx_api::{GfxContext, GfxError}, gfx_api::{GfxContext, GfxError, GfxFramebuffer, GfxTexture},
gfx_apis::create_gfx_context, gfx_apis::create_gfx_context,
globals::{Globals, GlobalsError, WaylandGlobal}, globals::{Globals, GlobalsError, WaylandGlobal},
ifs::{ ifs::{
@ -36,8 +37,9 @@ use {
leaks::Tracker, leaks::Tracker,
logger::Logger, logger::Logger,
rect::Rect, rect::Rect,
renderer::{renderer_base::RendererBase, RenderResult, Renderer},
scale::Scale, scale::Scale,
theme::Theme, theme::{Color, Theme},
tree::{ tree::{
ContainerNode, ContainerSplit, Direction, DisplayNode, FloatNode, Node, NodeIds, ContainerNode, ContainerSplit, Direction, DisplayNode, FloatNode, Node, NodeIds,
NodeVisitorBase, OutputNode, PlaceholderNode, ToplevelNode, WorkspaceNode, NodeVisitorBase, OutputNode, PlaceholderNode, ToplevelNode, WorkspaceNode,
@ -730,4 +732,70 @@ impl State {
f(tester); f(tester);
} }
} }
pub fn present_output(
&self,
output: &OutputNode,
fb: &Rc<dyn GfxFramebuffer>,
tex: &Rc<dyn GfxTexture>,
rr: &mut RenderResult,
render_hw_cursor: bool,
) {
fb.render_node(
output,
self,
Some(output.global.pos.get()),
Some(rr),
output.global.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, !render_hw_cursor);
}
pub fn perform_screencopy(
&self,
src: &Rc<dyn GfxTexture>,
target: &Rc<dyn GfxFramebuffer>,
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);
}
} }

View file

@ -2,7 +2,6 @@ use {
crate::{ crate::{
backend::{Connector, ConnectorEvent, ConnectorId, MonitorInfo}, backend::{Connector, ConnectorEvent, ConnectorId, MonitorInfo},
ifs::wl_output::WlOutputGlobal, ifs::wl_output::WlOutputGlobal,
scale::Scale,
state::{ConnectorData, OutputData, State}, state::{ConnectorData, OutputData, State},
tree::{OutputNode, OutputRenderData}, tree::{OutputNode, OutputRenderData},
utils::{asyncevent::AsyncEvent, clonecell::CloneCell}, utils::{asyncevent::AsyncEvent, clonecell::CloneCell},
@ -124,14 +123,13 @@ impl ConnectorHandler {
scroll: Default::default(), scroll: Default::default(),
pointer_positions: Default::default(), pointer_positions: Default::default(),
lock_surface: Default::default(), lock_surface: Default::default(),
preferred_scale: Cell::new(Scale::from_int(1)),
hardware_cursor: Default::default(), hardware_cursor: Default::default(),
jay_outputs: Default::default(), jay_outputs: Default::default(),
screencasts: Default::default(), screencasts: Default::default(),
update_render_data_scheduled: Cell::new(false), update_render_data_scheduled: Cell::new(false),
hardware_cursor_needs_render: 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 mode = info.initial_mode;
let output_data = Rc::new(OutputData { let output_data = Rc::new(OutputData {
connector: self.data.clone(), connector: self.data.clone(),
@ -278,7 +276,8 @@ impl ConnectorHandler {
if let Some(dev) = &self.data.drm_dev { if let Some(dev) = &self.data.drm_dev {
dev.connectors.remove(&self.id); 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); let _ = self.state.remove_global(&*global);
} }
} }

View file

@ -59,7 +59,6 @@ pub struct OutputNode {
pub scroll: Scroller, pub scroll: Scroller,
pub pointer_positions: CopyHashMap<SeatId, (i32, i32)>, pub pointer_positions: CopyHashMap<SeatId, (i32, i32)>,
pub lock_surface: CloneCell<Option<Rc<ExtSessionLockSurfaceV1>>>, pub lock_surface: CloneCell<Option<Rc<ExtSessionLockSurfaceV1>>>,
pub preferred_scale: Cell<Scale>,
pub hardware_cursor: CloneCell<Option<Rc<dyn HardwareCursor>>>, pub hardware_cursor: CloneCell<Option<Rc<dyn HardwareCursor>>>,
pub hardware_cursor_needs_render: Cell<bool>, pub hardware_cursor_needs_render: Cell<bool>,
pub update_render_data_scheduled: Cell<bool>, pub update_render_data_scheduled: Cell<bool>,
@ -79,15 +78,21 @@ pub async fn output_render_data(state: Rc<State>) {
} }
impl OutputNode { impl OutputNode {
pub fn perform_screencopies(&self, fb: &dyn GfxFramebuffer, tex: &Rc<dyn GfxTexture>) { pub fn perform_screencopies(
&self,
fb: &dyn GfxFramebuffer,
tex: &Rc<dyn GfxTexture>,
render_hardware_cursor: bool,
) {
if let Some(workspace) = self.workspace.get() { if let Some(workspace) = self.workspace.get() {
if !workspace.capture.get() { if !workspace.capture.get() {
return; return;
} }
} }
self.global.perform_screencopies(fb, tex); self.global
.perform_screencopies(fb, tex, render_hardware_cursor);
for sc in self.screencasts.lock().values() { for sc in self.screencasts.lock().values() {
sc.copy_texture(self, tex); sc.copy_texture(self, tex, render_hardware_cursor);
} }
} }
@ -111,7 +116,7 @@ impl OutputNode {
} }
pub fn set_preferred_scale(self: &Rc<Self>, scale: Scale) { pub fn set_preferred_scale(self: &Rc<Self>, scale: Scale) {
let old_scale = self.preferred_scale.replace(scale); let old_scale = self.global.preferred_scale.replace(scale);
if scale == old_scale { if scale == old_scale {
return; return;
} }
@ -152,7 +157,7 @@ impl OutputNode {
let font = self.state.theme.font.borrow_mut(); let font = self.state.theme.font.borrow_mut();
let theme = &self.state.theme; let theme = &self.state.theme;
let th = theme.sizes.title_height.get(); 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 { let scale = if scale != 1 {
Some(scale.to_f64()) Some(scale.to_f64())
} else { } else {
@ -410,7 +415,7 @@ impl OutputNode {
let mode = self.global.mode.get(); let mode = self.global.mode.get();
let mut width = mode.width; let mut width = mode.width;
let mut height = mode.height; let mut height = mode.height;
let scale = self.preferred_scale.get(); let scale = self.global.preferred_scale.get();
if scale != 1 { if scale != 1 {
let scale = scale.to_f64(); let scale = scale.to_f64();
width = (width as f64 / scale).round() as _; width = (width as f64 / scale).round() as _;