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 self.map.entry(id).or_insert_with(|| Box::new(T::default()));
99 self.map.get_mut(&id).unwrap().downcast_mut::<T>().unwrap()
100 }
101
102 pub fn remove<T: 'static>(&mut self) -> Option<T> {
103 self.map
104 .remove(&TypeId::of::<T>())
105 .and_then(|b| b.downcast::<T>().ok())
106 .map(|b| *b)
107 }
108
109 pub fn contains<T: 'static>(&self) -> bool {
110 self.map.contains_key(&TypeId::of::<T>())
111 }
112}
113
114#[derive(Clone, Copy, Debug)]
115pub struct ScreenDescriptor {
116 pub size_in_pixels: [u32; 2],
117 pub pixels_per_point: f32,
118 pub target_format: wgpu::TextureFormat,
120 pub sample_count: u32,
122}
123
124pub trait WgpuCallback: Send + Sync + 'static {
126 fn prepare(
129 &self,
130 _device: &wgpu::Device,
131 _queue: &wgpu::Queue,
132 _encoder: &mut wgpu::CommandEncoder,
133 _screen_descriptor: &ScreenDescriptor,
134 _resources: &mut CallbackResources,
135 ) -> Vec<wgpu::CommandBuffer> {
136 Vec::new()
137 }
138
139 fn finish_prepare(
141 &self,
142 _device: &wgpu::Device,
143 _queue: &wgpu::Queue,
144 _encoder: &mut wgpu::CommandEncoder,
145 _screen_descriptor: &ScreenDescriptor,
146 _resources: &mut CallbackResources,
147 ) -> Vec<wgpu::CommandBuffer> {
148 Vec::new()
149 }
150
151 fn paint(
152 &self,
153 info: PaintCallbackInfo,
154 render_pass: &mut wgpu::RenderPass<'static>,
155 resources: &CallbackResources,
156 );
157}
158
159pub struct Callback(pub Box<dyn WgpuCallback>);
160
161impl Callback {
162 #[deprecated(note = "rect is ignored; use Callback::new(callback) - layout supplies rect")]
163 pub fn new_paint_callback(
164 _rect: Rect,
165 callback: impl WgpuCallback + 'static,
166 ) -> PaintCallbackPayload {
167 Arc::new(Self(Box::new(callback)))
168 }
169
170 #[allow(clippy::new_ret_no_self)]
173 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}