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