aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/glx/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/glx/mod.rs')
-rw-r--r--src/api/glx/mod.rs101
1 files changed, 75 insertions, 26 deletions
diff --git a/src/api/glx/mod.rs b/src/api/glx/mod.rs
index f1eb436..d286813 100644
--- a/src/api/glx/mod.rs
+++ b/src/api/glx/mod.rs
@@ -1,15 +1,17 @@
#![cfg(all(target_os = "linux", feature = "window"))]
use BuilderAttribs;
+use ContextError;
use CreationError;
use GlContext;
use GlProfile;
use GlRequest;
use Api;
use PixelFormat;
+use Robustness;
use libc;
-use std::ffi::CString;
+use std::ffi::{CStr, CString};
use std::{mem, ptr};
use api::x11::ffi;
@@ -47,6 +49,13 @@ impl Context {
ptr::null()
};
+ // loading the list of extensions
+ let extensions = unsafe {
+ let extensions = glx.QueryExtensionsString(display as *mut _, 0); // FIXME: screen number
+ let extensions = CStr::from_ptr(extensions).to_bytes().to_vec();
+ String::from_utf8(extensions).unwrap()
+ };
+
// loading the extra GLX functions
let extra_functions = ffi::glx_extra::Glx::load_with(|addr| {
with_c_str(addr, |s| {
@@ -57,32 +66,35 @@ impl Context {
// creating GL context
let context = match builder.gl_version {
GlRequest::Latest => {
- if let Ok(ctxt) = create_context(&glx, &extra_functions, (3, 2),
- builder.gl_profile, builder.gl_debug, share,
+ 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)
{
ctxt
- } else if let Ok(ctxt) = create_context(&glx, &extra_functions, (3, 1),
+ } else if let Ok(ctxt) = create_context(&glx, &extra_functions, &extensions, (3, 1),
builder.gl_profile, builder.gl_debug,
- share, display, fb_config,
- &mut visual_infos)
+ builder.gl_robustness, share, display,
+ fb_config, &mut visual_infos)
{
ctxt
} else {
- try!(create_context(&glx, &extra_functions, (1, 0), builder.gl_profile,
- builder.gl_debug, share, display, fb_config,
- &mut visual_infos))
+ 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))
}
},
GlRequest::Specific(Api::OpenGl, (major, minor)) => {
- try!(create_context(&glx, &extra_functions, (major, minor), builder.gl_profile,
- builder.gl_debug, share, display, fb_config, &mut visual_infos))
+ 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))
},
GlRequest::Specific(_, _) => panic!("Only OpenGL is supported"),
GlRequest::GlThenGles { opengl_version: (major, minor), .. } => {
- try!(create_context(&glx, &extra_functions, (major, minor), builder.gl_profile,
- builder.gl_debug, share, display, fb_config, &mut visual_infos))
+ 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))
},
};
@@ -139,11 +151,13 @@ impl Context {
}
impl GlContext for Context {
- unsafe fn make_current(&self) {
+ 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 {
@@ -158,10 +172,10 @@ impl GlContext for Context {
}
}
- fn swap_buffers(&self) {
- unsafe {
- self.glx.SwapBuffers(self.display as *mut _, self.window)
- }
+ 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 {
@@ -179,16 +193,18 @@ unsafe impl Sync for Context {}
impl Drop for Context {
fn drop(&mut self) {
unsafe {
- // we don't call MakeCurrent(0, 0) because we are not sure that the context
- // is still the current one
+ 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,
+fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx, extensions: &str,
version: (u8, u8), profile: Option<GlProfile>, debug: bool,
- share: ffi::GLXContext, display: *mut ffi::Display,
+ robustness: Robustness, share: ffi::GLXContext, display: *mut ffi::Display,
fb_config: ffi::glx::types::GLXFBConfig,
visual_infos: &mut ffi::glx::types::XVisualInfo)
-> Result<ffi::GLXContext, CreationError>
@@ -214,10 +230,43 @@ fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx,
attributes.push(flag as libc::c_int);
}
- if 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);
- }
+ let flags = {
+ let mut flags = 0;
+
+ // robustness
+ if extensions.split(' ').find(|&i| i == "GLX_ARB_create_context_robustness").is_some() {
+ match robustness {
+ Robustness::RobustNoResetNotification | Robustness::TryRobustNoResetNotification => {
+ attributes.push(ffi::glx_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as libc::c_int);
+ attributes.push(ffi::glx_extra::NO_RESET_NOTIFICATION_ARB as libc::c_int);
+ flags = flags | ffi::glx_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB as libc::c_int;
+ },
+ Robustness::RobustLoseContextOnReset | Robustness::TryRobustLoseContextOnReset => {
+ attributes.push(ffi::glx_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as libc::c_int);
+ attributes.push(ffi::glx_extra::LOSE_CONTEXT_ON_RESET_ARB as libc::c_int);
+ flags = flags | ffi::glx_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB as libc::c_int;
+ },
+ Robustness::NotRobust => (),
+ Robustness::NoError => (),
+ }
+ } else {
+ match robustness {
+ Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => {
+ return Err(CreationError::NotSupported);
+ },
+ _ => ()
+ }
+ }
+
+ if debug {
+ flags = flags | ffi::glx_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int;
+ }
+
+ flags
+ };
+
+ attributes.push(ffi::glx_extra::CONTEXT_FLAGS_ARB as libc::c_int);
+ attributes.push(flags);
attributes.push(0);