8000 Improve wayland support and make it the default by TheRedDeveloper · Pull Request #662 · not-fl3/miniquad · GitHub
[go: up one dir, main page]

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ pub enum LinuxX11Gl {
/// Defaults to `X11Only`. The Wayland implementation is currently unstable
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum LinuxBackend {
/// Use only the X11 backend. Panics if unavailable. This is the default choice.
#[default]
/// Use only the X11 backend. Panics if unavailable.
X11Only,
/// Use only the Wayland backend. Panics if unavailable.
WaylandOnly,
/// Prefer X11, fall back to Wayland if X11 is unavailable.
X11WithWaylandFallback,
/// Prefer Wayland, fall back to X11 if Wayland is unavailable.
/// Prefer Wayland, fall back to X11 if Wayland is unavailable. This is the default choice.
#[default]
WaylandWithX11Fallback,
}

Expand Down
8000
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,13 +477,15 @@ where
if let Err(err) = native::linux_x11::run(&conf, f) {
eprintln!("{err:?}");
eprintln!("Failed to initialize through X11! Trying wayland instead");
native::linux_wayland::run(&conf, f);
if native::linux_wayland::run(&conf, f).is_none() {
panic!("Both X11 and Wayland backends failed");
}
}
}
conf::LinuxBackend::WaylandWithX11Fallback => {
if native::linux_wayland::run(&conf, f).is_none() {
eprintln!("Failed to initialize through wayland! Trying X11 instead");
native::linux_x11::run(&conf, f).unwrap()
native::linux_x11::run(&conf, f).expect("Both Wayland and X11 backends failed")
}
}
}
Expand Down
84 changes: 78 additions & 6 deletions src/native/linux_wayland.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ struct WaylandPayload {
keyboard_context: KeyboardContext,
drag_n_drop: drag_n_drop::WaylandDnD,
update_requested: bool,
frame_callback: *mut wl_callback,
background_timerfd: core::ffi::c_int,
blocking_event_loop: bool,
}

impl WaylandPayload {
Expand All @@ -83,12 +86,17 @@ impl WaylandPayload {
events: libc::POLLIN,
revents: 0,
},
libc::pollfd {
fd: self.background_timerfd,
events: libc::POLLIN,
revents: 0,
},
];
(self.client.wl_display_flush)(self.display);
while (self.client.wl_display_prepare_read)(self.display) != 0 {
(self.client.wl_display_dispatch_pending)(self.display);
}
if libc::poll(fds.as_mut_ptr(), 2, if blocking { i32::MAX } else { 0 }) > 0 {
if libc::poll(fds.as_mut_ptr(), 3, if blocking { i32::MAX } else { 0 }) > 0 {
// if the Wayland display has events available
if fds[0].revents & libc::POLLIN == 1 {
(self.client.wl_display_read_events)(self.display);
Expand Down Expand Up @@ -117,6 +125,18 @@ impl WaylandPayload {
);
}
}
if fds[2].revents & libc::POLLIN == 1 {
let mut count: [libc::size_t; 1] = [0];
let n_bits = core::mem::size_of::<libc::size_t>();
let _ = libc::read(
self.background_timerfd,
count.as_mut_ptr() as _,
n_bits,
);
if !self.blocking_event_loop {
self.update_requested = true;
}
}
} else {
(self.client.wl_display_cancel_read)(self.display);
}
Expand Down Expand Up @@ -240,6 +260,19 @@ fn new_itimerspec() -> libc::itimerspec {
}
}

fn new_timerfd(interval: Duration) -> core::ffi::c_int {
unsafe {
let fd = libc::timerfd_create(libc::CLOCK_MONOTONIC, libc::TFD_CLOEXEC);
let mut timer = new_itimerspec();
timer.it_interval.tv_sec = interval.as_secs() as _;
timer.it_interval.tv_nsec = interval.subsec_nanos() as _;
timer.it_value.tv_sec = interval.as_secs() as _;
timer.it_value.tv_nsec = interval.subsec_nanos() as _;
libc::timerfd_settime(fd, 0, &timer, core::ptr::null_mut());
fd
}
}

