diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index ddc75fb0..20da98f9 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -7,19 +7,25 @@ use crate::{ backend::render, config::OutputConfig, shell::Shell, - state::{BackendData, Common, State}, + state::{BackendData, ClientState, Common, Data}, + utils::prelude::*, }; use anyhow::{Context, Result}; use smithay::{ backend::{ - allocator::{gbm::GbmDevice, Format}, + allocator::{ + dmabuf::Dmabuf, + gbm::GbmDevice, + Format, + }, drm::{DrmDevice, DrmEvent, DrmEventTime, DrmNode, GbmBufferedSurface, NodeType}, egl::{EGLContext, EGLDevice, EGLDisplay}, input::InputEvent, libinput::{LibinputInputBackend, LibinputSessionInterface}, renderer::{ multigpu::{egl::EglGlesBackend, GpuManager}, + gles2::Gles2Renderbuffer, Bind, }, session::{auto::AutoSession, Session, Signal}, @@ -33,10 +39,16 @@ use smithay::{ drm::control::{connector, crtc, Device as ControlDevice, ModeTypeFlags}, input::Libinput, nix::{fcntl::OFlag, sys::stat::dev_t}, - wayland_server::protocol::{wl_output, wl_surface::WlSurface}, + wayland_server::{ + DisplayHandle, Resource, + protocol::{wl_output, wl_surface::WlSurface}, + }, }, utils::signaling::{Linkable, SignalToken, Signaler}, - wayland::output::{Mode as OutputMode, Output, PhysicalProperties}, + wayland::{ + dmabuf::DmabufGlobal, + output::{Mode as OutputMode, Output, PhysicalProperties}, + }, }; use std::{ @@ -56,7 +68,7 @@ use socket::*; pub struct KmsState { devices: HashMap, api: GpuManager, - primary: DrmNode, + pub primary: DrmNode, session: AutoSession, signaler: Signaler, _restart_token: SignalToken, @@ -67,7 +79,7 @@ pub struct Device { render_node: DrmNode, surfaces: HashMap, allocator: Rc>>, - drm: Dispatcher<'static, DrmDevice, State>, + drm: Dispatcher<'static, DrmDevice, Data>, formats: HashSet, supports_atomic: bool, event_token: Option, @@ -87,7 +99,7 @@ pub struct Surface { fps: Fps, } -pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut State) -> Result<()> { +pub fn init_backend(dh: &DisplayHandle, event_loop: &mut EventLoop<'static, Data>, state: &mut State) -> Result<()> { let (session, notifier) = AutoSession::new(None).context("Failed to acquire session")?; let signaler = notifier.signaler(); @@ -102,16 +114,16 @@ pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut Stat let libinput_event_source = event_loop .handle() - .insert_source(libinput_backend, move |mut event, _, state| { + .insert_source(libinput_backend, move |mut event, _, data| { if let &mut InputEvent::DeviceAdded { ref mut device } = &mut event { - state.common.config.read_device(device); + data.state.common.config.read_device(device); } - state.process_input_event(event); - for output in state.common.shell.outputs() { - if let Err(err) = state + data.state.process_input_event(&data.display.handle(), event); + for output in data.state.common.shell.outputs() { + if let Err(err) = data.state .backend .kms() - .schedule_render(&state.common.event_loop_handle, output) + .schedule_render(&data.state.common.event_loop_handle, output) { slog_scope::crit!("Error scheduling event loop for output {}: {:?}", output.name(), err); } @@ -153,16 +165,16 @@ pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut Stat }; slog_scope::info!("Using {} as primary gpu for rendering", primary); - let udev_dispatcher = Dispatcher::new(udev_backend, move |event, _, state: &mut State| { + let udev_dispatcher = Dispatcher::new(udev_backend, move |event, _, data: &mut Data| { match match event { - UdevEvent::Added { device_id, path } => state - .device_added(device_id, path) + UdevEvent::Added { device_id, path } => data.state + .device_added(device_id, path, &data.display.handle()) .with_context(|| format!("Failed to add drm device: {}", device_id)), - UdevEvent::Changed { device_id } => state + UdevEvent::Changed { device_id } => data.state .device_changed(device_id) .with_context(|| format!("Failed to update drm device: {}", device_id)), - UdevEvent::Removed { device_id } => state - .device_removed(device_id) + UdevEvent::Removed { device_id } => data.state + .device_removed(device_id, &data.display.handle()) .with_context(|| format!("Failed to remove drm device: {}", device_id)), } { Ok(()) => { @@ -184,7 +196,7 @@ pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut Stat let _restart_token = signaler.register(move |signal| { if let Signal::ActivateSession = signal { let dispatcher = dispatcher.clone(); - handle.insert_idle(move |state| { + handle.insert_idle(move |data| { for (dev, path) in dispatcher.as_source_ref().device_list() { let drm_node = match DrmNode::from_dev_id(dev) { Ok(node) => node, @@ -197,8 +209,8 @@ pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut Stat continue; } }; - if state.backend.kms().devices.contains_key(&drm_node) { - if let Err(err) = state.device_changed(dev) { + if data.state.backend.kms().devices.contains_key(&drm_node) { + if let Err(err) = data.state.device_changed(dev) { slog_scope::error!( "Failed to update drm device {}: {}", path.display(), @@ -206,7 +218,7 @@ pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut Stat ); } } else { - if let Err(err) = state.device_added(dev, path.into()) { + if let Err(err) = data.state.device_added(dev, path.into(), &data.display.handle()) { slog_scope::error!( "Failed to add drm device {}: {}", path.display(), @@ -215,24 +227,24 @@ pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut Stat } } } - state + data.state .common - .output_conf - .update(&mut *state.common.display.borrow_mut()); + .output_configuration_state + .update(); - state.common.config.read_outputs( - state.common.output_conf.outputs(), - &mut state.backend, - &mut state.common.shell, - &state.common.event_loop_handle, + data.state.common.config.read_outputs( + data.state.common.output_configuration_state.outputs(), + &mut data.state.backend, + &mut data.state.common.shell, + &data.state.common.event_loop_handle, ); - state.common.shell.refresh_outputs(); - state + data.state.common.shell.refresh_outputs(); + data.state .common .config - .write_outputs(state.common.output_conf.outputs()); + .write_outputs(data.state.common.output_configuration_state.outputs()); - for surface in state + for surface in data.state .backend .kms() .devices @@ -241,11 +253,11 @@ pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut Stat { surface.pending = false; } - for output in state.common.shell.outputs() { - if let Err(err) = state + for output in data.state.common.shell.outputs() { + if let Err(err) = data.state .backend .kms() - .schedule_render(&state.common.event_loop_handle, output) + .schedule_render(&data.state.common.event_loop_handle, output) { slog_scope::crit!("Error scheduling event loop for output {}: {:?}", output.name(), err); } @@ -271,14 +283,14 @@ pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut Stat for (dev, path) in udev_dispatcher.as_source_ref().device_list() { state - .device_added(dev, path.into()) + .device_added(dev, path.into(), dh) .with_context(|| format!("Failed to add drm device: {}", path.display()))?; } Ok(()) } impl State { - fn device_added(&mut self, dev: dev_t, path: PathBuf) -> Result<()> { + fn device_added(&mut self, dev: dev_t, path: PathBuf, dh: &DisplayHandle) -> Result<()> { if !self.backend.kms().session.is_active() { return Ok(()); } @@ -332,21 +344,21 @@ impl State { drm.link(self.backend.kms().signaler.clone()); let dispatcher = - Dispatcher::new(drm, move |event, metadata, state: &mut State| match event { + Dispatcher::new(drm, move |event, metadata, data: &mut Data| match event { DrmEvent::VBlank(crtc) => { - if let Some(device) = state.backend.kms().devices.get_mut(&drm_node) { + if let Some(device) = data.state.backend.kms().devices.get_mut(&drm_node) { if let Some(surface) = device.surfaces.get_mut(&crtc) { match surface.surface.as_mut().map(|x| x.frame_submitted()) { Some(Ok(_)) => { surface.last_submit = metadata.take().map(|data| data.time); surface.pending = false; - state + data.state .common .shell .active_space_mut(&surface.output) .space .send_frames( - state.common.start_time.elapsed().as_millis() as u32 + data.state.common.start_time.elapsed().as_millis() as u32 ); } Some(Err(err)) => { @@ -367,7 +379,7 @@ impl State { .register_dispatcher(dispatcher.clone()) .with_context(|| format!("Failed to add drm device to event loop: {}", dev))?; - let socket = match self.create_socket(render_node, formats.clone().into_iter()) { + let socket = match self.create_socket(dh, render_node, formats.clone().into_iter()) { Ok(socket) => Some(socket), Err(err) => { slog_scope::warn!( @@ -410,10 +422,10 @@ impl State { } self.backend.kms().devices.insert(drm_node, device); - self.common.output_conf.add_heads(wl_outputs.iter()); + self.common.output_configuration_state.add_heads(wl_outputs.iter()); self.common - .output_conf - .update(&mut *self.common.display.borrow_mut()); + .output_configuration_state + .update(); for output in wl_outputs { if let Err(err) = self.backend.kms().apply_config_for_output( &output, @@ -425,7 +437,7 @@ impl State { } } self.common.config.read_outputs( - self.common.output_conf.outputs(), + self.common.output_configuration_state.outputs(), &mut self.backend, &mut self.common.shell, &self.common.event_loop_handle, @@ -433,7 +445,7 @@ impl State { self.common.shell.refresh_outputs(); self.common .config - .write_outputs(self.common.output_conf.outputs()); + .write_outputs(self.common.output_configuration_state.outputs()); Ok(()) } @@ -475,8 +487,8 @@ impl State { } } - self.common.output_conf.remove_heads(outputs_removed.iter()); - self.common.output_conf.add_heads(outputs_added.iter()); + self.common.output_configuration_state.remove_heads(outputs_removed.iter()); + self.common.output_configuration_state.add_heads(outputs_added.iter()); for output in outputs_added { if let Err(err) = self.backend.kms().apply_config_for_output( &output, @@ -488,10 +500,10 @@ impl State { } } self.common - .output_conf - .update(&mut self.common.display.borrow_mut()); + .output_configuration_state + .update(); self.common.config.read_outputs( - self.common.output_conf.outputs(), + self.common.output_configuration_state.outputs(), &mut self.backend, &mut self.common.shell, &self.common.event_loop_handle, @@ -499,12 +511,12 @@ impl State { self.common.shell.refresh_outputs(); self.common .config - .write_outputs(self.common.output_conf.outputs()); + .write_outputs(self.common.output_configuration_state.outputs()); Ok(()) } - fn device_removed(&mut self, dev: dev_t) -> Result<()> { + fn device_removed(&mut self, dev: dev_t, dh: &DisplayHandle) -> Result<()> { let drm_node = DrmNode::from_dev_id(dev)?; let mut outputs_removed = Vec::new(); if let Some(mut device) = self.backend.kms().devices.remove(&drm_node) { @@ -519,16 +531,18 @@ impl State { } if let Some(socket) = device.socket.take() { self.common.event_loop_handle.remove(socket.token); + self.common.dmabuf_state.destroy_global::(dh, socket.dmabuf_global); + dh.remove_global(socket.drm_global); } } - self.common.output_conf.remove_heads(outputs_removed.iter()); + self.common.output_configuration_state.remove_heads(outputs_removed.iter()); self.common - .output_conf - .update(&mut *self.common.display.borrow_mut()); + .output_configuration_state + .update(); if self.backend.kms().session.is_active() { self.common.config.read_outputs( - self.common.output_conf.outputs(), + self.common.output_configuration_state.outputs(), &mut self.backend, &mut self.common.shell, &self.common.event_loop_handle, @@ -536,7 +550,7 @@ impl State { self.common.shell.refresh_outputs(); self.common .config - .write_outputs(self.common.output_conf.outputs()); + .write_outputs(self.common.output_configuration_state.outputs()); } Ok(()) @@ -658,7 +672,7 @@ impl Device { const MAX_CPU_COPIES: usize = 3; -fn render_node_for_output(output: &Output, target_node: DrmNode, shell: &Shell) -> DrmNode { +fn render_node_for_output(dh: &DisplayHandle, output: &Output, target_node: DrmNode, shell: &Shell) -> DrmNode { let workspace = shell.active_space(output); let nodes = workspace .get_fullscreen(output) @@ -666,13 +680,10 @@ fn render_node_for_output(output: &Output, target_node: DrmNode, shell: &Shell) .unwrap_or_else(|| workspace.space.windows().collect::>()) .into_iter() .flat_map(|w| { - w.toplevel() - .get_surface()? - .as_ref() - .client()? - .data_map() - .get::() - .cloned() + dh.get_client(w.toplevel().wl_surface().id()).ok()? + .get_data::().unwrap() + .drm_node + .clone() }) .collect::>(); if nodes.contains(&target_node) || nodes.len() < MAX_CPU_COPIES { @@ -695,6 +706,7 @@ fn render_node_for_output(output: &Output, target_node: DrmNode, shell: &Shell) impl Surface { pub fn render_output( &mut self, + dh: &DisplayHandle, api: &mut GpuManager, target_node: &DrmNode, state: &mut Common, @@ -707,7 +719,7 @@ impl Surface { self.surface.as_mut().unwrap().reset_buffers(); } - let render_node = render_node_for_output(&self.output, *target_node, &state.shell); + let render_node = render_node_for_output(dh, &self.output, *target_node, &state.shell); let mut renderer = api.renderer(&render_node, &target_node).unwrap(); let surface = self.surface.as_mut().unwrap(); @@ -753,7 +765,7 @@ impl KmsState { output: &Output, shell: &mut Shell, test_only: bool, - loop_handle: &LoopHandle<'_, State>, + loop_handle: &LoopHandle<'_, Data>, ) -> Result<(), anyhow::Error> { let recreated = if let Some(device) = self .devices @@ -848,10 +860,10 @@ impl KmsState { self.devices.iter().find(|(_, dev)| dev.surfaces.values().any(|s| s.output == *output)).map(|(target, _)| target).copied() } - pub fn try_early_import(&mut self, surface: &WlSurface, output: &Output, target: DrmNode, shell: &Shell) { - let render = render_node_for_output(&output, target, &shell); + pub fn try_early_import(&mut self, dh: &DisplayHandle, surface: &WlSurface, output: &Output, target: DrmNode, shell: &Shell) { + let render = render_node_for_output(dh, &output, target, &shell); if let Err(err) = self.api.early_import( - surface.as_ref().client().and_then(|c| c.data_map().get::().cloned()), + dh.get_client(surface.id()).ok().and_then(|c| c.get_data::().unwrap().drm_node.clone()), render, surface, ) { @@ -859,9 +871,23 @@ impl KmsState { } } + pub fn dmabuf_imported(&mut self, _dh: &DisplayHandle, global: &DmabufGlobal, dmabuf: Dmabuf) -> Result<()> { + use smithay::backend::renderer::ImportDma; + + for device in self.devices.values() { + if device.socket.as_ref().map(|s| &s.dmabuf_global == global).unwrap_or(false) { + return self.api.renderer::(&device.render_node, &device.render_node)? + .import_dmabuf(&dmabuf, None) + .map(|_| ()) + .map_err(Into::into); + } + } + unreachable!() + } + pub fn schedule_render( &mut self, - loop_handle: &LoopHandle<'_, State>, + loop_handle: &LoopHandle<'_, Data>, output: &Output, ) -> Result<(), InsertError> { if let Some((device, crtc, surface)) = self @@ -897,14 +923,15 @@ impl KmsState { /*} else { Timer::from_deadline(instant.unwrap()) }*/, - move |_time, _, state| { - let backend = state.backend.kms(); + move |_time, _, data| { + let backend = data.state.backend.kms(); if let Some(device) = backend.devices.get_mut(&device) { if let Some(surface) = device.surfaces.get_mut(&crtc) { if let Err(err) = surface.render_output( + &data.display.handle(), &mut backend.api, &device.render_node, - &mut state.common, + &mut data.state.common, ) { slog_scope::error!("Error rendering: {}", err); return TimeoutAction::ToDuration(Duration::from_secs_f64( diff --git a/src/backend/kms/socket.rs b/src/backend/kms/socket.rs index 8d4a8379..96854190 100644 --- a/src/backend/kms/socket.rs +++ b/src/backend/kms/socket.rs @@ -1,46 +1,42 @@ // SPDX-License-Identifier: GPL-3.0-only -use anyhow::{Context, Result}; +use anyhow::{anyhow, Context, Result}; use smithay::{ backend::{ allocator::Format, - drm::DrmNode, - renderer::{gles2::Gles2Renderbuffer, ImportDma}, + drm::{DrmNode, NodeType}, }, reexports::{ - calloop::{generic::Generic, Interest, Mode, PostAction, RegistrationToken}, - wayland_protocols::unstable::linux_dmabuf, - wayland_server::Client, + calloop::RegistrationToken, + wayland_server::{Client, DisplayHandle, backend::GlobalId}, }, - wayland::dmabuf::init_dmabuf_global_with_filter, -}; - -use std::{ - env, - os::unix::{ - io::{AsRawFd, IntoRawFd, RawFd}, - net::UnixListener, + wayland::{ + dmabuf::DmabufGlobal, + socket::ListeningSocketSource, }, - path::PathBuf, }; +use std::sync::Arc; -use crate::{state::State, utils::GlobalDrop, wayland::init_wl_drm_global}; +use crate::{ + state::{ClientState, Data}, + utils::prelude::*, +}; pub struct Socket { pub token: RegistrationToken, - pub drm_global: GlobalDrop, - pub dmabuf_global: GlobalDrop, + pub drm_global: GlobalId, + pub dmabuf_global: DmabufGlobal, } impl State { pub(super) fn create_socket( &mut self, + dh: &DisplayHandle, render_node: DrmNode, formats: impl Iterator, ) -> Result { let formats = formats.collect::>(); - let is_primary = self.backend.kms().primary == render_node; - let socket_path = PathBuf::from(env::var("XDG_RUNTIME_DIR").unwrap()).join(format!( + let socket_name = format!( "{}-{}", &self.common.socket.to_string_lossy(), render_node @@ -49,125 +45,63 @@ impl State { .file_name() .unwrap() .to_string_lossy() - )); - // HACK! - let _ = std::fs::remove_file(&socket_path); - - let listener = UnixListener::bind(socket_path.clone()) - .with_context(|| format!("Failed to bind socket to {}", socket_path.display()))?; - listener.set_nonblocking(true)?; - let listener = WaylandListener(listener); - let token = self - .common - .event_loop_handle - .insert_source( - Generic::new(listener, Interest::READ, Mode::Edge), - move |_, listener, state: &mut State| { - loop { - match listener.0.accept() { - Ok((stream, _)) => { - let display = state.common.display.clone(); - let client = unsafe { - display - .borrow_mut() - .create_client(stream.into_raw_fd(), state) - }; - client - .data_map() - .insert_if_missing_threadsafe(|| render_node); - } - Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { - // we have exhausted all the pending connections - break; - } - Err(e) => { - // this is a legitimate error - if let Ok(addr) = listener.0.local_addr() { - if let Some(path) = addr.as_pathname() { - slog_scope::error!( - "Error accepting connection on listening socket {} : {}", - path.display(), - e - ); - return Err(e); - } - } - slog_scope::error!( - "Error accepting connection on listening socket : {}", - e - ); - return Err(e); - } - } - } - - Ok(PostAction::Continue) - }, - ) - .context("Failed to add gpu-wayland socket to the event loop")?; + ); // initialize globals - let filter = move |client: Client| { - let dev_id = client.data_map().get::(); - if dev_id.is_none() && is_primary { - client - .data_map() - .insert_if_missing_threadsafe(|| render_node); - } - dev_id.map(|x| *x == render_node).unwrap_or(is_primary) + let filter = move |client: &Client| { + let dev_id = client.get_data::().unwrap().drm_node.unwrap(); + dev_id == render_node }; - let drm_global = init_wl_drm_global( - &mut *self.common.display.borrow_mut(), - render_node.dev_path().unwrap(), + let dmabuf_global = self.common.dmabuf_state.create_global_with_filter::( + dh, formats.clone(), - filter.clone(), - ); - let dmabuf_global = init_dmabuf_global_with_filter( - &mut *self.common.display.borrow_mut(), - formats, - move |buf, mut ddata| { - let state = ddata.get::().unwrap(); - state - .backend - .kms() - .api - .renderer::(&render_node, &render_node) - .map(|mut renderer| renderer.import_dmabuf(buf, None).is_ok()) - .unwrap_or(false) - }, filter, None, ); - slog_scope::info!( - "Adding socket at {} for gpu {}", - socket_path.display(), + let drm_global_id = self.common.wl_drm_state.create_global_with_filter::( + dh, render_node + .dev_path_with_type(NodeType::Render) + .or_else(|| render_node.dev_path()) + .ok_or(anyhow!("Could not determine path for gpu node: {}", render_node))?, + formats, + &dmabuf_global, + filter, + ); + + // add a special socket for the gpu + let listener = ListeningSocketSource::with_name(&socket_name, None) + .with_context(|| format!("Failed to bind socket to {}", socket_name))?; + let token = self + .common + .event_loop_handle + .insert_source( + listener, + move |client_stream, _, data: &mut Data| { + if let Err(err) = data + .display + .handle() + .insert_client(client_stream, Arc::new(data.state.new_client_state_with_node(render_node))) + { + slog_scope::warn!("Error adding wayland client ({}): {}", render_node, err); + } + } + ) + .context("Failed to add gpu-wayland socket to the event loop")?; + + + slog_scope::info!( + "Added socket at {} for gpu {}", + socket_name, + render_node, ); Ok(Socket { token, - drm_global: GlobalDrop::from(drm_global), - dmabuf_global: GlobalDrop::from(dmabuf_global), + drm_global: drm_global_id, + dmabuf_global, }) } } - -struct WaylandListener(UnixListener); - -impl AsRawFd for WaylandListener { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } -} - -impl Drop for WaylandListener { - fn drop(&mut self) { - if let Ok(socketaddr) = self.0.local_addr() { - if let Some(path) = socketaddr.as_pathname() { - let _ = ::std::fs::remove_file(path); - } - } - } -} diff --git a/src/backend/mod.rs b/src/backend/mod.rs index ba2bff2d..684845da 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,8 +1,11 @@ // SPDX-License-Identifier: GPL-3.0-only -use crate::state::State; +use crate::state::{Data, State}; use anyhow::Result; -use smithay::reexports::calloop::EventLoop; +use smithay::reexports::{ + calloop::EventLoop, + wayland_server::DisplayHandle, +}; pub mod render; @@ -13,28 +16,29 @@ pub mod x11; // pub mod wayland; // tbd in smithay pub fn init_backend_auto( - event_loop: &mut EventLoop<'static, State>, + dh: &DisplayHandle, + event_loop: &mut EventLoop<'static, Data>, state: &mut State, ) -> Result<()> { match std::env::var("COSMIC_BACKEND") { - Ok(x) if x == "x11" => x11::init_backend(event_loop, state), - Ok(x) if x == "winit" => winit::init_backend(event_loop, state), - Ok(x) if x == "kms" => kms::init_backend(event_loop, state), + Ok(x) if x == "x11" => x11::init_backend(dh, event_loop, state), + Ok(x) if x == "winit" => winit::init_backend(dh, event_loop, state), + Ok(x) if x == "kms" => kms::init_backend(dh, event_loop, state), Ok(_) => unimplemented!("There is no backend with this identifier"), Err(_) => { if std::env::var_os("DISPLAY").is_some() || std::env::var_os("WAYLAND_DISPLAY").is_some() { - match x11::init_backend(event_loop, state) { + match x11::init_backend(dh, event_loop, state) { Ok(_) => Ok(()), Err(err) => { slog_scope::warn!("X11 Backend failed with error: {}", err); slog_scope::info!("Falling back to winit backend."); - winit::init_backend(event_loop, state) + winit::init_backend(dh, event_loop, state) } } } else { - kms::init_backend(event_loop, state) + kms::init_backend(dh, event_loop, state) } } } diff --git a/src/backend/render/cursor.rs b/src/backend/render/cursor.rs index 138fc309..fdfb3b2b 100644 --- a/src/backend/render/cursor.rs +++ b/src/backend/render/cursor.rs @@ -1,11 +1,14 @@ // SPDX-License-Identifier: GPL-3.0-only -use crate::state::get_dnd_icon; +use crate::{ + wayland::handlers::data_device::get_dnd_icon, + utils::prelude::*, +}; use smithay::{ backend::renderer::{Frame, ImportAll, ImportMem, Renderer, Texture}, desktop::space::{RenderElement, SpaceOutputTuple, SurfaceTree}, reexports::wayland_server::protocol::wl_surface, - utils::{Logical, Point, Rectangle, Size, Transform}, + utils::{IsAlive, Logical, Physical, Point, Rectangle, Size, Scale, Transform}, wayland::{ compositor::{get_role, with_states}, seat::{CursorImageAttributes, CursorImageStatus, Seat}, @@ -125,27 +128,16 @@ pub fn draw_surface_cursor( where { let mut position = location.into(); - let ret = with_states(&surface, |states| { - Some( - states - .data_map - .get::>() - .unwrap() - .lock() - .unwrap() - .hotspot, - ) - }) - .unwrap_or(None); - position -= match ret { - Some(h) => h, - None => { - slog_scope::warn!( - "Trying to display as a cursor a surface that does not have the CursorImage role." - ); - (0, 0).into() - } - }; + let h = with_states(&surface, |states| { + states + .data_map + .get::>() + .unwrap() + .lock() + .unwrap() + .hotspot + }); + position -= h; SurfaceTree { surface, position, @@ -171,7 +163,7 @@ pub fn draw_dnd_icon( pub struct PointerElement { texture: T, - position: Point, + position: Point, size: Size, new_frame: bool, } @@ -179,7 +171,7 @@ pub struct PointerElement { impl PointerElement { pub fn new( texture: T, - relative_pointer_pos: Point, + relative_pointer_pos: Point, new_frame: bool, ) -> PointerElement { let size = texture.size().to_logical(1, Transform::Normal); @@ -201,16 +193,21 @@ where 0 } - fn geometry(&self) -> Rectangle { - Rectangle::from_loc_and_size(self.position, self.size) + fn location(&self, scale: impl Into>) -> Point { + self.position.to_physical(scale) + } + + fn geometry(&self, scale: impl Into>) -> Rectangle { + Rectangle::from_loc_and_size(self.position, self.size.to_f64()).to_physical(scale).to_i32_round() } fn accumulated_damage( &self, + scale: impl Into>, _: Option>, - ) -> Vec> { + ) -> Vec> { if self.new_frame { - vec![Rectangle::from_loc_and_size((0, 0), self.size)] + vec![Rectangle::from_loc_and_size((0, 0), self.size.to_physical_precise_round(scale))] } else { vec![] } @@ -220,21 +217,18 @@ where &self, _renderer: &mut R, frame: &mut ::Frame, - scale: f64, - position: Point, - damage: &[Rectangle], + scale: impl Into>, + position: Point, + damage: &[Rectangle], _log: &slog::Logger, ) -> Result<(), ::Error> { frame.render_texture_at( &self.texture, - position.to_f64().to_physical(scale as f64).to_i32_round(), + position.to_i32_round(), 1, - scale as f64, + scale, Transform::Normal, - &*damage - .iter() - .map(|rect| rect.to_physical(1).to_f64()) - .collect::>(), + damage, 1.0, )?; Ok(()) @@ -259,8 +253,8 @@ impl Default for CursorState { pub fn draw_cursor( renderer: &mut R, - seat: &Seat, - location: Point, + seat: &Seat, + location: Point, start_time: &std::time::Instant, draw_default: bool, ) -> Option @@ -272,8 +266,8 @@ where // draw the dnd icon if applicable { if let Some(wl_surface) = get_dnd_icon(seat) { - if wl_surface.as_ref().is_alive() { - return Some(draw_dnd_icon(wl_surface, location).into()); + if wl_surface.alive() { + return Some(draw_dnd_icon(wl_surface, location.to_i32_round()).into()); } } } @@ -287,7 +281,7 @@ where .map(|cell| { let mut cursor_status = cell.borrow_mut(); if let CursorImageStatus::Image(ref surface) = *cursor_status { - if !surface.as_ref().is_alive() { + if !surface.alive() { *cursor_status = CursorImageStatus::Default; } } @@ -296,7 +290,7 @@ where .unwrap_or(CursorImageStatus::Default); if let CursorImageStatus::Image(wl_surface) = cursor_status { - Some(draw_surface_cursor(wl_surface.clone(), location).into()) + Some(draw_surface_cursor(wl_surface.clone(), location.to_i32_round()).into()) } else if draw_default { let seat_userdata = seat.user_data(); seat_userdata.insert_if_missing(CursorState::default); @@ -329,7 +323,7 @@ where pointer_images.push((frame.clone(), Box::new(texture.clone()))); texture }); - let hotspot = Point::::from((frame.xhot as i32, frame.yhot as i32)); + let hotspot = Point::::from((frame.xhot as i32, frame.yhot as i32)).to_f64(); *state.current_image.borrow_mut() = Some(frame); Some(PointerElement::new(pointer_image.clone(), location - hotspot, new_frame).into()) diff --git a/src/backend/render/mod.rs b/src/backend/render/mod.rs index e9e2daa7..e11cfd3a 100644 --- a/src/backend/render/mod.rs +++ b/src/backend/render/mod.rs @@ -18,12 +18,12 @@ use smithay::{ }, }, desktop::{ - draw_layer_surface, draw_window, layer_map_for_output, + draw_layer_surface, draw_layer_popups, draw_window, draw_window_popups, layer_map_for_output, space::{RenderElement, RenderError, SpaceOutputTuple, SurfaceTree}, utils::damage_from_surface_tree, Window, }, - utils::{Logical, Point, Rectangle, Transform}, + utils::{Physical, Point, Rectangle, Scale, Transform}, wayland::{output::Output, shell::wlr_layer::Layer as WlrLayer}, }; @@ -44,7 +44,7 @@ smithay::custom_elements! { EguiFrame=EguiFrame, } -// TODO: due to the lifetime, we cannot be generic over CustomElem's renderer +// TODO: due to the lifetime of MultiRenderer, we cannot be generic over CustomElem's renderer // util after GATs land. So we generate with the macro for Gles2 and then // do a manual impl for MultiRenderer. impl RenderElement> for CustomElem { @@ -52,24 +52,29 @@ impl RenderElement> for CustomElem { RenderElement::::id(self) } - fn geometry(&self) -> Rectangle { - RenderElement::::geometry(self) + fn location(&self, scale: impl Into>) -> Point { + RenderElement::::location(self, scale) + } + + fn geometry(&self, scale: impl Into>) -> Rectangle { + RenderElement::::geometry(self, scale) } fn accumulated_damage( &self, + scale: impl Into>, for_values: Option>, - ) -> Vec> { - RenderElement::::accumulated_damage(self, for_values) + ) -> Vec> { + RenderElement::::accumulated_damage(self, scale, for_values) } fn draw( &self, renderer: &mut GlMultiRenderer<'_>, frame: &mut GlMultiFrame, - scale: f64, - location: Point, - damage: &[Rectangle], + scale: impl Into>, + location: Point, + damage: &[Rectangle], log: &Logger, ) -> Result<(), MultiError> { RenderElement::::draw( @@ -130,7 +135,7 @@ pub fn render_output( output: &Output, hardware_cursor: bool, #[cfg(feature = "debug")] fps: &mut Fps, -) -> Result>>, RenderError> +) -> Result>>, RenderError> where R: Renderer + ImportAll + AsGles2Renderer, ::TextureId: Clone + 'static, @@ -140,7 +145,6 @@ where { fps.start(); } - let workspace = state.shell.active_space(output); let maybe_fullscreen_window = workspace.get_fullscreen(output).cloned(); let res = if let Some(window) = maybe_fullscreen_window { @@ -179,7 +183,7 @@ fn render_desktop( output: &Output, hardware_cursor: bool, #[cfg(feature = "debug")] fps: &mut Fps, -) -> Result>>, RenderError> +) -> Result>>, RenderError> where R: Renderer + ImportAll + AsGles2Renderer, ::TextureId: Clone + 'static, @@ -246,7 +250,7 @@ fn render_fullscreen( output: &Output, hardware_cursor: bool, #[cfg(feature = "debug")] fps: &mut Fps, -) -> Result>>, RenderError> +) -> Result>>, RenderError> where R: Renderer + ImportAll + AsGles2Renderer, ::TextureId: Clone + 'static, @@ -293,20 +297,32 @@ where renderer .render(mode.size, transform, |renderer, frame| { - let mut damage = window.accumulated_damage(None); + let mut damage = window.accumulated_damage((0.0, 0.0), scale, None); frame.clear( CLEAR_COLOR, - &[Rectangle::from_loc_and_size((0, 0), mode.size).to_f64()], + &[Rectangle::from_loc_and_size((0, 0), mode.size)], )?; draw_window( renderer, frame, &window, scale, - (0, 0), + (0.0, 0.0), &[Rectangle::from_loc_and_size( (0, 0), - mode.size.to_f64().to_logical(scale).to_i32_round(), + mode.size, + )], + &slog_scope::logger(), + )?; + draw_window_popups( + renderer, + frame, + &window, + scale, + (0.0, 0.0), + &[Rectangle::from_loc_and_size( + (0, 0), + mode.size, )], &slog_scope::logger(), )?; @@ -318,22 +334,30 @@ where frame, layer_surface, scale, - geo.loc, - &[Rectangle::from_loc_and_size((0, 0), geo.size)], + geo.loc.to_f64().to_physical(scale), + &[Rectangle::from_loc_and_size((0, 0), geo.size.to_physical_precise_round(scale))], &slog_scope::logger(), )?; - if let Some(surface) = layer_surface.get_surface() { - damage.extend(damage_from_surface_tree(surface, geo.loc, None)); - } + draw_layer_popups( + renderer, + frame, + layer_surface, + scale, + geo.loc.to_f64().to_physical(scale), + &[Rectangle::from_loc_and_size((0, 0), geo.size.to_physical_precise_round(scale))], + &slog_scope::logger(), + )?; + damage.extend(damage_from_surface_tree(layer_surface.wl_surface(), geo.loc.to_f64().to_physical(scale), scale, None)); } for elem in custom_elements { - let geo = elem.geometry(); - let elem_damage = elem.accumulated_damage(None); + let loc = elem.location(scale); + let geo = elem.geometry(scale); + let elem_damage = elem.accumulated_damage(scale, None); elem.draw( renderer, frame, scale, - geo.loc, + loc, &[Rectangle::from_loc_and_size((0, 0), geo.size)], &slog_scope::logger(), )?; diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 6ff37569..01f60fc8 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -3,10 +3,11 @@ use crate::{ backend::render, config::OutputConfig, - input::{set_active_output, Devices}, - state::{BackendData, Common, State}, + input::Devices, + state::{BackendData, Common, Data}, + utils::prelude::*, }; -use anyhow::{Context, Result}; +use anyhow::{anyhow, Context, Result}; use smithay::{ backend::{ renderer::{ImportDma, ImportEgl}, @@ -17,23 +18,19 @@ use smithay::{ calloop::{ping, EventLoop}, wayland_server::{ protocol::wl_output::{Subpixel, Transform}, - Display, + DisplayHandle, }, }, - wayland::{ - dmabuf::init_dmabuf_global, - output::{Mode, Output, PhysicalProperties}, - }, + wayland::output::{Mode, Output, PhysicalProperties}, }; -use std::{cell::RefCell, rc::Rc}; +use std::cell::RefCell; #[cfg(feature = "debug")] use crate::state::Fps; pub struct WinitState { // The winit backend currently has no notion of multiple windows - backend: Rc>, - //_global: GlobalDrop, + pub backend: WinitGraphicsBackend, output: Output, age_reset: u8, #[cfg(feature = "debug")] @@ -46,18 +43,17 @@ impl WinitState { self.reset_buffers(); } - let backend = &mut *self.backend.borrow_mut(); - backend.bind().with_context(|| "Failed to bind buffer")?; + self.backend.bind().with_context(|| "Failed to bind buffer")?; let age = if self.age_reset > 0 { self.age_reset -= 1; 0 } else { - backend.buffer_age().unwrap_or(0) + self.backend.buffer_age().unwrap_or(0) }; match render::render_output( None, - backend.renderer(), + self.backend.renderer(), age as u8, state, &self.output, @@ -71,8 +67,8 @@ impl WinitState { .active_space_mut(&self.output) .space .send_frames(state.start_time.elapsed().as_millis() as u32); - backend - .submit(damage.as_ref().map(|x| &**x), 1.0) + self.backend + .submit(damage.as_ref().map(|x| &**x)) .with_context(|| "Failed to submit buffer for display")?; } Err(err) => { @@ -90,7 +86,7 @@ impl WinitState { ) -> Result<(), anyhow::Error> { // TODO: if we ever have multiple winit outputs, don't ignore config.enabled // reset size - let size = self.backend.borrow().window_size(); + let size = self.backend.window_size(); let mut config = output .user_data() .get::>() @@ -114,15 +110,14 @@ impl WinitState { } } -pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Result<()> { - let (backend, mut input) = - winit::init(None).with_context(|| "Failed to initilize winit backend")?; - let backend = Rc::new(RefCell::new(backend)); +pub fn init_backend(dh: &DisplayHandle, event_loop: &mut EventLoop, state: &mut State) -> Result<()> { + let (mut backend, mut input) = + winit::init(None).map_err(|_| anyhow!("Failed to initilize winit backend"))?; - init_egl_client_side(&mut *state.common.display.borrow_mut(), backend.clone())?; + init_egl_client_side(dh, state, &mut backend)?; let name = format!("WINIT-0"); - let size = backend.borrow().window_size(); + let size = backend.window_size(); let props = PhysicalProperties { size: (0, 0).into(), subpixel: Subpixel::Unknown, @@ -134,7 +129,7 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res refresh: 60_000, }; let output = Output::new(name, props, None); - //let _global = global.into(); + let _global = output.create_global::(dh); output.change_current_state( Some(mode), Some(Transform::Flipped180), @@ -162,8 +157,10 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res let mut token = Some( event_loop .handle() - .insert_source(render_source, move |_, _, state| { - if let Err(err) = state.backend.winit().render_output(&mut state.common) { + .insert_source(render_source, move |_, _, data| { + if let Err(err) = data.state.backend.winit().render_output( + &mut data.state.common + ) { slog_scope::error!("Failed to render frame: {}", err); render_ping.ping(); } @@ -173,17 +170,21 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res let event_loop_handle = event_loop.handle(); event_loop .handle() - .insert_source(event_source, move |_, _, state| { + .insert_source(event_source, move |_, _, data| { match input - .dispatch_new_events(|event| state.process_winit_event(event, &render_ping_handle)) + .dispatch_new_events(|event| data.state.process_winit_event( + &data.display.handle(), + event, + &render_ping_handle + )) { Ok(_) => { event_ping_handle.ping(); render_ping_handle.ping(); } Err(winit::WinitError::WindowClosed) => { - let output = state.backend.winit().output.clone(); - state.common.shell.remove_output(&output); + let output = data.state.backend.winit().output.clone(); + data.state.common.shell.remove_output(&output); if let Some(token) = token.take() { event_loop_handle.remove(token); } @@ -200,11 +201,11 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res fps: Fps::default(), age_reset: 0, }); - state.common.output_conf.add_heads(std::iter::once(&output)); + state.common.output_configuration_state.add_heads(std::iter::once(&output)); state .common - .output_conf - .update(&mut *state.common.display.borrow_mut()); + .output_configuration_state + .update(); state.common.shell.add_output(&output); state.common.config.read_outputs( std::iter::once(&output), @@ -219,29 +220,22 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res } fn init_egl_client_side( - display: &mut Display, - renderer: Rc>, + dh: &DisplayHandle, + state: &mut State, + renderer: &mut WinitGraphicsBackend, ) -> Result<()> { - let bind_result = renderer.borrow_mut().renderer().bind_wl_display(display); + let bind_result = renderer.renderer().bind_wl_display(dh); match bind_result { Ok(_) => { slog_scope::info!("EGL hardware-acceleration enabled"); let dmabuf_formats = renderer - .borrow_mut() .renderer() .dmabuf_formats() .cloned() .collect::>(); - init_dmabuf_global( - display, + state.common.dmabuf_state.create_global::( + dh, dmabuf_formats, - move |buffer, _| { - renderer - .borrow_mut() - .renderer() - .import_dmabuf(buffer, None) - .is_ok() - }, None, ); } @@ -252,7 +246,7 @@ fn init_egl_client_side( } impl State { - pub fn process_winit_event(&mut self, event: WinitEvent, render_ping: &ping::Ping) { + pub fn process_winit_event(&mut self, dh: &DisplayHandle, event: WinitEvent, render_ping: &ping::Ping) { // here we can handle special cases for winit inputs match event { WinitEvent::Focus(true) => { @@ -283,15 +277,15 @@ impl State { output.delete_mode(output.current_mode().unwrap()); output.set_preferred(mode); output.change_current_state(Some(mode), None, None, None); - layer_map_for_output(output).arrange(); + layer_map_for_output(output).arrange(dh); self.common - .output_conf - .update(&mut *self.common.display.borrow_mut()); + .output_configuration_state + .update(); self.common.shell.refresh_outputs(); render_ping.ping(); } WinitEvent::Refresh => render_ping.ping(), - WinitEvent::Input(event) => self.process_input_event(event), + WinitEvent::Input(event) => self.process_input_event(dh, event), _ => {} }; } diff --git a/src/backend/x11.rs b/src/backend/x11.rs index 918a61b7..59b49893 100644 --- a/src/backend/x11.rs +++ b/src/backend/x11.rs @@ -3,8 +3,9 @@ use crate::{ backend::render, config::OutputConfig, - input::{set_active_output, Devices}, - state::{BackendData, Common, State}, + input::Devices, + state::{BackendData, Common, Data}, + utils::prelude::*, }; use anyhow::{Context, Result}; use smithay::{ @@ -19,16 +20,12 @@ use smithay::{ reexports::{ calloop::{ping, EventLoop, LoopHandle}, gbm::{Device as GbmDevice, FdWrapper}, - wayland_server::{protocol::wl_output::Subpixel, Display}, - }, - wayland::{ - dmabuf::init_dmabuf_global, - output::{Mode, Output, PhysicalProperties}, + wayland_server::{protocol::wl_output::Subpixel, DisplayHandle}, }, + wayland::output::{Mode, Output, PhysicalProperties}, }; use std::{ cell::RefCell, - rc::Rc, sync::{Arc, Mutex}, }; @@ -38,13 +35,13 @@ use crate::state::Fps; pub struct X11State { allocator: Arc>>, _egl: EGLDisplay, - renderer: Rc>, + pub renderer: Gles2Renderer, surfaces: Vec, handle: X11Handle, } impl X11State { - pub fn add_window(&mut self, handle: LoopHandle<'_, State>) -> Result { + pub fn add_window(&mut self, handle: LoopHandle<'_, Data>) -> Result { let window = WindowBuilder::new() .title("COSMIC") .build(&self.handle) @@ -55,7 +52,7 @@ impl X11State { .create_surface( &window, self.allocator.clone(), - Bind::::supported_formats(&*self.renderer.borrow()) + Bind::::supported_formats(&self.renderer) .unwrap() .iter() .filter(|format| format.code == fourcc) @@ -89,15 +86,15 @@ impl X11State { let (ping, source) = ping::make_ping().with_context(|| "Failed to create output event loop source")?; let _token = handle - .insert_source(source, move |_, _, state| { - let x11_state = state.backend.x11(); + .insert_source(source, move |_, _, data| { + let x11_state = data.state.backend.x11(); if let Some(surface) = x11_state .surfaces .iter_mut() .find(|s| s.output == output_ref) { if let Err(err) = surface - .render_output(&mut *x11_state.renderer.borrow_mut(), &mut state.common) + .render_output(&mut x11_state.renderer, &mut data.state.common) { slog_scope::error!("Error rendering: {}", err); } @@ -221,7 +218,7 @@ impl Surface { } } -pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Result<()> { +pub fn init_backend(dh: &DisplayHandle, event_loop: &mut EventLoop, state: &mut State) -> Result<()> { let backend = X11Backend::new(None).with_context(|| "Failed to initilize X11 backend")?; let handle = backend.handle(); @@ -238,12 +235,10 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res // Create the OpenGL context let context = EGLContext::new(&egl, None).with_context(|| "Failed to create EGL context")?; // Create a renderer - let renderer = Rc::new(RefCell::new( - unsafe { Gles2Renderer::new(context, None) } - .with_context(|| "Failed to initialize renderer")?, - )); + let mut renderer = unsafe { Gles2Renderer::new(context, None) } + .with_context(|| "Failed to initialize renderer")?; - init_egl_client_side(&mut *state.common.display.borrow_mut(), renderer.clone())?; + init_egl_client_side(dh, state, &mut renderer)?; state.backend = BackendData::X11(X11State { handle, @@ -258,11 +253,11 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res .x11() .add_window(event_loop.handle()) .with_context(|| "Failed to create wl_output")?; - state.common.output_conf.add_heads(std::iter::once(&output)); + state.common.output_configuration_state.add_heads(std::iter::once(&output)); state .common - .output_conf - .update(&mut *state.common.display.borrow_mut()); + .output_configuration_state + .update(); state.common.shell.add_output(&output); state.common.config.read_outputs( std::iter::once(&output), @@ -275,11 +270,12 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res event_loop .handle() - .insert_source(backend, |event, _, state| match event { + .insert_source(backend, |event, _, data| match event { X11Event::CloseRequested { window_id } => { // TODO: drain_filter let mut outputs_removed = Vec::new(); - for surface in state + for surface in data + .state .backend .x11() .surfaces @@ -289,13 +285,13 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res surface.window.unmap(); outputs_removed.push(surface.output.clone()); } - state + data.state .backend .x11() .surfaces .retain(|s| s.window.id() != window_id); for output in outputs_removed.into_iter() { - state.common.shell.remove_output(&output); + data.state.common.shell.remove_output(&output); } } X11Event::Resized { @@ -307,7 +303,7 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res size, refresh: 60_000, }; - if let Some(surface) = state + if let Some(surface) = data.state .backend .x11() .surfaces @@ -327,12 +323,12 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res output.delete_mode(output.current_mode().unwrap()); output.change_current_state(Some(mode), None, None, None); output.set_preferred(mode); - layer_map_for_output(output).arrange(); - state + layer_map_for_output(output).arrange(&data.display.handle()); + data.state .common - .output_conf - .update(&mut *state.common.display.borrow_mut()); - state.common.shell.refresh_outputs(); + .output_configuration_state + .update(); + data.state.common.shell.refresh_outputs(); surface.dirty = true; if !surface.pending { surface.render.ping(); @@ -340,7 +336,8 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res } } X11Event::Refresh { window_id } | X11Event::PresentCompleted { window_id } => { - if let Some(surface) = state + if let Some(surface) = data + .state .backend .x11() .surfaces @@ -354,27 +351,25 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res } } } - X11Event::Input(event) => state.process_x11_event(event), + X11Event::Input(event) => data.state.process_x11_event(&data.display.handle(), event), }) .map_err(|_| anyhow::anyhow!("Failed to insert X11 Backend into event loop"))?; Ok(()) } -fn init_egl_client_side(display: &mut Display, renderer: Rc>) -> Result<()> { - let bind_result = renderer.borrow_mut().bind_wl_display(display); +fn init_egl_client_side(dh: &DisplayHandle, state: &mut State, renderer: &mut Gles2Renderer) -> Result<()> { + let bind_result = renderer.bind_wl_display(dh); match bind_result { Ok(_) => { slog_scope::info!("EGL hardware-acceleration enabled"); let dmabuf_formats = renderer - .borrow() .dmabuf_formats() .cloned() .collect::>(); - init_dmabuf_global( - display, + state.common.dmabuf_state.create_global::( + dh, dmabuf_formats, - move |buffer, _| renderer.borrow_mut().import_dmabuf(buffer, None).is_ok(), None, ); } @@ -385,7 +380,7 @@ fn init_egl_client_side(display: &mut Display, renderer: Rc) { + pub fn process_x11_event(&mut self, dh: &DisplayHandle, event: InputEvent) { // here we can handle special cases for x11 inputs, like mapping them to windows match &event { InputEvent::PointerMotionAbsolute { event } => { @@ -412,7 +407,7 @@ impl State { _ => {} }; - self.process_input_event(event); + self.process_input_event(dh, event); // TODO actually figure out the output for output in self.common.shell.outputs() { self.backend