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::egl::ffi;
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 super::{Error, GbmDevice, GbmSurface};
use drm::control::{connector, crtc, Device as ControlDevice, Mode};
use gbm::AsRaw;
use nix::libc::{c_int, c_void};
use std::marker::PhantomData;
use std::ptr;
/// 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> {
type Error = Error<<<D as RawDevice>::Surface as Surface>::Error>;
fn ptr(&self) -> ffi::NativeWindowType {
self.0.surface.borrow().as_raw() as *const _
unsafe fn create(
&self,
display: &EGLDisplayHandle,
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 {

View File

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

View File

@ -1,6 +1,7 @@
//! 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")]
use wayland_egl as wegl;
@ -200,8 +201,13 @@ pub unsafe trait NativeSurface {
/// Error of the underlying surface
type Error: std::error::Error;
/// Return a raw pointer egl will accept for surface creation.
fn ptr(&self) -> ffi::NativeWindowType;
/// Create an EGLSurface from the internal native type
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
/// 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 = Never;
fn ptr(&self) -> ffi::NativeWindowType {
self.0 as *const _
unsafe fn create(
&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 = Never;
fn ptr(&self) -> ffi::NativeWindowType {
self.ptr() as *const _
unsafe fn create(
&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
};
let surface = wrap_egl_call(|| unsafe {
ffi::egl::CreateWindowSurface(**display, config, native.ptr(), surface_attributes.as_ptr())
})?;
let surface = unsafe { native.create(&*display, config, &surface_attributes)? };
if surface == ffi::egl::NO_SURFACE {
return Err(EGLError::BadSurface);
@ -112,16 +110,12 @@ impl<N: native::NativeSurface> EGLSurface<N> {
if !surface.is_null() {
let _ = unsafe { ffi::egl::DestroySurface(**self.display, surface as *const _) };
}
//TODO remove recreate
self.native.recreate();
self.surface.set(unsafe {
wrap_egl_call(|| {
ffi::egl::CreateWindowSurface(
**self.display,
self.config_id,
self.native.ptr(),
self.surface_attributes.as_ptr(),
)
})
.map_err(SwapBuffersError::EGLCreateWindowSurface)?
self.native
.create(&*self.display, self.config_id, &self.surface_attributes)
.map_err(SwapBuffersError::EGLCreateWindowSurface)?
});
result.map_err(|err| {