Merge pull request #224 from mahkoh/jorth/frame-request-throttling
Various damage tracking changes
This commit is contained in:
commit
e59915bb33
4 changed files with 66 additions and 12 deletions
|
|
@ -267,6 +267,7 @@ pub struct WlSurface {
|
||||||
pub need_extents_update: Cell<bool>,
|
pub need_extents_update: Cell<bool>,
|
||||||
pub buffer: CloneCell<Option<Rc<SurfaceBuffer>>>,
|
pub buffer: CloneCell<Option<Rc<SurfaceBuffer>>>,
|
||||||
buffer_presented: Cell<bool>,
|
buffer_presented: Cell<bool>,
|
||||||
|
buffer_had_frame_request: Cell<bool>,
|
||||||
pub shm_texture: CloneCell<Option<Rc<dyn GfxTexture>>>,
|
pub shm_texture: CloneCell<Option<Rc<dyn GfxTexture>>>,
|
||||||
pub buf_x: NumCell<i32>,
|
pub buf_x: NumCell<i32>,
|
||||||
pub buf_y: NumCell<i32>,
|
pub buf_y: NumCell<i32>,
|
||||||
|
|
@ -579,6 +580,7 @@ impl WlSurface {
|
||||||
need_extents_update: Default::default(),
|
need_extents_update: Default::default(),
|
||||||
buffer: Default::default(),
|
buffer: Default::default(),
|
||||||
buffer_presented: Default::default(),
|
buffer_presented: Default::default(),
|
||||||
|
buffer_had_frame_request: Default::default(),
|
||||||
shm_texture: Default::default(),
|
shm_texture: Default::default(),
|
||||||
buf_x: Default::default(),
|
buf_x: Default::default(),
|
||||||
buf_y: Default::default(),
|
buf_y: Default::default(),
|
||||||
|
|
@ -1059,6 +1061,10 @@ impl WlSurface {
|
||||||
alpha_changed = true;
|
alpha_changed = true;
|
||||||
self.alpha.set(alpha);
|
self.alpha.set(alpha);
|
||||||
}
|
}
|
||||||
|
let buffer_abs_pos = self.buffer_abs_pos.get();
|
||||||
|
let mut max_surface_size = buffer_abs_pos.size();
|
||||||
|
let mut damage_full =
|
||||||
|
scale_changed || buffer_transform_changed || viewport_changed || alpha_changed;
|
||||||
let mut buffer_changed = false;
|
let mut buffer_changed = false;
|
||||||
let mut old_raw_size = None;
|
let mut old_raw_size = None;
|
||||||
let (dx, dy) = mem::take(&mut pending.offset);
|
let (dx, dy) = mem::take(&mut pending.offset);
|
||||||
|
|
@ -1091,6 +1097,7 @@ impl WlSurface {
|
||||||
self.buffer.set(Some(Rc::new(surface_buffer)));
|
self.buffer.set(Some(Rc::new(surface_buffer)));
|
||||||
if pending.has_damage() {
|
if pending.has_damage() {
|
||||||
self.buffer_presented.set(false);
|
self.buffer_presented.set(false);
|
||||||
|
self.buffer_had_frame_request.set(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.shm_texture.take();
|
self.shm_texture.take();
|
||||||
|
|
@ -1194,15 +1201,23 @@ impl WlSurface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let (width, height) = new_size.unwrap_or_default();
|
let (width, height) = new_size.unwrap_or_default();
|
||||||
if (width, height) != self.buffer_abs_pos.get().size() {
|
let (old_width, old_height) = buffer_abs_pos.size();
|
||||||
|
if (width, height) != (old_width, old_height) {
|
||||||
self.need_extents_update.set(true);
|
self.need_extents_update.set(true);
|
||||||
|
self.buffer_abs_pos
|
||||||
|
.set(buffer_abs_pos.with_size(width, height).unwrap());
|
||||||
|
max_surface_size = (width.max(old_width), height.max(old_height));
|
||||||
|
damage_full = true;
|
||||||
}
|
}
|
||||||
self.buffer_abs_pos
|
|
||||||
.set(self.buffer_abs_pos.get().with_size(width, height).unwrap());
|
|
||||||
}
|
}
|
||||||
self.frame_requests
|
let had_frame_requests = self.buffer_had_frame_request.get();
|
||||||
.borrow_mut()
|
let has_frame_requests = {
|
||||||
.extend(pending.frame_request.drain(..));
|
let frs = &mut *self.frame_requests.borrow_mut();
|
||||||
|
frs.extend(pending.frame_request.drain(..));
|
||||||
|
frs.is_not_empty()
|
||||||
|
};
|
||||||
|
self.buffer_had_frame_request
|
||||||
|
.set(had_frame_requests || has_frame_requests);
|
||||||
{
|
{
|
||||||
let mut fbs = self.presentation_feedback.borrow_mut();
|
let mut fbs = self.presentation_feedback.borrow_mut();
|
||||||
for fb in fbs.drain(..) {
|
for fb in fbs.drain(..) {
|
||||||
|
|
@ -1248,11 +1263,40 @@ impl WlSurface {
|
||||||
}
|
}
|
||||||
self.ext.get().after_apply_commit();
|
self.ext.get().after_apply_commit();
|
||||||
if self.visible.get() {
|
if self.visible.get() {
|
||||||
if self.buffer_presented.get() {
|
if damage_full {
|
||||||
let now = self.client.state.now_msec() as _;
|
let mut damage = buffer_abs_pos
|
||||||
for fr in self.frame_requests.borrow_mut().drain(..) {
|
.with_size(max_surface_size.0, max_surface_size.1)
|
||||||
fr.send_done(now);
|
.unwrap();
|
||||||
let _ = fr.client.remove_obj(&*fr);
|
if let Some(tl) = self.toplevel.get() {
|
||||||
|
damage = damage.intersect(tl.node_absolute_position());
|
||||||
|
}
|
||||||
|
self.client.state.damage(damage);
|
||||||
|
} else if self.buffer_presented.get() {
|
||||||
|
// 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). This is very inefficient and
|
||||||
|
// disables VRR from working correctly. But since only firefox
|
||||||
|
// is affected, I'm ok with this.
|
||||||
|
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 {
|
} else {
|
||||||
self.apply_damage(pending);
|
self.apply_damage(pending);
|
||||||
|
|
|
||||||
|
|
@ -470,6 +470,9 @@ impl StackedNode for Xwindow {
|
||||||
stacked_node_impl!();
|
stacked_node_impl!();
|
||||||
|
|
||||||
fn stacked_set_visible(&self, visible: bool) {
|
fn stacked_set_visible(&self, visible: bool) {
|
||||||
|
let extents = self.x.surface.extents.get();
|
||||||
|
let (x, y) = self.x.surface.buffer_abs_pos.get().position();
|
||||||
|
self.data.state.damage(extents.move_(x, y));
|
||||||
self.tl_set_visible(visible);
|
self.tl_set_visible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,11 @@ impl XdgPopupRequestHandler for XdgPopup {
|
||||||
|
|
||||||
impl XdgPopup {
|
impl XdgPopup {
|
||||||
pub fn set_visible(&self, visible: bool) {
|
pub fn set_visible(&self, visible: bool) {
|
||||||
|
let surface = &self.xdg.surface;
|
||||||
|
let extents = surface.extents.get();
|
||||||
|
let (x, y) = surface.buffer_abs_pos.get().position();
|
||||||
|
surface.client.state.damage(extents.move_(x, y));
|
||||||
|
|
||||||
// log::info!("set visible = {}", visible);
|
// log::info!("set visible = {}", visible);
|
||||||
self.set_visible_prepared.set(false);
|
self.set_visible_prepared.set(false);
|
||||||
self.xdg.set_visible(visible);
|
self.xdg.set_visible(visible);
|
||||||
|
|
|
||||||
|
|
@ -785,7 +785,9 @@ impl StackedNode for FloatNode {
|
||||||
stacked_node_impl!();
|
stacked_node_impl!();
|
||||||
|
|
||||||
fn stacked_set_visible(&self, visible: bool) {
|
fn stacked_set_visible(&self, visible: bool) {
|
||||||
self.visible.set(visible);
|
if self.visible.replace(visible) != visible {
|
||||||
|
self.state.damage(self.position.get());
|
||||||
|
}
|
||||||
if let Some(child) = self.child.get() {
|
if let Some(child) = self.child.get() {
|
||||||
child.tl_set_visible(visible);
|
child.tl_set_visible(visible);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue