Merge pull request #282 from tomaka/gl-api

Improve the OpenGL context request system
This commit is contained in:
tomaka 2015-02-19 21:55:15 +01:00
commit 8e1d0f7a97
7 changed files with 101 additions and 29 deletions

View file

@ -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,
};

View file

@ -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<id> {
fn create_context(view: id, vsync: bool, gl_version: GlRequest) -> Option<id> {
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 = [

View file

@ -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
}

View file

@ -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<winimpl::MonitorID>,
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,

View file

@ -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 {

View file

@ -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
}

View file

@ -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 {