diff options
author | Julien Isorce <julien.isorce@gmail.com> | 2008-11-23 16:04:27 +0100 |
---|---|---|
committer | Julien Isorce <julien.isorce@gmail.com> | 2008-11-23 16:04:27 +0100 |
commit | 60b504a27b2844d90631a0a5d78e0aa164a0a246 (patch) | |
tree | ebea3f9c1cb9db59fe87ca5ea6e619d00cd0134a | |
parent | de6c609d063698e94f3f2c23ab16da3d03cdeb72 (diff) |
Make cube example work on x11. Finish TODO task 9.
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | gst-libs/gst/gl/gstgldisplay.c | 4 | ||||
-rw-r--r-- | gst-libs/gst/gl/gstglwindow.h | 1 | ||||
-rw-r--r-- | gst-libs/gst/gl/gstglwindow_win32.c | 38 | ||||
-rw-r--r-- | gst-libs/gst/gl/gstglwindow_x11.c | 65 |
6 files changed, 100 insertions, 27 deletions
@@ -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> @@ -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); |