Skip to main content

baseview/gl/
mod.rs

1use std::ffi::c_void;
2use std::marker::PhantomData;
3use std::panic::AssertUnwindSafe;
4// On X11 creating the context is a two step process
5#[cfg(not(target_os = "linux"))]
6use raw_window_handle::RawWindowHandle;
7
8#[cfg(target_os = "windows")]
9mod win;
10#[cfg(target_os = "windows")]
11use win as platform;
12
13// We need to use this directly within the X11 window creation to negotiate the correct visual
14#[cfg(target_os = "linux")]
15pub(crate) mod x11;
16#[cfg(target_os = "linux")]
17pub(crate) use self::x11 as platform;
18
19#[cfg(target_os = "macos")]
20mod macos;
21#[cfg(target_os = "macos")]
22use macos as platform;
23
24#[derive(Clone, Debug, PartialEq)]
25pub struct GlConfig {
26    pub version: (u8, u8),
27    pub profile: Profile,
28    pub red_bits: u8,
29    pub blue_bits: u8,
30    pub green_bits: u8,
31    pub alpha_bits: u8,
32    pub depth_bits: u8,
33    pub stencil_bits: u8,
34    pub samples: Option<u8>,
35    pub srgb: bool,
36    pub double_buffer: bool,
37    pub vsync: bool,
38}
39
40impl Default for GlConfig {
41    fn default() -> Self {
42        GlConfig {
43            version: (3, 2),
44            profile: Profile::Core,
45            red_bits: 8,
46            blue_bits: 8,
47            green_bits: 8,
48            alpha_bits: 8,
49            depth_bits: 24,
50            stencil_bits: 8,
51            samples: None,
52            srgb: true,
53            double_buffer: true,
54            vsync: false,
55        }
56    }
57}
58
59#[derive(Clone, Copy, Debug, PartialEq, Eq)]
60pub enum Profile {
61    Compatibility,
62    Core,
63}
64
65#[derive(Debug)]
66pub enum GlError {
67    InvalidWindowHandle,
68    VersionNotSupported,
69    CreationFailed(platform::CreationFailedError),
70}
71
72pub struct GlContext {
73    // AssertUnwindSafe should *not* be here, but this is needed for now to keep semver compatibility
74    // Remove this in 0.2
75    context: AssertUnwindSafe<platform::GlContext>,
76    phantom: PhantomData<*mut ()>,
77}
78
79impl GlContext {
80    #[cfg(not(target_os = "linux"))]
81    pub(crate) unsafe fn create(
82        parent: &RawWindowHandle, config: GlConfig,
83    ) -> Result<GlContext, GlError> {
84        platform::GlContext::create(parent, config)
85            .map(|context| GlContext { context: AssertUnwindSafe(context), phantom: PhantomData })
86    }
87
88    /// The X11 version needs to be set up in a different way compared to the Windows and macOS
89    /// versions. So the platform-specific versions should be used to construct the context within
90    /// baseview, and then this object can be passed to the user.
91    #[cfg(target_os = "linux")]
92    pub(crate) fn new(context: platform::GlContext) -> GlContext {
93        GlContext { context: AssertUnwindSafe(context), phantom: PhantomData }
94    }
95
96    pub unsafe fn make_current(&self) {
97        self.context.make_current();
98    }
99
100    pub unsafe fn make_not_current(&self) {
101        self.context.make_not_current();
102    }
103
104    pub fn get_proc_address(&self, symbol: &str) -> *const c_void {
105        self.context.get_proc_address(symbol)
106    }
107
108    pub fn swap_buffers(&self) {
109        self.context.swap_buffers();
110    }
111
112    /// On macOS the `NSOpenGLView` needs to be resized separtely from our main view.
113    #[cfg(target_os = "macos")]
114    pub(crate) fn resize(&self, size: objc2_foundation::NSSize) {
115        self.context.resize(size);
116    }
117
118    /// Pointer to the `NSOpenGLView` this context renders into. Used by
119    /// the parent `NSView`'s `hitTest:` override to collapse hits on the
120    /// render subview to the parent, so AppKit routes `mouseDown:` on
121    /// first click in non-key windows.
122    #[cfg(target_os = "macos")]
123    pub(crate) fn ns_view(&self) -> &objc2_app_kit::NSView {
124        self.context.ns_view()
125    }
126}