Skip to main content

surfman/multi/
connection.rs

1//! A connection abstraction that allows the choice of backends dynamically.
2
3use super::device::{Adapter, Device, NativeDevice};
4use super::surface::NativeWidget;
5use crate::connection::Connection as ConnectionInterface;
6use crate::device::Device as DeviceInterface;
7use crate::Error;
8use crate::GLApi;
9
10use euclid::default::Size2D;
11
12use std::os::raw::c_void;
13
14/// A connection to the display server.
15pub enum Connection<Def, Alt>
16where
17    Def: DeviceInterface,
18    Alt: DeviceInterface,
19    Def::Connection: ConnectionInterface,
20    Alt::Connection: ConnectionInterface,
21{
22    /// The default connection to the display server.
23    Default(Def::Connection),
24    /// The alternate connection to the display server.
25    Alternate(Alt::Connection),
26}
27
28impl<Def, Alt> Clone for Connection<Def, Alt>
29where
30    Def: DeviceInterface,
31    Alt: DeviceInterface,
32    Def::Connection: Clone,
33    Alt::Connection: Clone,
34{
35    fn clone(&self) -> Self {
36        match self {
37            Connection::Default(ref connection) => Connection::Default(connection.clone()),
38            Connection::Alternate(ref connection) => Connection::Alternate(connection.clone()),
39        }
40    }
41}
42
43/// The native connection type.
44pub enum NativeConnection<Def, Alt>
45where
46    Def: DeviceInterface,
47    Alt: DeviceInterface,
48    Def::Connection: ConnectionInterface,
49    Alt::Connection: ConnectionInterface,
50{
51    /// The default native connection type.
52    Default(<Def::Connection as ConnectionInterface>::NativeConnection),
53    /// The alternate native connection type.
54    Alternate(<Alt::Connection as ConnectionInterface>::NativeConnection),
55}
56
57impl<Def, Alt> Connection<Def, Alt>
58where
59    Def: DeviceInterface,
60    Alt: DeviceInterface,
61    Def::Connection: ConnectionInterface<Device = Def>,
62    Alt::Connection: ConnectionInterface<Device = Alt>,
63{
64    /// Connects to the default display.
65    #[inline]
66    pub fn new() -> Result<Connection<Def, Alt>, Error> {
67        match <Def::Connection>::new() {
68            Ok(connection) => Ok(Connection::Default(connection)),
69            Err(_) => <Alt::Connection>::new().map(Connection::Alternate),
70        }
71    }
72
73    /// Returns the native connection corresponding to this connection.
74    pub fn native_connection(&self) -> NativeConnection<Def, Alt> {
75        match *self {
76            Connection::Default(ref connection) => {
77                NativeConnection::Default(connection.native_connection())
78            }
79            Connection::Alternate(ref connection) => {
80                NativeConnection::Alternate(connection.native_connection())
81            }
82        }
83    }
84
85    /// Returns the OpenGL API flavor that this connection supports (OpenGL or OpenGL ES).
86    pub fn gl_api(&self) -> GLApi {
87        match *self {
88            Connection::Default(ref connection) => connection.gl_api(),
89            Connection::Alternate(ref connection) => connection.gl_api(),
90        }
91    }
92
93    /// Returns the "best" adapter on this system.
94    ///
95    /// This is an alias for `Connection::create_hardware_adapter()`.
96    pub fn create_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
97        match *self {
98            Connection::Default(ref connection) => {
99                connection.create_adapter().map(Adapter::Default)
100            }
101            Connection::Alternate(ref connection) => {
102                connection.create_adapter().map(Adapter::Alternate)
103            }
104        }
105    }
106
107    /// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
108    pub fn create_hardware_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
109        match *self {
110            Connection::Default(ref connection) => {
111                connection.create_hardware_adapter().map(Adapter::Default)
112            }
113            Connection::Alternate(ref connection) => {
114                connection.create_hardware_adapter().map(Adapter::Alternate)
115            }
116        }
117    }
118
119    /// Returns the "best" adapter on this system, preferring low-power hardware adapters.
120    pub fn create_low_power_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
121        match *self {
122            Connection::Default(ref connection) => {
123                connection.create_low_power_adapter().map(Adapter::Default)
124            }
125            Connection::Alternate(ref connection) => connection
126                .create_low_power_adapter()
127                .map(Adapter::Alternate),
128        }
129    }
130
131    /// Returns the "best" adapter on this system, preferring software adapters.
132    pub fn create_software_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
133        match *self {
134            Connection::Default(ref connection) => {
135                connection.create_software_adapter().map(Adapter::Default)
136            }
137            Connection::Alternate(ref connection) => {
138                connection.create_software_adapter().map(Adapter::Alternate)
139            }
140        }
141    }
142
143    /// Opens the hardware device corresponding to the given adapter.
144    ///
145    /// Device handles are local to a single thread.
146    pub fn create_device(&self, adapter: &Adapter<Def, Alt>) -> Result<Device<Def, Alt>, Error> {
147        match (self, adapter) {
148            (Connection::Default(connection), Adapter::Default(adapter)) => {
149                connection.create_device(adapter).map(Device::Default)
150            }
151            (Connection::Alternate(connection), Adapter::Alternate(adapter)) => {
152                connection.create_device(adapter).map(Device::Alternate)
153            }
154            _ => Err(Error::IncompatibleAdapter),
155        }
156    }
157
158    /// Wraps a native device in a device.
159    #[inline]
160    pub unsafe fn create_device_from_native_device(
161        &self,
162        native_device: NativeDevice<Def, Alt>,
163    ) -> Result<Device<Def, Alt>, Error> {
164        match self {
165            Connection::Default(connection) => match native_device {
166                NativeDevice::Default(native_device) => connection
167                    .create_device_from_native_device(native_device)
168                    .map(Device::Default),
169                _ => Err(Error::IncompatibleNativeDevice),
170            },
171            Connection::Alternate(connection) => match native_device {
172                NativeDevice::Alternate(native_device) => connection
173                    .create_device_from_native_device(native_device)
174                    .map(Device::Alternate),
175                _ => Err(Error::IncompatibleNativeDevice),
176            },
177        }
178    }
179
180    /// Opens the display connection corresponding to the given `RawDisplayHandle.
181    #[cfg(feature = "sm-raw-window-handle-05")]
182    pub fn from_raw_display_handle(
183        raw_handle: rwh_05::RawDisplayHandle,
184    ) -> Result<Connection<Def, Alt>, Error> {
185        match <Def::Connection>::from_raw_display_handle(raw_handle) {
186            Ok(connection) => Ok(Connection::Default(connection)),
187            Err(_) => {
188                <Alt::Connection>::from_raw_display_handle(raw_handle).map(Connection::Alternate)
189            }
190        }
191    }
192
193    /// Opens the display connection corresponding to the given `DisplayHandle`.
194    #[cfg(feature = "sm-raw-window-handle-06")]
195    pub fn from_display_handle(
196        handle: rwh_06::DisplayHandle,
197    ) -> Result<Connection<Def, Alt>, Error> {
198        match <Def::Connection>::from_display_handle(handle) {
199            Ok(connection) => Ok(Connection::Default(connection)),
200            Err(_) => <Alt::Connection>::from_display_handle(handle).map(Connection::Alternate),
201        }
202    }
203
204    /// Create a native widget from a raw pointer
205    pub unsafe fn create_native_widget_from_ptr(
206        &self,
207        raw: *mut c_void,
208        size: Size2D<i32>,
209    ) -> NativeWidget<Def, Alt> {
210        match *self {
211            Connection::Default(ref connection) => {
212                NativeWidget::Default(connection.create_native_widget_from_ptr(raw, size))
213            }
214            Connection::Alternate(ref connection) => {
215                NativeWidget::Alternate(connection.create_native_widget_from_ptr(raw, size))
216            }
217        }
218    }
219
220    /// Create a native widget type from the given `RawWindowHandle`.
221    #[cfg(feature = "sm-raw-window-handle-05")]
222    pub fn create_native_widget_from_raw_window_handle(
223        &self,
224        raw_handle: rwh_05::RawWindowHandle,
225        size: Size2D<i32>,
226    ) -> Result<NativeWidget<Def, Alt>, Error> {
227        match *self {
228            Connection::Default(ref connection) => connection
229                .create_native_widget_from_raw_window_handle(raw_handle, size)
230                .map(NativeWidget::Default),
231            Connection::Alternate(ref connection) => connection
232                .create_native_widget_from_raw_window_handle(raw_handle, size)
233                .map(NativeWidget::Alternate),
234        }
235    }
236
237    /// Create a native widget type from the given `WindowHandle`.
238    #[cfg(feature = "sm-raw-window-handle-06")]
239    pub fn create_native_widget_from_window_handle(
240        &self,
241        handle: rwh_06::WindowHandle,
242        size: Size2D<i32>,
243    ) -> Result<NativeWidget<Def, Alt>, Error> {
244        match *self {
245            Connection::Default(ref connection) => connection
246                .create_native_widget_from_window_handle(handle, size)
247                .map(NativeWidget::Default),
248            Connection::Alternate(ref connection) => connection
249                .create_native_widget_from_window_handle(handle, size)
250                .map(NativeWidget::Alternate),
251        }
252    }
253}
254
255impl<Def, Alt> ConnectionInterface for Connection<Def, Alt>
256where
257    Def: DeviceInterface,
258    Alt: DeviceInterface,
259    Def::Connection: ConnectionInterface<Device = Def>,
260    Alt::Connection: ConnectionInterface<Device = Alt>,
261{
262    type Adapter = Adapter<Def, Alt>;
263    type Device = Device<Def, Alt>;
264    type NativeConnection = NativeConnection<Def, Alt>;
265    type NativeDevice = NativeDevice<Def, Alt>;
266    type NativeWidget = NativeWidget<Def, Alt>;
267
268    #[inline]
269    fn new() -> Result<Connection<Def, Alt>, Error> {
270        Connection::new()
271    }
272
273    #[inline]
274    fn native_connection(&self) -> NativeConnection<Def, Alt> {
275        Connection::native_connection(self)
276    }
277
278    #[inline]
279    fn gl_api(&self) -> GLApi {
280        Connection::gl_api(self)
281    }
282
283    #[inline]
284    fn create_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
285        Connection::create_adapter(self)
286    }
287
288    #[inline]
289    fn create_hardware_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
290        Connection::create_hardware_adapter(self)
291    }
292
293    #[inline]
294    fn create_low_power_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
295        Connection::create_low_power_adapter(self)
296    }
297
298    #[inline]
299    fn create_software_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
300        Connection::create_software_adapter(self)
301    }
302
303    #[inline]
304    fn create_device(&self, adapter: &Adapter<Def, Alt>) -> Result<Device<Def, Alt>, Error> {
305        Connection::create_device(self, adapter)
306    }
307
308    #[inline]
309    unsafe fn create_device_from_native_device(
310        &self,
311        native_device: NativeDevice<Def, Alt>,
312    ) -> Result<Device<Def, Alt>, Error> {
313        Connection::create_device_from_native_device(self, native_device)
314    }
315
316    #[cfg(feature = "sm-raw-window-handle-05")]
317    fn from_raw_display_handle(
318        raw_handle: rwh_05::RawDisplayHandle,
319    ) -> Result<Connection<Def, Alt>, Error> {
320        Connection::from_raw_display_handle(raw_handle)
321    }
322
323    #[cfg(feature = "sm-raw-window-handle-06")]
324    fn from_display_handle(handle: rwh_06::DisplayHandle) -> Result<Connection<Def, Alt>, Error> {
325        Connection::from_display_handle(handle)
326    }
327
328    #[inline]
329    unsafe fn create_native_widget_from_ptr(
330        &self,
331        raw: *mut c_void,
332        size: Size2D<i32>,
333    ) -> NativeWidget<Def, Alt> {
334        Connection::create_native_widget_from_ptr(self, raw, size)
335    }
336
337    #[cfg(feature = "sm-raw-window-handle-05")]
338    fn create_native_widget_from_raw_window_handle(
339        &self,
340        raw_handle: rwh_05::RawWindowHandle,
341        size: Size2D<i32>,
342    ) -> Result<Self::NativeWidget, Error> {
343        Connection::create_native_widget_from_raw_window_handle(self, raw_handle, size)
344    }
345
346    #[cfg(feature = "sm-raw-window-handle-06")]
347    fn create_native_widget_from_window_handle(
348        &self,
349        handle: rwh_06::WindowHandle,
350        size: Size2D<i32>,
351    ) -> Result<Self::NativeWidget, Error> {
352        Connection::create_native_widget_from_window_handle(self, handle, size)
353    }
354}