use super::sys::*;
use super::*;
use crate::gl::GlConfig;
use std::ffi::c_void;
use std::ptr::NonNull;
use x11rb::protocol::xproto::Window;
pub struct EglSurface {
display: EglDisplay,
raw: NonNull<c_void>,
}
impl EglSurface {
pub(super) fn create(
display: &EglDisplay, config: EglConfig, window: Window, gl_config: &GlConfig,
) -> Result<EglSurface, EglError> {
let raw = display.egl().create_surface(display, config, window, gl_config)?;
Ok(Self { display: display.clone(), raw })
}
pub fn display(&self) -> &EglDisplay {
&self.display
}
pub fn as_raw(&self) -> *mut c_void {
self.raw.as_ptr()
}
pub fn swap_buffers(&self) -> Result<(), EglError> {
self.display().egl().swap_buffers(self)
}
}
impl Drop for EglSurface {
fn drop(&mut self) {
if let Err(e) = unsafe { self.display.egl().destroy_surface(self) } {
crate::warn!("Failed to destroy EGL surface: {e}");
}
}
}
impl Egl {
fn get_surface_attribs(gl_config: &GlConfig) -> [Int; 3] {
#[rustfmt::skip]
let fb_attribs = [
EGL_GL_COLORSPACE, if gl_config.srgb { EGL_GL_COLORSPACE_SRGB } else { EGL_GL_COLORSPACE_LINEAR },
EGL_NONE,
];
fb_attribs
}
fn create_surface(
&self, display: &EglDisplay, config: EglConfig, window: Window, gl_config: &GlConfig,
) -> Result<NonNull<c_void>, EglError> {
let attribs = Self::get_surface_attribs(gl_config);
let result = unsafe {
(self.inner.functions.eglCreateWindowSurface)(
display.as_raw(),
config.0.as_ptr(),
window as _,
attribs.as_ptr(),
)
};
NonNull::new(result).ok_or_else(|| EglError::from_last_error(self))
}
fn swap_buffers(&self, surface: &EglSurface) -> Result<(), EglError> {
let result = unsafe {
(self.inner.functions.eglSwapBuffers)(surface.display().as_raw(), surface.as_raw())
};
if result == FALSE {
Err(EglError::from_last_error(self))
} else {
Ok(())
}
}
unsafe fn destroy_surface(&self, surface: &EglSurface) -> Result<(), EglError> {
let result = unsafe {
(self.inner.functions.eglDestroySurface)(surface.display().as_raw(), surface.as_raw())
};
if result == FALSE {
Err(EglError::from_last_error(self))
} else {
Ok(())
}
}
}