2007-04-19 19:56:05 -04:00
|
|
|
/* -*- 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>
|
|
|
|
|
*/
|
|
|
|
|
|
2009-07-04 21:43:27 +01:00
|
|
|
#include "cairo-boilerplate-private.h"
|
2007-04-20 02:27:19 -04:00
|
|
|
#include "cairo-boilerplate-xlib.h"
|
2007-04-19 19:56:05 -04:00
|
|
|
|
2008-01-14 18:09:32 +00:00
|
|
|
#include <cairo-xlib.h>
|
|
|
|
|
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
2007-04-19 19:56:05 -04:00
|
|
|
#include <cairo-xlib-xrender.h>
|
2008-01-14 18:09:32 +00:00
|
|
|
#endif
|
2007-04-19 19:56:05 -04:00
|
|
|
|
2008-01-14 18:09:32 +00:00
|
|
|
#include <X11/Xutil.h> /* for XDestroyImage */
|
|
|
|
|
|
2011-10-08 10:48:26 +02:00
|
|
|
#if !CAIRO_HAS_XLIB_XRENDER_SURFACE
|
|
|
|
|
#define PolyModePrecise 0
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-06-01 23:03:36 +01:00
|
|
|
static const cairo_user_data_key_t key;
|
|
|
|
|
|
2009-07-04 21:43:27 +01:00
|
|
|
typedef struct _xlib_target_closure {
|
2007-04-19 19:56:05 -04:00
|
|
|
Display *dpy;
|
|
|
|
|
Drawable drawable;
|
|
|
|
|
cairo_bool_t drawable_is_pixmap;
|
|
|
|
|
} xlib_target_closure_t;
|
|
|
|
|
|
2009-07-04 21:43:27 +01:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2007-04-19 19:56:05 -04:00
|
|
|
_cairo_boilerplate_xlib_synchronize (void *closure)
|
|
|
|
|
{
|
|
|
|
|
xlib_target_closure_t *xtc = closure;
|
|
|
|
|
XImage *ximage;
|
|
|
|
|
|
|
|
|
|
ximage = XGetImage (xtc->dpy, xtc->drawable,
|
|
|
|
|
0, 0, 1, 1, AllPlanes, ZPixmap);
|
|
|
|
|
if (ximage != NULL)
|
|
|
|
|
XDestroyImage (ximage);
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-14 18:09:32 +00:00
|
|
|
static cairo_bool_t
|
2010-06-24 14:59:18 +03:00
|
|
|
_cairo_boilerplate_xlib_check_screen_size (Display *dpy,
|
|
|
|
|
int screen,
|
|
|
|
|
int width,
|
|
|
|
|
int height)
|
2008-01-14 18:09:32 +00:00
|
|
|
{
|
|
|
|
|
Screen *scr = XScreenOfDisplay (dpy, screen);
|
|
|
|
|
return width <= WidthOfScreen (scr) && height <= HeightOfScreen (scr);
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-27 15:59:37 +01:00
|
|
|
static void
|
|
|
|
|
_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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-01-14 18:09:32 +00:00
|
|
|
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
2007-04-19 19:56:05 -04:00
|
|
|
/* 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 *
|
2010-06-24 14:59:18 +03:00
|
|
|
_cairo_boilerplate_xlib_test_create_surface (Display *dpy,
|
|
|
|
|
cairo_content_t content,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
xlib_target_closure_t *xtc)
|
2007-04-19 19:56:05 -04:00
|
|
|
{
|
|
|
|
|
XRenderPictFormat *xrender_format;
|
2011-05-27 15:59:37 +01:00
|
|
|
cairo_surface_t *surface;
|
2007-04-19 19:56:05 -04:00
|
|
|
|
|
|
|
|
/* 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
|
2010-06-24 14:59:18 +03:00
|
|
|
* cairo_test_xlib_disable_render. */
|
2007-04-19 19:56:05 -04:00
|
|
|
switch (content) {
|
|
|
|
|
case CAIRO_CONTENT_COLOR_ALPHA:
|
|
|
|
|
xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
|
|
|
|
|
break;
|
|
|
|
|
case CAIRO_CONTENT_COLOR:
|
|
|
|
|
xrender_format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
|
|
|
|
|
break;
|
|
|
|
|
case CAIRO_CONTENT_ALPHA:
|
|
|
|
|
default:
|
2009-01-03 22:30:55 +00:00
|
|
|
CAIRO_BOILERPLATE_DEBUG (("Invalid content for xlib test: %d\n", content));
|
2007-04-19 19:56:05 -04:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
if (xrender_format == NULL) {
|
2009-01-03 22:30:55 +00:00
|
|
|
CAIRO_BOILERPLATE_DEBUG (("X server does not have the Render extension.\n"));
|
2007-04-19 19:56:05 -04:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
xtc->drawable = XCreatePixmap (dpy, DefaultRootWindow (dpy),
|
|
|
|
|
width, height, xrender_format->depth);
|
|
|
|
|
xtc->drawable_is_pixmap = TRUE;
|
|
|
|
|
|
2011-05-27 15:59:37 +01:00
|
|
|
surface = cairo_xlib_surface_create_with_xrender_format (dpy, xtc->drawable,
|
2007-04-19 19:56:05 -04:00
|
|
|
DefaultScreenOfDisplay (dpy),
|
|
|
|
|
xrender_format,
|
|
|
|
|
width, height);
|
2011-05-27 15:59:37 +01:00
|
|
|
|
|
|
|
|
_cairo_boilerplate_xlib_setup_test_surface(surface);
|
|
|
|
|
|
|
|
|
|
return surface;
|
2007-04-19 19:56:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_surface_t *
|
2010-06-24 14:59:18 +03:00
|
|
|
_cairo_boilerplate_xlib_perf_create_surface (Display *dpy,
|
|
|
|
|
cairo_content_t content,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
xlib_target_closure_t *xtc)
|
2007-04-19 19:56:05 -04:00
|
|
|
{
|
|
|
|
|
XSetWindowAttributes attr;
|
|
|
|
|
XRenderPictFormat *xrender_format;
|
|
|
|
|
Visual *visual;
|
|
|
|
|
|
|
|
|
|
switch (content) {
|
|
|
|
|
case CAIRO_CONTENT_COLOR_ALPHA:
|
|
|
|
|
xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
|
2007-08-16 14:34:07 +01:00
|
|
|
if (xrender_format == NULL) {
|
2009-01-03 22:30:55 +00:00
|
|
|
CAIRO_BOILERPLATE_DEBUG (("X server does not have the Render extension.\n"));
|
2007-08-16 14:34:07 +01:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2007-04-19 19:56:05 -04:00
|
|
|
xtc->drawable = XCreatePixmap (dpy, DefaultRootWindow (dpy),
|
|
|
|
|
width, height, xrender_format->depth);
|
|
|
|
|
xtc->drawable_is_pixmap = TRUE;
|
|
|
|
|
break;
|
2007-08-16 14:34:07 +01:00
|
|
|
|
2007-04-19 19:56:05 -04:00
|
|
|
case CAIRO_CONTENT_COLOR:
|
2007-08-24 13:40:26 +01:00
|
|
|
if (! _cairo_boilerplate_xlib_check_screen_size (dpy,
|
2010-06-24 14:59:18 +03:00
|
|
|
DefaultScreen (dpy),
|
|
|
|
|
width, height)) {
|
2009-01-03 22:30:55 +00:00
|
|
|
CAIRO_BOILERPLATE_DEBUG (("Surface is larger than the Screen.\n"));
|
2007-08-24 13:40:26 +01:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2007-04-19 19:56:05 -04:00
|
|
|
visual = DefaultVisual (dpy, DefaultScreen (dpy));
|
|
|
|
|
xrender_format = XRenderFindVisualFormat (dpy, visual);
|
2007-08-16 14:34:07 +01:00
|
|
|
if (xrender_format == NULL) {
|
2009-01-03 22:30:55 +00:00
|
|
|
CAIRO_BOILERPLATE_DEBUG (("X server does not have the Render extension.\n"));
|
2007-08-16 14:34:07 +01:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2007-04-19 19:56:05 -04:00
|
|
|
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;
|
|
|
|
|
break;
|
2007-08-16 14:34:07 +01:00
|
|
|
|
2007-04-19 19:56:05 -04:00
|
|
|
case CAIRO_CONTENT_ALPHA:
|
|
|
|
|
default:
|
2009-01-03 22:30:55 +00:00
|
|
|
CAIRO_BOILERPLATE_DEBUG (("Invalid content for xlib test: %d\n", content));
|
2007-04-19 19:56:05 -04:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cairo_xlib_surface_create_with_xrender_format (dpy, xtc->drawable,
|
|
|
|
|
DefaultScreenOfDisplay (dpy),
|
|
|
|
|
xrender_format,
|
|
|
|
|
width, height);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-01 23:03:36 +01:00
|
|
|
struct similar {
|
|
|
|
|
Display *dpy;
|
|
|
|
|
Pixmap pixmap;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void _destroy_similar (void *closure)
|
|
|
|
|
{
|
|
|
|
|
struct similar *similar = closure;
|
|
|
|
|
|
|
|
|
|
XFreePixmap (similar->dpy, similar->pixmap);
|
|
|
|
|
free (similar);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_surface_t *
|
|
|
|
|
_cairo_boilerplate_xlib_create_similar (cairo_surface_t *other,
|
|
|
|
|
cairo_content_t content,
|
|
|
|
|
int width,
|
|
|
|
|
int height)
|
|
|
|
|
{
|
|
|
|
|
XRenderPictFormat *xrender_format;
|
|
|
|
|
uint32_t format;
|
|
|
|
|
struct similar *similar;
|
|
|
|
|
cairo_surface_t *surface;
|
|
|
|
|
|
|
|
|
|
similar = malloc (sizeof (*similar));
|
|
|
|
|
similar->dpy = cairo_xlib_surface_get_display (other);
|
|
|
|
|
|
|
|
|
|
switch (content) {
|
|
|
|
|
default:
|
|
|
|
|
case CAIRO_CONTENT_COLOR_ALPHA: format = PictStandardARGB32; break;
|
|
|
|
|
case CAIRO_CONTENT_COLOR: format = PictStandardRGB24; break;
|
|
|
|
|
case CAIRO_CONTENT_ALPHA: format = PictStandardA8; break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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),
|
|
|
|
|
xrender_format,
|
|
|
|
|
width, height);
|
|
|
|
|
|
|
|
|
|
cairo_surface_set_user_data (surface, &key, similar, _destroy_similar);
|
|
|
|
|
|
|
|
|
|
return surface;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-04 21:43:27 +01:00
|
|
|
static cairo_surface_t *
|
2010-06-24 14:59:18 +03:00
|
|
|
_cairo_boilerplate_xlib_create_surface (const char *name,
|
|
|
|
|
cairo_content_t content,
|
|
|
|
|
double width,
|
|
|
|
|
double height,
|
|
|
|
|
double max_width,
|
|
|
|
|
double max_height,
|
|
|
|
|
cairo_boilerplate_mode_t mode,
|
|
|
|
|
void **closure)
|
2007-04-19 19:56:05 -04:00
|
|
|
{
|
|
|
|
|
xlib_target_closure_t *xtc;
|
|
|
|
|
Display *dpy;
|
2008-08-11 21:12:45 +01:00
|
|
|
cairo_surface_t *surface;
|
2007-04-19 19:56:05 -04:00
|
|
|
|
2008-08-11 21:12:45 +01:00
|
|
|
*closure = xtc = xcalloc (1, sizeof (xlib_target_closure_t));
|
2007-04-19 19:56:05 -04:00
|
|
|
|
2009-06-27 17:53:18 +01:00
|
|
|
width = ceil (width);
|
|
|
|
|
if (width < 1)
|
2007-04-19 19:56:05 -04:00
|
|
|
width = 1;
|
2009-06-27 17:53:18 +01:00
|
|
|
|
|
|
|
|
height = ceil (height);
|
|
|
|
|
if (height < 1)
|
2007-04-19 19:56:05 -04:00
|
|
|
height = 1;
|
|
|
|
|
|
|
|
|
|
xtc->dpy = dpy = XOpenDisplay (NULL);
|
|
|
|
|
if (xtc->dpy == NULL) {
|
2008-08-11 21:12:45 +01:00
|
|
|
free (xtc);
|
2009-01-03 22:30:55 +00:00
|
|
|
CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", XDisplayName(0)));
|
2007-04-19 19:56:05 -04:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-21 10:08:21 +01:00
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
return surface;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-27 17:52:11 +01:00
|
|
|
static cairo_surface_t *
|
2010-06-24 14:59:18 +03:00
|
|
|
_cairo_boilerplate_xlib_window_create_surface (const char *name,
|
2010-05-27 17:52:11 +01:00
|
|
|
cairo_content_t content,
|
2010-06-24 14:59:18 +03:00
|
|
|
double width,
|
|
|
|
|
double height,
|
|
|
|
|
double max_width,
|
|
|
|
|
double max_height,
|
|
|
|
|
cairo_boilerplate_mode_t mode,
|
|
|
|
|
void **closure)
|
2010-05-27 17:52:11 +01:00
|
|
|
{
|
|
|
|
|
xlib_target_closure_t *xtc;
|
|
|
|
|
Display *dpy;
|
2011-10-26 19:16:17 +02:00
|
|
|
int screen;
|
2010-05-27 17:52:11 +01:00
|
|
|
XSetWindowAttributes attr;
|
|
|
|
|
cairo_surface_t *surface;
|
|
|
|
|
|
|
|
|
|
/* We're not yet bothering to support perf mode for the
|
|
|
|
|
* xlib-fallback surface. */
|
|
|
|
|
if (mode == CAIRO_BOILERPLATE_MODE_PERF)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
/* We also don't support drawing with destination-alpha in the
|
|
|
|
|
* xlib-fallback surface. */
|
|
|
|
|
if (content == CAIRO_CONTENT_COLOR_ALPHA)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
*closure = xtc = xmalloc (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)));
|
|
|
|
|
free (xtc);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This kills performance, but it makes debugging much
|
|
|
|
|
* easier. That's why we have it here only after explicitly not
|
|
|
|
|
* supporting PERF mode.*/
|
|
|
|
|
XSynchronize (dpy, 1);
|
|
|
|
|
|
|
|
|
|
screen = DefaultScreen (dpy);
|
|
|
|
|
if (! _cairo_boilerplate_xlib_check_screen_size (dpy, screen,
|
2010-06-24 14:59:18 +03:00
|
|
|
width, height)) {
|
2010-05-27 17:52:11 +01:00
|
|
|
CAIRO_BOILERPLATE_DEBUG (("Surface is larger than the Screen.\n"));
|
|
|
|
|
XCloseDisplay (dpy);
|
|
|
|
|
free (xtc);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
attr.override_redirect = True;
|
|
|
|
|
xtc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
|
2011-10-26 19:16:17 +02:00
|
|
|
0, 0,
|
2010-05-27 17:52:11 +01:00
|
|
|
width, height, 0,
|
|
|
|
|
DefaultDepth (dpy, screen),
|
|
|
|
|
InputOutput,
|
|
|
|
|
DefaultVisual (dpy, screen),
|
|
|
|
|
CWOverrideRedirect, &attr);
|
|
|
|
|
XMapWindow (dpy, xtc->drawable);
|
|
|
|
|
xtc->drawable_is_pixmap = FALSE;
|
|
|
|
|
|
|
|
|
|
surface = cairo_xlib_surface_create (dpy, xtc->drawable,
|
|
|
|
|
DefaultVisual (dpy, screen),
|
|
|
|
|
width, height);
|
|
|
|
|
if (cairo_surface_status (surface))
|
|
|
|
|
_cairo_boilerplate_xlib_cleanup (xtc);
|
|
|
|
|
|
2011-05-27 15:59:37 +01:00
|
|
|
_cairo_boilerplate_xlib_setup_test_surface(surface);
|
|
|
|
|
|
2010-05-27 17:52:11 +01:00
|
|
|
return surface;
|
|
|
|
|
}
|
2010-04-01 20:42:44 +01:00
|
|
|
#endif
|
2009-07-04 21:43:27 +01:00
|
|
|
|
2007-04-19 19:56:05 -04:00
|
|
|
|
2010-04-01 20:42:44 +01:00
|
|
|
#if CAIRO_HAS_XLIB_SURFACE
|
2007-08-20 14:50:02 -07:00
|
|
|
/* 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
|
|
|
|
|
*/
|
2009-07-04 21:43:27 +01:00
|
|
|
static cairo_surface_t *
|
2010-06-24 14:59:18 +03:00
|
|
|
_cairo_boilerplate_xlib_fallback_create_surface (const char *name,
|
|
|
|
|
cairo_content_t content,
|
|
|
|
|
double width,
|
|
|
|
|
double height,
|
|
|
|
|
double max_width,
|
|
|
|
|
double max_height,
|
|
|
|
|
cairo_boilerplate_mode_t mode,
|
|
|
|
|
void **closure)
|
2007-08-20 14:50:02 -07:00
|
|
|
{
|
|
|
|
|
xlib_target_closure_t *xtc;
|
|
|
|
|
Display *dpy;
|
2011-10-26 19:16:17 +02:00
|
|
|
int screen;
|
2007-08-20 14:50:02 -07:00
|
|
|
XSetWindowAttributes attr;
|
2012-02-22 10:41:37 +00:00
|
|
|
cairo_surface_t *surface, *dummy;
|
2007-08-20 14:50:02 -07:00
|
|
|
|
|
|
|
|
/* We're not yet bothering to support perf mode for the
|
|
|
|
|
* xlib-fallback surface. */
|
|
|
|
|
if (mode == CAIRO_BOILERPLATE_MODE_PERF)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
/* We also don't support drawing with destination-alpha in the
|
|
|
|
|
* xlib-fallback surface. */
|
|
|
|
|
if (content == CAIRO_CONTENT_COLOR_ALPHA)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
*closure = xtc = xmalloc (sizeof (xlib_target_closure_t));
|
|
|
|
|
|
2009-06-27 17:53:18 +01:00
|
|
|
width = ceil (width);
|
|
|
|
|
if (width < 1)
|
2007-08-20 14:50:02 -07:00
|
|
|
width = 1;
|
2009-06-27 17:53:18 +01:00
|
|
|
|
|
|
|
|
height = ceil (height);
|
|
|
|
|
if (height < 1)
|
2007-08-20 14:50:02 -07:00
|
|
|
height = 1;
|
|
|
|
|
|
|
|
|
|
xtc->dpy = dpy = XOpenDisplay (NULL);
|
|
|
|
|
if (xtc->dpy == NULL) {
|
2009-01-03 22:30:55 +00:00
|
|
|
CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", XDisplayName(0)));
|
2007-10-05 12:55:13 +01:00
|
|
|
free (xtc);
|
2007-08-20 14:50:02 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This kills performance, but it makes debugging much
|
|
|
|
|
* easier. That's why we have it here only after explicitly not
|
|
|
|
|
* supporting PERF mode.*/
|
|
|
|
|
XSynchronize (dpy, 1);
|
|
|
|
|
|
|
|
|
|
screen = DefaultScreen (dpy);
|
2007-08-24 13:40:26 +01:00
|
|
|
if (! _cairo_boilerplate_xlib_check_screen_size (dpy, screen,
|
2010-06-24 14:59:18 +03:00
|
|
|
width, height)) {
|
2009-01-03 22:30:55 +00:00
|
|
|
CAIRO_BOILERPLATE_DEBUG (("Surface is larger than the Screen.\n"));
|
2007-10-05 12:55:13 +01:00
|
|
|
XCloseDisplay (dpy);
|
|
|
|
|
free (xtc);
|
2007-08-24 13:40:26 +01:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2007-08-20 14:50:02 -07:00
|
|
|
attr.override_redirect = True;
|
|
|
|
|
xtc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
|
2011-10-26 19:16:17 +02:00
|
|
|
0, 0,
|
2007-08-20 14:50:02 -07:00
|
|
|
width, height, 0,
|
|
|
|
|
DefaultDepth (dpy, screen),
|
|
|
|
|
InputOutput,
|
|
|
|
|
DefaultVisual (dpy, screen),
|
|
|
|
|
CWOverrideRedirect, &attr);
|
|
|
|
|
XMapWindow (dpy, xtc->drawable);
|
|
|
|
|
xtc->drawable_is_pixmap = FALSE;
|
|
|
|
|
|
2012-02-22 10:41:37 +00:00
|
|
|
dummy = cairo_xlib_surface_create (dpy, xtc->drawable,
|
|
|
|
|
DefaultVisual (dpy, screen),
|
|
|
|
|
width, height);
|
|
|
|
|
cairo_xlib_device_debug_cap_xrender_version (cairo_surface_get_device (dummy),
|
|
|
|
|
-1, -1);
|
|
|
|
|
|
2007-08-20 14:50:02 -07:00
|
|
|
surface = cairo_xlib_surface_create (dpy, xtc->drawable,
|
|
|
|
|
DefaultVisual (dpy, screen),
|
|
|
|
|
width, height);
|
2012-02-22 10:41:37 +00:00
|
|
|
cairo_surface_destroy (dummy);
|
2007-10-05 12:55:13 +01:00
|
|
|
if (cairo_surface_status (surface))
|
|
|
|
|
_cairo_boilerplate_xlib_cleanup (xtc);
|
2007-08-20 14:50:02 -07:00
|
|
|
|
2011-05-27 15:59:37 +01:00
|
|
|
_cairo_boilerplate_xlib_setup_test_surface(surface);
|
|
|
|
|
|
2007-08-20 14:50:02 -07:00
|
|
|
return surface;
|
|
|
|
|
}
|
2009-07-04 21:43:27 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static const cairo_boilerplate_target_t targets[] = {
|
|
|
|
|
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
|
|
|
|
/* Acceleration architectures may make the results differ by a
|
|
|
|
|
* bit, so we set the error tolerance to 1. */
|
|
|
|
|
{
|
2011-09-16 11:09:22 +01:00
|
|
|
"xlib", "traps", NULL, "xlib-fallback",
|
2009-07-04 21:43:27 +01:00
|
|
|
CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA, 1,
|
2009-08-23 15:25:42 +01:00
|
|
|
"cairo_xlib_surface_create_with_xrender_format",
|
2009-07-04 21:43:27 +01:00
|
|
|
_cairo_boilerplate_xlib_create_surface,
|
2011-06-01 23:03:36 +01:00
|
|
|
_cairo_boilerplate_xlib_create_similar,
|
2009-07-04 21:43:27 +01:00
|
|
|
NULL, NULL,
|
|
|
|
|
_cairo_boilerplate_get_image_surface,
|
|
|
|
|
cairo_surface_write_to_png,
|
|
|
|
|
_cairo_boilerplate_xlib_cleanup,
|
2010-03-27 21:52:16 +00:00
|
|
|
_cairo_boilerplate_xlib_synchronize,
|
2010-06-30 18:27:54 +02:00
|
|
|
NULL,
|
2010-03-27 21:52:16 +00:00
|
|
|
TRUE, FALSE, FALSE
|
2009-07-04 21:43:27 +01:00
|
|
|
},
|
|
|
|
|
{
|
2011-09-16 11:09:22 +01:00
|
|
|
"xlib", "traps", NULL, "xlib-fallback",
|
2009-07-04 21:43:27 +01:00
|
|
|
CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
|
2009-08-23 15:25:42 +01:00
|
|
|
"cairo_xlib_surface_create_with_xrender_format",
|
2009-07-04 21:43:27 +01:00
|
|
|
_cairo_boilerplate_xlib_create_surface,
|
2011-06-01 23:03:36 +01:00
|
|
|
_cairo_boilerplate_xlib_create_similar,
|
2009-07-04 21:43:27 +01:00
|
|
|
NULL, NULL,
|
|
|
|
|
_cairo_boilerplate_get_image_surface,
|
|
|
|
|
cairo_surface_write_to_png,
|
|
|
|
|
_cairo_boilerplate_xlib_cleanup,
|
2010-03-27 21:52:16 +00:00
|
|
|
_cairo_boilerplate_xlib_synchronize,
|
2010-06-30 18:27:54 +02:00
|
|
|
NULL,
|
2010-03-27 21:52:16 +00:00
|
|
|
FALSE, FALSE, FALSE
|
2009-07-04 21:43:27 +01:00
|
|
|
},
|
2010-05-27 17:52:11 +01:00
|
|
|
{
|
2011-09-16 11:09:22 +01:00
|
|
|
"xlib-window", "traps", NULL, NULL,
|
2010-05-27 17:52:11 +01:00
|
|
|
CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
|
|
|
|
|
"cairo_xlib_surface_create",
|
|
|
|
|
_cairo_boilerplate_xlib_window_create_surface,
|
2011-06-01 23:03:36 +01:00
|
|
|
cairo_surface_create_similar,
|
2010-05-27 17:52:11 +01:00
|
|
|
NULL, NULL,
|
|
|
|
|
_cairo_boilerplate_get_image_surface,
|
|
|
|
|
cairo_surface_write_to_png,
|
|
|
|
|
_cairo_boilerplate_xlib_cleanup,
|
|
|
|
|
_cairo_boilerplate_xlib_synchronize,
|
2010-06-30 18:27:54 +02:00
|
|
|
NULL,
|
2010-05-27 17:52:11 +01:00
|
|
|
FALSE, FALSE, FALSE
|
|
|
|
|
},
|
2010-06-24 09:44:07 +03:00
|
|
|
#endif
|
|
|
|
|
#if CAIRO_HAS_XLIB_SURFACE
|
2009-07-04 21:43:27 +01:00
|
|
|
/* This is a fallback surface which uses xlib fallbacks instead of
|
|
|
|
|
* the Render extension. */
|
|
|
|
|
{
|
2012-02-22 10:18:56 +00:00
|
|
|
"xlib-fallback", "image", NULL, NULL,
|
2009-07-04 21:43:27 +01:00
|
|
|
CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
|
2009-08-23 15:25:42 +01:00
|
|
|
"cairo_xlib_surface_create",
|
2009-07-04 21:43:27 +01:00
|
|
|
_cairo_boilerplate_xlib_fallback_create_surface,
|
2011-06-01 23:03:36 +01:00
|
|
|
cairo_surface_create_similar,
|
2009-07-04 21:43:27 +01:00
|
|
|
NULL, NULL,
|
|
|
|
|
_cairo_boilerplate_get_image_surface,
|
|
|
|
|
cairo_surface_write_to_png,
|
|
|
|
|
_cairo_boilerplate_xlib_cleanup,
|
2010-03-27 21:52:16 +00:00
|
|
|
_cairo_boilerplate_xlib_synchronize,
|
2010-06-30 18:27:54 +02:00
|
|
|
NULL,
|
2010-03-27 21:52:16 +00:00
|
|
|
FALSE, FALSE, FALSE
|
2009-07-04 21:43:27 +01:00
|
|
|
},
|
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
CAIRO_BOILERPLATE (xlib, targets)
|