2 * Copyright © 2005 Red Hat, Inc.
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Red Hat, Inc. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior
11 * permission. Red Hat, Inc. makes no representations about the
12 * suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
15 * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
18 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
21 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: Carl D. Worth <cworth@cworth.org>
26 #include "cairo-test.h"
32 #include "cairo-xlib.h"
34 #include "cairo-boilerplate-xlib.h"
36 #include "buffer-diff.h"
39 #define OFFSCREEN_OFFSET 50
41 cairo_bool_t result = 0;
43 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
45 #include "cairo-xlib-xrender.h"
47 /* Vladimir Vukicevic reported that surfaces were being created with
48 * mismatching Visuals and XRenderPictFormats.
51 surface_compare_visual_and_format (cairo_surface_t *surface)
55 XRenderPictFormat *format;
57 dpy = cairo_xlib_surface_get_display (surface);
59 visual = cairo_xlib_surface_get_visual (surface);
63 format = cairo_xlib_surface_get_xrender_format (surface);
67 return format == XRenderFindVisualFormat (dpy, visual);
73 surface_compare_visual_and_format (cairo_surface_t *surface)
81 check_similar_visual_and_format (cairo_surface_t *surface)
83 cairo_surface_t *similar;
86 similar = cairo_surface_create_similar (surface,
87 CAIRO_CONTENT_COLOR_ALPHA,
89 if (cairo_surface_status (similar))
92 ret = surface_compare_visual_and_format (similar);
94 cairo_surface_destroy (similar);
101 draw_pattern (cairo_surface_t *surface)
103 cairo_t *cr = cairo_create (surface);
106 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
109 cairo_set_source_rgba (cr, 0, 0.0, 0.0, 0.50); /* half-alpha-black */
111 for (i = 1; i <= 3; i++) {
112 int inset = SIZE / 8 * i;
116 SIZE - 2 * inset, SIZE - 2 * inset);
124 erase_pattern (cairo_surface_t *surface)
126 cairo_t *cr = cairo_create (surface);
128 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
134 static cairo_test_status_t
135 do_test (const cairo_test_context_t *ctx,
137 unsigned char *reference_data,
138 unsigned char *test_data,
139 unsigned char *diff_data,
140 cairo_bool_t use_pixmap,
141 cairo_bool_t set_size,
142 cairo_bool_t offscreen)
144 cairo_surface_t *surface;
145 cairo_surface_t *test_surface;
147 buffer_diff_result_t result;
149 int screen = DefaultScreen (dpy);
151 if (use_pixmap && offscreen)
152 return CAIRO_TEST_SUCCESS;
155 drawable = XCreatePixmap (dpy, DefaultRootWindow (dpy),
156 SIZE, SIZE, DefaultDepth (dpy, screen));
158 XSetWindowAttributes xwa;
161 xwa.override_redirect = True;
164 x = - OFFSCREEN_OFFSET;
165 y = - OFFSCREEN_OFFSET;
171 drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
173 DefaultDepth (dpy, screen), InputOutput,
174 DefaultVisual (dpy, screen),
175 CWOverrideRedirect, &xwa);
176 XMapWindow (dpy, drawable);
179 surface = cairo_xlib_surface_create (dpy,
181 DefaultVisual (dpy, screen),
184 if (! surface_compare_visual_and_format (surface))
185 return CAIRO_TEST_FAILURE;
188 cairo_xlib_surface_set_size (surface, SIZE, SIZE);
190 if (cairo_xlib_surface_get_width (surface) != SIZE ||
191 cairo_xlib_surface_get_height (surface) != SIZE)
192 return CAIRO_TEST_FAILURE;
195 if (! check_similar_visual_and_format (surface))
196 return CAIRO_TEST_FAILURE;
198 draw_pattern (surface);
200 test_surface = cairo_image_surface_create_for_data (test_data,
205 test_cr = cairo_create (test_surface);
206 cairo_set_source_surface (test_cr, surface, 0, 0);
207 cairo_paint (test_cr);
209 cairo_destroy (test_cr);
210 cairo_surface_destroy (test_surface);
212 /* We erase the surface to black in case we get the same
213 * memory back again for the pixmap case.
215 erase_pattern (surface);
216 cairo_surface_destroy (surface);
219 XFreePixmap (dpy, drawable);
221 XDestroyWindow (dpy, drawable);
224 size_t offset = 4 * (SIZE * OFFSCREEN_OFFSET + OFFSCREEN_OFFSET);
226 buffer_diff_noalpha (reference_data + offset,
229 SIZE - OFFSCREEN_OFFSET,
230 SIZE - OFFSCREEN_OFFSET,
234 buffer_diff_noalpha (reference_data,
243 cairo_test_log (ctx, "xlib-surface: %s, %s, %s: %s\n",
244 set_size ? " size" : "no-size",
245 use_pixmap ? "pixmap" : "window",
246 use_pixmap ? " " : (offscreen ? ", offscreen" : ", onscreen"),
247 image_diff_is_failure (&result, 0) ? "FAIL" : "PASS");
249 if (image_diff_is_failure (&result, 0))
250 return CAIRO_TEST_FAILURE;
252 return CAIRO_TEST_SUCCESS;
256 check_visual (Display *dpy)
258 Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy));
260 if ((visual->red_mask == 0xff0000 &&
261 visual->green_mask == 0x00ff00 &&
262 visual->blue_mask == 0x0000ff) ||
263 (visual->red_mask == 0x0000ff &&
264 visual->green_mask == 0x00ff00 &&
265 visual->blue_mask == 0xff0000))
273 xcalloc (const cairo_test_context_t *ctx, size_t a, size_t b)
275 void *ptr = calloc (a, b);
277 cairo_test_log (ctx, "xlib-surface: unable to allocate memory, skipping\n");
283 static cairo_test_status_t
284 preamble (cairo_test_context_t *ctx)
287 unsigned char *reference_data;
288 unsigned char *test_data;
289 unsigned char *diff_data;
290 cairo_surface_t *reference_surface;
291 cairo_bool_t use_pixmap;
292 cairo_bool_t set_size;
293 cairo_bool_t offscreen;
294 cairo_test_status_t status, result = CAIRO_TEST_UNTESTED;
297 if (! cairo_test_is_target_enabled (ctx, "xlib"))
300 dpy = XOpenDisplay (NULL);
302 cairo_test_log (ctx, "xlib-surface: Cannot open display, skipping\n");
306 if (!check_visual (dpy)) {
307 cairo_test_log (ctx, "xlib-surface: default visual is not RGB24 or BGR24, skipping\n");
308 goto CLEANUP_DISPLAY;
311 stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, SIZE);
313 reference_data = xcalloc (ctx, SIZE, stride);
314 test_data = xcalloc (ctx, SIZE, stride);
315 diff_data = xcalloc (ctx, SIZE, stride);
317 reference_surface = cairo_image_surface_create_for_data (reference_data,
322 draw_pattern (reference_surface);
323 cairo_surface_destroy (reference_surface);
325 result = CAIRO_TEST_SUCCESS;
327 for (set_size = 0; set_size <= 1; set_size++)
328 for (use_pixmap = 0; use_pixmap <= 1; use_pixmap++)
329 for (offscreen = 0; offscreen <= 1; offscreen++) {
330 status = do_test (ctx, dpy,
331 reference_data, test_data, diff_data,
332 use_pixmap, set_size, offscreen);
337 free (reference_data);
348 CAIRO_TEST (xlib_surface,
349 "Check creating surfaces for various XWindows",
350 "xlib", /* keywords */
351 NULL, /* requirements */