From 3ddbdbd38359fa36adb6ee679744658369c9ed16 Mon Sep 17 00:00:00 2001 From: Anders Hellerup Madsen <ahem@github.com> Date: Sun, 5 Feb 2023 17:56:47 +0100 Subject: [PATCH] gstreamer-gl: Require object lock in GLDisplay The methods `gst_gl_display_get_gl_context_for_thread()`, `gst_gl_display_create_context()`, `gst_gl_display_add_context()` and `gst_gl_display_remove_context()` now require the display's object lock to be held when called. This is required by the C API. Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/439 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1212> --- gstreamer-gl/Gir.toml | 18 ++++--- gstreamer-gl/src/auto/gl_display.rs | 61 +---------------------- gstreamer-gl/src/gl_display.rs | 77 +++++++++++++++++++++++++++++ gstreamer-gl/src/lib.rs | 1 + 4 files changed, 90 insertions(+), 67 deletions(-) create mode 100644 gstreamer-gl/src/gl_display.rs diff --git a/gstreamer-gl/Gir.toml b/gstreamer-gl/Gir.toml index cdb13e09f..5793ab748 100644 --- a/gstreamer-gl/Gir.toml +++ b/gstreamer-gl/Gir.toml @@ -338,19 +338,23 @@ status = "generate" [[object.function]] name = "get_gl_context_for_thread" - # glib::Thread not found in `glib` - ignore = true + # require object lock + manual = true [[object.function]] name = "create_context" - [[object.function.parameter]] - name = "other_context" - nullable = true + # require object lock + manual = true [[object.function]] name = "add_context" - [object.function.return] - bool_return_is_error = "Failed to add OpenGL context" + # require object lock + manual = true + + [[object.function]] + name = "remove_context" + # require object lock + manual = true [[object.function]] name = "remove_window" diff --git a/gstreamer-gl/src/auto/gl_display.rs b/gstreamer-gl/src/auto/gl_display.rs index a0cc68736..0e2c67dfe 100644 --- a/gstreamer-gl/src/auto/gl_display.rs +++ b/gstreamer-gl/src/auto/gl_display.rs @@ -9,7 +9,7 @@ use glib::{ signal::{connect_raw, SignalHandlerId}, translate::*, }; -use std::{boxed::Box as Box_, mem::transmute, ptr}; +use std::{boxed::Box as Box_, mem::transmute}; glib::wrapper! { #[doc(alias = "GstGLDisplay")] @@ -49,15 +49,6 @@ unsafe impl Send for GLDisplay {} unsafe impl Sync for GLDisplay {} pub trait GLDisplayExt: 'static { - #[doc(alias = "gst_gl_display_add_context")] - fn add_context(&self, context: &impl IsA<GLContext>) -> Result<(), glib::error::BoolError>; - - #[doc(alias = "gst_gl_display_create_context")] - fn create_context( - &self, - other_context: Option<&impl IsA<GLContext>>, - ) -> Result<GLContext, glib::Error>; - #[doc(alias = "gst_gl_display_create_window")] fn create_window(&self) -> Result<GLWindow, glib::BoolError>; @@ -76,11 +67,6 @@ pub trait GLDisplayExt: 'static { #[doc(alias = "get_handle_type")] fn handle_type(&self) -> GLDisplayType; - #[cfg(any(feature = "v1_18", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] - #[doc(alias = "gst_gl_display_remove_context")] - fn remove_context(&self, context: &impl IsA<GLContext>); - #[doc(alias = "gst_gl_display_remove_window")] fn remove_window(&self, window: &impl IsA<GLWindow>) -> Result<(), glib::error::BoolError>; @@ -99,40 +85,6 @@ pub trait GLDisplayExt: 'static { } impl<O: IsA<GLDisplay>> GLDisplayExt for O { - fn add_context(&self, context: &impl IsA<GLContext>) -> Result<(), glib::error::BoolError> { - unsafe { - glib::result_from_gboolean!( - ffi::gst_gl_display_add_context( - self.as_ref().to_glib_none().0, - context.as_ref().to_glib_none().0 - ), - "Failed to add OpenGL context" - ) - } - } - - fn create_context( - &self, - other_context: Option<&impl IsA<GLContext>>, - ) -> Result<GLContext, glib::Error> { - unsafe { - let mut p_context = ptr::null_mut(); - let mut error = ptr::null_mut(); - let is_ok = ffi::gst_gl_display_create_context( - self.as_ref().to_glib_none().0, - other_context.map(|p| p.as_ref()).to_glib_none().0, - &mut p_context, - &mut error, - ); - debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null()); - if error.is_null() { - Ok(from_glib_full(p_context)) - } else { - Err(from_glib_full(error)) - } - } - } - fn create_window(&self) -> Result<GLWindow, glib::BoolError> { unsafe { Option::<_>::from_glib_full(ffi::gst_gl_display_create_window( @@ -172,17 +124,6 @@ impl<O: IsA<GLDisplay>> GLDisplayExt for O { } } - #[cfg(any(feature = "v1_18", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] - fn remove_context(&self, context: &impl IsA<GLContext>) { - unsafe { - ffi::gst_gl_display_remove_context( - self.as_ref().to_glib_none().0, - context.as_ref().to_glib_none().0, - ); - } - } - fn remove_window(&self, window: &impl IsA<GLWindow>) -> Result<(), glib::error::BoolError> { unsafe { glib::result_from_gboolean!( diff --git a/gstreamer-gl/src/gl_display.rs b/gstreamer-gl/src/gl_display.rs new file mode 100644 index 000000000..d1755153c --- /dev/null +++ b/gstreamer-gl/src/gl_display.rs @@ -0,0 +1,77 @@ +use crate::{GLContext, GLDisplay}; + +use glib::prelude::*; +use glib::translate::*; + +impl GLDisplay { + #[doc(alias = "gst_gl_display_get_gl_context_for_thread")] + pub fn get_gl_context_for_current_thread( + display: &gst::ObjectLockGuard<GLDisplay>, + ) -> Option<GLContext> { + skip_assert_initialized!(); + unsafe { + let ctx = ffi::gst_gl_display_get_gl_context_for_thread( + display.as_ref().to_glib_none().0, + std::ptr::null_mut(), + ); + from_glib_full(ctx) + } + } + + #[doc(alias = "gst_gl_display_create_context")] + pub fn create_context( + display: &gst::ObjectLockGuard<GLDisplay>, + other_context: Option<&impl IsA<GLContext>>, + ) -> Result<GLContext, glib::Error> { + skip_assert_initialized!(); + unsafe { + let mut p_context = std::ptr::null_mut(); + let mut error = std::ptr::null_mut(); + let is_ok = ffi::gst_gl_display_create_context( + display.as_ref().to_glib_none().0, + other_context.map(|p| p.as_ref()).to_glib_none().0, + &mut p_context, + &mut error, + ); + debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null()); + if error.is_null() { + Ok(from_glib_full(p_context)) + } else { + Err(from_glib_full(error)) + } + } + } + + #[doc(alias = "gst_gl_display_add_context")] + pub fn add_context( + display: &gst::ObjectLockGuard<GLDisplay>, + context: &impl IsA<GLContext>, + ) -> Result<(), glib::error::BoolError> { + skip_assert_initialized!(); + unsafe { + glib::result_from_gboolean!( + ffi::gst_gl_display_add_context( + display.as_ref().to_glib_none().0, + context.as_ref().to_glib_none().0 + ), + "Failed to add OpenGL context" + ) + } + } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] + #[doc(alias = "gst_gl_display_remove_context")] + pub fn remove_context( + display: &gst::ObjectLockGuard<GLDisplay>, + context: &impl IsA<GLContext>, + ) { + skip_assert_initialized!(); + unsafe { + ffi::gst_gl_display_remove_context( + display.as_ref().to_glib_none().0, + context.as_ref().to_glib_none().0, + ); + } + } +} diff --git a/gstreamer-gl/src/lib.rs b/gstreamer-gl/src/lib.rs index 4bd6f12f0..93bd68398 100644 --- a/gstreamer-gl/src/lib.rs +++ b/gstreamer-gl/src/lib.rs @@ -40,6 +40,7 @@ mod context; pub mod functions; pub use crate::functions::*; mod gl_context; +mod gl_display; mod gl_sync_meta; mod gl_video_frame; pub use crate::gl_sync_meta::*;