Check Opengl version is 3.3+ before creating a GL context over a GL ES context (#5996)

* Retry with GLES if creating a GL context fails

* Cleaner GL context creation retry
This commit is contained in:
James Pruitt 2024-08-06 02:19:23 -06:00 committed by GitHub
parent 8c7c5c4974
commit 594476c991
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 29 deletions

View File

@ -49,6 +49,7 @@ Bottom level categories:
#### General
- If GL context creation fails retry with GLES. By @Rapdorian in [#5996](https://github.com/gfx-rs/wgpu/pull/5996)
- Fix profiling with `tracy`. By @waywardmonkeys in [#5988](https://github.com/gfx-rs/wgpu/pull/5988)
- As a workaround for [issue #4905](https://github.com/gfx-rs/wgpu/issues/4905), `wgpu-core` is undocumented unless `--cfg wgpu_core_doc` feature is enabled. By @kpreid in [#5987](https://github.com/gfx-rs/wgpu/pull/5987)
- Bump MSRV for `d3d12`/`naga`/`wgpu-core`/`wgpu-hal`/`wgpu-types`' to 1.76. By @wumpf in [#6003](https://github.com/gfx-rs/wgpu/pull/6003)

View File

@ -550,26 +550,25 @@ impl Inner {
let supports_khr_context = display_extensions.contains("EGL_KHR_create_context");
let mut context_attributes = vec![];
if supports_opengl {
context_attributes.push(khronos_egl::CONTEXT_MAJOR_VERSION);
context_attributes.push(3);
context_attributes.push(khronos_egl::CONTEXT_MINOR_VERSION);
context_attributes.push(3);
if force_gles_minor_version != wgt::Gles3MinorVersion::Automatic {
log::warn!("Ignoring specified GLES minor version as OpenGL is used");
}
} else {
context_attributes.push(khronos_egl::CONTEXT_MAJOR_VERSION);
context_attributes.push(3); // Request GLES 3.0 or higher
if force_gles_minor_version != wgt::Gles3MinorVersion::Automatic {
context_attributes.push(khronos_egl::CONTEXT_MINOR_VERSION);
context_attributes.push(match force_gles_minor_version {
wgt::Gles3MinorVersion::Automatic => unreachable!(),
wgt::Gles3MinorVersion::Version0 => 0,
wgt::Gles3MinorVersion::Version1 => 1,
wgt::Gles3MinorVersion::Version2 => 2,
});
}
let mut gl_context_attributes = vec![];
let mut gles_context_attributes = vec![];
gl_context_attributes.push(khronos_egl::CONTEXT_MAJOR_VERSION);
gl_context_attributes.push(3);
gl_context_attributes.push(khronos_egl::CONTEXT_MINOR_VERSION);
gl_context_attributes.push(3);
if supports_opengl && force_gles_minor_version != wgt::Gles3MinorVersion::Automatic {
log::warn!("Ignoring specified GLES minor version as OpenGL is used");
}
gles_context_attributes.push(khronos_egl::CONTEXT_MAJOR_VERSION);
gles_context_attributes.push(3); // Request GLES 3.0 or higher
if force_gles_minor_version != wgt::Gles3MinorVersion::Automatic {
gles_context_attributes.push(khronos_egl::CONTEXT_MINOR_VERSION);
gles_context_attributes.push(match force_gles_minor_version {
wgt::Gles3MinorVersion::Automatic => unreachable!(),
wgt::Gles3MinorVersion::Version0 => 0,
wgt::Gles3MinorVersion::Version1 => 1,
wgt::Gles3MinorVersion::Version2 => 2,
});
}
if flags.contains(wgt::InstanceFlags::DEBUG) {
if version >= (1, 5) {
@ -606,15 +605,31 @@ impl Inner {
context_attributes.push(khr_context_flags);
}
context_attributes.push(khronos_egl::NONE);
let context = match egl.create_context(display, config, None, &context_attributes) {
Ok(context) => context,
Err(e) => {
return Err(crate::InstanceError::with_source(
String::from("unable to create GLES 3.x context"),
e,
));
}
};
gl_context_attributes.extend(&context_attributes);
gles_context_attributes.extend(&context_attributes);
let context = if supports_opengl {
egl.create_context(display, config, None, &gl_context_attributes)
.or_else(|_| {
egl.bind_api(khronos_egl::OPENGL_ES_API).unwrap();
egl.create_context(display, config, None, &gles_context_attributes)
})
.map_err(|e| {
crate::InstanceError::with_source(
String::from("unable to create OpenGL or GLES 3.x context"),
e,
)
})
} else {
egl.create_context(display, config, None, &gles_context_attributes)
.map_err(|e| {
crate::InstanceError::with_source(
String::from("unable to create GLES 3.x context"),
e,
)
})
}?;
// Testing if context can be binded without surface
// and creating dummy pbuffer surface if not.