From c244f8c033f100a6e0f3e0b2b408f6ddc1006d47 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sun, 20 Sep 2015 09:29:22 +0200 Subject: [PATCH] Extract GlAttributes from BuilderAttribs --- src/api/cocoa/mod.rs | 8 ++-- src/api/egl/mod.rs | 22 +++++----- src/api/emscripten/mod.rs | 2 +- src/api/glx/mod.rs | 28 ++++++------- src/api/osmesa/mod.rs | 2 +- src/api/wgl/mod.rs | 12 +++--- src/api/win32/init.rs | 2 +- src/api/x11/window.rs | 2 +- src/headless.rs | 6 +-- src/lib.rs | 87 +++++++++++++++++++++++++++++---------- src/window.rs | 12 +++--- 11 files changed, 113 insertions(+), 70 deletions(-) diff --git a/src/api/cocoa/mod.rs b/src/api/cocoa/mod.rs index 259f847f..e259f398 100644 --- a/src/api/cocoa/mod.rs +++ b/src/api/cocoa/mod.rs @@ -267,11 +267,11 @@ impl<'a> Iterator for WaitEventsIterator<'a> { impl Window { #[cfg(feature = "window")] pub fn new(builder: BuilderAttribs) -> Result { - if builder.sharing.is_some() { + if builder.opengl.sharing.is_some() { unimplemented!() } - match builder.gl_robustness { + match builder.opengl.robustness { Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => { return Err(CreationError::RobustnessNotSupported); }, @@ -438,7 +438,7 @@ impl Window { } fn create_context(view: id, builder: &BuilderAttribs) -> Result<(IdRef, PixelFormat), CreationError> { - let profile = match (builder.gl_version, builder.gl_version.to_gl_version(), builder.gl_profile) { + let profile = match (builder.opengl.version, builder.opengl.version.to_gl_version(), builder.opengl.profile) { // Note: we are not using ranges because of a rust bug that should be fixed here: // https://github.com/rust-lang/rust/pull/27050 @@ -540,7 +540,7 @@ impl Window { }; cxt.setView_(view); - let value = if builder.vsync { 1 } else { 0 }; + let value = if builder.opengl.vsync { 1 } else { 0 }; cxt.setValues_forParameter_(&value, NSOpenGLContextParameter::NSOpenGLCPSwapInterval); CGLEnable(cxt.CGLContextObj(), kCGLCECrashOnRemovedFunctions); diff --git a/src/api/egl/mod.rs b/src/api/egl/mod.rs index 4cd7a7ce..c06c8ef3 100644 --- a/src/api/egl/mod.rs +++ b/src/api/egl/mod.rs @@ -162,7 +162,7 @@ impl Context { native_display: NativeDisplay) -> Result, CreationError> { - if builder.sharing.is_some() { + if builder.opengl.sharing.is_some() { unimplemented!() } @@ -197,7 +197,7 @@ impl Context { // binding the right API and choosing the version let (version, api) = unsafe { - match builder.gl_version { + match builder.opengl.version { GlRequest::Latest => { if egl_version >= (1, 4) { if egl.BindAPI(ffi::egl::OPENGL_API) != 0 { @@ -394,18 +394,18 @@ impl<'a> ContextPrototype<'a> { if let Some(version) = self.version { try!(create_context(&self.egl, self.display, &self.egl_version, &self.extensions, self.api, version, self.config_id, - self.builder.gl_debug, self.builder.gl_robustness)) + self.builder.opengl.debug, self.builder.opengl.robustness)) } else if self.api == Api::OpenGlEs { if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version, &self.extensions, self.api, (2, 0), self.config_id, - self.builder.gl_debug, self.builder.gl_robustness) + self.builder.opengl.debug, self.builder.opengl.robustness) { ctxt } else if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version, &self.extensions, self.api, (1, 0), - self.config_id, self.builder.gl_debug, - self.builder.gl_robustness) + self.config_id, self.builder.opengl.debug, + self.builder.opengl.robustness) { ctxt } else { @@ -415,19 +415,19 @@ impl<'a> ContextPrototype<'a> { } else { if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version, &self.extensions, self.api, (3, 2), self.config_id, - self.builder.gl_debug, self.builder.gl_robustness) + self.builder.opengl.debug, self.builder.opengl.robustness) { ctxt } else if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version, &self.extensions, self.api, (3, 1), - self.config_id, self.builder.gl_debug, - self.builder.gl_robustness) + self.config_id, self.builder.opengl.debug, + self.builder.opengl.robustness) { ctxt } else if let Ok(ctxt) = create_context(&self.egl, self.display, &self.egl_version, &self.extensions, self.api, (1, 0), - self.config_id, self.builder.gl_debug, - self.builder.gl_robustness) + self.config_id, self.builder.opengl.debug, + self.builder.opengl.robustness) { ctxt } else { diff --git a/src/api/emscripten/mod.rs b/src/api/emscripten/mod.rs index 79dda6b1..e6f51e32 100644 --- a/src/api/emscripten/mod.rs +++ b/src/api/emscripten/mod.rs @@ -83,7 +83,7 @@ impl Window { // setting the attributes // FIXME: - /*match builder.gl_version { + /*match builder.opengl.version { Some((major, minor)) => { attributes.majorVersion = major as libc::c_int; attributes.minorVersion = minor as libc::c_int; diff --git a/src/api/glx/mod.rs b/src/api/glx/mod.rs index a1ee0921..6a4461c6 100644 --- a/src/api/glx/mod.rs +++ b/src/api/glx/mod.rs @@ -133,7 +133,7 @@ impl<'a> ContextPrototype<'a> { } pub fn finish(self, window: ffi::Window) -> Result { - let share = if let Some(win) = self.builder.sharing { + let share = if let Some(win) = self.builder.opengl.sharing { match win { &PlatformWindow::X(ref win) => match win.x.context { ::api::x11::Context::Glx(ref c) => c.context, @@ -160,46 +160,46 @@ impl<'a> ContextPrototype<'a> { }); // creating GL context - let context = match self.builder.gl_version { + let context = match self.builder.opengl.version { GlRequest::Latest => { 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.builder.opengl.profile, self.builder.opengl.debug, + self.builder.opengl.robustness, share, self.display, self.fb_config, &self.visual_infos) { ctxt } 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, + (3, 1), self.builder.opengl.profile, + self.builder.opengl.debug, + self.builder.opengl.robustness, share, self.display, self.fb_config, &self.visual_infos) { ctxt } else { try!(create_context(&self.glx, &extra_functions, &extensions, (1, 0), - self.builder.gl_profile, self.builder.gl_debug, - self.builder.gl_robustness, + self.builder.opengl.profile, self.builder.opengl.debug, + self.builder.opengl.robustness, share, self.display, self.fb_config, &self.visual_infos)) } }, GlRequest::Specific(Api::OpenGl, (major, minor)) => { 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.builder.opengl.profile, self.builder.opengl.debug, + self.builder.opengl.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(&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.builder.opengl.profile, self.builder.opengl.debug, + self.builder.opengl.robustness, share, self.display, self.fb_config, &self.visual_infos)) }, }; // vsync - if self.builder.vsync { + if self.builder.opengl.vsync { unsafe { self.glx.MakeCurrent(self.display as *mut _, window, context) }; if extra_functions.SwapIntervalEXT.is_loaded() { diff --git a/src/api/osmesa/mod.rs b/src/api/osmesa/mod.rs index 9bd24b6c..2bfc8f5c 100644 --- a/src/api/osmesa/mod.rs +++ b/src/api/osmesa/mod.rs @@ -39,7 +39,7 @@ impl OsMesaContext { let dimensions = builder.dimensions.unwrap(); - match builder.gl_robustness { + match builder.opengl.robustness { Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => { return Err(CreationError::RobustnessNotSupported.into()); }, diff --git a/src/api/wgl/mod.rs b/src/api/wgl/mod.rs index 89538f15..a32d0234 100644 --- a/src/api/wgl/mod.rs +++ b/src/api/wgl/mod.rs @@ -131,7 +131,7 @@ impl Context { let gl_library = try!(load_opengl32_dll()); // handling vsync - if builder.vsync { + if builder.opengl.vsync { if extensions.split(' ').find(|&i| i == "WGL_EXT_swap_control").is_some() { let _guard = try!(CurrentContextGuard::make_current(hdc, context.0)); @@ -220,7 +220,7 @@ unsafe fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'st if extensions.split(' ').find(|&i| i == "WGL_ARB_create_context").is_some() { let mut attributes = Vec::new(); - match builder.gl_version { + match builder.opengl.version { GlRequest::Latest => {}, GlRequest::Specific(Api::OpenGl, (major, minor)) => { attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); @@ -252,7 +252,7 @@ unsafe fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'st }, } - if let Some(profile) = builder.gl_profile { + if let Some(profile) = builder.opengl.profile { if extensions.split(' ').find(|&i| i == "WGL_ARB_create_context_profile").is_some() { let flag = match profile { @@ -273,7 +273,7 @@ unsafe fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'st // robustness if extensions.split(' ').find(|&i| i == "WGL_ARB_create_context_robustness").is_some() { - match builder.gl_robustness { + match builder.opengl.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); @@ -288,7 +288,7 @@ unsafe fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'st Robustness::NoError => (), } } else { - match builder.gl_robustness { + match builder.opengl.robustness { Robustness::RobustNoResetNotification | Robustness::RobustLoseContextOnReset => { return Err(CreationError::RobustnessNotSupported); }, @@ -296,7 +296,7 @@ unsafe fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'st } } - if builder.gl_debug { + if builder.opengl.debug { flags = flags | gl::wgl_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int; } diff --git a/src/api/win32/init.rs b/src/api/win32/init.rs index c3225b67..daa6b5a8 100644 --- a/src/api/win32/init.rs +++ b/src/api/win32/init.rs @@ -159,7 +159,7 @@ unsafe fn init(title: Vec, builder: BuilderAttribs<'static>, }; // creating the OpenGL context - let context = match builder.gl_version { + let context = match builder.opengl.version { GlRequest::Specific(Api::OpenGlEs, (_major, _minor)) => { if let Some(egl) = egl { if let Ok(c) = EglContext::new(egl, &builder, diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs index 5bfbda97..8e2bdb59 100644 --- a/src/api/x11/window.rs +++ b/src/api/x11/window.rs @@ -349,7 +349,7 @@ impl Window { Egl(::api::egl::ContextPrototype<'a>), } let builder_clone = builder.clone(); - let context = match builder.gl_version { + let context = match builder.opengl.version { GlRequest::Latest | GlRequest::Specific(Api::OpenGl, _) | GlRequest::GlThenGles { .. } => { // GLX should be preferred over EGL, otherwise crashes may occur // on X11 – issue #314 diff --git a/src/headless.rs b/src/headless.rs index 69f9aab2..1d14a4c9 100644 --- a/src/headless.rs +++ b/src/headless.rs @@ -31,7 +31,7 @@ impl HeadlessRendererBuilder { /// Sets how the backend should choose the OpenGL API and version. pub fn with_gl(mut self, request: GlRequest) -> HeadlessRendererBuilder { - self.attribs.gl_version = request; + self.attribs.opengl.version = request; self } @@ -40,13 +40,13 @@ impl HeadlessRendererBuilder { /// The default value for this flag is `cfg!(ndebug)`, which means that it's enabled /// when you run `cargo build` and disabled when you run `cargo build --release`. pub fn with_gl_debug_flag(mut self, flag: bool) -> HeadlessRendererBuilder { - self.attribs.gl_debug = flag; + self.attribs.opengl.debug = flag; 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.attribs.opengl.robustness = robustness; self } diff --git a/src/lib.rs b/src/lib.rs index 24913fb7..82d0f3b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -371,15 +371,9 @@ pub struct BuilderAttribs<'a> { #[allow(dead_code)] headless: bool, strict: bool, - sharing: Option<&'a platform::Window>, dimensions: Option<(u32, u32)>, title: String, monitor: Option, - gl_version: GlRequest, - gl_profile: Option, - gl_debug: bool, - gl_robustness: Robustness, - vsync: bool, visible: bool, multisampling: Option, depth_bits: Option, @@ -390,7 +384,8 @@ pub struct BuilderAttribs<'a> { srgb: Option, transparent: bool, decorations: bool, - multitouch: bool + multitouch: bool, + opengl: GlAttributes<&'a platform::Window>, } impl BuilderAttribs<'static> { @@ -398,15 +393,9 @@ impl BuilderAttribs<'static> { BuilderAttribs { headless: false, strict: false, - sharing: None, dimensions: None, title: "glutin window".to_string(), monitor: None, - gl_version: GlRequest::Latest, - gl_profile: None, - gl_debug: cfg!(debug_assertions), - gl_robustness: Robustness::NotRobust, - vsync: false, visible: true, multisampling: None, depth_bits: None, @@ -417,7 +406,8 @@ impl BuilderAttribs<'static> { srgb: None, transparent: false, decorations: true, - multitouch: false + multitouch: false, + opengl: Default::default(), } } } @@ -425,20 +415,14 @@ impl BuilderAttribs<'static> { impl<'a> BuilderAttribs<'a> { #[allow(dead_code)] fn extract_non_static(mut self) -> (BuilderAttribs<'static>, Option<&'a platform::Window>) { - let sharing = self.sharing.take(); + let sharing = self.opengl.sharing.take(); let new_attribs = BuilderAttribs { headless: self.headless, strict: self.strict, - sharing: None, dimensions: self.dimensions, title: self.title, monitor: self.monitor, - 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, depth_bits: self.depth_bits, @@ -449,7 +433,15 @@ impl<'a> BuilderAttribs<'a> { srgb: self.srgb, transparent: self.transparent, decorations: self.decorations, - multitouch: self.multitouch + multitouch: self.multitouch, + opengl: GlAttributes { + sharing: None, + version: self.opengl.version, + profile: self.opengl.profile, + debug: self.opengl.debug, + robustness: self.opengl.robustness, + vsync: self.opengl.vsync, + }, }; (new_attribs, sharing) @@ -555,6 +547,57 @@ impl<'a> BuilderAttribs<'a> { } } +/// Attributes to use when creating an OpenGL context. +#[derive(Clone)] +pub struct GlAttributes { + /// An existing context to share the new the context with. + /// + /// The default is `None`. + pub sharing: Option, + + /// Version to try create. See `GlRequest` for more infos. + /// + /// The default is `Latest`. + pub version: GlRequest, + + /// OpenGL profile to use. + /// + /// The default is `None`. + pub profile: Option, + + /// Whether to enable the `debug` flag of the context. + /// + /// Debug contexts are usually slower but give better error reporting. + /// + /// The default is `true` in debug mode and `false` in release mode. + pub debug: bool, + + /// How the OpenGL context should detect errors. + /// + /// The default is `NotRobust` because this is what is typically expected when you create an + /// OpenGL context. However for safety you should consider `TryRobustLoseContextOnReset`. + pub robustness: Robustness, + + /// Whether to use vsync. If vsync is enabled, calling `swap_buffers` will block until the + /// screen refreshes. This is typically used to prevent screen tearing. + /// + /// The default is `false`. + pub vsync: bool, +} + +impl Default for GlAttributes { + fn default() -> GlAttributes { + GlAttributes { + sharing: None, + version: GlRequest::Latest, + profile: None, + debug: cfg!(debug_assertions), + robustness: Robustness::NotRobust, + vsync: false, + } + } +} + mod native_monitor { /// Native platform identifier for a monitor. Different platforms use fundamentally different types /// to represent a monitor ID. diff --git a/src/window.rs b/src/window.rs index 00174d3d..afca3197 100644 --- a/src/window.rs +++ b/src/window.rs @@ -60,19 +60,19 @@ impl<'a> WindowBuilder<'a> { /// /// There are some exceptions, like FBOs or VAOs. See the OpenGL documentation. pub fn with_shared_lists(mut self, other: &'a Window) -> WindowBuilder<'a> { - self.attribs.sharing = Some(&other.window); + self.attribs.opengl.sharing = Some(&other.window); self } /// Sets how the backend should choose the OpenGL API and version. pub fn with_gl(mut self, request: GlRequest) -> WindowBuilder<'a> { - self.attribs.gl_version = request; + self.attribs.opengl.version = request; self } /// Sets the desired OpenGL context profile. pub fn with_gl_profile(mut self, profile: GlProfile) -> WindowBuilder<'a> { - self.attribs.gl_profile = Some(profile); + self.attribs.opengl.profile = Some(profile); self } @@ -81,19 +81,19 @@ impl<'a> WindowBuilder<'a> { /// The default value for this flag is `cfg!(debug_assertions)`, which means that it's enabled /// when you run `cargo build` and disabled when you run `cargo build --release`. pub fn with_gl_debug_flag(mut self, flag: bool) -> WindowBuilder<'a> { - self.attribs.gl_debug = flag; + self.attribs.opengl.debug = flag; 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.attribs.opengl.robustness = robustness; self } /// Requests that the window has vsync enabled. pub fn with_vsync(mut self) -> WindowBuilder<'a> { - self.attribs.vsync = true; + self.attribs.opengl.vsync = true; self }