surfman/platform/unix/generic/
connection.rs

1// surfman/surfman/src/platform/unix/generic/connection.rs
2//
3//! Represents a connection to a display server.
4
5use super::device::{Adapter, Device, NativeDevice};
6use super::surface::NativeWidget;
7use crate::egl;
8use crate::egl::types::{EGLAttrib, EGLDisplay};
9use crate::info::GLApi;
10use crate::platform::generic::egl::device::EGL_FUNCTIONS;
11use crate::platform::generic::egl::ffi::EGL_PLATFORM_SURFACELESS_MESA;
12use crate::Error;
13
14use euclid::default::Size2D;
15
16use std::os::raw::c_void;
17use std::sync::Arc;
18
19/// A no-op connection.
20#[derive(Clone)]
21pub struct Connection {
22    pub(crate) native_connection: Arc<NativeConnectionWrapper>,
23}
24
25/// Native connections.
26#[derive(Clone)]
27pub struct NativeConnection(Arc<NativeConnectionWrapper>);
28
29/// Native connections.
30pub struct NativeConnectionWrapper {
31    pub(crate) egl_display: EGLDisplay,
32}
33
34unsafe impl Send for NativeConnectionWrapper {}
35unsafe impl Sync for NativeConnectionWrapper {}
36
37impl Connection {
38    /// Opens a surfaceless Mesa display.
39    #[inline]
40    pub fn new() -> Result<Connection, Error> {
41        unsafe {
42            EGL_FUNCTIONS.with(|egl| {
43                let egl_display_attributes = [egl::NONE as EGLAttrib];
44                let egl_display = egl.GetPlatformDisplay(
45                    EGL_PLATFORM_SURFACELESS_MESA,
46                    egl::DEFAULT_DISPLAY as *mut c_void,
47                    egl_display_attributes.as_ptr(),
48                );
49                if egl_display == egl::NO_DISPLAY {
50                    return Err(Error::ConnectionFailed);
51                }
52
53                let (mut egl_major_version, mut egl_minor_version) = (0, 0);
54                let ok =
55                    egl.Initialize(egl_display, &mut egl_major_version, &mut egl_minor_version);
56                if ok == egl::FALSE {
57                    return Err(Error::ConnectionFailed);
58                }
59
60                let native_connection =
61                    NativeConnection(Arc::new(NativeConnectionWrapper { egl_display }));
62
63                Connection::from_native_connection(native_connection)
64            })
65        }
66    }
67
68    /// An alias for `Connection::new()`, present for consistency with other backends.
69    #[inline]
70    pub unsafe fn from_native_connection(
71        native_connection: NativeConnection,
72    ) -> Result<Connection, Error> {
73        Ok(Connection {
74            native_connection: native_connection.0,
75        })
76    }
77
78    /// Returns the underlying native connection.
79    #[inline]
80    pub fn native_connection(&self) -> NativeConnection {
81        NativeConnection(self.native_connection.clone())
82    }
83
84    /// Returns the OpenGL API flavor that this connection supports (OpenGL or OpenGL ES).
85    #[inline]
86    pub fn gl_api(&self) -> GLApi {
87        GLApi::GL
88    }
89
90    /// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
91    ///
92    /// This is an alias for `Connection::create_hardware_adapter()`.
93    #[inline]
94    pub fn create_adapter(&self) -> Result<Adapter, Error> {
95        self.create_hardware_adapter()
96    }
97
98    /// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
99    ///
100    /// On the OSMesa backend, this returns a software adapter.
101    #[inline]
102    pub fn create_hardware_adapter(&self) -> Result<Adapter, Error> {
103        Ok(Adapter::hardware())
104    }
105
106    /// Returns the "best" adapter on this system, preferring low-power hardware adapters.
107    ///
108    /// On the OSMesa backend, this returns a software adapter.
109    #[inline]
110    pub fn create_low_power_adapter(&self) -> Result<Adapter, Error> {
111        Ok(Adapter::low_power())
112    }
113
114    /// Returns the "best" adapter on this system, preferring software adapters.
115    #[inline]
116    pub fn create_software_adapter(&self) -> Result<Adapter, Error> {
117        Ok(Adapter::software())
118    }
119
120    /// Opens the hardware device corresponding to the given adapter.
121    ///
122    /// Device handles are local to a single thread.
123    #[inline]
124    pub fn create_device(&self, adapter: &Adapter) -> Result<Device, Error> {
125        Device::new(self, adapter)
126    }
127
128    /// An alias for `connection.create_device()` with the default adapter.
129    #[inline]
130    pub unsafe fn create_device_from_native_device(
131        &self,
132        _: NativeDevice,
133    ) -> Result<Device, Error> {
134        Device::new(self, &self.create_adapter()?)
135    }
136
137    /// Opens the display connection corresponding to the given `RawDisplayHandle`.
138    #[cfg(feature = "sm-raw-window-handle-05")]
139    pub fn from_raw_display_handle(_: rwh_05::RawDisplayHandle) -> Result<Connection, Error> {
140        Err(Error::IncompatibleNativeWidget)
141    }
142
143    /// Opens the display connection corresponding to the given `DisplayHandle`.
144    #[cfg(feature = "sm-raw-window-handle-06")]
145    pub fn from_display_handle(_: rwh_06::DisplayHandle) -> Result<Connection, Error> {
146        Err(Error::IncompatibleNativeWidget)
147    }
148
149    /// Create a native widget from a raw pointer
150    pub unsafe fn create_native_widget_from_ptr(
151        &self,
152        _raw: *mut c_void,
153        _size: Size2D<i32>,
154    ) -> NativeWidget {
155        NativeWidget
156    }
157
158    /// Create a native widget type from the given `RawWindowHandle`.
159    #[cfg(feature = "sm-raw-window-handle-05")]
160    #[inline]
161    pub fn create_native_widget_from_raw_window_handle(
162        &self,
163        _: rwh_05::RawWindowHandle,
164        _size: Size2D<i32>,
165    ) -> Result<NativeWidget, Error> {
166        Err(Error::IncompatibleNativeWidget)
167    }
168
169    /// Create a native widget type from the given `WindowHandle`.
170    #[cfg(feature = "sm-raw-window-handle-06")]
171    #[inline]
172    pub fn create_native_widget_from_window_handle(
173        &self,
174        _: rwh_06::WindowHandle,
175        _size: Size2D<i32>,
176    ) -> Result<NativeWidget, Error> {
177        Err(Error::IncompatibleNativeWidget)
178    }
179}