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 now = Instant::now();
|
||||
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;
|
||||
}
|
||||
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`.
|
||||
#[tracing::instrument(level = "debug", skip(self), fields(output = output.name()))]
|
||||
fn render_surface(&mut self, output: &Output) {
|
||||
let udev = self.backend.udev_mut();
|
||||
|
||||
|
@ -1267,63 +1258,6 @@ impl State {
|
|||
Ok(true) => surface.render_state = RenderState::WaitingForVblank { dirty: false },
|
||||
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},
|
||||
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},
|
||||
},
|
||||
utils::{IsAlive, Transform},
|
||||
|
@ -44,7 +47,6 @@ pub struct Winit {
|
|||
pub damage_tracker: OutputDamageTracker,
|
||||
pub dmabuf_state: (DmabufState, DmabufGlobal, Option<DmabufFeedback>),
|
||||
pub full_redraw: u8,
|
||||
render_state: RenderState,
|
||||
}
|
||||
|
||||
impl BackendData for Winit {
|
||||
|
@ -60,11 +62,6 @@ impl BackendData for Winit {
|
|||
}
|
||||
|
||||
impl Backend {
|
||||
fn winit(&self) -> &Winit {
|
||||
let Backend::Winit(winit) = self else { unreachable!() };
|
||||
winit
|
||||
}
|
||||
|
||||
fn winit_mut(&mut self) -> &mut Winit {
|
||||
let Backend::Winit(winit) = self else { unreachable!() };
|
||||
winit
|
||||
|
@ -169,7 +166,6 @@ pub fn run_winit() -> anyhow::Result<()> {
|
|||
damage_tracker: OutputDamageTracker::from_output(&output),
|
||||
dmabuf_state,
|
||||
full_redraw: 0,
|
||||
render_state: RenderState::Idle,
|
||||
}),
|
||||
display,
|
||||
event_loop.get_signal(),
|
||||
|
@ -227,7 +223,7 @@ pub fn run_winit() -> anyhow::Result<()> {
|
|||
state.process_input_event(input_evt);
|
||||
}
|
||||
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))
|
||||
});
|
||||
if let Err(err) = insert_ret {
|
||||
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(
|
||||
Some(Duration::from_micros(((1.0 / 144.0) * 1000000.0) as u64)),
|
||||
&mut CalloopData {
|
||||
|
@ -283,31 +260,10 @@ pub fn run_winit() -> anyhow::Result<()> {
|
|||
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 {
|
||||
fn render_window(&mut self, output: &Output) {
|
||||
let winit = self.backend.winit_mut();
|
||||
|
||||
assert!(matches!(winit.render_state, RenderState::Scheduled));
|
||||
|
||||
let pending_wins = self
|
||||
.windows
|
||||
.iter()
|
||||
|
@ -322,6 +278,16 @@ impl State {
|
|||
};
|
||||
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| {
|
||||
(
|
||||
win.class().unwrap_or("None".to_string()),
|
||||
|
@ -347,7 +313,6 @@ impl State {
|
|||
|
||||
// TODO: still draw the cursor here
|
||||
|
||||
winit.render_state = RenderState::Idle;
|
||||
return;
|
||||
}
|
||||
let full_redraw = &mut winit.full_redraw;
|
||||
|
@ -448,6 +413,5 @@ impl State {
|
|||
tracing::warn!("{}", err);
|
||||
}
|
||||
}
|
||||
winit.render_state = RenderState::Idle;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -407,9 +407,9 @@ pub fn take_presentation_feedback(
|
|||
|
||||
impl State {
|
||||
pub fn schedule_render(&mut self, output: &Output) {
|
||||
match &mut self.backend {
|
||||
Backend::Winit(winit) => winit.schedule_render(&self.loop_handle, output),
|
||||
Backend::Udev(udev) => udev.schedule_render(&self.loop_handle, output),
|
||||
// I'm relegating winit to render every frame because it's not my priority right now
|
||||
if let Backend::Udev(udev) = &mut self.backend {
|
||||
udev.schedule_render(&self.loop_handle, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue