Make it compile on Linux

This commit is contained in:
Pierre Krieger 2016-02-27 13:59:11 +01:00
parent b4d4fee8b6
commit 16f76b2407
11 changed files with 16 additions and 729 deletions

View file

@ -4,17 +4,4 @@ pub use x11_dl::xf86vmode::*;
pub use x11_dl::xlib::*;
pub use x11_dl::xinput::*;
pub use x11_dl::xinput2::*;
pub use x11_dl::error::OpenError;
pub use self::glx::types::GLXContext;
/// GLX bindings
pub mod glx {
include!(concat!(env!("OUT_DIR"), "/glx_bindings.rs"));
}
/// Functions that are not necessarly always available
pub mod glx_extra {
include!(concat!(env!("OUT_DIR"), "/glx_extra_bindings.rs"));
}

View file

@ -1,7 +1,7 @@
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd"))]
pub use self::monitor::{MonitorId, get_available_monitors, get_primary_monitor};
pub use self::window::{Window, XWindow, PollEventsIterator, WaitEventsIterator, Context, WindowProxy};
pub use self::window::{Window, XWindow, PollEventsIterator, WaitEventsIterator, WindowProxy};
pub use self::xdisplay::{XConnection, XNotSupported, XError};
pub mod ffi;

View file

@ -12,20 +12,9 @@ use std::os::raw::c_long;
use std::thread;
use std::time::Duration;
use Api;
use ContextError;
use CursorState;
use GlAttributes;
use GlContext;
use GlRequest;
use PixelFormat;
use PixelFormatRequirements;
use WindowAttributes;
use api::glx::Context as GlxContext;
use api::egl;
use api::egl::Context as EglContext;
use platform::MonitorId as PlatformMonitorId;
use super::input::XInputEventHandler;
@ -54,22 +43,14 @@ unsafe impl Send for WindowProxyData {}
pub struct XWindow {
display: Arc<XConnection>,
window: ffi::Window,
pub context: Context,
is_fullscreen: bool,
screen_id: libc::c_int,
xf86_desk_mode: Option<ffi::XF86VidModeModeInfo>,
ic: ffi::XIC,
im: ffi::XIM,
colormap: ffi::Colormap,
window_proxy_data: Arc<Mutex<Option<WindowProxyData>>>,
}
pub enum Context {
Glx(GlxContext),
Egl(EglContext),
None,
}
unsafe impl Send for XWindow {}
unsafe impl Sync for XWindow {}
@ -83,10 +64,6 @@ impl Drop for XWindow {
// are no longer able to send messages to this window.
*self.window_proxy_data.lock().unwrap() = None;
// we don't call MakeCurrent(0, 0) because we are not sure that the context
// is still the current one
self.context = Context::None;
let _lock = GLOBAL_XOPENIM_LOCK.lock().unwrap();
if self.is_fullscreen {
@ -99,7 +76,6 @@ impl Drop for XWindow {
(self.display.xlib.XDestroyIC)(self.ic);
(self.display.xlib.XCloseIM)(self.im);
(self.display.xlib.XDestroyWindow)(self.display.display, self.window);
(self.display.xlib.XFreeColormap)(self.display.display, self.colormap);
}
}
}
@ -306,8 +282,7 @@ pub struct Window {
}
impl Window {
pub fn new(display: &Arc<XConnection>, window_attrs: &WindowAttributes,
pf_reqs: &PixelFormatRequirements, opengl: &GlAttributes<&Window>)
pub fn new(display: &Arc<XConnection>, window_attrs: &WindowAttributes)
-> Result<Window, CreationError>
{
let dimensions = window_attrs.dimensions.unwrap_or((800, 600));
@ -353,76 +328,14 @@ impl Window {
}
};
// start the context building process
enum Prototype<'a> {
Glx(::api::glx::ContextPrototype<'a>),
Egl(::api::egl::ContextPrototype<'a>),
}
let builder_clone_opengl_glx = opengl.clone().map_sharing(|_| unimplemented!()); // FIXME:
let builder_clone_opengl_egl = opengl.clone().map_sharing(|_| unimplemented!()); // FIXME:
let context = match opengl.version {
GlRequest::Latest | GlRequest::Specific(Api::OpenGl, _) | GlRequest::GlThenGles { .. } => {
// GLX should be preferred over EGL, otherwise crashes may occur
// on X11 issue #314
if let Some(ref glx) = display.glx {
Prototype::Glx(try!(GlxContext::new(glx.clone(), &display.xlib, pf_reqs, &builder_clone_opengl_glx, display.display, screen_id)))
} else if let Some(ref egl) = display.egl {
Prototype::Egl(try!(EglContext::new(egl.clone(), pf_reqs, &builder_clone_opengl_egl, egl::NativeDisplay::X11(Some(display.display as *const _)))))
} else {
return Err(CreationError::NotSupported);
}
},
GlRequest::Specific(Api::OpenGlEs, _) => {
if let Some(ref egl) = display.egl {
Prototype::Egl(try!(EglContext::new(egl.clone(), pf_reqs, &builder_clone_opengl_egl, egl::NativeDisplay::X11(Some(display.display as *const _)))))
} else {
return Err(CreationError::NotSupported);
}
},
GlRequest::Specific(_, _) => {
return Err(CreationError::NotSupported);
},
};
// getting the `visual_infos` (a struct that contains information about the visual to use)
let visual_infos = match context {
Prototype::Glx(ref p) => p.get_visual_infos().clone(),
Prototype::Egl(ref p) => {
unsafe {
let mut template: ffi::XVisualInfo = mem::zeroed();
template.visualid = p.get_native_visual_id() as ffi::VisualID;
let mut num_visuals = 0;
let vi = (display.xlib.XGetVisualInfo)(display.display, ffi::VisualIDMask,
&mut template, &mut num_visuals);
display.check_errors().expect("Failed to call XGetVisualInfo");
assert!(!vi.is_null());
assert!(num_visuals == 1);
let vi_copy = ptr::read(vi as *const _);
(display.xlib.XFree)(vi as *mut _);
vi_copy
}
},
};
// getting the root window
let root = unsafe { (display.xlib.XDefaultRootWindow)(display.display) };
display.check_errors().expect("Failed to get root window");
// creating the color map
let cmap = unsafe {
let cmap = (display.xlib.XCreateColormap)(display.display, root,
visual_infos.visual as *mut _,
ffi::AllocNone);
display.check_errors().expect("Failed to call XCreateColormap");
cmap
};
// creating
let mut set_win_attr = {
let mut swa: ffi::XSetWindowAttributes = unsafe { mem::zeroed() };
swa.colormap = cmap;
swa.colormap = 0;
swa.event_mask = ffi::ExposureMask | ffi::StructureNotifyMask |
ffi::VisibilityChangeMask | ffi::KeyPressMask | ffi::PointerMotionMask |
ffi::KeyReleaseMask | ffi::ButtonPressMask |
@ -444,8 +357,8 @@ impl Window {
// finally creating the window
let window = unsafe {
let win = (display.xlib.XCreateWindow)(display.display, root, 0, 0, dimensions.0 as libc::c_uint,
dimensions.1 as libc::c_uint, 0, visual_infos.depth, ffi::InputOutput as libc::c_uint,
visual_infos.visual as *mut _, window_attributes,
dimensions.1 as libc::c_uint, 0, ffi::CopyFromParent, ffi::InputOutput as libc::c_uint,
ffi::CopyFromParent as *mut _, window_attributes,
&mut set_win_attr);
display.check_errors().expect("Failed to call XCreateWindow");
win
@ -591,19 +504,6 @@ impl Window {
}
}
// finish creating the OpenGL context
let context = match context {
Prototype::Glx(ctxt) => {
Context::Glx(try!(ctxt.finish(window)))
},
Prototype::Egl(ctxt) => {
Context::Egl(try!(ctxt.finish(window as *const libc::c_void)))
},
};
// creating the OpenGL can produce errors, but since everything is checked we ignore
display.ignore_error();
// creating the window object
let window_proxy_data = WindowProxyData {
display: display.clone(),
@ -617,11 +517,9 @@ impl Window {
window: window,
im: im,
ic: ic,
context: context,
screen_id: screen_id,
is_fullscreen: is_fullscreen,
xf86_desk_mode: xf86_desk_mode,
colormap: cmap,
window_proxy_data: window_proxy_data,
}),
is_closed: AtomicBool::new(false),
@ -906,59 +804,3 @@ impl Window {
}
}
}
impl GlContext for Window {
#[inline]
unsafe fn make_current(&self) -> Result<(), ContextError> {
match self.x.context {
Context::Glx(ref ctxt) => ctxt.make_current(),
Context::Egl(ref ctxt) => ctxt.make_current(),
Context::None => Ok(())
}
}
#[inline]
fn is_current(&self) -> bool {
match self.x.context {
Context::Glx(ref ctxt) => ctxt.is_current(),
Context::Egl(ref ctxt) => ctxt.is_current(),
Context::None => panic!()
}
}
#[inline]
fn get_proc_address(&self, addr: &str) -> *const () {
match self.x.context {
Context::Glx(ref ctxt) => ctxt.get_proc_address(addr),
Context::Egl(ref ctxt) => ctxt.get_proc_address(addr),
Context::None => ptr::null()
}
}
#[inline]
fn swap_buffers(&self) -> Result<(), ContextError> {
match self.x.context {
Context::Glx(ref ctxt) => ctxt.swap_buffers(),
Context::Egl(ref ctxt) => ctxt.swap_buffers(),
Context::None => Ok(())
}
}
#[inline]
fn get_api(&self) -> Api {
match self.x.context {
Context::Glx(ref ctxt) => ctxt.get_api(),
Context::Egl(ref ctxt) => ctxt.get_api(),
Context::None => panic!()
}
}
#[inline]
fn get_pixel_format(&self) -> PixelFormat {
match self.x.context {
Context::Glx(ref ctxt) => ctxt.get_pixel_format(),
Context::Egl(ref ctxt) => ctxt.get_pixel_format(),
Context::None => panic!()
}
}
}

View file

@ -7,7 +7,6 @@ use std::sync::Mutex;
use libc;
use super::ffi;
use api::egl::ffi::egl::Egl;
use api::dlopen;
/// A connection to an X server.
@ -16,8 +15,6 @@ pub struct XConnection {
pub xf86vmode: ffi::Xf86vmode,
pub xcursor: ffi::Xcursor,
pub xinput2: ffi::XInput2,
pub glx: Option<ffi::glx::Glx>,
pub egl: Option<Egl>,
pub display: *mut ffi::Display,
pub latest_error: Mutex<Option<XError>>,
}
@ -38,40 +35,6 @@ impl XConnection {
unsafe { (xlib.XInitThreads)() };
unsafe { (xlib.XSetErrorHandler)(error_handler) };
// TODO: use something safer than raw "dlopen"
let glx = {
let mut libglx = unsafe { dlopen::dlopen(b"libGL.so.1\0".as_ptr() as *const _, dlopen::RTLD_NOW) };
if libglx.is_null() {
libglx = unsafe { dlopen::dlopen(b"libGL.so\0".as_ptr() as *const _, dlopen::RTLD_NOW) };
}
if libglx.is_null() {
None
} else {
Some(ffi::glx::Glx::load_with(|sym| {
let sym = CString::new(sym).unwrap();
unsafe { dlopen::dlsym(libglx, sym.as_ptr()) }
}))
}
};
// TODO: use something safer than raw "dlopen"
let egl = {
let mut libegl = unsafe { dlopen::dlopen(b"libEGL.so.1\0".as_ptr() as *const _, dlopen::RTLD_NOW) };
if libegl.is_null() {
libegl = unsafe { dlopen::dlopen(b"libEGL.so\0".as_ptr() as *const _, dlopen::RTLD_NOW) };
}
if libegl.is_null() {
None
} else {
Some(Egl::load_with(|sym| {
let sym = CString::new(sym).unwrap();
unsafe { dlopen::dlsym(libegl, sym.as_ptr()) }
}))
}
};
// calling XOpenDisplay
let display = unsafe {
let display = (xlib.XOpenDisplay)(ptr::null());
@ -86,8 +49,6 @@ impl XConnection {
xf86vmode: xf86vmode,
xcursor: xcursor,
xinput2: xinput2,
glx: glx,
egl: egl,
display: display,
latest_error: Mutex::new(None),
})