diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index 18b885b79d..2972fb0584 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -112,6 +112,7 @@ gst_gl_display_init (GstGLDisplay *display, GstGLDisplayClass *klass) //conditions display->cond_create_context = g_cond_new (); + display->cond_destroy_context = g_cond_new (); //action redisplay display->redisplay_texture = 0; @@ -338,12 +339,29 @@ gst_gl_display_finalize (GObject* object) { GstGLDisplay* display = GST_GL_DISPLAY (object); - //leave gl window loop - gst_gl_display_lock (display); - GST_INFO ("send quit gl window loop"); - gst_gl_window_quit_loop (display->gl_window); - GST_INFO ("quit sent to gl window loop"); - gst_gl_display_unlock (display); + if (display->mutex && display->gl_window) + { + + gst_gl_display_lock (display); + GST_INFO ("send message thread destroy context"); + gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (gst_gl_display_thread_destroy_context), display); + + gst_gl_window_set_resize_callback (display->gl_window, NULL, NULL); + gst_gl_window_set_draw_callback (display->gl_window, NULL, NULL); + gst_gl_window_set_close_callback (display->gl_window, NULL, NULL); + + //leave gl window loop + + GST_INFO ("send quit gl window loop"); + + gst_gl_window_quit_loop (display->gl_window); + + GST_INFO ("quit sent to gl window loop"); + + g_cond_wait (display->cond_destroy_context, display->mutex); + GST_INFO ("quit received from gl window"); + gst_gl_display_unlock (display); + } if (display->gl_thread) { @@ -363,6 +381,10 @@ gst_gl_display_finalize (GObject* object) g_mutex_free (display->mutex); display->mutex = NULL; } + if (display->cond_destroy_context) { + g_cond_free (display->cond_destroy_context); + display->cond_destroy_context = NULL; + } if (display->cond_create_context) { g_cond_free (display->cond_create_context); display->cond_create_context = NULL; @@ -453,12 +475,12 @@ gst_gl_display_thread_create_context (GstGLDisplay *display) display->isAlive = FALSE; - gst_gl_display_thread_destroy_context (display); - g_object_unref (G_OBJECT (display->gl_window)); display->gl_window = NULL; + g_cond_signal (display->cond_destroy_context); + gst_gl_display_unlock (display); return NULL; @@ -579,10 +601,6 @@ gst_gl_display_thread_destroy_context (GstGLDisplay *display) g_hash_table_foreach_remove (display->texture_pool, gst_gl_display_texture_pool_func_clean, NULL); - gst_gl_window_set_resize_callback (display->gl_window, NULL, NULL); - gst_gl_window_set_draw_callback (display->gl_window, NULL, NULL); - gst_gl_window_set_close_callback (display->gl_window, NULL, NULL); - GST_INFO ("Context destroyed"); } diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index 40706cc413..6909b9942a 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -86,6 +86,7 @@ struct _GstGLDisplay { //conditions GCond* cond_create_context; + GCond* cond_destroy_context; //generic gl code GstGLDisplayThreadFunc generic_callback; diff --git a/gst-libs/gst/gl/gstglwindow_x11.c b/gst-libs/gst/gl/gstglwindow_x11.c index 89beee0928..52ddc96b42 100644 --- a/gst-libs/gst/gl/gstglwindow_x11.c +++ b/gst-libs/gst/gl/gstglwindow_x11.c @@ -248,7 +248,7 @@ gst_gl_window_new (gint width, gint height) XWMHints wm_hints; unsigned long mask; const gchar *title = "OpenGL renderer"; - Atom wm_delete_and_gl[2]; + Atom wm_atoms[3]; static gint x = 0; static gint y = 0; @@ -326,15 +326,19 @@ gst_gl_window_new (gint width, gint height) g_debug ("gl window id: %lld\n", (guint64) priv->internal_win_id); - wm_delete_and_gl[0] = XInternAtom (priv->device, "WM_DELETE_WINDOW", True); - if (wm_delete_and_gl[0] == None) + wm_atoms[0] = XInternAtom (priv->device, "WM_DELETE_WINDOW", True); + if (wm_atoms[0] == None) g_debug ("Cannot create WM_DELETE_WINDOW\n"); - wm_delete_and_gl[1] = XInternAtom (priv->device, "WM_GL_WINDOW", False); - if (wm_delete_and_gl[1] == None) + wm_atoms[1] = XInternAtom (priv->device, "WM_GL_WINDOW", False); + if (wm_atoms[1] == None) g_debug ("Cannot create WM_GL_WINDOW\n"); - XSetWMProtocols (priv->device, priv->internal_win_id, wm_delete_and_gl, 2); + wm_atoms[2] = XInternAtom (priv->device, "WM_QUIT_LOOP", False); + if (wm_atoms[2] == None) + g_debug ("Cannot create WM_QUIT_LOOP\n"); + + XSetWMProtocols (priv->device, priv->internal_win_id, wm_atoms, 2); priv->gl_context = glXCreateContext (priv->device, priv->visual_info, NULL, TRUE); @@ -542,11 +546,14 @@ gst_gl_window_run_loop (GstGLWindow *window) Atom wm_delete = XInternAtom (priv->device, "WM_DELETE_WINDOW", True); Atom wm_gl = XInternAtom (priv->device, "WM_GL_WINDOW", True); + Atom wm_quit_loop = XInternAtom (priv->device, "WM_QUIT_LOOP", True); if (wm_delete == None) g_debug ("Cannot create WM_DELETE_WINDOW\n"); if (wm_gl == None) g_debug ("Cannot create WM_GL_WINDOW\n"); + if (wm_quit_loop == None) + g_debug ("Cannot create WM_QUIT_LOOP\n"); if (wm_gl != None && event.xclient.message_type == wm_gl) { @@ -568,12 +575,8 @@ gst_gl_window_run_loop (GstGLWindow *window) else if (wm_delete != None && (Atom) event.xclient.data.l[0] == wm_delete) { - XEvent event; - g_debug ("Close %lld\n", (guint64) priv->internal_win_id); - priv->running = FALSE; - if (priv->close_cb) priv->close_cb (priv->close_data); @@ -583,6 +586,15 @@ gst_gl_window_run_loop (GstGLWindow *window) priv->resize_data = NULL; priv->close_cb = NULL; priv->close_data = NULL; + } + + else if (wm_quit_loop != None && event.xclient.message_type == wm_quit_loop) + { + XEvent event; + + g_debug ("Quit loop message %lld\n", (guint64) priv->internal_win_id); + + priv->running = FALSE; XFlush (priv->device); while (XCheckTypedEvent (priv->device, ClientMessage, &event)) @@ -687,9 +699,8 @@ gst_gl_window_quit_loop (GstGLWindow *window) event.xclient.send_event = TRUE; event.xclient.display = disp; event.xclient.window = priv->internal_win_id; - event.xclient.message_type = 0; + event.xclient.message_type = XInternAtom (disp, "WM_QUIT_LOOP", True);; event.xclient.format = 32; - event.xclient.data.l[0] = XInternAtom (disp, "WM_DELETE_WINDOW", True); XSendEvent (disp, priv->internal_win_id, FALSE, NoEventMask, &event); XSync (disp, FALSE);