use super::{error::*, ffi};
use crate::backend::graphics::SwapBuffersError;
#[cfg(feature = "backend_winit")]
use std::ptr;
#[cfg(feature = "backend_winit")]
use wayland_client::egl as wegl;
#[cfg(feature = "backend_winit")]
use winit::os::unix::WindowExt;
#[cfg(feature = "backend_winit")]
use winit::Window as WinitWindow;
pub trait Backend {
type Surface: NativeSurface;
unsafe fn get_display<F: Fn(&str) -> bool>(
display: ffi::NativeDisplayType,
has_dp_extension: F,
log: ::slog::Logger,
) -> ffi::egl::types::EGLDisplay;
}
#[cfg(feature = "backend_winit")]
pub enum Wayland {}
#[cfg(feature = "backend_winit")]
impl Backend for Wayland {
type Surface = wegl::WlEglSurface;
unsafe fn get_display<F>(
display: ffi::NativeDisplayType,
has_dp_extension: F,
log: ::slog::Logger,
) -> ffi::egl::types::EGLDisplay
where
F: Fn(&str) -> bool,
{
if has_dp_extension("EGL_KHR_platform_wayland") && ffi::egl::GetPlatformDisplay::is_loaded() {
trace!(log, "EGL Display Initialization via EGL_KHR_platform_wayland");
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_WAYLAND_KHR, display as *mut _, ptr::null())
} else if has_dp_extension("EGL_EXT_platform_wayland") && ffi::egl::GetPlatformDisplayEXT::is_loaded()
{
trace!(log, "EGL Display Initialization via EGL_EXT_platform_wayland");
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_WAYLAND_EXT, display as *mut _, ptr::null())
} else {
trace!(log, "Default EGL Display Initialization via GetDisplay");
ffi::egl::GetDisplay(display as *mut _)
}
}
}
#[cfg(feature = "backend_winit")]
pub struct XlibWindow(u64);
#[cfg(feature = "backend_winit")]
pub enum X11 {}
#[cfg(feature = "backend_winit")]
impl Backend for X11 {
type Surface = XlibWindow;
unsafe fn get_display<F>(
display: ffi::NativeDisplayType,
has_dp_extension: F,
log: ::slog::Logger,
) -> ffi::egl::types::EGLDisplay
where
F: Fn(&str) -> bool,
{
if has_dp_extension("EGL_KHR_platform_x11") && ffi::egl::GetPlatformDisplay::is_loaded() {
trace!(log, "EGL Display Initialization via EGL_KHR_platform_x11");
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null())
} else if has_dp_extension("EGL_EXT_platform_x11") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
trace!(log, "EGL Display Initialization via EGL_EXT_platform_x11");
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null())
} else {
trace!(log, "Default EGL Display Initialization via GetDisplay");
ffi::egl::GetDisplay(display as *mut _)
}
}
}
pub unsafe trait NativeDisplay<B: Backend> {
type Arguments;
type Error: ::std::error::Error + Send + 'static;
fn is_backend(&self) -> bool;
fn ptr(&self) -> Result<ffi::NativeDisplayType>;
fn create_surface(&mut self, args: Self::Arguments) -> ::std::result::Result<B::Surface, Self::Error>;
}
#[cfg(feature = "backend_winit")]
unsafe impl NativeDisplay<X11> for WinitWindow {
type Arguments = ();
type Error = Error;
fn is_backend(&self) -> bool {
self.get_xlib_display().is_some()
}
fn ptr(&self) -> Result<ffi::NativeDisplayType> {
self.get_xlib_display()
.map(|ptr| ptr as *const _)
.ok_or(ErrorKind::NonMatchingBackend("X11").into())
}
fn create_surface(&mut self, _args: ()) -> Result<XlibWindow> {
self.get_xlib_window()
.map(XlibWindow)
.ok_or(ErrorKind::NonMatchingBackend("X11").into())
}
}
#[cfg(feature = "backend_winit")]
unsafe impl NativeDisplay<Wayland> for WinitWindow {
type Arguments = ();
type Error = Error;
fn is_backend(&self) -> bool {
self.get_wayland_display().is_some()
}
fn ptr(&self) -> Result<ffi::NativeDisplayType> {
self.get_wayland_display()
.map(|ptr| ptr as *const _)
.ok_or(ErrorKind::NonMatchingBackend("Wayland").into())
}
fn create_surface(&mut self, _args: ()) -> Result<wegl::WlEglSurface> {
if let Some(surface) = self.get_wayland_surface() {
let size = self.get_inner_size().unwrap();
Ok(unsafe {
wegl::WlEglSurface::new_from_raw(surface as *mut _, size.width as i32, size.height as i32)
})
} else {
bail!(ErrorKind::NonMatchingBackend("Wayland"))
}
}
}
pub unsafe trait NativeSurface {
fn ptr(&self) -> ffi::NativeWindowType;
fn needs_recreation(&self) -> bool {
false
}
fn recreate(&self) -> bool {
true
}
fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> {
Ok(())
}
}
#[cfg(feature = "backend_winit")]
unsafe impl NativeSurface for XlibWindow {
fn ptr(&self) -> ffi::NativeWindowType {
self.0 as *const _
}
}
#[cfg(feature = "backend_winit")]
unsafe impl NativeSurface for wegl::WlEglSurface {
fn ptr(&self) -> ffi::NativeWindowType {
self.ptr() as *const _
}
}