Improve the OpenGL context request system

This commit is contained in:
Pierre Krieger 2015-02-18 16:49:53 +01:00
parent 8f8c1b71bc
commit f4f84c6566
7 changed files with 101 additions and 29 deletions

View file

@ -11,7 +11,9 @@ use events::MouseButton;
use std::collections::RingBuf; use std::collections::RingBuf;
use Api;
use BuilderAttribs; use BuilderAttribs;
use GlRequest;
pub struct Window { pub struct Window {
display: ffi::egl::types::EGLDisplay, display: ffi::egl::types::EGLDisplay,
@ -157,7 +159,10 @@ impl Window {
android_glue::write_log("eglInitialize succeeded"); android_glue::write_log("eglInitialize succeeded");
let use_gles2 = match builder.gl_version { 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, _ => false,
}; };

View file

@ -5,7 +5,9 @@ use {CreationError, Event, MouseCursor};
use CreationError::OsError; use CreationError::OsError;
use libc; use libc;
use Api;
use BuilderAttribs; use BuilderAttribs;
use GlRequest;
use cocoa::base::{Class, id, YES, NO, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair}; 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}; 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<id> { fn create_context(view: id, vsync: bool, gl_version: GlRequest) -> Option<id> {
let profile = match gl_version { let profile = match gl_version {
None | Some((0...2, _)) | Some((3, 0)) => NSOpenGLProfileVersionLegacy as u32, GlRequest::Latest => NSOpenGLProfileVersion4_1Core as u32,
Some((3, 1...2)) => NSOpenGLProfileVersion3_2Core as u32, GlRequest::Specific(Api::OpenGl, (1 ... 2, _)) => NSOpenGLProfileVersionLegacy as u32,
Some((_, _)) => NSOpenGLProfileVersion4_1Core 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 { unsafe {
let attributes = [ let attributes = [

View file

@ -1,6 +1,7 @@
use Api; use Api;
use BuilderAttribs; use BuilderAttribs;
use CreationError; use CreationError;
use GlRequest;
use gl_common; use gl_common;
use libc; use libc;
@ -24,12 +25,16 @@ impl HeadlessRendererBuilder {
} }
} }
/// Requests to use a specific OpenGL version. /// THIS FUNCTION IS DEPRECATED
/// #[deprecated = "Use with_gl instead"]
/// Version is a (major, minor) pair. For example to request OpenGL 3.3
/// you would pass `(3, 3)`.
pub fn with_gl_version(mut self, version: (u32, u32)) -> HeadlessRendererBuilder { 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 self
} }

View file

@ -114,6 +114,30 @@ pub enum Api {
WebGl, 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)] #[derive(Debug, Copy)]
pub enum MouseCursor { pub enum MouseCursor {
/// The platform-dependent default cursor. /// The platform-dependent default cursor.
@ -194,7 +218,7 @@ struct BuilderAttribs<'a> {
dimensions: Option<(u32, u32)>, dimensions: Option<(u32, u32)>,
title: String, title: String,
monitor: Option<winimpl::MonitorID>, monitor: Option<winimpl::MonitorID>,
gl_version: Option<(u32, u32)>, gl_version: GlRequest,
gl_debug: bool, gl_debug: bool,
vsync: bool, vsync: bool,
visible: bool, visible: bool,
@ -215,7 +239,7 @@ impl BuilderAttribs<'static> {
dimensions: None, dimensions: None,
title: "glutin window".to_string(), title: "glutin window".to_string(),
monitor: None, monitor: None,
gl_version: None, gl_version: GlRequest::Latest,
gl_debug: cfg!(ndebug), gl_debug: cfg!(ndebug),
vsync: false, vsync: false,
visible: true, visible: true,

View file

@ -5,9 +5,12 @@ use std::os;
use super::callback; use super::callback;
use super::Window; use super::Window;
use super::MonitorID; use super::MonitorID;
use Api;
use BuilderAttribs; use BuilderAttribs;
use CreationError; use CreationError;
use CreationError::OsError; use CreationError::OsError;
use GlRequest;
use PixelFormat; use PixelFormat;
use std::ffi::CString; 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() { if extra_functions.CreateContextAttribsARB.is_loaded() {
let mut attributes = Vec::new(); let mut attributes = Vec::new();
if builder.gl_version.is_some() { match builder.gl_version {
let version = builder.gl_version.as_ref().unwrap(); GlRequest::Latest => {},
attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); GlRequest::Specific(Api::OpenGl, (major, minor)) => {
attributes.push(version.0 as libc::c_int); attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int);
attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); attributes.push(major as libc::c_int);
attributes.push(version.1 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 { if builder.gl_debug {

View file

@ -5,6 +5,7 @@ use Api;
use BuilderAttribs; use BuilderAttribs;
use CreationError; use CreationError;
use Event; use Event;
use GlRequest;
use MouseCursor; use MouseCursor;
use gl_common; use gl_common;
@ -56,12 +57,16 @@ impl<'a> WindowBuilder<'a> {
self self
} }
/// Requests to use a specific OpenGL version. /// THIS FUNCTION IS DEPRECATED
/// #[deprecated = "Use with_gl instead"]
/// Version is a (major, minor) pair. For example to request OpenGL 3.3
/// you would pass `(3, 3)`.
pub fn with_gl_version(mut self, version: (u32, u32)) -> WindowBuilder<'a> { 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 self
} }

View file

@ -10,6 +10,9 @@ use super::ffi;
use std::sync::{Arc, Mutex, Once, ONCE_INIT, Weak}; use std::sync::{Arc, Mutex, Once, ONCE_INIT, Weak};
use std::sync::{StaticMutex, MUTEX_INIT}; use std::sync::{StaticMutex, MUTEX_INIT};
use Api;
use GlRequest;
pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
mod events; mod events;
@ -483,12 +486,21 @@ impl Window {
let (context, extra_functions) = unsafe { let (context, extra_functions) = unsafe {
let mut attributes = Vec::new(); let mut attributes = Vec::new();
if builder.gl_version.is_some() { match builder.gl_version {
let version = builder.gl_version.as_ref().unwrap(); GlRequest::Latest => {},
attributes.push(ffi::GLX_CONTEXT_MAJOR_VERSION); GlRequest::Specific(Api::OpenGl, (major, minor)) => {
attributes.push(version.0 as libc::c_int); attributes.push(ffi::GLX_CONTEXT_MAJOR_VERSION);
attributes.push(ffi::GLX_CONTEXT_MINOR_VERSION); attributes.push(major as libc::c_int);
attributes.push(version.1 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 { if builder.gl_debug {