diff options
author | Benjamin Otte <otte@gnome.org> | 2009-10-13 12:04:36 +0200 |
---|---|---|
committer | Benjamin Otte <otte@gnome.org> | 2009-10-14 10:12:21 +0200 |
commit | d8c30a3a55dcb8ace6fe1ae67add53dfeea1c072 (patch) | |
tree | 10c140518fd3ce5c836889afd69ab43ceceea5a3 | |
parent | 734902ff1c524ca98993a118af6fb50f6b2d87ac (diff) |
Handle xlib in the core lib
The code will only be compiled if xlib code is available, but is now
available via the gst_buffer_new_similar() and
gst_create_similar_surface() APIs. It also cleans up the xlib elements
quite a bit.
-rw-r--r-- | ext/xlib/Makefile.am | 4 | ||||
-rw-r--r-- | ext/xlib/gstcairoxconvert.c | 18 | ||||
-rw-r--r-- | ext/xlib/gstcairoxconvert.h | 4 | ||||
-rw-r--r-- | ext/xlib/gstcairoxsink.c | 103 | ||||
-rw-r--r-- | ext/xlib/gstcairoxsink.h | 8 | ||||
-rw-r--r-- | gst-libs/gst/cairo/Makefile.am | 10 | ||||
-rw-r--r-- | gst-libs/gst/cairo/gstcairobuffer.c | 39 | ||||
-rw-r--r-- | gst-libs/gst/cairo/gstcairobuffer.h | 4 | ||||
-rw-r--r-- | gst-libs/gst/cairo/gstcairoxbuffer.c (renamed from ext/xlib/gstcairoxbuffer.c) | 87 | ||||
-rw-r--r-- | gst-libs/gst/cairo/gstcairoxbuffer.h (renamed from ext/xlib/gstcairoxbuffer.h) | 3 | ||||
-rw-r--r-- | gst-libs/gst/cairo/gstcairoxdisplay.c (renamed from ext/xlib/gstcairoxdisplay.c) | 151 | ||||
-rw-r--r-- | gst-libs/gst/cairo/gstcairoxdisplay.h (renamed from ext/xlib/gstcairoxdisplay.h) | 11 |
12 files changed, 262 insertions, 180 deletions
diff --git a/ext/xlib/Makefile.am b/ext/xlib/Makefile.am index bdaa257..f2d31f7 100644 --- a/ext/xlib/Makefile.am +++ b/ext/xlib/Makefile.am @@ -5,16 +5,12 @@ AM_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(CAIRO_ AM_LIBS = $(GST_BASE_LIBS) $(CAIRO_LIBS) $(XLIB_LIBS) noinst_HEADERS = \ - gstcairoxbuffer.h \ gstcairoxconvert.h \ - gstcairoxdisplay.h \ gstcairoxsink.h \ gstcairoxsource.h libgstcairoxlib_la_SOURCES = \ - gstcairoxbuffer.c \ gstcairoxconvert.c \ - gstcairoxdisplay.c \ gstcairoxlib.c \ gstcairoxsink.c \ gstcairoxsource.c diff --git a/ext/xlib/gstcairoxconvert.c b/ext/xlib/gstcairoxconvert.c index 5eda206..fb1beb7 100644 --- a/ext/xlib/gstcairoxconvert.c +++ b/ext/xlib/gstcairoxconvert.c @@ -36,9 +36,7 @@ #include "gstcairoxconvert.h" -#include <X11/Xlib.h> - -#include "gstcairoxbuffer.h" +#include <cairo-xlib.h> GST_BOILERPLATE (GstCairoXConvert, gst_cairo_x_convert, GstElement, GST_TYPE_BASE_TRANSFORM); @@ -80,7 +78,7 @@ gst_cairo_x_convert_start (GstBaseTransform * btrans) { GstCairoXConvert *convert = GST_CAIRO_X_CONVERT (btrans); - convert->display = gst_cairo_x_display_new (NULL); + convert->display = XOpenDisplay (NULL); if (convert->display == NULL) return FALSE; @@ -96,7 +94,7 @@ gst_cairo_x_convert_stop (GstBaseTransform * btrans) convert->in_format = NULL; gst_cairo_format_free (convert->out_format); convert->out_format = NULL; - gst_cairo_x_display_free (convert->display); + XCloseDisplay (convert->display); convert->display = NULL; return TRUE; @@ -145,14 +143,16 @@ gst_cairo_x_convert_buffer_alloc (GstPad * pad, guint64 offset, { GstCairoXConvert *convert = GST_CAIRO_X_CONVERT (gst_pad_get_parent (pad)); GstCairoFormat *format; + cairo_surface_t *root; format = gst_cairo_format_new (caps); - if (gst_cairo_format_is_native (format)) - *buf = gst_cairo_x_buffer_new (convert->display, - DefaultRootWindow (gst_cairo_x_display_get_display (convert->display)), - format); + root = cairo_xlib_surface_create (convert->display, + DefaultRootWindow (convert->display), + DefaultVisual (convert->display, DefaultScreen (convert->display)), 1, 1); + *buf = gst_cairo_buffer_new_similar (root, format); + cairo_surface_destroy (root); gst_cairo_format_free (format); gst_object_unref (convert); diff --git a/ext/xlib/gstcairoxconvert.h b/ext/xlib/gstcairoxconvert.h index b904708..d67daa4 100644 --- a/ext/xlib/gstcairoxconvert.h +++ b/ext/xlib/gstcairoxconvert.h @@ -24,7 +24,7 @@ #include <gst/base/gstbasetransform.h> #include <gst/cairo/gstcairo.h> -#include "gstcairoxdisplay.h" +#include <X11/Xlib.h> G_BEGIN_DECLS @@ -48,7 +48,7 @@ struct _GstCairoXConvert { GstCairoFormat * in_format; /* negotiated format on the sink side */ GstCairoFormat * out_format; /* negotiated format on the source side */ - GstCairoXDisplay * display; /* connection to X server */ + Display * display; /* connection to X server */ }; struct _GstCairoXConvertClass diff --git a/ext/xlib/gstcairoxsink.c b/ext/xlib/gstcairoxsink.c index 561033b..b155d97 100644 --- a/ext/xlib/gstcairoxsink.c +++ b/ext/xlib/gstcairoxsink.c @@ -39,7 +39,6 @@ #include <cairo-xlib.h> #include <gst/interfaces/navigation.h> -#include "gstcairoxbuffer.h" #include "gstcairoxsource.h" static void @@ -59,11 +58,12 @@ gst_cairo_x_sink_navigation_send_event (GstNavigation * navigation, if (gst_structure_get_double (structure, "pointer_x", &d)) gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, d * - gst_cairo_format_get_width (xsink->format) / xsink->window_width, NULL); + gst_cairo_format_get_width (xsink->format) / + cairo_xlib_surface_get_width (xsink->window), NULL); if (gst_structure_get_double (structure, "pointer_y", &d)) gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, d * - gst_cairo_format_get_height (xsink->format) / xsink->window_height, - NULL); + gst_cairo_format_get_height (xsink->format) / + cairo_xlib_surface_get_height (xsink->window), NULL); event = gst_event_new_navigation (structure); @@ -92,37 +92,32 @@ GST_BOILERPLATE_FULL (GstCairoXSink, gst_cairo_x_sink, GstElement, int height) { GstBaseSink *bsink = GST_BASE_SINK (xsink); - cairo_surface_t *target, *source; + cairo_surface_t *source; GstCairoFormat *format; GstBuffer *buffer; cairo_t *cr; - Display *xdisplay; buffer = gst_base_sink_get_last_buffer (bsink); if (buffer == NULL) return; - xdisplay = gst_cairo_x_display_get_display (xsink->display); format = gst_cairo_format_new (GST_BUFFER_CAPS (buffer)); - target = - cairo_xlib_surface_create (xdisplay, xsink->window, - DefaultVisual (xdisplay, DefaultScreen (xdisplay)), - xsink->window_width, xsink->window_height); - source = gst_cairo_create_surface (buffer, format); - cr = cairo_create (target); + source = gst_cairo_create_similar_surface (buffer, xsink->window, format); + cr = cairo_create (xsink->window); cairo_scale (cr, - (double) xsink->window_width / gst_cairo_format_get_width (format), - (double) xsink->window_height / gst_cairo_format_get_height (format)); + (double) cairo_xlib_surface_get_width (xsink->window) / + gst_cairo_format_get_width (format), + (double) cairo_xlib_surface_get_height (xsink->window) / + gst_cairo_format_get_height (format)); cairo_set_source_surface (cr, source, 0, 0); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_paint (cr); cairo_destroy (cr); - cairo_surface_destroy (target); cairo_surface_destroy (source); - XSync (gst_cairo_x_display_get_display (xsink->display), False); + XSync (xsink->display, False); gst_buffer_unref (buffer); gst_cairo_format_free (format); } @@ -143,8 +138,8 @@ gst_cairo_x_sink_handle_event (XEvent * event, gpointer sink) case ConfigureNotify: { XConfigureEvent *configure = &event->xconfigure; - xsink->window_width = configure->width; - xsink->window_height = configure->height; + cairo_xlib_surface_set_size (xsink->window, configure->width, + configure->height); break; } case ButtonPress: @@ -164,8 +159,7 @@ gst_cairo_x_sink_handle_event (XEvent * event, gpointer sink) case KeyPress: case KeyRelease: { - KeySym keysym = - XKeycodeToKeysym (gst_cairo_x_display_get_display (xsink->display), + KeySym keysym = XKeycodeToKeysym (xsink->display, event->xkey.keycode, 0); if (keysym != NoSymbol) { char *key = NULL; @@ -196,15 +190,13 @@ gst_cairo_x_sink_run (gpointer sink) { GstCairoXSink *xsink = sink; GSource *source; - Display *display; - display = gst_cairo_x_display_get_display (xsink->display); - XSelectInput (display, xsink->window, ExposureMask | StructureNotifyMask - | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | - KeyReleaseMask); + XSelectInput (xsink->display, cairo_xlib_surface_get_drawable (xsink->window), + ExposureMask | StructureNotifyMask | PointerMotionMask | ButtonPressMask + | ButtonReleaseMask | KeyPressMask | KeyReleaseMask); source = - gst_cairo_x_source_new (gst_cairo_x_display_get_display (xsink->display), + gst_cairo_x_source_new (xsink->display, gst_cairo_x_sink_handle_event, xsink); g_source_attach (source, xsink->context); g_source_unref (source); @@ -218,8 +210,9 @@ gst_cairo_x_sink_repaint (gpointer sink) { GstCairoXSink *xsink = sink; - gst_cairo_x_sink_paint (xsink, 0, 0, xsink->window_width, - xsink->window_height); + gst_cairo_x_sink_paint (xsink, 0, 0, + cairo_xlib_surface_get_width (xsink->window), + cairo_xlib_surface_get_height (xsink->window)); return FALSE; } @@ -240,17 +233,17 @@ static gboolean gst_cairo_x_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) { GstCairoXSink *xsink = GST_CAIRO_X_SINK (bsink); - Display *display; + Window window; gst_cairo_format_free (xsink->format); xsink->format = gst_cairo_format_new (caps); - display = gst_cairo_x_display_get_display (xsink->display); - XResizeWindow (display, xsink->window, + window = cairo_xlib_surface_get_drawable (xsink->window); + XResizeWindow (xsink->display, window, gst_cairo_format_get_width (xsink->format), gst_cairo_format_get_height (xsink->format)); - XMapWindow (display, xsink->window); - XSync (display, False); + XMapWindow (xsink->display, window); + XSync (xsink->display, False); return TRUE; } @@ -259,28 +252,29 @@ static gboolean gst_cairo_x_sink_start (GstBaseSink * bsink) { GstCairoXSink *xsink = GST_CAIRO_X_SINK (bsink); - Display *display; - Visual *visual; + Window window; - xsink->display = gst_cairo_x_display_new (NULL); + xsink->display = XOpenDisplay (NULL); if (xsink->display == NULL) return FALSE; - display = gst_cairo_x_display_get_display (xsink->display); - visual = gst_cairo_x_display_get_visual (xsink->display); - xsink->window = XCreateSimpleWindow (display, DefaultRootWindow (display), - 0, 0, xsink->window_width, xsink->window_height, 0, 0, - XBlackPixel (display, DefaultScreen (display))); - XSync (display, False); + window = XCreateSimpleWindow (xsink->display, + DefaultRootWindow (xsink->display), + 0, 0, 400, 300, 0, 0, + XBlackPixel (xsink->display, DefaultScreen (xsink->display))); + XSync (xsink->display, False); + xsink->window = cairo_xlib_surface_create (xsink->display, window, + DefaultVisual (xsink->display, DefaultScreen (xsink->display)), 400, 300); xsink->context = g_main_context_new (); xsink->loop = g_main_loop_new (xsink->context, TRUE); xsink->thread = g_thread_create (gst_cairo_x_sink_run, xsink, TRUE, NULL); if (!xsink->thread) { - XDestroyWindow (display, xsink->window); - xsink->window = 0; - gst_cairo_x_display_free (xsink->display); + XDestroyWindow (xsink->display, window); + XCloseDisplay (xsink->display); xsink->display = NULL; + cairo_surface_destroy (xsink->window); + xsink->window = NULL; return FALSE; } @@ -291,8 +285,8 @@ static gboolean gst_cairo_x_sink_stop (GstBaseSink * bsink) { GstCairoXSink *xsink = GST_CAIRO_X_SINK (bsink); - Display *display; GSource *source; + Window window; source = g_idle_source_new (); g_source_set_callback (source, gst_cairo_x_sink_stop_thread, xsink, NULL); @@ -306,11 +300,12 @@ gst_cairo_x_sink_stop (GstBaseSink * bsink) g_main_context_unref (xsink->context); xsink->context = NULL; - display = gst_cairo_x_display_get_display (xsink->display); - XDestroyWindow (display, xsink->window); - xsink->window = 0; + window = cairo_xlib_surface_get_drawable (xsink->window); + cairo_surface_destroy (xsink->window); + xsink->window = NULL; + XDestroyWindow (xsink->display, window); - gst_cairo_x_display_free (xsink->display); + XCloseDisplay (xsink->display); xsink->display = NULL; gst_cairo_format_free (xsink->format); xsink->format = NULL; @@ -341,8 +336,8 @@ gst_cairo_x_sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, format = gst_cairo_format_new (caps); if (gst_cairo_format_is_native (format)) { - g_assert (xsink->display); - *buf = gst_cairo_x_buffer_new (xsink->display, xsink->window, format); + g_assert (xsink->window); + *buf = gst_cairo_buffer_new_similar (xsink->window, format); } gst_cairo_format_free (format); @@ -381,6 +376,4 @@ gst_cairo_x_sink_class_init (GstCairoXSinkClass * klass) static void gst_cairo_x_sink_init (GstCairoXSink * xsink, GstCairoXSinkClass * klass) { - xsink->window_width = 400; - xsink->window_height = 300; } diff --git a/ext/xlib/gstcairoxsink.h b/ext/xlib/gstcairoxsink.h index 9fc7b44..0f8d368 100644 --- a/ext/xlib/gstcairoxsink.h +++ b/ext/xlib/gstcairoxsink.h @@ -24,7 +24,7 @@ #include <gst/cairo/gstcairo.h> #include <gst/video/gstvideosink.h> -#include "gstcairoxdisplay.h" +#include <X11/Xlib.h> G_BEGIN_DECLS @@ -45,10 +45,8 @@ typedef struct _GstCairoXSinkClass GstCairoXSinkClass; struct _GstCairoXSink { GstVideoSink sink; - GstCairoXDisplay * display; /* magic happens here */ - Window window; /* the window we display to */ - int window_width; /* width of the window */ - int window_height; /* height of the window */ + Display * display; /* the Display in use */ + cairo_surface_t * window; /* xlib surface of window or NULL */ GMainContext * context; /* context of event thread */ GMainLoop * loop; /* loop running context in event thread */ GstCairoFormat * format; /* negotiated format on the sink side */ diff --git a/gst-libs/gst/cairo/Makefile.am b/gst-libs/gst/cairo/Makefile.am index 07d765c..71f2a4b 100644 --- a/gst-libs/gst/cairo/Makefile.am +++ b/gst-libs/gst/cairo/Makefile.am @@ -16,9 +16,17 @@ libgstcairo_@GST_MAJORMINOR@include_HEADERS = \ gstcairoformat.h \ gstcairopad.h +if USE_XLIB +libgstcairo_@GST_MAJORMINOR@_la_SOURCES += \ + gstcairoxbuffer.c \ + gstcairoxdisplay.c +endif + noinst_HEADERS = \ gstcairocaps2format.h \ - gstcairoformat-private.h + gstcairoformat-private.h \ + gstcairoxbuffer.h \ + gstcairoxdisplay.h libgstcairo_@GST_MAJORMINOR@_la_LIBADD = \ $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) \ diff --git a/gst-libs/gst/cairo/gstcairobuffer.c b/gst-libs/gst/cairo/gstcairobuffer.c index b5fbd96..fea057c 100644 --- a/gst-libs/gst/cairo/gstcairobuffer.c +++ b/gst-libs/gst/cairo/gstcairobuffer.c @@ -24,6 +24,9 @@ #include "gstcairobuffer.h" #include "gstcairoformat-private.h" +#ifdef HAVE_XLIB +# include "gstcairoxbuffer.h" +#endif G_DEFINE_TYPE (GstCairoBuffer, gst_cairo_buffer, GST_TYPE_BUFFER) @@ -95,13 +98,14 @@ gst_cairo_buffer_set_format (GstBuffer * buffer, const GstCairoFormat * format) } static cairo_surface_t * -gst_cairo_buffer_get_surface (GstCairoBuffer * cbuffer) +gst_cairo_buffer_get_surface (GstCairoBuffer * cbuffer, + cairo_surface_t * similar) { GstCairoBufferClass *klass; cairo_surface_t *surface; klass = GST_CAIRO_BUFFER_GET_CLASS (cbuffer); - surface = klass->get_surface (GST_BUFFER (cbuffer), cbuffer->format); + surface = klass->get_surface (GST_BUFFER (cbuffer), similar, cbuffer->format); /* we only set fixed afterwards, so the get_surface() function can use * gst_cairo_buffer_is_fixed() to check if it's the first time it was * called. @@ -126,18 +130,25 @@ gst_cairo_buffer_get_surface (GstCairoBuffer * cbuffer) cairo_surface_t * gst_cairo_create_surface (GstBuffer * buffer, const GstCairoFormat * format) { - cairo_surface_t *surface; + return gst_cairo_create_similar_surface (buffer, NULL, format); +} + +cairo_surface_t * +gst_cairo_create_similar_surface (GstBuffer * buffer, + cairo_surface_t * surface, const GstCairoFormat * format) +{ + cairo_surface_t *result; g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); g_return_val_if_fail (format != NULL, NULL); if (GST_IS_CAIRO_BUFFER (buffer)) { GstCairoBuffer *cbuffer = GST_CAIRO_BUFFER (buffer); - surface = gst_cairo_buffer_get_surface (cbuffer); + result = gst_cairo_buffer_get_surface (cbuffer, surface); } else { static cairo_user_data_key_t buffer_free; guint8 *data = GST_BUFFER_DATA (buffer); - surface = + result = cairo_image_surface_create_with_pixman_format (data, gst_cairo_format_get_pixman_format (format), format->width, format->height, @@ -149,11 +160,11 @@ gst_cairo_create_surface (GstBuffer * buffer, const GstCairoFormat * format) data + gst_cairo_format_get_offset (format, 3), gst_cairo_format_get_stride (format, 3)); gst_buffer_ref (buffer); - cairo_surface_set_user_data (surface, &buffer_free, buffer, + cairo_surface_set_user_data (result, &buffer_free, buffer, (cairo_destroy_func_t) gst_buffer_unref); } - return surface; + return result; } /** @@ -198,8 +209,22 @@ GstBuffer * gst_cairo_buffer_new_similar (cairo_surface_t * surface, const GstCairoFormat * format) { + G_GNUC_UNUSED GstBuffer *buffer; + g_return_val_if_fail (surface != NULL, NULL); g_return_val_if_fail (format != NULL, NULL); + switch (cairo_surface_get_type (surface)) { + case CAIRO_SURFACE_TYPE_XLIB: +#ifdef HAVE_XLIB + buffer = gst_cairo_x_buffer_new (surface, format); + if (buffer) + return buffer; +#endif + break; + default: + break; + } + return gst_cairo_buffer_new (format); } diff --git a/gst-libs/gst/cairo/gstcairobuffer.h b/gst-libs/gst/cairo/gstcairobuffer.h index ce93007..d960d0c 100644 --- a/gst-libs/gst/cairo/gstcairobuffer.h +++ b/gst-libs/gst/cairo/gstcairobuffer.h @@ -47,6 +47,7 @@ struct _GstCairoBufferClass { GstBufferClass buffer_class; cairo_surface_t * (* get_surface) (GstBuffer * buffer, + cairo_surface_t * similar, const GstCairoFormat * format); }; @@ -62,6 +63,9 @@ void gst_cairo_buffer_set_format (GstBuffer * cairo_surface_t * gst_cairo_create_surface (GstBuffer * buffer, const GstCairoFormat * format); +cairo_surface_t * gst_cairo_create_similar_surface(GstBuffer * buffer, + cairo_surface_t * surface, + const GstCairoFormat * format); #endif /* __GST_CAIRO_BUFFER_H__ */ diff --git a/ext/xlib/gstcairoxbuffer.c b/gst-libs/gst/cairo/gstcairoxbuffer.c index b1e6142..f79e6ef 100644 --- a/ext/xlib/gstcairoxbuffer.c +++ b/gst-libs/gst/cairo/gstcairoxbuffer.c @@ -32,14 +32,35 @@ G_DEFINE_TYPE (GstCairoXBuffer, gst_cairo_x_buffer, GST_TYPE_CAIRO_BUFFER) GstCairoXBuffer *xbuffer = GST_CAIRO_X_BUFFER (object); if (gst_cairo_buffer_is_fixed (GST_BUFFER (xbuffer))) { - XFreePixmap (gst_cairo_x_display_get_display (xbuffer->display), - xbuffer->drawable); + GstCairoXThread *thread; + thread = gst_cairo_x_display_get_thread (xbuffer->display); + XFreePixmap (thread->display, xbuffer->drawable); + gst_cairo_x_thread_unref (thread); } gst_cairo_x_display_unref (xbuffer->display); GST_MINI_OBJECT_CLASS (gst_cairo_x_buffer_parent_class)->finalize (object); } +static GstBuffer * +gst_cairo_x_buffer_new_internal (GstCairoXDisplay * display, + Drawable similar_to, const GstCairoFormat * format) +{ + GstCairoXBuffer *xbuffer; + GstBuffer *buffer; + + xbuffer = + GST_CAIRO_X_BUFFER (g_type_create_instance (GST_TYPE_CAIRO_X_BUFFER)); + buffer = GST_BUFFER (xbuffer); + + xbuffer->display = gst_cairo_x_display_ref (display); + xbuffer->drawable = similar_to; + + gst_cairo_buffer_set_format (buffer, format); + + return buffer; +} + static GstMiniObject * gst_cairo_x_buffer_copy (const GstMiniObject * object) { @@ -48,7 +69,9 @@ gst_cairo_x_buffer_copy (const GstMiniObject * object) const GstCairoFormat *format; format = GST_CAIRO_BUFFER (source)->format; - copy = gst_cairo_x_buffer_new (source->display, source->drawable, format); + copy = + gst_cairo_x_buffer_new_internal (source->display, source->drawable, + format); if (gst_cairo_buffer_is_fixed (GST_BUFFER (source))) { cairo_surface_t *source_surface, *copy_surface; @@ -92,7 +115,7 @@ gst_cairo_x_buffer_destroy_surface (gpointer data) static cairo_surface_t * gst_cairo_x_buffer_get_surface (GstBuffer * buffer, - const GstCairoFormat * format) + cairo_surface_t * similar, const GstCairoFormat * format) { static const cairo_user_data_key_t thread_key; GstCairoXBuffer *xbuffer = GST_CAIRO_X_BUFFER (buffer); @@ -101,6 +124,11 @@ gst_cairo_x_buffer_get_surface (GstBuffer * buffer, thread = gst_cairo_x_display_get_thread (xbuffer->display); + /* FIXME: I want to return an error surface here - this error only happens + * when XOpenDisplay fails though, so it's probably not very important */ + if (thread == NULL) + return NULL; + if (!gst_cairo_buffer_is_fixed (buffer)) { xbuffer->drawable = XCreatePixmap (thread->display, xbuffer->drawable, @@ -115,18 +143,26 @@ gst_cairo_x_buffer_get_surface (GstBuffer * buffer, /* XSync (display, False); */ } - /* FIXME: I want to return an error surface here - this error only happens - * when XOpenDisplay fails though, so it's probably not very important */ - if (thread == NULL) - return NULL; - - surface = cairo_xlib_surface_create (thread->display, - xbuffer->drawable, - thread->visual, - gst_cairo_format_get_width (format), - gst_cairo_format_get_height (format)); - cairo_surface_set_user_data (surface, &thread_key, thread, - gst_cairo_x_buffer_destroy_surface); + if (similar != NULL && + cairo_surface_get_type (similar) == CAIRO_SURFACE_TYPE_XLIB && + xbuffer->display == + gst_cairo_x_display_get (cairo_xlib_surface_get_display (similar))) { + surface = + cairo_xlib_surface_create (cairo_xlib_surface_get_display (similar), + xbuffer->drawable, gst_cairo_x_display_find_visual (xbuffer->display, + cairo_xlib_surface_get_display (similar)), + gst_cairo_format_get_width (format), + gst_cairo_format_get_height (format)); + gst_cairo_x_thread_unref (thread); + } else { + surface = cairo_xlib_surface_create (thread->display, + xbuffer->drawable, + thread->visual, + gst_cairo_format_get_width (format), + gst_cairo_format_get_height (format)); + cairo_surface_set_user_data (surface, &thread_key, thread, + gst_cairo_x_buffer_destroy_surface); + } return surface; } @@ -148,20 +184,15 @@ gst_cairo_x_buffer_init (GstCairoXBuffer * buffer) } GstBuffer * -gst_cairo_x_buffer_new (GstCairoXDisplay * display, Drawable similar_to, +gst_cairo_x_buffer_new (cairo_surface_t * similar, const GstCairoFormat * format) { - GstCairoXBuffer *xbuffer; - GstBuffer *buffer; + GstCairoXDisplay *xdisplay; - xbuffer = - GST_CAIRO_X_BUFFER (g_type_create_instance (GST_TYPE_CAIRO_X_BUFFER)); - buffer = GST_BUFFER (xbuffer); - - xbuffer->display = gst_cairo_x_display_ref (display); - xbuffer->drawable = similar_to; - - gst_cairo_buffer_set_format (buffer, format); + xdisplay = gst_cairo_x_display_get (cairo_xlib_surface_get_display (similar)); + if (xdisplay == NULL) + return NULL; - return buffer; + return gst_cairo_x_buffer_new_internal (xdisplay, + cairo_xlib_surface_get_drawable (similar), format); } diff --git a/ext/xlib/gstcairoxbuffer.h b/gst-libs/gst/cairo/gstcairoxbuffer.h index 7e8f7c6..a86588a 100644 --- a/ext/xlib/gstcairoxbuffer.h +++ b/gst-libs/gst/cairo/gstcairoxbuffer.h @@ -46,8 +46,7 @@ struct _GstCairoXBufferClass { GType gst_cairo_x_buffer_get_type (void); -GstBuffer * gst_cairo_x_buffer_new (GstCairoXDisplay * display, - Drawable similar_to, +GstBuffer * gst_cairo_x_buffer_new (cairo_surface_t * similar, const GstCairoFormat * format); diff --git a/ext/xlib/gstcairoxdisplay.c b/gst-libs/gst/cairo/gstcairoxdisplay.c index b940164..efc532e 100644 --- a/ext/xlib/gstcairoxdisplay.c +++ b/gst-libs/gst/cairo/gstcairoxdisplay.c @@ -38,11 +38,12 @@ #include <cairo-xlib.h> #include <X11/Xlib.h> +#include <X11/Xlibint.h> #include <X11/Xutil.h> G_LOCK_DEFINE_STATIC (dlock); -#define DISPLAY_LOCK(display) G_LOCK (dlock) -#define DISPLAY_UNLOCK(display) G_UNLOCK (dlock) +#define DISPLAY_LOCK() G_LOCK (dlock) +#define DISPLAY_UNLOCK() G_UNLOCK (dlock) #define GST_CAIRO_IS_X_DISPLAY(display) ((display) && (display)->threads) @@ -93,6 +94,26 @@ gst_cairo_x_visual_find (Display * display, long vinfo_mask, return result; } +Visual * +gst_cairo_x_display_find_visual (GstCairoXDisplay * display, Display * dpy) +{ + XVisualInfo tmpl; + Visual *visual; + + if (display->visual_id == 0) + return NULL; + + tmpl.visualid = display->visual_id; + tmpl.screen = DefaultScreen (dpy); + visual = gst_cairo_x_visual_find (dpy, VisualIDMask | VisualScreenMask, + &tmpl); + + /* FIXME: Fix when we ever encounter it */ + g_assert (display->visual_id == XVisualIDFromVisual (visual)); + + return visual; +} + static GstCairoXThread * gst_cairo_x_thread_new (GstCairoXDisplay * display) { @@ -110,16 +131,7 @@ gst_cairo_x_thread_new (GstCairoXDisplay * display) thread->thread = g_thread_self (); thread->display = xdisplay; thread->depth = display->depth; - if (display->visual_id) { - XVisualInfo tmpl; - tmpl.visualid = display->visual_id; - tmpl.screen = DefaultScreen (thread->display); - thread->visual = - gst_cairo_x_visual_find (xdisplay, VisualIDMask | VisualScreenMask, - &tmpl); - /* FIXME: Fix when we ever encounter it */ - g_assert (display->visual_id == XVisualIDFromVisual (thread->visual)); - } + thread->visual = gst_cairo_x_display_find_visual (display, xdisplay); gst_cairo_x_display_ref (display); if (display->threads) { @@ -142,22 +154,81 @@ gst_cairo_x_thread_unref (GstCairoXThread * thread) /*** API ***/ +static GHashTable *all_displays = NULL; + +static int +gst_cairo_x_display_remove (Display * dpy, XExtCodes * codes) +{ + DISPLAY_LOCK (); + g_hash_table_remove (all_displays, dpy); + DISPLAY_UNLOCK (); + + return 0; +} + +static void +gst_cairo_x_display_attach (Display * dpy) +{ + XExtCodes *codes; + + codes = XAddExtension (dpy); + if (codes == NULL) + return; + + XESetCloseDisplay (dpy, codes->extension, gst_cairo_x_display_remove); +} + +static void +gst_cairo_x_display_free (gpointer displayp) +{ + GstCairoXDisplay *display = displayp; + GHashTable *threads; + + g_return_if_fail (GST_CAIRO_IS_X_DISPLAY (display)); + + threads = display->threads; + display->threads = NULL; + g_hash_table_destroy (threads); + gst_cairo_x_display_unref (display); +} + +static GstCairoXDisplay * +gst_cairo_x_display_find (Display * dpy) +{ + GstCairoXDisplay *result; + + if (all_displays == NULL) + all_displays = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, gst_cairo_x_display_free); + result = g_hash_table_lookup (all_displays, dpy); + + return result; +} + GstCairoXDisplay * -gst_cairo_x_display_new (const char *display_name) +gst_cairo_x_display_get (Display * dpy) { GstCairoXDisplay *display; GstCairoXThread *thread; XVisualInfo tmpl; + DISPLAY_LOCK (); + display = gst_cairo_x_display_find (dpy); + if (display) { + DISPLAY_UNLOCK (); + return display; + } + display = g_slice_new0 (GstCairoXDisplay); display->refcount = 1; display->threads = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) gst_cairo_x_thread_unref); - display->display_name = g_strdup (display_name); + display->display_name = g_strdup (DisplayString (dpy)); thread = gst_cairo_x_thread_new (display); if (thread == NULL) { gst_cairo_x_display_unref (display); + DISPLAY_UNLOCK (); return NULL; } @@ -182,24 +253,14 @@ gst_cairo_x_display_new (const char *display_name) thread->depth = display->depth; display->visual_id = XVisualIDFromVisual (thread->visual); g_assert (display->visual_id != 0); - gst_cairo_x_thread_unref (thread); - - return display; -} + g_hash_table_insert (all_displays, dpy, display); + DISPLAY_UNLOCK (); -void -gst_cairo_x_display_free (GstCairoXDisplay * display) -{ - GHashTable *threads; + gst_cairo_x_display_attach (dpy); - g_return_if_fail (GST_CAIRO_IS_X_DISPLAY (display)); + gst_cairo_x_thread_unref (thread); - DISPLAY_LOCK (display); - threads = display->threads; - display->threads = NULL; - DISPLAY_UNLOCK (display); - g_hash_table_destroy (threads); - gst_cairo_x_display_unref (display); + return display; } GstCairoXThread * @@ -209,7 +270,7 @@ gst_cairo_x_display_get_thread (GstCairoXDisplay * display) GThread *self; self = g_thread_self (); - DISPLAY_LOCK (display); + DISPLAY_LOCK (); if (display->threads) thread = g_hash_table_lookup (display->threads, g_thread_self ()); else @@ -219,34 +280,6 @@ gst_cairo_x_display_get_thread (GstCairoXDisplay * display) thread = gst_cairo_x_thread_new (display); else g_atomic_int_inc (&thread->refcount); - DISPLAY_UNLOCK (display); + DISPLAY_UNLOCK (); return thread; } - -Display * -gst_cairo_x_display_get_display (GstCairoXDisplay * display) -{ - GstCairoXThread *thread; - - g_return_val_if_fail (GST_CAIRO_IS_X_DISPLAY (display), NULL); - - thread = gst_cairo_x_display_get_thread (display); - /* is fine, because the display isn't destroyed yet */ - gst_cairo_x_thread_unref (thread); - - return thread->display; -} - -Visual * -gst_cairo_x_display_get_visual (GstCairoXDisplay * display) -{ - GstCairoXThread *thread; - - g_return_val_if_fail (GST_CAIRO_IS_X_DISPLAY (display), NULL); - - thread = gst_cairo_x_display_get_thread (display); - /* is fine, because the display isn't destroyed yet */ - gst_cairo_x_thread_unref (thread); - - return thread->visual; -} diff --git a/ext/xlib/gstcairoxdisplay.h b/gst-libs/gst/cairo/gstcairoxdisplay.h index e985268..229c451 100644 --- a/ext/xlib/gstcairoxdisplay.h +++ b/gst-libs/gst/cairo/gstcairoxdisplay.h @@ -28,15 +28,10 @@ G_BEGIN_DECLS typedef struct _GstCairoXDisplay GstCairoXDisplay; -GstCairoXDisplay * gst_cairo_x_display_new (const char * display_name); -void gst_cairo_x_display_free (GstCairoXDisplay * display); +GstCairoXDisplay * gst_cairo_x_display_get (Display * display); -Display * gst_cairo_x_display_get_display (GstCairoXDisplay * display); -Visual * gst_cairo_x_display_get_visual (GstCairoXDisplay * display); -cairo_surface_t * gst_cairo_x_display_get_surface (GstCairoXDisplay * display, - cairo_surface_t * surface); - -/*< private >*/ +Visual * gst_cairo_x_display_find_visual (GstCairoXDisplay * display, + Display * dpy); GstCairoXDisplay * gst_cairo_x_display_ref (GstCairoXDisplay * display); void gst_cairo_x_display_unref (GstCairoXDisplay * display); |