summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2009-10-05 16:03:37 +0200
committerBenjamin Otte <otte@gnome.org>2009-11-11 10:09:15 +0100
commitc4cc90d570d029a39eff55624be2b4584eff764c (patch)
tree76e82546f8cb9f9568298675db9609fb7dd99766
parentfbe9738c0fae3006502df79a68cd0b226f454f83 (diff)
Add very hacky support for uploading I420 as YUV.xv
This patch requires the X server supporting XvPutImage to work on pixmaps. It also fails to properly check abort conditions. Consider this a proof of concept more than anything else.
-rw-r--r--boilerplate/Makefile.win32.features10
-rw-r--r--build/Makefile.win32.features1
-rw-r--r--build/Makefile.win32.features-h3
-rw-r--r--configure.ac14
-rw-r--r--src/Makefile.win32.features14
-rw-r--r--src/cairo-image-surface.c14
-rw-r--r--src/cairo-xlib-surface.c106
7 files changed, 162 insertions, 0 deletions
diff --git a/boilerplate/Makefile.win32.features b/boilerplate/Makefile.win32.features
index 5c1e0119..647b9b1a 100644
--- a/boilerplate/Makefile.win32.features
+++ b/boilerplate/Makefile.win32.features
@@ -39,6 +39,16 @@ enabled_cairo_boilerplate_private += $(cairo_boilerplate_xlib_xrender_private)
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_xlib_xrender_sources)
endif
+supported_cairo_boilerplate_headers += $(cairo_boilerplate_xlib_xv_headers)
+all_cairo_boilerplate_headers += $(cairo_boilerplate_xlib_xv_headers)
+all_cairo_boilerplate_private += $(cairo_boilerplate_xlib_xv_private)
+all_cairo_boilerplate_sources += $(cairo_boilerplate_xlib_xv_sources)
+ifeq ($(CAIRO_HAS_XLIB_XV_SURFACE),1)
+enabled_cairo_boilerplate_headers += $(cairo_boilerplate_xlib_xv_headers)
+enabled_cairo_boilerplate_private += $(cairo_boilerplate_xlib_xv_private)
+enabled_cairo_boilerplate_sources += $(cairo_boilerplate_xlib_xv_sources)
+endif
+
unsupported_cairo_boilerplate_headers += $(cairo_boilerplate_xcb_headers)
all_cairo_boilerplate_headers += $(cairo_boilerplate_xcb_headers)
all_cairo_boilerplate_private += $(cairo_boilerplate_xcb_private)
diff --git a/build/Makefile.win32.features b/build/Makefile.win32.features
index bd314e9f..1cd72adb 100644
--- a/build/Makefile.win32.features
+++ b/build/Makefile.win32.features
@@ -2,6 +2,7 @@
CAIRO_HAS_XLIB_SURFACE=0
CAIRO_HAS_XLIB_XRENDER_SURFACE=0
+CAIRO_HAS_XLIB_XV_SURFACE=0
CAIRO_HAS_XCB_SURFACE=0
CAIRO_HAS_QT_SURFACE=0
CAIRO_HAS_QUARTZ_SURFACE=0
diff --git a/build/Makefile.win32.features-h b/build/Makefile.win32.features-h
index 7e49cd63..bfd2c3c4 100644
--- a/build/Makefile.win32.features-h
+++ b/build/Makefile.win32.features-h
@@ -11,6 +11,9 @@ endif
ifeq ($(CAIRO_HAS_XLIB_XRENDER_SURFACE),1)
@echo "#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1" >> src/cairo-features.h
endif
+ifeq ($(CAIRO_HAS_XLIB_XV_SURFACE),1)
+ @echo "#define CAIRO_HAS_XLIB_XV_SURFACE 1" >> src/cairo-features.h
+endif
ifeq ($(CAIRO_HAS_XCB_SURFACE),1)
@echo "#define CAIRO_HAS_XCB_SURFACE 1" >> src/cairo-features.h
endif
diff --git a/configure.ac b/configure.ac
index ba3cbc06..6a1c8683 100644
--- a/configure.ac
+++ b/configure.ac
@@ -103,6 +103,20 @@ CAIRO_ENABLE_SURFACE_BACKEND(xlib_xrender, Xlib Xrender, auto, [
fi
])
+CAIRO_ENABLE_SURFACE_BACKEND(xlib_xv, Xlib Xv, auto, [
+ if test "x$use_xlib" != "xyes"; then
+ use_xlib_xv="no (requires --enable-xlib)"
+ else
+ xlib_xv_BASE=cairo-xlib
+ xlib_xv_REQUIRES="xv"
+ PKG_CHECK_MODULES(xlib_xv, $xlib_xv_REQUIRES,
+ [AC_DEFINE([CAIRO_HAS_XV], 1, [Define to 1 if xv support is available])],
+ [AC_MSG_RESULT(no)
+ use_xlib_xrender="no (requires $xlib_xrender_REQUIRES http://freedesktop.org/Software/xlibs)"
+ ])
+ fi
+])
+
dnl ===========================================================================
CAIRO_ENABLE_SURFACE_BACKEND(xcb, XCB, no, [
diff --git a/src/Makefile.win32.features b/src/Makefile.win32.features
index 048c9211..207b84c2 100644
--- a/src/Makefile.win32.features
+++ b/src/Makefile.win32.features
@@ -49,6 +49,20 @@ ifeq ($(CAIRO_HAS_XLIB_XRENDER_SURFACE),1)
enabled_cairo_pkgconf += cairo-xlib-xrender.pc
endif
+supported_cairo_headers += $(cairo_xlib_xv_headers)
+all_cairo_headers += $(cairo_xlib_xv_headers)
+all_cairo_private += $(cairo_xlib_xv_private)
+all_cairo_sources += $(cairo_xlib_xv_sources)
+ifeq ($(CAIRO_HAS_XLIB_XV_SURFACE),1)
+enabled_cairo_headers += $(cairo_xlib_xv_headers)
+enabled_cairo_private += $(cairo_xlib_xv_private)
+enabled_cairo_sources += $(cairo_xlib_xv_sources)
+endif
+all_cairo_pkgconf += cairo-xlib-xv.pc
+ifeq ($(CAIRO_HAS_XLIB_XV_SURFACE),1)
+enabled_cairo_pkgconf += cairo-xlib-xv.pc
+endif
+
unsupported_cairo_headers += $(cairo_xcb_headers)
all_cairo_headers += $(cairo_xcb_headers)
all_cairo_private += $(cairo_xcb_private)
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index ebf6c39f..d057c559 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -116,6 +116,9 @@ _cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,15,16)
case PIXMAN_a2r10g10b10:
#endif
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,17,0)
+ case PIXMAN_ayuv:
+#endif
return CAIRO_CONTENT_COLOR_ALPHA;
case PIXMAN_x8r8g8b8:
case PIXMAN_x8b8g8r8:
@@ -145,6 +148,17 @@ _cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,15,16)
case PIXMAN_x2r10g10b10:
#endif
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,17,0)
+ case PIXMAN_i420:
+ case PIXMAN_nv12:
+ case PIXMAN_nv21:
+ case PIXMAN_y41b:
+ case PIXMAN_y42b:
+ case PIXMAN_y444:
+ case PIXMAN_yuy2:
+ case PIXMAN_uyvy:
+ case PIXMAN_yvyu:
+#endif
return CAIRO_CONTENT_COLOR;
case PIXMAN_a8:
case PIXMAN_a1:
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 20ba21cb..6a768112 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -55,6 +55,9 @@
#include <X11/Xutil.h> /* for XDestroyImage */
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+
#define XLIB_COORD_MAX 32767
#define DEBUG 0
@@ -998,6 +1001,101 @@ _cairo_xlib_surface_put_gc (cairo_xlib_surface_t *surface, GC gc)
gc);
}
+static const struct {
+ pixman_format_code_t pixman_format;
+ int xv_id;
+} xv_format_map[] = {
+ { PIXMAN_i420, 0x30323449 }
+};
+
+static cairo_status_t
+_draw_image_surface_xv (cairo_xlib_surface_t *surface,
+ cairo_image_surface_t *image,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
+ int dst_x,
+ int dst_y)
+{
+ XvImage *xvimage;
+ int res, j, n_formats;
+ unsigned int i, n_adaptors, format_id;
+ cairo_status_t status;
+ XvImageFormatValues *formats;
+ XvAdaptorInfo *adaptors;
+ XvPortID port;
+ GC gc;
+
+ res = XvQueryAdaptors (surface->dpy,
+ RootWindowOfScreen (surface->screen->screen),
+ &n_adaptors,
+ &adaptors);
+ if (res != Success)
+ return res == XvBadAlloc ? _cairo_error (CAIRO_STATUS_NO_MEMORY) : CAIRO_INT_STATUS_UNSUPPORTED;
+
+ for (format_id = 0; format_id < ARRAY_LENGTH (xv_format_map); format_id++)
+ {
+ if (xv_format_map[format_id].pixman_format == image->pixman_format)
+ break;
+ }
+ if (format_id == ARRAY_LENGTH (xv_format_map))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ for (i = 0; i < n_adaptors; i++)
+ {
+ if ((adaptors[i].type & (XvInputMask | XvImageMask)) != (XvInputMask | XvImageMask))
+ continue;
+
+ port = adaptors[i].base_id;
+
+ formats = XvListImageFormats (surface->dpy, port, &n_formats);
+ for (j = 0; j < n_formats; j++)
+ {
+ if (formats[j].type != XvYUV)
+ continue;
+
+ if (formats[j].id == xv_format_map[format_id].xv_id)
+ break;
+ }
+ XFree (formats);
+ if (j < n_formats)
+ break;
+ }
+ XFree (adaptors);
+
+ if (i == n_adaptors)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ /* FIXME: check strides here */
+
+ xvimage = XvCreateImage (surface->dpy, port,
+ xv_format_map[format_id].xv_id,
+ (char *) pixman_image_get_data (image->pixman_image),
+ pixman_image_get_width (image->pixman_image),
+ pixman_image_get_height (image->pixman_image));
+ if (xvimage == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ status = _cairo_xlib_surface_get_gc (surface, &gc);
+ if (unlikely (status))
+ {
+ XFree (xvimage);
+ return status;
+ }
+
+ XvPutImage (surface->dpy, port,
+ surface->drawable, gc,
+ xvimage,
+ src_x, src_y, width, height,
+ dst_x, dst_y, width, height);
+
+ _cairo_xlib_surface_put_gc (surface, gc);
+ XFree (xvimage);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
static cairo_status_t
_draw_image_surface (cairo_xlib_surface_t *surface,
cairo_image_surface_t *image,
@@ -1016,6 +1114,14 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
cairo_bool_t own_data;
GC gc;
+ status = _draw_image_surface_xv (surface,
+ image,
+ src_x, src_y,
+ width, height,
+ dst_x, dst_y);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
ximage.width = image->width;
ximage.height = image->height;
ximage.format = ZPixmap;