[cairo-commit] cairo/src Makefile.am, 1.47,
1.48 cairo-xlib-surface.c, 1.65, 1.66 cairo-xlib-test.h, NONE,
1.1 cairo-xlib.h, 1.14, 1.15
Owen Taylor
commit at pdx.freedesktop.org
Fri May 13 17:54:46 PDT 2005
Committed by: otaylor
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv27045/src
Modified Files:
Makefile.am cairo-xlib-surface.c cairo-xlib.h
Added Files:
cairo-xlib-test.h
Log Message:
2005-05-13 Owen Taylor <otaylor at redhat.com>
* src/cairo-xlib-surface.c src/cairo-xlib.h
doc/public/cairo-sections.txt: Drop the _for_pixmap() and
_for_window() out of the create functions and use some lazy
cleverness to sniff the information out as needed.
* src/cairo-xlib-surface.c src/cairo-xlib-test.h Makefile.am:
add cairo_test_xlib_disable_render() to turn off RENDER
for tests.
* test/xlib-surface.c: Test various different types of
Xlib surface creation.
* src/cairo-xlib.h: Remove left-over include of Xrender.h.
Index: Makefile.am
===================================================================
RCS file: /cvs/cairo/cairo/src/Makefile.am,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -d -r1.47 -r1.48
--- Makefile.am 3 May 2005 15:16:47 -0000 1.47
+++ Makefile.am 14 May 2005 00:54:43 -0000 1.48
@@ -15,7 +15,7 @@
if CAIRO_HAS_XLIB_SURFACE
libcairo_xlib_headers = cairo-xlib.h
-libcairo_xlib_sources = cairo-xlib-surface.c
+libcairo_xlib_sources = cairo-xlib-surface.c cairo-xlib-test.h
endif
if CAIRO_HAS_QUARTZ_SURFACE
Index: cairo-xlib-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib-surface.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -d -r1.65 -r1.66
--- cairo-xlib-surface.c 13 May 2005 15:09:24 -0000 1.65
+++ cairo-xlib-surface.c 14 May 2005 00:54:43 -0000 1.66
@@ -36,11 +36,18 @@
#include "cairoint.h"
#include "cairo-xlib.h"
+#include "cairo-xlib-test.h"
+#include <X11/extensions/Xrender.h>
+
+/* Xlib doesn't define a typedef, so define one ourselves */
+typedef int (*cairo_xlib_error_func_t) (Display *display,
+ XErrorEvent *event);
typedef struct _cairo_xlib_surface cairo_xlib_surface_t;
typedef enum {
- CAIRO_XLIB_PIXMAP,
+ CAIRO_XLIB_UNKNOWN,
+ CAIRO_XLIB_PIXMAP,
CAIRO_XLIB_WINDOW
} cairo_xlib_drawable_type_t;
@@ -90,6 +97,24 @@
#define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
#define CAIRO_SURFACE_RENDER_HAS_FILTERS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
+static cairo_bool_t cairo_xlib_render_disabled = FALSE;
+
+/**
+ * cairo_test_xlib_disable_render:
+ *
+ * Disables the use of the RENDER extension.
+ *
+ * <note>
+ * This function is for testing use within the Cairo distribution
+ * <emphasis>only</emphasis> and is in any publically installed header.
+ * </note>
+ **/
+void
+cairo_test_xlib_disable_render (void)
+{
+ cairo_xlib_render_disabled = TRUE;
+}
+
static int
_CAIRO_FORMAT_DEPTH (cairo_format_t format)
{
@@ -133,7 +158,7 @@
_CAIRO_FORMAT_DEPTH (format));
surface = (cairo_xlib_surface_t *)
- cairo_xlib_surface_create_for_pixmap (dpy, pix, format);
+ cairo_xlib_surface_create (dpy, pix, format);
cairo_xlib_surface_set_size (&surface->base, width, height);
surface->owns_pixmap = TRUE;
@@ -159,6 +184,13 @@
return CAIRO_STATUS_SUCCESS;
}
+static int
+_noop_error_handler (Display *display,
+ XErrorEvent *event)
+{
+ return False; /* return value is ignored */
+}
+
static void
_cairo_xlib_surface_get_size (cairo_xlib_surface_t *surface,
int *width,
@@ -175,18 +207,60 @@
return;
}
- XGetGeometry (surface->dpy,
- surface->drawable,
- &root_ignore, &x_ignore, &y_ignore,
- &width_u, &height_u,
- &bwidth_ignore, &depth_ignore);
-
- /* The size of a pixmap can't change, so we store
- * the information to avoid having to get it again
+ /* The first time we get the size for a drawable, we
+ * also want to determine whether it was a window or
+ * a pixmap. By calling XGetWindowAttributes(), we'll
+ * get:
+ *
+ * A BadWindow error if the drawable was a pixmap
+ * The size if the drawable was a window
+ *
+ * In the first case, we retry with XGetGeometry(). We
+ * could reduce all cases to a single round-trip with
+ * custom Xlib async code, but since this code is never
+ * hit when we have RENDER, or when the application calls
+ * cairo_xlib_surface_set_size(), it's probably not
+ * worth it.
*/
- if (surface->type == CAIRO_XLIB_PIXMAP) {
- surface->width = width_u;
- surface->height = height_u;
+ retry:
+ if (surface->type == CAIRO_XLIB_UNKNOWN) {
+ cairo_xlib_error_func_t old_handler;
+ XWindowAttributes xwa;
+ int result;
+
+ old_handler = XSetErrorHandler (_noop_error_handler);
+
+ result = XGetWindowAttributes (surface->dpy,
+ surface->drawable,
+ &xwa);
+
+ XSetErrorHandler (old_handler);
+
+ if (result) {
+ surface->type = CAIRO_XLIB_WINDOW;
+
+ width_u = xwa.width;
+ height_u = xwa.height;
+ } else {
+ surface->type = CAIRO_XLIB_PIXMAP;
+ goto retry;
+ }
+
+ } else {
+
+ XGetGeometry (surface->dpy,
+ surface->drawable,
+ &root_ignore, &x_ignore, &y_ignore,
+ &width_u, &height_u,
+ &bwidth_ignore, &depth_ignore);
+
+ if (surface->type == CAIRO_XLIB_PIXMAP) {
+ /* The size of a pixmap can't change, so we store
+ * the information to avoid having to get it again
+ */
+ surface->width = width_u;
+ surface->height = height_u;
+ }
}
*width = width_u;
@@ -239,7 +313,8 @@
}
/* XXX: This should try to use the XShm extension if available */
-
+
+ retry:
if (surface->type == CAIRO_XLIB_WINDOW) {
/* XGetImage from a window is dangerous because it can
@@ -266,11 +341,25 @@
XFreePixmap (surface->dpy, pixmap);
} else {
+ cairo_xlib_error_func_t old_handler;
+
+ old_handler = XSetErrorHandler (_noop_error_handler);
+
ximage = XGetImage (surface->dpy,
surface->drawable,
x1, y1,
x2 - x1, y2 - y1,
AllPlanes, ZPixmap);
+
+ XSetErrorHandler (old_handler);
+
+ /* If we get an error, the surface must have been a window,
+ * so retry with the safe code path.
+ */
+ if (!ximage) {
+ surface->type = CAIRO_XLIB_WINDOW;
+ goto retry;
+ }
}
if (surface->visual) {
@@ -910,7 +999,6 @@
static cairo_surface_t *
_cairo_xlib_surface_create_internal (Display *dpy,
Drawable drawable,
- cairo_xlib_drawable_type_t type,
Visual *visual,
cairo_format_t format)
{
@@ -922,7 +1010,7 @@
_cairo_surface_init (&surface->base, &cairo_xlib_surface_backend);
- surface->type = type;
+ surface->type = CAIRO_XLIB_UNKNOWN;
surface->dpy = dpy;
@@ -962,7 +1050,8 @@
surface->visual = NULL;
}
- if (! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) {
+ if (cairo_xlib_render_disabled ||
+ ! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) {
surface->render_major = -1;
surface->render_minor = -1;
}
@@ -1005,87 +1094,60 @@
}
/**
- * cairo_xlib_surface_create_for_pixmap:
+ * cairo_xlib_surface_create:
* @dpy: an X display
- * @pixmap: an X pixmap
+ * @drawable: an X drawable
* @format: a standard cairo pixel data format. The depth (number of
* of bits used) for the format must match the depth of
* @pixmap.
*
- * Creates an Xlib surface that draws to the given pixmap.
+ * Creates an Xlib surface that draws to the given drawable.
* The way that colors are represented in the pixmap is specified
* by giving one of cairo's standard pixel data formats.
*
- * For maximum efficiency, if you know the size of the pixmap,
+ * For maximum efficiency, if you know the size of the drawable,
* you should call cairo_xlib_surface_set_size().
*
* Return value: the newly created surface
**/
cairo_surface_t *
-cairo_xlib_surface_create_for_pixmap (Display *dpy,
- Pixmap pixmap,
- cairo_format_t format)
+cairo_xlib_surface_create (Display *dpy,
+ Drawable drawable,
+ cairo_format_t format)
{
- return _cairo_xlib_surface_create_internal (dpy, pixmap,
- CAIRO_XLIB_PIXMAP,
+ return _cairo_xlib_surface_create_internal (dpy, drawable,
NULL, format);
}
/**
- * cairo_xlib_surface_create_for_pixmap_with_visual:
+ * cairo_xlib_surface_create_with_visual:
* @dpy: an X display
- * @pixmap: an X pixmap
- * @visual: the visual to use for drawing to @pixmap. The depth
- * of the visual must match the depth of the pixmap.
+ * @drawable: an X pixmap
+ * @visual: the visual to use for drawing to @drawable. The depth
+ * of the visual must match the depth of the drawable.
* Currently, only TrueColor visuals are fully supported.
*
- * Creates an Xlib surface that draws to the given pixmap.
- * The way that colors are represented in the pixmap is specified
+ * Creates an Xlib surface that draws to the given drawable.
+ * The way that colors are represented in the drawable is specified
* by an X visual.
*
* Normally, you would use this function instead of
- * cairo_xlib_surface_create_for_pixmap() when you double-buffering by
- * using cairo to draw to pixmap and then XCopyArea() to copy the
+ * cairo_xlib_surface_create() when you are double-buffering by
+ * using cairo to draw to a pixmap and then XCopyArea() to copy the
* results to a window. In that case, @visual is the visual of the
* window.
*
- * For maximum efficiency, if you know the size of the pixmap,
+ * For maximum efficiency, if you know the size of the drawable,
* you should call cairo_xlib_surface_set_size().
*
* Return value: the newly created surface
**/
cairo_surface_t *
-cairo_xlib_surface_create_for_pixmap_with_visual (Display *dpy,
- Pixmap pixmap,
- Visual *visual)
+cairo_xlib_surface_create_with_visual (Display *dpy,
+ Pixmap pixmap,
+ Visual *visual)
{
return _cairo_xlib_surface_create_internal (dpy, pixmap,
- CAIRO_XLIB_PIXMAP,
- visual,
- (cairo_format_t)-1);
-}
-
-/**
- * cairo_xlib_surface_create_for_window_with_visual:
- * @dpy: an X display
- * @window: an X window
- * @visual: the visual of @window. Currently, only TrueColor visuals
- * are fully supported.
- *
- * Creates a new XLib backend surface that draws to the given Window.
- *
- * For maximum efficiency, you should use cairo_xlib_surface_set_size()
- * to inform cairo of the size of the window.
- *
- * Return value: the newly created surface.
- **/
-cairo_surface_t *
-cairo_xlib_surface_create_for_window_with_visual (Display *dpy,
- Window window,
- Visual *visual)
-{
- return _cairo_xlib_surface_create_internal (dpy, window,
- CAIRO_XLIB_WINDOW,
visual,
(cairo_format_t)-1);
}
--- NEW FILE: cairo-xlib-test.h ---
(This appears to be a binary file; contents omitted.)
Index: cairo-xlib.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- cairo-xlib.h 11 May 2005 04:06:01 -0000 1.14
+++ cairo-xlib.h 14 May 2005 00:54:43 -0000 1.15
@@ -42,24 +42,18 @@
#if CAIRO_HAS_XLIB_SURFACE
#include <X11/Xlib.h>
-#include <X11/extensions/Xrender.h>
CAIRO_BEGIN_DECLS
cairo_surface_t *
-cairo_xlib_surface_create_for_pixmap (Display *dpy,
- Pixmap pixmap,
- cairo_format_t format);
-
-cairo_surface_t *
-cairo_xlib_surface_create_for_pixmap_with_visual (Display *dpy,
- Pixmap pixmap,
- Visual *visual);
+cairo_xlib_surface_create (Display *dpy,
+ Drawable drawable,
+ cairo_format_t format);
cairo_surface_t *
-cairo_xlib_surface_create_for_window_with_visual (Display *dpy,
- Window window,
- Visual *visual);
+cairo_xlib_surface_create_with_visual (Display *dpy,
+ Drawable drawable,
+ Visual *visual);
void
cairo_xlib_surface_set_size (cairo_surface_t *surface,
More information about the cairo-commit
mailing list