diff options
Diffstat (limited to 'src/api/x11')
-rw-r--r-- | src/api/x11/mod.rs | 170 |
1 files changed, 51 insertions, 119 deletions
diff --git a/src/api/x11/mod.rs b/src/api/x11/mod.rs index c4c5a76..0bb5c88 100644 --- a/src/api/x11/mod.rs +++ b/src/api/x11/mod.rs @@ -15,11 +15,13 @@ use CursorState; use GlRequest; use PixelFormat; +use api::glx::Context as GlxContext; + pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; mod events; -mod ffi; mod monitor; +pub mod ffi; static THREAD_INIT: Once = ONCE_INIT; @@ -42,16 +44,17 @@ fn ensure_thread_init() { }); } +// TODO: remove me fn with_c_str<F, T>(s: &str, f: F) -> T where F: FnOnce(*const libc::c_char) -> T { use std::ffi::CString; let c_str = CString::new(s.as_bytes().to_vec()).unwrap(); f(c_str.as_ptr()) } -struct XWindow { +pub struct XWindow { display: *mut ffi::Display, window: ffi::Window, - context: ffi::GLXContext, + pub context: Context, is_fullscreen: bool, screen_id: libc::c_int, xf86_desk_mode: *mut ffi::XF86VidModeModeInfo, @@ -59,6 +62,11 @@ struct XWindow { im: ffi::XIM, } +pub enum Context { + Glx(GlxContext), + None, +} + unsafe impl Send for XWindow {} unsafe impl Sync for XWindow {} @@ -70,7 +78,7 @@ impl Drop for XWindow { unsafe { // we don't call MakeCurrent(0, 0) because we are not sure that the context // is still the current one - ffi::glx::DestroyContext(self.display as *mut _, self.context); + self.context = Context::None; if self.is_fullscreen { ffi::XF86VidModeSwitchToMode(self.display, self.screen_id, self.xf86_desk_mode); @@ -282,7 +290,7 @@ impl<'a> Iterator for WaitEventsIterator<'a> { } pub struct Window { - x: Arc<XWindow>, + pub x: Arc<XWindow>, is_closed: AtomicBool, wm_delete_window: ffi::Atom, current_size: Cell<(libc::c_int, libc::c_int)>, @@ -528,109 +536,22 @@ impl Window { }); } - // creating GL context - let (context, extra_functions) = unsafe { - let mut attributes = Vec::new(); - - match builder.gl_version { - GlRequest::Latest => {}, - GlRequest::Specific(Api::OpenGl, (major, minor)) => { - attributes.push(ffi::glx_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); - attributes.push(major as libc::c_int); - attributes.push(ffi::glx_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); - attributes.push(minor as libc::c_int); - }, - GlRequest::Specific(_, _) => panic!("Only OpenGL is supported"), - GlRequest::GlThenGles { opengl_version: (major, minor), .. } => { - attributes.push(ffi::glx_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); - attributes.push(major as libc::c_int); - attributes.push(ffi::glx_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); - attributes.push(minor as libc::c_int); - }, - } - - if builder.gl_debug { - attributes.push(ffi::glx_extra::CONTEXT_FLAGS_ARB as libc::c_int); - attributes.push(ffi::glx_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int); - } - - attributes.push(0); - - // loading the extra GLX functions - let extra_functions = ffi::glx_extra::Glx::load_with(|addr| { - with_c_str(addr, |s| { - use libc; - ffi::glx::GetProcAddress(s as *const u8) as *const libc::c_void - }) - }); - - let share = if let Some(win) = builder.sharing { - win.x.context - } else { - ptr::null() - }; - - let mut context = if extra_functions.CreateContextAttribsARB.is_loaded() { - extra_functions.CreateContextAttribsARB(display as *mut ffi::glx_extra::types::Display, - fb_config, share, 1, attributes.as_ptr()) - } else { - ptr::null() - }; - - if context.is_null() { - context = ffi::glx::CreateContext(display as *mut _, &mut visual_infos, share, 1) - } - - if context.is_null() { - return Err(OsError(format!("GL context creation failed"))); - } - - (context, extra_functions) + let is_fullscreen = builder.monitor.is_some(); + // creating the context + let context = match builder.gl_version { + GlRequest::Latest | GlRequest::Specific(Api::OpenGl, _) | GlRequest::GlThenGles { .. } => { + Context::Glx(try!(GlxContext::new(builder, display, window, + fb_config, visual_infos))) + }, + /*GlRequest::Specific(Api::OpenGlEs, _) => { + let egl = ::egl::ffi::egl::Egl; + Context::Egl(try!(EglContext::new(egl, builder, Some(display as *const _), window))) + },*/ + GlRequest::Specific(_, _) => { + return Err(CreationError::NotSupported); + }, }; - // vsync - if builder.vsync { - unsafe { ffi::glx::MakeCurrent(display as *mut _, window, context) }; - - if extra_functions.SwapIntervalEXT.is_loaded() { - // this should be the most common extension - unsafe { - extra_functions.SwapIntervalEXT(display as *mut _, window, 1); - } - - // checking that it worked - if builder.strict { - let mut swap = unsafe { mem::uninitialized() }; - unsafe { - ffi::glx::QueryDrawable(display as *mut _, window, - ffi::glx_extra::SWAP_INTERVAL_EXT as i32, - &mut swap); - } - - if swap != 1 { - return Err(OsError(format!("Couldn't setup vsync: expected \ - interval `1` but got `{}`", swap))); - } - } - - // GLX_MESA_swap_control is not official - /*} else if extra_functions.SwapIntervalMESA.is_loaded() { - unsafe { - extra_functions.SwapIntervalMESA(1); - }*/ - - } else if extra_functions.SwapIntervalSGI.is_loaded() { - unsafe { - extra_functions.SwapIntervalSGI(1); - } - - } else if builder.strict { - return Err(OsError(format!("Couldn't find any available vsync extension"))); - } - - unsafe { ffi::glx::MakeCurrent(display as *mut _, 0, ptr::null()) }; - } - // creating the window object let window = Window { x: Arc::new(XWindow { @@ -640,7 +561,7 @@ impl Window { ic: ic, context: context, screen_id: screen_id, - is_fullscreen: builder.monitor.is_some(), + is_fullscreen: is_fullscreen, xf86_desk_mode: xf86_desk_mode, }), is_closed: AtomicBool::new(false), @@ -743,28 +664,35 @@ impl Window { } pub unsafe fn make_current(&self) { - let res = ffi::glx::MakeCurrent(self.x.display as *mut _, self.x.window, self.x.context); - if res == 0 { - panic!("glx::MakeCurrent failed"); + match self.x.context { + Context::Glx(ref ctxt) => ctxt.make_current(), + //Context::Egl(ref ctxt) => ctxt.make_current(), + Context::None => {} } } pub fn is_current(&self) -> bool { - unsafe { ffi::glx::GetCurrentContext() == self.x.context } + match self.x.context { + Context::Glx(ref ctxt) => ctxt.is_current(), + //Context::Egl(ref ctxt) => ctxt.is_current(), + Context::None => panic!() + } } pub fn get_proc_address(&self, addr: &str) -> *const () { - use std::mem; - - unsafe { - with_c_str(addr, |s| { - ffi::glx::GetProcAddress(mem::transmute(s)) as *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() } } pub fn swap_buffers(&self) { - unsafe { ffi::glx::SwapBuffers(self.x.display as *mut _, self.x.window) } + match self.x.context { + Context::Glx(ref ctxt) => ctxt.swap_buffers(), + //Context::Egl(ref ctxt) => ctxt.swap_buffers(), + Context::None => {} + } } pub fn platform_display(&self) -> *mut libc::c_void { @@ -777,7 +705,11 @@ impl Window { /// See the docs in the crate root file. pub fn get_api(&self) -> ::Api { - ::Api::OpenGl + match self.x.context { + Context::Glx(ref ctxt) => ctxt.get_api(), + //Context::Egl(ref ctxt) => ctxt.get_api(), + Context::None => panic!() + } } pub fn get_pixel_format(&self) -> PixelFormat { |