Skip to main content

gstreamer_gl/
gl_context.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::{prelude::*, translate::*};
4use libc::uintptr_t;
5
6use crate::{GLAPI, GLContext, GLDisplay, GLPlatform, ffi};
7
8impl GLContext {
9    /// Wraps an existing OpenGL context into a [`GLContext`][crate::GLContext].
10    ///
11    /// Note: The caller is responsible for ensuring that the OpenGL context
12    /// represented by `handle` stays alive while the returned [`GLContext`][crate::GLContext] is
13    /// active.
14    ///
15    /// `context_type` must not be `GST_GL_PLATFORM_NONE` or `GST_GL_PLATFORM_ANY`
16    ///
17    /// `available_apis` must not be `GST_GL_API_NONE` or `GST_GL_API_ANY`
18    /// ## `display`
19    /// a [`GLDisplay`][crate::GLDisplay]
20    /// ## `handle`
21    /// the OpenGL context to wrap
22    /// ## `context_type`
23    /// a [`GLPlatform`][crate::GLPlatform] specifying the type of context in `handle`
24    /// ## `available_apis`
25    /// a [`GLAPI`][crate::GLAPI] containing the available OpenGL apis in `handle`
26    ///
27    /// # Returns
28    ///
29    /// a [`GLContext`][crate::GLContext] wrapping `handle`
30    pub unsafe fn new_wrapped<T: IsA<GLDisplay>>(
31        display: &T,
32        handle: uintptr_t,
33        context_type: GLPlatform,
34        available_apis: GLAPI,
35    ) -> Option<Self> {
36        unsafe {
37            from_glib_full(ffi::gst_gl_context_new_wrapped(
38                display.as_ref().to_glib_none().0,
39                handle,
40                context_type.into_glib(),
41                available_apis.into_glib(),
42            ))
43        }
44    }
45
46    /// ## `context_type`
47    /// a [`GLPlatform`][crate::GLPlatform] specifying the type of context to retrieve
48    ///
49    /// # Returns
50    ///
51    /// The OpenGL context handle current in the calling thread or [`None`]
52    #[doc(alias = "get_current_gl_context")]
53    #[doc(alias = "gst_gl_context_get_current_gl_context")]
54    pub fn current_gl_context(context_type: GLPlatform) -> uintptr_t {
55        skip_assert_initialized!();
56        unsafe { ffi::gst_gl_context_get_current_gl_context(context_type.into_glib()) as uintptr_t }
57    }
58
59    /// Attempts to use the `context_type` specific GetProcAddress implementations
60    /// to retrieve `name`.
61    ///
62    /// See also [`GLContextExtManual::proc_address()`][crate::prelude::GLContextExtManual::proc_address()].
63    /// ## `context_type`
64    /// a [`GLPlatform`][crate::GLPlatform]
65    /// ## `gl_api`
66    /// a [`GLAPI`][crate::GLAPI]
67    /// ## `name`
68    /// the name of the function to retrieve
69    ///
70    /// # Returns
71    ///
72    /// a function pointer for `name`, or [`None`]
73    #[doc(alias = "get_proc_address_with_platform")]
74    #[doc(alias = "gst_gl_context_get_proc_address_with_platform")]
75    pub fn proc_address_with_platform(
76        context_type: GLPlatform,
77        gl_api: GLAPI,
78        name: &str,
79    ) -> uintptr_t {
80        skip_assert_initialized!();
81        unsafe {
82            ffi::gst_gl_context_get_proc_address_with_platform(
83                context_type.into_glib(),
84                gl_api.into_glib(),
85                name.to_glib_none().0,
86            ) as uintptr_t
87        }
88    }
89}
90
91pub trait GLContextExtManual: IsA<GLContext> + 'static {
92    /// Gets the backing OpenGL context used by `self`.
93    ///
94    /// # Returns
95    ///
96    /// The platform specific backing OpenGL context
97    #[doc(alias = "get_gl_context")]
98    #[doc(alias = "gst_gl_context_get_gl_context")]
99    fn gl_context(&self) -> uintptr_t {
100        unsafe { ffi::gst_gl_context_get_gl_context(self.as_ref().to_glib_none().0) as uintptr_t }
101    }
102
103    /// Get a function pointer to a specified opengl function, `name`. If the the
104    /// specific function does not exist, NULL is returned instead.
105    ///
106    /// Platform specific functions (names starting 'egl', 'glX', 'wgl', etc) can also
107    /// be retrieved using this method.
108    ///
109    /// Note: This function may return valid function pointers that may not be valid
110    /// to call in `self`. The caller is responsible for ensuring that the
111    /// returned function is a valid function to call in `self` by either checking
112    /// the OpenGL API and version or for an appropriate OpenGL extension.
113    ///
114    /// Note: On success, you need to cast the returned function pointer to the
115    /// correct type to be able to call it correctly. On 32-bit Windows, this will
116    /// include the `GSTGLAPI` identifier to use the correct calling convention.
117    /// e.g.
118    ///
119    ///
120    ///
121    /// **⚠️ The following code is in C ⚠️**
122    ///
123    /// ```C
124    /// void (GSTGLAPI *PFN_glGetIntegerv) (GLenum name, GLint * ret)
125    /// ```
126    /// ## `name`
127    /// an opengl function name
128    ///
129    /// # Returns
130    ///
131    /// a function pointer or [`None`]
132    #[doc(alias = "get_proc_address")]
133    #[doc(alias = "gst_gl_context_get_proc_address")]
134    fn proc_address(&self, name: &str) -> uintptr_t {
135        unsafe {
136            ffi::gst_gl_context_get_proc_address(
137                self.as_ref().to_glib_none().0,
138                name.to_glib_none().0,
139            ) as uintptr_t
140        }
141    }
142
143    /// Execute `func` in the OpenGL thread of `self` with `data`
144    ///
145    /// MT-safe
146    /// ## `func`
147    /// a `GstGLContextThreadFunc`
148    #[doc(alias = "gst_gl_context_thread_add")]
149    fn thread_add<F: FnOnce(&Self) + Send>(&self, func: F) {
150        let mut func = std::mem::ManuallyDrop::new(func);
151        let user_data: *mut F = &mut *func;
152
153        unsafe extern "C" fn trampoline<O: IsA<GLContext>, F: FnOnce(&O) + Send>(
154            context: *mut ffi::GstGLContext,
155            data: glib::ffi::gpointer,
156        ) {
157            unsafe {
158                let func = std::ptr::read(data as *mut F);
159                let context = GLContext::from_glib_borrow(context);
160                func(context.unsafe_cast_ref())
161            }
162        }
163
164        unsafe {
165            ffi::gst_gl_context_thread_add(
166                self.as_ref().to_glib_none().0,
167                Some(trampoline::<Self, F>),
168                user_data as glib::ffi::gpointer,
169            );
170        }
171    }
172}
173
174impl<O: IsA<GLContext>> GLContextExtManual for O {}