Skip to content

Commit 98f24a5

Browse files
committed
plumb drm
1 parent dc88bc5 commit 98f24a5

File tree

10 files changed

+141
-70
lines changed

10 files changed

+141
-70
lines changed

examples/window.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
//! Simple winit window example.
22
3+
use std::any::Any;
34
use std::error::Error;
45

56
use winit::application::ApplicationHandler;
67
use winit::event::WindowEvent;
7-
use winit::event_loop::{ActiveEventLoop, EventLoop};
8+
use winit::event_loop::{ActiveEventLoop, AsWaylandEventLoop, EventLoop};
9+
use winit::platform::wayland::LinuxDrm;
810
#[cfg(web_platform)]
911
use winit::platform::web::WindowAttributesWeb;
1012
use winit::window::{Window, WindowAttributes, WindowId};
@@ -19,6 +21,12 @@ struct App {
1921
window: Option<Box<dyn Window>>,
2022
}
2123

24+
impl LinuxDrm for App {
25+
fn main_device(&mut self, device: libc::dev_t) {
26+
dbg!(device);
27+
}
28+
}
29+
2230
impl ApplicationHandler for App {
2331
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
2432
#[cfg(not(web_platform))]
@@ -67,6 +75,10 @@ impl ApplicationHandler for App {
6775
_ => (),
6876
}
6977
}
78+
79+
fn as_any(&mut self) -> Option<&mut dyn Any> {
80+
Some(self)
81+
}
7082
}
7183

