egl: move surface creation into `NativeSurface`

This commit is contained in:
Victor Brekenfeld 2020-04-22 22:14:08 +02:00
parent 4647141770
commit 0267703e91
4 changed files with 63 additions and 26 deletions

View File

@ -5,15 +5,17 @@
//! //!
use crate::backend::drm::{Device, RawDevice, Surface}; use crate::backend::drm::{Device, RawDevice, Surface};
use crate::backend::egl::ffi;
use crate::backend::egl::native::{Backend, NativeDisplay, NativeSurface}; use crate::backend::egl::native::{Backend, NativeDisplay, NativeSurface};
use crate::backend::egl::{display::EGLDisplayHandle, ffi};
use crate::backend::egl::{wrap_egl_call, EGLError, Error as EglBackendError}; use crate::backend::egl::{wrap_egl_call, EGLError, Error as EglBackendError};
use super::{Error, GbmDevice, GbmSurface}; use super::{Error, GbmDevice, GbmSurface};
use drm::control::{connector, crtc, Device as ControlDevice, Mode}; use drm::control::{connector, crtc, Device as ControlDevice, Mode};
use gbm::AsRaw; use gbm::AsRaw;
use nix::libc::{c_int, c_void};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ptr;
/// Egl Gbm backend type /// Egl Gbm backend type
/// ///
@ -80,10 +82,18 @@ unsafe impl<D: RawDevice + ControlDevice + 'static> NativeDisplay<Gbm<D>> for Gb
} }
unsafe impl<D: RawDevice + 'static> NativeSurface for GbmSurface<D> { unsafe impl<D: RawDevice + 'static> NativeSurface for GbmSurface<D> {
type Error = Error<<<D as RawDevice>::Surface as Surface>::Error>; unsafe fn create(
&self,
fn ptr(&self) -> ffi::NativeWindowType { display: &EGLDisplayHandle,
self.0.surface.borrow().as_raw() as *const _ config_id: ffi::egl::types::EGLConfig,
surface_attributes: &[c_int],
) -> *const c_void {
ffi::egl::CreateWindowSurface(
display.handle,
config_id,
self.0.surface.borrow().as_raw() as *const _,
surface_attributes.as_ptr(),
)
} }
fn needs_recreation(&self) -> bool { fn needs_recreation(&self) -> bool {

View File

@ -30,8 +30,9 @@ use std::ops::Deref;
/// Wrapper around [`ffi::EGLDisplay`](ffi::egl::types::EGLDisplay) to ensure display is only destroyed /// Wrapper around [`ffi::EGLDisplay`](ffi::egl::types::EGLDisplay) to ensure display is only destroyed
/// once all resources bound to it have been dropped. /// once all resources bound to it have been dropped.
pub(crate) struct EGLDisplayHandle { pub struct EGLDisplayHandle {
handle: ffi::egl::types::EGLDisplay, /// ffi EGLDisplay ptr
pub handle: ffi::egl::types::EGLDisplay,
} }
impl Deref for EGLDisplayHandle { impl Deref for EGLDisplayHandle {

View File

@ -1,6 +1,7 @@
//! Type safe native types for safe context/surface creation //! Type safe native types for safe context/surface creation
use super::{ffi, wrap_egl_call, EGLError, Error}; use super::{display::EGLDisplayHandle, ffi, wrap_egl_call, EGLError, Error, SurfaceCreationError};
use nix::libc::{c_int, c_void};
#[cfg(feature = "backend_winit")] #[cfg(feature = "backend_winit")]
use wayland_egl as wegl; use wayland_egl as wegl;
@ -200,8 +201,13 @@ pub unsafe trait NativeSurface {
/// Error of the underlying surface /// Error of the underlying surface
type Error: std::error::Error; type Error: std::error::Error;
/// Return a raw pointer egl will accept for surface creation. /// Create an EGLSurface from the internal native type
fn ptr(&self) -> ffi::NativeWindowType; unsafe fn create(
&self,
display: &EGLDisplayHandle,
config_id: ffi::egl::types::EGLConfig,
surface_attributes: &[c_int],
) -> Result<*const c_void, SurfaceCreationError<Self::Error>>;
/// Will be called to check if any internal resources will need /// Will be called to check if any internal resources will need
/// to be recreated. Old resources must be used until `recreate` /// to be recreated. Old resources must be used until `recreate`
@ -247,8 +253,21 @@ unsafe impl NativeSurface for XlibWindow {
// type Error = !; (https://github.com/rust-lang/rust/issues/35121) // type Error = !; (https://github.com/rust-lang/rust/issues/35121)
type Error = Never; type Error = Never;
fn ptr(&self) -> ffi::NativeWindowType { unsafe fn create(
self.0 as *const _ &self,
display: &EGLDisplayHandle,
config_id: ffi::egl::types::EGLConfig,
surface_attributes: &[c_int],
) -> Result<*const c_void, SurfaceCreationError<Never>> {
wrap_egl_call(|| {
ffi::egl::CreateWindowSurface(
display.handle,
config_id,
self.0 as *const _,
surface_attributes.as_ptr(),
)
})
.map_err(SurfaceCreationError::EGLSurfaceCreationFailed)
} }
} }
@ -257,7 +276,20 @@ unsafe impl NativeSurface for wegl::WlEglSurface {
// type Error = !; // type Error = !;
type Error = Never; type Error = Never;
fn ptr(&self) -> ffi::NativeWindowType { unsafe fn create(
self.ptr() as *const _ &self,
display: &EGLDisplayHandle,
config_id: ffi::egl::types::EGLConfig,
surface_attributes: &[c_int],
) -> Result<*const c_void, SurfaceCreationError<Never>> {
wrap_egl_call(|| {
ffi::egl::CreateWindowSurface(
display.handle,
config_id,
self.ptr() as *const _,
surface_attributes.as_ptr(),
)
})
.map_err(SurfaceCreationError::EGLSurfaceCreationFailed)
} }
} }

View File

@ -69,9 +69,7 @@ impl<N: native::NativeSurface> EGLSurface<N> {
out out
}; };
let surface = wrap_egl_call(|| unsafe { let surface = unsafe { native.create(&*display, config, &surface_attributes)? };
ffi::egl::CreateWindowSurface(**display, config, native.ptr(), surface_attributes.as_ptr())
})?;
if surface == ffi::egl::NO_SURFACE { if surface == ffi::egl::NO_SURFACE {
return Err(EGLError::BadSurface); return Err(EGLError::BadSurface);
@ -112,16 +110,12 @@ impl<N: native::NativeSurface> EGLSurface<N> {
if !surface.is_null() { if !surface.is_null() {
let _ = unsafe { ffi::egl::DestroySurface(**self.display, surface as *const _) }; let _ = unsafe { ffi::egl::DestroySurface(**self.display, surface as *const _) };
} }
//TODO remove recreate
self.native.recreate();
self.surface.set(unsafe { self.surface.set(unsafe {
wrap_egl_call(|| { self.native
ffi::egl::CreateWindowSurface( .create(&*self.display, self.config_id, &self.surface_attributes)
**self.display, .map_err(SwapBuffersError::EGLCreateWindowSurface)?
self.config_id,
self.native.ptr(),
self.surface_attributes.as_ptr(),
)
})
.map_err(SwapBuffersError::EGLCreateWindowSurface)?
}); });
result.map_err(|err| { result.map_err(|err| {