Skip to content

Commit 68a10a0

Browse files
authored
[egl] Fix robust context creation failing on some devices (#7952)
1 parent 4bd0f75 commit 68a10a0

File tree

1 file changed

+93
-39
lines changed

1 file changed

+93
-39
lines changed

wgpu-hal/src/gles/egl.rs

Lines changed: 93 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,6 @@ impl Inner {
574574
})
575575
.unwrap();
576576

577-
let needs_robustness = true;
578577
let mut khr_context_flags = 0;
579578
let supports_khr_context = display_extensions.contains("EGL_KHR_create_context");
580579

@@ -611,53 +610,108 @@ impl Inner {
611610
log::debug!("\tEGL context: -debug");
612611
}
613612
}
614-
if needs_robustness {
615-
//Note: the core version can fail if robustness is not supported
616-
// (regardless of whether the extension is supported!).
617-
// In fact, Angle does precisely that awful behavior, so we don't try it there.
618-
if version >= (1, 5) && !display_extensions.contains("EGL_ANGLE_") {
619-
log::debug!("\tEGL context: +robust access");
620-
context_attributes.push(khronos_egl::CONTEXT_OPENGL_ROBUST_ACCESS);
621-
context_attributes.push(khronos_egl::TRUE as _);
622-
} else if display_extensions.contains("EGL_EXT_create_context_robustness") {
623-
log::debug!("\tEGL context: +robust access EXT");
624-
context_attributes.push(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
625-
context_attributes.push(khronos_egl::TRUE as _);
626-
} else {
627-
//Note: we aren't trying `EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR`
628-
// because it's for desktop GL only, not GLES.
629-
log::warn!("\tEGL context: -robust access");
630-
}
631-
}
613+
632614
if khr_context_flags != 0 {
633615
context_attributes.push(EGL_CONTEXT_FLAGS_KHR);
634616
context_attributes.push(khr_context_flags);
635617
}
636-
context_attributes.push(khronos_egl::NONE);
637618

638619
gl_context_attributes.extend(&context_attributes);
639620
gles_context_attributes.extend(&context_attributes);
640621

641-
let context = if supports_opengl {
642-
egl.create_context(display, config, None, &gl_context_attributes)
643-
.or_else(|_| {
644-
egl.bind_api(khronos_egl::OPENGL_ES_API).unwrap();
622+
let context = {
623+
enum Robustness {
624+
Core,
625+
Ext,
626+
}
627+
628+
let mut robustness = if version >= (1, 5) {
629+
Some(Robustness::Core)
630+
} else if display_extensions.contains("EGL_EXT_create_context_robustness") {
631+
Some(Robustness::Ext)
632+
} else {
633+
None
634+
};
635+
636+
loop {
637+
let robustness_attributes = match robustness {
638+
Some(Robustness::Core) => {
639+
vec![
640+
khronos_egl::CONTEXT_OPENGL_ROBUST_ACCESS,
641+
khronos_egl::TRUE as _,
642+
khronos_egl::NONE,
643+
]
644+
}
645+
Some(Robustness::Ext) => {
646+
vec![
647+
EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT,
648+
khronos_egl::TRUE as _,
649+
khronos_egl::NONE,
650+
]
651+
}
652+
None => vec![khronos_egl::NONE],
653+
};
654+
655+
let mut gl_context_attributes = gl_context_attributes.clone();
656+
gl_context_attributes.extend(&robustness_attributes);
657+
658+
let mut gles_context_attributes = gles_context_attributes.clone();
659+
gles_context_attributes.extend(&robustness_attributes);
660+
661+
let result = if supports_opengl {
662+
egl.create_context(display, config, None, &gl_context_attributes)
663+
.or_else(|_| {
664+
egl.bind_api(khronos_egl::OPENGL_ES_API).unwrap();
665+
egl.create_context(display, config, None, &gles_context_attributes)
666+
})
667+
} else {
645668
egl.create_context(display, config, None, &gles_context_attributes)
646-
})
647-
.map_err(|e| {
648-
crate::InstanceError::with_source(
649-
String::from("unable to create OpenGL or GLES 3.x context"),
650-
e,
651-
)
652-
})
653-
} else {
654-
egl.create_context(display, config, None, &gles_context_attributes)
655-
.map_err(|e| {
656-
crate::InstanceError::with_source(
657-
String::from("unable to create GLES 3.x context"),
658-
e,
659-
)
660-
})
669+
};
670+
671+
match (result, robustness) {
672+
// We have a context at the requested robustness level
673+
(Ok(_), robustness) => {
674+
match robustness {
675+
Some(Robustness::Core) => {
676+
log::debug!("\tEGL context: +robust access");
677+
}
678+
Some(Robustness::Ext) => {
679+
log::debug!("\tEGL context: +robust access EXT");
680+
}
681+
None => {
682+
log::debug!("\tEGL context: -robust access");
683+
}
684+
}
685+
686+
break result;
687+
}
688+
689+
// BadAttribute could mean that context creation is not supported at the requested robustness level
690+
// We try the next robustness level.
691+
(Err(khronos_egl::Error::BadAttribute), Some(r)) => {
692+
// Trying EXT robustness if Core robustness is not working
693+
// and EXT robustness is supported.
694+
robustness = if matches!(r, Robustness::Core)
695+
&& display_extensions.contains("EGL_EXT_create_context_robustness")
696+
{
697+
Some(Robustness::Ext)
698+
} else {
699+
None
700+
};
701+
702+
continue;
703+
}
704+
705+
// Any other error, or depleted robustness levels, we give up.
706+
_ => break result,
707+
}
708+
}
709+
.map_err(|e| {
710+
crate::InstanceError::with_source(
711+
String::from("unable to create OpenGL or GLES 3.x context"),
712+
e,
713+
)
714+
})
661715
}?;
662716

663717
// Testing if context can be binded without surface

0 commit comments

Comments
 (0)