#define GST_GL_WINDOW_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW, GstGLWindowPrivate))
+
+/* A gl window is created and deleted in a thread dedicated to opengl calls
+ The name contains "window" because an opengl context is used in cooperation
+ with a window */
+
enum
{
ARG_0,
struct _GstGLWindowPrivate
{
+ /* X is not thread safe */
GMutex *x_lock;
GCond *cond_send_message;
gboolean running;
gboolean visible;
gboolean allow_extra_expose_events;
+ /* opengl context */
gchar *display_name;
Display *device;
Screen *screen;
XVisualInfo *visual_info;
Window parent;
+ /* We use a specific connection to send events */
Display *disp_send;
+ /* X window */
Window internal_win_id;
GLXContext gl_context;
+ /* frozen callbacks */
GstGLWindowCB draw_cb;
gpointer draw_data;
GstGLWindowCB2 resize_cb;
g_mutex_lock (priv->x_lock);
- g_debug ("gl window finalizing\n");
-
priv->parent = 0;
XUnmapWindow (priv->device, priv->internal_win_id);
XSync (priv->device, FALSE);
while(XPending (priv->device))
- {
- g_debug ("one more last pending x msg\n");
XNextEvent (priv->device, &event);
- }
XSetCloseDownMode (priv->device, DestroyAll);
//The following line is commented to avoid the disagreement explained before.
//XCloseDisplay (priv->device);
+ g_debug ("display receiver closed\n");
+
XCloseDisplay (priv->disp_send);
- g_debug ("display closed\n");
+ g_debug ("display sender closed\n");
if (priv->cond_send_message)
{
}
G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object);
-
- g_debug ("lock deleted\n");
}
static void
return g_quark_from_static_string ("gst-gl-window-error");
}
+/* Not called by the gl thread */
void
gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id)
{
- g_debug ("SET EXTERNAL WIN IN\n");
if (window)
{
GstGLWindowPrivate *priv = window->priv;
g_mutex_unlock (priv->x_lock);
}
- g_debug ("SET EXTERNAL WIN OUT\n");
}
void
g_warning ("gst_gl_window_set_external_gl_context: not implemented\n");
}
-/* Must be called in the gl thread */
void
gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data)
{
g_mutex_unlock (priv->x_lock);
}
-/* Must be called in the gl thread */
void
gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowCB2 callback , gpointer data)
{
g_mutex_unlock (priv->x_lock);
}
-/* Must be called in the gl thread */
void
gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data)
{
g_mutex_unlock (priv->x_lock);
}
+/* Called in the gl thread */
void
gst_gl_window_draw_unlocked (GstGLWindow *window)
{
}
}
-/* Thread safe */
+/* Not called by the gl thread */
void
gst_gl_window_draw (GstGLWindow *window)
{
- g_debug ("DRAW IN\n");
if (window)
{
GstGLWindowPrivate *priv = window->priv;
g_mutex_unlock (priv->x_lock);
}
- g_debug ("DRAW OUT\n");
}
+/* Called in the gl thread */
void
gst_gl_window_run_loop (GstGLWindow *window)
{
g_mutex_unlock (priv->x_lock);
- g_debug("Before XNextEvent\n");
-
/* XSendEvent (which are called in other threads) are done from another display structure */
XNextEvent(priv->device, &event);
- g_debug("After XNextEvent\n");
-
g_mutex_lock (priv->x_lock);
+ // use in generic/cube and other related uses
+ priv->allow_extra_expose_events = XPending (priv->device) <= 2;
+
switch (event.type)
{
case ClientMessage:
if (wm_quit_loop == None)
g_debug ("Cannot create WM_QUIT_LOOP\n");
+ /* Message sent with gst_gl_window_send_message */
if (wm_gl != None && event.xclient.message_type == wm_gl)
{
if (priv->running)
if (!custom_cb || !custom_data)
g_debug ("custom cb not initialized\n");
- if (glXGetCurrentContext () != priv->gl_context)
- g_warning ("current gl context has changed\n");
-
custom_cb (custom_data);
}
g_cond_signal (priv->cond_send_message);
}
+ /* User clicked on the cross */
else if (wm_delete != None && (Atom) event.xclient.data.l[0] == wm_delete)
{
g_debug ("Close %lld\n", (guint64) priv->internal_win_id);
priv->close_data = NULL;
}
+ /* message sent with gst_gl_window_quit_loop */
else if (wm_quit_loop != None && event.xclient.message_type == wm_quit_loop)
{
GstGLWindowCB destroy_cb = (GstGLWindowCB) event.xclient.data.l[0];
g_debug ("Quit loop message %lld\n", (guint64) priv->internal_win_id);
+ /* exit loop */
priv->running = FALSE;
+ /* make sure last pendings send message calls are executed */
XFlush (priv->device);
while (XCheckTypedEvent (priv->device, ClientMessage, &pending_event))
{
g_cond_signal (priv->cond_send_message);
}
+ /* Finally we can destroy opengl ressources (texture/shaders/fbo) */
if (!destroy_cb || !destroy_data)
- g_debug ("destroy cb not initialized\n");
-
- if (glXGetCurrentContext () != priv->gl_context)
- g_warning ("current gl context has changed\n");
+ g_debug ("destroy cb not correclty set\n");
destroy_cb (destroy_data);
}
else
- {
- g_debug("not reconized client message\n");
- }
+ g_debug("client message not reconized \n");
break;
}
case Expose:
if (priv->draw_cb)
{
- if (glXGetCurrentContext () != priv->gl_context)
- g_warning ("current gl context has changed\n");
priv->draw_cb (priv->draw_data);
glFlush();
glXSwapBuffers (priv->device, priv->internal_win_id);
}
default:
- g_print("unknow\n");
+ g_debug ("unknow\n");
break;
}// switch
- // use in cube example
- if (XPending (priv->device) > 10)
- {
- XEvent extra_expose_event;
- priv->allow_extra_expose_events = FALSE;
- while (XCheckTypedWindowEvent (priv->device, priv->internal_win_id, Expose, &extra_expose_event))
- {
- if (priv->draw_cb)
- {
- if (glXGetCurrentContext () != priv->gl_context)
- g_warning ("current gl context has changed\n");
- priv->draw_cb (priv->draw_data);
- glFlush();
- glXSwapBuffers (priv->device, priv->internal_win_id);
- }
- }
- priv->allow_extra_expose_events = TRUE;
- }
-
}// while running
g_mutex_unlock (priv->x_lock);
g_debug ("end loop\n");
}
-/* Thread safe */
+/* Not called by the gl thread */
void
gst_gl_window_quit_loop (GstGLWindow *window, GstGLWindowCB callback, gpointer data)
{
}
g_mutex_unlock (priv->x_lock);
-
}
- g_debug ("QUIT LOOP OUT\n");
}
-/* Thread safe */
+/* Not called by the gl thread */
void
gst_gl_window_send_message (GstGLWindow *window, GstGLWindowCB callback, gpointer data)
{
- g_debug ("CUSTOM IN\n");
if (window)
{
-
GstGLWindowPrivate *priv = window->priv;
g_mutex_lock (priv->x_lock);
- g_debug ("AA CUSTOM IN: %lld\n", (guint64)priv->internal_win_id);
-
if (priv->running)
{
XEvent event;
XSendEvent (priv->disp_send, priv->internal_win_id, FALSE, NoEventMask, &event);
XSync (priv->disp_send, FALSE);
+ /* block until opengl calls have been executed in the gl thread */
g_cond_wait (priv->cond_send_message, priv->x_lock);
-
}
g_mutex_unlock (priv->x_lock);
-
}
- g_debug ("CUSTOM OUT\n");
}