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};
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
43impl<Def, Alt> Connection<Def, Alt>
44where
45    Def: DeviceInterface,
46    Alt: DeviceInterface,
47    Def::Connection: ConnectionInterface<Device = Def>,
48    Alt::Connection: ConnectionInterface<Device = Alt>,
49{
50    /// Connects to the default display.
51    #[inline]
52    pub fn new() -> Result<Connection<Def, Alt>, Error> {
53        match <Def::Connection>::new() {
54            Ok(connection) => Ok(Connection::Default(connection)),
55            Err(_) => <Alt::Connection>::new().map(Connection::Alternate),
56        }
57    }
58
59    /// Returns the OpenGL API flavor that this connection supports (OpenGL or OpenGL ES).
60    pub fn gl_api(&self) -> GLApi {
61        match *self {
62            Connection::Default(ref connection) => connection.gl_api(),
63            Connection::Alternate(ref connection) => connection.gl_api(),
64        }
65    }
66
67    /// Returns the "best" adapter on this system.
68    ///
69    /// This is an alias for `Connection::create_hardware_adapter()`.
70    pub fn create_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
71        match *self {
72            Connection::Default(ref connection) => {
73                connection.create_adapter().map(Adapter::Default)
74            }
75            Connection::Alternate(ref connection) => {
76                connection.create_adapter().map(Adapter::Alternate)
77            }
78        }
79    }
80
81    /// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
82    pub fn create_hardware_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
83        match *self {
84            Connection::Default(ref connection) => {
85                connection.create_hardware_adapter().map(Adapter::Default)
86            }
87            Connection::Alternate(ref connection) => {
88                connection.create_hardware_adapter().map(Adapter::Alternate)
89            }
90        }
91    }
92
93    /// Returns the "best" adapter on this system, preferring low-power hardware adapters.
94    pub fn create_low_power_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
95        match *self {
96            Connection::Default(ref connection) => {
97                connection.create_low_power_adapter().map(Adapter::Default)
98            }
99            Connection::Alternate(ref connection) => connection
100                .create_low_power_adapter()
101                .map(Adapter::Alternate),
102        }
103    }
104
105    /// Returns the "best" adapter on this system, preferring software adapters.
106    pub fn create_software_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
107        match *self {
108            Connection::Default(ref connection) => {
109                connection.create_software_adapter().map(Adapter::Default)
110            }
111            Connection::Alternate(ref connection) => {
112                connection.create_software_adapter().map(Adapter::Alternate)
113            }
114        }
115    }
116
117    /// Opens the hardware device corresponding to the given adapter.
118    ///
119    /// Device handles are local to a single thread.
120    pub fn create_device(&self, adapter: &Adapter<Def, Alt>) -> Result<Device<Def, Alt>, Error> {
121        match (self, adapter) {
122            (Connection::Default(connection), Adapter::Default(adapter)) => {
123                connection.create_device(adapter).map(Device::Default)
124            }
125            (Connection::Alternate(connection), Adapter::Alternate(adapter)) => {
126                connection.create_device(adapter).map(Device::Alternate)
127            }
128            _ => Err(Error::IncompatibleAdapter),
129        }
130    }
131
132    /// Opens the display connection corresponding to the given `DisplayHandle`.
133    pub fn from_display_handle(
134        handle: raw_window_handle::DisplayHandle,
135    ) -> Result<Connection<Def, Alt>, Error> {
136        match <Def::Connection>::from_display_handle(handle) {
137            Ok(connection) => Ok(Connection::Default(connection)),
138            Err(_) => <Alt::Connection>::from_display_handle(handle).map(Connection::Alternate),
139        }
140    }
141
142    /// Create a native widget from a raw pointer
143    pub unsafe fn create_native_widget_from_ptr(
144        &self,
145        raw: *mut c_void,
146        size: Size2D<i32>,
147    ) -> NativeWidget<Def, Alt> {
148        match *self {
149            Connection::Default(ref connection) => {
150                NativeWidget::Default(connection.create_native_widget_from_ptr(raw, size))
151            }
152            Connection::Alternate(ref connection) => {
153                NativeWidget::Alternate(connection.create_native_widget_from_ptr(raw, size))
154            }
155        }
156    }
157
158    /// Create a native widget type from the given `WindowHandle`.
159    pub fn create_native_widget_from_window_handle(
160        &self,
161        handle: raw_window_handle::WindowHandle,
162        size: Size2D<i32>,
163    ) -> Result<NativeWidget<Def, Alt>, Error> {
164        match *self {
165            Connection::Default(ref connection) => connection
166                .create_native_widget_from_window_handle(handle, size)
167                .map(NativeWidget::Default),
168            Connection::Alternate(ref connection) => connection
169                .create_native_widget_from_window_handle(handle, size)
170                .map(NativeWidget::Alternate),
171        }
172    }
173}
174
175impl<Def, Alt> ConnectionInterface for Connection<Def, Alt>
176where
177    Def: DeviceInterface,
178    Alt: DeviceInterface,
179    Def::Connection: ConnectionInterface<Device = Def>,
180    Alt::Connection: ConnectionInterface<Device = Alt>,
181{
182    type Adapter = Adapter<Def, Alt>;
183    type Device = Device<Def, Alt>;
184    type NativeWidget = NativeWidget<Def, Alt>;
185
186    #[inline]
187    fn new() -> Result<Connection<Def, Alt>, Error> {
188        Connection::new()
189    }
190
191    #[inline]
192    fn gl_api(&self) -> GLApi {
193        Connection::gl_api(self)
194    }
195
196    #[inline]
197    fn create_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
198        Connection::create_adapter(self)
199    }
200
201    #[inline]
202    fn create_hardware_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
203        Connection::create_hardware_adapter(self)
204    }
205
206    #[inline]
207    fn create_low_power_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
208        Connection::create_low_power_adapter(self)
209    }
210
211    #[inline]
212    fn create_software_adapter(&self) -> Result<Adapter<Def, Alt>, Error> {
213        Connection::create_software_adapter(self)
214    }
215
216    #[inline]
217    fn create_device(&self, adapter: &Adapter<Def, Alt>) -> Result<Device<Def, Alt>, Error> {
218        Connection::create_device(self, adapter)
219    }
220
221    fn from_display_handle(
222        handle: raw_window_handle::DisplayHandle,
223    ) -> Result<Connection<Def, Alt>, Error> {
224        Connection::from_display_handle(handle)
225    }
226
227    #[inline]
228    unsafe fn create_native_widget_from_ptr(
229        &self,
230        raw: *mut c_void,
231        size: Size2D<i32>,
232    ) -> NativeWidget<Def, Alt> {
233        Connection::create_native_widget_from_ptr(self, raw, size)
234    }
235
236    fn create_native_widget_from_window_handle(
237        &self,
238        handle: raw_window_handle::WindowHandle,
239        size: Size2D<i32>,
240    ) -> Result<Self::NativeWidget, Error> {
241        Connection::create_native_widget_from_window_handle(self, handle, size)
242    }
243}