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 ///
104 /// void (GSTGLAPI *PFN_glGetIntegerv) (GLenum name, GLint * ret)
105 /// ]|
106 /// ## `name`
107 /// an opengl function name
108 ///
109 /// # Returns
110 ///
111 /// a function pointer or [`None`]
112 #[doc(alias = "get_proc_address")]
113 #[doc(alias = "gst_gl_context_get_proc_address")]
114 fn proc_address(&self, name: &str) -> uintptr_t {
115 unsafe {
116 ffi::gst_gl_context_get_proc_address(
117 self.as_ref().to_glib_none().0,
118 name.to_glib_none().0,
119 ) as uintptr_t
120 }
121 }
122
123 /// Execute `func` in the OpenGL thread of `self` with `data`
124 ///
125 /// MT-safe
126 /// ## `func`
127 /// a `GstGLContextThreadFunc`
128 #[doc(alias = "gst_gl_context_thread_add")]
129 fn thread_add<F: FnOnce(&Self) + Send>(&self, func: F) {
130 let mut func = std::mem::ManuallyDrop::new(func);
131 let user_data: *mut F = &mut *func;
132
133 unsafe extern "C" fn trampoline<O: IsA<GLContext>, F: FnOnce(&O) + Send>(
134 context: *mut ffi::GstGLContext,
135 data: glib::ffi::gpointer,
136 ) {
137 unsafe {
138 let func = std::ptr::read(data as *mut F);
139 let context = GLContext::from_glib_borrow(context);
140 func(context.unsafe_cast_ref())
141 }
142 }
143
144 unsafe {
145 ffi::gst_gl_context_thread_add(
146 self.as_ref().to_glib_none().0,
147 Some(trampoline::<Self, F>),
148 user_data as glib::ffi::gpointer,
149 );
150 }
151 }
152}
153
154impl<O: IsA<GLContext>> GLContextExtManual for O {}