mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 06:11:30 +11:00
Merge pull request #677 from tomaka/pf
No longer manually enumerate pixel formats
This commit is contained in:
commit
1f5f997a68
5
build.rs
5
build.rs
|
@ -28,10 +28,12 @@ fn main() {
|
||||||
"WGL_ARB_create_context".to_string(),
|
"WGL_ARB_create_context".to_string(),
|
||||||
"WGL_ARB_create_context_profile".to_string(),
|
"WGL_ARB_create_context_profile".to_string(),
|
||||||
"WGL_ARB_create_context_robustness".to_string(),
|
"WGL_ARB_create_context_robustness".to_string(),
|
||||||
|
"WGL_ARB_context_flush_control".to_string(),
|
||||||
"WGL_ARB_extensions_string".to_string(),
|
"WGL_ARB_extensions_string".to_string(),
|
||||||
"WGL_ARB_framebuffer_sRGB".to_string(),
|
"WGL_ARB_framebuffer_sRGB".to_string(),
|
||||||
"WGL_ARB_multisample".to_string(),
|
"WGL_ARB_multisample".to_string(),
|
||||||
"WGL_ARB_pixel_format".to_string(),
|
"WGL_ARB_pixel_format".to_string(),
|
||||||
|
"WGL_ARB_pixel_format_float".to_string(),
|
||||||
"WGL_EXT_create_context_es2_profile".to_string(),
|
"WGL_EXT_create_context_es2_profile".to_string(),
|
||||||
"WGL_EXT_extensions_string".to_string(),
|
"WGL_EXT_extensions_string".to_string(),
|
||||||
"WGL_EXT_framebuffer_sRGB".to_string(),
|
"WGL_EXT_framebuffer_sRGB".to_string(),
|
||||||
|
@ -78,8 +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_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()
|
||||||
],
|
],
|
||||||
|
|
|
@ -13,6 +13,7 @@ use GlProfile;
|
||||||
use GlRequest;
|
use GlRequest;
|
||||||
use PixelFormat;
|
use PixelFormat;
|
||||||
use PixelFormatRequirements;
|
use PixelFormatRequirements;
|
||||||
|
use ReleaseBehavior;
|
||||||
use Robustness;
|
use Robustness;
|
||||||
use WindowAttributes;
|
use WindowAttributes;
|
||||||
use native_monitor::NativeMonitorId;
|
use native_monitor::NativeMonitorId;
|
||||||
|
@ -491,6 +492,8 @@ impl Window {
|
||||||
let alpha_depth = pf_reqs.alpha_bits.unwrap_or(8);
|
let alpha_depth = pf_reqs.alpha_bits.unwrap_or(8);
|
||||||
let color_depth = pf_reqs.color_bits.unwrap_or(24) + alpha_depth;
|
let color_depth = pf_reqs.color_bits.unwrap_or(24) + alpha_depth;
|
||||||
|
|
||||||
|
// TODO: handle hardware_accelerated parameter of pf_reqs
|
||||||
|
|
||||||
let mut attributes = vec![
|
let mut attributes = vec![
|
||||||
NSOpenGLPFADoubleBuffer as u32,
|
NSOpenGLPFADoubleBuffer as u32,
|
||||||
NSOpenGLPFAClosestPolicy as u32,
|
NSOpenGLPFAClosestPolicy as u32,
|
||||||
|
@ -501,10 +504,19 @@ impl Window {
|
||||||
NSOpenGLPFAOpenGLProfile as u32, profile,
|
NSOpenGLPFAOpenGLProfile as u32, profile,
|
||||||
];
|
];
|
||||||
|
|
||||||
// A color depth higher than 64 implies we're using either 16-bit
|
if pf_reqs.release_behavior != ReleaseBehavior::Flush {
|
||||||
// floats or 32-bit floats and OS X requires a flag to be set
|
return Err(CreationError::NoAvailablePixelFormat);
|
||||||
// accordingly.
|
}
|
||||||
if color_depth >= 64 {
|
|
||||||
|
if pf_reqs.stereoscopy {
|
||||||
|
unimplemented!(); // TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
if pf_reqs.double_buffer == Some(false) {
|
||||||
|
unimplemented!(); // TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
if pf_reqs.float_color_buffer {
|
||||||
attributes.push(NSOpenGLPFAColorFloat as u32);
|
attributes.push(NSOpenGLPFAColorFloat as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ use GlContext;
|
||||||
use GlRequest;
|
use GlRequest;
|
||||||
use PixelFormat;
|
use PixelFormat;
|
||||||
use PixelFormatRequirements;
|
use PixelFormatRequirements;
|
||||||
|
use ReleaseBehavior;
|
||||||
use Robustness;
|
use Robustness;
|
||||||
use Api;
|
use Api;
|
||||||
|
|
||||||
|
@ -247,8 +248,9 @@ impl Context {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let configs = unsafe { try!(enumerate_configs(&egl, display, &egl_version, api, version)) };
|
let (config_id, pixel_format) = unsafe {
|
||||||
let (config_id, pixel_format) = try!(pf_reqs.choose_pixel_format(configs.into_iter()));
|
try!(choose_fbconfig(&egl, display, &egl_version, api, version, pf_reqs))
|
||||||
|
};
|
||||||
|
|
||||||
Ok(ContextPrototype {
|
Ok(ContextPrototype {
|
||||||
opengl: opengl,
|
opengl: opengl,
|
||||||
|
@ -451,108 +453,162 @@ impl<'a> ContextPrototype<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn enumerate_configs(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDisplay,
|
unsafe fn choose_fbconfig(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDisplay,
|
||||||
egl_version: &(ffi::egl::types::EGLint, ffi::egl::types::EGLint),
|
egl_version: &(ffi::egl::types::EGLint, ffi::egl::types::EGLint),
|
||||||
api: Api, version: Option<(u8, u8)>)
|
api: Api, version: Option<(u8, u8)>, reqs: &PixelFormatRequirements)
|
||||||
-> Result<Vec<(ffi::egl::types::EGLConfig, PixelFormat)>, CreationError>
|
-> Result<(ffi::egl::types::EGLConfig, PixelFormat), CreationError>
|
||||||
{
|
{
|
||||||
let mut num_configs = mem::uninitialized();
|
let descriptor = {
|
||||||
if egl.GetConfigs(display, ptr::null_mut(), 0, &mut num_configs) == 0 {
|
let mut out: Vec<c_int> = Vec::with_capacity(37);
|
||||||
return Err(CreationError::OsError(format!("eglGetConfigs failed")));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut configs_ids = Vec::with_capacity(num_configs as usize);
|
if egl_version >= &(1, 2) {
|
||||||
if egl.GetConfigs(display, configs_ids.as_mut_ptr(),
|
out.push(ffi::egl::COLOR_BUFFER_TYPE as c_int);
|
||||||
configs_ids.capacity() as ffi::egl::types::EGLint,
|
out.push(ffi::egl::RGB_BUFFER as c_int);
|
||||||
&mut num_configs) == 0
|
}
|
||||||
{
|
|
||||||
return Err(CreationError::OsError(format!("eglGetConfigs failed")));
|
|
||||||
}
|
|
||||||
configs_ids.set_len(num_configs as usize);
|
|
||||||
|
|
||||||
// analyzing each config
|
if egl_version >= &(1, 3) {
|
||||||
let mut result = Vec::with_capacity(num_configs as usize);
|
out.push(ffi::egl::SURFACE_TYPE as c_int);
|
||||||
for config_id in configs_ids {
|
out.push((ffi::egl::WINDOW_BIT | ffi::egl::PBUFFER_BIT) as c_int);
|
||||||
macro_rules! attrib {
|
}
|
||||||
($egl:expr, $display:expr, $config:expr, $attr:expr) => (
|
|
||||||
{
|
match (api, version) {
|
||||||
let mut value = mem::uninitialized();
|
(Api::OpenGlEs, Some((3, _))) => {
|
||||||
let res = $egl.GetConfigAttrib($display, $config,
|
if egl_version < &(1, 3) { return Err(CreationError::NoAvailablePixelFormat); }
|
||||||
$attr as ffi::egl::types::EGLint, &mut value);
|
out.push(ffi::egl::RENDERABLE_TYPE as c_int);
|
||||||
if res == 0 {
|
out.push(ffi::egl::OPENGL_ES3_BIT as c_int);
|
||||||
return Err(CreationError::OsError(format!("eglGetConfigAttrib failed")));
|
out.push(ffi::egl::CONFORMANT as c_int);
|
||||||
}
|
out.push(ffi::egl::OPENGL_ES3_BIT as c_int);
|
||||||
value
|
},
|
||||||
|
(Api::OpenGlEs, Some((2, _))) => {
|
||||||
|
if egl_version < &(1, 3) { return Err(CreationError::NoAvailablePixelFormat); }
|
||||||
|
out.push(ffi::egl::RENDERABLE_TYPE as c_int);
|
||||||
|
out.push(ffi::egl::OPENGL_ES2_BIT as c_int);
|
||||||
|
out.push(ffi::egl::CONFORMANT as c_int);
|
||||||
|
out.push(ffi::egl::OPENGL_ES2_BIT as c_int);
|
||||||
|
},
|
||||||
|
(Api::OpenGlEs, Some((1, _))) => {
|
||||||
|
if egl_version >= &(1, 3) {
|
||||||
|
out.push(ffi::egl::RENDERABLE_TYPE as c_int);
|
||||||
|
out.push(ffi::egl::OPENGL_ES_BIT as c_int);
|
||||||
|
out.push(ffi::egl::CONFORMANT as c_int);
|
||||||
|
out.push(ffi::egl::OPENGL_ES_BIT as c_int);
|
||||||
}
|
}
|
||||||
)
|
},
|
||||||
|
(Api::OpenGlEs, _) => unimplemented!(),
|
||||||
|
(Api::OpenGl, Some((1, _))) => {
|
||||||
|
if egl_version < &(1, 3) { return Err(CreationError::NoAvailablePixelFormat); }
|
||||||
|
out.push(ffi::egl::RENDERABLE_TYPE as c_int);
|
||||||
|
out.push(ffi::egl::OPENGL_BIT as c_int);
|
||||||
|
out.push(ffi::egl::CONFORMANT as c_int);
|
||||||
|
out.push(ffi::egl::OPENGL_BIT as c_int);
|
||||||
|
},
|
||||||
|
(_, _) => unimplemented!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let renderable = attrib!(egl, display, config_id, ffi::egl::RENDERABLE_TYPE) as u32;
|
if let Some(hardware_accelerated) = reqs.hardware_accelerated {
|
||||||
let conformant = attrib!(egl, display, config_id, ffi::egl::CONFORMANT) as u32;
|
out.push(ffi::egl::CONFIG_CAVEAT as c_int);
|
||||||
|
out.push(if hardware_accelerated {
|
||||||
if api == Api::OpenGlEs {
|
ffi::egl::NONE as c_int
|
||||||
if let Some(version) = version {
|
} else {
|
||||||
if version.0 == 3 && (renderable & ffi::egl::OPENGL_ES3_BIT == 0 ||
|
ffi::egl::SLOW_CONFIG as c_int
|
||||||
conformant & ffi::egl::OPENGL_ES3_BIT == 0)
|
});
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if version.0 == 2 && (renderable & ffi::egl::OPENGL_ES2_BIT == 0 ||
|
|
||||||
conformant & ffi::egl::OPENGL_ES2_BIT == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if version.0 == 1 && (renderable & ffi::egl::OPENGL_ES_BIT == 0 ||
|
|
||||||
conformant & ffi::egl::OPENGL_ES_BIT == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if api == Api::OpenGl {
|
|
||||||
if renderable & ffi::egl::OPENGL_BIT == 0 ||
|
|
||||||
conformant & ffi::egl::OPENGL_BIT == 0
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if attrib!(egl, display, config_id, ffi::egl::SURFACE_TYPE) &
|
if let Some(color) = reqs.color_bits {
|
||||||
(ffi::egl::WINDOW_BIT | ffi::egl::PBUFFER_BIT) as i32 == 0
|
out.push(ffi::egl::RED_SIZE as c_int);
|
||||||
{
|
out.push((color / 3) as c_int);
|
||||||
continue;
|
out.push(ffi::egl::GREEN_SIZE as c_int);
|
||||||
|
out.push((color / 3 + if color % 3 != 0 { 1 } else { 0 }) as c_int);
|
||||||
|
out.push(ffi::egl::BLUE_SIZE as c_int);
|
||||||
|
out.push((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
if attrib!(egl, display, config_id, ffi::egl::TRANSPARENT_TYPE) != ffi::egl::NONE as i32 {
|
if let Some(alpha) = reqs.alpha_bits {
|
||||||
continue;
|
out.push(ffi::egl::ALPHA_SIZE as c_int);
|
||||||
|
out.push(alpha as c_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
if attrib!(egl, display, config_id, ffi::egl::COLOR_BUFFER_TYPE) != ffi::egl::RGB_BUFFER as i32 {
|
if let Some(depth) = reqs.depth_bits {
|
||||||
continue;
|
out.push(ffi::egl::DEPTH_SIZE as c_int);
|
||||||
|
out.push(depth as c_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push((config_id, PixelFormat {
|
if let Some(stencil) = reqs.stencil_bits {
|
||||||
hardware_accelerated: attrib!(egl, display, config_id, ffi::egl::CONFIG_CAVEAT)
|
out.push(ffi::egl::STENCIL_SIZE as c_int);
|
||||||
!= ffi::egl::SLOW_CONFIG as i32,
|
out.push(stencil as c_int);
|
||||||
color_bits: attrib!(egl, display, config_id, ffi::egl::RED_SIZE) as u8 +
|
}
|
||||||
attrib!(egl, display, config_id, ffi::egl::BLUE_SIZE) as u8 +
|
|
||||||
attrib!(egl, display, config_id, ffi::egl::GREEN_SIZE) as u8,
|
if let Some(true) = reqs.double_buffer {
|
||||||
alpha_bits: attrib!(egl, display, config_id, ffi::egl::ALPHA_SIZE) as u8,
|
return Err(CreationError::NoAvailablePixelFormat);
|
||||||
depth_bits: attrib!(egl, display, config_id, ffi::egl::DEPTH_SIZE) as u8,
|
}
|
||||||
stencil_bits: attrib!(egl, display, config_id, ffi::egl::STENCIL_SIZE) as u8,
|
|
||||||
stereoscopy: false,
|
if let Some(multisampling) = reqs.multisampling {
|
||||||
double_buffer: true,
|
out.push(ffi::egl::SAMPLES as c_int);
|
||||||
multisampling: match attrib!(egl, display, config_id, ffi::egl::SAMPLES) {
|
out.push(multisampling as c_int);
|
||||||
0 | 1 => None,
|
}
|
||||||
a => Some(a as u16),
|
|
||||||
|
if reqs.stereoscopy {
|
||||||
|
return Err(CreationError::NoAvailablePixelFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: srgb is not taken into account
|
||||||
|
|
||||||
|
match reqs.release_behavior {
|
||||||
|
ReleaseBehavior::Flush => (),
|
||||||
|
ReleaseBehavior::None => {
|
||||||
|
// TODO: with EGL you need to manually set the behavior
|
||||||
|
unimplemented!()
|
||||||
},
|
},
|
||||||
srgb: false, // TODO: use EGL_KHR_gl_colorspace to know that
|
}
|
||||||
}));
|
|
||||||
|
out.push(0);
|
||||||
|
out
|
||||||
|
};
|
||||||
|
|
||||||
|
// calling `eglChooseConfig`
|
||||||
|
let mut config_id = mem::uninitialized();
|
||||||
|
let mut num_configs = mem::uninitialized();
|
||||||
|
if egl.ChooseConfig(display, descriptor.as_ptr(), &mut config_id, 1, &mut num_configs) == 0 {
|
||||||
|
return Err(CreationError::OsError(format!("eglChooseConfig failed")));
|
||||||
|
}
|
||||||
|
if num_configs == 0 {
|
||||||
|
return Err(CreationError::NoAvailablePixelFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result)
|
// analyzing each config
|
||||||
|
macro_rules! attrib {
|
||||||
|
($egl:expr, $display:expr, $config:expr, $attr:expr) => (
|
||||||
|
{
|
||||||
|
let mut value = mem::uninitialized();
|
||||||
|
let res = $egl.GetConfigAttrib($display, $config,
|
||||||
|
$attr as ffi::egl::types::EGLint, &mut value);
|
||||||
|
if res == 0 {
|
||||||
|
return Err(CreationError::OsError(format!("eglGetConfigAttrib failed")));
|
||||||
|
}
|
||||||
|
value
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let desc = PixelFormat {
|
||||||
|
hardware_accelerated: attrib!(egl, display, config_id, ffi::egl::CONFIG_CAVEAT)
|
||||||
|
!= ffi::egl::SLOW_CONFIG as i32,
|
||||||
|
color_bits: attrib!(egl, display, config_id, ffi::egl::RED_SIZE) as u8 +
|
||||||
|
attrib!(egl, display, config_id, ffi::egl::BLUE_SIZE) as u8 +
|
||||||
|
attrib!(egl, display, config_id, ffi::egl::GREEN_SIZE) as u8,
|
||||||
|
alpha_bits: attrib!(egl, display, config_id, ffi::egl::ALPHA_SIZE) as u8,
|
||||||
|
depth_bits: attrib!(egl, display, config_id, ffi::egl::DEPTH_SIZE) as u8,
|
||||||
|
stencil_bits: attrib!(egl, display, config_id, ffi::egl::STENCIL_SIZE) as u8,
|
||||||
|
stereoscopy: false,
|
||||||
|
double_buffer: true,
|
||||||
|
multisampling: match attrib!(egl, display, config_id, ffi::egl::SAMPLES) {
|
||||||
|
0 | 1 => None,
|
||||||
|
a => Some(a as u16),
|
||||||
|
},
|
||||||
|
srgb: false, // TODO: use EGL_KHR_gl_colorspace to know that
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((config_id, desc))
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_context(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDisplay,
|
unsafe fn create_context(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDisplay,
|
||||||
|
|
|
@ -9,9 +9,11 @@ use GlRequest;
|
||||||
use Api;
|
use Api;
|
||||||
use PixelFormat;
|
use PixelFormat;
|
||||||
use PixelFormatRequirements;
|
use PixelFormatRequirements;
|
||||||
|
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};
|
||||||
|
|
||||||
|
@ -39,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
|
||||||
|
@ -58,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,
|
||||||
|
@ -125,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,
|
||||||
|
@ -144,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| {
|
||||||
|
@ -161,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,
|
||||||
|
@ -176,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))
|
||||||
|
@ -263,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 {
|
||||||
|
@ -276,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 = {
|
||||||
|
@ -287,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 => (),
|
||||||
|
@ -309,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);
|
||||||
|
@ -338,78 +342,145 @@ 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 configs: Vec<ffi::glx::types::GLXFBConfig> = {
|
let descriptor = {
|
||||||
let mut num_configs = 0;
|
let mut out: Vec<c_int> = Vec::with_capacity(37);
|
||||||
let vals = glx.GetFBConfigs(display as *mut _, 0, &mut num_configs); // TODO: screen number
|
|
||||||
assert!(!vals.is_null());
|
out.push(ffi::glx::X_RENDERABLE as c_int);
|
||||||
let configs = slice::from_raw_parts(vals, num_configs as usize);
|
out.push(1);
|
||||||
let ret = configs.to_vec();
|
|
||||||
(xlib.XFree)(vals as *mut _);
|
out.push(ffi::glx::X_VISUAL_TYPE as c_int);
|
||||||
ret
|
out.push(ffi::glx::TRUE_COLOR as c_int);
|
||||||
|
|
||||||
|
out.push(ffi::glx::DRAWABLE_TYPE as c_int);
|
||||||
|
out.push(ffi::glx::WINDOW_BIT as c_int);
|
||||||
|
|
||||||
|
out.push(ffi::glx::RENDER_TYPE as c_int);
|
||||||
|
if reqs.float_color_buffer {
|
||||||
|
if extensions.split(' ').find(|&i| i == "GLX_ARB_fbconfig_float").is_some() {
|
||||||
|
out.push(ffi::glx_extra::RGBA_FLOAT_BIT_ARB as c_int);
|
||||||
|
} else {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.push(ffi::glx::RGBA_BIT as c_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(hardware_accelerated) = reqs.hardware_accelerated {
|
||||||
|
out.push(ffi::glx::CONFIG_CAVEAT as c_int);
|
||||||
|
out.push(if hardware_accelerated {
|
||||||
|
ffi::glx::NONE as c_int
|
||||||
|
} else {
|
||||||
|
ffi::glx::SLOW_CONFIG as c_int
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(color) = reqs.color_bits {
|
||||||
|
out.push(ffi::glx::RED_SIZE as c_int);
|
||||||
|
out.push((color / 3) as c_int);
|
||||||
|
out.push(ffi::glx::GREEN_SIZE as c_int);
|
||||||
|
out.push((color / 3 + if color % 3 != 0 { 1 } else { 0 }) as c_int);
|
||||||
|
out.push(ffi::glx::BLUE_SIZE as c_int);
|
||||||
|
out.push((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(alpha) = reqs.alpha_bits {
|
||||||
|
out.push(ffi::glx::ALPHA_SIZE as c_int);
|
||||||
|
out.push(alpha as c_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(depth) = reqs.depth_bits {
|
||||||
|
out.push(ffi::glx::DEPTH_SIZE as c_int);
|
||||||
|
out.push(depth as c_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(stencil) = reqs.stencil_bits {
|
||||||
|
out.push(ffi::glx::STENCIL_SIZE as c_int);
|
||||||
|
out.push(stencil as c_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(double_buffer) = reqs.double_buffer {
|
||||||
|
out.push(ffi::glx::DOUBLEBUFFER as c_int);
|
||||||
|
out.push(if double_buffer { 1 } else { 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(multisampling) = reqs.multisampling {
|
||||||
|
if extensions.split(' ').find(|&i| i == "GLX_ARB_multisample").is_some() {
|
||||||
|
out.push(ffi::glx_extra::SAMPLE_BUFFERS_ARB as c_int);
|
||||||
|
out.push(if multisampling == 0 { 0 } else { 1 });
|
||||||
|
out.push(ffi::glx_extra::SAMPLES_ARB as c_int);
|
||||||
|
out.push(multisampling as c_int);
|
||||||
|
} else {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push(ffi::glx::STEREO as c_int);
|
||||||
|
out.push(if reqs.stereoscopy { 1 } else { 0 });
|
||||||
|
|
||||||
|
if reqs.srgb {
|
||||||
|
if extensions.split(' ').find(|&i| i == "GLX_ARB_framebuffer_sRGB").is_some() {
|
||||||
|
out.push(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as c_int);
|
||||||
|
out.push(1);
|
||||||
|
} else {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match reqs.release_behavior {
|
||||||
|
ReleaseBehavior::Flush => (),
|
||||||
|
ReleaseBehavior::None => {
|
||||||
|
if extensions.split(' ').find(|&i| i == "GLX_ARB_context_flush_control").is_some() {
|
||||||
|
out.push(ffi::glx_extra::CONTEXT_RELEASE_BEHAVIOR_ARB as c_int);
|
||||||
|
out.push(ffi::glx_extra::CONTEXT_RELEASE_BEHAVIOR_NONE_ARB as c_int);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push(0);
|
||||||
|
out
|
||||||
};
|
};
|
||||||
|
|
||||||
let get_attrib = |attrib: libc::c_int, fb_config: ffi::glx::types::GLXFBConfig| -> i32 {
|
// calling glXChooseFBConfig
|
||||||
|
let fb_config = {
|
||||||
|
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 num_configs == 0 { return Err(()); }
|
||||||
|
let val = *result;
|
||||||
|
(xlib.XFree)(result as *mut _);
|
||||||
|
val
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
value
|
value
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(configs.into_iter().filter_map(|config| {
|
let pf_desc = PixelFormat {
|
||||||
if get_attrib(ffi::glx::X_RENDERABLE as libc::c_int, config) == 0 {
|
hardware_accelerated: get_attrib(ffi::glx::CONFIG_CAVEAT as c_int) !=
|
||||||
return None;
|
ffi::glx::SLOW_CONFIG as c_int,
|
||||||
}
|
color_bits: get_attrib(ffi::glx::RED_SIZE as c_int) as u8 +
|
||||||
|
get_attrib(ffi::glx::GREEN_SIZE as c_int) as u8 +
|
||||||
|
get_attrib(ffi::glx::BLUE_SIZE as c_int) as u8,
|
||||||
|
alpha_bits: get_attrib(ffi::glx::ALPHA_SIZE as c_int) as u8,
|
||||||
|
depth_bits: get_attrib(ffi::glx::DEPTH_SIZE as c_int) as u8,
|
||||||
|
stencil_bits: get_attrib(ffi::glx::STENCIL_SIZE as c_int) as u8,
|
||||||
|
stereoscopy: get_attrib(ffi::glx::STEREO as c_int) != 0,
|
||||||
|
double_buffer: get_attrib(ffi::glx::DOUBLEBUFFER as c_int) != 0,
|
||||||
|
multisampling: if get_attrib(ffi::glx::SAMPLE_BUFFERS as c_int) != 0 {
|
||||||
|
Some(get_attrib(ffi::glx::SAMPLES as c_int) as u16)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
srgb: get_attrib(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as c_int) != 0,
|
||||||
|
};
|
||||||
|
|
||||||
if get_attrib(ffi::glx::X_VISUAL_TYPE as libc::c_int, config) !=
|
Ok((fb_config, pf_desc))
|
||||||
ffi::glx::TRUE_COLOR as libc::c_int
|
|
||||||
{
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if get_attrib(ffi::glx::DRAWABLE_TYPE as libc::c_int, config) &
|
|
||||||
ffi::glx::WINDOW_BIT as libc::c_int == 0
|
|
||||||
{
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if get_attrib(ffi::glx::VISUAL_ID as libc::c_int, config) == 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if get_attrib(ffi::glx::RENDER_TYPE as libc::c_int, config) &
|
|
||||||
ffi::glx::RGBA_BIT as libc::c_int == 0
|
|
||||||
{
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add a flag to PixelFormat for non-conformant configs
|
|
||||||
let caveat = get_attrib(ffi::glx::CONFIG_CAVEAT as libc::c_int, config);
|
|
||||||
/*if caveat == ffi::glx::NON_CONFORMANT_CONFIG as libc::c_int {
|
|
||||||
return None;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// TODO: make sure everything is supported
|
|
||||||
let pf = PixelFormat {
|
|
||||||
hardware_accelerated: caveat != ffi::glx::SLOW_CONFIG as libc::c_int,
|
|
||||||
color_bits: get_attrib(ffi::glx::RED_SIZE as libc::c_int, config) as u8 +
|
|
||||||
get_attrib(ffi::glx::GREEN_SIZE as libc::c_int, config) as u8 +
|
|
||||||
get_attrib(ffi::glx::BLUE_SIZE as libc::c_int, config) as u8,
|
|
||||||
alpha_bits: get_attrib(ffi::glx::ALPHA_SIZE as libc::c_int, config) as u8,
|
|
||||||
depth_bits: get_attrib(ffi::glx::DEPTH_SIZE as libc::c_int, config) as u8,
|
|
||||||
stencil_bits: get_attrib(ffi::glx::STENCIL_SIZE as libc::c_int, config) as u8,
|
|
||||||
stereoscopy: get_attrib(ffi::glx::STEREO as libc::c_int, config) != 0,
|
|
||||||
double_buffer: get_attrib(ffi::glx::DOUBLEBUFFER as libc::c_int, config) != 0,
|
|
||||||
multisampling: if get_attrib(ffi::glx::SAMPLE_BUFFERS as libc::c_int, config) != 0 {
|
|
||||||
Some(get_attrib(ffi::glx::SAMPLES as libc::c_int, config) as u16)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
srgb: get_attrib(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as libc::c_int, config) != 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
Some((config, pf))
|
|
||||||
}).collect())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ use GlRequest;
|
||||||
use GlProfile;
|
use GlProfile;
|
||||||
use PixelFormat;
|
use PixelFormat;
|
||||||
use PixelFormatRequirements;
|
use PixelFormatRequirements;
|
||||||
|
use ReleaseBehavior;
|
||||||
use Robustness;
|
use Robustness;
|
||||||
use Api;
|
use Api;
|
||||||
|
|
||||||
|
@ -107,20 +108,16 @@ impl Context {
|
||||||
|
|
||||||
// calling SetPixelFormat
|
// calling SetPixelFormat
|
||||||
let pixel_format = {
|
let pixel_format = {
|
||||||
let formats = if extensions.split(' ').find(|&i| i == "WGL_ARB_pixel_format")
|
let (id, f) = if extensions.split(' ').find(|&i| i == "WGL_ARB_pixel_format")
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
let f = enumerate_arb_pixel_formats(&extra_functions, &extensions, hdc);
|
try!(choose_arb_pixel_format(&extra_functions, &extensions, hdc, pf_reqs)
|
||||||
if f.is_empty() {
|
.map_err(|_| CreationError::NoAvailablePixelFormat))
|
||||||
enumerate_native_pixel_formats(hdc)
|
|
||||||
} else {
|
|
||||||
f
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
enumerate_native_pixel_formats(hdc)
|
try!(choose_native_pixel_format(hdc, pf_reqs)
|
||||||
|
.map_err(|_| CreationError::NoAvailablePixelFormat))
|
||||||
};
|
};
|
||||||
|
|
||||||
let (id, f) = try!(pf_reqs.choose_pixel_format(formats));
|
|
||||||
try!(set_pixel_format(hdc, id));
|
try!(set_pixel_format(hdc, id));
|
||||||
f
|
f
|
||||||
};
|
};
|
||||||
|
@ -349,117 +346,297 @@ unsafe fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &PixelFormatRequire
|
||||||
Ok(ContextWrapper(ctxt as winapi::HGLRC))
|
Ok(ContextWrapper(ctxt as winapi::HGLRC))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enumerates the list of pixel formats without using WGL.
|
/// Chooses a pixel formats without using WGL.
|
||||||
///
|
///
|
||||||
/// Gives less precise results than `enumerate_arb_pixel_formats`.
|
/// Gives less precise results than `enumerate_arb_pixel_formats`.
|
||||||
unsafe fn enumerate_native_pixel_formats(hdc: winapi::HDC) -> Vec<(c_int, PixelFormat)> {
|
unsafe fn choose_native_pixel_format(hdc: winapi::HDC, reqs: &PixelFormatRequirements)
|
||||||
let size_of_pxfmtdescr = mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>() as u32;
|
-> Result<(c_int, PixelFormat), ()>
|
||||||
let num = gdi32::DescribePixelFormat(hdc, 1, size_of_pxfmtdescr, ptr::null_mut());
|
{
|
||||||
|
// TODO: hardware acceleration is not handled
|
||||||
|
|
||||||
let mut result = Vec::new();
|
// handling non-supported stuff
|
||||||
|
if reqs.float_color_buffer {
|
||||||
for index in (0 .. num) {
|
return Err(());
|
||||||
let mut output: winapi::PIXELFORMATDESCRIPTOR = mem::zeroed();
|
|
||||||
|
|
||||||
if gdi32::DescribePixelFormat(hdc, index, size_of_pxfmtdescr, &mut output) == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output.dwFlags & winapi::PFD_DRAW_TO_WINDOW) == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output.dwFlags & winapi::PFD_SUPPORT_OPENGL) == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if output.iPixelType != winapi::PFD_TYPE_RGBA {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.push((index, PixelFormat {
|
|
||||||
hardware_accelerated: (output.dwFlags & winapi::PFD_GENERIC_FORMAT) == 0,
|
|
||||||
color_bits: output.cRedBits + output.cGreenBits + output.cBlueBits,
|
|
||||||
alpha_bits: output.cAlphaBits,
|
|
||||||
depth_bits: output.cDepthBits,
|
|
||||||
stencil_bits: output.cStencilBits,
|
|
||||||
stereoscopy: (output.dwFlags & winapi::PFD_STEREO) != 0,
|
|
||||||
double_buffer: (output.dwFlags & winapi::PFD_DOUBLEBUFFER) != 0,
|
|
||||||
multisampling: None,
|
|
||||||
srgb: false,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
match reqs.multisampling {
|
||||||
|
Some(0) => (),
|
||||||
|
None => (),
|
||||||
|
Some(_) => return Err(())
|
||||||
|
};
|
||||||
|
|
||||||
|
if reqs.stereoscopy {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if reqs.srgb {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if reqs.release_behavior != ReleaseBehavior::Flush {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// building the descriptor to pass to ChoosePixelFormat
|
||||||
|
let descriptor = winapi::PIXELFORMATDESCRIPTOR {
|
||||||
|
nSize: mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>() as u16,
|
||||||
|
nVersion: 1,
|
||||||
|
dwFlags: {
|
||||||
|
let f1 = match reqs.double_buffer {
|
||||||
|
None => winapi::PFD_DOUBLEBUFFER_DONTCARE,
|
||||||
|
Some(true) => winapi::PFD_DOUBLEBUFFER,
|
||||||
|
Some(false) => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let f2 = if reqs.stereoscopy {
|
||||||
|
winapi::PFD_STEREO
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
winapi::PFD_DRAW_TO_WINDOW | winapi::PFD_SUPPORT_OPENGL | f1 | f2
|
||||||
|
},
|
||||||
|
iPixelType: winapi::PFD_TYPE_RGBA,
|
||||||
|
cColorBits: reqs.color_bits.unwrap_or(0),
|
||||||
|
cRedBits: 0,
|
||||||
|
cRedShift: 0,
|
||||||
|
cGreenBits: 0,
|
||||||
|
cGreenShift: 0,
|
||||||
|
cBlueBits: 0,
|
||||||
|
cBlueShift: 0,
|
||||||
|
cAlphaBits: reqs.alpha_bits.unwrap_or(0),
|
||||||
|
cAlphaShift: 0,
|
||||||
|
cAccumBits: 0,
|
||||||
|
cAccumRedBits: 0,
|
||||||
|
cAccumGreenBits: 0,
|
||||||
|
cAccumBlueBits: 0,
|
||||||
|
cAccumAlphaBits: 0,
|
||||||
|
cDepthBits: reqs.depth_bits.unwrap_or(0),
|
||||||
|
cStencilBits: reqs.stencil_bits.unwrap_or(0),
|
||||||
|
cAuxBuffers: 0,
|
||||||
|
iLayerType: winapi::PFD_MAIN_PLANE,
|
||||||
|
bReserved: 0,
|
||||||
|
dwLayerMask: 0,
|
||||||
|
dwVisibleMask: 0,
|
||||||
|
dwDamageMask: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// now querying
|
||||||
|
let pf_id = gdi32::ChoosePixelFormat(hdc, &descriptor);
|
||||||
|
if pf_id == 0 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// querying back the capabilities of what windows told us
|
||||||
|
let mut output: winapi::PIXELFORMATDESCRIPTOR = mem::zeroed();
|
||||||
|
if gdi32::DescribePixelFormat(hdc, pf_id, mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>() as u32,
|
||||||
|
&mut output) == 0
|
||||||
|
{
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// windows may return us a non-conforming pixel format if none are supported, so we have to
|
||||||
|
// check this
|
||||||
|
if (output.dwFlags & winapi::PFD_DRAW_TO_WINDOW) == 0 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
if (output.dwFlags & winapi::PFD_SUPPORT_OPENGL) == 0 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
if output.iPixelType != winapi::PFD_TYPE_RGBA {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let pf_desc = PixelFormat {
|
||||||
|
hardware_accelerated: (output.dwFlags & winapi::PFD_GENERIC_FORMAT) == 0,
|
||||||
|
color_bits: output.cRedBits + output.cGreenBits + output.cBlueBits,
|
||||||
|
alpha_bits: output.cAlphaBits,
|
||||||
|
depth_bits: output.cDepthBits,
|
||||||
|
stencil_bits: output.cStencilBits,
|
||||||
|
stereoscopy: (output.dwFlags & winapi::PFD_STEREO) != 0,
|
||||||
|
double_buffer: (output.dwFlags & winapi::PFD_DOUBLEBUFFER) != 0,
|
||||||
|
multisampling: None,
|
||||||
|
srgb: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if pf_desc.alpha_bits < reqs.alpha_bits.unwrap_or(0) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
if pf_desc.depth_bits < reqs.depth_bits.unwrap_or(0) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
if pf_desc.stencil_bits < reqs.stencil_bits.unwrap_or(0) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
if pf_desc.color_bits < reqs.color_bits.unwrap_or(0) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
if let Some(req) = reqs.hardware_accelerated {
|
||||||
|
if pf_desc.hardware_accelerated != req {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(req) = reqs.double_buffer {
|
||||||
|
if pf_desc.double_buffer != req {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((pf_id, pf_desc))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enumerates the list of pixel formats by using extra WGL functions.
|
/// Enumerates the list of pixel formats by using extra WGL functions.
|
||||||
///
|
///
|
||||||
/// Gives more precise results than `enumerate_native_pixel_formats`.
|
/// Gives more precise results than `enumerate_native_pixel_formats`.
|
||||||
unsafe fn enumerate_arb_pixel_formats(extra: &gl::wgl_extra::Wgl, extensions: &str,
|
unsafe fn choose_arb_pixel_format(extra: &gl::wgl_extra::Wgl, extensions: &str,
|
||||||
hdc: winapi::HDC) -> Vec<(c_int, PixelFormat)>
|
hdc: winapi::HDC, reqs: &PixelFormatRequirements)
|
||||||
|
-> Result<(c_int, PixelFormat), ()>
|
||||||
{
|
{
|
||||||
let get_info = |index: u32, attrib: u32| {
|
let descriptor = {
|
||||||
|
let mut out: Vec<c_int> = Vec::with_capacity(37);
|
||||||
|
|
||||||
|
out.push(gl::wgl_extra::DRAW_TO_WINDOW_ARB as c_int);
|
||||||
|
out.push(1);
|
||||||
|
|
||||||
|
out.push(gl::wgl_extra::SUPPORT_OPENGL_ARB as c_int);
|
||||||
|
out.push(1);
|
||||||
|
|
||||||
|
out.push(gl::wgl_extra::PIXEL_TYPE_ARB as c_int);
|
||||||
|
if reqs.float_color_buffer {
|
||||||
|
if extensions.split(' ').find(|&i| i == "WGL_ARB_pixel_format_float").is_some() {
|
||||||
|
out.push(gl::wgl_extra::TYPE_RGBA_FLOAT_ARB as c_int);
|
||||||
|
} else {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.push(gl::wgl_extra::TYPE_RGBA_ARB as c_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(hardware_accelerated) = reqs.hardware_accelerated {
|
||||||
|
out.push(gl::wgl_extra::ACCELERATION_ARB as c_int);
|
||||||
|
out.push(if hardware_accelerated {
|
||||||
|
gl::wgl_extra::FULL_ACCELERATION_ARB as c_int
|
||||||
|
} else {
|
||||||
|
gl::wgl_extra::NO_ACCELERATION_ARB as c_int
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(color) = reqs.color_bits {
|
||||||
|
out.push(gl::wgl_extra::COLOR_BITS_ARB as c_int);
|
||||||
|
out.push(color as c_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(alpha) = reqs.alpha_bits {
|
||||||
|
out.push(gl::wgl_extra::ALPHA_BITS_ARB as c_int);
|
||||||
|
out.push(alpha as c_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(depth) = reqs.depth_bits {
|
||||||
|
out.push(gl::wgl_extra::DEPTH_BITS_ARB as c_int);
|
||||||
|
out.push(depth as c_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(stencil) = reqs.stencil_bits {
|
||||||
|
out.push(gl::wgl_extra::STENCIL_BITS_ARB as c_int);
|
||||||
|
out.push(stencil as c_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(double_buffer) = reqs.double_buffer {
|
||||||
|
out.push(gl::wgl_extra::DOUBLE_BUFFER_ARB as c_int);
|
||||||
|
out.push(if double_buffer { 1 } else { 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(multisampling) = reqs.multisampling {
|
||||||
|
if extensions.split(' ').find(|&i| i == "WGL_ARB_multisample").is_some() {
|
||||||
|
out.push(gl::wgl_extra::SAMPLE_BUFFERS_ARB as c_int);
|
||||||
|
out.push(if multisampling == 0 { 0 } else { 1 });
|
||||||
|
out.push(gl::wgl_extra::SAMPLES_ARB as c_int);
|
||||||
|
out.push(multisampling as c_int);
|
||||||
|
} else {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push(gl::wgl_extra::STEREO_ARB as c_int);
|
||||||
|
out.push(if reqs.stereoscopy { 1 } else { 0 });
|
||||||
|
|
||||||
|
if reqs.srgb {
|
||||||
|
if extensions.split(' ').find(|&i| i == "WGL_ARB_framebuffer_sRGB").is_some() {
|
||||||
|
out.push(gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as c_int);
|
||||||
|
out.push(1);
|
||||||
|
} else if extensions.split(' ').find(|&i| i == "WGL_EXT_framebuffer_sRGB").is_some() {
|
||||||
|
out.push(gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT as c_int);
|
||||||
|
out.push(1);
|
||||||
|
} else {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match reqs.release_behavior {
|
||||||
|
ReleaseBehavior::Flush => (),
|
||||||
|
ReleaseBehavior::None => {
|
||||||
|
if extensions.split(' ').find(|&i| i == "WGL_ARB_context_flush_control").is_some() {
|
||||||
|
out.push(gl::wgl_extra::CONTEXT_RELEASE_BEHAVIOR_ARB as c_int);
|
||||||
|
out.push(gl::wgl_extra::CONTEXT_RELEASE_BEHAVIOR_NONE_ARB as c_int);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push(0);
|
||||||
|
out
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut format_id = mem::uninitialized();
|
||||||
|
let mut num_formats = mem::uninitialized();
|
||||||
|
if extra.ChoosePixelFormatARB(hdc as *const _, descriptor.as_ptr(), ptr::null(), 1,
|
||||||
|
&mut format_id, &mut num_formats) == 0
|
||||||
|
{
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if num_formats == 0 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let get_info = |attrib: u32| {
|
||||||
let mut value = mem::uninitialized();
|
let mut value = mem::uninitialized();
|
||||||
extra.GetPixelFormatAttribivARB(hdc as *const _, index as c_int,
|
extra.GetPixelFormatAttribivARB(hdc as *const _, format_id as c_int,
|
||||||
0, 1, [attrib as c_int].as_ptr(),
|
0, 1, [attrib as c_int].as_ptr(),
|
||||||
&mut value);
|
&mut value);
|
||||||
value as u32
|
value as u32
|
||||||
};
|
};
|
||||||
|
|
||||||
// getting the number of formats
|
let pf_desc = PixelFormat {
|
||||||
// the `1` is ignored
|
hardware_accelerated: get_info(gl::wgl_extra::ACCELERATION_ARB) !=
|
||||||
let num = get_info(1, gl::wgl_extra::NUMBER_PIXEL_FORMATS_ARB);
|
gl::wgl_extra::NO_ACCELERATION_ARB,
|
||||||
|
color_bits: get_info(gl::wgl_extra::RED_BITS_ARB) as u8 +
|
||||||
let mut result = Vec::new();
|
get_info(gl::wgl_extra::GREEN_BITS_ARB) as u8 +
|
||||||
|
get_info(gl::wgl_extra::BLUE_BITS_ARB) as u8,
|
||||||
for index in (0 .. num) {
|
alpha_bits: get_info(gl::wgl_extra::ALPHA_BITS_ARB) as u8,
|
||||||
if get_info(index, gl::wgl_extra::DRAW_TO_WINDOW_ARB) == 0 {
|
depth_bits: get_info(gl::wgl_extra::DEPTH_BITS_ARB) as u8,
|
||||||
continue;
|
stencil_bits: get_info(gl::wgl_extra::STENCIL_BITS_ARB) as u8,
|
||||||
}
|
stereoscopy: get_info(gl::wgl_extra::STEREO_ARB) != 0,
|
||||||
if get_info(index, gl::wgl_extra::SUPPORT_OPENGL_ARB) == 0 {
|
double_buffer: get_info(gl::wgl_extra::DOUBLE_BUFFER_ARB) != 0,
|
||||||
continue;
|
multisampling: {
|
||||||
}
|
if extensions.split(' ').find(|&i| i == "WGL_ARB_multisample").is_some() {
|
||||||
|
match get_info(gl::wgl_extra::SAMPLES_ARB) {
|
||||||
if get_info(index, gl::wgl_extra::ACCELERATION_ARB) == gl::wgl_extra::NO_ACCELERATION_ARB {
|
0 => None,
|
||||||
continue;
|
a => Some(a as u16),
|
||||||
}
|
|
||||||
|
|
||||||
if get_info(index, gl::wgl_extra::PIXEL_TYPE_ARB) != gl::wgl_extra::TYPE_RGBA_ARB {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.push((index as c_int, PixelFormat {
|
|
||||||
hardware_accelerated: true,
|
|
||||||
color_bits: get_info(index, gl::wgl_extra::RED_BITS_ARB) as u8 +
|
|
||||||
get_info(index, gl::wgl_extra::GREEN_BITS_ARB) as u8 +
|
|
||||||
get_info(index, gl::wgl_extra::BLUE_BITS_ARB) as u8,
|
|
||||||
alpha_bits: get_info(index, gl::wgl_extra::ALPHA_BITS_ARB) as u8,
|
|
||||||
depth_bits: get_info(index, gl::wgl_extra::DEPTH_BITS_ARB) as u8,
|
|
||||||
stencil_bits: get_info(index, gl::wgl_extra::STENCIL_BITS_ARB) as u8,
|
|
||||||
stereoscopy: get_info(index, gl::wgl_extra::STEREO_ARB) != 0,
|
|
||||||
double_buffer: get_info(index, gl::wgl_extra::DOUBLE_BUFFER_ARB) != 0,
|
|
||||||
multisampling: {
|
|
||||||
if extensions.split(' ').find(|&i| i == "WGL_ARB_multisample").is_some() {
|
|
||||||
match get_info(index, gl::wgl_extra::SAMPLES_ARB) {
|
|
||||||
0 => None,
|
|
||||||
a => Some(a as u16),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
srgb: if extensions.split(' ').find(|&i| i == "WGL_ARB_framebuffer_sRGB").is_some() {
|
|
||||||
get_info(index, gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB) != 0
|
|
||||||
} else if extensions.split(' ').find(|&i| i == "WGL_EXT_framebuffer_sRGB").is_some() {
|
|
||||||
get_info(index, gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT) != 0
|
|
||||||
} else {
|
} else {
|
||||||
false
|
None
|
||||||
},
|
}
|
||||||
}));
|
},
|
||||||
}
|
srgb: if extensions.split(' ').find(|&i| i == "WGL_ARB_framebuffer_sRGB").is_some() {
|
||||||
|
get_info(gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB) != 0
|
||||||
|
} else if extensions.split(' ').find(|&i| i == "WGL_EXT_framebuffer_sRGB").is_some() {
|
||||||
|
get_info(gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT) != 0
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
result
|
Ok((format_id, pf_desc))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls `SetPixelFormat` on a window.
|
/// Calls `SetPixelFormat` on a window.
|
||||||
|
@ -550,8 +727,7 @@ unsafe fn load_extra_functions(window: winapi::HWND) -> Result<gl::wgl_extra::Wg
|
||||||
|
|
||||||
// getting the pixel format that we will use and setting it
|
// getting the pixel format that we will use and setting it
|
||||||
{
|
{
|
||||||
let formats = enumerate_native_pixel_formats(dummy_window.1);
|
let id = try!(choose_dummy_pixel_format(dummy_window.1));
|
||||||
let id = try!(choose_dummy_pixel_format(formats.into_iter()));
|
|
||||||
try!(set_pixel_format(dummy_window.1, id));
|
try!(set_pixel_format(dummy_window.1, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,22 +744,44 @@ unsafe fn load_extra_functions(window: winapi::HWND) -> Result<gl::wgl_extra::Wg
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a list of pixel formats, this function chooses one that is likely to be provided by
|
/// This function chooses a pixel format that is likely to be provided by
|
||||||
/// the main video driver of the system.
|
/// the main video driver of the system.
|
||||||
fn choose_dummy_pixel_format<I>(iter: I) -> Result<c_int, CreationError>
|
fn choose_dummy_pixel_format(hdc: winapi::HDC) -> Result<c_int, CreationError> {
|
||||||
where I: Iterator<Item=(c_int, PixelFormat)>
|
// building the descriptor to pass to ChoosePixelFormat
|
||||||
{
|
let descriptor = winapi::PIXELFORMATDESCRIPTOR {
|
||||||
let mut backup_id = None;
|
nSize: mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>() as u16,
|
||||||
|
nVersion: 1,
|
||||||
|
dwFlags: winapi::PFD_DRAW_TO_WINDOW | winapi::PFD_SUPPORT_OPENGL | winapi::PFD_DOUBLEBUFFER,
|
||||||
|
iPixelType: winapi::PFD_TYPE_RGBA,
|
||||||
|
cColorBits: 24,
|
||||||
|
cRedBits: 0,
|
||||||
|
cRedShift: 0,
|
||||||
|
cGreenBits: 0,
|
||||||
|
cGreenShift: 0,
|
||||||
|
cBlueBits: 0,
|
||||||
|
cBlueShift: 0,
|
||||||
|
cAlphaBits: 8,
|
||||||
|
cAlphaShift: 0,
|
||||||
|
cAccumBits: 0,
|
||||||
|
cAccumRedBits: 0,
|
||||||
|
cAccumGreenBits: 0,
|
||||||
|
cAccumBlueBits: 0,
|
||||||
|
cAccumAlphaBits: 0,
|
||||||
|
cDepthBits: 24,
|
||||||
|
cStencilBits: 8,
|
||||||
|
cAuxBuffers: 0,
|
||||||
|
iLayerType: winapi::PFD_MAIN_PLANE,
|
||||||
|
bReserved: 0,
|
||||||
|
dwLayerMask: 0,
|
||||||
|
dwVisibleMask: 0,
|
||||||
|
dwDamageMask: 0,
|
||||||
|
};
|
||||||
|
|
||||||
for (id, format) in iter {
|
// now querying
|
||||||
if backup_id.is_none() {
|
let pf_id = unsafe { gdi32::ChoosePixelFormat(hdc, &descriptor) };
|
||||||
backup_id = Some(id);
|
if pf_id == 0 {
|
||||||
}
|
return Err(CreationError::OsError("No available pixel format".to_owned()));
|
||||||
|
|
||||||
if format.hardware_accelerated {
|
|
||||||
return Ok(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backup_id.ok_or(CreationError::OsError("No available pixel format".to_string()))
|
Ok(pf_id)
|
||||||
}
|
}
|
||||||
|
|
171
src/lib.rs
171
src/lib.rs
|
@ -300,6 +300,16 @@ pub enum Robustness {
|
||||||
TryRobustLoseContextOnReset,
|
TryRobustLoseContextOnReset,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The behavior of the driver when you change the current context.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum ReleaseBehavior {
|
||||||
|
/// Doesn't do anything. Most notably doesn't flush.
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// Flushes the context that was previously current as if `glFlush` was called.
|
||||||
|
Flush,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum MouseCursor {
|
pub enum MouseCursor {
|
||||||
/// The platform-dependent default cursor.
|
/// The platform-dependent default cursor.
|
||||||
|
@ -388,132 +398,71 @@ pub struct PixelFormat {
|
||||||
pub srgb: bool,
|
pub srgb: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// VERY UNSTABLE! Describes how the backend should choose a pixel format.
|
/// Describes how the backend should choose a pixel format.
|
||||||
|
// TODO: swap method? (swap, copy)
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub struct PixelFormatRequirements {
|
pub struct PixelFormatRequirements {
|
||||||
pub multisampling: Option<u16>,
|
/// If true, only hardware-accelerated formats will be conisdered. If false, only software
|
||||||
pub depth_bits: Option<u8>,
|
/// renderers. `None` means "don't care". Default is `Some(true)`.
|
||||||
pub stencil_bits: Option<u8>,
|
pub hardware_accelerated: Option<bool>,
|
||||||
|
|
||||||
|
/// Minimum number of bits for the color buffer, excluding alpha. `None` means "don't care".
|
||||||
|
/// The default is `Some(24)`.
|
||||||
pub color_bits: Option<u8>,
|
pub color_bits: Option<u8>,
|
||||||
|
|
||||||
|
/// If true, the color buffer must be in a floating point format. Default is `false`.
|
||||||
|
///
|
||||||
|
/// Using floating points allows you to write values outside of the `[0.0, 1.0]` range.
|
||||||
|
pub float_color_buffer: bool,
|
||||||
|
|
||||||
|
/// Minimum number of bits for the alpha in the color buffer. `None` means "don't care".
|
||||||
|
/// The default is `Some(8)`.
|
||||||
pub alpha_bits: Option<u8>,
|
pub alpha_bits: Option<u8>,
|
||||||
|
|
||||||
|
/// Minimum number of bits for the depth buffer. `None` means "don't care".
|
||||||
|
/// The default value is `Some(24)`.
|
||||||
|
pub depth_bits: Option<u8>,
|
||||||
|
|
||||||
|
/// Minimum number of bits for the depth buffer. `None` means "don't care".
|
||||||
|
/// The default value is `Some(8)`.
|
||||||
|
pub stencil_bits: Option<u8>,
|
||||||
|
|
||||||
|
/// If true, only double-buffered formats will be considered. If false, only single-buffer
|
||||||
|
/// formats. `None` means "don't care". The default is `Some(true)`.
|
||||||
|
pub double_buffer: Option<bool>,
|
||||||
|
|
||||||
|
/// Contains the minimum number of samples per pixel in the color, depth and stencil buffers.
|
||||||
|
/// `None` means "don't care". Default is `None`.
|
||||||
|
/// A value of `Some(0)` indicates that multisampling must not be enabled.
|
||||||
|
pub multisampling: Option<u16>,
|
||||||
|
|
||||||
|
/// If true, only stereoscopic formats will be considered. If false, only non-stereoscopic
|
||||||
|
/// formats. The default is `false`.
|
||||||
pub stereoscopy: bool,
|
pub stereoscopy: bool,
|
||||||
pub srgb: Option<bool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PixelFormatRequirements {
|
/// If true, only sRGB-capable formats will be considered. If false, don't care.
|
||||||
#[cfg(not(target_os = "macos"))]
|
/// The default is `false`.
|
||||||
fn choose_pixel_format<T, I>(&self, iter: I) -> Result<(T, PixelFormat), CreationError>
|
pub srgb: bool,
|
||||||
where I: IntoIterator<Item=(T, PixelFormat)>, T: Clone
|
|
||||||
{
|
|
||||||
// filtering formats that don't match the requirements
|
|
||||||
let iter = iter.into_iter().filter(|&(_, ref format)| {
|
|
||||||
if format.color_bits < self.color_bits.unwrap_or(0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if format.alpha_bits < self.alpha_bits.unwrap_or(0) {
|
/// The behavior when changing the current context. Default is `Flush`.
|
||||||
return false;
|
pub release_behavior: ReleaseBehavior,
|
||||||
}
|
|
||||||
|
|
||||||
if format.depth_bits < self.depth_bits.unwrap_or(0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if format.stencil_bits < self.stencil_bits.unwrap_or(0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !format.stereoscopy && self.stereoscopy {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(req_ms) = self.multisampling {
|
|
||||||
match format.multisampling {
|
|
||||||
Some(val) if val >= req_ms => (),
|
|
||||||
_ => return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if format.multisampling.is_some() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(srgb) = self.srgb {
|
|
||||||
if srgb != format.srgb {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
});
|
|
||||||
|
|
||||||
// sorting so that the preferred format comes first
|
|
||||||
let mut formats = iter.collect::<Vec<_>>();
|
|
||||||
formats.sort_by(|&(_, ref left), &(_, ref right)| {
|
|
||||||
// prefer hardware-accelerated formats
|
|
||||||
if left.hardware_accelerated && !right.hardware_accelerated {
|
|
||||||
return Ordering::Less;
|
|
||||||
} else if right.hardware_accelerated && !left.hardware_accelerated {
|
|
||||||
return Ordering::Greater;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefer sRGB formats
|
|
||||||
if left.srgb && !right.srgb {
|
|
||||||
return Ordering::Less;
|
|
||||||
} else if right.srgb && !left.srgb {
|
|
||||||
return Ordering::Greater;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefer formats with the highest color+alpha bits
|
|
||||||
if left.color_bits + left.alpha_bits != right.color_bits + right.alpha_bits {
|
|
||||||
return (right.color_bits + right.alpha_bits)
|
|
||||||
.cmp(&(left.color_bits + left.alpha_bits));
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefer double-buffering formats
|
|
||||||
if left.double_buffer && !right.double_buffer {
|
|
||||||
return Ordering::Less;
|
|
||||||
} else if right.double_buffer && !left.double_buffer {
|
|
||||||
return Ordering::Greater;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefer formats with the highest depth bits
|
|
||||||
if left.depth_bits != right.depth_bits {
|
|
||||||
return (right.depth_bits).cmp(&left.depth_bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefer formats with the highest stencil bits
|
|
||||||
if left.stencil_bits != right.stencil_bits {
|
|
||||||
return (right.stencil_bits).cmp(&left.stencil_bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefer formats with multisampling
|
|
||||||
if left.multisampling.is_some() && right.multisampling.is_none() {
|
|
||||||
return Ordering::Less;
|
|
||||||
} else if right.multisampling.is_some() && left.multisampling.is_none() {
|
|
||||||
return Ordering::Greater;
|
|
||||||
}
|
|
||||||
|
|
||||||
// default
|
|
||||||
return Ordering::Equal;
|
|
||||||
});
|
|
||||||
|
|
||||||
formats.into_iter().next().ok_or(CreationError::NoAvailablePixelFormat)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PixelFormatRequirements {
|
impl Default for PixelFormatRequirements {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> PixelFormatRequirements {
|
fn default() -> PixelFormatRequirements {
|
||||||
PixelFormatRequirements {
|
PixelFormatRequirements {
|
||||||
|
hardware_accelerated: Some(true),
|
||||||
|
color_bits: Some(24),
|
||||||
|
float_color_buffer: false,
|
||||||
|
alpha_bits: Some(8),
|
||||||
|
depth_bits: Some(24),
|
||||||
|
stencil_bits: Some(8),
|
||||||
|
double_buffer: Some(true),
|
||||||
multisampling: None,
|
multisampling: None,
|
||||||
depth_bits: None,
|
|
||||||
stencil_bits: None,
|
|
||||||
color_bits: None,
|
|
||||||
alpha_bits: None,
|
|
||||||
stereoscopy: false,
|
stereoscopy: false,
|
||||||
srgb: None,
|
srgb: false,
|
||||||
|
release_behavior: ReleaseBehavior::Flush,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,7 +186,7 @@ impl<'a> WindowBuilder<'a> {
|
||||||
/// Sets whether sRGB should be enabled on the window. `None` means "I don't care".
|
/// Sets whether sRGB should be enabled on the window. `None` means "I don't care".
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_srgb(mut self, srgb_enabled: Option<bool>) -> WindowBuilder<'a> {
|
pub fn with_srgb(mut self, srgb_enabled: Option<bool>) -> WindowBuilder<'a> {
|
||||||
self.pf_reqs.srgb = srgb_enabled;
|
self.pf_reqs.srgb = srgb_enabled.unwrap_or(false);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue