Fix vsync attribute

This commit is contained in:
Chandler Newman 2020-04-16 16:03:10 +01:00
parent 4b97ed8eba
commit 28eb4dd943
2 changed files with 70 additions and 16 deletions

View File

@ -63,7 +63,7 @@ impl EGLContext {
} }
}; };
let (pixel_format, config_id) = display.choose_config(version, reqs)?; let (pixel_format, config_id) = display.choose_config(attributes, reqs)?;
let mut context_attributes = Vec::with_capacity(10); let mut context_attributes = Vec::with_capacity(10);

View File

@ -161,7 +161,7 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
/// Finds a compatible [`EGLConfig`] for a given set of requirements /// Finds a compatible [`EGLConfig`] for a given set of requirements
pub fn choose_config( pub fn choose_config(
&self, &self,
version: (u8, u8), attributes: GlAttributes,
reqs: PixelFormatRequirements, reqs: PixelFormatRequirements,
) -> Result<(PixelFormat, ffi::egl::types::EGLConfig), Error> { ) -> Result<(PixelFormat, ffi::egl::types::EGLConfig), Error> {
let descriptor = { let descriptor = {
@ -180,8 +180,8 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
// if we ask for PBUFFER_BIT as well as WINDOW_BIT // if we ask for PBUFFER_BIT as well as WINDOW_BIT
out.push((ffi::egl::WINDOW_BIT) as c_int); out.push((ffi::egl::WINDOW_BIT) as c_int);
match version { match attributes.version {
(3, _) => { Some((3, _)) => {
if self.egl_version < (1, 3) { if self.egl_version < (1, 3) {
error!( error!(
self.logger, self.logger,
@ -196,7 +196,7 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
out.push(ffi::egl::CONFORMANT as c_int); out.push(ffi::egl::CONFORMANT as c_int);
out.push(ffi::egl::OPENGL_ES3_BIT as c_int); out.push(ffi::egl::OPENGL_ES3_BIT as c_int);
} }
(2, _) => { Some((2, _)) => {
if self.egl_version < (1, 3) { if self.egl_version < (1, 3) {
error!( error!(
self.logger, self.logger,
@ -211,7 +211,12 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
out.push(ffi::egl::CONFORMANT as c_int); out.push(ffi::egl::CONFORMANT as c_int);
out.push(ffi::egl::OPENGL_ES2_BIT as c_int); out.push(ffi::egl::OPENGL_ES2_BIT as c_int);
} }
(_, _) => unreachable!(), Some(ver) => {
return Err(Error::OpenGlVersionNotSupported(ver));
}
None => {
return Err(Error::OpenGlVersionNotSupported((0, 0)));
}
}; };
reqs.create_attributes(&mut out, &self.logger)?; reqs.create_attributes(&mut out, &self.logger)?;
@ -221,30 +226,79 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
}; };
// calling `eglChooseConfig` // calling `eglChooseConfig`
let mut config_id = MaybeUninit::uninit(); let mut num_configs = unsafe { std::mem::zeroed() };
let mut num_configs = MaybeUninit::uninit();
if unsafe { if unsafe {
ffi::egl::ChooseConfig( ffi::egl::ChooseConfig(
**self.display, **self.display,
descriptor.as_ptr(), descriptor.as_ptr(),
config_id.as_mut_ptr(), std::ptr::null_mut(),
1, 0,
num_configs.as_mut_ptr(), &mut num_configs,
) )
} == 0 } == 0
{ {
return Err(Error::ConfigFailed); return Err(Error::ConfigFailed);
} }
let config_id = unsafe { config_id.assume_init() };
let num_configs = unsafe { num_configs.assume_init() };
if num_configs == 0 { if num_configs == 0 {
error!(self.logger, "No matching color format found");
return Err(Error::NoAvailablePixelFormat); return Err(Error::NoAvailablePixelFormat);
} }
// TODO: Filter configs for matching vsync property let mut config_ids = Vec::with_capacity(num_configs as usize);
config_ids.resize_with(num_configs as usize, || unsafe { std::mem::zeroed() });
if unsafe {
ffi::egl::ChooseConfig(
**self.display,
descriptor.as_ptr(),
config_ids.as_mut_ptr(),
num_configs,
&mut num_configs,
)
} == 0
{
return Err(Error::ConfigFailed);
}
// TODO: Deeper swap intervals might have some uses
let desired_swap_interval = if attributes.vsync { 1 } else { 0 };
let config_ids = config_ids
.into_iter()
.filter(|&config| unsafe {
let mut min_swap_interval = 0;
ffi::egl::GetConfigAttrib(
**self.display,
config,
ffi::egl::MIN_SWAP_INTERVAL as ffi::egl::types::EGLint,
&mut min_swap_interval,
);
if desired_swap_interval < min_swap_interval {
return false;
}
let mut max_swap_interval = 0;
ffi::egl::GetConfigAttrib(
**self.display,
config,
ffi::egl::MAX_SWAP_INTERVAL as ffi::egl::types::EGLint,
&mut max_swap_interval,
);
if desired_swap_interval > max_swap_interval {
return false;
}
true
})
.collect::<Vec<_>>();
if config_ids.is_empty() {
return Err(Error::NoAvailablePixelFormat);
}
// TODO: Improve config selection
let config_id = config_ids[0];
// analyzing each config // analyzing each config
macro_rules! attrib { macro_rules! attrib {