Let GLES/Angle path compile on macOS

This commit is contained in:
Dzmitry Malyshau 2021-12-05 16:37:57 -05:00 committed by Dzmitry Malyshau
parent ab28009d80
commit e867a7434c
6 changed files with 69 additions and 76 deletions

View File

@ -66,19 +66,20 @@ We have a [wiki](https://github.com/gfx-rs/wgpu/wiki) that serves as a knowledge
## Supported Platforms ## Supported Platforms
API | Windows | Linux & Android | macOS & iOS | API | Windows | Linux & Android | macOS & iOS |
----- | ----------------------------- | ------------------------- | ------------------ | ----- | ----------------------------- | ------------------------- | ------------------- |
Vulkan | :white_check_mark: | :white_check_mark: | | Vulkan | :white_check_mark: | :white_check_mark: | |
Metal | | | :white_check_mark: | Metal | | | :white_check_mark: |
DX12 | :white_check_mark: (W10 only) | | | DX12 | :white_check_mark: (W10 only) | | |
DX11 | :hammer_and_wrench: | | | DX11 | :hammer_and_wrench: | | |
GLES3 | :triangular_ruler: | :ok: + :triangular_ruler: | | GLES3 | | :ok: | |
Angle | :ok: | :ok: | :hammer_and_wrench: |
:white_check_mark: = First Class Support — :ok: = Best Effort Support — :triangular_ruler: = via [Angle](angleproject.org) — :hammer_and_wrench: = Unsupported, but support in progress :white_check_mark: = First Class Support — :ok: = Best Effort Support — :hammer_and_wrench: = Unsupported, but support in progress
### Angle ### Angle
Angle is a translation layer from GLES to other backends, developed by Google. [Angle](angleproject.org) is a translation layer from GLES to other backends, developed by Google.
We support running our GLES3 backend over it in order to reach platforms with GLES2 or DX11 support, which aren't accessible otherwise. We support running our GLES3 backend over it in order to reach platforms with GLES2 or DX11 support, which aren't accessible otherwise.
In order to run with Angle, "angle" feature has to be enabled, and Angle libraries placed in a location visible to the application. In order to run with Angle, "angle" feature has to be enabled, and Angle libraries placed in a location visible to the application.
These binaries can be downloaded from [gfbuild-angle](https://github.com/DileSoft/gfbuild-angle) artifacts. These binaries can be downloaded from [gfbuild-angle](https://github.com/DileSoft/gfbuild-angle) artifacts.

View File

@ -964,6 +964,7 @@ impl HalApi for hal::api::Metal {
Instance { Instance {
name: name.to_owned(), name: name.to_owned(),
metal: Some(hal_instance), metal: Some(hal_instance),
..Default::default()
} }
} }
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> { fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> {

View File

@ -496,6 +496,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}, },
//acquired_texture: None, //acquired_texture: None,
}), }),
#[cfg(gl)]
gl: None,
}; };
let mut token = Token::root(); let mut token = Token::root();

View File

@ -14,6 +14,8 @@
clippy::needless_lifetimes, clippy::needless_lifetimes,
// No need for defaults in the internal types. // No need for defaults in the internal types.
clippy::new_without_default, clippy::new_without_default,
// Needless updates are more scaleable, easier to play with features.
clippy::needless_update,
// For some reason `rustc` can warn about these in const generics even // For some reason `rustc` can warn about these in const generics even
// though they are required. // though they are required.
unused_braces, unused_braces,

View File

