summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2009-10-13 12:04:36 +0200
committerBenjamin Otte <otte@gnome.org>2009-10-14 10:12:21 +0200
commitd8c30a3a55dcb8ace6fe1ae67add53dfeea1c072 (patch)
tree10c140518fd3ce5c836889afd69ab43ceceea5a3
parent734902ff1c524ca98993a118af6fb50f6b2d87ac (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.am4
-rw-r--r--ext/xlib/gstcairoxconvert.c18
-rw-r--r--ext/xlib/gstcairoxconvert.h4
-rw-r--r--ext/xlib/gstcairoxsink.c103
-rw-r--r--ext/xlib/gstcairoxsink.h8
-rw-r--r--gst-libs/gst/cairo/Makefile.am10
-rw-r--r--gst-libs/gst/cairo/gstcairobuffer.c39
-rw-r--r--gst-libs/gst/cairo/gstcairobuffer.h4
-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);