Skip to content

Commit

Permalink
Implement Surface Creation For Xlib and Wayland
Browse files Browse the repository at this point in the history
  • Loading branch information
zicklag committed Feb 25, 2020
1 parent 02589fe commit d35f34b
Showing 1 changed file with 98 additions and 2 deletions.
100 changes: 98 additions & 2 deletions src/backend/gl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ extern crate gfx_hal as hal;
pub extern crate glutin;

use std::cell::Cell;
use std::ffi::c_void;
use std::fmt;
use std::ops::Deref;
use std::os::raw::c_ulong;
use std::sync::{Arc, Weak};
use std::thread::{self, ThreadId};

Expand Down Expand Up @@ -736,6 +738,83 @@ pub enum Instance {
Surface(Surface),
}

use glutin::platform::unix::RawContextExt;
impl Instance {

pub fn create_surface_from_wayland(
&self,
display: *mut c_void,
surface: *mut c_void,
) -> Surface {
log::trace!("Creating GL surface from wayland");
let context = unsafe {
glutin::ContextBuilder::new()
.with_vsync(true)
.build_raw_wayland_context(
display as _,
surface,
/*TODO: do something with these dimensions*/
400,
400,
)
.expect("TODO: handle this error")
};
let context = unsafe { context.make_current().expect("TODO: handle this error") };
Surface::from_context(context)
}

pub fn create_surface_from_xlib(&self, window: c_ulong, display: *mut c_void) -> Surface {
log::trace!("Creating GL surface from Xlib");
let xconn = {
// This is taken from `glutin::platform::unix::x11::XConnection::new except with tweaks
// that allow us to create the connection with an existing display pointer
use glutin::platform::unix::x11::{XConnection, ffi};

// opening the libraries
let xlib = ffi::Xlib::open().expect("TODO: Handle error");
let xcursor = ffi::Xcursor::open().expect("TODO: Handle error");
let xrandr = ffi::Xrandr_2_2_0::open().expect("TODO: Handle error");
let xrandr_1_5 = ffi::Xrandr::open().ok();
let xinput2 = ffi::XInput2::open().expect("TODO: Handle error");
let xlib_xcb = ffi::Xlib_xcb::open().expect("TODO: Handle error");
let xrender = ffi::Xrender::open().expect("TODO: Handle error");

unsafe { (xlib.XInitThreads)() };
// unsafe { (xlib.XSetErrorHandler)(error_handler) };

// Get X11 socket file descriptor
let fd = unsafe { (xlib.XConnectionNumber)(display as *mut ffi::_XDisplay) };

XConnection {
xlib,
xrandr,
xrandr_1_5,
xcursor,
xinput2,
xlib_xcb,
xrender,
display: display as _,
x11_fd: fd,
latest_error: parking_lot::Mutex::new(None),
cursor_cache: Default::default(),
}
};
let xconn = Arc::new(xconn);

let context = unsafe {
glutin::ContextBuilder::new()
.with_vsync(true)
.build_raw_x11_context(
xconn,
window
)
.expect("TODO: handle this error")
};
let context = unsafe { context.make_current().expect("TODO: handle this error") };
Surface::from_context(context)
}
}

#[cfg(all(feature = "glutin", not(target_arch = "wasm32")))]
impl hal::Instance<Backend> for Instance {
fn create(name: &str, version: u32) -> Result<Instance, hal::UnsupportedBackend> {
Expand All @@ -751,9 +830,26 @@ impl hal::Instance<Backend> for Instance {

unsafe fn create_surface(
&self,
_: &impl raw_window_handle::HasRawWindowHandle,
has_handle: &impl raw_window_handle::HasRawWindowHandle,
) -> Result<Surface, hal::window::InitError> {
unimplemented!()
use raw_window_handle::RawWindowHandle;

match has_handle.raw_window_handle() {
#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
RawWindowHandle::Wayland(handle) => {
Ok(self.create_surface_from_wayland(handle.display, handle.surface))
}
#[cfg(all(
feature = "x11",
unix,
not(target_os = "android"),
not(target_os = "macos")
))]
RawWindowHandle::Xlib(handle) => {
Ok(self.create_surface_from_xlib(handle.display as *mut _, handle.window))
}
_ => Err(hal::window::InitError::UnsupportedWindowHandle),
}
}

unsafe fn destroy_surface(&self, _surface: Surface) {
Expand Down

0 comments on commit d35f34b

Please sign in to comment.