@ -422,18 +422,17 @@ impl Inner {
} }
} }
if needs_robustness { if needs_robustness {
//Note: we specifically check the extension first, and then the core. //Note: the core version can fail if robustness is not supported
// This is because the core version can fail if robustness is not supported
// (regardless of whether the extension is supported!). // (regardless of whether the extension is supported!).
// In fact, Angle does precisely that awful behavior. // In fact, Angle does precisely that awful behavior, so we don't try it there.
if display_extensions.contains("EGL_EXT_create_context_robustness") { if version >= (1, 5) && !display_extensions.contains("EGL_ANGLE_") {
log::info!("\tEGL context: +robust access EXT");
context_attributes.push(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
context_attributes.push(egl::TRUE as _);
} else if version >= (1, 5) {
log::info!("\tEGL context: +robust access"); log::info!("\tEGL context: +robust access");
context_attributes.push(egl::CONTEXT_OPENGL_ROBUST_ACCESS); context_attributes.push(egl::CONTEXT_OPENGL_ROBUST_ACCESS);
context_attributes.push(egl::TRUE as _); context_attributes.push(egl::TRUE as _);
} else if display_extensions.contains("EGL_EXT_create_context_robustness") {
log::info!("\tEGL context: +robust access EXT");
context_attributes.push(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
context_attributes.push(egl::TRUE as _);
} else { } else {
//Note: we aren't trying `EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR` //Note: we aren't trying `EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR`
// because it's for desktop GL only, not GLES. // because it's for desktop GL only, not GLES.
@ -501,16 +500,17 @@ enum WindowKind {
Wayland, Wayland,
X11, X11,
AngleX11, AngleX11,
Unknown,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct WindowSystemInterface { struct WindowSystemInterface {
library: Arc<libloading::Library>, library: Option<Arc<libloading::Library>>,
kind: WindowKind, kind: WindowKind,
} }
pub struct Instance { pub struct Instance {
wsi: Option<WindowSystemInterface>, wsi: WindowSystemInterface,
flags: crate::InstanceFlags, flags: crate::InstanceFlags,
inner: Mutex<Inner>, inner: Mutex<Inner>,
} }
@ -522,6 +522,8 @@ impl crate::Instance<super::Api> for Instance {
unsafe fn init(desc: &crate::InstanceDescriptor) -> Result<Self, crate::InstanceError> { unsafe fn init(desc: &crate::InstanceDescriptor) -> Result<Self, crate::InstanceError> {
let egl_result = if cfg!(windows) { let egl_result = if cfg!(windows) {
egl::DynamicInstance::<egl::EGL1_4>::load_required_from_filename("libEGL.dll") egl::DynamicInstance::<egl::EGL1_4>::load_required_from_filename("libEGL.dll")
} else if cfg!(any(target_os = "macos", target_os = "ios")) {
egl::DynamicInstance::<egl::EGL1_4>::load_required_from_filename("libEGL.dylib")
} else { } else {
egl::DynamicInstance::<egl::EGL1_4>::load_required() egl::DynamicInstance::<egl::EGL1_4>::load_required()
}; };
@ -554,13 +556,13 @@ impl crate::Instance<super::Api> for Instance {
} else { } else {
None None
}; };
let angle_display_library = if client_ext_str.contains(&"EGL_ANGLE_platform_angle") { let angle_x11_display_library = if client_ext_str.contains(&"EGL_ANGLE_platform_angle") {
open_x_display() open_x_display()
} else { } else {
None None
}; };
let (display, wsi) = if let (Some(library), Some(egl)) = let (display, wsi_library, wsi_kind) = if let (Some(library), Some(egl)) =
(wayland_library, egl.upcast::<egl::EGL1_5>()) (wayland_library, egl.upcast::<egl::EGL1_5>())
{ {
log::info!("Using Wayland platform"); log::info!("Using Wayland platform");
@ -572,13 +574,7 @@ impl crate::Instance<super::Api> for Instance {
&display_attributes, &display_attributes,
) )
.unwrap(); .unwrap();
( (display, Some(Arc::new(library)), WindowKind::Wayland)
display,
Some(WindowSystemInterface {
library: Arc::new(library),
kind: WindowKind::Wayland,
}),
)
} else if let (Some((display, library)), Some(egl)) = } else if let (Some((display, library)), Some(egl)) =
(x11_display_library, egl.upcast::<egl::EGL1_5>()) (x11_display_library, egl.upcast::<egl::EGL1_5>())
{ {
@ -587,15 +583,9 @@ impl crate::Instance<super::Api> for Instance {
let display = egl let display = egl
.get_platform_display(EGL_PLATFORM_X11_KHR, display.as_ptr(), &display_attributes) .get_platform_display(EGL_PLATFORM_X11_KHR, display.as_ptr(), &display_attributes)
.unwrap(); .unwrap();
( (display, Some(Arc::new(library)), WindowKind::X11)
display,
Some(WindowSystemInterface {
library: Arc::new(library),
kind: WindowKind::X11,
}),
)
} else if let (Some((display, library)), Some(egl)) = } else if let (Some((display, library)), Some(egl)) =
(angle_display_library, egl.upcast::<egl::EGL1_5>()) (angle_x11_display_library, egl.upcast::<egl::EGL1_5>())
{ {
log::info!("Using Angle platform with X11"); log::info!("Using Angle platform with X11");
let display_attributes = [ let display_attributes = [
@ -616,17 +606,11 @@ impl crate::Instance<super::Api> for Instance {
&display_attributes, &display_attributes,
) )
.unwrap(); .unwrap();
( (display, Some(Arc::new(library)), WindowKind::AngleX11)
display,
Some(WindowSystemInterface {
library: Arc::new(library),
kind: WindowKind::AngleX11,
}),
)
} else { } else {
log::info!("Using default platform"); log::info!("Using default platform");
let display = egl.get_display(egl::DEFAULT_DISPLAY).unwrap(); let display = egl.get_display(egl::DEFAULT_DISPLAY).unwrap();
(display, None) (display, None, WindowKind::Unknown)
}; };
if desc.flags.contains(crate::InstanceFlags::VALIDATION) if desc.flags.contains(crate::InstanceFlags::VALIDATION)
@ -652,7 +636,10 @@ impl crate::Instance<super::Api> for Instance {
let inner = Inner::create(desc.flags, egl, display)?; let inner = Inner::create(desc.flags, egl, display)?;
Ok(Instance { Ok(Instance {
wsi, wsi: WindowSystemInterface {
library: wsi_library,
kind: wsi_kind,
},
flags: desc.flags, flags: desc.flags,
inner: Mutex::new(inner), inner: Mutex::new(inner),
}) })
@ -674,6 +661,7 @@ impl crate::Instance<super::Api> for Instance {
Rwh::Xlib(_) => {} Rwh::Xlib(_) => {}
Rwh::Xcb(_) => {} Rwh::Xcb(_) => {}
Rwh::Win32(_) => {} Rwh::Win32(_) => {}
Rwh::AppKit(_) => {}
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
Rwh::AndroidNdk(handle) => { Rwh::AndroidNdk(handle) => {
let format = inner let format = inner
@ -814,7 +802,7 @@ pub struct Swapchain {
#[derive(Debug)] #[derive(Debug)]
pub struct Surface { pub struct Surface {
egl: Arc<egl::DynamicInstance<egl::EGL1_4>>, egl: Arc<egl::DynamicInstance<egl::EGL1_4>>,
wsi: Option<WindowSystemInterface>, wsi: WindowSystemInterface,
config: egl::Config, config: egl::Config,
display: egl::Display, display: egl::Display,
context: egl::Context, context: egl::Context,
@ -921,28 +909,27 @@ impl crate::Surface<super::Api> for Surface {
let (surface, wl_window) = match self.unconfigure_impl(device) { let (surface, wl_window) = match self.unconfigure_impl(device) {
Some(pair) => pair, Some(pair) => pair,
None => { None => {
let wsi_kind = self.wsi.as_ref().map(|wsi| wsi.kind);
let mut wl_window = None; let mut wl_window = None;
let (mut temp_xlib_handle, mut temp_xcb_handle); let (mut temp_xlib_handle, mut temp_xcb_handle);
#[allow(trivial_casts)] #[allow(trivial_casts)]
let native_window_ptr = match (wsi_kind, self.raw_window_handle) { let native_window_ptr = match (self.wsi.kind, self.raw_window_handle) {
(None | Some(WindowKind::X11), Rwh::Xlib(handle)) => { (WindowKind::Unknown | WindowKind::X11, Rwh::Xlib(handle)) => {
temp_xlib_handle = handle.window; temp_xlib_handle = handle.window;
&mut temp_xlib_handle as *mut _ as *mut std::ffi::c_void &mut temp_xlib_handle as *mut _ as *mut std::ffi::c_void
} }
(Some(WindowKind::AngleX11), Rwh::Xlib(handle)) => { (WindowKind::AngleX11, Rwh::Xlib(handle)) => {
handle.window as *mut std::ffi::c_void handle.window as *mut std::ffi::c_void
} }
(None | Some(WindowKind::X11), Rwh::Xcb(handle)) => { (WindowKind::Unknown | WindowKind::X11, Rwh::Xcb(handle)) => {
temp_xcb_handle = handle.window; temp_xcb_handle = handle.window;
&mut temp_xcb_handle as *mut _ as *mut std::ffi::c_void &mut temp_xcb_handle as *mut _ as *mut std::ffi::c_void
} }
(Some(WindowKind::AngleX11), Rwh::Xcb(handle)) => { (WindowKind::AngleX11, Rwh::Xcb(handle)) => {
handle.window as *mut std::ffi::c_void handle.window as *mut std::ffi::c_void
} }
(None, Rwh::AndroidNdk(handle)) => handle.a_native_window, (WindowKind::Unknown, Rwh::AndroidNdk(handle)) => handle.a_native_window,
(Some(WindowKind::Wayland), Rwh::Wayland(handle)) => { (WindowKind::Wayland, Rwh::Wayland(handle)) => {
let library = &self.wsi.as_ref().unwrap().library; let library = self.wsi.library.as_ref().unwrap();
let wl_egl_window_create: libloading::Symbol<WlEglWindowCreateFun> = let wl_egl_window_create: libloading::Symbol<WlEglWindowCreateFun> =
library.get(b"wl_egl_window_create").unwrap(); library.get(b"wl_egl_window_create").unwrap();
let window = wl_egl_window_create(handle.surface, 640, 480) as *mut _ let window = wl_egl_window_create(handle.surface, 640, 480) as *mut _
@ -959,11 +946,12 @@ impl crate::Surface<super::Api> for Surface {
wl_window = Some(window); wl_window = Some(window);
window window
} }
(None, Rwh::Win32(handle)) => handle.hwnd, (WindowKind::Unknown, Rwh::Win32(handle)) => handle.hwnd,
(WindowKind::Unknown, Rwh::AppKit(handle)) => handle.ns_view,
_ => { _ => {
log::warn!( log::warn!(
"Initialized platform {:?} doesn't work with window {:?}", "Initialized platform {:?} doesn't work with window {:?}",
wsi_kind, self.wsi.kind,
self.raw_window_handle self.raw_window_handle
); );
return Err(crate::SurfaceError::Other("incompatible window kind")); return Err(crate::SurfaceError::Other("incompatible window kind"));
@ -977,7 +965,7 @@ impl crate::Surface<super::Api> for Surface {
// Some drivers just fail on surface creation seeing `EGL_SINGLE_BUFFER`. // Some drivers just fail on surface creation seeing `EGL_SINGLE_BUFFER`.
if cfg!(target_os = "android") if cfg!(target_os = "android")
|| cfg!(windows) || cfg!(windows)
|| wsi_kind == Some(WindowKind::AngleX11) || self.wsi.kind == WindowKind::AngleX11
{ {
egl::BACK_BUFFER egl::BACK_BUFFER
} else { } else {
@ -998,30 +986,31 @@ impl crate::Surface<super::Api> for Surface {
attributes.push(egl::ATTRIB_NONE as i32); attributes.push(egl::ATTRIB_NONE as i32);
// Careful, we can still be in 1.4 version even if `upcast` succeeds // Careful, we can still be in 1.4 version even if `upcast` succeeds
let raw_result = if let Some(egl) = self.egl.upcast::<egl::EGL1_5>() { let raw_result = match self.egl.upcast::<egl::EGL1_5>() {
let attributes_usize = attributes Some(egl) if self.wsi.kind != WindowKind::Unknown => {
.into_iter() let attributes_usize = attributes
.map(|v| v as usize) .into_iter()
.collect::<Vec<_>>(); .map(|v| v as usize)
egl.create_platform_window_surface( .collect::<Vec<_>>();
self.display, egl.create_platform_window_surface(
self.config, self.display,
native_window_ptr, self.config,
&attributes_usize, native_window_ptr,
) &attributes_usize,
} else { )
self.egl.create_window_surface( }
_ => self.egl.create_window_surface(
self.display, self.display,
self.config, self.config,
native_window_ptr, native_window_ptr,
Some(&attributes), Some(&attributes),
) ),
}; };
match raw_result { match raw_result {
Ok(raw) => (raw, wl_window), Ok(raw) => (raw, wl_window),
Err(e) => { Err(e) => {
log::warn!("Error in create_platform_window_surface: {:?}", e); log::warn!("Error in create_window_surface: {:?}", e);
return Err(crate::SurfaceError::Lost); return Err(crate::SurfaceError::Lost);
} }
} }
@ -1069,9 +1058,9 @@ impl crate::Surface<super::Api> for Surface {
if let Some(window) = wl_window { if let Some(window) = wl_window {
let wl_egl_window_destroy: libloading::Symbol<WlEglWindowDestroyFun> = self let wl_egl_window_destroy: libloading::Symbol<WlEglWindowDestroyFun> = self
.wsi .wsi
.library
.as_ref() .as_ref()
.expect("unsupported window") .expect("unsupported window")
.library
.get(b"wl_egl_window_destroy") .get(b"wl_egl_window_destroy")
.unwrap(); .unwrap();
wl_egl_window_destroy(window); wl_egl_window_destroy(window);

View File

@ -51,8 +51,6 @@
compile_error!("Metal API enabled on non-Apple OS. If your project is not using resolver=\"2\" in Cargo.toml, it should."); compile_error!("Metal API enabled on non-Apple OS. If your project is not using resolver=\"2\" in Cargo.toml, it should.");
#[cfg(all(feature = "dx12", not(windows)))] #[cfg(all(feature = "dx12", not(windows)))]
compile_error!("DX12 API enabled on non-Windows OS. If your project is not using resolver=\"2\" in Cargo.toml, it should."); compile_error!("DX12 API enabled on non-Windows OS. If your project is not using resolver=\"2\" in Cargo.toml, it should.");
#[cfg(all(feature = "gles", any(target_os = "macos", target_os = "ios")))]
compile_error!("Gles API enabled on Apple OS. If your project is not using resolver=\"2\" in Cargo.toml, it should.");
#[cfg(all(feature = "dx12", windows))] #[cfg(all(feature = "dx12", windows))]
mod dx12; mod dx12;