anvil: bulk-send frame events after each page flip

This commit is contained in:
Victor Berger 2020-04-21 19:42:03 +02:00 committed by Victor Berger
parent 59f7167702
commit 315797ff43
6 changed files with 51 additions and 12 deletions

View File

@ -24,7 +24,6 @@ use smithay::{
data_device::DnDIconRole,
seat::CursorImageRole,
shm::with_buffer_contents as shm_buffer_contents,
SERIAL_COUNTER as SCOUNTER,
},
};
@ -381,11 +380,6 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
},
);
}
// send a frame event to the surface if applicable
if let Some(callback) = data.borrow_mut().frame_callback.take() {
callback.done(SCOUNTER.next_serial());
}
}
},
|_, _, _, _| true,

View File

@ -694,6 +694,13 @@ impl SurfaceData {
self.input_region.as_ref().unwrap().contains(point)
}
/// Send the frame callback if it had been requested
pub fn send_frame(&mut self, serial: u32) {
if let Some(callback) = self.frame_callback.take() {
callback.done(serial);
}
}
}
fn surface_commit(

View File

@ -70,6 +70,8 @@ impl AnvilState {
)
.expect("Failed to init the wayland event source.");
// Init the basic compositor globals
init_shm_global(&mut display.borrow_mut(), vec![], log.clone());
let (ctoken, _, _, window_map) = init_shell(&mut display.borrow_mut(), buffer_utils, log.clone());
@ -83,6 +85,8 @@ impl AnvilState {
info!(log, "Listening on wayland socket"; "name" => socket_name.clone());
::std::env::set_var("WAYLAND_DISPLAY", &socket_name);
// init data device
let dnd_icon = Arc::new(Mutex::new(None));
let dnd_icon2 = dnd_icon.clone();

View File

@ -6,6 +6,7 @@ use std::{
path::PathBuf,
rc::Rc,
sync::{atomic::Ordering, Arc, Mutex},
time::Duration,
};
use glium::Surface as GliumSurface;
@ -20,7 +21,7 @@ use smithay::{
common::fallback::FallbackDevice,
device_bind,
egl::{EglDevice, EglSurface},
gbm::{egl::Gbm as EglGbmBackend, GbmDevice},
gbm::{egl::Gbm as EglGbmBackend, GbmDevice, GbmSurface},
legacy::LegacyDrmDevice,
DevPath, Device, DeviceHandler, Surface,
},
@ -56,6 +57,7 @@ use smithay::{
data_device::set_data_device_focus,
output::{Mode, Output, PhysicalProperties},
seat::{CursorImageStatus, Seat, XkbConfig},
SERIAL_COUNTER as SCOUNTER,
},
};
@ -63,8 +65,7 @@ use crate::buffer_utils::BufferUtils;
use crate::glium_drawer::GliumDrawer;
use crate::input_handler::AnvilInputHandler;
use crate::shell::{MyWindowMap, Roles};
use crate::AnvilState;
use smithay::backend::drm::gbm::GbmSurface;
use crate::state::AnvilState;
#[derive(Clone)]
pub struct SessionFd(RawFd);
@ -238,7 +239,7 @@ pub fn run_udev(
while state.running.load(Ordering::SeqCst) {
if event_loop
.dispatch(Some(::std::time::Duration::from_millis(16)), &mut state)
.dispatch(Some(Duration::from_millis(16)), &mut state)
.is_err()
{
state.running.store(false, Ordering::SeqCst);
@ -599,6 +600,9 @@ impl DeviceHandler for DrmHandlerImpl {
if let Err(err) = frame.finish() {
error!(self.logger, "Error during rendering: {:?}", err);
}
// Send frame events so that client start drawing their next frame
self.window_map.borrow().send_frames(SCOUNTER.next_serial());
}
}

View File

@ -169,6 +169,26 @@ where
})
.unwrap_or(self.bbox)
}
/// Sends the frame callback to all the subsurfaces in this
/// window that requested it
pub fn send_frame(&self, serial: u32, ctoken: CompositorToken<R>) {
if let Some(wl_surface) = self.toplevel.get_surface() {
ctoken.with_surface_tree_downward(
wl_surface,
(),
|_, _, _, &()| TraversalAction::DoChildren(()),
|_, attributes, _, &()| {
// the surface may not have any user_data if it is a subsurface and has not
// yet been commited
if let Some(data) = attributes.user_data.get::<RefCell<SurfaceData>>() {
data.borrow_mut().send_frame(serial)
}
},
|_, _, _, &()| true,
);
}
}
}
pub struct WindowMap<R> {
@ -291,4 +311,10 @@ where
.find(|w| w.toplevel.equals(toplevel))
.map(|w| w.geometry(self.ctoken))
}
pub fn send_frames(&self, serial: u32) {
for window in &self.windows {
window.send_frame(serial, self.ctoken);
}
}
}

View File

@ -2,6 +2,7 @@ use std::{
cell::RefCell,
rc::Rc,
sync::{atomic::Ordering, Arc, Mutex},
time::Duration,
};
use smithay::{
@ -14,6 +15,7 @@ use smithay::{
data_device::set_data_device_focus,
output::{Mode, Output, PhysicalProperties},
seat::{CursorImageStatus, Seat, XkbConfig},
SERIAL_COUNTER as SCOUNTER,
},
};
@ -22,7 +24,7 @@ use slog::Logger;
use crate::buffer_utils::BufferUtils;
use crate::glium_drawer::GliumDrawer;
use crate::input_handler::AnvilInputHandler;
use crate::AnvilState;
use crate::state::AnvilState;
pub fn run_winit(
display: Rc<RefCell<Display>>,
@ -164,9 +166,11 @@ pub fn run_winit(
error!(log, "Error during rendering: {:?}", err);
}
}
// Send frame events so that client start drawing their next frame
state.window_map.borrow().send_frames(SCOUNTER.next_serial());
if event_loop
.dispatch(Some(::std::time::Duration::from_millis(16)), &mut state)
.dispatch(Some(Duration::from_millis(16)), &mut state)
.is_err()
{
state.running.store(false, Ordering::SeqCst);