Skip to content

Commit

Permalink
surface: throttle frame requests at the refresh rate
Browse files Browse the repository at this point in the history
  • Loading branch information
mahkoh committed Jul 14, 2024
1 parent 618fdfe commit 049545f
Showing 1 changed file with 34 additions and 7 deletions.
41 changes: 34 additions & 7 deletions src/ifs/wl_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ pub struct WlSurface {
pub need_extents_update: Cell<bool>,
pub buffer: CloneCell<Option<Rc<SurfaceBuffer>>>,
buffer_presented: Cell<bool>,
buffer_has_frame_request: Cell<bool>,
pub shm_texture: CloneCell<Option<Rc<dyn GfxTexture>>>,
pub buf_x: NumCell<i32>,
pub buf_y: NumCell<i32>,
Expand Down Expand Up @@ -579,6 +580,7 @@ impl WlSurface {
need_extents_update: Default::default(),
buffer: Default::default(),
buffer_presented: Default::default(),
buffer_has_frame_request: Default::default(),
shm_texture: Default::default(),
buf_x: Default::default(),
buf_y: Default::default(),
Expand Down Expand Up @@ -1091,6 +1093,7 @@ impl WlSurface {
self.buffer.set(Some(Rc::new(surface_buffer)));
if pending.has_damage() {
self.buffer_presented.set(false);
self.buffer_has_frame_request.set(false);
}
} else {
self.shm_texture.take();
Expand Down Expand Up @@ -1200,9 +1203,14 @@ impl WlSurface {
self.buffer_abs_pos
.set(self.buffer_abs_pos.get().with_size(width, height).unwrap());
}
self.frame_requests
.borrow_mut()
.extend(pending.frame_request.drain(..));
let had_frame_requests = self.buffer_has_frame_request.get();
let has_frame_requests = {
let frs = &mut *self.frame_requests.borrow_mut();
frs.extend(pending.frame_request.drain(..));
frs.is_not_empty()
};
self.buffer_has_frame_request
.set(had_frame_requests || has_frame_requests);
{
let mut fbs = self.presentation_feedback.borrow_mut();
for fb in fbs.drain(..) {
Expand Down Expand Up @@ -1249,10 +1257,29 @@ impl WlSurface {
self.ext.get().after_apply_commit();
if self.visible.get() {
if self.buffer_presented.get() {
let now = self.client.state.now_msec() as _;
for fr in self.frame_requests.borrow_mut().drain(..) {
fr.send_done(now);
let _ = fr.client.remove_obj(&*fr);
// If the currently attached buffer has already been fully presented ...
if has_frame_requests {
// ... and there are new frame requests ...
if had_frame_requests {
// ... and we've already dispatched frame requests for that buffer,
// then schedule new presentation of the primary output and
// unset the buffer_presented flag. This is for clients that
// send frame requests at an uncapped rate and expect the
// compositor to dispatch frame requests at the monitor
// refresh rate. (e.g. firefox, mpv)
let rect = self.output.get().global.pos.get();
self.client.state.damage(rect);
self.buffer_presented.set(false);
} else {
// ... and this is the first commit that attaches a frame request
// for that buffer, then dispatch the frame requests
// immediately.
let now = self.client.state.now_msec() as _;
for fr in self.frame_requests.borrow_mut().drain(..) {
fr.send_done(now);
let _ = fr.client.remove_obj(&*fr);
}
}
}
} else {
self.apply_damage(pending);
Expand Down

0 comments on commit 049545f

Please sign in to comment.