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