Skip to content

Commit 319ff56

Browse files
committed
Use static dispatch
1 parent 58d4fd4 commit 319ff56

File tree

7 files changed

+75
-49
lines changed

7 files changed

+75
-49
lines changed

src/cg.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{GraphicsContextImpl, SwBufError};
1+
use crate::SwBufError;
22
use raw_window_handle::AppKitWindowHandle;
33
use core_graphics::base::{kCGBitmapByteOrder32Little, kCGImageAlphaNoneSkipFirst, kCGRenderingIntentDefault};
44
use core_graphics::color_space::CGColorSpace;
@@ -32,10 +32,8 @@ impl CGImpl {
3232
let _: () = msg_send![subview, release]; // releases subview (-1) = 1
3333
Ok(Self{layer})
3434
}
35-
}
3635

37-
impl GraphicsContextImpl for CGImpl {
38-
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
36+
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
3937
let color_space = CGColorSpace::create_device_rgb();
4038
let data = std::slice::from_raw_parts(
4139
buffer.as_ptr() as *const u8,

src/lib.rs

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,54 @@ use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandl
2727
/// An instance of this struct contains the platform-specific data that must be managed in order to
2828
/// write to a window on that platform.
2929
pub struct GraphicsContext {
30-
graphics_context_impl: Box<dyn GraphicsContextImpl>,
30+
/// The inner static dispatch object.
31+
///
32+
/// This is boxed so that `GraphicsContext` is the same size on every platform, which should
33+
/// hopefully prevent surprises.
34+
graphics_context_impl: Box<Dispatch>
35+
}
36+
37+
/// A macro for creating the enum used to statically dispatch to the platform-specific implementation.
38+
macro_rules! make_dispatch {
39+
(
40+
$(
41+
$(#[$attr:meta])*
42+
$name: ident ($inner_ty: ty),
43+
)*
44+
) => {
45+
enum Dispatch {
46+
$(
47+
$(#[$attr])*
48+
$name($inner_ty),
49+
)*
50+
}
51+
52+
impl Dispatch {
53+
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
54+
match self {
55+
$(
56+
$(#[$attr])*
57+
Self::$name(inner) => inner.set_buffer(buffer, width, height),
58+
)*
59+
}
60+
}
61+
}
62+
};
63+
}
64+
65+
make_dispatch! {
66+
#[cfg(all(feature = "x11", any(target_os = "linux", target_os = "freebsd")))]
67+
X11(x11::X11Impl),
68+
#[cfg(all(feature = "wayland", any(target_os = "linux", target_os = "freebsd")))]
69+
Wayland(wayland::WaylandImpl),
70+
#[cfg(target_os = "windows")]
71+
Win32(win32::Win32Impl),
72+
#[cfg(target_os = "macos")]
73+
CG(cg::CGImpl),
74+
#[cfg(target_arch = "wasm32")]
75+
Web(web::WebImpl),
76+
#[cfg(target_os = "redox")]
77+
Orbital(orbital::OrbitalImpl),
3178
}
3279

3380
impl GraphicsContext {
@@ -48,19 +95,19 @@ impl GraphicsContext {
4895
/// - Ensure that the provided handles are valid to draw a 2D buffer to, and are valid for the
4996
/// lifetime of the GraphicsContext
5097
pub unsafe fn from_raw(raw_window_handle: RawWindowHandle, raw_display_handle: RawDisplayHandle) -> Result<Self, SwBufError> {
51-
let imple: Box<dyn GraphicsContextImpl> = match (raw_window_handle, raw_display_handle) {
98+
let imple: Dispatch = match (raw_window_handle, raw_display_handle) {
5299
#[cfg(all(feature = "x11", any(target_os = "linux", target_os = "freebsd")))]
53-
(RawWindowHandle::Xlib(xlib_window_handle), RawDisplayHandle::Xlib(xlib_display_handle)) => Box::new(x11::X11Impl::new(xlib_window_handle, xlib_display_handle)?),
100+
(RawWindowHandle::Xlib(xlib_window_handle), RawDisplayHandle::Xlib(xlib_display_handle)) => Dispatch::X11(x11::X11Impl::new(xlib_window_handle, xlib_display_handle)?),
54101
#[cfg(all(feature = "wayland", any(target_os = "linux", target_os = "freebsd")))]
55-
(RawWindowHandle::Wayland(wayland_window_handle), RawDisplayHandle::Wayland(wayland_display_handle)) => Box::new(wayland::WaylandImpl::new(wayland_window_handle, wayland_display_handle)?),
102+
(RawWindowHandle::Wayland(wayland_window_handle), RawDisplayHandle::Wayland(wayland_display_handle)) => Dispatch::Wayland(wayland::WaylandImpl::new(wayland_window_handle, wayland_display_handle)?),
56103
#[cfg(target_os = "windows")]
57-
(RawWindowHandle::Win32(win32_handle), _) => Box::new(win32::Win32Impl::new(&win32_handle)?),
104+
(RawWindowHandle::Win32(win32_handle), _) => Dispatch::Win32(win32::Win32Impl::new(&win32_handle)?),
58105
#[cfg(target_os = "macos")]
59-
(RawWindowHandle::AppKit(appkit_handle), _) => Box::new(cg::CGImpl::new(appkit_handle)?),
106+
(RawWindowHandle::AppKit(appkit_handle), _) => Dispatch::CG(cg::CGImpl::new(appkit_handle)?),
60107
#[cfg(target_arch = "wasm32")]
61-
(RawWindowHandle::Web(web_handle), _) => Box::new(web::WebImpl::new(web_handle)?),
108+
(RawWindowHandle::Web(web_handle), _) => Dispatch::Web(web::WebImpl::new(web_handle)?),
62109
#[cfg(target_os = "redox")]
63-
(RawWindowHandle::Orbital(orbital_handle), _) => Box::new(orbital::OrbitalImpl::new(orbital_handle)?),
110+
(RawWindowHandle::Orbital(orbital_handle), _) => Dispatch::Orbital(orbital::OrbitalImpl::new(orbital_handle)?),
64111
(unimplemented_window_handle, unimplemented_display_handle) => return Err(SwBufError::UnsupportedPlatform {
65112
human_readable_window_platform_name: window_handle_type_name(&unimplemented_window_handle),
66113
human_readable_display_platform_name: display_handle_type_name(&unimplemented_display_handle),
@@ -70,7 +117,7 @@ impl GraphicsContext {
70117
};
71118

72119
Ok(Self {
73-
graphics_context_impl: imple,
120+
graphics_context_impl: Box::new(imple)
74121
})
75122
}
76123

@@ -109,10 +156,6 @@ impl GraphicsContext {
109156
}
110157
}
111158

112-
trait GraphicsContextImpl {
113-
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16);
114-
}
115-
116159
fn window_handle_type_name(handle: &RawWindowHandle) -> &'static str {
117160
match handle {
118161
RawWindowHandle::Xlib(_) => "Xlib",

src/orbital.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use std::{
55
str,
66
};
77

8-
use crate::GraphicsContextImpl;
98
use crate::SwBufError;
109

1110
struct OrbitalMap {
@@ -49,10 +48,8 @@ impl OrbitalImpl {
4948
pub fn new(handle: OrbitalWindowHandle) -> Result<Self, SwBufError> {
5049
Ok(Self { handle })
5150
}
52-
}
5351

54-
impl GraphicsContextImpl for OrbitalImpl {
55-
unsafe fn set_buffer(&mut self, buffer: &[u32], width_u16: u16, height_u16: u16) {
52+
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width_u16: u16, height_u16: u16) {
5653
let window_fd = self.handle.window as usize;
5754

5855
// Read the current width and size

src/wayland/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{error::unwrap, GraphicsContextImpl, SwBufError};
1+
use crate::{error::unwrap, SwBufError};
22
use raw_window_handle::{WaylandDisplayHandle, WaylandWindowHandle};
33
use std::collections::VecDeque;
44
use wayland_client::{
@@ -78,10 +78,8 @@ impl WaylandImpl {
7878
self.buffers.push_back(buffer);
7979
self.buffers.back().unwrap()
8080
}
81-
}
8281

83-
impl GraphicsContextImpl for WaylandImpl {
84-
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
82+
pub(super) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
8583
let _ = self.event_queue.dispatch_pending(&mut State);
8684

8785
let surface = self.surface.clone();

src/web.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use web_sys::CanvasRenderingContext2d;
55
use web_sys::HtmlCanvasElement;
66
use web_sys::ImageData;
77

8-
use crate::GraphicsContextImpl;
98
use crate::SwBufError;
109

1110
pub struct WebImpl {
@@ -60,10 +59,8 @@ impl WebImpl {
6059

6160
Ok(Self { canvas, ctx })
6261
}
63-
}
6462

65-
impl GraphicsContextImpl for WebImpl {
66-
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
63+
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
6764
self.canvas.set_width(width.into());
6865
self.canvas.set_height(height.into());
6966

src/win32.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
//! Implementation of software buffering for Windows.
2-
//!
2+
//!
33
//! This module converts the input buffer into a bitmap and then stretches it to the window.
44
5-
use crate::{GraphicsContextImpl, SwBufError};
5+
use crate::SwBufError;
66
use raw_window_handle::Win32WindowHandle;
77

8-
use std::mem;
98
use std::io;
9+
use std::mem;
1010
use std::os::raw::c_int;
1111

1212
use windows_sys::Win32::Foundation::HWND;
@@ -33,9 +33,9 @@ struct BitmapInfo {
3333

3434
impl Win32Impl {
3535
/// Create a new `Win32Impl` from a `Win32WindowHandle`.
36-
///
36+
///
3737
/// # Safety
38-
///
38+
///
3939
/// The `Win32WindowHandle` must be a valid window handle.
4040
pub unsafe fn new(handle: &Win32WindowHandle) -> Result<Self, crate::SwBufError> {
4141
// It is valid for the window handle to be null here. Error out if it is.
@@ -56,17 +56,12 @@ impl Win32Impl {
5656
));
5757
}
5858

59-
Ok(Self {
60-
dc,
61-
window: hwnd,
62-
})
59+
Ok(Self { dc, window: hwnd })
6360
}
64-
}
6561

66-
impl GraphicsContextImpl for Win32Impl {
67-
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
62+
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
6863
// Create a new bitmap info struct.
69-
let mut bitmap_info: BitmapInfo =mem::zeroed();
64+
let mut bitmap_info: BitmapInfo = mem::zeroed();
7065

7166
bitmap_info.bmi_header.biSize = mem::size_of::<BITMAPINFOHEADER>() as u32;
7267
bitmap_info.bmi_header.biPlanes = 1;

src/x11.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
//! Implementation of software buffering for X11.
2-
//!
2+
//!
33
//! This module converts the input buffer into an XImage and then sends it over the wire to be
44
//! drawn. A more effective implementation would use shared memory instead of the wire. In
55
//! addition, we may also want to blit to a pixmap instead of a window.
66
7-
use crate::{GraphicsContextImpl, SwBufError};
7+
use crate::SwBufError;
88
use raw_window_handle::{XlibDisplayHandle, XlibWindowHandle};
99
use std::os::raw::{c_char, c_uint};
1010
use x11_dl::xlib::{Display, Visual, Xlib, ZPixmap, GC};
@@ -32,9 +32,9 @@ pub struct X11Impl {
3232

3333
impl X11Impl {
3434
/// Create a new `X11Impl` from a `XlibWindowHandle` and `XlibDisplayHandle`.
35-
///
35+
///
3636
/// # Safety
37-
///
37+
///
3838
/// The `XlibWindowHandle` and `XlibDisplayHandle` must be valid.
3939
pub unsafe fn new(
4040
window_handle: XlibWindowHandle,
@@ -83,10 +83,8 @@ impl X11Impl {
8383
depth,
8484
})
8585
}
86-
}
8786

88-
impl GraphicsContextImpl for X11Impl {
89-
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
87+
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
9088
// Create the image from the buffer.
9189
let image = (self.lib.XCreateImage)(
9290
self.display_handle.display as *mut Display,

0 commit comments

Comments
 (0)