eglglessink: Only attach the context once to the streaming thread

This commit is contained in:
Sebastian Dröge 2012-10-03 12:32:38 +02:00
parent 09b3518bae
commit e022fc5389

View file

@ -101,6 +101,8 @@
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
#include <GLES2/gl2ext.h> #include <GLES2/gl2ext.h>
#include <pthread.h>
#include "video_platform_wrapper.h" #include "video_platform_wrapper.h"
#include "gsteglglessink.h" #include "gsteglglessink.h"
@ -376,7 +378,7 @@ static inline gboolean got_gl_error (const char *wtf);
static inline void show_egl_error (const char *wtf); static inline void show_egl_error (const char *wtf);
static void gst_eglglessink_wipe_fmt (gpointer data); static void gst_eglglessink_wipe_fmt (gpointer data);
static inline gboolean egl_init (GstEglGlesSink * eglglessink); static inline gboolean egl_init (GstEglGlesSink * eglglessink);
static gboolean gst_eglglessink_context_make_current (GstEglGlesSink * eglglessink, gboolean bind); static gboolean gst_eglglessink_context_make_current (GstEglGlesSink * eglglessink, gboolean bind, gboolean streaming_thread);
static GstBufferClass *gsteglglessink_buffer_parent_class = NULL; static GstBufferClass *gsteglglessink_buffer_parent_class = NULL;
#define GST_TYPE_EGLGLESBUFFER (gst_eglglesbuffer_get_type()) #define GST_TYPE_EGLGLESBUFFER (gst_eglglesbuffer_get_type())
@ -1041,8 +1043,7 @@ gst_eglglessink_stop (GstBaseSink * sink)
GstEglGlesSink *eglglessink = GST_EGLGLESSINK (sink); GstEglGlesSink *eglglessink = GST_EGLGLESSINK (sink);
/* EGL/GLES2 cleanup */ /* EGL/GLES2 cleanup */
if (!gst_eglglessink_context_make_current (eglglessink, TRUE, FALSE))
if (!gst_eglglessink_context_make_current (eglglessink, TRUE))
return FALSE; return FALSE;
if (eglglessink->rendering_path == GST_EGLGLESSINK_RENDER_SLOW) { if (eglglessink->rendering_path == GST_EGLGLESSINK_RENDER_SLOW) {
@ -1074,7 +1075,7 @@ gst_eglglessink_stop (GstBaseSink * sink)
} }
} }
if (!gst_eglglessink_context_make_current (eglglessink, FALSE)) if (!gst_eglglessink_context_make_current (eglglessink, FALSE, FALSE))
return FALSE; return FALSE;
if (eglglessink->eglglesctx->surface) { if (eglglessink->eglglesctx->surface) {
@ -1440,12 +1441,33 @@ gst_eglglessink_update_surface_dimensions (GstEglGlesSink * eglglessink)
return FALSE; return FALSE;
} }
static pthread_key_t context_key;
static void
detach_context (void *data)
{
GstEglGlesSink * eglglessink = data;
GST_DEBUG_OBJECT (eglglessink, "Detaching current context from streaming thread");
gst_eglglessink_context_make_current (eglglessink, FALSE, TRUE);
gst_object_unref (eglglessink);
}
static gboolean static gboolean
gst_eglglessink_context_make_current (GstEglGlesSink * eglglessink, gboolean bind) gst_eglglessink_context_make_current (GstEglGlesSink * eglglessink, gboolean bind, gboolean streaming_thread)
{ {
g_assert (eglglessink->eglglesctx->display != NULL); g_assert (eglglessink->eglglesctx->display != NULL);
if (bind && eglglessink->eglglesctx->surface && eglglessink->eglglesctx->eglcontext) { if (bind && eglglessink->eglglesctx->surface && eglglessink->eglglesctx->eglcontext) {
if (streaming_thread) {
EGLContext *ctx = eglGetCurrentContext ();
if (ctx == eglglessink->eglglesctx->eglcontext) {
GST_DEBUG_OBJECT (eglglessink, "Already attached the context");
return TRUE;
}
GST_DEBUG_OBJECT (eglglessink, "Attaching context to streaming thread");
if (!eglMakeCurrent (eglglessink->eglglesctx->display, if (!eglMakeCurrent (eglglessink->eglglesctx->display,
eglglessink->eglglesctx->surface, eglglessink->eglglesctx->surface, eglglessink->eglglesctx->surface, eglglessink->eglglesctx->surface,
eglglessink->eglglesctx->eglcontext)) { eglglessink->eglglesctx->eglcontext)) {
@ -1453,7 +1475,22 @@ gst_eglglessink_context_make_current (GstEglGlesSink * eglglessink, gboolean bin
GST_ERROR_OBJECT (eglglessink, "Couldn't bind context"); GST_ERROR_OBJECT (eglglessink, "Couldn't bind context");
return FALSE; return FALSE;
} }
if (!pthread_getspecific (context_key)) {
pthread_setspecific (context_key, gst_object_ref (eglglessink));
}
} else { } else {
GST_DEBUG_OBJECT (eglglessink, "Attaching context");
if (!eglMakeCurrent (eglglessink->eglglesctx->display,
eglglessink->eglglesctx->surface, eglglessink->eglglesctx->surface,
eglglessink->eglglesctx->eglcontext)) {
show_egl_error ("eglMakeCurrent");
GST_ERROR_OBJECT (eglglessink, "Couldn't bind context");
return FALSE;
}
}
} else {
GST_DEBUG_OBJECT (eglglessink, "Detaching context");
if (!eglMakeCurrent (eglglessink->eglglesctx->display, if (!eglMakeCurrent (eglglessink->eglglesctx->display,
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT)) { EGL_NO_CONTEXT)) {
@ -1490,7 +1527,7 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink)
goto HANDLE_EGL_ERROR_LOCKED; goto HANDLE_EGL_ERROR_LOCKED;
} }
if (!gst_eglglessink_context_make_current (eglglessink, TRUE)) if (!gst_eglglessink_context_make_current (eglglessink, TRUE, TRUE))
goto HANDLE_EGL_ERROR_LOCKED; goto HANDLE_EGL_ERROR_LOCKED;
/* Save surface dims */ /* Save surface dims */
@ -1892,7 +1929,7 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
}; };
#endif #endif
if (!gst_eglglessink_context_make_current (eglglessink, TRUE)) if (!gst_eglglessink_context_make_current (eglglessink, TRUE, TRUE))
goto HANDLE_EGL_ERROR; goto HANDLE_EGL_ERROR;
w = GST_VIDEO_SINK_WIDTH (eglglessink); w = GST_VIDEO_SINK_WIDTH (eglglessink);
@ -2132,9 +2169,6 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
} }
} }
if (!gst_eglglessink_context_make_current (eglglessink, FALSE))
goto HANDLE_EGL_ERROR;
GST_DEBUG_OBJECT (eglglessink, "Succesfully rendered 1 frame"); GST_DEBUG_OBJECT (eglglessink, "Succesfully rendered 1 frame");
return GST_FLOW_OK; return GST_FLOW_OK;
@ -2143,7 +2177,6 @@ HANDLE_EGL_ERROR:
HANDLE_ERROR: HANDLE_ERROR:
GST_ERROR_OBJECT (eglglessink, "Rendering disabled for this frame"); GST_ERROR_OBJECT (eglglessink, "Rendering disabled for this frame");
gst_eglglessink_context_make_current (eglglessink, FALSE);
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
@ -2340,9 +2373,6 @@ gst_eglglessink_setcaps (GstBaseSink * bsink, GstCaps * caps)
} }
} }
if (!gst_eglglessink_context_make_current (eglglessink, FALSE))
return FALSE;
SUCCEED: SUCCEED:
GST_INFO_OBJECT (eglglessink, "Setcaps succeed"); GST_INFO_OBJECT (eglglessink, "Setcaps succeed");
return TRUE; return TRUE;
@ -2350,7 +2380,6 @@ SUCCEED:
/* Errors */ /* Errors */
HANDLE_ERROR: HANDLE_ERROR:
GST_ERROR_OBJECT (eglglessink, "Setcaps failed"); GST_ERROR_OBJECT (eglglessink, "Setcaps failed");
gst_eglglessink_context_make_current (eglglessink, FALSE);
return FALSE; return FALSE;
} }
@ -2590,6 +2619,8 @@ eglglessink_plugin_init (GstPlugin * plugin)
GST_DEBUG_CATEGORY_INIT (gst_eglglessink_debug, "eglglessink", GST_DEBUG_CATEGORY_INIT (gst_eglglessink_debug, "eglglessink",
0, "Simple EGL/GLES Sink"); 0, "Simple EGL/GLES Sink");
pthread_key_create (&context_key, detach_context);
return gst_element_register (plugin, "eglglessink", GST_RANK_PRIMARY, return gst_element_register (plugin, "eglglessink", GST_RANK_PRIMARY,
GST_TYPE_EGLGLESSINK); GST_TYPE_EGLGLESSINK);
} }