From 315797ff43d9750d38b8fb7b2e73c65783ac3049 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Tue, 21 Apr 2020 19:42:03 +0200 Subject: [PATCH] anvil: bulk-send frame events after each page flip --- anvil/src/glium_drawer.rs | 6 ------ anvil/src/shell.rs | 7 +++++++ anvil/src/state.rs | 4 ++++ anvil/src/udev.rs | 12 ++++++++---- anvil/src/window_map.rs | 26 ++++++++++++++++++++++++++ anvil/src/winit.rs | 8 ++++++-- 6 files changed, 51 insertions(+), 12 deletions(-) diff --git a/anvil/src/glium_drawer.rs b/anvil/src/glium_drawer.rs index 80c226d..47c9e6e 100644 --- a/anvil/src/glium_drawer.rs +++ b/anvil/src/glium_drawer.rs @@ -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 GliumDrawer { }, ); } - - // 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, diff --git a/anvil/src/shell.rs b/anvil/src/shell.rs index 70f4eb0..f43cf9e 100644 --- a/anvil/src/shell.rs +++ b/anvil/src/shell.rs @@ -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( diff --git a/anvil/src/state.rs b/anvil/src/state.rs index 5248500..9af1ad5 100644 --- a/anvil/src/state.rs +++ b/anvil/src/state.rs @@ -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(); diff --git a/anvil/src/udev.rs b/anvil/src/udev.rs index 345edfd..5120dee 100644 --- a/anvil/src/udev.rs +++ b/anvil/src/udev.rs @@ -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()); } } diff --git a/anvil/src/window_map.rs b/anvil/src/window_map.rs index bc0bd74..fdfdc19 100644 --- a/anvil/src/window_map.rs +++ b/anvil/src/window_map.rs @@ -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) { + 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::>() { + data.borrow_mut().send_frame(serial) + } + }, + |_, _, _, &()| true, + ); + } + } } pub struct WindowMap { @@ -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); + } + } } diff --git a/anvil/src/winit.rs b/anvil/src/winit.rs index 2bc4789..d40f33b 100644 --- a/anvil/src/winit.rs +++ b/anvil/src/winit.rs @@ -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>, @@ -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);