|
7 | 7 | //! The `softbuffer` crate is used, largely because of its ease of use. `glutin` or `wgpu` could |
8 | 8 | //! also be used to fill the window buffer, but they are more complicated to use. |
9 | 9 |
|
10 | | -#[allow(unused_imports)] |
11 | | -pub use platform::cleanup_window; |
12 | | -#[allow(unused_imports)] |
13 | | -pub use platform::fill_window; |
14 | | -#[allow(unused_imports)] |
15 | | -pub use platform::fill_window_with_animated_color; |
16 | | -#[allow(unused_imports)] |
17 | | -pub use platform::fill_window_with_color; |
18 | | - |
19 | | -mod platform { |
20 | | - use std::cell::RefCell; |
21 | | - use std::collections::HashMap; |
22 | | - use std::mem; |
23 | | - use std::mem::ManuallyDrop; |
24 | | - use std::num::NonZeroU32; |
25 | | - #[cfg(not(web_platform))] |
26 | | - use std::time::Instant; |
27 | | - |
28 | | - use softbuffer::{Context, Surface}; |
29 | | - #[cfg(web_platform)] |
30 | | - use web_time::Instant; |
31 | | - use winit::window::{Window, WindowId}; |
32 | | - |
33 | | - thread_local! { |
34 | | - // NOTE: You should never do things like that, create context and drop it before |
35 | | - // you drop the event loop. We do this for brevity to not blow up examples. We use |
36 | | - // ManuallyDrop to prevent destructors from running. |
37 | | - // |
38 | | - // A static, thread-local map of graphics contexts to open windows. |
39 | | - static GC: ManuallyDrop<RefCell<Option<GraphicsContext>>> = const { ManuallyDrop::new(RefCell::new(None)) }; |
40 | | - } |
| 10 | +use std::cell::RefCell; |
| 11 | +use std::collections::HashMap; |
| 12 | +use std::mem; |
| 13 | +use std::mem::ManuallyDrop; |
| 14 | +use std::num::NonZeroU32; |
| 15 | +#[cfg(not(web_platform))] |
| 16 | +use std::time::Instant; |
| 17 | + |
| 18 | +use softbuffer::{Context, Surface}; |
| 19 | +#[cfg(web_platform)] |
| 20 | +use web_time::Instant; |
| 21 | +use winit::window::{Window, WindowId}; |
| 22 | + |
| 23 | +thread_local! { |
| 24 | + // NOTE: You should never do things like that, create context and drop it before |
| 25 | + // you drop the event loop. We do this for brevity to not blow up examples. We use |
| 26 | + // ManuallyDrop to prevent destructors from running. |
| 27 | + // |
| 28 | + // A static, thread-local map of graphics contexts to open windows. |
| 29 | + static GC: ManuallyDrop<RefCell<Option<GraphicsContext>>> = const { ManuallyDrop::new(RefCell::new(None)) }; |
| 30 | +} |
41 | 31 |
|
42 | | - /// The graphics context used to draw to a window. |
43 | | - struct GraphicsContext { |
44 | | - /// The global softbuffer context. |
45 | | - context: RefCell<Context<&'static dyn Window>>, |
| 32 | +/// The graphics context used to draw to a window. |
| 33 | +struct GraphicsContext { |
| 34 | + /// The global softbuffer context. |
| 35 | + context: RefCell<Context<&'static dyn Window>>, |
46 | 36 |
|
47 | | - /// The hash map of window IDs to surfaces. |
48 | | - surfaces: HashMap<WindowId, Surface<&'static dyn Window, &'static dyn Window>>, |
49 | | - } |
| 37 | + /// The hash map of window IDs to surfaces. |
| 38 | + surfaces: HashMap<WindowId, Surface<&'static dyn Window, &'static dyn Window>>, |
| 39 | +} |
50 | 40 |
|
51 | | - impl GraphicsContext { |
52 | | - fn new(w: &dyn Window) -> Self { |
53 | | - Self { |
54 | | - context: RefCell::new( |
55 | | - Context::new(unsafe { |
56 | | - mem::transmute::<&'_ dyn Window, &'static dyn Window>(w) |
57 | | - }) |
| 41 | +impl GraphicsContext { |
| 42 | + fn new(w: &dyn Window) -> Self { |
| 43 | + Self { |
| 44 | + context: RefCell::new( |
| 45 | + Context::new(unsafe { mem::transmute::<&'_ dyn Window, &'static dyn Window>(w) }) |
58 | 46 | .expect("Failed to create a softbuffer context"), |
59 | | - ), |
60 | | - surfaces: HashMap::new(), |
61 | | - } |
| 47 | + ), |
| 48 | + surfaces: HashMap::new(), |
62 | 49 | } |
| 50 | + } |
63 | 51 |
|
64 | | - fn create_surface( |
65 | | - &mut self, |
66 | | - window: &dyn Window, |
67 | | - ) -> &mut Surface<&'static dyn Window, &'static dyn Window> { |
68 | | - self.surfaces.entry(window.id()).or_insert_with(|| { |
69 | | - Surface::new(&self.context.borrow(), unsafe { |
70 | | - mem::transmute::<&'_ dyn Window, &'static dyn Window>(window) |
71 | | - }) |
72 | | - .expect("Failed to create a softbuffer surface") |
| 52 | + fn create_surface( |
| 53 | + &mut self, |
| 54 | + window: &dyn Window, |
| 55 | + ) -> &mut Surface<&'static dyn Window, &'static dyn Window> { |
| 56 | + self.surfaces.entry(window.id()).or_insert_with(|| { |
| 57 | + Surface::new(&self.context.borrow(), unsafe { |
| 58 | + mem::transmute::<&'_ dyn Window, &'static dyn Window>(window) |
73 | 59 | }) |
74 | | - } |
| 60 | + .expect("Failed to create a softbuffer surface") |
| 61 | + }) |
| 62 | + } |
75 | 63 |
|
76 | | - fn destroy_surface(&mut self, window: &dyn Window) { |
77 | | - self.surfaces.remove(&window.id()); |
78 | | - } |
| 64 | + fn destroy_surface(&mut self, window: &dyn Window) { |
| 65 | + self.surfaces.remove(&window.id()); |
79 | 66 | } |
| 67 | +} |
80 | 68 |
|
81 | | - pub fn fill_window_with_color(window: &dyn Window, color: u32) { |
82 | | - GC.with(|gc| { |
83 | | - let size = window.surface_size(); |
84 | | - let (Some(width), Some(height)) = |
85 | | - (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) |
86 | | - else { |
87 | | - return; |
88 | | - }; |
| 69 | +pub fn fill_window_with_color(window: &dyn Window, color: u32) { |
| 70 | + GC.with(|gc| { |
| 71 | + let size = window.surface_size(); |
| 72 | + let (Some(width), Some(height)) = |
| 73 | + (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) |
| 74 | + else { |
| 75 | + return; |
| 76 | + }; |
89 | 77 |
|
90 | | - // Either get the last context used or create a new one. |
91 | | - let mut gc = gc.borrow_mut(); |
92 | | - let surface = |
93 | | - gc.get_or_insert_with(|| GraphicsContext::new(window)).create_surface(window); |
| 78 | + // Either get the last context used or create a new one. |
| 79 | + let mut gc = gc.borrow_mut(); |
| 80 | + let surface = gc.get_or_insert_with(|| GraphicsContext::new(window)).create_surface(window); |
94 | 81 |
|
95 | | - // Fill a buffer with a solid color |
| 82 | + // Fill a buffer with a solid color |
96 | 83 |
|
97 | | - surface.resize(width, height).expect("Failed to resize the softbuffer surface"); |
| 84 | + surface.resize(width, height).expect("Failed to resize the softbuffer surface"); |
98 | 85 |
|
99 | | - let mut buffer = surface.buffer_mut().expect("Failed to get the softbuffer buffer"); |
100 | | - buffer.fill(color); |
101 | | - buffer.present().expect("Failed to present the softbuffer buffer"); |
102 | | - }) |
103 | | - } |
| 86 | + let mut buffer = surface.buffer_mut().expect("Failed to get the softbuffer buffer"); |
| 87 | + buffer.fill(color); |
| 88 | + buffer.present().expect("Failed to present the softbuffer buffer"); |
| 89 | + }) |
| 90 | +} |
104 | 91 |
|
105 | | - #[allow(dead_code)] |
106 | | - pub fn fill_window(window: &dyn Window) { |
107 | | - fill_window_with_color(window, 0xff181818); |
108 | | - } |
| 92 | +#[allow(dead_code)] |
| 93 | +pub fn fill_window(window: &dyn Window) { |
| 94 | + fill_window_with_color(window, 0xff181818); |
| 95 | +} |
109 | 96 |
|
110 | | - #[allow(dead_code)] |
111 | | - pub fn fill_window_with_animated_color(window: &dyn Window, start: Instant) { |
112 | | - let time = start.elapsed().as_secs_f32() * 1.5; |
113 | | - let blue = (time.sin() * 255.0) as u32; |
114 | | - let green = ((time.cos() * 255.0) as u32) << 8; |
115 | | - let red = ((1.0 - time.sin() * 255.0) as u32) << 16; |
116 | | - let color = red | green | blue; |
117 | | - fill_window_with_color(window, color); |
118 | | - } |
| 97 | +#[allow(dead_code)] |
| 98 | +pub fn fill_window_with_animated_color(window: &dyn Window, start: Instant) { |
| 99 | + let time = start.elapsed().as_secs_f32() * 1.5; |
| 100 | + let blue = (time.sin() * 255.0) as u32; |
| 101 | + let green = ((time.cos() * 255.0) as u32) << 8; |
| 102 | + let red = ((1.0 - time.sin() * 255.0) as u32) << 16; |
| 103 | + let color = red | green | blue; |
| 104 | + fill_window_with_color(window, color); |
| 105 | +} |
119 | 106 |
|
120 | | - #[allow(dead_code)] |
121 | | - pub fn cleanup_window(window: &dyn Window) { |
122 | | - GC.with(|gc| { |
123 | | - let mut gc = gc.borrow_mut(); |
124 | | - if let Some(context) = gc.as_mut() { |
125 | | - context.destroy_surface(window); |
126 | | - } |
127 | | - }); |
128 | | - } |
| 107 | +#[allow(dead_code)] |
| 108 | +pub fn cleanup_window(window: &dyn Window) { |
| 109 | + GC.with(|gc| { |
| 110 | + let mut gc = gc.borrow_mut(); |
| 111 | + if let Some(context) = gc.as_mut() { |
| 112 | + context.destroy_surface(window); |
| 113 | + } |
| 114 | + }); |
129 | 115 | } |
0 commit comments