dioxus_native/
dioxus_renderer.rs1use std::rc::Rc;
2use std::sync::Arc;
3use std::{any::Any, cell::RefCell};
4
5use anyrender::{CompositeAlphaMode, RenderContext, RendererConfig, WindowRenderer};
6use peniko::Color;
7
8cfg_if::cfg_if! {
10 if #[cfg(feature = "vello")] {
11 pub use anyrender_vello::{
12 VelloRendererOptions as InnerRendererOptions, VelloWindowRenderer as InnerRenderer,
13 wgpu::{Features, Limits},
14 };
15 } else if #[cfg(feature = "vello-cpu-base")] {
16 use anyrender_vello_cpu::VelloCpuWindowRenderer as InnerRenderer;
17 } else if #[cfg(feature = "skia")] {
18 use anyrender_skia::SkiaWindowRenderer as InnerRenderer;
19 } else if #[cfg(feature = "skia-raster-base")] {
20 use anyrender_skia::raster::SkiaRasterWindowRenderer as InnerRenderer;
21 } else if #[cfg(feature = "vello-hybrid")] {
22 pub use anyrender_vello_hybrid::{
23 VelloHybridRendererOptions as InnerRendererOptions, VelloHybridWindowRenderer as InnerRenderer,
24 wgpu::{Features, Limits},
25 };
26 } else {
27 compile_error!("At least one renderer feature must be enabled");
28 }
29}
30
31#[derive(Default)]
36pub struct RendererOptions {
37 pub base_color: Option<Color>,
39 pub alpha_mode: Option<CompositeAlphaMode>,
41 #[cfg(any(feature = "vello", feature = "vello-hybrid"))]
43 pub features: Option<Features>,
44 #[cfg(any(feature = "vello", feature = "vello-hybrid"))]
46 pub limits: Option<Limits>,
47}
48
49#[derive(Clone)]
50pub struct DioxusNativeWindowRenderer {
51 inner: Rc<RefCell<InnerRenderer>>,
52}
53
54impl Default for DioxusNativeWindowRenderer {
55 fn default() -> Self {
56 Self::new()
57 }
58}
59
60impl DioxusNativeWindowRenderer {
61 pub fn new() -> Self {
62 Self::with_options(RendererOptions::default())
63 }
64
65 #[cfg(any(feature = "vello-hybrid", feature = "vello"))]
66 pub fn with_features_and_limits(features: Option<Features>, limits: Option<Limits>) -> Self {
67 Self::with_options(RendererOptions {
68 features,
69 limits,
70 ..Default::default()
71 })
72 }
73
74 pub fn with_options(options: RendererOptions) -> Self {
81 let mut config = RendererConfig::default();
82 config.base_color = options.base_color;
83 config.composite_alpha_mode = options.alpha_mode;
84
85 cfg_if::cfg_if! {
86 if #[cfg(any(feature = "vello", feature = "vello-hybrid"))] {
87 let mut inner_options: InnerRendererOptions = config.into();
88 if let Some(features) = options.features {
89 inner_options = inner_options.features(features);
90 }
91 if let Some(limits) = options.limits {
92 inner_options = inner_options.limits(limits);
93 }
94 let inner_renderer = InnerRenderer::with_options(inner_options);
95 } else {
96 let inner_renderer = InnerRenderer::with_options(config);
97 }
98 }
99
100 Self::with_inner_renderer(inner_renderer)
101 }
102
103 fn with_inner_renderer(inner_renderer: InnerRenderer) -> Self {
104 Self {
105 inner: Rc::new(RefCell::new(inner_renderer)),
106 }
107 }
108}
109
110impl RenderContext for DioxusNativeWindowRenderer {
111 fn try_register_custom_resource(
112 &mut self,
113 resource: Box<dyn Any>,
114 ) -> Result<anyrender::ResourceId, anyrender::RegisterResourceError> {
115 self.inner
116 .borrow_mut()
117 .try_register_custom_resource(resource)
118 }
119
120 fn unregister_resource(&mut self, resource_id: anyrender::ResourceId) {
121 self.inner.borrow_mut().unregister_resource(resource_id)
122 }
123
124 fn renderer_specific_context(&self) -> Option<Box<dyn Any>> {
125 self.inner.borrow_mut().renderer_specific_context()
126 }
127}
128impl WindowRenderer for DioxusNativeWindowRenderer {
129 type ScenePainter<'a>
130 = <InnerRenderer as WindowRenderer>::ScenePainter<'a>
131 where
132 Self: 'a;
133
134 fn resume<F: FnOnce() + 'static>(
135 &mut self,
136 window: Arc<dyn anyrender::WindowHandle>,
137 width: u32,
138 height: u32,
139 on_ready: F,
140 ) {
141 self.inner
142 .borrow_mut()
143 .resume(window, width, height, on_ready)
144 }
145
146 fn complete_resume(&mut self) -> bool {
147 self.inner.borrow_mut().complete_resume()
148 }
149
150 fn suspend(&mut self) {
151 self.inner.borrow_mut().suspend()
152 }
153
154 fn is_active(&self) -> bool {
155 self.inner.borrow().is_active()
156 }
157
158 fn is_pending(&self) -> bool {
159 self.inner.borrow().is_pending()
160 }
161
162 fn set_size(&mut self, width: u32, height: u32) {
163 self.inner.borrow_mut().set_size(width, height)
164 }
165
166 fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(&mut self, draw_fn: F) {
167 self.inner.borrow_mut().render(draw_fn)
168 }
169}