aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.rs8
-rw-r--r--src/api/cocoa/mod.rs8
-rw-r--r--src/api/egl/mod.rs62
-rw-r--r--src/api/glx/mod.rs81
-rw-r--r--src/api/osmesa/mod.rs8
-rw-r--r--src/api/wgl/mod.rs41
-rw-r--r--src/headless.rs7
-rw-r--r--src/lib.rs30
-rw-r--r--src/window.rs7
9 files changed, 216 insertions, 36 deletions
diff --git a/build.rs b/build.rs
index c21f4f6..f62dc93 100644
--- a/build.rs
+++ b/build.rs
@@ -25,6 +25,7 @@ fn main() {
vec![
"WGL_ARB_create_context".to_string(),
"WGL_ARB_create_context_profile".to_string(),
+ "WGL_ARB_create_context_robustness".to_string(),
"WGL_ARB_extensions_string".to_string(),
"WGL_ARB_framebuffer_sRGB".to_string(),
"WGL_ARB_multisample".to_string(),
@@ -42,7 +43,8 @@ fn main() {
gl_generator::Fallbacks::All,
khronos_api::EGL_XML,
vec![
- "EGL_KHR_create_context".to_string()
+ "EGL_KHR_create_context".to_string(),
+ "EGL_EXT_create_context_robustness".to_string(),
],
"1.5", "core", &mut file).unwrap();
}
@@ -63,6 +65,7 @@ fn main() {
vec![
"GLX_ARB_create_context".to_string(),
"GLX_ARB_create_context_profile".to_string(),
+ "GLX_ARB_create_context_robustness".to_string(),
"GLX_ARB_framebuffer_sRGB".to_string(),
"GLX_EXT_framebuffer_sRGB".to_string(),
"GLX_EXT_swap_control".to_string(),
@@ -76,7 +79,8 @@ fn main() {
gl_generator::Fallbacks::All,
khronos_api::EGL_XML,
vec![
- "EGL_KHR_create_context".to_string()
+ "EGL_KHR_create_context".to_string(),
+ "EGL_EXT_create_context_robustness".to_string(),
],
"1.5", "core", &mut file).unwrap();
}
diff --git a/src/api/cocoa/mod.rs b/src/api/cocoa/mod.rs
index 772b906..332244e 100644
--- a/src/api/cocoa/mod.rs
+++ b/src/api/cocoa/mod.rs
@@ -13,6 +13,7 @@ use GlContext;
use GlProfile;
use GlRequest;
use PixelFormat;
+use Robustness;
use native_monitor::NativeMonitorId;
use objc::runtime::{Class, Object, Sel, BOOL, YES, NO};
@@ -332,6 +333,13 @@ impl Window {
unimplemented!()
}
+ match builder.gl_robustness {
+ Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => {
+ return Err(CreationError::NotSupported);
+ },
+ _ => ()
+ }
+
let app = match Window::create_app() {
Some(app) => app,
None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
diff --git a/src/api/egl/mod.rs b/src/api/egl/mod.rs
index 7b31017..07c70b0 100644
--- a/src/api/egl/mod.rs
+++ b/src/api/egl/mod.rs
@@ -7,6 +7,7 @@ use CreationError;
use GlContext;
use GlRequest;
use PixelFormat;
+use Robustness;
use Api;
use libc;
@@ -116,15 +117,16 @@ impl Context {
let context = unsafe {
if let Some(version) = version {
try!(create_context(&egl, display, &egl_version, api, version, config_id,
- builder.gl_debug).map_err(|_| CreationError::NotSupported))
+ builder.gl_debug, builder.gl_robustness))
} else if api == Api::OpenGlEs {
if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (2, 0),
- config_id, builder.gl_debug)
+ config_id, builder.gl_debug, builder.gl_robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (1, 0),
- config_id, builder.gl_debug)
+ config_id, builder.gl_debug,
+ builder.gl_robustness)
{
ctxt
} else {
@@ -133,15 +135,17 @@ impl Context {
} else {
if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (3, 2),
- config_id, builder.gl_debug)
+ config_id, builder.gl_debug, builder.gl_robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (3, 1),
- config_id, builder.gl_debug)
+ config_id, builder.gl_debug,
+ builder.gl_robustness)
{
ctxt
} else if let Ok(ctxt) = create_context(&egl, display, &egl_version, api, (1, 0),
- config_id, builder.gl_debug)
+ config_id, builder.gl_debug,
+ builder.gl_robustness)
{
ctxt
} else {
@@ -335,8 +339,8 @@ unsafe fn enumerate_configs(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDi
unsafe fn create_context(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDisplay,
egl_version: &(ffi::egl::types::EGLint, ffi::egl::types::EGLint),
api: Api, version: (u8, u8), config_id: ffi::egl::types::EGLConfig,
- gl_debug: bool)
- -> Result<ffi::egl::types::EGLContext, ()>
+ gl_debug: bool, gl_robustness: Robustness)
+ -> Result<ffi::egl::types::EGLContext, CreationError>
{
let extensions = if egl_version >= &(1, 2) {
let p = CStr::from_ptr(egl.QueryString(display, ffi::egl::EXTENSIONS as i32));
@@ -346,6 +350,7 @@ unsafe fn create_context(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDispl
};
let mut context_attributes = vec![];
+ let mut flags = 0;
if egl_version >= &(1, 5) ||
extensions.contains("EGL_KHR_create_context ") ||
@@ -356,17 +361,52 @@ unsafe fn create_context(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDispl
context_attributes.push(ffi::egl::CONTEXT_MINOR_VERSION as i32);
context_attributes.push(version.1 as i32);
+ if egl_version >= &(1, 5) ||
+ extensions.contains("EGL_EXT_create_context_robustness ") ||
+ extensions.ends_with("EGL_EXT_create_context_robustness")
+ {
+ match gl_robustness {
+ Robustness::RobustNoResetNotification | Robustness::TryRobustNoResetNotification => {
+ context_attributes.push(ffi::egl::CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY as libc::c_int);
+ context_attributes.push(ffi::egl::NO_RESET_NOTIFICATION as libc::c_int);
+ flags = flags | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as libc::c_int;
+ },
+ Robustness::RobustLoseContextOnReset | Robustness::TryRobustLoseContextOnReset => {
+ context_attributes.push(ffi::egl::CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY as libc::c_int);
+ context_attributes.push(ffi::egl::LOSE_CONTEXT_ON_RESET as libc::c_int);
+ flags = flags | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as libc::c_int;
+ },
+ Robustness::NotRobust => ()
+ }
+ } else {
+ match gl_robustness {
+ Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => {
+ return Err(CreationError::NotSupported);
+ },
+ _ => ()
+ }
+ }
+
if gl_debug {
if egl_version >= &(1, 5) {
context_attributes.push(ffi::egl::CONTEXT_OPENGL_DEBUG as i32);
context_attributes.push(ffi::egl::TRUE as i32);
} else {
- context_attributes.push(ffi::egl::CONTEXT_FLAGS_KHR as i32);
- context_attributes.push(ffi::egl::CONTEXT_OPENGL_DEBUG_BIT_KHR as i32);
+ flags = flags | ffi::egl::CONTEXT_OPENGL_DEBUG_BIT_KHR as i32;
}
}
+ context_attributes.push(ffi::egl::CONTEXT_FLAGS_KHR as i32);
+ context_attributes.push(flags);
+
} else if egl_version >= &(1, 3) && api == Api::OpenGlEs {
+ match gl_robustness {
+ Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => {
+ return Err(CreationError::NotSupported);
+ },
+ _ => ()
+ }
+
context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32);
context_attributes.push(version.0 as i32);
}
@@ -377,7 +417,7 @@ unsafe fn create_context(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDispl
context_attributes.as_ptr());
if context.is_null() {
- return Err(());
+ return Err(CreationError::NotSupported);
}
Ok(context)
diff --git a/src/api/glx/mod.rs b/src/api/glx/mod.rs
index 455f6a5..2c15e18 100644
--- a/src/api/glx/mod.rs
+++ b/src/api/glx/mod.rs
@@ -8,9 +8,10 @@ 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;
@@ -48,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| {
@@ -58,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))
},
};
@@ -191,9 +202,9 @@ impl Drop for 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>
@@ -219,10 +230,42 @@ 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 => ()
+ }
+ } 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);
diff --git a/src/api/osmesa/mod.rs b/src/api/osmesa/mod.rs
index daaba52..db0a1e7 100644
--- a/src/api/osmesa/mod.rs
+++ b/src/api/osmesa/mod.rs
@@ -8,6 +8,7 @@ use ContextError;
use CreationError;
use GlContext;
use PixelFormat;
+use Robustness;
use libc;
use std::{mem, ptr};
use std::ffi::CString;
@@ -38,6 +39,13 @@ impl OsMesaContext {
let dimensions = builder.dimensions.unwrap();
+ match builder.gl_robustness {
+ Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => {
+ return Err(CreationError::NotSupported.into());
+ },
+ _ => ()
+ }
+
Ok(OsMesaContext {
width: dimensions.0,
height: dimensions.1,
diff --git a/src/api/wgl/mod.rs b/src/api/wgl/mod.rs
index c33054e..ee8aa3b 100644
--- a/src/api/wgl/mod.rs
+++ b/src/api/wgl/mod.rs
@@ -7,6 +7,7 @@ use GlContext;
use GlRequest;
use GlProfile;
use PixelFormat;
+use Robustness;
use Api;
use self::make_current_guard::CurrentContextGuard;
@@ -266,10 +267,42 @@ unsafe fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'st
}
}
- if builder.gl_debug {
- attributes.push(gl::wgl_extra::CONTEXT_FLAGS_ARB as libc::c_int);
- attributes.push(gl::wgl_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int);
- }
+ let flags = {
+ let mut flags = 0;
+
+ // robustness
+ if extensions.split(' ').find(|&i| i == "WGL_ARB_create_context_robustness").is_some() {
+ match builder.gl_robustness {
+ Robustness::RobustNoResetNotification | Robustness::TryRobustNoResetNotification => {
+ attributes.push(gl::wgl_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as libc::c_int);
+ attributes.push(gl::wgl_extra::NO_RESET_NOTIFICATION_ARB as libc::c_int);
+ flags = flags | gl::wgl_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB as libc::c_int;
+ },
+ Robustness::RobustLoseContextOnReset | Robustness::TryRobustLoseContextOnReset => {
+ attributes.push(gl::wgl_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as libc::c_int);
+ attributes.push(gl::wgl_extra::LOSE_CONTEXT_ON_RESET_ARB as libc::c_int);
+ flags = flags | gl::wgl_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB as libc::c_int;
+ },
+ Robustness::NotRobust => ()
+ }
+ } else {
+ match builder.gl_robustness {
+ Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => {
+ return Err(CreationError::NotSupported);
+ },
+ _ => ()
+ }
+ }
+
+ if builder.gl_debug {
+ flags = flags | gl::wgl_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int;
+ }
+
+ flags
+ };
+
+ attributes.push(gl::wgl_extra::CONTEXT_FLAGS_ARB as libc::c_int);
+ attributes.push(flags);
attributes.push(0);
diff --git a/src/headless.rs b/src/headless.rs
index 8ee81d8..69f9aab 100644
--- a/src/headless.rs
+++ b/src/headless.rs
@@ -5,6 +5,7 @@ use CreationError;
use GlRequest;
use GlContext;
use PixelFormat;
+use Robustness;
use gl_common;
use libc;
@@ -43,6 +44,12 @@ impl HeadlessRendererBuilder {
self
}
+ /// Sets the robustness of the OpenGL context. See the docs of `Robustness`.
+ pub fn with_gl_robustness(mut self, robustness: Robustness) -> HeadlessRendererBuilder {
+ self.attribs.gl_robustness = robustness;
+ self
+ }
+
/// Builds the headless context.
///
/// Error should be very rare and only occur in case of permission denied, incompatible system,
diff --git a/src/lib.rs b/src/lib.rs
index 068b9b8..6e96efb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -197,6 +197,33 @@ impl GlRequest {
/// the compatibility profile features.
pub static GL_CORE: GlRequest = GlRequest::Specific(Api::OpenGl, (3, 2));
+/// Specifies the tolerance of the OpenGL context to faults. If you accept raw OpenGL commands
+/// and/or raw shader code from an untrusted source, you should definitely care about this.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum Robustness {
+ /// Not everything is checked. Your application can crash if you do something wrong with your
+ /// shaders.
+ NotRobust,
+
+ /// Everything is checked to avoid any crash. The driver will attempt to avoid any problem,
+ /// but if a problem occurs the behavior is implementation-defined. You are just guaranteed not
+ /// to get a crash.
+ RobustNoResetNotification,
+
+ /// Same as `RobustNoResetNotification` but the context creation doesn't fail if it's not
+ /// supported.
+ TryRobustNoResetNotification,
+
+ /// Everything is checked to avoid any crash. If a problem occurs, the context will enter a
+ /// "context lost" state. It must then be recreated. For the moment, glutin doesn't provide a
+ /// way to recreate a context with the same window :-/
+ RobustLoseContextOnReset,
+
+ /// Same as `RobustLoseContextOnReset` but the context creation doesn't fail if it's not
+ /// supported.
+ TryRobustLoseContextOnReset,
+}
+
#[derive(Debug, Copy, Clone)]
pub enum MouseCursor {
/// The platform-dependent default cursor.
@@ -299,6 +326,7 @@ pub struct BuilderAttribs<'a> {
gl_version: GlRequest,
gl_profile: Option<GlProfile>,
gl_debug: bool,
+ gl_robustness: Robustness,
vsync: bool,
visible: bool,
multisampling: Option<u16>,
@@ -324,6 +352,7 @@ impl BuilderAttribs<'static> {
gl_version: GlRequest::Latest,
gl_profile: None,
gl_debug: cfg!(debug_assertions),
+ gl_robustness: Robustness::NotRobust,
vsync: false,
visible: true,
multisampling: None,
@@ -354,6 +383,7 @@ impl<'a> BuilderAttribs<'a> {
gl_version: self.gl_version,
gl_profile: self.gl_profile,
gl_debug: self.gl_debug,
+ gl_robustness: self.gl_robustness,
vsync: self.vsync,
visible: self.visible,
multisampling: self.multisampling,
diff --git a/src/window.rs b/src/window.rs
index 485ba58..9685287 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -12,6 +12,7 @@ use GlProfile;
use GlRequest;
use MouseCursor;
use PixelFormat;
+use Robustness;
use native_monitor::NativeMonitorId;
use gl_common;
@@ -84,6 +85,12 @@ impl<'a> WindowBuilder<'a> {
self
}
+ /// Sets the robustness of the OpenGL context. See the docs of `Robustness`.
+ pub fn with_gl_robustness(mut self, robustness: Robustness) -> WindowBuilder<'a> {
+ self.attribs.gl_robustness = robustness;
+ self
+ }
+
/// Requests that the window has vsync enabled.
pub fn with_vsync(mut self) -> WindowBuilder<'a> {
self.attribs.vsync = true;