diff --git a/Cargo.toml b/Cargo.toml index a1a826a8..206829e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ shared_library = "0.1.0" [build-dependencies] gl_generator = "0.0.26" -khronos_api = "0.0.5" +khronos_api = "0.0.6" [dev-dependencies] clock_ticks = "0.0.5" diff --git a/build.rs b/build.rs index f62dc931..3940912b 100644 --- a/build.rs +++ b/build.rs @@ -45,6 +45,7 @@ fn main() { vec![ "EGL_KHR_create_context".to_string(), "EGL_EXT_create_context_robustness".to_string(), + "EGL_KHR_create_context_no_error".to_string(), ], "1.5", "core", &mut file).unwrap(); } @@ -81,6 +82,7 @@ fn main() { vec![ "EGL_KHR_create_context".to_string(), "EGL_EXT_create_context_robustness".to_string(), + "EGL_KHR_create_context_no_error".to_string(), ], "1.5", "core", &mut file).unwrap(); } @@ -92,7 +94,9 @@ 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(), + "EGL_KHR_create_context_no_error".to_string(), ], "1.5", "core", &mut file).unwrap(); } diff --git a/src/api/egl/mod.rs b/src/api/egl/mod.rs index 07c70b0d..1a6cc06e 100644 --- a/src/api/egl/mod.rs +++ b/src/api/egl/mod.rs @@ -349,7 +349,7 @@ unsafe fn create_context(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDispl format!("") }; - let mut context_attributes = vec![]; + let mut context_attributes = Vec::with_capacity(10); let mut flags = 0; if egl_version >= &(1, 5) || @@ -361,30 +361,62 @@ 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); + // handling robustness + let supports_robustness = egl_version >= &(1, 5) || + extensions.contains("EGL_EXT_create_context_robustness ") || + extensions.ends_with("EGL_EXT_create_context_robustness"); + + match gl_robustness { + Robustness::NotRobust => (), + + Robustness::NoError => { + if extensions.contains("EGL_KHR_create_context_no_error ") || + extensions.ends_with("EGL_KHR_create_context_no_error") + { + context_attributes.push(ffi::egl::CONTEXT_OPENGL_NO_ERROR_KHR as libc::c_int); + context_attributes.push(1); + } + }, + + Robustness::RobustNoResetNotification => { + if supports_robustness { + 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); + } else { + return Err(CreationError::NotSupported); + } + }, + + Robustness::TryRobustNoResetNotification => { + if supports_robustness { + 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 => { + if supports_robustness { + 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 => { + } else { return Err(CreationError::NotSupported); - }, - _ => () - } + } + }, + + Robustness::TryRobustLoseContextOnReset => { + if supports_robustness { + 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; + } + }, } if gl_debug { @@ -400,6 +432,7 @@ unsafe fn create_context(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDispl context_attributes.push(flags); } else if egl_version >= &(1, 3) && api == Api::OpenGlEs { + // robustness is not supported match gl_robustness { Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => { return Err(CreationError::NotSupported); diff --git a/src/api/glx/mod.rs b/src/api/glx/mod.rs index 2c15e181..d286813b 100644 --- a/src/api/glx/mod.rs +++ b/src/api/glx/mod.rs @@ -246,7 +246,8 @@ fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx, ex 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::NotRobust => (), + Robustness::NoError => (), } } else { match robustness { diff --git a/src/api/wgl/mod.rs b/src/api/wgl/mod.rs index 55fd22ab..a71bb34b 100644 --- a/src/api/wgl/mod.rs +++ b/src/api/wgl/mod.rs @@ -281,7 +281,8 @@ unsafe fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'st 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 => () + Robustness::NotRobust => (), + Robustness::NoError => (), } } else { match builder.gl_robustness { diff --git a/src/lib.rs b/src/lib.rs index 64b0acef..3dcf0f90 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -205,6 +205,13 @@ pub enum Robustness { /// shaders. NotRobust, + /// The driver doesn't check anything. This option is very dangerous. Please know what you're + /// doing before using it. See the `GL_KHR_no_error` extension. + /// + /// Since this option is purely an optimisation, no error will be returned if the backend + /// doesn't support it. Instead it will automatically fall back to `NotRobust`. + NoError, + /// 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.