Skip to main content

surfman/mesa_surfaceless/
connection.rs

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