Lines
0.48 %
Functions
7.69 %
Branches
0 %
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/*
* Copyright © 2004,2006 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Red Hat, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Red Hat, Inc. makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* Author: Carl D. Worth <cworth@cworth.org>
*/
#include "cairo-boilerplate-private.h"
#include "cairo-boilerplate-xlib.h"
#include "cairo-malloc-private.h"
#include <cairo-xlib.h>
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
#include <cairo-xlib-xrender.h>
#endif
#include <X11/Xutil.h> /* for XDestroyImage */
#if !CAIRO_HAS_XLIB_XRENDER_SURFACE
#define PolyModePrecise 0
static const cairo_user_data_key_t key;
typedef struct _xlib_target_closure {
Display *dpy;
Drawable drawable;
cairo_bool_t drawable_is_pixmap;
} xlib_target_closure_t;
static void
_cairo_boilerplate_xlib_cleanup (void *closure)
{
xlib_target_closure_t *xtc = closure;
if (xtc->drawable) {
if (xtc->drawable_is_pixmap)
XFreePixmap (xtc->dpy, xtc->drawable);
else
XDestroyWindow (xtc->dpy, xtc->drawable);
}
XCloseDisplay (xtc->dpy);
free (xtc);
_cairo_boilerplate_xlib_synchronize (void *closure)
XImage *ximage;
ximage = XGetImage (xtc->dpy, xtc->drawable,
0, 0, 1, 1, AllPlanes, ZPixmap);
if (ximage != NULL)
XDestroyImage (ximage);
static cairo_bool_t
_cairo_boilerplate_xlib_check_screen_size (Display *dpy,
int screen,
int width,
int height)
Screen *scr = XScreenOfDisplay (dpy, screen);
return width <= WidthOfScreen (scr) && height <= HeightOfScreen (scr);
_cairo_boilerplate_xlib_setup_test_surface (cairo_surface_t *surface)
/* For testing purposes, tell the X server to strictly adhere to the
* Render specification.
cairo_xlib_device_debug_set_precision(cairo_surface_get_device(surface),
PolyModePrecise);
/* For the xlib backend we distinguish between TEST and PERF mode in a
* couple of ways.
* For TEST, we always test against pixmaps of depth 32 (for
* COLOR_ALPHA) or 24 (for COLOR) and we use XSynchronize to make it
* easier to debug problems.
* For PERF, we test against 32-bit pixmaps for COLOR_ALPHA, but for
* COLOR we test against _windows_ at the depth of the default visual.
* For obvious reasons, we don't use XSynchronize.
static cairo_surface_t *
_cairo_boilerplate_xlib_test_create_surface (Display *dpy,
cairo_content_t content,
int height,
xlib_target_closure_t *xtc)
XRenderPictFormat *xrender_format;
cairo_surface_t *surface;
/* This kills performance, but it makes debugging much
* easier. That's why we have it here when in TEST mode, but not
* over in PERF mode. */
XSynchronize (xtc->dpy, 1);
/* XXX: Currently we don't do any xlib testing when the X server
* doesn't have the Render extension. We could do better here,
* (perhaps by converting the tests from ARGB32 to RGB24). One
* step better would be to always test the non-Render fallbacks
* for each test even if the server does have the Render
* extension. That would probably be through another
* cairo_boilerplate_target which would use an extended version of
* cairo_test_xlib_disable_render. */
switch (content) {
case CAIRO_CONTENT_COLOR_ALPHA:
xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
break;
case CAIRO_CONTENT_COLOR:
xrender_format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
case CAIRO_CONTENT_ALPHA:
default:
CAIRO_BOILERPLATE_DEBUG (("Invalid content for xlib test: %d\n", content));
return NULL;
if (xrender_format == NULL) {
CAIRO_BOILERPLATE_DEBUG (("X server does not have the Render extension.\n"));
xtc->drawable = XCreatePixmap (dpy, DefaultRootWindow (dpy),
width, height, xrender_format->depth);
xtc->drawable_is_pixmap = TRUE;
surface = cairo_xlib_surface_create_with_xrender_format (dpy, xtc->drawable,
DefaultScreenOfDisplay (dpy),
xrender_format,
width, height);
_cairo_boilerplate_xlib_setup_test_surface(surface);
return surface;
_cairo_boilerplate_xlib_perf_create_surface (Display *dpy,
XSetWindowAttributes attr;
Visual *visual;
if (! _cairo_boilerplate_xlib_check_screen_size (dpy,
DefaultScreen (dpy),
width, height)) {
CAIRO_BOILERPLATE_DEBUG (("Surface is larger than the Screen.\n"));
visual = DefaultVisual (dpy, DefaultScreen (dpy));
xrender_format = XRenderFindVisualFormat (dpy, visual);
attr.override_redirect = True;
xtc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
width, height, 0, xrender_format->depth,
InputOutput, visual, CWOverrideRedirect, &attr);
XMapWindow (dpy, xtc->drawable);
xtc->drawable_is_pixmap = FALSE;
return cairo_xlib_surface_create_with_xrender_format (dpy, xtc->drawable,
struct similar {
Pixmap pixmap;
};
static void _destroy_similar (void *closure)
struct similar *similar = closure;
XFreePixmap (similar->dpy, similar->pixmap);
free (similar);
_cairo_boilerplate_xlib_create_similar (cairo_surface_t *other,
uint32_t format;
struct similar *similar;
similar = _cairo_malloc (sizeof (*similar));
similar->dpy = cairo_xlib_surface_get_display (other);
format = PictStandardRGB24;
format = PictStandardA8;
format = PictStandardARGB32;
xrender_format = XRenderFindStandardFormat (similar->dpy, format);
similar->pixmap = XCreatePixmap (similar->dpy,
DefaultRootWindow (similar->dpy),
width, height,
xrender_format->depth);
surface =
cairo_xlib_surface_create_with_xrender_format (similar->dpy,
similar->pixmap,
DefaultScreenOfDisplay (similar->dpy),
cairo_surface_set_user_data (surface, &key, similar, _destroy_similar);
_cairo_boilerplate_xlib_create_surface (const char *name,
double width,
double height,
double max_width,
double max_height,
cairo_boilerplate_mode_t mode,
void **closure)
xlib_target_closure_t *xtc;
*closure = xtc = xcalloc (1, sizeof (xlib_target_closure_t));
width = ceil (width);
if (width < 1)
width = 1;
height = ceil (height);
if (height < 1)
height = 1;
xtc->dpy = dpy = XOpenDisplay (NULL);
if (xtc->dpy == NULL) {
CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", XDisplayName(0)));
if (mode == CAIRO_BOILERPLATE_MODE_TEST)
surface = _cairo_boilerplate_xlib_test_create_surface (dpy, content, width, height, xtc);
else /* mode == CAIRO_BOILERPLATE_MODE_PERF */
surface = _cairo_boilerplate_xlib_perf_create_surface (dpy, content, width, height, xtc);
if (surface == NULL || cairo_surface_status (surface))
_cairo_boilerplate_xlib_cleanup (xtc);
_cairo_boilerplate_xlib_render_0_0_create_surface (const char *name,
int screen;
cairo_surface_t *surface, *dummy;
screen = DefaultScreen (dpy);
pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy), 1, 1,
DefaultDepth (dpy, screen));
dummy = cairo_xlib_surface_create (dpy, pixmap,
DefaultVisual (dpy, screen),
1, 1);
cairo_xlib_device_debug_cap_xrender_version (cairo_surface_get_device (dummy),
0, 0);
cairo_surface_destroy (dummy);
XFreePixmap (dpy, pixmap);
_cairo_boilerplate_xlib_window_create_surface (const char *name,
/* We're not yet bothering to support perf mode for the
* xlib-fallback surface. */
if (mode == CAIRO_BOILERPLATE_MODE_PERF)
/* We also don't support drawing with destination-alpha in the
if (content == CAIRO_CONTENT_COLOR_ALPHA)
*closure = xtc = xmalloc (sizeof (xlib_target_closure_t));
* easier. That's why we have it here only after explicitly not
* supporting PERF mode.*/
XSynchronize (dpy, 1);
if (! _cairo_boilerplate_xlib_check_screen_size (dpy, screen,
XCloseDisplay (dpy);
xtc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
0, 0,
width, height, 0,
DefaultDepth (dpy, screen),
InputOutput,
CWOverrideRedirect, &attr);
surface = cairo_xlib_surface_create (dpy, xtc->drawable,
if (cairo_surface_status (surface))
#if CAIRO_HAS_XLIB_SURFACE
/* The xlib-fallback target differs from the xlib target in two ways:
* 1. It creates its surfaces without relying on the Render extension
* 2. It disables use of the Render extension for its surfaces
* This provides testing of the non-Render fallback paths we have in
* cairo-xlib-surface.c
_cairo_boilerplate_xlib_fallback_create_surface (const char *name,
dummy = cairo_xlib_surface_create (dpy, xtc->drawable,
-1, -1);
static const cairo_boilerplate_target_t targets[] = {
/* Acceleration architectures may make the results differ by a
* bit, so we set the error tolerance to 1. */
"xlib", "traps", NULL, "xlib-fallback",
CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA, 1,
"cairo_xlib_surface_create_with_xrender_format",
_cairo_boilerplate_xlib_create_surface,
_cairo_boilerplate_xlib_create_similar,
NULL, NULL,
_cairo_boilerplate_get_image_surface,
cairo_surface_write_to_png,
_cairo_boilerplate_xlib_cleanup,
_cairo_boilerplate_xlib_synchronize,
NULL,
TRUE, FALSE, FALSE
},
CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
FALSE, FALSE, FALSE
"xlib-window", "traps", NULL, NULL,
"cairo_xlib_surface_create",
_cairo_boilerplate_xlib_window_create_surface,
cairo_surface_create_similar,
"xlib-render-0_0", "mask", NULL, NULL,
_cairo_boilerplate_xlib_render_0_0_create_surface,
/* This is a fallback surface which uses xlib fallbacks instead of
* the Render extension. */
"xlib-fallback", "image", NULL, NULL,
_cairo_boilerplate_xlib_fallback_create_surface,
CAIRO_BOILERPLATE (xlib, targets)