1//! Implements `buffer_interface::*` traits for enums dispatching to backends
2
3use crate::{backend_interface::*, backends, InitError, Rect, SoftBufferError};
4
5use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
6use std::num::NonZeroU32;
7#[cfg(any(wayland_platform, x11_platform, kms_platform))]
8use std::sync::Arc;
9
10/// A macro for creating the enum used to statically dispatch to the platform-specific implementation.
11macro_rules! make_dispatch {
12 (
13 <$dgen: ident, $wgen: ident> =>
14 $(
15 $(#[$attr:meta])*
16 $name: ident
17 ($context_inner: ty, $surface_inner: ty, $buffer_inner: ty),
18 )*
19 ) => {
20 pub(crate) enum ContextDispatch<$dgen> {
21 $(
22 $(#[$attr])*
23 $name($context_inner),
24 )*
25 }
26
27 impl<D: HasDisplayHandle> ContextDispatch<D> {
28 pub fn variant_name(&self) -> &'static str {
29 match self {
30 $(
31 $(#[$attr])*
32 Self::$name(_) => stringify!($name),
33 )*
34 }
35 }
36 }
37
38 impl<D: HasDisplayHandle> ContextInterface<D> for ContextDispatch<D> {
39 fn new(mut display: D) -> Result<Self, InitError<D>>
40 where
41 D: Sized,
42 {
43 $(
44 $(#[$attr])*
45 match <$context_inner as ContextInterface<D>>::new(display) {
46 Ok(x) => {
47 return Ok(Self::$name(x));
48 }
49 Err(InitError::Unsupported(d)) => display = d,
50 Err(InitError::Failure(f)) => return Err(InitError::Failure(f)),
51 }
52 )*
53
54 Err(InitError::Unsupported(display))
55 }
56 }
57
58 #[allow(clippy::large_enum_variant)] // it's boxed anyways
59 pub(crate) enum SurfaceDispatch<$dgen, $wgen> {
60 $(
61 $(#[$attr])*
62 $name($surface_inner),
63 )*
64 }
65
66 impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for SurfaceDispatch<D, W> {
67 type Context = ContextDispatch<D>;
68 type Buffer<'a> = BufferDispatch<'a, D, W> where Self: 'a;
69
70 fn new(window: W, display: &Self::Context) -> Result<Self, InitError<W>>
71 where
72 W: Sized,
73 Self: Sized {
74 match display {
75 $(
76 $(#[$attr])*
77 ContextDispatch::$name(inner) => Ok(Self::$name(<$surface_inner>::new(window, inner)?)),
78 )*
79 }
80 }
81
82 fn window(&self) -> &W {
83 match self {
84 $(
85 $(#[$attr])*
86 Self::$name(inner) => inner.window(),
87 )*
88 }
89 }
90
91 fn resize(&mut self, width: NonZeroU32, height: NonZeroU32) -> Result<(), SoftBufferError> {
92 match self {
93 $(
94 $(#[$attr])*
95 Self::$name(inner) => inner.resize(width, height),
96 )*
97 }
98 }
99
100 fn buffer_mut(&mut self) -> Result<BufferDispatch<'_, D, W>, SoftBufferError> {
101 match self {
102 $(
103 $(#[$attr])*
104 Self::$name(inner) => Ok(BufferDispatch::$name(inner.buffer_mut()?)),
105 )*
106 }
107 }
108
109 fn fetch(&mut self) -> Result<Vec<u32>, SoftBufferError> {
110 match self {
111 $(
112 $(#[$attr])*
113 Self::$name(inner) => inner.fetch(),
114 )*
115 }
116 }
117 }
118
119 pub(crate) enum BufferDispatch<'a, $dgen, $wgen> {
120 $(
121 $(#[$attr])*
122 $name($buffer_inner),
123 )*
124 }
125
126 impl<'a, D: HasDisplayHandle, W: HasWindowHandle> BufferInterface for BufferDispatch<'a, D, W> {
127 #[inline]
128 fn pixels(&self) -> &[u32] {
129 match self {
130 $(
131 $(#[$attr])*
132 Self::$name(inner) => inner.pixels(),
133 )*
134 }
135 }
136
137 #[inline]
138 fn pixels_mut(&mut self) -> &mut [u32] {
139 match self {
140 $(
141 $(#[$attr])*
142 Self::$name(inner) => inner.pixels_mut(),
143 )*
144 }
145 }
146
147 fn age(&self) -> u8 {
148 match self {
149 $(
150 $(#[$attr])*
151 Self::$name(inner) => inner.age(),
152 )*
153 }
154 }
155
156 fn present(self) -> Result<(), SoftBufferError> {
157 match self {
158 $(
159 $(#[$attr])*
160 Self::$name(inner) => inner.present(),
161 )*
162 }
163 }
164
165 fn present_with_damage(self, damage: &[Rect]) -> Result<(), SoftBufferError> {
166 match self {
167 $(
168 $(#[$attr])*
169 Self::$name(inner) => inner.present_with_damage(damage),
170 )*
171 }
172 }
173 }
174 };
175}
176
177// XXX empty enum with generic bound is invalid?
178
179make_dispatch! {
180 <D, W> =>
181 #[cfg(x11_platform)]
182 X11(Arc<backends::x11::X11DisplayImpl<D>>, backends::x11::X11Impl<D, W>, backends::x11::BufferImpl<'a, D, W>),
183 #[cfg(wayland_platform)]
184 Wayland(Arc<backends::wayland::WaylandDisplayImpl<D>>, backends::wayland::WaylandImpl<D, W>, backends::wayland::BufferImpl<'a, D, W>),
185 #[cfg(kms_platform)]
186 Kms(Arc<backends::kms::KmsDisplayImpl<D>>, backends::kms::KmsImpl<D, W>, backends::kms::BufferImpl<'a, D, W>),
187 #[cfg(target_os = "windows")]
188 Win32(D, backends::win32::Win32Impl<D, W>, backends::win32::BufferImpl<'a, D, W>),
189 #[cfg(target_vendor = "apple")]
190 CoreGraphics(D, backends::cg::CGImpl<D, W>, backends::cg::BufferImpl<'a, D, W>),
191 #[cfg(target_arch = "wasm32")]
192 Web(backends::web::WebDisplayImpl<D>, backends::web::WebImpl<D, W>, backends::web::BufferImpl<'a, D, W>),
193 #[cfg(target_os = "redox")]
194 Orbital(D, backends::orbital::OrbitalImpl<D, W>, backends::orbital::BufferImpl<'a, D, W>),
195}
196