7284
fn main() -> Result<(), Box<dyn Error>> {
@@ -75,7 +87,10 @@ fn main() -> Result<(), Box<dyn Error>> {
7587

7688
tracing::init();
7789

78-
let event_loop = EventLoop::new()?;
90+
let mut event_loop = EventLoop::new()?;
91+
if let Some(event_loop) = event_loop.as_wayland_event_loop() {
92+
event_loop.listen_linux_dmabuf::<App>();
93+
}
7994

8095
// For alternative loop run options see `pump_events` and `run_on_demand` examples.
8196
event_loop.run_app(App::default())?;

winit-core/src/application/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! End user application handling.
22
3+
use std::any::Any;
4+
35
use crate::event::{DeviceEvent, DeviceId, StartCause, WindowEvent};
46
use crate::event_loop::ActiveEventLoop;
57
use crate::window::WindowId;
@@ -343,6 +345,11 @@ pub trait ApplicationHandler {
343345
fn macos_handler(&mut self) -> Option<&mut dyn macos::ApplicationHandlerExtMacOS> {
344346
None
345347
}
348+
349+
#[inline(always)]
350+
fn as_any(&mut self) -> Option<&mut dyn Any> {
351+
None
352+
}
346353
}
347354

348355
#[deny(clippy::missing_trait_methods)]
@@ -411,6 +418,11 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
411418
fn macos_handler(&mut self) -> Option<&mut dyn macos::ApplicationHandlerExtMacOS> {
412419
(**self).macos_handler()
413420
}
421+
422+
#[inline(always)]
423+
fn as_any(&mut self) -> Option<&mut dyn Any> {
424+
(**self).as_any()
425+
}
414426
}
415427

416428
#[deny(clippy::missing_trait_methods)]
@@ -479,4 +491,9 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for Box<A> {
479491
fn macos_handler(&mut self) -> Option<&mut dyn macos::ApplicationHandlerExtMacOS> {
480492
(**self).macos_handler()
481493
}
494+
495+
#[inline(always)]
496+
fn as_any(&mut self) -> Option<&mut dyn Any> {
497+
(**self).as_any()
498+
}
482499
}

winit-wayland/src/event_loop/mod.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use winit_core::event_loop::{
3030
use winit_core::monitor::MonitorHandle as CoreMonitorHandle;
3131
use winit_core::window::Theme;
3232

33+
use crate::state::ExtensionEvents;
3334
use crate::types::cursor::WaylandCustomCursor;
3435

3536
mod proxy;
@@ -61,6 +62,7 @@ pub struct EventLoop {
6162
buffer_sink: EventSink,
6263
compositor_updates: Vec<WindowCompositorUpdate>,
6364
window_ids: Vec<WindowId>,
65+
extension_events: Vec<ExtensionEvents>,
6466

6567
/// The Wayland dispatcher to has raw access to the queue when needed, such as
6668
/// when creating a new window.
@@ -70,7 +72,7 @@ pub struct EventLoop {
7072
handle: Arc<OwnedDisplayHandle>,
7173

7274
/// Event loop window target.
73-
active_event_loop: ActiveEventLoop,
75+
pub(crate) active_event_loop: ActiveEventLoop,
7476

7577
// XXX drop after everything else, just to be safe.
7678
/// Calloop's event loop.
@@ -96,7 +98,7 @@ impl EventLoop {
9698
let event_loop =
9799
calloop::EventLoop::<WinitState>::try_new().map_err(|err| os_error!(err))?;
98100

99-
let mut winit_state = WinitState::new(&globals, &queue_handle, event_loop.handle())?;
101+
let mut winit_state = WinitState::new(globals, &queue_handle, event_loop.handle())?;
100102

101103
// NOTE: do a roundtrip after binding the globals to prevent potential
102104
// races with the server.
@@ -109,7 +111,8 @@ impl EventLoop {
109111
let result = queue.dispatch_pending(winit_state);
110112
if result.is_ok()
111113
&& (!winit_state.events_sink.is_empty()
112-
|| !winit_state.window_compositor_updates.is_empty())
114+
|| !winit_state.window_compositor_updates.is_empty()
115+
|| !winit_state.extension_events.is_empty())
113116
{
114117
winit_state.dispatched_events = true;
115118
}
@@ -153,10 +156,12 @@ impl EventLoop {
153156
control_flow: Cell::new(ControlFlow::default()),
154157
exit: Cell::new(None),
155158
state: RefCell::new(winit_state),
159+
extensions: Default::default(),
156160
};
157161

158162
let event_loop = Self {
159163
loop_running: false,
164+
extension_events: Vec::new(),
160165
compositor_updates: Vec::new(),
161166
buffer_sink: EventSink::default(),
162167
window_ids: Vec::new(),
@@ -325,6 +330,7 @@ impl EventLoop {
325330
// when finished.
326331
let mut compositor_updates = std::mem::take(&mut self.compositor_updates);
327332
let mut buffer_sink = std::mem::take(&mut self.buffer_sink);
333+
let mut extension_events = std::mem::take(&mut self.extension_events);
328334
let mut window_ids = std::mem::take(&mut self.window_ids);
329335

330336
app.new_events(&self.active_event_loop, cause);
@@ -340,6 +346,15 @@ impl EventLoop {
340346
app.proxy_wake_up(&self.active_event_loop);
341347
}
342348

349+
if let Some(main_device) = self.active_event_loop.extensions.main_device {
350+
self.with_state(|state| extension_events.append(&mut state.extension_events));
351+
352+
for extension_event in extension_events.drain(..) {
353+
let ExtensionEvents::LinuxMainDevice(device) = extension_event;
354+
main_device(app, device);
355+
}
356+
}
357+
343358
// Drain the pending compositor updates.
344359
self.with_state(|state| compositor_updates.append(&mut state.window_compositor_updates));
345360

@@ -567,10 +582,6 @@ impl EventLoop {
567582
fn exit_code(&self) -> Option<i32> {
568583
self.active_event_loop.exit_code()
569584
}
570-
571-
pub fn main_drm_device(&self) -> Option<dev_t> {
572-
self.active_event_loop.state.borrow().linux_dmabuf_manager.as_ref()?.device()
573-
}
574585
}
575586

576587
impl AsFd for EventLoop {
@@ -611,6 +622,13 @@ pub struct ActiveEventLoop {
611622

612623
/// Handle for the underlying event loop.
613624
pub handle: Arc<OwnedDisplayHandle>,
625+
626+
pub(crate) extensions: Extensions,
627+
}
628+
629+
#[derive(Default, Debug)]
630+
pub(crate) struct Extensions {
631+
pub(crate) main_device: Option<fn(&mut dyn ApplicationHandler, dev_t)>,
614632
}
615633

616634
impl RootActiveEventLoop for ActiveEventLoop {

winit-wayland/src/lib.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ use std::ffi::c_void;
1717
use std::ptr::NonNull;
1818

1919
use dpi::{LogicalSize, PhysicalSize};
20+
use libc::dev_t;
2021
use sctk::reexports::client::protocol::wl_surface::WlSurface;
2122
use sctk::reexports::client::Proxy;
2223
use sctk::shm::slot::{Buffer, CreateBufferError, SlotPool};
2324
use wayland_client::protocol::wl_shm::Format;
25+
use winit_core::application::ApplicationHandler;
2426
use winit_core::event_loop::ActiveEventLoop as CoreActiveEventLoop;
2527
use winit_core::window::{
2628
ActivationToken, PlatformWindowAttributes, Window as CoreWindow, WindowId,
@@ -42,6 +44,33 @@ mod window;
4244
pub use self::event_loop::{ActiveEventLoop, EventLoop};
4345
pub use self::window::Window;
4446

47+
/// Listen to Linux Direct Rendering Manager (DRM) events.
48+
pub trait LinuxDrm: ApplicationHandler {
49+
/// Returns the device that the system prefers to use.
50+
///
51+
/// The EGL EGL_EXT_device_drm and Vulkan VK_EXT_physical_device_drm extensions can be
52+
/// used to select a matching device for accelerated rendering.
53+
///
54+
/// This function returns `None` if the device is unknown.
55+
fn main_device(&mut self, device: dev_t);
56+
}
57+
58+
impl EventLoop {
59+
pub fn listen_linux_dmabuf<T: LinuxDrm + 'static>(&mut self) {
60+
self.active_event_loop.extensions.main_device =
61+
Some(|app: &mut dyn ApplicationHandler, device: dev_t| {
62+
app.as_any()
63+
.expect("as_any not implemented")
64+
.downcast_mut::<T>()
65+
.unwrap()
66+
.main_device(device);
67+
});
68+
69+
let queue_handle = &self.active_event_loop.queue_handle;
70+
self.active_event_loop.state.get_mut().register_linux_dmabuf(queue_handle);
71+
}
72+
}
73+
4574
/// Additional methods on [`ActiveEventLoop`] that are specific to Wayland.
4675
pub trait ActiveEventLoopExtWayland {
4776
/// True if the [`ActiveEventLoop`] uses Wayland.

winit-wayland/src/state.rs

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::sync::atomic::Ordering;
33
use std::sync::{Arc, Mutex};
44

55
use ahash::AHashMap;
6+
use libc::dev_t;
67
use sctk::compositor::{CompositorHandler, CompositorState};
78
use sctk::output::{OutputHandler, OutputState};
89
use sctk::reexports::calloop::LoopHandle;
@@ -40,6 +41,8 @@ use crate::WindowId;
4041
/// Winit's Wayland state.
4142
#[derive(Debug)]
4243
pub struct WinitState {
44+
globals: GlobalList,
45+
4346
/// The WlRegistry.
4447
pub registry_state: RegistryState,
4548

@@ -125,20 +128,27 @@ pub struct WinitState {
125128

126129
/// Whether the user initiated a wake up.
127130
pub proxy_wake_up: bool,
131+
132+
pub extension_events: Vec<ExtensionEvents>,
133+
}
134+
135+
#[derive(Debug, Clone, Copy)]
136+
pub enum ExtensionEvents {
137+
LinuxMainDevice(dev_t),
128138
}
129139

130140
impl WinitState {
131141
pub fn new(
132-
globals: &GlobalList,
142+
globals: GlobalList,
133143
queue_handle: &QueueHandle<Self>,
134144
loop_handle: LoopHandle<'static, WinitState>,
135145
) -> Result<Self, OsError> {
136-
let registry_state = RegistryState::new(globals);
146+
let registry_state = RegistryState::new(&globals);
137147
let compositor_state =
138-
CompositorState::bind(globals, queue_handle).map_err(|err| os_error!(err))?;
148+
CompositorState::bind(&globals, queue_handle).map_err(|err| os_error!(err))?;
139149
let subcompositor_state = match SubcompositorState::bind(
140150
compositor_state.wl_compositor().clone(),
141-
globals,
151+
&globals,
142152
queue_handle,
143153
) {
144154
Ok(c) => Some(c),
@@ -148,26 +158,24 @@ impl WinitState {
148158
},
149159
};
150160

151-
let output_state = OutputState::new(globals, queue_handle);
161+
let output_state = OutputState::new(&globals, queue_handle);
152162
let monitors = output_state.outputs().map(MonitorHandle::new).collect();
153163

154-
let seat_state = SeatState::new(globals, queue_handle);
164+
let seat_state = SeatState::new(&globals, queue_handle);
155165

156166
let mut seats = AHashMap::default();
157167
for seat in seat_state.seats() {
158168
seats.insert(seat.id(), WinitSeatState::new());
159169
}
160170

161171
let (viewporter_state, fractional_scaling_manager) =
162-
if let Ok(fsm) = FractionalScalingManager::new(globals, queue_handle) {
163-
(ViewporterState::new(globals, queue_handle).ok(), Some(fsm))
172+
if let Ok(fsm) = FractionalScalingManager::new(&globals, queue_handle) {
173+
(ViewporterState::new(&globals, queue_handle).ok(), Some(fsm))
164174
} else {
165175
(None, None)
166176
};
167177

168-
let linux_dmabuf_manager = LinuxDmabufManager::new(globals, queue_handle).ok();
169-
170-
let shm = Shm::bind(globals, queue_handle).map_err(|err| os_error!(err))?;
178+
let shm = Shm::bind(&globals, queue_handle).map_err(|err| os_error!(err))?;
171179
let image_pool = Arc::new(Mutex::new(SlotPool::new(2, &shm).unwrap()));
172180

173181
Ok(Self {
@@ -178,9 +186,9 @@ impl WinitState {
178186
seat_state,
179187
shm,
180188

181-
xdg_shell: XdgShell::bind(globals, queue_handle).map_err(|err| os_error!(err))?,
182-
xdg_activation: XdgActivationState::bind(globals, queue_handle).ok(),
183-
xdg_toplevel_icon_manager: XdgToplevelIconManagerState::bind(globals, queue_handle)
189+
xdg_shell: XdgShell::bind(&globals, queue_handle).map_err(|err| os_error!(err))?,
190+
xdg_activation: XdgActivationState::bind(&globals, queue_handle).ok(),
191+
xdg_toplevel_icon_manager: XdgToplevelIconManagerState::bind(&globals, queue_handle)
184192
.ok(),
185193

186194
image_pool,
@@ -191,14 +199,14 @@ impl WinitState {
191199
window_events_sink: Default::default(),
192200
viewporter_state,
193201
fractional_scaling_manager,
194-
kwin_blur_manager: KWinBlurManager::new(globals, queue_handle).ok(),
195-
linux_dmabuf_manager,
202+
linux_dmabuf_manager: None,
203+
kwin_blur_manager: KWinBlurManager::new(&globals, queue_handle).ok(),
196204

197205
seats,
198-
text_input_state: TextInputState::new(globals, queue_handle).ok(),
206+
text_input_state: TextInputState::new(&globals, queue_handle).ok(),
199207

200-
relative_pointer: RelativePointerState::new(globals, queue_handle).ok(),
201-
pointer_constraints: PointerConstraintsState::new(globals, queue_handle)
208+
relative_pointer: RelativePointerState::new(&globals, queue_handle).ok(),
209+
pointer_constraints: PointerConstraintsState::new(&globals, queue_handle)
202210
.map(Arc::new)
203211
.ok(),
204212
pointer_surfaces: Default::default(),
@@ -209,9 +217,17 @@ impl WinitState {
209217
// Make it true by default.
210218
dispatched_events: true,
211219
proxy_wake_up: false,
220+
extension_events: Vec::new(),
221+
globals,
212222
})
213223
}
214224

225+
pub fn register_linux_dmabuf(&mut self, queue_handle: &QueueHandle<Self>) {
226+
if self.linux_dmabuf_manager.is_none() {
227+
self.linux_dmabuf_manager = LinuxDmabufManager::new(&self.globals, queue_handle).ok();
228+
}
229+
}
230+
215231
pub fn scale_factor_changed(
216232
&mut self,
217233
surface: &WlSurface,

0 commit comments

Comments
 (0)