@@ -27,7 +27,54 @@ use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandl
27
27
/// An instance of this struct contains the platform-specific data that must be managed in order to
28
28
/// write to a window on that platform.
29
29
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 ) ,
31
78
}
32
79
33
80
impl GraphicsContext {
@@ -48,19 +95,19 @@ impl GraphicsContext {
48
95
/// - Ensure that the provided handles are valid to draw a 2D buffer to, and are valid for the
49
96
/// lifetime of the GraphicsContext
50
97
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) {
52
99
#[ 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) ?) ,
54
101
#[ 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) ?) ,
56
103
#[ 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) ?) ,
58
105
#[ 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) ?) ,
60
107
#[ 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) ?) ,
62
109
#[ 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) ?) ,
64
111
( unimplemented_window_handle, unimplemented_display_handle) => return Err ( SwBufError :: UnsupportedPlatform {
65
112
human_readable_window_platform_name : window_handle_type_name ( & unimplemented_window_handle) ,
66
113
human_readable_display_platform_name : display_handle_type_name ( & unimplemented_display_handle) ,
@@ -70,7 +117,7 @@ impl GraphicsContext {
70
117
} ;
71
118
72
119
Ok ( Self {
73
- graphics_context_impl : imple,
120
+ graphics_context_impl : Box :: new ( imple)
74
121
} )
75
122
}
76
123
@@ -109,10 +156,6 @@ impl GraphicsContext {
109
156
}
110
157
}
111
158
112
- trait GraphicsContextImpl {
113
- unsafe fn set_buffer ( & mut self , buffer : & [ u32 ] , width : u16 , height : u16 ) ;
114
- }
115
-
116
159
fn window_handle_type_name ( handle : & RawWindowHandle ) -> & ' static str {
117
160
match handle {
118
161
RawWindowHandle :: Xlib ( _) => "Xlib" ,
0 commit comments