use super::ffi;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("The requested OpenGL version {0:?} is not supported")]
OpenGlVersionNotSupported((u8, u8)),
#[error("The EGL implementation does not support creating OpenGL ES contexts. Err: {0:?}")]
OpenGlesNotSupported(#[source] Option<EGLError>),
#[error("No available pixel format matched the criteria")]
NoAvailablePixelFormat,
#[error("The expected backend '{0:?}' does not match the runtime")]
NonMatchingBackend(&'static str),
#[error("Display creation failed with error: {0:}")]
DisplayCreationError(#[source] EGLError),
#[error("Unable to obtain a valid EGL Display.")]
DisplayNotSupported,
#[error("Failed to initialize EGL. Err: {0:}")]
InitFailed(#[source] EGLError),
#[error("Failed to configure the EGL context")]
ConfigFailed(#[source] EGLError),
#[error("Context creation failed as one or more requirements could not be met. Try removing some gl attributes or pixel format requirements. Err: {0:}")]
CreationFailed(#[source] EGLError),
#[error("None of the following EGL extensions is supported by the underlying EGL implementation, at least one is required: {0:?}")]
EglExtensionNotSupported(&'static [&'static str]),
#[error("Only one EGLDisplay may be bound to a given `WlDisplay` at any time")]
OtherEGLDisplayAlreadyBound(#[source] EGLError),
#[error("No EGLDisplay is currently bound to this `WlDisplay`")]
NoEGLDisplayBound,
#[error("Index of plane is out of bounds for `EGLBuffer`")]
PlaneIndexOutOfBounds,
#[error("Failed to create `EGLBuffer` from the buffer")]
EGLImageCreationFailed,
}
#[derive(thiserror::Error, Debug)]
pub enum EGLError {
#[error(
"EGL is not initialized, or could not be initialized, for the specified EGL display connection."
)]
NotInitialized,
#[error("EGL cannot access a requested resource (for example a context is bound in another thread).")]
BadAccess,
#[error("EGL failed to allocate resources for the requested operation.")]
BadAlloc,
#[error("An unrecognized attribute or attribute value was passed in the attribute list.")]
BadAttribute,
#[error("An EGLContext argument does not name a valid EGL rendering context.")]
BadContext,
#[error("An EGLConfig argument does not name a valid EGL frame buffer configuration.")]
BadConfig,
#[error("The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid.")]
BadCurrentSurface,
#[error("An EGLDisplay argument does not name a valid EGL display connection.")]
BadDisplay,
#[error("An EGLSurface argument does not name a valid surface (window, pixel buffer or pixmap) configured for GL rendering.")]
BadSurface,
#[error("Arguments are inconsistent (for example, a valid context requires buffers not supplied by a valid surface).")]
BadMatch,
#[error("One or more argument values are invalid.")]
BadParameter,
#[error("A NativePixmapType argument does not refer to a valid native pixmap.")]
BadNativePixmap,
#[error("A NativeWindowType argument does not refer to a valid native window.")]
BadNativeWindow,
#[cfg(feature = "backend_drm_eglstream")]
#[error("The EGL operation failed due to temporary unavailability of a requested resource, but the arguments were otherwise valid, and a subsequent attempt may succeed.")]
ResourceBusy,
#[error("A power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering.")]
ContextLost,
#[error("An unknown error ({0:x})")]
Unknown(u32),
}
impl From<u32> for EGLError {
fn from(value: u32) -> Self {
match value {
ffi::egl::NOT_INITIALIZED => EGLError::NotInitialized,
ffi::egl::BAD_ACCESS => EGLError::BadAccess,
ffi::egl::BAD_ALLOC => EGLError::BadAlloc,
ffi::egl::BAD_ATTRIBUTE => EGLError::BadAttribute,
ffi::egl::BAD_CONTEXT => EGLError::BadContext,
ffi::egl::BAD_CURRENT_SURFACE => EGLError::BadCurrentSurface,
ffi::egl::BAD_DISPLAY => EGLError::BadDisplay,
ffi::egl::BAD_SURFACE => EGLError::BadSurface,
ffi::egl::BAD_MATCH => EGLError::BadMatch,
ffi::egl::BAD_PARAMETER => EGLError::BadParameter,
ffi::egl::BAD_NATIVE_PIXMAP => EGLError::BadNativePixmap,
ffi::egl::BAD_NATIVE_WINDOW => EGLError::BadNativeWindow,
#[cfg(feature = "backend_drm_eglstream")]
ffi::egl::RESOURCE_BUSY_EXT => EGLError::ResourceBusy,
ffi::egl::CONTEXT_LOST => EGLError::ContextLost,
x => EGLError::Unknown(x),
}
}
}
impl EGLError {
pub(super) fn from_last_call() -> Result<(), EGLError> {
match unsafe { ffi::egl::GetError() as u32 } {
ffi::egl::SUCCESS => Ok(()),
x => Err(EGLError::from(x)),
}
}
}
pub fn wrap_egl_call<R, F: FnOnce() -> R>(call: F) -> Result<R, EGLError> {
let res = call();
EGLError::from_last_call().map(|()| res)
}