mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 02:30:35 +00:00
libgstgl: cocoa, eagl: don't marshal GL calls to the context thread
Execute GL calls without marshalling them to the context thread. In the cocoa and eagl backends calling gst_gl_context_activate is cheap and therefore calling it on the current thread and serializing GL calls with a per-context lock is more efficient (faster and has less overhead) than marshalling everything to the context thread. This optimization cuts a large overhead in g_poll (continuously waking up the context thread) and in g_mutex_*/g_cond_* (waiting for results from the context thread).
This commit is contained in:
parent
6d343abec8
commit
90889bc73f
6 changed files with 116 additions and 3 deletions
|
@ -40,6 +40,7 @@ struct _GstGLContextCocoaPrivate
|
||||||
GstGLAPI context_api;
|
GstGLAPI context_api;
|
||||||
|
|
||||||
gint source_id;
|
gint source_id;
|
||||||
|
GRecMutex current_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,8 +60,13 @@ struct _GstGLContextCocoaPrivate
|
||||||
|
|
||||||
gboolean gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa);
|
gboolean gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa);
|
||||||
|
|
||||||
|
|
||||||
void _invoke_on_main (GstGLWindowCB func, gpointer data);
|
void _invoke_on_main (GstGLWindowCB func, gpointer data);
|
||||||
|
|
||||||
|
typedef void (*GstGLContextCocoaInvokeFunc) (gpointer data);
|
||||||
|
void _gst_gl_context_cocoa_invoke (GstGLContext * context,
|
||||||
|
GstGLContextCocoaInvokeFunc func, gpointer data, GDestroyNotify notify);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_GL_COCOA_PRIVATE_H__ */
|
#endif /* __GST_GL_COCOA_PRIVATE_H__ */
|
||||||
|
|
|
@ -43,14 +43,18 @@ GST_DEBUG_CATEGORY_STATIC (gst_gl_context_cocoa_debug);
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (GstGLContextCocoa, gst_gl_context_cocoa,
|
G_DEFINE_TYPE_WITH_CODE (GstGLContextCocoa, gst_gl_context_cocoa,
|
||||||
GST_GL_TYPE_CONTEXT, GST_DEBUG_CATEGORY_INIT (gst_gl_context_cocoa_debug, "glcontext_cocoa", 0, "Cocoa GL Context"); );
|
GST_GL_TYPE_CONTEXT, GST_DEBUG_CATEGORY_INIT (gst_gl_context_cocoa_debug, "glcontext_cocoa", 0, "Cocoa GL Context"); );
|
||||||
|
static void gst_gl_context_cocoa_finalize (GObject * object);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass)
|
gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass)
|
||||||
{
|
{
|
||||||
|
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||||
GstGLContextClass *context_class = (GstGLContextClass *) klass;
|
GstGLContextClass *context_class = (GstGLContextClass *) klass;
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (GstGLContextCocoaPrivate));
|
g_type_class_add_private (klass, sizeof (GstGLContextCocoaPrivate));
|
||||||
|
|
||||||
|
gobject_class->finalize = gst_gl_context_cocoa_finalize;
|
||||||
|
|
||||||
context_class->destroy_context =
|
context_class->destroy_context =
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_destroy_context);
|
GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_destroy_context);
|
||||||
context_class->create_context =
|
context_class->create_context =
|
||||||
|
@ -68,6 +72,13 @@ static void
|
||||||
gst_gl_context_cocoa_init (GstGLContextCocoa * context)
|
gst_gl_context_cocoa_init (GstGLContextCocoa * context)
|
||||||
{
|
{
|
||||||
context->priv = GST_GL_CONTEXT_COCOA_GET_PRIVATE (context);
|
context->priv = GST_GL_CONTEXT_COCOA_GET_PRIVATE (context);
|
||||||
|
g_rec_mutex_init (&context->priv->current_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gst_gl_context_cocoa_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
g_rec_mutex_clear (&GST_GL_CONTEXT_COCOA (object)->priv->current_lock);
|
||||||
|
G_OBJECT_CLASS (gst_gl_context_cocoa_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must be called in the gl thread */
|
/* Must be called in the gl thread */
|
||||||
|
@ -327,3 +338,17 @@ gst_gl_context_cocoa_get_current_context (void)
|
||||||
{
|
{
|
||||||
return (guintptr) CGLGetCurrentContext ();
|
return (guintptr) CGLGetCurrentContext ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gst_gl_context_cocoa_invoke (GstGLContext * context,
|
||||||
|
GstGLContextCocoaInvokeFunc func, gpointer data, GDestroyNotify destroy)
|
||||||
|
{
|
||||||
|
GstGLContextCocoa *context_cocoa = (GstGLContextCocoa *) context;
|
||||||
|
|
||||||
|
g_rec_mutex_lock (&context_cocoa->priv->current_lock);
|
||||||
|
gst_gl_context_activate (context, TRUE);
|
||||||
|
func (data);
|
||||||
|
if (destroy)
|
||||||
|
destroy (data);
|
||||||
|
g_rec_mutex_unlock (&context_cocoa->priv->current_lock);
|
||||||
|
}
|
||||||
|
|
|
@ -77,6 +77,10 @@ static void gst_gl_window_cocoa_set_preferred_size (GstGLWindow * window,
|
||||||
gint width, gint height);
|
gint width, gint height);
|
||||||
static void gst_gl_window_cocoa_show (GstGLWindow * window);
|
static void gst_gl_window_cocoa_show (GstGLWindow * window);
|
||||||
static void gst_gl_window_cocoa_queue_resize (GstGLWindow * window);
|
static void gst_gl_window_cocoa_queue_resize (GstGLWindow * window);
|
||||||
|
static void gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
|
||||||
|
GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
|
||||||
|
static void gst_gl_window_cocoa_send_message (GstGLWindow * window,
|
||||||
|
GstGLWindowCB callback, gpointer data);
|
||||||
|
|
||||||
struct _GstGLWindowCocoaPrivate
|
struct _GstGLWindowCocoaPrivate
|
||||||
{
|
{
|
||||||
|
@ -111,6 +115,10 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass)
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_set_preferred_size);
|
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_set_preferred_size);
|
||||||
window_class->show = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_show);
|
window_class->show = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_show);
|
||||||
window_class->queue_resize = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_queue_resize);
|
window_class->queue_resize = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_queue_resize);
|
||||||
|
window_class->send_message_async =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message_async);
|
||||||
|
window_class->send_message =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message);
|
||||||
|
|
||||||
gobject_class->finalize = gst_gl_window_cocoa_finalize;
|
gobject_class->finalize = gst_gl_window_cocoa_finalize;
|
||||||
}
|
}
|
||||||
|
@ -370,6 +378,24 @@ gst_gl_cocoa_resize_cb (GstGLNSView * view, guint width, guint height)
|
||||||
[pool release];
|
[pool release];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
|
||||||
|
GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
|
||||||
|
{
|
||||||
|
GstGLContext *context = gst_gl_window_get_context (window);
|
||||||
|
_gst_gl_context_cocoa_invoke (context, callback, data, destroy);
|
||||||
|
gst_object_unref (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_window_cocoa_send_message (GstGLWindow * window,
|
||||||
|
GstGLWindowCB callback, gpointer data)
|
||||||
|
{
|
||||||
|
GstGLContext *context = gst_gl_window_get_context (window);
|
||||||
|
_gst_gl_context_cocoa_invoke (context, callback, data, NULL);
|
||||||
|
gst_object_unref (context);
|
||||||
|
}
|
||||||
|
|
||||||
/* =============================================================*/
|
/* =============================================================*/
|
||||||
/* */
|
/* */
|
||||||
/* GstGLNSWindow implementation */
|
/* GstGLNSWindow implementation */
|
||||||
|
|
|
@ -65,6 +65,10 @@ void gst_gl_context_eagl_prepare_draw (GstGLContextEagl * context);
|
||||||
void gst_gl_context_eagl_finish_draw (GstGLContextEagl * context);
|
void gst_gl_context_eagl_finish_draw (GstGLContextEagl * context);
|
||||||
guintptr gst_gl_context_eagl_get_current_context (void);
|
guintptr gst_gl_context_eagl_get_current_context (void);
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
typedef void (*GstGLContextEaglInvokeFunc) (gpointer data);
|
||||||
|
void _gst_gl_context_eagl_invoke (GstGLContext * context,
|
||||||
|
GstGLContextEaglInvokeFunc func, gpointer data, GDestroyNotify destroy);
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_GL_CONTEXT_EAGL_H__ */
|
#endif /* __GST_GL_CONTEXT_EAGL_H__ */
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#define GST_CAT_DEFAULT gst_gl_context_debug
|
#define GST_CAT_DEFAULT gst_gl_context_debug
|
||||||
|
|
||||||
|
static void gst_gl_context_eagl_finalize (GObject * object);
|
||||||
static gboolean gst_gl_context_eagl_create_context (GstGLContext * context,
|
static gboolean gst_gl_context_eagl_create_context (GstGLContext * context,
|
||||||
GstGLAPI gl_api, GstGLContext * other_context, GError ** error);
|
GstGLAPI gl_api, GstGLContext * other_context, GError ** error);
|
||||||
static void gst_gl_context_eagl_destroy_context (GstGLContext * context);
|
static void gst_gl_context_eagl_destroy_context (GstGLContext * context);
|
||||||
|
@ -53,6 +54,7 @@ struct _GstGLContextEaglPrivate
|
||||||
GLuint framebuffer;
|
GLuint framebuffer;
|
||||||
GLuint color_renderbuffer;
|
GLuint color_renderbuffer;
|
||||||
GLuint depth_renderbuffer;
|
GLuint depth_renderbuffer;
|
||||||
|
GRecMutex current_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GST_GL_CONTEXT_EAGL_GET_PRIVATE(o) \
|
#define GST_GL_CONTEXT_EAGL_GET_PRIVATE(o) \
|
||||||
|
@ -63,12 +65,13 @@ G_DEFINE_TYPE (GstGLContextEagl, gst_gl_context_eagl, GST_GL_TYPE_CONTEXT);
|
||||||
static void
|
static void
|
||||||
gst_gl_context_eagl_class_init (GstGLContextEaglClass * klass)
|
gst_gl_context_eagl_class_init (GstGLContextEaglClass * klass)
|
||||||
{
|
{
|
||||||
GstGLContextClass *context_class;
|
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||||
|
GstGLContextClass *context_class = (GstGLContextClass *) klass;
|
||||||
context_class = (GstGLContextClass *) klass;
|
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (GstGLContextEaglPrivate));
|
g_type_class_add_private (klass, sizeof (GstGLContextEaglPrivate));
|
||||||
|
|
||||||
|
gobject_class->finalize = gst_gl_context_eagl_finalize;
|
||||||
|
|
||||||
context_class->destroy_context =
|
context_class->destroy_context =
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_context_eagl_destroy_context);
|
GST_DEBUG_FUNCPTR (gst_gl_context_eagl_destroy_context);
|
||||||
context_class->create_context =
|
context_class->create_context =
|
||||||
|
@ -90,6 +93,14 @@ static void
|
||||||
gst_gl_context_eagl_init (GstGLContextEagl * context)
|
gst_gl_context_eagl_init (GstGLContextEagl * context)
|
||||||
{
|
{
|
||||||
context->priv = GST_GL_CONTEXT_EAGL_GET_PRIVATE (context);
|
context->priv = GST_GL_CONTEXT_EAGL_GET_PRIVATE (context);
|
||||||
|
g_rec_mutex_init (&context->priv->current_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_context_eagl_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
g_rec_mutex_clear (&GST_GL_CONTEXT_EAGL (object)->priv->current_lock);
|
||||||
|
G_OBJECT_CLASS (gst_gl_context_eagl_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must be called in the gl thread */
|
/* Must be called in the gl thread */
|
||||||
|
@ -363,6 +374,20 @@ gst_gl_context_eagl_activate (GstGLContext * context, gboolean activate)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gst_gl_context_eagl_invoke (GstGLContext * context,
|
||||||
|
GstGLContextEaglInvokeFunc func, gpointer data, GDestroyNotify destroy)
|
||||||
|
{
|
||||||
|
GstGLContextEagl *context_eagl = (GstGLContextEagl *) context;
|
||||||
|
|
||||||
|
g_rec_mutex_lock (&context_eagl->priv->current_lock);
|
||||||
|
gst_gl_context_activate (context, TRUE);
|
||||||
|
func (data);
|
||||||
|
if (destroy)
|
||||||
|
destroy (data);
|
||||||
|
g_rec_mutex_unlock (&context_eagl->priv->current_lock);
|
||||||
|
}
|
||||||
|
|
||||||
static GstGLAPI
|
static GstGLAPI
|
||||||
gst_gl_context_eagl_get_gl_api (GstGLContext * context)
|
gst_gl_context_eagl_get_gl_api (GstGLContext * context)
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,6 +48,10 @@ static void gst_gl_window_eagl_set_window_handle (GstGLWindow * window,
|
||||||
static void gst_gl_window_eagl_set_preferred_size (GstGLWindow * window,
|
static void gst_gl_window_eagl_set_preferred_size (GstGLWindow * window,
|
||||||
gint width, gint height);
|
gint width, gint height);
|
||||||
static void gst_gl_window_eagl_draw (GstGLWindow * window);
|
static void gst_gl_window_eagl_draw (GstGLWindow * window);
|
||||||
|
static void gst_gl_window_eagl_send_message_async (GstGLWindow * window,
|
||||||
|
GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
|
||||||
|
static void gst_gl_window_eagl_send_message (GstGLWindow * window,
|
||||||
|
GstGLWindowCB callback, gpointer data);
|
||||||
|
|
||||||
struct _GstGLWindowEaglPrivate
|
struct _GstGLWindowEaglPrivate
|
||||||
{
|
{
|
||||||
|
@ -72,6 +76,10 @@ gst_gl_window_eagl_class_init (GstGLWindowEaglClass * klass)
|
||||||
window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_eagl_draw);
|
window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_eagl_draw);
|
||||||
window_class->set_preferred_size =
|
window_class->set_preferred_size =
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_window_eagl_set_preferred_size);
|
GST_DEBUG_FUNCPTR (gst_gl_window_eagl_set_preferred_size);
|
||||||
|
window_class->send_message_async =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_gl_window_eagl_send_message_async);
|
||||||
|
window_class->send_message =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_gl_window_eagl_send_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -126,6 +134,25 @@ gst_gl_window_eagl_set_preferred_size (GstGLWindow * window, gint width, gint he
|
||||||
window_eagl->priv->preferred_height = height;
|
window_eagl->priv->preferred_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_window_eagl_send_message_async (GstGLWindow * window,
|
||||||
|
GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
|
||||||
|
{
|
||||||
|
GstGLContext *context = gst_gl_window_get_context (window);
|
||||||
|
_gst_gl_context_eagl_invoke (context, callback, data, destroy);
|
||||||
|
gst_object_unref (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_window_eagl_send_message (GstGLWindow * window,
|
||||||
|
GstGLWindowCB callback, gpointer data)
|
||||||
|
{
|
||||||
|
GstGLContext *context = gst_gl_window_get_context (window);
|
||||||
|
_gst_gl_context_eagl_invoke (context, callback, data, NULL);
|
||||||
|
gst_object_unref (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_cb (gpointer data)
|
draw_cb (gpointer data)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue