From f4f84c6566d99c297cddee3c712e94927f313204 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Wed, 18 Feb 2015 16:49:53 +0100 Subject: Improve the OpenGL context request system --- src/android/mod.rs | 7 ++++++- src/cocoa/mod.rs | 17 +++++++++++++---- src/headless.rs | 15 ++++++++++----- src/lib.rs | 28 ++++++++++++++++++++++++++-- src/win32/init.rs | 24 ++++++++++++++++++------ src/window.rs | 15 ++++++++++----- src/x11/window/mod.rs | 24 ++++++++++++++++++------ 7 files changed, 101 insertions(+), 29 deletions(-) diff --git a/src/android/mod.rs b/src/android/mod.rs index ea93040..72ebda3 100644 --- a/src/android/mod.rs +++ b/src/android/mod.rs @@ -11,7 +11,9 @@ use events::MouseButton; use std::collections::RingBuf; +use Api; use BuilderAttribs; +use GlRequest; pub struct Window { display: ffi::egl::types::EGLDisplay, @@ -157,7 +159,10 @@ impl Window { android_glue::write_log("eglInitialize succeeded"); let use_gles2 = match builder.gl_version { - Some((2, 0)) => true, + GlRequest::Specific(Api::OpenGlEs, (2, _)) => true, + GlRequest::Specific(Api::OpenGlEs, _) => false, + GlRequest::Specific(_, _) => panic!("Only OpenGL ES is supported"), // FIXME: return a result + GlRequest::GlThenGles { opengles_version: (2, _), .. } => true, _ => false, }; diff --git a/src/cocoa/mod.rs b/src/cocoa/mod.rs index 98b1879..2b8b342 100644 --- a/src/cocoa/mod.rs +++ b/src/cocoa/mod.rs @@ -5,7 +5,9 @@ use {CreationError, Event, MouseCursor}; use CreationError::OsError; use libc; +use Api; use BuilderAttribs; +use GlRequest; use cocoa::base::{Class, id, YES, NO, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair}; use cocoa::base::{selector, msg_send, msg_send_stret, class_addMethod, class_addIvar}; @@ -453,11 +455,18 @@ impl Window { } } - fn create_context(view: id, vsync: bool, gl_version: Option<(u32, u32)>) -> Option { + fn create_context(view: id, vsync: bool, gl_version: GlRequest) -> Option { let profile = match gl_version { - None | Some((0...2, _)) | Some((3, 0)) => NSOpenGLProfileVersionLegacy as u32, - Some((3, 1...2)) => NSOpenGLProfileVersion3_2Core as u32, - Some((_, _)) => NSOpenGLProfileVersion4_1Core as u32, + GlRequest::Latest => NSOpenGLProfileVersion4_1Core as u32, + GlRequest::Specific(Api::OpenGl, (1 ... 2, _)) => NSOpenGLProfileVersionLegacy as u32, + GlRequest::Specific(Api::OpenGl, (3, 0)) => NSOpenGLProfileVersionLegacy as u32, + GlRequest::Specific(Api::OpenGl, (3, 1 ... 2)) => NSOpenGLProfileVersion3_2Core as u32, + GlRequest::Specific(Api::OpenGl, _) => NSOpenGLProfileVersion4_1Core as u32, + GlRequest::Specific(_, _) => panic!("Only the OpenGL API is supported"), // FIXME: return Result + GlRequest::GlThenGles { opengl_version: (1 ... 2, _), .. } => NSOpenGLProfileVersionLegacy as u32, + GlRequest::GlThenGles { opengl_version: (3, 0), .. } => NSOpenGLProfileVersionLegacy as u32, + GlRequest::GlThenGles { opengl_version: (3, 1 ... 2), .. } => NSOpenGLProfileVersion3_2Core as u32, + GlRequest::GlThenGles { .. } => NSOpenGLProfileVersion4_1Core as u32, }; unsafe { let attributes = [ diff --git a/src/headless.rs b/src/headless.rs index 9d9cd8d..a38c194 100644 --- a/src/headless.rs +++ b/src/headless.rs @@ -1,6 +1,7 @@ use Api; use BuilderAttribs; use CreationError; +use GlRequest; use gl_common; use libc; @@ -24,12 +25,16 @@ impl HeadlessRendererBuilder { } } - /// Requests to use a specific OpenGL version. - /// - /// Version is a (major, minor) pair. For example to request OpenGL 3.3 - /// you would pass `(3, 3)`. + /// THIS FUNCTION IS DEPRECATED + #[deprecated = "Use with_gl instead"] pub fn with_gl_version(mut self, version: (u32, u32)) -> HeadlessRendererBuilder { - self.attribs.gl_version = Some(version); + self.attribs.gl_version = GlRequest::Specific(::Api::OpenGl, (version.0 as u8, version.1 as u8)); + self + } + + /// 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 } diff --git a/src/lib.rs b/src/lib.rs index 1bd29bb..3798ffd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,6 +114,30 @@ pub enum Api { WebGl, } +/// Describes the OpenGL API and version that are being requested when a context is created. +#[derive(Debug, Copy, Clone)] +pub enum GlRequest { + /// Request the latest version of the "best" API of this platform. + /// + /// On desktop, will try OpenGL. + Latest, + + /// Request a specific version of a specific API. + /// + /// Example: `GlRequest::Specific(Api::OpenGl, (3, 3))`. + Specific(Api, (u8, u8)), + + /// If OpenGL is available, create an OpenGL context with the specified `opengl_version`. + /// Else if OpenGL ES or WebGL is available, create a context with the + /// specified `opengles_version`. + GlThenGles { + /// The version to use for OpenGL. + opengl_version: (u8, u8), + /// The version to use for OpenGL ES. + opengles_version: (u8, u8), + }, +} + #[derive(Debug, Copy)] pub enum MouseCursor { /// The platform-dependent default cursor. @@ -194,7 +218,7 @@ struct BuilderAttribs<'a> { dimensions: Option<(u32, u32)>, title: String, monitor: Option, - gl_version: Option<(u32, u32)>, + gl_version: GlRequest, gl_debug: bool, vsync: bool, visible: bool, @@ -215,7 +239,7 @@ impl BuilderAttribs<'static> { dimensions: None, title: "glutin window".to_string(), monitor: None, - gl_version: None, + gl_version: GlRequest::Latest, gl_debug: cfg!(ndebug), vsync: false, visible: true, diff --git a/src/win32/init.rs b/src/win32/init.rs index 90a6035..8a91214 100644 --- a/src/win32/init.rs +++ b/src/win32/init.rs @@ -5,9 +5,12 @@ use std::os; use super::callback; use super::Window; use super::MonitorID; + +use Api; use BuilderAttribs; use CreationError; use CreationError::OsError; +use GlRequest; use PixelFormat; use std::ffi::CString; @@ -353,12 +356,21 @@ fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'static>)> if extra_functions.CreateContextAttribsARB.is_loaded() { let mut attributes = Vec::new(); - if builder.gl_version.is_some() { - let version = builder.gl_version.as_ref().unwrap(); - attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); - attributes.push(version.0 as libc::c_int); - attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); - attributes.push(version.1 as libc::c_int); + match builder.gl_version { + GlRequest::Latest => {}, + GlRequest::Specific(Api::OpenGl, (major, minor)) => { + attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); + attributes.push(major as libc::c_int); + attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); + attributes.push(minor as libc::c_int); + }, + GlRequest::Specific(_, _) => panic!("Only OpenGL is supported"), + GlRequest::GlThenGles { opengl_version: (major, minor), .. } => { + attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); + attributes.push(major as libc::c_int); + attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); + attributes.push(minor as libc::c_int); + }, } if builder.gl_debug { diff --git a/src/window.rs b/src/window.rs index a830733..c916b27 100644 --- a/src/window.rs +++ b/src/window.rs @@ -5,6 +5,7 @@ use Api; use BuilderAttribs; use CreationError; use Event; +use GlRequest; use MouseCursor; use gl_common; @@ -56,12 +57,16 @@ impl<'a> WindowBuilder<'a> { self } - /// Requests to use a specific OpenGL version. - /// - /// Version is a (major, minor) pair. For example to request OpenGL 3.3 - /// you would pass `(3, 3)`. + /// THIS FUNCTION IS DEPRECATED + #[deprecated = "Use with_gl instead"] pub fn with_gl_version(mut self, version: (u32, u32)) -> WindowBuilder<'a> { - self.attribs.gl_version = Some(version); + self.attribs.gl_version = GlRequest::Specific(::Api::OpenGl, (version.0 as u8, version.1 as u8)); + 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 } diff --git a/src/x11/window/mod.rs b/src/x11/window/mod.rs index 05fcf14..f8afc08 100644 --- a/src/x11/window/mod.rs +++ b/src/x11/window/mod.rs @@ -10,6 +10,9 @@ use super::ffi; use std::sync::{Arc, Mutex, Once, ONCE_INIT, Weak}; use std::sync::{StaticMutex, MUTEX_INIT}; +use Api; +use GlRequest; + pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; mod events; @@ -483,12 +486,21 @@ impl Window { let (context, extra_functions) = unsafe { let mut attributes = Vec::new(); - if builder.gl_version.is_some() { - let version = builder.gl_version.as_ref().unwrap(); - attributes.push(ffi::GLX_CONTEXT_MAJOR_VERSION); - attributes.push(version.0 as libc::c_int); - attributes.push(ffi::GLX_CONTEXT_MINOR_VERSION); - attributes.push(version.1 as libc::c_int); + match builder.gl_version { + GlRequest::Latest => {}, + GlRequest::Specific(Api::OpenGl, (major, minor)) => { + attributes.push(ffi::GLX_CONTEXT_MAJOR_VERSION); + attributes.push(major as libc::c_int); + attributes.push(ffi::GLX_CONTEXT_MINOR_VERSION); + attributes.push(minor as libc::c_int); + }, + GlRequest::Specific(_, _) => panic!("Only OpenGL is supported"), + GlRequest::GlThenGles { opengl_version: (major, minor), .. } => { + attributes.push(ffi::GLX_CONTEXT_MAJOR_VERSION); + attributes.push(major as libc::c_int); + attributes.push(ffi::GLX_CONTEXT_MINOR_VERSION); + attributes.push(minor as libc::c_int); + }, } if builder.gl_debug { -- cgit v1.2.3