summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Isorce <julien.isorce@gmail.com>2008-11-23 16:04:27 +0100
committerJulien Isorce <julien.isorce@gmail.com>2008-11-23 16:04:27 +0100
commit60b504a27b2844d90631a0a5d78e0aa164a0a246 (patch)
treeebea3f9c1cb9db59fe87ca5ea6e619d00cd0134a
parentde6c609d063698e94f3f2c23ab16da3d03cdeb72 (diff)
Make cube example work on x11. Finish TODO task 9.
-rw-r--r--ChangeLog17
-rw-r--r--TODO2
-rw-r--r--gst-libs/gst/gl/gstgldisplay.c4
-rw-r--r--gst-libs/gst/gl/gstglwindow.h1
-rw-r--r--gst-libs/gst/gl/gstglwindow_win32.c38
-rw-r--r--gst-libs/gst/gl/gstglwindow_x11.c65
6 files changed, 100 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 2764f4e..dff00ef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2008-11-23 Julien Isorce <julien.isorce@gmail.com>
+
+ * ChangeLog
+ * gst-libs/gst/gl/gstgldisplay.c
+ * gst-libs/gst/gl/gstglwindow.h
+ * gst-libs/gst/gl/gstglwindow_win32.c
+ * gst-libs/gst/gl/gstglwindow_x11.c
+ Make cube and other related example work with x11.
+ This commit terminates the first acceptable gstglwindow_x11.c
+ implementation.
+ * TODO
+ End of TODO task 9.
+
2008-11-22 Julien Isorce <julien.isorce@gmail.com>
* gst-libs/gst/gl/gstgldisplay.c
@@ -6,9 +19,9 @@
* gst-libs/gst/gl/gstglwindow_win32.c
* gst-libs/gst/gl/gstglwindow_x11.c
* gst/gl/gstglimagesink.c
- Remove set_visible, because it's now automatically done when
+ Remove set_visible, because it's now automatically done when
the first post redisplay comes.
- Apply the same mecanism I did for _x11 implemantion: Make sure the gl
+ Apply the same mecanism I did for _x11 implemantion: Make sure the gl
ressoures are destroyed before to destroy gl window.
2008-11-21 Julien Isorce <julien.isorce@gmail.com>
diff --git a/TODO b/TODO
index 8eeea84..c9bbfee 100644
--- a/TODO
+++ b/TODO
@@ -33,7 +33,7 @@
t. ! glqueue ! glfilterC ! glimagesink
Assuming glfilterA is GPU consumming and so do not need to duplicate it.
-(IN PROGRESS) - 9: rewrite the freeglut part that I minimized. Although I removed 90% of the orignal code,
+(DONE) - 9: rewrite the freeglut part that I minimized. Although I removed 90% of the orignal code,
it should be rewrite with the GLib API. To have a better design and handle X/WIN32 with interfaces
instead of having a lot of "define WIN32" scopes.
And make it thread safe in order to have one glthread per GstGLDisplay, instead of having a global glthread.
diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c
index dd408d2..5007326 100644
--- a/gst-libs/gst/gl/gstgldisplay.c
+++ b/gst-libs/gst/gl/gstgldisplay.c
@@ -1363,8 +1363,8 @@ void gst_gl_display_on_draw(GstGLDisplay* display)
display->clientDrawCallback (display->redisplay_texture,
display->redisplay_texture_width, display->redisplay_texture_height);
- if (doRedisplay)
- gst_gl_window_draw (display->gl_window);
+ if (doRedisplay && display->gl_window)
+ gst_gl_window_draw_unlocked (display->gl_window);
}
//default opengl scene
else
diff --git a/gst-libs/gst/gl/gstglwindow.h b/gst-libs/gst/gl/gstglwindow.h
index 15e9142..9dd1d92 100644
--- a/gst-libs/gst/gl/gstglwindow.h
+++ b/gst-libs/gst/gl/gstglwindow.h
@@ -71,6 +71,7 @@ void gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callbac
void gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowCB2 callback, gpointer data);
void gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
+void gst_gl_window_draw_unlocked (GstGLWindow *window);
void gst_gl_window_draw (GstGLWindow *window);
void gst_gl_window_run_loop (GstGLWindow *window);
void gst_gl_window_quit_loop (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
diff --git a/gst-libs/gst/gl/gstglwindow_win32.c b/gst-libs/gst/gl/gstglwindow_win32.c
index c4cb968..33c623d 100644
--- a/gst-libs/gst/gl/gstglwindow_win32.c
+++ b/gst-libs/gst/gl/gstglwindow_win32.c
@@ -1,4 +1,4 @@
-/*
+/*
* GStreamer
* Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com>
*
@@ -190,7 +190,7 @@ gst_gl_window_new (gint width, gint height)
g_debug ("gl window created: %d\n", priv->internal_win_id);
- //device is set in the window_proc
+ //device is set in the window_proc
g_assert (priv->device);
ShowCursor (TRUE);
@@ -204,7 +204,7 @@ gst_gl_window_error_quark (void)
return g_quark_from_static_string ("gst-gl-window-error");
}
-void
+void
gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id)
{
GstGLWindowPrivate *priv = window->priv;
@@ -215,9 +215,9 @@ gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id)
SetProp ((HWND)id, "gl_window_id", priv->internal_win_id);
SetProp ((HWND)id, "gl_window_parent_proc", (WNDPROC) window_parent_proc);
SetWindowLongPtr ((HWND)id, GWL_WNDPROC, (DWORD) (guint64) sub_class_proc);
-
+
SetWindowLongPtr (priv->internal_win_id, GWL_STYLE, WS_CHILD | WS_MAXIMIZE);
- SetParent (priv->internal_win_id, (HWND)id);
+ SetParent (priv->internal_win_id, (HWND)id);
//take changes into account: SWP_FRAMECHANGED
GetClientRect ((HWND)id, &rect);
@@ -226,7 +226,7 @@ gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id)
MoveWindow (priv->internal_win_id, rect.left, rect.top, rect.right, rect.bottom, FALSE);
}
-void
+void
gst_gl_window_set_external_gl_context (GstGLWindow *window, guint64 context)
{
g_warning ("gst_gl_window_set_external_gl_context: not implemented\n");
@@ -237,7 +237,7 @@ void
gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data)
{
GstGLWindowPrivate *priv = window->priv;
-
+
priv->draw_cb = callback;
priv->draw_data = data;
}
@@ -262,6 +262,12 @@ gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, g
priv->close_data = data;
}
+void
+gst_gl_window_draw_unlocked (GstGLWindow *window)
+{
+ gst_gl_window_draw (window);
+}
+
/* Thread safe */
void
gst_gl_window_draw (GstGLWindow *window)
@@ -289,7 +295,7 @@ gst_gl_window_run_loop (GstGLWindow *window)
g_debug ("begin loop\n");
while (running && (bRet = GetMessage (&msg, NULL, 0, 0)) != 0)
- {
+ {
if (bRet == -1)
{
g_error ("Failed to get message %x\r\n", GetLastError());
@@ -297,8 +303,8 @@ gst_gl_window_run_loop (GstGLWindow *window)
}
else
{
- TranslateMessage (&msg);
- DispatchMessage (&msg);
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
}
}
@@ -370,7 +376,7 @@ gst_gl_window_set_pixel_format (GstGLWindow *window)
pfd.cColorBits = (BYTE) GetDeviceCaps (priv->device, BITSPIXEL);
pixelformat = ChoosePixelFormat (priv->device, &pfd );
-
+
g_assert (pixelformat);
res = SetPixelFormat (priv->device, pixelformat, &pfd);
@@ -432,7 +438,7 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
}
case WM_PAINT:
- {
+ {
if (priv->draw_cb)
{
PAINTSTRUCT ps;
@@ -447,7 +453,7 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
case WM_CLOSE:
{
ShowWindowAsync (priv->internal_win_id, SW_HIDE);
-
+
if (priv->close_cb)
priv->close_cb (priv->close_data);
@@ -473,7 +479,7 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
if (parent_id)
{
WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc");
-
+
g_assert (parent_proc);
SetWindowLongPtr (parent_id, GWL_WNDPROC, (LONG) (guint64) parent_proc);
@@ -502,7 +508,7 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
g_debug ("failed to destroy window %d, %x\r\n", hWnd, GetLastError());
g_debug ("AFTER\n");
}
-
+
PostQuitMessage (0);
break;
}
@@ -541,7 +547,7 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
LRESULT FAR PASCAL sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WNDPROC window_parent_proc = GetProp (hWnd, "gl_window_parent_proc");
-
+
if (uMsg == WM_SIZE)
{
HWND gl_window_id = GetProp (hWnd, "gl_window_id");
diff --git a/gst-libs/gst/gl/gstglwindow_x11.c b/gst-libs/gst/gl/gstglwindow_x11.c
index d4defb0..3d512b9 100644
--- a/gst-libs/gst/gl/gstglwindow_x11.c
+++ b/gst-libs/gst/gl/gstglwindow_x11.c
@@ -41,6 +41,7 @@ struct _GstGLWindowPrivate
GCond *cond_send_message;
gboolean running;
gboolean visible;
+ gboolean allow_extra_expose_events;
gchar *display_name;
Display *device;
@@ -116,14 +117,20 @@ gst_gl_window_finalize (GObject * object)
XSetCloseDownMode (priv->device, DestroyAll);
- XCloseDisplay (priv->device);
-
- XCloseDisplay (priv->disp_send);
-
/*XAddToSaveSet (display, w)
Display *display;
Window w;*/
+ //FIXME: it seems it causes destroy all created windows, even by other display connection:
+ //This is case in: gst-launch-0.10 videotestsrc ! tee name=t t. ! queue ! glimagesink t. ! queue ! glimagesink
+ //When the first window is closed and so its display is closed by the following line, then the other Window managed by the
+ //other glimagesink, is not useable and so each opengl call causes a segmentation fault.
+ //Maybe the solution is to use: XAddToSaveSet
+ //The following line is commented to avoid the disagreement explained before.
+ //XCloseDisplay (priv->device);
+
+ XCloseDisplay (priv->disp_send);
+
g_debug ("display closed\n");
if (priv->cond_send_message)
@@ -269,6 +276,7 @@ gst_gl_window_new (gint width, gint height)
priv->running = TRUE;
priv->visible = FALSE;
priv->parent = 0;
+ priv->allow_extra_expose_events = TRUE;
g_mutex_lock (priv->x_lock);
@@ -472,6 +480,33 @@ gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, g
g_mutex_unlock (priv->x_lock);
}
+void
+gst_gl_window_draw_unlocked (GstGLWindow *window)
+{
+ GstGLWindowPrivate *priv = window->priv;
+
+ if (priv->running && priv->allow_extra_expose_events)
+ {
+ XEvent event;
+ XWindowAttributes attr;
+
+ XGetWindowAttributes (priv->device, priv->internal_win_id, &attr);
+
+ event.xexpose.type = Expose;
+ event.xexpose.send_event = TRUE;
+ event.xexpose.display = priv->device;
+ event.xexpose.window = priv->internal_win_id;
+ event.xexpose.x = attr.x;
+ event.xexpose.y = attr.y;
+ event.xexpose.width = attr.width;
+ event.xexpose.height = attr.height;
+ event.xexpose.count = 0;
+
+ XSendEvent (priv->device, priv->internal_win_id, FALSE, ExposureMask, &event);
+ XSync (priv->disp_send, FALSE);
+ }
+}
+
/* Thread safe */
void
gst_gl_window_draw (GstGLWindow *window)
@@ -535,7 +570,6 @@ gst_gl_window_run_loop (GstGLWindow *window)
{
GstGLWindowPrivate *priv = window->priv;
-
g_debug ("begin loop\n");
g_mutex_lock (priv->x_lock);
@@ -543,6 +577,7 @@ gst_gl_window_run_loop (GstGLWindow *window)
while (priv->running)
{
XEvent event;
+ XEvent pending_event;
g_mutex_unlock (priv->x_lock);
@@ -609,7 +644,6 @@ gst_gl_window_run_loop (GstGLWindow *window)
else if (wm_quit_loop != None && event.xclient.message_type == wm_quit_loop)
{
- XEvent pending_event;
GstGLWindowCB destroy_cb = (GstGLWindowCB) event.xclient.data.l[0];
gpointer destroy_data = (gpointer) event.xclient.data.l[1];
@@ -702,6 +736,25 @@ gst_gl_window_run_loop (GstGLWindow *window)
}// 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);