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 {}