diff options
Diffstat (limited to 'src/api')
| -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) +    } +} | 
