surfman/platform/generic/multi/
connection.rs

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