[egl] get rid of unwrap where possible (#8024)

Co-authored-by: Andreas Reich <r_andreas2@web.de>
This commit is contained in:
Lucas Abel 2025-08-28 23:59:54 +02:00 committed by GitHub
parent 0aacfeadff
commit cd14b194a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 155 additions and 109 deletions

View File

@ -133,6 +133,10 @@ By @cwfitzgerald in [#8162](https://github.com/gfx-rs/wgpu/pull/8162).
- Fixed a bug where access to matrices with 2 rows would not work in some cases. By @andyleiserson in [#7438](https://github.com/gfx-rs/wgpu/pull/7438).
##### EGL
- Fixed unwrap failed in context creation for some Android devices. By @uael in [#8024](https://github.com/gfx-rs/wgpu/pull/8024).
#### naga
- [wgsl-in] Allow a trailing comma in `@blend_src(…)` attributes. By @ErichDonGubler in [#8137](https://github.com/gfx-rs/wgpu/pull/8137).

View File

@ -136,8 +136,13 @@ impl Drop for DisplayOwner {
fn drop(&mut self) {
match self.display {
DisplayRef::X11(ptr) => unsafe {
let func: libloading::Symbol<XCloseDisplayFun> =
self.library.get(c"XCloseDisplay".to_bytes()).unwrap();
let Ok(func): Result<libloading::Symbol<XCloseDisplayFun>, _> = self
.library
.get(c"XCloseDisplay".to_bytes())
.inspect_err(|err| log::error!("Failed to load XCloseDisplay: {err:?}"))
else {
return;
};
func(ptr.as_ptr());
},
DisplayRef::Wayland => {}
@ -149,8 +154,10 @@ fn open_x_display() -> Option<DisplayOwner> {
log::debug!("Loading X11 library to get the current display");
unsafe {
let library = find_library(&["libX11.so.6", "libX11.so"])?;
let func: libloading::Symbol<XOpenDisplayFun> =
library.get(c"XOpenDisplay".to_bytes()).unwrap();
let func: libloading::Symbol<XOpenDisplayFun> = library
.get(c"XOpenDisplay".to_bytes())
.inspect_err(|err| log::error!("Failed to load XOpenDisplay: {err:?}"))
.ok()?;
let result = func(ptr::null());
ptr::NonNull::new(result).map(|ptr| DisplayOwner {
display: DisplayRef::X11(ptr),
@ -178,10 +185,12 @@ fn test_wayland_display() -> Option<DisplayOwner> {
let client_library = find_library(&["libwayland-client.so.0", "libwayland-client.so"])?;
let wl_display_connect: libloading::Symbol<WlDisplayConnectFun> = client_library
.get(c"wl_display_connect".to_bytes())
.unwrap();
.inspect_err(|err| log::error!("Failed to load wl_display_connect: {err:?}"))
.ok()?;
let wl_display_disconnect: libloading::Symbol<WlDisplayDisconnectFun> = client_library
.get(c"wl_display_disconnect".to_bytes())
.unwrap();
.inspect_err(|err| log::error!("Failed to load wl_display_disconnect: {err:?}"))
.ok()?;
let display = ptr::NonNull::new(wl_display_connect(ptr::null()))?;
wl_display_disconnect(display.as_ptr());
find_library(&["libwayland-egl.so.1", "libwayland-egl.so"])?
@ -394,9 +403,9 @@ impl<'a> core::ops::Deref for AdapterContextLock<'a> {
impl<'a> Drop for AdapterContextLock<'a> {
fn drop(&mut self) {
if let Some(egl) = self.egl.take() {
egl.instance
.make_current(egl.display, None, None, None)
.unwrap();
if let Err(err) = egl.instance.make_current(egl.display, None, None, None) {
log::error!("Failed to make EGL context current: {err:?}");
}
}
}
}
@ -501,6 +510,12 @@ fn terminate_display(
}
}
fn instance_err<E: core::error::Error + Send + Sync + 'static>(
message: impl Into<String>,
) -> impl FnOnce(E) -> crate::InstanceError {
move |e| crate::InstanceError::with_source(message.into(), e)
}
impl Inner {
fn create(
flags: wgt::InstanceFlags,
@ -508,18 +523,14 @@ impl Inner {
display: khronos_egl::Display,
force_gles_minor_version: wgt::Gles3MinorVersion,
) -> Result<Self, crate::InstanceError> {
let version = initialize_display(&egl, display).map_err(|e| {
crate::InstanceError::with_source(
String::from("failed to initialize EGL display connection"),
e,
)
})?;
let version = initialize_display(&egl, display)
.map_err(instance_err("failed to initialize EGL display connection"))?;
let vendor = egl
.query_string(Some(display), khronos_egl::VENDOR)
.unwrap();
.map_err(instance_err("failed to query EGL vendor"))?;
let display_extensions = egl
.query_string(Some(display), khronos_egl::EXTENSIONS)
.unwrap()
.map_err(instance_err("failed to query EGL display extensions"))?
.to_string_lossy();
log::debug!("Display vendor {vendor:?}, version {version:?}",);
log::debug!(
@ -540,16 +551,19 @@ impl Inner {
if log::max_level() >= log::LevelFilter::Trace {
log::trace!("Configurations:");
let config_count = egl.get_config_count(display).unwrap();
let config_count = egl
.get_config_count(display)
.map_err(instance_err("failed to get config count"))?;
let mut configurations = Vec::with_capacity(config_count);
egl.get_configs(display, &mut configurations).unwrap();
egl.get_configs(display, &mut configurations)
.map_err(instance_err("failed to get configs"))?;
for &config in configurations.iter() {
log::trace!("\tCONFORMANT=0x{:X}, RENDERABLE=0x{:X}, NATIVE_RENDERABLE=0x{:X}, SURFACE_TYPE=0x{:X}, ALPHA_SIZE={}",
egl.get_config_attrib(display, config, khronos_egl::CONFORMANT).unwrap(),
egl.get_config_attrib(display, config, khronos_egl::RENDERABLE_TYPE).unwrap(),
egl.get_config_attrib(display, config, khronos_egl::NATIVE_RENDERABLE).unwrap(),
egl.get_config_attrib(display, config, khronos_egl::SURFACE_TYPE).unwrap(),
egl.get_config_attrib(display, config, khronos_egl::ALPHA_SIZE).unwrap(),
log::trace!("\tCONFORMANT=0x{:X?}, RENDERABLE=0x{:X?}, NATIVE_RENDERABLE=0x{:X?}, SURFACE_TYPE=0x{:X?}, ALPHA_SIZE={:?}",
egl.get_config_attrib(display, config, khronos_egl::CONFORMANT),
egl.get_config_attrib(display, config, khronos_egl::RENDERABLE_TYPE),
egl.get_config_attrib(display, config, khronos_egl::NATIVE_RENDERABLE),
egl.get_config_attrib(display, config, khronos_egl::SURFACE_TYPE),
egl.get_config_attrib(display, config, khronos_egl::ALPHA_SIZE),
);
}
}
@ -559,7 +573,7 @@ impl Inner {
let supports_opengl = if version >= (1, 4) {
let client_apis = egl
.query_string(Some(display), khronos_egl::CLIENT_APIS)
.unwrap()
.map_err(instance_err("failed to query EGL client APIs string"))?
.to_string_lossy();
client_apis
.split(' ')
@ -572,7 +586,7 @@ impl Inner {
} else {
khronos_egl::OPENGL_ES_API
})
.unwrap();
.map_err(instance_err("failed to bind API"))?;
let mut khr_context_flags = 0;
let supports_khr_context = display_extensions.contains("EGL_KHR_create_context");
@ -661,7 +675,7 @@ impl Inner {
let result = if supports_opengl {
egl.create_context(display, config, None, &gl_context_attributes)
.or_else(|_| {
egl.bind_api(khronos_egl::OPENGL_ES_API).unwrap();
egl.bind_api(khronos_egl::OPENGL_ES_API)?;
egl.create_context(display, config, None, &gles_context_attributes)
})
} else {
@ -848,15 +862,9 @@ impl crate::Instance for Instance {
} else {
unsafe { khronos_egl::DynamicInstance::<khronos_egl::EGL1_4>::load_required() }
};
let egl = match egl_result {
Ok(egl) => Arc::new(egl),
Err(e) => {
return Err(crate::InstanceError::with_source(
String::from("unable to open libEGL"),
e,
));
}
};
let egl = egl_result
.map(Arc::new)
.map_err(instance_err("unable to open libEGL"))?;
let client_extensions = egl.query_string(None, khronos_egl::EXTENSIONS);
@ -891,75 +899,83 @@ impl crate::Instance for Instance {
#[cfg(Emscripten)]
let egl1_5: Option<&Arc<EglInstance>> = Some(&egl);
let (display, display_owner, wsi_kind) =
if let (Some(library), Some(egl)) = (wayland_library, egl1_5) {
log::info!("Using Wayland platform");
let display_attributes = [khronos_egl::ATTRIB_NONE];
let display = unsafe {
egl.get_platform_display(
EGL_PLATFORM_WAYLAND_KHR,
khronos_egl::DEFAULT_DISPLAY,
&display_attributes,
)
}
.unwrap();
(display, Some(Rc::new(library)), WindowKind::Wayland)
} else if let (Some(display_owner), Some(egl)) = (x11_display_library, egl1_5) {
log::info!("Using X11 platform");
let display_attributes = [khronos_egl::ATTRIB_NONE];
let display = unsafe {
egl.get_platform_display(
EGL_PLATFORM_X11_KHR,
display_owner.display.as_ptr(),
&display_attributes,
)
}
.unwrap();
(display, Some(Rc::new(display_owner)), WindowKind::X11)
} else if let (Some(display_owner), Some(egl)) = (angle_x11_display_library, egl1_5) {
log::info!("Using Angle platform with X11");
let display_attributes = [
EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE as khronos_egl::Attrib,
EGL_PLATFORM_X11_KHR as khronos_egl::Attrib,
EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED as khronos_egl::Attrib,
usize::from(desc.flags.contains(wgt::InstanceFlags::VALIDATION)),
khronos_egl::ATTRIB_NONE,
];
let display = unsafe {
egl.get_platform_display(
EGL_PLATFORM_ANGLE_ANGLE,
display_owner.display.as_ptr(),
&display_attributes,
)
}
.unwrap();
(display, Some(Rc::new(display_owner)), WindowKind::AngleX11)
} else if client_ext_str.contains("EGL_MESA_platform_surfaceless") {
log::warn!("No windowing system present. Using surfaceless platform");
#[allow(clippy::unnecessary_literal_unwrap)] // This is only a literal on Emscripten
let egl = egl1_5.expect("Failed to get EGL 1.5 for surfaceless");
let display = unsafe {
egl.get_platform_display(
EGL_PLATFORM_SURFACELESS_MESA,
khronos_egl::DEFAULT_DISPLAY,
&[khronos_egl::ATTRIB_NONE],
)
}
.unwrap();
let (display, display_owner, wsi_kind) = if let (Some(library), Some(egl)) =
(wayland_library, egl1_5)
{
log::info!("Using Wayland platform");
let display_attributes = [khronos_egl::ATTRIB_NONE];
let display = unsafe {
egl.get_platform_display(
EGL_PLATFORM_WAYLAND_KHR,
khronos_egl::DEFAULT_DISPLAY,
&display_attributes,
)
}
.map_err(instance_err("failed to get Wayland display"))?;
(display, Some(Rc::new(library)), WindowKind::Wayland)
} else if let (Some(display_owner), Some(egl)) = (x11_display_library, egl1_5) {
log::info!("Using X11 platform");
let display_attributes = [khronos_egl::ATTRIB_NONE];
let display = unsafe {
egl.get_platform_display(
EGL_PLATFORM_X11_KHR,
display_owner.display.as_ptr(),
&display_attributes,
)
}
.map_err(instance_err("failed to get x11 display"))?;
(display, Some(Rc::new(display_owner)), WindowKind::X11)
} else if let (Some(display_owner), Some(egl)) = (angle_x11_display_library, egl1_5) {
log::info!("Using Angle platform with X11");
let display_attributes = [
EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE as khronos_egl::Attrib,
EGL_PLATFORM_X11_KHR as khronos_egl::Attrib,
EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED as khronos_egl::Attrib,
usize::from(desc.flags.contains(wgt::InstanceFlags::VALIDATION)),
khronos_egl::ATTRIB_NONE,
];
let display = unsafe {
egl.get_platform_display(
EGL_PLATFORM_ANGLE_ANGLE,
display_owner.display.as_ptr(),
&display_attributes,
)
}
.map_err(instance_err("failed to get Angle display"))?;
(display, Some(Rc::new(display_owner)), WindowKind::AngleX11)
} else if client_ext_str.contains("EGL_MESA_platform_surfaceless") {
log::warn!("No windowing system present. Using surfaceless platform");
#[allow(clippy::unnecessary_literal_unwrap)] // This is only a literal on Emscripten
let egl = egl1_5.expect("Failed to get EGL 1.5 for surfaceless");
let display = unsafe {
egl.get_platform_display(
EGL_PLATFORM_SURFACELESS_MESA,
khronos_egl::DEFAULT_DISPLAY,
&[khronos_egl::ATTRIB_NONE],
)
}
.map_err(instance_err("failed to get MESA display"))?;
(display, None, WindowKind::Unknown)
} else {
log::warn!("EGL_MESA_platform_surfaceless not available. Using default platform");
let display = unsafe { egl.get_display(khronos_egl::DEFAULT_DISPLAY) }.unwrap();
(display, None, WindowKind::Unknown)
};
(display, None, WindowKind::Unknown)
} else {
log::warn!("EGL_MESA_platform_surfaceless not available. Using default platform");
let display = unsafe { egl.get_display(khronos_egl::DEFAULT_DISPLAY) }
.ok_or_else(|| crate::InstanceError::new("Failed to get default display".into()))?;
(display, None, WindowKind::Unknown)
};
if desc.flags.contains(wgt::InstanceFlags::VALIDATION)
&& client_ext_str.contains("EGL_KHR_debug")
{
log::debug!("Enabling EGL debug output");
let function: EglDebugMessageControlFun = {
let addr = egl.get_proc_address("eglDebugMessageControlKHR").unwrap();
let addr = egl
.get_proc_address("eglDebugMessageControlKHR")
.ok_or_else(|| {
crate::InstanceError::new(
"failed to get `eglDebugMessageControlKHR` proc address".into(),
)
})?;
unsafe { core::mem::transmute(addr) }
};
let attributes = [
@ -1021,7 +1037,7 @@ impl crate::Instance for Instance {
inner.config,
khronos_egl::NATIVE_VISUAL_ID,
)
.unwrap();
.map_err(instance_err("failed to get config NATIVE_VISUAL_ID"))?;
let ret = unsafe {
ndk_sys::ANativeWindow_setBuffersGeometry(
@ -1064,14 +1080,18 @@ impl crate::Instance for Instance {
.egl
.instance
.upcast::<khronos_egl::EGL1_5>()
.unwrap()
.ok_or_else(|| {
crate::InstanceError::new(
"EGL 1.5 is required for Wayland support".into(),
)
})?
.get_platform_display(
EGL_PLATFORM_WAYLAND_KHR,
display_handle.display.as_ptr(),
&display_attributes,
)
}
.unwrap();
.map_err(instance_err("failed to get wayland display"))?;
let new_inner = Inner::create(
self.flags,
@ -1237,7 +1257,9 @@ impl Surface {
) -> Result<(), crate::SurfaceError> {
let gl = unsafe { context.get_without_egl_lock() };
let swapchain = self.swapchain.read();
let sc = swapchain.as_ref().unwrap();
let sc = swapchain.as_ref().ok_or(crate::SurfaceError::Other(
"Surface has no swap-chain configured",
))?;
self.egl
.instance
@ -1363,9 +1385,20 @@ impl crate::Surface for Surface {
}
(WindowKind::Unknown, Rwh::OhosNdk(handle)) => handle.native_window.as_ptr(),
(WindowKind::Wayland, Rwh::Wayland(handle)) => {
let library = &self.wsi.display_owner.as_ref().unwrap().library;
let library = &self
.wsi
.display_owner
.as_ref()
.ok_or(crate::SurfaceError::Other("No WSI display owner"))?
.library;
let wl_egl_window_create: libloading::Symbol<WlEglWindowCreateFun> =
unsafe { library.get(c"wl_egl_window_create".to_bytes()) }.unwrap();
unsafe { library.get(c"wl_egl_window_create".to_bytes()) }.map_err(
|_| {
crate::SurfaceError::Other(
"Failed to load `wl_egl_window_create",
)
},
)?;
let window =
unsafe { wl_egl_window_create(handle.surface.as_ptr(), 640, 480) }
.cast();
@ -1475,9 +1508,16 @@ impl crate::Surface for Surface {
};
if let Some(window) = wl_window {
let library = &self.wsi.display_owner.as_ref().unwrap().library;
let wl_egl_window_resize: libloading::Symbol<WlEglWindowResizeFun> =
unsafe { library.get(c"wl_egl_window_resize".to_bytes()) }.unwrap();
let library = &self
.wsi
.display_owner
.as_ref()
.ok_or(crate::SurfaceError::Other("No WSI display owner"))?
.library;
let wl_egl_window_resize: libloading::Symbol<WlEglWindowResizeFun> = unsafe {
library.get(c"wl_egl_window_resize".to_bytes())
}
.map_err(|_| crate::SurfaceError::Other("Failed to load `wl_egl_window_resize"))?;
unsafe {
wl_egl_window_resize(
window,
@ -1561,7 +1601,9 @@ impl crate::Surface for Surface {
_fence: &super::Fence,
) -> Result<Option<crate::AcquiredSurfaceTexture<super::Api>>, crate::SurfaceError> {
let swapchain = self.swapchain.read();
let sc = swapchain.as_ref().unwrap();
let sc = swapchain.as_ref().ok_or(crate::SurfaceError::Other(
"Surface has no swap-chain configured",
))?;
let texture = super::Texture {
inner: super::TextureInner::Renderbuffer {
raw: sc.renderbuffer,