use std::any::Any;
use std::fmt;
use std::rc::Rc;
use gpui_engine::SceneRenderer;
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
use crate::{DevicePixels, GpuSpecs, Pixels, Size};
#[cfg(target_os = "macos")]
pub trait MacSceneRenderer: SceneRenderer {
fn layer_ptr(&self) -> *mut std::ffi::c_void;
fn set_presents_with_transaction(&mut self, value: bool);
}
#[cfg(target_os = "windows")]
pub trait WinSceneRenderer: SceneRenderer {
fn set_background_appearance(&mut self, appearance: crate::WindowBackgroundAppearance);
fn resize(&mut self, size: Size<DevicePixels>) -> anyhow::Result<()>;
fn mark_drawable(&mut self) {}
}
#[cfg(target_os = "macos")]
pub trait NativeSceneHooks: MacSceneRenderer {}
#[cfg(target_os = "windows")]
pub trait NativeSceneHooks: WinSceneRenderer {}
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
pub trait NativeSceneHooks: SceneRenderer {}
#[cfg(target_os = "macos")]
impl<T: MacSceneRenderer + ?Sized> NativeSceneHooks for T {}
#[cfg(target_os = "windows")]
impl<T: WinSceneRenderer + ?Sized> NativeSceneHooks for T {}
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
impl<T: SceneRenderer + ?Sized> NativeSceneHooks for T {}
pub trait PlatformRenderer: NativeSceneHooks {
fn update_drawable_size(&mut self, size: Size<DevicePixels>);
fn max_texture_size(&self) -> u32;
fn gpu_specs(&self) -> Option<GpuSpecs>;
fn set_subpixel_layout(&mut self, _is_bgr: bool) {}
fn update_transparency(&mut self, _transparent: bool) {}
fn destroy(&mut self) {}
fn device_lost(&self) -> bool {
false
}
fn needs_redraw(&mut self) -> bool {
false
}
#[cfg(not(target_family = "wasm"))]
fn recover(&mut self, _target: RendererTarget<'_>) -> anyhow::Result<()> {
anyhow::bail!("renderer does not support recovery")
}
}
pub struct RendererTarget<'a> {
pub window_handle: Option<RawWindowHandle>,
pub display_handle: Option<RawDisplayHandle>,
pub size: Size<Pixels>,
pub scale_factor: f32,
pub transparent: bool,
pub backend: Option<&'a dyn Any>,
}
pub trait RendererFactory: 'static {
fn create(&self, target: RendererTarget<'_>) -> anyhow::Result<Box<dyn PlatformRenderer>>;
}
#[derive(Clone)]
pub struct DynRendererFactory(pub Rc<dyn RendererFactory>);
impl fmt::Debug for DynRendererFactory {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("DynRendererFactory(..)")
}
}
pub struct FnRendererFactory<F>(pub F);
impl<F> RendererFactory for FnRendererFactory<F>
where
F: Fn(RendererTarget<'_>) -> anyhow::Result<Box<dyn PlatformRenderer>> + 'static,
{
fn create(&self, target: RendererTarget<'_>) -> anyhow::Result<Box<dyn PlatformRenderer>> {
(self.0)(target)
}
}