Fix compilation on linux

This commit is contained in:
Pierre Krieger 2015-12-19 15:00:32 +01:00
parent 67356b45a3
commit 61bca52217
2 changed files with 61 additions and 52 deletions

View file

@ -80,9 +80,11 @@ fn main() {
"GLX_ARB_create_context".to_string(), "GLX_ARB_create_context".to_string(),
"GLX_ARB_create_context_profile".to_string(), "GLX_ARB_create_context_profile".to_string(),
"GLX_ARB_create_context_robustness".to_string(), "GLX_ARB_create_context_robustness".to_string(),
"GLX_ARB_context_flush_control".to_string(),
"GLX_ARB_fbconfig_float".to_string(), "GLX_ARB_fbconfig_float".to_string(),
"GLX_ARB_framebuffer_sRGB".to_string(), "GLX_ARB_framebuffer_sRGB".to_string(),
"GLX_EXT_framebuffer_sRGB".to_string(), "GLX_EXT_framebuffer_sRGB".to_string(),
"GLX_ARB_multisample".to_string(),
"GLX_EXT_swap_control".to_string(), "GLX_EXT_swap_control".to_string(),
"GLX_SGI_swap_control".to_string() "GLX_SGI_swap_control".to_string()
], ],

View file

@ -13,6 +13,7 @@ use ReleaseBehavior;
use Robustness; use Robustness;
use libc; use libc;
use libc::c_int;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::{mem, ptr, slice}; use std::{mem, ptr, slice};
@ -40,10 +41,17 @@ impl Context {
opengl: &'a GlAttributes<&'a Context>, display: *mut ffi::Display) opengl: &'a GlAttributes<&'a Context>, display: *mut ffi::Display)
-> Result<ContextPrototype<'a>, CreationError> -> Result<ContextPrototype<'a>, CreationError>
{ {
// loading the list of extensions
let extensions = unsafe {
let extensions = glx.QueryExtensionsString(display as *mut _, 0); // FIXME: screen number
let extensions = CStr::from_ptr(extensions).to_bytes().to_vec();
String::from_utf8(extensions).unwrap()
};
// finding the pixel format we want // finding the pixel format we want
let (fb_config, pixel_format) = { let (fb_config, pixel_format) = unsafe {
let configs = unsafe { try!(enumerate_configs(&glx, xlib, display)) }; try!(choose_fbconfig(&glx, &extensions, xlib, display, pf_reqs)
try!(pf_reqs.choose_pixel_format(configs.into_iter())) .map_err(|_| CreationError::NoAvailablePixelFormat))
}; };
// getting the visual infos // getting the visual infos
@ -59,6 +67,7 @@ impl Context {
Ok(ContextPrototype { Ok(ContextPrototype {
glx: glx, glx: glx,
extensions: extensions,
opengl: opengl, opengl: opengl,
display: display, display: display,
fb_config: fb_config, fb_config: fb_config,
@ -126,6 +135,7 @@ impl Drop for Context {
pub struct ContextPrototype<'a> { pub struct ContextPrototype<'a> {
glx: ffi::glx::Glx, glx: ffi::glx::Glx,
extensions: String,
opengl: &'a GlAttributes<&'a Context>, opengl: &'a GlAttributes<&'a Context>,
display: *mut ffi::Display, display: *mut ffi::Display,
fb_config: ffi::glx::types::GLXFBConfig, fb_config: ffi::glx::types::GLXFBConfig,
@ -145,13 +155,6 @@ impl<'a> ContextPrototype<'a> {
None => ptr::null() None => ptr::null()
}; };
// loading the list of extensions
let extensions = unsafe {
let extensions = self.glx.QueryExtensionsString(self.display as *mut _, 0); // FIXME: screen number
let extensions = CStr::from_ptr(extensions).to_bytes().to_vec();
String::from_utf8(extensions).unwrap()
};
// loading the extra GLX functions // loading the extra GLX functions
let extra_functions = ffi::glx_extra::Glx::load_with(|addr| { let extra_functions = ffi::glx_extra::Glx::load_with(|addr| {
with_c_str(addr, |s| { with_c_str(addr, |s| {
@ -162,13 +165,13 @@ impl<'a> ContextPrototype<'a> {
// creating GL context // creating GL context
let context = match self.opengl.version { let context = match self.opengl.version {
GlRequest::Latest => { GlRequest::Latest => {
if let Ok(ctxt) = create_context(&self.glx, &extra_functions, &extensions, (3, 2), if let Ok(ctxt) = create_context(&self.glx, &extra_functions, &self.extensions, (3, 2),
self.opengl.profile, self.opengl.debug, self.opengl.profile, self.opengl.debug,
self.opengl.robustness, share, self.opengl.robustness, share,
self.display, self.fb_config, &self.visual_infos) self.display, self.fb_config, &self.visual_infos)
{ {
ctxt ctxt
} else if let Ok(ctxt) = create_context(&self.glx, &extra_functions, &extensions, } else if let Ok(ctxt) = create_context(&self.glx, &extra_functions, &self.extensions,
(3, 1), self.opengl.profile, (3, 1), self.opengl.profile,
self.opengl.debug, self.opengl.debug,
self.opengl.robustness, share, self.display, self.opengl.robustness, share, self.display,
@ -177,21 +180,21 @@ impl<'a> ContextPrototype<'a> {
ctxt ctxt
} else { } else {
try!(create_context(&self.glx, &extra_functions, &extensions, (1, 0), try!(create_context(&self.glx, &extra_functions, &self.extensions, (1, 0),
self.opengl.profile, self.opengl.debug, self.opengl.profile, self.opengl.debug,
self.opengl.robustness, self.opengl.robustness,
share, self.display, self.fb_config, &self.visual_infos)) share, self.display, self.fb_config, &self.visual_infos))
} }
}, },
GlRequest::Specific(Api::OpenGl, (major, minor)) => { GlRequest::Specific(Api::OpenGl, (major, minor)) => {
try!(create_context(&self.glx, &extra_functions, &extensions, (major, minor), try!(create_context(&self.glx, &extra_functions, &self.extensions, (major, minor),
self.opengl.profile, self.opengl.debug, self.opengl.profile, self.opengl.debug,
self.opengl.robustness, share, self.display, self.fb_config, self.opengl.robustness, share, self.display, self.fb_config,
&self.visual_infos)) &self.visual_infos))
}, },
GlRequest::Specific(_, _) => panic!("Only OpenGL is supported"), GlRequest::Specific(_, _) => panic!("Only OpenGL is supported"),
GlRequest::GlThenGles { opengl_version: (major, minor), .. } => { GlRequest::GlThenGles { opengl_version: (major, minor), .. } => {
try!(create_context(&self.glx, &extra_functions, &extensions, (major, minor), try!(create_context(&self.glx, &extra_functions, &self.extensions, (major, minor),
self.opengl.profile, self.opengl.debug, self.opengl.profile, self.opengl.debug,
self.opengl.robustness, share, self.display, self.fb_config, self.opengl.robustness, share, self.display, self.fb_config,
&self.visual_infos)) &self.visual_infos))
@ -264,10 +267,10 @@ fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx, ex
let context = if extensions.split(' ').find(|&i| i == "GLX_ARB_create_context").is_some() { let context = if extensions.split(' ').find(|&i| i == "GLX_ARB_create_context").is_some() {
let mut attributes = Vec::with_capacity(9); let mut attributes = Vec::with_capacity(9);
attributes.push(ffi::glx_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); attributes.push(ffi::glx_extra::CONTEXT_MAJOR_VERSION_ARB as c_int);
attributes.push(version.0 as libc::c_int); attributes.push(version.0 as c_int);
attributes.push(ffi::glx_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); attributes.push(ffi::glx_extra::CONTEXT_MINOR_VERSION_ARB as c_int);
attributes.push(version.1 as libc::c_int); attributes.push(version.1 as c_int);
if let Some(profile) = profile { if let Some(profile) = profile {
let flag = match profile { let flag = match profile {
@ -277,8 +280,8 @@ fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx, ex
ffi::glx_extra::CONTEXT_CORE_PROFILE_BIT_ARB, ffi::glx_extra::CONTEXT_CORE_PROFILE_BIT_ARB,
}; };
attributes.push(ffi::glx_extra::CONTEXT_PROFILE_MASK_ARB as libc::c_int); attributes.push(ffi::glx_extra::CONTEXT_PROFILE_MASK_ARB as c_int);
attributes.push(flag as libc::c_int); attributes.push(flag as c_int);
} }
let flags = { let flags = {
@ -288,14 +291,14 @@ fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx, ex
if extensions.split(' ').find(|&i| i == "GLX_ARB_create_context_robustness").is_some() { if extensions.split(' ').find(|&i| i == "GLX_ARB_create_context_robustness").is_some() {
match robustness { match robustness {
Robustness::RobustNoResetNotification | Robustness::TryRobustNoResetNotification => { Robustness::RobustNoResetNotification | Robustness::TryRobustNoResetNotification => {
attributes.push(ffi::glx_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as libc::c_int); attributes.push(ffi::glx_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as c_int);
attributes.push(ffi::glx_extra::NO_RESET_NOTIFICATION_ARB as libc::c_int); attributes.push(ffi::glx_extra::NO_RESET_NOTIFICATION_ARB as c_int);
flags = flags | ffi::glx_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB as libc::c_int; flags = flags | ffi::glx_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB as c_int;
}, },
Robustness::RobustLoseContextOnReset | Robustness::TryRobustLoseContextOnReset => { Robustness::RobustLoseContextOnReset | Robustness::TryRobustLoseContextOnReset => {
attributes.push(ffi::glx_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as libc::c_int); attributes.push(ffi::glx_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as c_int);
attributes.push(ffi::glx_extra::LOSE_CONTEXT_ON_RESET_ARB as libc::c_int); attributes.push(ffi::glx_extra::LOSE_CONTEXT_ON_RESET_ARB as c_int);
flags = flags | ffi::glx_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB as libc::c_int; flags = flags | ffi::glx_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB as c_int;
}, },
Robustness::NotRobust => (), Robustness::NotRobust => (),
Robustness::NoError => (), Robustness::NoError => (),
@ -310,13 +313,13 @@ fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx, ex
} }
if debug { if debug {
flags = flags | ffi::glx_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int; flags = flags | ffi::glx_extra::CONTEXT_DEBUG_BIT_ARB as c_int;
} }
flags flags
}; };
attributes.push(ffi::glx_extra::CONTEXT_FLAGS_ARB as libc::c_int); attributes.push(ffi::glx_extra::CONTEXT_FLAGS_ARB as c_int);
attributes.push(flags); attributes.push(flags);
attributes.push(0); attributes.push(0);
@ -339,8 +342,9 @@ fn create_context(glx: &ffi::glx::Glx, extra_functions: &ffi::glx_extra::Glx, ex
} }
/// Enumerates all available FBConfigs /// Enumerates all available FBConfigs
unsafe fn enumerate_configs(glx: &ffi::glx::Glx, xlib: &ffi::Xlib, display: *mut ffi::Display) unsafe fn choose_fbconfig(glx: &ffi::glx::Glx, extensions: &str, xlib: &ffi::Xlib,
-> Result<Vec<(ffi::glx::types::GLXFBConfig, PixelFormat)>, CreationError> display: *mut ffi::Display, reqs: &PixelFormatRequirements)
-> Result<(ffi::glx::types::GLXFBConfig, PixelFormat), ()>
{ {
let descriptor = { let descriptor = {
let mut out: Vec<c_int> = Vec::with_capacity(37); let mut out: Vec<c_int> = Vec::with_capacity(37);
@ -357,7 +361,7 @@ unsafe fn enumerate_configs(glx: &ffi::glx::Glx, xlib: &ffi::Xlib, display: *mut
out.push(ffi::glx::RENDER_TYPE as c_int); out.push(ffi::glx::RENDER_TYPE as c_int);
if reqs.float_color_buffer { if reqs.float_color_buffer {
if extensions.split(' ').find(|&i| i == "GLX_ARB_fbconfig_float").is_some() { if extensions.split(' ').find(|&i| i == "GLX_ARB_fbconfig_float").is_some() {
out.push(ffi::glx::RGBA_FLOAT_BIT_ARB as c_int); out.push(ffi::glx_extra::RGBA_FLOAT_BIT_ARB as c_int);
} else { } else {
return Err(()); return Err(());
} }
@ -405,9 +409,9 @@ unsafe fn enumerate_configs(glx: &ffi::glx::Glx, xlib: &ffi::Xlib, display: *mut
if let Some(multisampling) = reqs.multisampling { if let Some(multisampling) = reqs.multisampling {
if extensions.split(' ').find(|&i| i == "GLX_ARB_multisample").is_some() { if extensions.split(' ').find(|&i| i == "GLX_ARB_multisample").is_some() {
out.push(ffi::glx::SAMPLE_BUFFERS_ARB as c_int); out.push(ffi::glx_extra::SAMPLE_BUFFERS_ARB as c_int);
out.push(if multisampling == 0 { 0 } else { 1 }); out.push(if multisampling == 0 { 0 } else { 1 });
out.push(ffi::glx::SAMPLES_ARB as c_int); out.push(ffi::glx_extra::SAMPLES_ARB as c_int);
out.push(multisampling as c_int); out.push(multisampling as c_int);
} else { } else {
return Err(()); return Err(());
@ -419,7 +423,7 @@ unsafe fn enumerate_configs(glx: &ffi::glx::Glx, xlib: &ffi::Xlib, display: *mut
if reqs.srgb { if reqs.srgb {
if extensions.split(' ').find(|&i| i == "GLX_ARB_framebuffer_sRGB").is_some() { if extensions.split(' ').find(|&i| i == "GLX_ARB_framebuffer_sRGB").is_some() {
out.push(ffi::glx::FRAMEBUFFER_SRGB_CAPABLE_ARB as c_int); out.push(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as c_int);
out.push(1); out.push(1);
} else { } else {
return Err(()); return Err(());
@ -430,8 +434,8 @@ unsafe fn enumerate_configs(glx: &ffi::glx::Glx, xlib: &ffi::Xlib, display: *mut
ReleaseBehavior::Flush => (), ReleaseBehavior::Flush => (),
ReleaseBehavior::None => { ReleaseBehavior::None => {
if extensions.split(' ').find(|&i| i == "GLX_ARB_context_flush_control").is_some() { if extensions.split(' ').find(|&i| i == "GLX_ARB_context_flush_control").is_some() {
out.push(ffi::glx::CONTEXT_RELEASE_BEHAVIOR_ARB as c_int); out.push(ffi::glx_extra::CONTEXT_RELEASE_BEHAVIOR_ARB as c_int);
out.push(ffi::glx::CONTEXT_RELEASE_BEHAVIOR_NONE_ARB as c_int); out.push(ffi::glx_extra::CONTEXT_RELEASE_BEHAVIOR_NONE_ARB as c_int);
} }
}, },
} }
@ -442,14 +446,17 @@ unsafe fn enumerate_configs(glx: &ffi::glx::Glx, xlib: &ffi::Xlib, display: *mut
// calling glXChooseFBConfig // calling glXChooseFBConfig
let fb_config = { let fb_config = {
let result = glx.ChooseFBConfig(display as *mut _, 0, descriptor.as_ptr(), &1); let mut num_configs = 1;
let result = glx.ChooseFBConfig(display as *mut _, 0, descriptor.as_ptr(),
&mut num_configs);
if result.is_null() { return Err(()); } if result.is_null() { return Err(()); }
if num_configs == 0 { return Err(()); }
let val = *result; let val = *result;
(xlib.XFree)(result as *mut _); (xlib.XFree)(result as *mut _);
val val
}; };
let get_attrib = |attrib: libc::c_int| -> i32 { let get_attrib = |attrib: c_int| -> i32 {
let mut value = 0; let mut value = 0;
glx.GetFBConfigAttrib(display as *mut _, fb_config, attrib, &mut value); glx.GetFBConfigAttrib(display as *mut _, fb_config, attrib, &mut value);
// TODO: check return value // TODO: check return value
@ -457,22 +464,22 @@ unsafe fn enumerate_configs(glx: &ffi::glx::Glx, xlib: &ffi::Xlib, display: *mut
}; };
let pf_desc = PixelFormat { let pf_desc = PixelFormat {
hardware_accelerated: get_attrib(ffi::glx::CONFIG_CAVEAT as libc::c_int, config) != hardware_accelerated: get_attrib(ffi::glx::CONFIG_CAVEAT as c_int) !=
ffi::glx::SLOW_CONFIG as libc::c_int, ffi::glx::SLOW_CONFIG as c_int,
color_bits: get_attrib(ffi::glx::RED_SIZE as libc::c_int, config) as u8 + color_bits: get_attrib(ffi::glx::RED_SIZE as c_int) as u8 +
get_attrib(ffi::glx::GREEN_SIZE as libc::c_int, config) as u8 + get_attrib(ffi::glx::GREEN_SIZE as c_int) as u8 +
get_attrib(ffi::glx::BLUE_SIZE as libc::c_int, config) as u8, get_attrib(ffi::glx::BLUE_SIZE as c_int) as u8,
alpha_bits: get_attrib(ffi::glx::ALPHA_SIZE as libc::c_int, config) as u8, alpha_bits: get_attrib(ffi::glx::ALPHA_SIZE as c_int) as u8,
depth_bits: get_attrib(ffi::glx::DEPTH_SIZE as libc::c_int, config) as u8, depth_bits: get_attrib(ffi::glx::DEPTH_SIZE as c_int) as u8,
stencil_bits: get_attrib(ffi::glx::STENCIL_SIZE as libc::c_int, config) as u8, stencil_bits: get_attrib(ffi::glx::STENCIL_SIZE as c_int) as u8,
stereoscopy: get_attrib(ffi::glx::STEREO as libc::c_int, config) != 0, stereoscopy: get_attrib(ffi::glx::STEREO as c_int) != 0,
double_buffer: get_attrib(ffi::glx::DOUBLEBUFFER as libc::c_int, config) != 0, double_buffer: get_attrib(ffi::glx::DOUBLEBUFFER as c_int) != 0,
multisampling: if get_attrib(ffi::glx::SAMPLE_BUFFERS as libc::c_int, config) != 0 { multisampling: if get_attrib(ffi::glx::SAMPLE_BUFFERS as c_int) != 0 {
Some(get_attrib(ffi::glx::SAMPLES as libc::c_int, config) as u16) Some(get_attrib(ffi::glx::SAMPLES as c_int) as u16)
} else { } else {
None None
}, },
srgb: get_attrib(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as libc::c_int, config) != 0, srgb: get_attrib(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as c_int) != 0,
}; };
Ok((fb_config, pf_desc)) Ok((fb_config, pf_desc))