diff options
-rw-r--r-- | src/api/glx/mod.rs | 163 |
1 files changed, 94 insertions, 69 deletions
diff --git a/src/api/glx/mod.rs b/src/api/glx/mod.rs index 3c0c8a0..f1eb436 100644 --- a/src/api/glx/mod.rs +++ b/src/api/glx/mod.rs @@ -35,80 +35,55 @@ impl Context { fb_config: ffi::glx::types::GLXFBConfig, mut visual_infos: ffi::glx::types::XVisualInfo) -> Result<Context, CreationError> { - // creating GL context - let (context, extra_functions) = unsafe { - let mut attributes = Vec::new(); - - match builder.gl_version { - GlRequest::Latest => {}, - GlRequest::Specific(Api::OpenGl, (major, minor)) => { - attributes.push(ffi::glx_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); - attributes.push(major as libc::c_int); - attributes.push(ffi::glx_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(ffi::glx_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); - attributes.push(major as libc::c_int); - attributes.push(ffi::glx_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); - attributes.push(minor as libc::c_int); + let share = if let Some(win) = builder.sharing { + match win { + &PlatformWindow::X(ref win) => match win.x.context { + ::api::x11::Context::Glx(ref c) => c.context, + _ => panic!("Cannot share contexts between different APIs") }, + _ => panic!("Cannot use glx on a non-X11 window.") } + } else { + ptr::null() + }; - if let Some(profile) = builder.gl_profile { - let flag = match profile { - GlProfile::Compatibility => - ffi::glx_extra::CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - GlProfile::Core => - ffi::glx_extra::CONTEXT_CORE_PROFILE_BIT_ARB, - }; - attributes.push(ffi::glx_extra::CONTEXT_PROFILE_MASK_ARB as libc::c_int); - attributes.push(flag as libc::c_int); - } - - if builder.gl_debug { - attributes.push(ffi::glx_extra::CONTEXT_FLAGS_ARB as libc::c_int); - attributes.push(ffi::glx_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int); - } - - attributes.push(0); + // loading the extra GLX functions + let extra_functions = ffi::glx_extra::Glx::load_with(|addr| { + with_c_str(addr, |s| { + unsafe { glx.GetProcAddress(s as *const u8) as *const _ } + }) + }); - // loading the extra GLX functions - let extra_functions = ffi::glx_extra::Glx::load_with(|addr| { - with_c_str(addr, |s| { - glx.GetProcAddress(s as *const u8) as *const libc::c_void - }) - }); - - let share = if let Some(win) = builder.sharing { - match win { - &PlatformWindow::X(ref win) => match win.x.context { - ::api::x11::Context::Glx(ref c) => c.context, - _ => panic!("Cannot share contexts between different APIs") - }, - _ => panic!("Cannot use glx on a non-X11 window.") + // creating GL context + let context = match builder.gl_version { + GlRequest::Latest => { + if let Ok(ctxt) = create_context(&glx, &extra_functions, (3, 2), + builder.gl_profile, builder.gl_debug, share, + display, fb_config, &mut visual_infos) + { + ctxt + } else if let Ok(ctxt) = create_context(&glx, &extra_functions, (3, 1), + builder.gl_profile, builder.gl_debug, + share, display, fb_config, + &mut visual_infos) + { + ctxt + + } else { + try!(create_context(&glx, &extra_functions, (1, 0), builder.gl_profile, + builder.gl_debug, share, display, fb_config, + &mut visual_infos)) } - } else { - ptr::null() - }; - - let mut context = if extra_functions.CreateContextAttribsARB.is_loaded() { - extra_functions.CreateContextAttribsARB(display as *mut ffi::glx_extra::types::Display, - fb_config, share, 1, attributes.as_ptr()) - } else { - ptr::null() - }; - - if context.is_null() { - context = glx.CreateContext(display as *mut _, &mut visual_infos, share, 1) - } - - if context.is_null() { - return Err(CreationError::OsError(format!("GL context creation failed"))); - } - - (context, extra_functions) + }, + GlRequest::Specific(Api::OpenGl, (major, minor)) => { + try!(create_context(&glx, &extra_functions, (major, minor), builder.gl_profile, + builder.gl_debug, share, display, fb_config, &mut visual_infos)) + }, + GlRequest::Specific(_, _) => panic!("Only OpenGL is supported"), + GlRequest::GlThenGles { opengl_version: (major, minor), .. } => { + try!(create_context(&glx, &extra_functions, (major, minor), builder.gl_profile, + builder.gl_debug, share, display, fb_config, &mut visual_infos)) + }, }; // vsync @@ -210,3 +185,53 @@ impl Drop for Context { } } } + +fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx, + version: (u8, u8), profile: Option<GlProfile>, debug: bool, + share: ffi::GLXContext, display: *mut ffi::Display, + fb_config: ffi::glx::types::GLXFBConfig, + visual_infos: &mut ffi::glx::types::XVisualInfo) + -> Result<ffi::GLXContext, CreationError> +{ + unsafe { + let context = if extra_functions.CreateContextAttribsARB.is_loaded() { + let mut attributes = Vec::with_capacity(9); + + attributes.push(ffi::glx_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); + attributes.push(version.0 as libc::c_int); + attributes.push(ffi::glx_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); + attributes.push(version.1 as libc::c_int); + + if let Some(profile) = profile { + let flag = match profile { + GlProfile::Compatibility => + ffi::glx_extra::CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + GlProfile::Core => + ffi::glx_extra::CONTEXT_CORE_PROFILE_BIT_ARB, + }; + + attributes.push(ffi::glx_extra::CONTEXT_PROFILE_MASK_ARB as libc::c_int); + attributes.push(flag as libc::c_int); + } + + if debug { + attributes.push(ffi::glx_extra::CONTEXT_FLAGS_ARB as libc::c_int); + attributes.push(ffi::glx_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int); + } + + attributes.push(0); + + extra_functions.CreateContextAttribsARB(display as *mut _, fb_config, share, 1, + attributes.as_ptr()) + + } else { + glx.CreateContext(display as *mut _, visual_infos, share, 1) + }; + + if context.is_null() { + return Err(CreationError::OsError(format!("GL context creation failed"))); + } + + Ok(context) + } +} |