#[cfg(feature = "desktop")]
use wgpu::{Device, Queue, Surface, SurfaceConfiguration};
#[cfg(feature = "desktop")]
use winit::window::Window;
#[allow(unused_imports)]
use crate::vdom::VNode;
pub struct DesktopRenderer {
#[cfg(feature = "desktop")]
device: Device,
#[cfg(feature = "desktop")]
queue: Queue,
#[cfg(feature = "desktop")]
surface: Surface<'static>,
#[cfg(feature = "desktop")]
config: SurfaceConfiguration,
}
#[cfg(feature = "desktop")]
impl DesktopRenderer {
pub async fn new(window: std::sync::Arc<Window>) -> Result<Self, String> {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
..Default::default()
});
let surface = instance
.create_surface(window.clone())
.map_err(|e| format!("Failed to create surface: {}", e))?;
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
compatible_surface: Some(&surface),
force_fallback_adapter: false,
})
.await
.ok_or("Failed to find suitable graphics adapter")?;
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: Some("Windjammer UI Device"),
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
memory_hints: Default::default(),
},
None,
)
.await
.map_err(|e| format!("Failed to create device: {}", e))?;
let size = window.inner_size();
let config = SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_capabilities(&adapter).formats[0],
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
alpha_mode: wgpu::CompositeAlphaMode::Auto,
view_formats: vec![],
desired_maximum_frame_latency: 2,
};
surface.configure(&device, &config);
Ok(Self {
device,
queue,
surface,
config,
})
}
pub fn render(&mut self, _vdom: &VNode) -> Result<(), String> {
let output = self
.surface
.get_current_texture()
.map_err(|e| format!("Failed to get surface texture: {}", e))?;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
});
{
let _render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.1,
g: 0.1,
b: 0.1,
a: 1.0,
}),
store: wgpu::StoreOp::Store,
},
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});
}
self.queue.submit(std::iter::once(encoder.finish()));
output.present();
Ok(())
}
pub fn resize(&mut self, width: u32, height: u32) {
if width > 0 && height > 0 {
self.config.width = width;
self.config.height = height;
self.surface.configure(&self.device, &self.config);
}
}
}