aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/api/android/mod.rs1
-rw-r--r--src/api/cocoa/monitor.rs1
-rw-r--r--src/api/egl/mod.rs13
-rw-r--r--src/api/glx/mod.rs311
-rw-r--r--src/api/win32/monitor.rs1
-rw-r--r--src/api/x11/monitor.rs1
-rw-r--r--src/api/x11/window.rs173
-rw-r--r--src/lib.rs3
-rw-r--r--src/platform/linux/api_dispatch.rs1
9 files changed, 298 insertions, 207 deletions
diff --git a/src/api/android/mod.rs b/src/api/android/mod.rs
index b5fac08..83ef12b 100644
--- a/src/api/android/mod.rs
+++ b/src/api/android/mod.rs
@@ -30,6 +30,7 @@ pub struct Window {
event_rx: Receiver<android_glue::Event>,
}
+#[derive(Clone)]
pub struct MonitorID;
mod ffi;
diff --git a/src/api/cocoa/monitor.rs b/src/api/cocoa/monitor.rs
index 40c7896..138bbcd 100644
--- a/src/api/cocoa/monitor.rs
+++ b/src/api/cocoa/monitor.rs
@@ -2,6 +2,7 @@ use core_graphics::display;
use std::collections::VecDeque;
use native_monitor::NativeMonitorId;
+#[derive(Clone)]
pub struct MonitorID(u32);
pub fn get_available_monitors() -> VecDeque<MonitorID> {
diff --git a/src/api/egl/mod.rs b/src/api/egl/mod.rs
index 0cb6dbd..d22c009 100644
--- a/src/api/egl/mod.rs
+++ b/src/api/egl/mod.rs
@@ -472,9 +472,13 @@ unsafe fn create_context(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDispl
if egl_version >= &(1, 5) {
context_attributes.push(ffi::egl::CONTEXT_OPENGL_DEBUG as i32);
context_attributes.push(ffi::egl::TRUE as i32);
- } else {
- flags = flags | ffi::egl::CONTEXT_OPENGL_DEBUG_BIT_KHR as i32;
}
+
+ // TODO: using this flag sometimes generates an error
+ // there was a change in the specs that added this flag, so it may not be
+ // supported everywhere ; however it is not possible to know whether it is
+ // supported or not
+ //flags = flags | ffi::egl::CONTEXT_OPENGL_DEBUG_BIT_KHR as i32;
}
context_attributes.push(ffi::egl::CONTEXT_FLAGS_KHR as i32);
@@ -499,7 +503,10 @@ unsafe fn create_context(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDispl
context_attributes.as_ptr());
if context.is_null() {
- return Err(CreationError::NotSupported);
+ match egl.GetError() as u32 {
+ ffi::egl::BAD_ATTRIBUTE => return Err(CreationError::NotSupported),
+ e => panic!("eglCreateContext failed: 0x{:x}", e),
+ }
}
Ok(context)
diff --git a/src/api/glx/mod.rs b/src/api/glx/mod.rs
index d286813..3779597 100644
--- a/src/api/glx/mod.rs
+++ b/src/api/glx/mod.rs
@@ -23,6 +23,7 @@ pub struct Context {
display: *mut ffi::Display,
window: ffi::Window,
context: ffi::GLXContext,
+ pixel_format: PixelFormat,
}
// TODO: remove me
@@ -33,11 +34,157 @@ fn with_c_str<F, T>(s: &str, f: F) -> T where F: FnOnce(*const libc::c_char) ->
}
impl Context {
- pub fn new(glx: ffi::glx::Glx, builder: BuilderAttribs, display: *mut ffi::Display, window: ffi::Window,
- fb_config: ffi::glx::types::GLXFBConfig, mut visual_infos: ffi::glx::types::XVisualInfo)
- -> Result<Context, CreationError>
+ pub fn new<'a>(glx: ffi::glx::Glx, xlib: &ffi::Xlib, builder: &'a BuilderAttribs<'a>,
+ display: *mut ffi::Display)
+ -> Result<ContextPrototype<'a>, CreationError>
{
- let share = if let Some(win) = builder.sharing {
+ // finding the pixel format we want
+ // TODO: enumerate them instead
+ let fb_config = unsafe {
+ let mut visual_attributes = vec![
+ ffi::glx::X_RENDERABLE as libc::c_int, 1,
+ ffi::glx::DRAWABLE_TYPE as libc::c_int, ffi::glx::WINDOW_BIT as libc::c_int,
+ ffi::glx::RENDER_TYPE as libc::c_int, ffi::glx::RGBA_BIT as libc::c_int,
+ ffi::glx::X_VISUAL_TYPE as libc::c_int, ffi::glx::TRUE_COLOR as libc::c_int,
+ ffi::glx::RED_SIZE as libc::c_int, 8,
+ ffi::glx::GREEN_SIZE as libc::c_int, 8,
+ ffi::glx::BLUE_SIZE as libc::c_int, 8,
+ ffi::glx::ALPHA_SIZE as libc::c_int, 8,
+ ffi::glx::DEPTH_SIZE as libc::c_int, 24,
+ ffi::glx::STENCIL_SIZE as libc::c_int, 8,
+ ffi::glx::DOUBLEBUFFER as libc::c_int, 1,
+ ];
+
+ if let Some(val) = builder.multisampling {
+ visual_attributes.push(ffi::glx::SAMPLE_BUFFERS as libc::c_int);
+ visual_attributes.push(1);
+ visual_attributes.push(ffi::glx::SAMPLES as libc::c_int);
+ visual_attributes.push(val as libc::c_int);
+ }
+
+ if let Some(val) = builder.srgb {
+ visual_attributes.push(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as libc::c_int);
+ visual_attributes.push(if val {1} else {0});
+ }
+
+ visual_attributes.push(0);
+
+ let mut num_fb: libc::c_int = mem::uninitialized();
+
+ let fb = glx.ChooseFBConfig(display as *mut _, (xlib.XDefaultScreen)(display),
+ visual_attributes.as_ptr(), &mut num_fb);
+ if fb.is_null() {
+ return Err(CreationError::OsError(format!("glxChooseFBConfig failed")));
+ }
+
+ let preferred_fb = if builder.transparent {
+ let mut best_fbi_for_transparent = 0isize;
+
+ for i in 0isize..num_fb as isize {
+ let vi = glx.GetVisualFromFBConfig(display as *mut _, *fb.offset(i));
+ if (*vi).depth == 32 {
+ best_fbi_for_transparent = i;
+ break;
+ }
+ }
+
+ *fb.offset(best_fbi_for_transparent)
+ } else {
+ *fb // TODO: choose more wisely
+ };
+
+ (xlib.XFree)(fb as *mut _);
+ preferred_fb
+ };
+
+ // getting the visual infos
+ let visual_infos: ffi::glx::types::XVisualInfo = unsafe {
+ let vi = glx.GetVisualFromFBConfig(display as *mut _, fb_config);
+ if vi.is_null() {
+ return Err(CreationError::OsError(format!("glxGetVisualFromFBConfig failed")));
+ }
+ let vi_copy = ptr::read(vi as *const _);
+ (xlib.XFree)(vi as *mut _);
+ vi_copy
+ };
+
+ Ok(ContextPrototype {
+ glx: glx,
+ builder: builder,
+ display: display,
+ fb_config: fb_config,
+ visual_infos: unsafe { mem::transmute(visual_infos) },
+ })
+ }
+}
+
+impl GlContext for Context {
+ unsafe fn make_current(&self) -> Result<(), ContextError> {
+ // TODO: glutin needs some internal changes for proper error recovery
+ let res = self.glx.MakeCurrent(self.display as *mut _, self.window, self.context);
+ if res == 0 {
+ panic!("glx::MakeCurrent failed");
+ }
+ Ok(())
+ }
+
+ fn is_current(&self) -> bool {
+ unsafe { self.glx.GetCurrentContext() == self.context }
+ }
+
+ fn get_proc_address(&self, addr: &str) -> *const libc::c_void {
+ let addr = CString::new(addr.as_bytes()).unwrap();
+ let addr = addr.as_ptr();
+ unsafe {
+ self.glx.GetProcAddress(addr as *const _) as *const _
+ }
+ }
+
+ fn swap_buffers(&self) -> Result<(), ContextError> {
+ // TODO: glutin needs some internal changes for proper error recovery
+ unsafe { self.glx.SwapBuffers(self.display as *mut _, self.window); }
+ Ok(())
+ }
+
+ fn get_api(&self) -> ::Api {
+ ::Api::OpenGl
+ }
+
+ fn get_pixel_format(&self) -> PixelFormat {
+ self.pixel_format.clone()
+ }
+}
+
+unsafe impl Send for Context {}
+unsafe impl Sync for Context {}
+
+impl Drop for Context {
+ fn drop(&mut self) {
+ unsafe {
+ if self.is_current() {
+ self.glx.MakeCurrent(self.display as *mut _, 0, ptr::null_mut());
+ }
+
+ self.glx.DestroyContext(self.display as *mut _, self.context);
+ }
+ }
+}
+
+pub struct ContextPrototype<'a> {
+ glx: ffi::glx::Glx,
+ builder: &'a BuilderAttribs<'a>,
+ display: *mut ffi::Display,
+ fb_config: ffi::glx::types::GLXFBConfig,
+ visual_infos: ffi::XVisualInfo,
+}
+
+impl<'a> ContextPrototype<'a> {
+ pub fn get_visual_infos(&self) -> &ffi::XVisualInfo {
+ &self.visual_infos
+ }
+
+ pub fn finish(self, window: ffi::Window) -> Result<Context, CreationError> {
+ let share = if let Some(win) = self.builder.sharing {
match win {
&PlatformWindow::X(ref win) => match win.x.context {
::api::x11::Context::Glx(ref c) => c.context,
@@ -51,7 +198,7 @@ impl Context {
// loading the list of extensions
let extensions = unsafe {
- let extensions = glx.QueryExtensionsString(display as *mut _, 0); // FIXME: screen number
+ let extensions = self.glx.QueryExtensionsString(self.display as *mut _, 0); // FIXME: screen number
let extensions = CStr::from_ptr(extensions).to_bytes().to_vec();
String::from_utf8(extensions).unwrap()
};
@@ -59,62 +206,66 @@ impl Context {
// loading the extra GLX functions
let extra_functions = ffi::glx_extra::Glx::load_with(|addr| {
with_c_str(addr, |s| {
- unsafe { glx.GetProcAddress(s as *const u8) as *const _ }
+ unsafe { self.glx.GetProcAddress(s as *const u8) as *const _ }
})
});
// creating GL context
- let context = match builder.gl_version {
+ let context = match self.builder.gl_version {
GlRequest::Latest => {
- if let Ok(ctxt) = create_context(&glx, &extra_functions, &extensions, (3, 2),
- builder.gl_profile, builder.gl_debug,
- builder.gl_robustness, share,
- display, fb_config, &mut visual_infos)
+ if let Ok(ctxt) = create_context(&self.glx, &extra_functions, &extensions, (3, 2),
+ self.builder.gl_profile, self.builder.gl_debug,
+ self.builder.gl_robustness, share,
+ self.display, self.fb_config, &self.visual_infos)
{
ctxt
- } else if let Ok(ctxt) = create_context(&glx, &extra_functions, &extensions, (3, 1),
- builder.gl_profile, builder.gl_debug,
- builder.gl_robustness, share, display,
- fb_config, &mut visual_infos)
+ } else if let Ok(ctxt) = create_context(&self.glx, &extra_functions, &extensions,
+ (3, 1), self.builder.gl_profile,
+ self.builder.gl_debug,
+ self.builder.gl_robustness, share, self.display,
+ self.fb_config, &self.visual_infos)
{
ctxt
} else {
- try!(create_context(&glx, &extra_functions, &extensions, (1, 0),
- builder.gl_profile, builder.gl_debug, builder.gl_robustness,
- share, display, fb_config, &mut visual_infos))
+ try!(create_context(&self.glx, &extra_functions, &extensions, (1, 0),
+ self.builder.gl_profile, self.builder.gl_debug,
+ self.builder.gl_robustness,
+ share, self.display, self.fb_config, &self.visual_infos))
}
},
GlRequest::Specific(Api::OpenGl, (major, minor)) => {
- try!(create_context(&glx, &extra_functions, &extensions, (major, minor),
- builder.gl_profile, builder.gl_debug, builder.gl_robustness,
- share, display, fb_config, &mut visual_infos))
+ try!(create_context(&self.glx, &extra_functions, &extensions, (major, minor),
+ self.builder.gl_profile, self.builder.gl_debug,
+ self.builder.gl_robustness, share, self.display, self.fb_config,
+ &self.visual_infos))
},
GlRequest::Specific(_, _) => panic!("Only OpenGL is supported"),
GlRequest::GlThenGles { opengl_version: (major, minor), .. } => {
- try!(create_context(&glx, &extra_functions, &extensions, (major, minor),
- builder.gl_profile, builder.gl_debug, builder.gl_robustness,
- share, display, fb_config, &mut visual_infos))
+ try!(create_context(&self.glx, &extra_functions, &extensions, (major, minor),
+ self.builder.gl_profile, self.builder.gl_debug,
+ self.builder.gl_robustness, share, self.display, self.fb_config,
+ &self.visual_infos))
},
};
// vsync
- if builder.vsync {
- unsafe { glx.MakeCurrent(display as *mut _, window, context) };
+ if self.builder.vsync {
+ unsafe { self.glx.MakeCurrent(self.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);
+ extra_functions.SwapIntervalEXT(self.display as *mut _, window, 1);
}
// checking that it worked
- if builder.strict {
+ if self.builder.strict {
let mut swap = unsafe { mem::uninitialized() };
unsafe {
- glx.QueryDrawable(display as *mut _, window,
- ffi::glx_extra::SWAP_INTERVAL_EXT as i32,
- &mut swap);
+ self.glx.QueryDrawable(self.display as *mut _, window,
+ ffi::glx_extra::SWAP_INTERVAL_EXT as i32,
+ &mut swap);
}
if swap != 1 {
@@ -134,79 +285,30 @@ impl Context {
extra_functions.SwapIntervalSGI(1);
}
- } else if builder.strict {
+ } else if self.builder.strict {
return Err(CreationError::OsError(format!("Couldn't find any available vsync extension")));
}
- unsafe { glx.MakeCurrent(display as *mut _, 0, ptr::null()) };
+ unsafe { self.glx.MakeCurrent(self.display as *mut _, 0, ptr::null()) };
}
+ let pixel_format = unsafe { get_pixel_format(&self.glx, self.display, self.fb_config) };
+
Ok(Context {
- glx: glx,
- display: display,
+ glx: self.glx,
+ display: self.display,
window: window,
context: context,
+ pixel_format: pixel_format,
})
}
}
-impl GlContext for Context {
- unsafe fn make_current(&self) -> Result<(), ContextError> {
- // TODO: glutin needs some internal changes for proper error recovery
- let res = self.glx.MakeCurrent(self.display as *mut _, self.window, self.context);
- if res == 0 {
- panic!("glx::MakeCurrent failed");
- }
- Ok(())
- }
-
- fn is_current(&self) -> bool {
- unsafe { self.glx.GetCurrentContext() == self.context }
- }
-
- fn get_proc_address(&self, addr: &str) -> *const libc::c_void {
- let addr = CString::new(addr.as_bytes()).unwrap();
- let addr = addr.as_ptr();
- unsafe {
- self.glx.GetProcAddress(addr as *const _) as *const _
- }
- }
-
- fn swap_buffers(&self) -> Result<(), ContextError> {
- // TODO: glutin needs some internal changes for proper error recovery
- unsafe { self.glx.SwapBuffers(self.display as *mut _, self.window); }
- Ok(())
- }
-
- fn get_api(&self) -> ::Api {
- ::Api::OpenGl
- }
-
- fn get_pixel_format(&self) -> PixelFormat {
- unimplemented!();
- }
-}
-
-unsafe impl Send for Context {}
-unsafe impl Sync for Context {}
-
-impl Drop for Context {
- fn drop(&mut self) {
- unsafe {
- if self.is_current() {
- self.glx.MakeCurrent(self.display as *mut _, 0, ptr::null_mut());
- }
-
- self.glx.DestroyContext(self.display as *mut _, self.context);
- }
- }
-}
-
fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx, extensions: &str,
version: (u8, u8), profile: Option<GlProfile>, debug: bool,
robustness: Robustness, share: ffi::GLXContext, display: *mut ffi::Display,
fb_config: ffi::glx::types::GLXFBConfig,
- visual_infos: &mut ffi::glx::types::XVisualInfo)
+ visual_infos: &ffi::XVisualInfo)
-> Result<ffi::GLXContext, CreationError>
{
unsafe {
@@ -274,7 +376,8 @@ fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx, ex
attributes.as_ptr())
} else {
- glx.CreateContext(display as *mut _, visual_infos, share, 1)
+ let visual_infos: *const ffi::XVisualInfo = visual_infos;
+ glx.CreateContext(display as *mut _, visual_infos as *mut _, share, 1)
};
if context.is_null() {
@@ -284,3 +387,33 @@ fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx, ex
Ok(context)
}
}
+
+unsafe fn get_pixel_format(glx: &ffi::glx::Glx, display: *mut ffi::Display,
+ fb_config: ffi::glx::types::GLXFBConfig) -> PixelFormat
+{
+ let get_attrib = |attrib: libc::c_int| -> i32 {
+ let mut value = 0;
+ glx.GetFBConfigAttrib(display as *mut _, fb_config, attrib, &mut value);
+ // TODO: check return value
+ value
+ };
+
+ // TODO: make sure everything is supported
+ PixelFormat {
+ hardware_accelerated: true,
+ color_bits: get_attrib(ffi::glx::RED_SIZE as libc::c_int) as u8 +
+ get_attrib(ffi::glx::GREEN_SIZE as libc::c_int) as u8 +
+ get_attrib(ffi::glx::BLUE_SIZE as libc::c_int) as u8,
+ alpha_bits: get_attrib(ffi::glx::ALPHA_SIZE as libc::c_int) as u8,
+ depth_bits: get_attrib(ffi::glx::DEPTH_SIZE as libc::c_int) as u8,
+ stencil_bits: get_attrib(ffi::glx::STENCIL_SIZE as libc::c_int) as u8,
+ stereoscopy: get_attrib(ffi::glx::STEREO as libc::c_int) != 0,
+ double_buffer: get_attrib(ffi::glx::DOUBLEBUFFER as libc::c_int) != 0,
+ multisampling: if get_attrib(ffi::glx::SAMPLE_BUFFERS as libc::c_int) != 0 {
+ Some(get_attrib(ffi::glx::SAMPLES as libc::c_int) as u16)
+ } else {
+ None
+ },
+ srgb: get_attrib(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as libc::c_int) != 0,
+ }
+}
diff --git a/src/api/win32/monitor.rs b/src/api/win32/monitor.rs
index 4b592cb..d87c928 100644
--- a/src/api/win32/monitor.rs
+++ b/src/api/win32/monitor.rs
@@ -7,6 +7,7 @@ use std::mem;
use native_monitor::NativeMonitorId;
/// Win32 implementation of the main `MonitorID` object.
+#[derive(Clone)]
pub struct MonitorID {
/// The system name of the adapter.
adapter_name: [winapi::WCHAR; 32],
diff --git a/src/api/x11/monitor.rs b/src/api/x11/monitor.rs
index d556930..90b12c2 100644
--- a/src/api/x11/monitor.rs
+++ b/src/api/x11/monitor.rs
@@ -4,6 +4,7 @@ use std::sync::Arc;
use super::XConnection;
use native_monitor::NativeMonitorId;
+#[derive(Clone)]
pub struct MonitorID(pub Arc<XConnection>, pub u32);
pub fn get_available_monitors(x: &Arc<XConnection>) -> VecDeque<MonitorID> {
diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs
index 79118ff..6a4f39a 100644
--- a/src/api/x11/window.rs
+++ b/src/api/x11/window.rs
@@ -271,7 +271,6 @@ pub struct Window {
is_closed: AtomicBool,
wm_delete_window: ffi::Atom,
current_size: Cell<(libc::c_int, libc::c_int)>,
- pixel_format: PixelFormat,
/// Events that have been retreived with XLib but not dispatched with iterators yet
pending_events: Mutex<VecDeque<Event>>,
cursor_state: Mutex<CursorState>,
@@ -287,64 +286,6 @@ impl Window {
_ => unsafe { (display.xlib.XDefaultScreen)(display.display) },
};
- // getting the FBConfig
- let fb_config = unsafe {
- let mut visual_attributes = vec![
- ffi::glx::X_RENDERABLE as libc::c_int, 1,
- ffi::glx::DRAWABLE_TYPE as libc::c_int, ffi::glx::WINDOW_BIT as libc::c_int,
- ffi::glx::RENDER_TYPE as libc::c_int, ffi::glx::RGBA_BIT as libc::c_int,
- ffi::glx::X_VISUAL_TYPE as libc::c_int, ffi::glx::TRUE_COLOR as libc::c_int,
- ffi::glx::RED_SIZE as libc::c_int, 8,
- ffi::glx::GREEN_SIZE as libc::c_int, 8,
- ffi::glx::BLUE_SIZE as libc::c_int, 8,
- ffi::glx::ALPHA_SIZE as libc::c_int, 8,
- ffi::glx::DEPTH_SIZE as libc::c_int, 24,
- ffi::glx::STENCIL_SIZE as libc::c_int, 8,
- ffi::glx::DOUBLEBUFFER as libc::c_int, 1,
- ];
-
- if let Some(val) = builder.multisampling {
- visual_attributes.push(ffi::glx::SAMPLE_BUFFERS as libc::c_int);
- visual_attributes.push(1);
- visual_attributes.push(ffi::glx::SAMPLES as libc::c_int);
- visual_attributes.push(val as libc::c_int);
- }
-
- if let Some(val) = builder.srgb {
- visual_attributes.push(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as libc::c_int);
- visual_attributes.push(if val {1} else {0});
- }
-
- visual_attributes.push(0);
-
- let mut num_fb: libc::c_int = mem::uninitialized();
-
- let fb = display.glx.as_ref().unwrap().ChooseFBConfig(display.display as *mut _, (display.xlib.XDefaultScreen)(display.display),
- visual_attributes.as_ptr(), &mut num_fb);
- if fb.is_null() {
- return Err(OsError(format!("glx::ChooseFBConfig failed")));
- }
-
- let preferred_fb = if builder.transparent {
- let mut best_fbi_for_transparent = 0isize;
-
- for i in 0isize..num_fb as isize {
- let vi = display.glx.as_ref().unwrap().GetVisualFromFBConfig(display.display as *mut _, *fb.offset(i));
- if (*vi).depth == 32 {
- best_fbi_for_transparent = i;
- break;
- }
- }
-
- *fb.offset(best_fbi_for_transparent)
- } else {
- *fb // TODO: choose more wisely
- };
-
- (display.xlib.XFree)(fb as *mut _);
- preferred_fb
- };
-
// finding the mode to switch to if necessary
let (mode_to_switch_to, xf86_desk_mode) = unsafe {
let mut mode_num: libc::c_int = mem::uninitialized();
@@ -385,40 +326,53 @@ impl Window {
(mode_to_switch_to, xf86_desk_mode)
};
- // getting the visual infos
- let visual_infos: ffi::glx::types::XVisualInfo = unsafe {
- let vi = display.glx.as_ref().unwrap().GetVisualFromFBConfig(display.display as *mut _, fb_config);
- if vi.is_null() {
- return Err(OsError(format!("glx::ChooseVisual failed")));
- }
- let vi_copy = ptr::read(vi as *const _);
- (display.xlib.XFree)(vi as *mut _);
- vi_copy
+ // start the context building process
+ enum Prototype<'a> {
+ Glx(::api::glx::ContextPrototype<'a>),
+ Egl(::api::egl::ContextPrototype<'a>),
+ }
+ let builder_clone = builder.clone();
+ let context = match builder.gl_version {
+ GlRequest::Latest | GlRequest::Specific(Api::OpenGl, _) | GlRequest::GlThenGles { .. } => {
+ if let Some(ref glx) = display.glx {
+ Prototype::Glx(try!(GlxContext::new(glx.clone(), &display.xlib, &builder_clone, display.display)))
+ } else if let Some(ref egl) = display.egl {
+ Prototype::Egl(try!(EglContext::new(egl.clone(), &builder_clone, 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(), &builder_clone, Some(display.display as *const _))))
+ } else {
+ return Err(CreationError::NotSupported);
+ }
+ },
+ GlRequest::Specific(_, _) => {
+ return Err(CreationError::NotSupported);
+ },
};
- // querying the chosen pixel format
- let pixel_format = {
- let get_attrib = |attrib: libc::c_int| -> i32 {
- let mut value = 0;
- unsafe { display.glx.as_ref().unwrap().GetFBConfigAttrib(display.display as *mut _, fb_config, attrib, &mut value); }
- value
- };
-
- PixelFormat {
- hardware_accelerated: true,
- color_bits: get_attrib(ffi::glx::RED_SIZE as libc::c_int) as u8 +
- get_attrib(ffi::glx::GREEN_SIZE as libc::c_int) as u8 +
- get_attrib(ffi::glx::BLUE_SIZE as libc::c_int) as u8,
- alpha_bits: get_attrib(ffi::glx::ALPHA_SIZE as libc::c_int) as u8,
- depth_bits: get_attrib(ffi::glx::DEPTH_SIZE as libc::c_int) as u8,
- stencil_bits: get_attrib(ffi::glx::STENCIL_SIZE as libc::c_int) as u8,
- stereoscopy: get_attrib(ffi::glx::STEREO as libc::c_int) != 0,
- double_buffer: get_attrib(ffi::glx::DOUBLEBUFFER as libc::c_int) != 0,
- multisampling: if get_attrib(ffi::glx::SAMPLE_BUFFERS as libc::c_int) != 0 {
- Some(get_attrib(ffi::glx::SAMPLES as libc::c_int) as u16)
- }else { None },
- srgb: get_attrib(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as libc::c_int) != 0,
- }
+ // 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);
+ 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
@@ -427,7 +381,8 @@ impl Window {
// creating the color map
let cmap = unsafe {
let cmap = (display.xlib.XCreateColormap)(display.display, root,
- visual_infos.visual as *mut _, ffi::AllocNone);
+ visual_infos.visual as *mut _,
+ ffi::AllocNone);
// TODO: error checking?
cmap
};
@@ -545,27 +500,14 @@ impl Window {
}
let is_fullscreen = builder.monitor.is_some();
- // creating the context
- let context = match builder.gl_version {
- GlRequest::Latest | GlRequest::Specific(Api::OpenGl, _) | GlRequest::GlThenGles { .. } => {
- if let Some(ref glx) = display.glx {
- Context::Glx(try!(GlxContext::new(glx.clone(), builder, display.display, window,
- fb_config, visual_infos)))
- } else if let Some(ref egl) = display.egl {
- Context::Egl(try!(EglContext::new(egl.clone(), &builder, Some(display.display as *const _)).and_then(|p| p.finish(window as *const _))))
- } else {
- return Err(CreationError::NotSupported);
- }
- },
- GlRequest::Specific(Api::OpenGlEs, _) => {
- if let Some(ref egl) = display.egl {
- Context::Egl(try!(EglContext::new(egl.clone(), &builder, Some(display.display as *const _)).and_then(|p| p.finish(window as *const _))))
- } else {
- return Err(CreationError::NotSupported);
- }
+
+ // finish creating the OpenGL context
+ let context = match context {
+ Prototype::Glx(ctxt) => {
+ Context::Glx(try!(ctxt.finish(window)))
},
- GlRequest::Specific(_, _) => {
- return Err(CreationError::NotSupported);
+ Prototype::Egl(ctxt) => {
+ Context::Egl(try!(ctxt.finish(window as *const libc::c_void)))
},
};
@@ -585,7 +527,6 @@ impl Window {
is_closed: AtomicBool::new(false),
wm_delete_window: wm_delete_window,
current_size: Cell::new((0, 0)),
- pixel_format: pixel_format,
pending_events: Mutex::new(VecDeque::new()),
cursor_state: Mutex::new(CursorState::Normal),
input_handler: Mutex::new(XInputEventHandler::new(display, window, ic))
@@ -835,6 +776,10 @@ impl GlContext for Window {
}
fn get_pixel_format(&self) -> PixelFormat {
- self.pixel_format.clone()
+ match self.x.context {
+ Context::Glx(ref ctxt) => ctxt.get_pixel_format(),
+ Context::Egl(ref ctxt) => ctxt.get_pixel_format(),
+ Context::None => panic!()
+ }
}
}
diff --git a/src/lib.rs b/src/lib.rs
index f128f40..d43dcfb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -323,6 +323,7 @@ pub struct PixelFormat {
/// Attributes
// FIXME: remove `pub` (https://github.com/rust-lang/rust/issues/23585)
+#[derive(Clone)]
#[doc(hidden)]
pub struct BuilderAttribs<'a> {
#[allow(dead_code)]
@@ -471,7 +472,7 @@ impl<'a> BuilderAttribs<'a> {
mod native_monitor {
/// Native platform identifier for a monitor. Different platforms use fundamentally different types
/// to represent a monitor ID.
- #[derive(PartialEq, Eq)]
+ #[derive(Clone, PartialEq, Eq)]
pub enum NativeMonitorId {
/// Cocoa and X11 use a numeric identifier to represent a monitor.
Numeric(u32),
diff --git a/src/platform/linux/api_dispatch.rs b/src/platform/linux/api_dispatch.rs
index b2cd741..e580ab1 100644
--- a/src/platform/linux/api_dispatch.rs
+++ b/src/platform/linux/api_dispatch.rs
@@ -60,6 +60,7 @@ impl WindowProxy {
}
}
+#[derive(Clone)]
pub enum MonitorID {
#[doc(hidden)]
X(x11::MonitorID),