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
89mod sealed {
90 pub trait Sealed {}
91 impl<T: super::IsA<super::GLContext>> Sealed for T {}
92}
93
94pub trait GLContextExtManual: sealed::Sealed + IsA<GLContext> + 'static {
95 /// Gets the backing OpenGL context used by `self`.
96 ///
97 /// # Returns
98 ///
99 /// The platform specific backing OpenGL context
100 #[doc(alias = "get_gl_context")]
101 #[doc(alias = "gst_gl_context_get_gl_context")]
102 fn gl_context(&self) -> uintptr_t {
103 unsafe { ffi::gst_gl_context_get_gl_context(self.as_ref().to_glib_none().0) as uintptr_t }
104 }
105
106 /// Get a function pointer to a specified opengl function, `name`. If the the
107 /// specific function does not exist, NULL is returned instead.
108 ///
109 /// Platform specific functions (names starting 'egl', 'glX', 'wgl', etc) can also
110 /// be retrieved using this method.
111 ///
112 /// Note: This function may return valid function pointers that may not be valid
113 /// to call in `self`. The caller is responsible for ensuring that the
114 /// returned function is a valid function to call in `self` by either checking
115 /// the OpenGL API and version or for an appropriate OpenGL extension.
116 ///
117 /// Note: On success, you need to cast the returned function pointer to the
118 /// correct type to be able to call it correctly. On 32-bit Windows, this will
119 /// include the `GSTGLAPI` identifier to use the correct calling convention.
120 /// e.g.
121 ///
122 ///
123 ///
124 /// **⚠️ The following code is in C ⚠️**
125 ///
126 /// ```C
127 /// void (GSTGLAPI *PFN_glGetIntegerv) (GLenum name, GLint * ret)
128 /// ```
129 /// ## `name`
130 /// an opengl function name
131 ///
132 /// # Returns
133 ///
134 /// a function pointer or [`None`]
135 #[doc(alias = "get_proc_address")]
136 #[doc(alias = "gst_gl_context_get_proc_address")]
137 fn proc_address(&self, name: &str) -> uintptr_t {
138 unsafe {
139 ffi::gst_gl_context_get_proc_address(
140 self.as_ref().to_glib_none().0,
141 name.to_glib_none().0,
142 ) as uintptr_t
143 }
144 }
145
146 /// Execute `func` in the OpenGL thread of `self` with `data`
147 ///
148 /// MT-safe
149 /// ## `func`
150 /// a `GstGLContextThreadFunc`
151 #[doc(alias = "gst_gl_context_thread_add")]
152 fn thread_add<F: FnOnce(&Self) + Send>(&self, func: F) {
153 let mut func = std::mem::ManuallyDrop::new(func);
154 let user_data: *mut F = &mut *func;
155
156 unsafe extern "C" fn trampoline<O: IsA<GLContext>, F: FnOnce(&O) + Send>(
157 context: *mut ffi::GstGLContext,
158 data: glib::ffi::gpointer,
159 ) {
160 let func = std::ptr::read(data as *mut F);
161 let context = GLContext::from_glib_borrow(context);
162 func(context.unsafe_cast_ref())
163 }
164
165 unsafe {
166 ffi::gst_gl_context_thread_add(
167 self.as_ref().to_glib_none().0,
168 Some(trampoline::<Self, F>),
169 user_data as glib::ffi::gpointer,
170 );
171 }
172 }
173}
174
175impl<O: IsA<GLContext>> GLContextExtManual for O {}