mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-27 21:58:18 +01:00
Fix winit rendering
This commit is contained in:
parent
7fbacbd52f
commit
7572523cfc
3 changed files with 22 additions and 124 deletions
|
@ -680,7 +680,7 @@ impl State {
|
||||||
let then = udev.last_vblank_time;
|
let then = udev.last_vblank_time;
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let diff = now.duration_since(then);
|
let diff = now.duration_since(then);
|
||||||
tracing::debug!(time = diff.as_secs_f64(), "Time since last vblank");
|
// tracing::debug!(time = diff.as_secs_f64(), "Time since last vblank");
|
||||||
udev.last_vblank_time = now;
|
udev.last_vblank_time = now;
|
||||||
}
|
}
|
||||||
data.state.on_vblank(node, crtc, metadata);
|
data.state.on_vblank(node, crtc, metadata);
|
||||||
|
@ -1160,19 +1160,10 @@ impl State {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if schedule_render {
|
|
||||||
// // Anvil had some stuff here about delaying a render to reduce latency,
|
|
||||||
// // but it introduces visible hitching when scrolling, so I'm removing it here.
|
|
||||||
// //
|
|
||||||
// // If latency is a problem then future me can deal with it :)
|
|
||||||
// self.loop_handle.insert_idle(move |data| {
|
|
||||||
// data.state.render_surface(&output);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render to the [`RenderSurface`] associated with the given `output`.
|
/// Render to the [`RenderSurface`] associated with the given `output`.
|
||||||
|
#[tracing::instrument(level = "debug", skip(self), fields(output = output.name()))]
|
||||||
fn render_surface(&mut self, output: &Output) {
|
fn render_surface(&mut self, output: &Output) {
|
||||||
let udev = self.backend.udev_mut();
|
let udev = self.backend.udev_mut();
|
||||||
|
|
||||||
|
@ -1267,63 +1258,6 @@ impl State {
|
||||||
Ok(true) => surface.render_state = RenderState::WaitingForVblank { dirty: false },
|
Ok(true) => surface.render_state = RenderState::WaitingForVblank { dirty: false },
|
||||||
Ok(false) | Err(_) => surface.render_state = RenderState::Idle,
|
Ok(false) | Err(_) => surface.render_state = RenderState::Idle,
|
||||||
}
|
}
|
||||||
|
|
||||||
// let reschedule = match &result {
|
|
||||||
// Ok(has_rendered) => !has_rendered,
|
|
||||||
// Err(err) => {
|
|
||||||
// tracing::warn!("Error during rendering: {:?}", err);
|
|
||||||
// match err {
|
|
||||||
// SwapBuffersError::AlreadySwapped => false,
|
|
||||||
// SwapBuffersError::TemporaryFailure(err) => !matches!(
|
|
||||||
// err.downcast_ref::<DrmError>(),
|
|
||||||
// Some(&DrmError::DeviceInactive)
|
|
||||||
// | Some(&DrmError::Access {
|
|
||||||
// source: drm::SystemError::PermissionDenied,
|
|
||||||
// ..
|
|
||||||
// })
|
|
||||||
// ),
|
|
||||||
// SwapBuffersError::ContextLost(err) => panic!("Rendering loop lost: {}", err),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// if reschedule {
|
|
||||||
// tracing::debug!("rescheduling due to no dmg or error");
|
|
||||||
// let Some(data) = output.user_data().get::<UdevOutputData>() else {
|
|
||||||
// unreachable!()
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// // Literally no idea if this refresh time calculation is doing anything, but we're
|
|
||||||
// // gonna keep it here because I already added the stuff for it
|
|
||||||
// let refresh_time = if let Some(mode) = data.mode {
|
|
||||||
// self::utils::refresh_time(mode)
|
|
||||||
// } else {
|
|
||||||
// let output_refresh = match output.current_mode() {
|
|
||||||
// Some(mode) => mode.refresh,
|
|
||||||
// None => {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// Duration::from_millis((1_000_000f32 / output_refresh as f32) as u64)
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// // If reschedule is true we either hit a temporary failure or more likely rendering
|
|
||||||
// // did not cause any damage on the output. In this case we just re-schedule a repaint
|
|
||||||
// // after approx. one frame to re-test for damage.
|
|
||||||
// tracing::trace!(
|
|
||||||
// "reschedule repaint timer with delay {:?} on {}",
|
|
||||||
// refresh_time,
|
|
||||||
// output.name(),
|
|
||||||
// );
|
|
||||||
// let timer = Timer::from_duration(refresh_time);
|
|
||||||
// let output = output.clone();
|
|
||||||
// self.loop_handle
|
|
||||||
// .insert_source(timer, move |_, _, data| {
|
|
||||||
// data.state.render_surface(&output);
|
|
||||||
// TimeoutAction::Drop
|
|
||||||
// })
|
|
||||||
// .expect("failed to schedule frame timer");
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,10 @@ use smithay::{
|
||||||
timer::{TimeoutAction, Timer},
|
timer::{TimeoutAction, Timer},
|
||||||
EventLoop,
|
EventLoop,
|
||||||
},
|
},
|
||||||
wayland_protocols::wp::presentation_time::server::wp_presentation_feedback,
|
wayland_protocols::{
|
||||||
|
wp::presentation_time::server::wp_presentation_feedback,
|
||||||
|
xdg::shell::server::xdg_toplevel,
|
||||||
|
},
|
||||||
wayland_server::{protocol::wl_surface::WlSurface, Display},
|
wayland_server::{protocol::wl_surface::WlSurface, Display},
|
||||||
},
|
},
|
||||||
utils::{IsAlive, Transform},
|
utils::{IsAlive, Transform},
|
||||||
|
@ -44,7 +47,6 @@ pub struct Winit {
|
||||||
pub damage_tracker: OutputDamageTracker,
|
pub damage_tracker: OutputDamageTracker,
|
||||||
pub dmabuf_state: (DmabufState, DmabufGlobal, Option<DmabufFeedback>),
|
pub dmabuf_state: (DmabufState, DmabufGlobal, Option<DmabufFeedback>),
|
||||||
pub full_redraw: u8,
|
pub full_redraw: u8,
|
||||||
render_state: RenderState,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackendData for Winit {
|
impl BackendData for Winit {
|
||||||
|
@ -60,11 +62,6 @@ impl BackendData for Winit {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backend {
|
impl Backend {
|
||||||
fn winit(&self) -> &Winit {
|
|
||||||
let Backend::Winit(winit) = self else { unreachable!() };
|
|
||||||
winit
|
|
||||||
}
|
|
||||||
|
|
||||||
fn winit_mut(&mut self) -> &mut Winit {
|
fn winit_mut(&mut self) -> &mut Winit {
|
||||||
let Backend::Winit(winit) = self else { unreachable!() };
|
let Backend::Winit(winit) = self else { unreachable!() };
|
||||||
winit
|
winit
|
||||||
|
@ -169,7 +166,6 @@ pub fn run_winit() -> anyhow::Result<()> {
|
||||||
damage_tracker: OutputDamageTracker::from_output(&output),
|
damage_tracker: OutputDamageTracker::from_output(&output),
|
||||||
dmabuf_state,
|
dmabuf_state,
|
||||||
full_redraw: 0,
|
full_redraw: 0,
|
||||||
render_state: RenderState::Idle,
|
|
||||||
}),
|
}),
|
||||||
display,
|
display,
|
||||||
event_loop.get_signal(),
|
event_loop.get_signal(),
|
||||||
|
@ -227,7 +223,7 @@ pub fn run_winit() -> anyhow::Result<()> {
|
||||||
state.process_input_event(input_evt);
|
state.process_input_event(input_evt);
|
||||||
}
|
}
|
||||||
WinitEvent::Refresh => {
|
WinitEvent::Refresh => {
|
||||||
state.schedule_render(&output);
|
state.render_window(&output);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -238,33 +234,14 @@ pub fn run_winit() -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
state.render_window(&output);
|
||||||
|
|
||||||
TimeoutAction::ToDuration(Duration::from_micros(((1.0 / 144.0) * 1000000.0) as u64))
|
TimeoutAction::ToDuration(Duration::from_micros(((1.0 / 144.0) * 1000000.0) as u64))
|
||||||
});
|
});
|
||||||
if let Err(err) = insert_ret {
|
if let Err(err) = insert_ret {
|
||||||
anyhow::bail!("Failed to insert winit events into event loop: {err}");
|
anyhow::bail!("Failed to insert winit events into event loop: {err}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let frame_time = Duration::from_micros(((1.0 / 144.0) * 1000000.0) as u64);
|
|
||||||
let refresh_timer = Timer::from_duration(frame_time);
|
|
||||||
state
|
|
||||||
.loop_handle
|
|
||||||
.insert_source(refresh_timer, move |instant, _, data| {
|
|
||||||
let winit = data.state.backend.winit();
|
|
||||||
|
|
||||||
winit.backend.window().request_redraw();
|
|
||||||
|
|
||||||
let frame_time = winit
|
|
||||||
.backend
|
|
||||||
.window()
|
|
||||||
.current_monitor()
|
|
||||||
.and_then(|monitor| monitor.refresh_rate_millihertz())
|
|
||||||
.map(|rate| Duration::from_secs_f64(1000.0 / rate as f64))
|
|
||||||
.unwrap_or(frame_time);
|
|
||||||
|
|
||||||
TimeoutAction::ToInstant(instant + frame_time)
|
|
||||||
})
|
|
||||||
.expect("failed to insert render timer into event loop");
|
|
||||||
|
|
||||||
event_loop.run(
|
event_loop.run(
|
||||||
Some(Duration::from_micros(((1.0 / 144.0) * 1000000.0) as u64)),
|
Some(Duration::from_micros(((1.0 / 144.0) * 1000000.0) as u64)),
|
||||||
&mut CalloopData {
|
&mut CalloopData {
|
||||||
|
@ -283,31 +260,10 @@ pub fn run_winit() -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RenderState {
|
|
||||||
Idle,
|
|
||||||
Scheduled,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Winit {
|
|
||||||
pub fn schedule_render(&mut self, loop_handle: &LoopHandle<CalloopData>, output: &Output) {
|
|
||||||
match &self.render_state {
|
|
||||||
RenderState::Idle => {
|
|
||||||
let output = output.clone();
|
|
||||||
loop_handle.insert_idle(move |data| data.state.render_window(&output));
|
|
||||||
|
|
||||||
self.render_state = RenderState::Scheduled;
|
|
||||||
}
|
|
||||||
RenderState::Scheduled => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
fn render_window(&mut self, output: &Output) {
|
fn render_window(&mut self, output: &Output) {
|
||||||
let winit = self.backend.winit_mut();
|
let winit = self.backend.winit_mut();
|
||||||
|
|
||||||
assert!(matches!(winit.render_state, RenderState::Scheduled));
|
|
||||||
|
|
||||||
let pending_wins = self
|
let pending_wins = self
|
||||||
.windows
|
.windows
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -322,6 +278,16 @@ impl State {
|
||||||
};
|
};
|
||||||
pending_size || win.with_state(|state| !state.loc_request_state.is_idle())
|
pending_size || win.with_state(|state| !state.loc_request_state.is_idle())
|
||||||
})
|
})
|
||||||
|
.filter(|win| {
|
||||||
|
if let WindowElement::Wayland(win) = win {
|
||||||
|
!win.toplevel()
|
||||||
|
.current_state()
|
||||||
|
.states
|
||||||
|
.contains(xdg_toplevel::State::Resizing)
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
})
|
||||||
.map(|win| {
|
.map(|win| {
|
||||||
(
|
(
|
||||||
win.class().unwrap_or("None".to_string()),
|
win.class().unwrap_or("None".to_string()),
|
||||||
|
@ -347,7 +313,6 @@ impl State {
|
||||||
|
|
||||||
// TODO: still draw the cursor here
|
// TODO: still draw the cursor here
|
||||||
|
|
||||||
winit.render_state = RenderState::Idle;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let full_redraw = &mut winit.full_redraw;
|
let full_redraw = &mut winit.full_redraw;
|
||||||
|
@ -448,6 +413,5 @@ impl State {
|
||||||
tracing::warn!("{}", err);
|
tracing::warn!("{}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
winit.render_state = RenderState::Idle;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -407,9 +407,9 @@ pub fn take_presentation_feedback(
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub fn schedule_render(&mut self, output: &Output) {
|
pub fn schedule_render(&mut self, output: &Output) {
|
||||||
match &mut self.backend {
|
// I'm relegating winit to render every frame because it's not my priority right now
|
||||||
Backend::Winit(winit) => winit.schedule_render(&self.loop_handle, output),
|
if let Backend::Udev(udev) = &mut self.backend {
|
||||||
Backend::Udev(udev) => udev.schedule_render(&self.loop_handle, output),
|
udev.schedule_render(&self.loop_handle, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue