118 lines
4.1 KiB
Rust
118 lines
4.1 KiB
Rust
//! Fill the window buffer with a solid color.
|
|
//!
|
|
//! Launching a window without drawing to it has unpredictable results varying from platform to
|
|
//! platform. In order to have well-defined examples, this module provides an easy way to
|
|
//! fill the window buffer with a solid color.
|
|
//!
|
|
//! 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.
|
|
|
|
#[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"))))]
|
|
mod platform {
|
|
use std::cell::RefCell;
|
|
use std::collections::HashMap;
|
|
use std::mem;
|
|
use std::mem::ManuallyDrop;
|
|
use std::num::NonZeroU32;
|
|
|
|
use softbuffer::{Context, Surface};
|
|
use winit::window::{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>>> = const { ManuallyDrop::new(RefCell::new(None)) };
|
|
}
|
|
|
|
/// The graphics context used to draw to a window.
|
|
struct GraphicsContext {
|
|
/// The global softbuffer context.
|
|
context: RefCell<Context<&'static Window>>,
|
|
|
|
/// The hash map of window IDs to surfaces.
|
|
surfaces: HashMap<WindowId, Surface<&'static Window, &'static Window>>,
|
|
}
|
|
|
|
impl GraphicsContext {
|
|
fn new(w: &Window) -> Self {
|
|
Self {
|
|
context: RefCell::new(
|
|
Context::new(unsafe { mem::transmute::<&'_ Window, &'static Window>(w) })
|
|
.expect("Failed to create a softbuffer context"),
|
|
),
|
|
surfaces: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
fn create_surface(
|
|
&mut self,
|
|
window: &Window,
|
|
) -> &mut Surface<&'static Window, &'static Window> {
|
|
self.surfaces.entry(window.id()).or_insert_with(|| {
|
|
Surface::new(&self.context.borrow(), unsafe {
|
|
mem::transmute::<&'_ Window, &'static Window>(window)
|
|
})
|
|
.expect("Failed to create a softbuffer surface")
|
|
})
|
|
}
|
|
|
|
fn destroy_surface(&mut self, window: &Window) {
|
|
self.surfaces.remove(&window.id());
|
|
}
|
|
}
|
|
|
|
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");
|
|
})
|
|
}
|
|
|
|
#[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")))))]
|
|
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.
|
|
}
|
|
}
|