parent
9a28bb4b49
commit
8cc5cb9d9b
13 changed files with 141 additions and 69 deletions
|
|
@ -7,17 +7,30 @@
|
|||
//! The `softbuffer` crate is used, largely because of its ease of use. `glutin` or `wgpu` could
|
||||
//! also be used to fill the window buffer, but they are more complicated to use.
|
||||
|
||||
use winit::window::Window;
|
||||
#[allow(unused_imports)]
|
||||
pub use platform::cleanup_window;
|
||||
pub use platform::fill_window;
|
||||
|
||||
#[cfg(all(feature = "rwh_05", not(any(target_os = "android", target_os = "ios"))))]
|
||||
pub(super) fn fill_window(window: &Window) {
|
||||
use softbuffer::{Context, Surface};
|
||||
mod platform {
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use softbuffer::{Context, Surface};
|
||||
use winit::window::Window;
|
||||
use winit::window::WindowId;
|
||||
|
||||
thread_local! {
|
||||
// NOTE: You should never do things like that, create context and drop it before
|
||||
// you drop the event loop. We do this for brevity to not blow up examples. We use
|
||||
// ManuallyDrop to prevent destructors from running.
|
||||
//
|
||||
// A static, thread-local map of graphics contexts to open windows.
|
||||
static GC: ManuallyDrop<RefCell<Option<GraphicsContext>>> = ManuallyDrop::new(RefCell::new(None));
|
||||
}
|
||||
|
||||
/// The graphics context used to draw to a window.
|
||||
struct GraphicsContext {
|
||||
/// The global softbuffer context.
|
||||
|
|
@ -35,55 +48,69 @@ pub(super) fn fill_window(window: &Window) {
|
|||
}
|
||||
}
|
||||
|
||||
fn surface(&mut self, w: &Window) -> &mut Surface {
|
||||
self.surfaces.entry(w.id()).or_insert_with(|| {
|
||||
unsafe { Surface::new(&self.context, w) }
|
||||
fn create_surface(&mut self, window: &Window) -> &mut Surface {
|
||||
self.surfaces.entry(window.id()).or_insert_with(|| {
|
||||
unsafe { Surface::new(&self.context, window) }
|
||||
.expect("Failed to create a softbuffer surface")
|
||||
})
|
||||
}
|
||||
|
||||
fn destroy_surface(&mut self, window: &Window) {
|
||||
self.surfaces.remove(&window.id());
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
// NOTE: You should never do things like that, create context and drop it before
|
||||
// you drop the event loop. We do this for brevity to not blow up examples. We use
|
||||
// ManuallyDrop to prevent destructors from running.
|
||||
//
|
||||
// A static, thread-local map of graphics contexts to open windows.
|
||||
static GC: ManuallyDrop<RefCell<Option<GraphicsContext>>> = ManuallyDrop::new(RefCell::new(None));
|
||||
pub fn fill_window(window: &Window) {
|
||||
GC.with(|gc| {
|
||||
let size = window.inner_size();
|
||||
let (Some(width), Some(height)) =
|
||||
(NonZeroU32::new(size.width), NonZeroU32::new(size.height))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Either get the last context used or create a new one.
|
||||
let mut gc = gc.borrow_mut();
|
||||
let surface = gc
|
||||
.get_or_insert_with(|| GraphicsContext::new(window))
|
||||
.create_surface(window);
|
||||
|
||||
// Fill a buffer with a solid color.
|
||||
const DARK_GRAY: u32 = 0xFF181818;
|
||||
|
||||
surface
|
||||
.resize(width, height)
|
||||
.expect("Failed to resize the softbuffer surface");
|
||||
|
||||
let mut buffer = surface
|
||||
.buffer_mut()
|
||||
.expect("Failed to get the softbuffer buffer");
|
||||
buffer.fill(DARK_GRAY);
|
||||
buffer
|
||||
.present()
|
||||
.expect("Failed to present the softbuffer buffer");
|
||||
})
|
||||
}
|
||||
|
||||
GC.with(|gc| {
|
||||
let size = window.inner_size();
|
||||
let (Some(width), Some(height)) =
|
||||
(NonZeroU32::new(size.width), NonZeroU32::new(size.height))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Either get the last context used or create a new one.
|
||||
let mut gc = gc.borrow_mut();
|
||||
let surface = gc
|
||||
.get_or_insert_with(|| GraphicsContext::new(window))
|
||||
.surface(window);
|
||||
|
||||
// Fill a buffer with a solid color.
|
||||
const DARK_GRAY: u32 = 0xFF181818;
|
||||
|
||||
surface
|
||||
.resize(width, height)
|
||||
.expect("Failed to resize the softbuffer surface");
|
||||
|
||||
let mut buffer = surface
|
||||
.buffer_mut()
|
||||
.expect("Failed to get the softbuffer buffer");
|
||||
buffer.fill(DARK_GRAY);
|
||||
buffer
|
||||
.present()
|
||||
.expect("Failed to present the softbuffer buffer");
|
||||
})
|
||||
#[allow(dead_code)]
|
||||
pub fn cleanup_window(window: &Window) {
|
||||
GC.with(|gc| {
|
||||
let mut gc = gc.borrow_mut();
|
||||
if let Some(context) = gc.as_mut() {
|
||||
context.destroy_surface(window);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(all(feature = "rwh_05", not(any(target_os = "android", target_os = "ios")))))]
|
||||
pub(super) fn fill_window(_window: &Window) {
|
||||
// No-op on mobile platforms.
|
||||
mod platform {
|
||||
pub fn fill_window(_window: &winit::window::Window) {
|
||||
// No-op on mobile platforms.
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn cleanup_window(_window: &winit::window::Window) {
|
||||
// No-op on mobile platforms.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ fn main() -> Result<(), impl std::error::Error> {
|
|||
window_id,
|
||||
} if window.id() == window_id => {
|
||||
println!("--------------------------------------------------------- Window {idx} CloseRequested");
|
||||
fill::cleanup_window(window);
|
||||
app.window = None;
|
||||
}
|
||||
Event::AboutToWait => window.request_redraw(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue