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, data_device::DnDIconRole,
seat::CursorImageRole, seat::CursorImageRole,
shm::with_buffer_contents as shm_buffer_contents, 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, |_, _, _, _| true,

View File

@ -694,6 +694,13 @@ impl SurfaceData {
self.input_region.as_ref().unwrap().contains(point) 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( fn surface_commit(

View File

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

View File

@ -6,6 +6,7 @@ use std::{
path::PathBuf, path::PathBuf,
rc::Rc, rc::Rc,
sync::{atomic::Ordering, Arc, Mutex}, sync::{atomic::Ordering, Arc, Mutex},
time::Duration,
}; };
use glium::Surface as GliumSurface; use glium::Surface as GliumSurface;
@ -20,7 +21,7 @@ use smithay::{
common::fallback::FallbackDevice, common::fallback::FallbackDevice,
device_bind, device_bind,
egl::{EglDevice, EglSurface}, egl::{EglDevice, EglSurface},
gbm::{egl::Gbm as EglGbmBackend, GbmDevice}, gbm::{egl::Gbm as EglGbmBackend, GbmDevice, GbmSurface},
legacy::LegacyDrmDevice, legacy::LegacyDrmDevice,
DevPath, Device, DeviceHandler, Surface, DevPath, Device, DeviceHandler, Surface,
}, },
@ -56,6 +57,7 @@ use smithay::{
data_device::set_data_device_focus, data_device::set_data_device_focus,
output::{Mode, Output, PhysicalProperties}, output::{Mode, Output, PhysicalProperties},
seat::{CursorImageStatus, Seat, XkbConfig}, seat::{CursorImageStatus, Seat, XkbConfig},
SERIAL_COUNTER as SCOUNTER,
}, },
}; };
@ -63,8 +65,7 @@ use crate::buffer_utils::BufferUtils;
use crate::glium_drawer::GliumDrawer; use crate::glium_drawer::GliumDrawer;
use crate::input_handler::AnvilInputHandler; use crate::input_handler::AnvilInputHandler;
use crate::shell::{MyWindowMap, Roles}; use crate::shell::{MyWindowMap, Roles};
use crate::AnvilState; use crate::state::AnvilState;
use smithay::backend::drm::gbm::GbmSurface;
#[derive(Clone)] #[derive(Clone)]
pub struct SessionFd(RawFd); pub struct SessionFd(RawFd);
@ -238,7 +239,7 @@ pub fn run_udev(
while state.running.load(Ordering::SeqCst) { while state.running.load(Ordering::SeqCst) {
if event_loop if event_loop
.dispatch(Some(::std::time::Duration::from_millis(16)), &mut state) .dispatch(Some(Duration::from_millis(16)), &mut state)
.is_err() .is_err()
{ {
state.running.store(false, Ordering::SeqCst); state.running.store(false, Ordering::SeqCst);
@ -599,6 +600,9 @@ impl DeviceHandler for DrmHandlerImpl {
if let Err(err) = frame.finish() { if let Err(err) = frame.finish() {
error!(self.logger, "Error during rendering: {:?}", err); 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) .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> { pub struct WindowMap<R> {
@ -291,4 +311,10 @@ where
.find(|w| w.toplevel.equals(toplevel)) .find(|w| w.toplevel.equals(toplevel))
.map(|w| w.geometry(self.ctoken)) .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, cell::RefCell,
rc::Rc, rc::Rc,
sync::{atomic::Ordering, Arc, Mutex}, sync::{atomic::Ordering, Arc, Mutex},
time::Duration,
}; };
use smithay::{ use smithay::{
@ -14,6 +15,7 @@ use smithay::{
data_device::set_data_device_focus, data_device::set_data_device_focus,
output::{Mode, Output, PhysicalProperties}, output::{Mode, Output, PhysicalProperties},
seat::{CursorImageStatus, Seat, XkbConfig}, seat::{CursorImageStatus, Seat, XkbConfig},
SERIAL_COUNTER as SCOUNTER,
}, },
}; };
@ -22,7 +24,7 @@ use slog::Logger;
use crate::buffer_utils::BufferUtils; use crate::buffer_utils::BufferUtils;
use crate::glium_drawer::GliumDrawer; use crate::glium_drawer::GliumDrawer;
use crate::input_handler::AnvilInputHandler; use crate::input_handler::AnvilInputHandler;
use crate::AnvilState; use crate::state::AnvilState;
pub fn run_winit( pub fn run_winit(
display: Rc<RefCell<Display>>, display: Rc<RefCell<Display>>,
@ -164,9 +166,11 @@ pub fn run_winit(
error!(log, "Error during rendering: {:?}", err); 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 if event_loop
.dispatch(Some(::std::time::Duration::from_millis(16)), &mut state) .dispatch(Some(Duration::from_millis(16)), &mut state)
.is_err() .is_err()
{ {
state.running.store(false, Ordering::SeqCst); state.running.store(false, Ordering::SeqCst);