aura-gui 0.3.5

UI nativa acelerada por GPU para escritorio, Android e iOS, en un solo crate: estilo tipo Tailwind, componentes, sombras, animaciones y agentes de IA. Reposo a cero. Licencia AGPL-3.0 o comercial.
//! Presentación del frame pintado por CPU. Con softbuffer funciona en cualquier sistema con ventanas, aunque no
//! haya GPU ni controladores 3D: GDI en Windows (también Windows 7), CoreGraphics en macOS y X11/Wayland en Linux.

use crate::gpu::context::Error;
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use std::num::NonZeroU32;

/// Entrega a quien pinta el búfer de la ventana (`0x00RRGGBB`) y luego lo muestra.
pub trait Presenter {
    fn present(&mut self, width: u32, height: u32, draw: &mut dyn FnMut(&mut [u32])) -> Result<(), Error>;
}

pub struct SoftbufferPresenter<D, W> {
    surface: softbuffer::Surface<D, W>,
}

impl<D: HasDisplayHandle, W: HasWindowHandle> SoftbufferPresenter<D, W> {
    pub fn new(display: D, window: W) -> Result<Self, Error> {
        let context = softbuffer::Context::new(display).map_err(|error| Error(error.to_string()))?;
        let surface = softbuffer::Surface::new(&context, window).map_err(|error| Error(error.to_string()))?;
        Ok(Self { surface })
    }
}

impl<D: HasDisplayHandle, W: HasWindowHandle> Presenter for SoftbufferPresenter<D, W> {
    fn present(&mut self, width: u32, height: u32, draw: &mut dyn FnMut(&mut [u32])) -> Result<(), Error> {
        let (Some(width), Some(height)) = (NonZeroU32::new(width), NonZeroU32::new(height)) else { return Ok(()) };
        self.surface.resize(width, height).map_err(|error| Error(error.to_string()))?;
        let mut buffer = self.surface.buffer_mut().map_err(|error| Error(error.to_string()))?;
        draw(&mut buffer);
        buffer.present().map_err(|error| Error(error.to_string()))
    }
}