Commit 4f6c226b authored by Matthew Waters's avatar Matthew Waters 🐨

gl/x11: use xcb instead of libX11

- xcb is supposedly thread-safe!

videotestsrc ! glimagesink now doesn't spuriously result in a
'call XInitThreads()' error however if anybody else is using X11,
then XInitThreads() still needs to be called and multiple glimagesink's
still need XInitThreads().

Everything still takes libX11 handles as they are compatible with the xcb
variants.  Unfortunately we cannot move fully over to xcb due to GLX being
entirely based on Xlib.  It's also impossible to transform a xcb_connection
to a Display which means we require X11 handles.
parent e4916fb1
......@@ -692,7 +692,7 @@ AC_ARG_ENABLE([dispmanx],
*) AC_MSG_ERROR([bad value ${enableval} for --enable-dispmanx]) ;;
esac],[NEED_DISPMANX=auto])
AG_GST_PKG_CHECK_MODULES(X, x11)
AG_GST_PKG_CHECK_MODULES(X11_XCB, x11-xcb)
save_CPPFLAGS="$CPPFLAGS"
save_LIBS="$LIBS"
......@@ -847,7 +847,7 @@ if test "x$HAVE_GLES2" = "xno"; then
fi
dnl X, GLX and OpenGL
if test "x$HAVE_X" = "xno"; then
if test "x$HAVE_X11_XCB" = "xno"; then
if test "x$NEED_GLX" = "xyes"; then
AC_MSG_ERROR([Building the GLX backend without X11 is unsupported])
fi
......@@ -1002,7 +1002,7 @@ case $host in
AC_MSG_ERROR([WGL is not available on unix])
fi
if test "x$HAVE_X" = "xno"; then
if test "x$HAVE_X11_XCB" = "xno"; then
if test "x$HAVE_WAYLAND_EGL" = "xno"; then
AC_MSG_WARN([X or Wayland is required for OpenGL support])
fi
......@@ -1023,10 +1023,10 @@ case $host in
fi
fi
if test "x$HAVE_X" = "xyes" -a "x$HAVE_EGL_RPI" = "xno"; then
if test "x$HAVE_X11_XCB" = "xyes" -a "x$HAVE_EGL_RPI" = "xno"; then
if test "x$NEED_X11" != "xno"; then
GL_LIBS="$GL_LIBS $X_LIBS"
GL_CFLAGS="$GL_CFLAGS $X_CFLAGS"
GL_LIBS="$GL_LIBS $X11_XCB_LIBS"
GL_CFLAGS="$GL_CFLAGS $X11_XCB_CFLAGS"
HAVE_WINDOW_X11=yes
fi
fi
......@@ -1110,10 +1110,10 @@ case $host in
fi
if test "x$USE_GLX" = "xyes"; then
if test "x$HAVE_X" = "xyes"; then
if test "x$HAVE_X11_XCB" = "xyes"; then
if test "x$NEED_X11" != "xno"; then
GL_LIBS="$GL_LIBS $X_LIBS"
GL_CFLAGS="$GL_CFLAGS $X_CFLAGS"
GL_LIBS="$GL_LIBS $X11_XCB_LIBS"
GL_CFLAGS="$GL_CFLAGS $X11_XCB_CFLAGS"
HAVE_WINDOW_X11=yes
fi
fi
......
......@@ -5,11 +5,11 @@ noinst_LTLIBRARIES = libgstgl-x11.la
libgstgl_x11_la_SOURCES = \
gstgldisplay_x11.c \
gstglwindow_x11.c \
x11_event_source.c
xcb_event_source.c
noinst_HEADERS = \
gstglwindow_x11.h \
x11_event_source.h
xcb_event_source.h
libgstgl_x11includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl/x11
libgstgl_x11include_HEADERS = \
......
......@@ -23,6 +23,8 @@
#endif
#include <gst/gl/x11/gstgldisplay_x11.h>
#include <gst/gl/x11/gstglwindow_x11.h>
#include "xcb_event_source.h"
GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
#define GST_CAT_DEFAULT gst_gl_display_debug
......@@ -32,6 +34,10 @@ G_DEFINE_TYPE (GstGLDisplayX11, gst_gl_display_x11, GST_TYPE_GL_DISPLAY);
static void gst_gl_display_x11_finalize (GObject * object);
static guintptr gst_gl_display_x11_get_handle (GstGLDisplay * display);
gboolean gst_gl_display_x11_handle_event (GstGLDisplayX11 * display_x11);
extern gboolean gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11,
xcb_generic_event_t * event);
static void
gst_gl_display_x11_class_init (GstGLDisplayX11Class * klass)
{
......@@ -58,6 +64,7 @@ gst_gl_display_x11_finalize (GObject * object)
g_free (display_x11->name);
if (!display_x11->foreign_display && display_x11->display) {
XSync (display_x11->display, FALSE);
XCloseDisplay (display_x11->display);
}
......@@ -86,8 +93,23 @@ gst_gl_display_x11_new (const gchar * name)
if (!ret->display) {
GST_ERROR ("Failed to open X11 display connection with name, \'%s\'", name);
gst_object_unref (ret);
return NULL;
}
ret->xcb_connection = XGetXCBConnection (ret->display);
if (!ret->xcb_connection) {
GST_ERROR ("Failed to open retieve XCB connection from X11 Display");
gst_object_unref (ret);
return NULL;
}
XSetEventQueueOwner (ret->display, XCBOwnsEventQueue);
GST_GL_DISPLAY (ret)->event_source = xcb_event_source_new (ret);
g_source_attach (GST_GL_DISPLAY (ret)->event_source,
GST_GL_DISPLAY (ret)->main_context);
return ret;
}
......@@ -112,6 +134,14 @@ gst_gl_display_x11_new_with_display (Display * display)
ret->name = g_strdup (DisplayString (display));
ret->display = display;
ret->xcb_connection = XGetXCBConnection (ret->display);
if (!ret->xcb_connection) {
GST_ERROR ("Failed to open retieve XCB connection from X11 Display");
gst_object_unref (ret);
return NULL;
}
ret->foreign_display = TRUE;
return ret;
......@@ -122,3 +152,85 @@ gst_gl_display_x11_get_handle (GstGLDisplay * display)
{
return (guintptr) GST_GL_DISPLAY_X11 (display)->display;
}
static int
_compare_xcb_window (GstGLWindowX11 * window_x11, xcb_window_t * window_id)
{
return window_x11->internal_win_id - *window_id;
}
static GstGLWindowX11 *
_find_window_from_xcb_window (GstGLDisplayX11 * display_x11,
xcb_window_t window_id)
{
GstGLDisplay *display = GST_GL_DISPLAY (display_x11);
GstGLWindowX11 *ret = NULL;
GList *l;
if (!window_id)
return NULL;
GST_OBJECT_LOCK (display);
l = g_list_find_custom (display->windows, &window_id,
(GCompareFunc) _compare_xcb_window);
if (l)
ret = gst_object_ref (l->data);
GST_OBJECT_UNLOCK (display);
return ret;
}
static GstGLWindowX11 *
_window_from_event (GstGLDisplayX11 * display_x11, xcb_generic_event_t * event)
{
uint8_t event_code = event->response_type & 0x7f;
switch (event_code) {
/* *INDENT-OFF* */
#define WIN_FROM_EVENT(case_val,event_type,window_field) \
case case_val:{ \
event_type * real_event = (event_type *) event; \
return _find_window_from_xcb_window (display_x11, real_event->window_field); \
}
WIN_FROM_EVENT (XCB_CLIENT_MESSAGE, xcb_client_message_event_t, window)
WIN_FROM_EVENT (XCB_CONFIGURE_NOTIFY, xcb_configure_notify_event_t, window)
WIN_FROM_EVENT (XCB_EXPOSE, xcb_expose_event_t, window)
WIN_FROM_EVENT (XCB_KEY_PRESS, xcb_key_press_event_t, event)
WIN_FROM_EVENT (XCB_KEY_RELEASE, xcb_key_release_event_t, event)
WIN_FROM_EVENT (XCB_BUTTON_PRESS, xcb_button_press_event_t, event)
WIN_FROM_EVENT (XCB_BUTTON_RELEASE, xcb_button_release_event_t, event)
WIN_FROM_EVENT (XCB_MOTION_NOTIFY, xcb_motion_notify_event_t, event)
#undef WIN_FROM_EVENT
/* *INDENT-ON* */
default:
return NULL;
}
}
gboolean
gst_gl_display_x11_handle_event (GstGLDisplayX11 * display_x11)
{
xcb_connection_t *connection = display_x11->xcb_connection;
xcb_generic_event_t *event;
gboolean ret = TRUE;
while ((event = xcb_poll_for_event (connection))) {
GstGLWindowX11 *window_x11 = _window_from_event (display_x11, event);
GST_TRACE_OBJECT (display_x11, "got event %p to window %" GST_PTR_FORMAT,
event, window_x11);
if (window_x11) {
ret = gst_gl_window_x11_handle_event (window_x11, event);
} else {
/* unknown window, ignore */
ret = TRUE;
}
if (window_x11)
gst_object_unref (window_x11);
g_free (event);
}
return ret;
}
......@@ -23,8 +23,7 @@
#include <gst/gst.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xlib-xcb.h>
#include <gst/gl/gstgl_fwd.h>
#include <gst/gl/gstgldisplay.h>
......@@ -56,6 +55,7 @@ struct _GstGLDisplayX11
/* <private> */
gchar *name;
Display *display;
xcb_connection_t *xcb_connection;
gboolean foreign_display;
gpointer _padding[GST_PADDING];
......
This diff is collapsed.
......@@ -25,36 +25,35 @@
#include <stdint.h>
#include <stdlib.h>
#include "x11_event_source.h"
#include "xcb_event_source.h"
#include "gstgldisplay_x11.h"
#include "gstglwindow_x11.h"
extern gboolean gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11);
extern gboolean gst_gl_display_x11_handle_event (GstGLDisplayX11 * display_x11);
typedef struct _X11EventSource
typedef struct _XCBEventSource
{
GSource source;
GPollFD pfd;
uint32_t mask;
GstGLWindowX11 *window;
} X11EventSource;
GstGLDisplayX11 *display_x11;
} XCBEventSource;
static gboolean
x11_event_source_prepare (GSource * base, gint * timeout)
xcb_event_source_prepare (GSource * base, gint * timeout)
{
X11EventSource *source = (X11EventSource *) base;
gboolean retval;
*timeout = -1;
XCBEventSource *source = (XCBEventSource *) base;
retval = XPending (source->window->device);
xcb_flush (source->display_x11->xcb_connection);
return retval;
*timeout = -1;
return FALSE;
}
static gboolean
x11_event_source_check (GSource * base)
xcb_event_source_check (GSource * base)
{
X11EventSource *source = (X11EventSource *) base;
XCBEventSource *source = (XCBEventSource *) base;
gboolean retval;
retval = source->pfd.revents;
......@@ -63,11 +62,13 @@ x11_event_source_check (GSource * base)
}
static gboolean
x11_event_source_dispatch (GSource * base, GSourceFunc callback, gpointer data)
xcb_event_source_dispatch (GSource * base, GSourceFunc callback, gpointer data)
{
X11EventSource *source = (X11EventSource *) base;
XCBEventSource *source = (XCBEventSource *) base;
gboolean ret = gst_gl_display_x11_handle_event (source->display_x11);
gboolean ret = gst_gl_window_x11_handle_event (source->window);
source->pfd.revents = 0;
if (callback)
callback (data);
......@@ -75,22 +76,26 @@ x11_event_source_dispatch (GSource * base, GSourceFunc callback, gpointer data)
return ret;
}
static GSourceFuncs x11_event_source_funcs = {
x11_event_source_prepare,
x11_event_source_check,
x11_event_source_dispatch,
static GSourceFuncs xcb_event_source_funcs = {
xcb_event_source_prepare,
xcb_event_source_check,
xcb_event_source_dispatch,
NULL
};
GSource *
x11_event_source_new (GstGLWindowX11 * window_x11)
xcb_event_source_new (GstGLDisplayX11 * display_x11)
{
X11EventSource *source;
xcb_connection_t *connection;
XCBEventSource *source;
connection = display_x11->xcb_connection;
g_return_val_if_fail (connection != NULL, NULL);
source = (X11EventSource *)
g_source_new (&x11_event_source_funcs, sizeof (X11EventSource));
source->window = window_x11;
source->pfd.fd = ConnectionNumber (source->window->device);
source = (XCBEventSource *)
g_source_new (&xcb_event_source_funcs, sizeof (XCBEventSource));
source->display_x11 = display_x11;
source->pfd.fd = xcb_get_file_descriptor (connection);
source->pfd.events = G_IO_IN | G_IO_ERR;
g_source_add_poll (&source->source, &source->pfd);
......
......@@ -18,13 +18,12 @@
* Boston, MA 02110-1301, USA.
*/
#ifndef __X11_EVENT_SOURCE_H__
#define __X11_EVENT_SOURCE_H__
#ifndef __XCB_EVENT_SOURCE_H__
#define __XCB_EVENT_SOURCE_H__
#include <glib-object.h>
#include "gstglwindow_x11.h"
#include "gstgldisplay_x11.h"
GSource *
x11_event_source_new (GstGLWindowX11 *window_x11);
GSource * xcb_event_source_new (GstGLDisplayX11 *display_x11);
#endif /* __WAYLAND_EVENT_SOURCE_H__ */
#endif /* __XCB_EVENT_SOURCE_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment