pixels_window_renderer/
lib.rs1#![cfg_attr(docsrs, feature(doc_cfg))]
4
5use anyrender::{ImageRenderer, WindowHandle, WindowRenderer};
6use debug_timer::debug_timer;
7use pixels::{Pixels, SurfaceTexture, wgpu::Color};
8use std::sync::Arc;
9
10pub struct ActiveRenderState {
12 pixels: Pixels<'static>,
14}
15
16#[allow(clippy::large_enum_variant)]
17pub enum RenderState {
18 Active(ActiveRenderState),
19 Suspended,
20}
21
22pub struct PixelsWindowRenderer<Renderer: ImageRenderer> {
23 render_state: RenderState,
26 window_handle: Option<Arc<dyn WindowHandle>>,
27 renderer: Renderer,
28}
29
30impl<Renderer: ImageRenderer> PixelsWindowRenderer<Renderer> {
31 #[allow(clippy::new_without_default)]
32 pub fn new() -> Self {
33 Self::with_renderer(Renderer::new(0, 0))
34 }
35
36 pub fn with_renderer<R: ImageRenderer>(renderer: R) -> PixelsWindowRenderer<R> {
37 PixelsWindowRenderer {
38 render_state: RenderState::Suspended,
39 window_handle: None,
40 renderer,
41 }
42 }
43}
44
45impl<Renderer: ImageRenderer> WindowRenderer for PixelsWindowRenderer<Renderer> {
46 type ScenePainter<'a>
47 = <Renderer as ImageRenderer>::ScenePainter<'a>
48 where
49 Renderer: 'a;
50
51 fn is_active(&self) -> bool {
52 matches!(self.render_state, RenderState::Active(_))
53 }
54
55 fn resume(&mut self, window_handle: Arc<dyn WindowHandle>, width: u32, height: u32) {
56 let surface = SurfaceTexture::new(width, height, window_handle.clone());
57 let mut pixels = Pixels::new(width, height, surface).unwrap();
58 pixels.enable_vsync(true);
59 pixels.clear_color(Color {
60 r: 1.0,
61 g: 1.0,
62 b: 1.0,
63 a: 1.0,
64 });
65 self.render_state = RenderState::Active(ActiveRenderState { pixels });
66 self.window_handle = Some(window_handle);
67
68 self.set_size(width, height);
69 }
70
71 fn suspend(&mut self) {
72 self.render_state = RenderState::Suspended;
73 }
74
75 fn set_size(&mut self, physical_width: u32, physical_height: u32) {
76 if let RenderState::Active(state) = &mut self.render_state {
77 state
78 .pixels
79 .resize_buffer(physical_width, physical_height)
80 .unwrap();
81 state
82 .pixels
83 .resize_surface(physical_width, physical_height)
84 .unwrap();
85 self.renderer.resize(physical_width, physical_height);
86 };
87 }
88
89 fn render<F: FnOnce(&mut Renderer::ScenePainter<'_>)>(&mut self, draw_fn: F) {
90 let RenderState::Active(state) = &mut self.render_state else {
91 return;
92 };
93
94 debug_timer!(timer, feature = "log_frame_times");
95
96 self.renderer.render(draw_fn, state.pixels.frame_mut());
98 timer.record_time("render");
99
100 state.pixels.render().unwrap();
101 timer.record_time("present");
102 timer.print_times("pixels: ");
103
104 self.renderer.reset();
106 }
107}