diff options
| author | tomaka <pierre.krieger1708@gmail.com> | 2015-06-23 16:46:52 +0200 | 
|---|---|---|
| committer | tomaka <pierre.krieger1708@gmail.com> | 2015-06-23 16:46:52 +0200 | 
| commit | 40b84577c3894190aecebf096349d916cd1d000e (patch) | |
| tree | e2303fa1ff9990706e6be83f530ad9ab746606aa | |
| parent | 717ea3d5ba655a3ec18f834f5e27152e81c7a8b5 (diff) | |
| parent | dbaca24cde140052fb08fbe00924da4a528ea7cf (diff) | |
| download | glutin-40b84577c3894190aecebf096349d916cd1d000e.tar.gz glutin-40b84577c3894190aecebf096349d916cd1d000e.zip  | |
Merge pull request #497 from tomaka/robustness
Add with_robustness and handle robustness on all implementations
| -rw-r--r-- | build.rs | 8 | ||||
| -rw-r--r-- | src/api/cocoa/mod.rs | 8 | ||||
| -rw-r--r-- | src/api/egl/mod.rs | 62 | ||||
| -rw-r--r-- | src/api/glx/mod.rs | 81 | ||||
| -rw-r--r-- | src/api/osmesa/mod.rs | 8 | ||||
| -rw-r--r-- | src/api/wgl/mod.rs | 41 | ||||
| -rw-r--r-- | src/headless.rs | 7 | ||||
| -rw-r--r-- | src/lib.rs | 30 | ||||
| -rw-r--r-- | src/window.rs | 7 | 
9 files changed, 216 insertions, 36 deletions
@@ -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, @@ -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;  | 
