summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wgpu-hal/src/gles/egl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wgpu-hal/src/gles/egl.rs')
-rw-r--r--third_party/rust/wgpu-hal/src/gles/egl.rs69
1 files changed, 53 insertions, 16 deletions
diff --git a/third_party/rust/wgpu-hal/src/gles/egl.rs b/third_party/rust/wgpu-hal/src/gles/egl.rs
index aa985d8121..f4bfcf5487 100644
--- a/third_party/rust/wgpu-hal/src/gles/egl.rs
+++ b/third_party/rust/wgpu-hal/src/gles/egl.rs
@@ -1,7 +1,8 @@
use glow::HasContext;
+use once_cell::sync::Lazy;
use parking_lot::{Mutex, MutexGuard, RwLock};
-use std::{ffi, os::raw, ptr, rc::Rc, sync::Arc, time::Duration};
+use std::{collections::HashMap, ffi, os::raw, ptr, rc::Rc, sync::Arc, time::Duration};
/// The amount of time to wait while trying to obtain a lock to the adapter context
const CONTEXT_LOCK_TIMEOUT_SECS: u64 = 1;
@@ -50,16 +51,6 @@ type WlEglWindowResizeFun = unsafe extern "system" fn(
type WlEglWindowDestroyFun = unsafe extern "system" fn(window: *const raw::c_void);
-#[cfg(target_os = "android")]
-extern "C" {
- pub fn ANativeWindow_setBuffersGeometry(
- window: *mut raw::c_void,
- width: i32,
- height: i32,
- format: i32,
- ) -> i32;
-}
-
type EglLabel = *const raw::c_void;
#[allow(clippy::upper_case_acronyms)]
@@ -161,7 +152,7 @@ impl Drop for DisplayOwner {
fn open_x_display() -> Option<DisplayOwner> {
log::debug!("Loading X11 library to get the current display");
unsafe {
- let library = libloading::Library::new("libX11.so").ok()?;
+ let library = find_library(&["libX11.so.6", "libX11.so"])?;
let func: libloading::Symbol<XOpenDisplayFun> = library.get(b"XOpenDisplay").unwrap();
let result = func(ptr::null());
ptr::NonNull::new(result).map(|ptr| DisplayOwner {
@@ -442,6 +433,45 @@ struct Inner {
srgb_kind: SrgbFrameBufferKind,
}
+// Different calls to `eglGetPlatformDisplay` may return the same `Display`, making it a global
+// state of all our `EglContext`s. This forces us to track the number of such context to prevent
+// terminating the display if it's currently used by another `EglContext`.
+static DISPLAYS_REFERENCE_COUNT: Lazy<Mutex<HashMap<usize, usize>>> = Lazy::new(Default::default);
+
+fn initialize_display(
+ egl: &EglInstance,
+ display: khronos_egl::Display,
+) -> Result<(i32, i32), khronos_egl::Error> {
+ let mut guard = DISPLAYS_REFERENCE_COUNT.lock();
+ *guard.entry(display.as_ptr() as usize).or_default() += 1;
+
+ // We don't need to check the reference count here since according to the `eglInitialize`
+ // documentation, initializing an already initialized EGL display connection has no effect
+ // besides returning the version numbers.
+ egl.initialize(display)
+}
+
+fn terminate_display(
+ egl: &EglInstance,
+ display: khronos_egl::Display,
+) -> Result<(), khronos_egl::Error> {
+ let key = &(display.as_ptr() as usize);
+ let mut guard = DISPLAYS_REFERENCE_COUNT.lock();
+ let count_ref = guard
+ .get_mut(key)
+ .expect("Attempted to decref a display before incref was called");
+
+ if *count_ref > 1 {
+ *count_ref -= 1;
+
+ Ok(())
+ } else {
+ guard.remove(key);
+
+ egl.terminate(display)
+ }
+}
+
impl Inner {
fn create(
flags: wgt::InstanceFlags,
@@ -449,7 +479,7 @@ impl Inner {
display: khronos_egl::Display,
force_gles_minor_version: wgt::Gles3MinorVersion,
) -> Result<Self, crate::InstanceError> {
- let version = egl.initialize(display).map_err(|e| {
+ let version = initialize_display(&egl, display).map_err(|e| {
crate::InstanceError::with_source(
String::from("failed to initialize EGL display connection"),
e,
@@ -618,7 +648,8 @@ impl Drop for Inner {
{
log::warn!("Error in destroy_context: {:?}", e);
}
- if let Err(e) = self.egl.instance.terminate(self.egl.display) {
+
+ if let Err(e) = terminate_display(&self.egl.instance, self.egl.display) {
log::warn!("Error in terminate: {:?}", e);
}
}
@@ -783,11 +814,12 @@ impl crate::Instance<super::Api> for Instance {
(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,
- std::ptr::null_mut(),
+ khronos_egl::DEFAULT_DISPLAY,
&[khronos_egl::ATTRIB_NONE],
)
}
@@ -863,7 +895,12 @@ impl crate::Instance<super::Api> for Instance {
.unwrap();
let ret = unsafe {
- ANativeWindow_setBuffersGeometry(handle.a_native_window.as_ptr(), 0, 0, format)
+ ndk_sys::ANativeWindow_setBuffersGeometry(
+ handle.a_native_window.as_ptr() as *mut ndk_sys::ANativeWindow,
+ 0,
+ 0,
+ format,
+ )
};
if ret != 0 {