1use hashbrown::HashMap;
2pub use notan_graphics::prelude::*;
3pub use notan_graphics::*;
4use std::any::{Any, TypeId};
5use std::cell::{Ref, RefCell, RefMut};
6
7pub struct Graphics {
11 pub device: Device,
13
14 pub extensions: ExtContainer,
15}
16
17impl Graphics {
18 pub fn new(backend: Box<dyn DeviceBackend>) -> Result<Self, String> {
19 let device = Device::new(backend)?;
20 let plugins = ExtContainer::default();
21
22 Ok(Self {
23 device,
24 extensions: plugins,
25 })
26 }
27
28 #[inline]
30 pub fn add_extension<R, T>(&mut self, extension: T)
31 where
32 R: GfxRenderer,
33 T: GfxExtension<R> + 'static,
34 {
35 self.extensions.add(extension);
36 }
37
38 #[inline]
40 pub fn remove_extension<R, T>(&mut self)
41 where
42 R: GfxRenderer,
43 T: GfxExtension<R> + 'static,
44 {
45 self.extensions.remove::<R, T>();
46 }
47
48 #[inline]
50 pub fn extension_mut<R, T>(&self) -> Option<RefMut<'_, T>>
51 where
52 R: GfxRenderer,
53 T: GfxExtension<R> + 'static,
54 {
55 self.extensions.get_mut()
56 }
57
58 #[inline]
60 pub fn extension<R, T>(&self) -> Option<Ref<'_, T>>
61 where
62 R: GfxRenderer,
63 T: GfxExtension<R> + 'static,
64 {
65 self.extensions.get()
66 }
67
68 #[inline]
70 pub fn create_pipeline(&mut self) -> PipelineBuilder<'_, '_> {
71 self.device.create_pipeline()
72 }
73
74 #[inline]
76 pub fn create_texture(&mut self) -> TextureBuilder<'_, '_> {
77 self.device.create_texture()
78 }
79
80 #[inline]
82 pub fn create_render_texture(&mut self, width: u32, height: u32) -> RenderTextureBuilder<'_> {
83 self.device.create_render_texture(width, height)
84 }
85
86 #[inline]
88 pub fn create_vertex_buffer(&mut self) -> VertexBufferBuilder<'_> {
89 self.device.create_vertex_buffer()
90 }
91
92 #[inline]
94 pub fn create_index_buffer(&mut self) -> IndexBufferBuilder<'_> {
95 self.device.create_index_buffer()
96 }
97
98 #[inline]
100 pub fn create_uniform_buffer(&mut self, slot: u32, name: &str) -> UniformBufferBuilder<'_> {
101 self.device.create_uniform_buffer(slot, name)
102 }
103
104 #[inline]
106 pub fn update_texture<'a>(&'a mut self, texture: &'a mut Texture) -> TextureUpdater<'a> {
107 self.device.update_texture(texture)
108 }
109
110 #[inline]
112 pub fn read_pixels<'a>(&'a mut self, texture: &'a Texture) -> TextureReader<'a> {
113 self.device.read_pixels(texture)
114 }
115
116 #[inline]
118 pub fn render<G: GfxRenderer>(&mut self, renderer: &G) {
119 if let Err(err) = renderer.render(&mut self.device, &mut self.extensions, None) {
120 log::error!("{err}");
121 panic!("{}", err);
122 }
123 }
124
125 #[inline]
127 pub fn render_to<G: GfxRenderer>(&mut self, target: &RenderTexture, renderer: &G) {
128 if let Err(err) = renderer.render(&mut self.device, &mut self.extensions, Some(target)) {
129 log::error!("{err}");
130 panic!("{}", err);
131 }
132 }
133
134 #[inline]
136 pub fn set_buffer_data<T: BufferData>(&mut self, buffer: &Buffer, data: T) {
137 self.device.set_buffer_data(buffer, data);
138 }
139
140 #[inline]
142 pub fn create_renderer(&self) -> Renderer {
143 self.device.create_renderer()
144 }
145
146 #[inline]
148 pub fn limits(&self) -> Limits {
149 self.device.limits()
150 }
151
152 #[inline]
154 pub fn size(&self) -> (u32, u32) {
155 self.device.size()
156 }
157
158 #[inline]
160 pub fn set_size(&mut self, width: u32, height: u32) {
161 self.device.set_size(width, height);
162 }
163
164 #[inline]
166 pub fn dpi(&self) -> f64 {
167 self.device.dpi()
168 }
169
170 #[inline]
172 pub fn set_dpi(&mut self, scale_factor: f64) {
173 self.device.set_dpi(scale_factor);
174 }
175
176 #[inline]
178 pub fn stats(&self) -> GpuStats {
179 self.device.stats()
180 }
181}
182
183impl std::ops::Deref for Graphics {
184 type Target = Device;
185
186 fn deref(&self) -> &Self::Target {
187 &self.device
188 }
189}
190
191impl std::ops::DerefMut for Graphics {
192 fn deref_mut(&mut self) -> &mut Self::Target {
193 &mut self.device
194 }
195}
196
197#[derive(Default)]
199pub struct ExtContainer {
200 map: HashMap<TypeId, Box<dyn Any>>,
201}
202
203impl ExtContainer {
204 #[inline]
206 pub fn add<R, T>(&mut self, value: T)
207 where
208 R: GfxRenderer,
209 T: GfxExtension<R> + 'static,
210 {
211 self.map
212 .insert(TypeId::of::<T>(), Box::new(RefCell::new(value)));
213 }
214
215 #[inline]
217 pub fn get_mut<R, T>(&self) -> Option<RefMut<'_, T>>
218 where
219 R: GfxRenderer,
220 T: GfxExtension<R> + 'static,
221 {
222 self.map
223 .get(&TypeId::of::<T>())?
224 .downcast_ref::<RefCell<T>>()
225 .map(|value| value.borrow_mut())
226 }
227
228 #[inline]
230 pub fn get<R, T>(&self) -> Option<Ref<'_, T>>
231 where
232 R: GfxRenderer,
233 T: GfxExtension<R> + 'static,
234 {
235 self.map
236 .get(&TypeId::of::<T>())?
237 .downcast_ref::<RefCell<T>>()
238 .map(|value| value.borrow())
239 }
240
241 #[inline]
243 pub fn remove<R, T>(&mut self)
244 where
245 R: GfxRenderer,
246 T: GfxExtension<R> + 'static,
247 {
248 self.map.remove(&TypeId::of::<T>());
249 }
250}
251
252pub trait GfxRenderer {
254 fn render(
256 &self,
257 device: &mut Device,
258 extensions: &mut ExtContainer,
259 target: Option<&RenderTexture>,
260 ) -> Result<(), String>;
261}
262
263pub trait GfxExtension<T: ?Sized> {}
264
265impl GfxRenderer for Renderer {
266 fn render(
267 &self,
268 device: &mut Device,
269 _extensions: &mut ExtContainer,
270 target: Option<&RenderTexture>,
271 ) -> Result<(), String> {
272 match target {
273 None => device.render(self.commands()),
274 Some(rt) => device.render_to(rt, self.commands()),
275 }
276
277 Ok(())
278 }
279}