Merge pull request #806 from glennw/osmesa

Add support to Linux headless implementation for specifying OpenGL version.
This commit is contained in:
tomaka 2016-08-22 12:42:13 +02:00 committed by GitHub
commit bb91df4fb8
2 changed files with 52 additions and 5 deletions

View file

@ -7,6 +7,8 @@ use ContextError;
use CreationError; use CreationError;
use GlAttributes; use GlAttributes;
use GlContext; use GlContext;
use GlProfile;
use GlRequest;
use PixelFormat; use PixelFormat;
use PixelFormatRequirements; use PixelFormatRequirements;
use Robustness; use Robustness;
@ -34,7 +36,7 @@ impl From<CreationError> for OsMesaCreationError {
} }
impl OsMesaContext { impl OsMesaContext {
pub fn new(dimensions: (u32, u32), pf_reqs: &PixelFormatRequirements, pub fn new(dimensions: (u32, u32), _pf_reqs: &PixelFormatRequirements,
opengl: &GlAttributes<&OsMesaContext>) -> Result<OsMesaContext, OsMesaCreationError> opengl: &GlAttributes<&OsMesaContext>) -> Result<OsMesaContext, OsMesaCreationError>
{ {
if let Err(_) = osmesa_sys::OsMesa::try_loading() { if let Err(_) = osmesa_sys::OsMesa::try_loading() {
@ -51,7 +53,44 @@ impl OsMesaContext {
} }
// TODO: use `pf_reqs` for the format // TODO: use `pf_reqs` for the format
// TODO: check OpenGL version and return `OpenGlVersionNotSupported` if necessary
let mut attribs = Vec::new();
if let Some(profile) = opengl.profile {
attribs.push(osmesa_sys::OSMESA_PROFILE);
match profile {
GlProfile::Compatibility => {
attribs.push(osmesa_sys::OSMESA_COMPAT_PROFILE);
}
GlProfile::Core => {
attribs.push(osmesa_sys::OSMESA_CORE_PROFILE);
}
}
}
match opengl.version {
GlRequest::Latest => {},
GlRequest::Specific(Api::OpenGl, (major, minor)) => {
attribs.push(osmesa_sys::OSMESA_CONTEXT_MAJOR_VERSION);
attribs.push(major as libc::c_int);
attribs.push(osmesa_sys::OSMESA_CONTEXT_MINOR_VERSION);
attribs.push(minor as libc::c_int);
},
GlRequest::Specific(Api::OpenGlEs, _) => {
return Err(OsMesaCreationError::NotSupported);
},
GlRequest::Specific(_, _) => return Err(OsMesaCreationError::NotSupported),
GlRequest::GlThenGles { opengl_version: (major, minor), .. } => {
attribs.push(osmesa_sys::OSMESA_CONTEXT_MAJOR_VERSION);
attribs.push(major as libc::c_int);
attribs.push(osmesa_sys::OSMESA_CONTEXT_MINOR_VERSION);
attribs.push(minor as libc::c_int);
},
}
// attribs array must be NULL terminated.
attribs.push(0);
Ok(OsMesaContext { Ok(OsMesaContext {
width: dimensions.0, width: dimensions.0,
@ -59,9 +98,9 @@ impl OsMesaContext {
buffer: ::std::iter::repeat(unsafe { mem::uninitialized() }) buffer: ::std::iter::repeat(unsafe { mem::uninitialized() })
.take((dimensions.0 * dimensions.1) as usize).collect(), .take((dimensions.0 * dimensions.1) as usize).collect(),
context: unsafe { context: unsafe {
let ctxt = osmesa_sys::OSMesaCreateContext(0x1908, ptr::null_mut()); let ctxt = osmesa_sys::OSMesaCreateContextAttribs(attribs.as_ptr(), ptr::null_mut());
if ctxt.is_null() { if ctxt.is_null() {
return Err(CreationError::OsError("OSMesaCreateContext failed".to_string()).into()); return Err(CreationError::OsError("OSMesaCreateContextAttribs failed".to_string()).into());
} }
ctxt ctxt
} }

View file

@ -2,6 +2,7 @@ use Api;
use ContextError; use ContextError;
use CreationError; use CreationError;
use GlAttributes; use GlAttributes;
use GlProfile;
use GlRequest; use GlRequest;
use GlContext; use GlContext;
use PixelFormat; use PixelFormat;
@ -45,6 +46,13 @@ impl<'a> HeadlessRendererBuilder<'a> {
self self
} }
/// Sets the desired OpenGL context profile.
#[inline]
pub fn with_gl_profile(mut self, profile: GlProfile) -> HeadlessRendererBuilder<'a> {
self.opengl.profile = Some(profile);
self
}
/// Sets the *debug* flag for the OpenGL context. /// Sets the *debug* flag for the OpenGL context.
/// ///
/// The default value for this flag is `cfg!(ndebug)`, which means that it's enabled /// The default value for this flag is `cfg!(ndebug)`, which means that it's enabled
@ -95,7 +103,7 @@ impl HeadlessContext {
pub unsafe fn make_current(&self) -> Result<(), ContextError> { pub unsafe fn make_current(&self) -> Result<(), ContextError> {
self.context.make_current() self.context.make_current()
} }
/// Returns true if this context is the current one in this thread. /// Returns true if this context is the current one in this thread.
#[inline] #[inline]
pub fn is_current(&self) -> bool { pub fn is_current(&self) -> bool {