aura-gui 0.2.2

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.
//! El renderizador que usa una ventana: la GPU (wgpu) o, si no hay una utilizable, la CPU. Las dos pintan la misma
//! `Scene` con la misma API, así quien dibuja (aura_ui) no sabe cuál hay debajo.

use crate::core::Rgba;
use crate::gpu::capture::CapturedFrame;
use crate::gpu::context::{Error, GpuContext};
use crate::gpu::cpu::{CpuRenderer, Presenter};
use crate::gpu::renderer::GpuRenderer;
use crate::gpu::scene::Scene;
use crate::gpu::text::GlyphTarget;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RendererKind {
    Gpu,
    Cpu,
}

pub enum Renderer {
    Gpu(Box<GpuRenderer>),
    Cpu(CpuRenderer),
}

impl Renderer {
    pub fn gpu(context: GpuContext) -> Result<Self, Error> {
        Ok(Self::Gpu(Box::new(GpuRenderer::new(context)?)))
    }

    pub fn cpu(presenter: Box<dyn Presenter>, width: u32, height: u32) -> Self {
        Self::Cpu(CpuRenderer::new(Some(presenter), width, height))
    }

    pub fn kind(&self) -> RendererKind {
        match self {
            Self::Gpu(_) => RendererKind::Gpu,
            Self::Cpu(_) => RendererKind::Cpu,
        }
    }

    /// Qué pinta la ventana, para registros y ajustes: «Apple M2 (Metal)» o «CPU».
    pub fn description(&self) -> String {
        match self {
            Self::Gpu(gpu) => {
                let info = &gpu.context.adapter;
                format!("{} ({:?})", info.name, info.backend)
            }
            Self::Cpu(_) => "CPU (sin GPU)".into(),
        }
    }

    pub fn resize(&mut self, width: u32, height: u32) {
        match self {
            Self::Gpu(gpu) => gpu.resize(width, height),
            Self::Cpu(cpu) => cpu.resize(width, height),
        }
    }

    pub fn take_atlas_overflow(&mut self) -> bool {
        match self {
            Self::Gpu(gpu) => gpu.take_atlas_overflow(),
            Self::Cpu(cpu) => cpu.take_atlas_overflow(),
        }
    }

    pub fn glyph_target(&mut self) -> GlyphTarget<'_> {
        match self {
            Self::Gpu(gpu) => gpu.glyph_target(),
            Self::Cpu(cpu) => cpu.glyph_target(),
        }
    }

    /// `Ok(false)` cuando el frame se omitió (ventana oculta o superficie obsoleta).
    pub fn render(&mut self, scene: &Scene, scale: f32, clear: Rgba) -> Result<bool, Error> {
        match self {
            Self::Gpu(gpu) => gpu.render(scene, scale, clear),
            Self::Cpu(cpu) => cpu.render(scene, scale, clear),
        }
    }

    pub fn shrink_caches(&mut self) {
        match self {
            Self::Gpu(gpu) => gpu.shrink_caches(),
            Self::Cpu(cpu) => cpu.shrink_caches(),
        }
    }

    pub fn capture(&mut self, scene: &Scene, scale: f32, clear: Rgba) -> Result<CapturedFrame, Error> {
        match self {
            Self::Gpu(gpu) => gpu.capture(scene, scale, clear),
            Self::Cpu(cpu) => Ok(cpu.capture(scene, scale, clear)),
        }
    }
}