<NME> error.rs
<BEF> use super::ffi;

#[derive(thiserror::Error, Debug)]
/// EGL errors
pub enum Error {
    /// The requested OpenGL version is not supported
    #[error("The requested OpenGL version {0:?} is not supported")]
    OpenGlVersionNotSupported((u8, u8)),
    /// The EGL implementation does not support creating OpenGL ES contexts
    #[error("The EGL implementation does not support creating OpenGL ES contexts. Err: {0:?}")]
    OpenGlesNotSupported(#[source] Option<EGLError>),
    /// No available pixel format matched the criteria
    #[error("No available pixel format matched the criteria")]
    NoAvailablePixelFormat,
    /// Backend does not match the context type
    #[error("The expected backend '{0:?}' does not match the runtime")]
    NonMatchingBackend(&'static str),
    /// Display creation failed
    #[error("Display creation failed with error: {0:}")]
    DisplayCreationError(#[source] EGLError),
    /// Display query result invalid
    #[error("Display query result invalid")]
    DisplayQueryResultInvalid,
    /// Unable to obtain a valid EGL Display
    #[error("Unable to obtain a valid EGL Display.")]
    DisplayNotSupported,
    /// `eglInitialize` returned an error
    #[error("Failed to initialize EGL. Err: {0:}")]
    InitFailed(#[source] EGLError),
    /// Failed to configure the EGL context
    #[error("Failed to configure the EGL context")]
    ConfigFailed(#[source] EGLError),
    /// Context creation failed as one or more requirements could not be met. Try removing some gl attributes or pixel format requirements
    #[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),
    /// The required EGL extension is not supported by the underlying EGL implementation
    #[error("None of the following EGL extensions is supported by the underlying EGL implementation, at least one is required: {0:?}")]
    EglExtensionNotSupported(&'static [&'static str]),
    /// No EGLDisplay is currently bound to this `WlDisplay`
    #[error("No EGLDisplay is currently bound to this `WlDisplay`")]
    NoEGLDisplayBound,
    /// Index of plane is out of bounds for `EGLBuffer`
    #[error("Index of plane is out of bounds for `EGLBuffer`")]
    PlaneIndexOutOfBounds,
    /// Failed to create `EGLBuffer` from the buffer
    #[error("Failed to create `EGLBuffer` from the buffer")]
    EGLImageCreationFailed,
    /// Failed to query the available `EGLDevice`s
    #[error("Failed to query the available `EGLDevice`s")]
    QueryDevices(#[source] EGLError),
    /// Failed to query the available `EGLDevice`s
    #[error("Failed to query the available `EGLDevice`s")]
    QueryDevices(#[source] EGLError),
    /// Failed to query device properties
    #[error("Failed to query the requested device property")]
    QueryDeviceProperty(#[source] EGLError),
    /// The device does not have the given property
    #[error("The device does not have the given property")]
    EmptyDeviceProperty,
}

/// Raw EGL error
#[derive(thiserror::Error, Debug)]
pub enum EGLError {
    /// EGL is not initialized, or could not be initialized, for the specified EGL display connection.
    #[error(
        "EGL is not initialized, or could not be initialized, for the specified EGL display connection."
    )]
    NotInitialized,
    /// EGL cannot access a requested resource (for example a context is bound in another thread).
    #[error("EGL cannot access a requested resource (for example a context is bound in another thread).")]
    BadAccess,
    /// EGL failed to allocate resources for the requested operation.
    #[error("EGL failed to allocate resources for the requested operation.")]
    BadAlloc,
    /// An unrecognized attribute or attribute value was passed in the attribute list.
    #[error("An unrecognized attribute or attribute value was passed in the attribute list.")]
    BadAttribute,
    /// An EGLContext argument does not name a valid EGL rendering context.
    #[error("An EGLContext argument does not name a valid EGL rendering context.")]
    BadContext,
    /// An EGLConfig argument does not name a valid EGL frame buffer configuration.
    #[error("An EGLConfig argument does not name a valid EGL frame buffer configuration.")]
    BadConfig,
    /// The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid.
    #[error("The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid.")]
    BadCurrentSurface,
    /// An EGLDevice argument is not valid for this display.
    #[error("An EGLDevice argument is not valid for this display.")]
    BadDevice,
    /// An EGLDisplay argument does not name a valid EGL display connection.
    #[error("An EGLDisplay argument does not name a valid EGL display connection.")]
    BadDisplay,
    /// An EGLSurface argument does not name a valid surface (window, pixel buffer or pixmap) configured for GL rendering.
    #[error("An EGLSurface argument does not name a valid surface (window, pixel buffer or pixmap) configured for GL rendering.")]
    BadSurface,
    /// Arguments are inconsistent (for example, a valid context requires buffers not supplied by a valid surface).
    #[error("Arguments are inconsistent (for example, a valid context requires buffers not supplied by a valid surface).")]
    BadMatch,
    /// One or more argument values are invalid.
    #[error("One or more argument values are invalid.")]
    BadParameter,
    /// A NativePixmapType argument does not refer to a valid native pixmap.
    #[error("A NativePixmapType argument does not refer to a valid native pixmap.")]
    BadNativePixmap,
    /// A NativeWindowType argument does not refer to a valid native window.
    #[error("A NativeWindowType argument does not refer to a valid native window.")]
    BadNativeWindow,
    /// The EGL operation failed due to temporary unavailability of a requested resource, but the arguments were otherwise valid, and a subsequent attempt may succeed.
    #[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,
    /// A power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering.
    #[error("A power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering.")]
    ContextLost,
    /// An unknown error
    #[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_DEVICE_EXT => EGLError::BadDevice,
            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,
            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)),
        }
    }
}

/// Wraps a raw egl call and returns error codes from `eglGetError`, if it fails.
pub fn wrap_egl_call<R, F: FnOnce() -> R>(call: F) -> Result<R, EGLError> {
    let res = call();
    EGLError::from_last_call().map(|()| res)
}

<MSG> egl: Add function to export egl images

<DFF> @@ -39,12 +39,15 @@ pub enum Error {
     /// No EGLDisplay is currently bound to this `WlDisplay`
     #[error("No EGLDisplay is currently bound to this `WlDisplay`")]
     NoEGLDisplayBound,
-    /// Index of plane is out of bounds for `EGLBuffer`
+    /// Index of plane is out of bounds for `EGLImage`
     #[error("Index of plane is out of bounds for `EGLBuffer`")]
     PlaneIndexOutOfBounds,
-    /// Failed to create `EGLBuffer` from the buffer
-    #[error("Failed to create `EGLBuffer` from the buffer")]
+    /// Failed to create `EGLImage` from the buffer
+    #[error("Failed to create `EGLImage` from the buffer")]
     EGLImageCreationFailed,
+    /// Failed to create `Dmabuf` from the image
+    #[error("Faiedl to create `Dmabuf` from the image")]
+    DmabufExportFailed(#[source] EGLError),
     /// Failed to query the available `EGLDevice`s
     #[error("Failed to query the available `EGLDevice`s")]
     QueryDevices(#[source] EGLError),

egl: Add function to export egl images