repose_render_wgpu/
callback.rs1use std::any::TypeId;
35use std::collections::HashMap;
36use std::sync::Arc;
37
38use repose_core::{PaintCallbackInfo, PaintCallbackPayload, Rect};
39
40#[cfg(not(all(
42 target_arch = "wasm32",
43 not(feature = "fragile-send-sync-non-atomic-wasm")
44)))]
45type AnyBox = Box<dyn std::any::Any + Send + Sync>;
46#[cfg(all(
47 target_arch = "wasm32",
48 not(feature = "fragile-send-sync-non-atomic-wasm")
49))]
50type AnyBox = Box<dyn std::any::Any>;
51
52#[cfg(not(all(
53 target_arch = "wasm32",
54 not(feature = "fragile-send-sync-non-atomic-wasm")
55)))]
56pub trait MaybeSendSync: Send + Sync + 'static {}
57#[cfg(not(all(
58 target_arch = "wasm32",
59 not(feature = "fragile-send-sync-non-atomic-wasm")
60)))]
61impl<T: Send + Sync + 'static> MaybeSendSync for T {}
62
63#[cfg(all(
64 target_arch = "wasm32",
65 not(feature = "fragile-send-sync-non-atomic-wasm")
66))]
67pub trait MaybeSendSync: 'static {}
68#[cfg(all(
69 target_arch = "wasm32",
70 not(feature = "fragile-send-sync-non-atomic-wasm")
71))]
72impl<T: 'static> MaybeSendSync for T {}
73
74#[derive(Default)]
75pub struct CallbackResources {
76 map: HashMap<TypeId, AnyBox>,
77}
78
79impl CallbackResources {
80 pub fn insert<T: MaybeSendSync>(&mut self, value: T) {
81 self.map.insert(TypeId::of::<T>(), Box::new(value));
82 }
83
84 pub fn get<T: MaybeSendSync>(&self) -> Option<&T> {
85 self.map
86 .get(&TypeId::of::<T>())
87 .and_then(|b| b.downcast_ref::<T>())
88 }
89
90 pub fn get_mut<T: MaybeSendSync>(&mut self) -> Option<&mut T> {
91 self.map
92 .get_mut(&TypeId::of::<T>())
93 .and_then(|b| b.downcast_mut::<T>())
94 }
95
96 pub fn get_or_insert_with<T: MaybeSendSync + Default>(&mut self) -> &mut T {
97 let id = TypeId::of::<T>();
98 if !self.map.contains_key(&id) {
99 self.map.insert(id, Box::new(T::default()));
100 }
101 self.map.get_mut(&id).unwrap().downcast_mut::<T>().unwrap()
102 }
103
104 pub fn remove<T: 'static>(&mut self) -> Option<T> {
105 self.map
106 .remove(&TypeId::of::<T>())
107 .and_then(|b| b.downcast::<T>().ok())
108 .map(|b| *b)
109 }
110
111 pub fn contains<T: 'static>(&self) -> bool {
112 self.map.contains_key(&TypeId::of::<T>())
113 }
114}
115
116#[derive(Clone, Copy, Debug)]
117pub struct ScreenDescriptor {
118 pub size_in_pixels: [u32; 2],
119 pub pixels_per_point: f32,
120 pub target_format: wgpu::TextureFormat,
122 pub sample_count: u32,
124}
125
126pub trait WgpuCallback: Send + Sync + 'static {
128 fn prepare(
131 &self,
132 _device: &wgpu::Device,
133 _queue: &wgpu::Queue,
134 _encoder: &mut wgpu::CommandEncoder,
135 _screen_descriptor: &ScreenDescriptor,
136 _resources: &mut CallbackResources,
137 ) -> Vec<wgpu::CommandBuffer> {
138 Vec::new()
139 }
140
141 fn finish_prepare(
143 &self,
144 _device: &wgpu::Device,
145 _queue: &wgpu::Queue,
146 _encoder: &mut wgpu::CommandEncoder,
147 _screen_descriptor: &ScreenDescriptor,
148 _resources: &mut CallbackResources,
149 ) -> Vec<wgpu::CommandBuffer> {
150 Vec::new()
151 }
152
153 fn paint(
154 &self,
155 info: PaintCallbackInfo,
156 render_pass: &mut wgpu::RenderPass<'static>,
157 resources: &CallbackResources,
158 );
159}
160
161pub struct Callback(pub Box<dyn WgpuCallback>);
162
163impl Callback {
164 #[deprecated(note = "rect is ignored; use Callback::new(callback) - layout supplies rect")]
165 pub fn new_paint_callback(
166 _rect: Rect,
167 callback: impl WgpuCallback + 'static,
168 ) -> PaintCallbackPayload {
169 Arc::new(Self(Box::new(callback)))
170 }
171
172 pub fn new(callback: impl WgpuCallback + 'static) -> PaintCallbackPayload {
174 Arc::new(Self(Box::new(callback)))
175 }
176
177 pub fn embedded_view(
180 modifier: repose_core::Modifier,
181 callback: impl WgpuCallback + 'static,
182 ) -> repose_core::View {
183 let payload = Self::new(callback);
184 let mut m = modifier.paint_callback(payload);
185 let has_size = m.size.is_some()
186 || m.width.is_some()
187 || m.height.is_some()
188 || m.fill_max.is_some()
189 || m.fill_max_w.is_some()
190 || m.fill_max_h.is_some();
191 if !has_size {
192 m = m.size(100.0, 100.0);
193 }
194 repose_core::View::new(0, repose_core::ViewKind::Box).modifier(m)
195 }
196}