impl KeyboardContext {
fn new() -> Self {
Self {
Expand Down Expand Up @@ -542,8 +575,24 @@ enum WaylandEvent {
Resize(f32, f32),
WindowMinimized,
WindowRestored,
FrameCompleted,
}

unsafe extern "C" fn frame_handle_done(
data: *mut ::core::ffi::c_void,
callback: *mut wl_callback,
_time: u32,
) {
let display: &mut WaylandPayload = &mut *(data as *mut _);
(display.client.wl_proxy_destroy)(callback as _);
display.frame_callback = std::ptr::null_mut();
display.events.push(WaylandEvent::FrameCompleted);
}

static mut FRAME_LISTENER: wl_callback_listener = wl_callback_listener {
done: frame_handle_done,
};

unsafe extern "C" fn keyboard_handle_keymap(
data: *mut ::core::ffi::c_void,
_wl_keyboard: *mut wl_keyboard,
Expand Down Expand Up @@ -1103,6 +1152,9 @@ where
keyboard_context: KeyboardContext::new(),
drag_n_drop: Default::default(),
update_requested: true,
frame_callback: std::ptr::null_mut(),
background_timerfd: new_timerfd(Duration::from_millis(2000)),
blocking_event_loop: conf.platform.blocking_event_loop,
};

let mut registry_listener = wl_registry_listener::dummy();
Expand Down Expand Up @@ -1168,7 +1220,7 @@ where
panic!("eglMakeCurrent failed");
}

if (libegl.eglSwapInterval)(egl_display, conf.platform.swap_interval.unwrap_or(1)) == 0 {
if (libegl.eglSwapInterval)(egl_display, 0) == 0 {
eprintln!("eglSwapInterval failed");
}

Expand Down Expand Up @@ -1252,9 +1304,7 @@ where
}
}

// If `blocking_event_loop` is set but an update is requested, we should still poll the
// new events but continue without blocking
let blocking = conf.platform.blocking_event_loop && !display.update_requested;
let blocking = !display.update_requested;
display.poll_new_event(blocking);

for event in display.events.drain(..) {
Expand Down Expand Up @@ -1291,6 +1341,11 @@ where
}
WaylandEvent::WindowMinimized => event_handler.window_minimized_event(),
WaylandEvent::WindowRestored => event_handler.window_restored_event(),
WaylandEvent::FrameCompleted => {
if !conf.platform.blocking_event_loop {
display.update_requested = true;
}
}
WaylandEvent::FilesDropped(filenames) => {
let mut d = crate::native_display().try_lock().unwrap();
d.dropped_files = Default::default();
Expand Down Expand Up @@ -1320,10 +1375,27 @@ where
}
}

if !conf.platform.blocking_event_loop || display.update_requested {
if display.update_requested {
display.update_requested = false;
event_handler.update();
event_handler.draw();

if display.frame_callback.is_null() {
display.frame_callback = wl_request_constructor!(
display.client,
display.surface,
WL_SURFACE_FRAME,
display.client.wl_callback_interface
);
if !display.frame_callback.is_null() {
(display.client.wl_proxy_add_listener)(
display.frame_callback as _,
&FRAME_LISTENER as *const _ as _,
&mut display as *mut _ as _,
);
}
}

(libegl.eglSwapBuffers)(egl_display, egl_surface);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/native/linux_wayland/libwayland_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ crate::declare_module!(
pub wl_data_device_manager_interface: *mut wl_interface,
pub wl_data_device_interface: *mut wl_interface,
pub wl_data_source_interface: *mut wl_interface,
pub wl_callback_interface: *mut wl_interface,
...
pub fn wl_display_connect(*const c_char) -> *mut wl_display,
pub fn wl_display_disconnect(*mut wl_display),
Expand Down
2 changes: 1 addition & 1 deletion src/native/linux_x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ where

let x11_display = (libx11.XOpenDisplay)(std::ptr::null());
if x11_display.is_null() {
panic!("XOpenDisplay() failed!");
return Err(X11Error::GLXError("XOpenDisplay() failed".to_string()));
}

// screen selection process. The place to do something about
Expand Down
Loading
0