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>
30 #include "cairo-xlib.h"
31 #include "cairo-test.h"
33 #include "cairo-boilerplate-xlib.h"
35 #include "buffer-diff.h"
38 #define OFFSCREEN_OFFSET 50
40 cairo_bool_t result = 0;
42 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
44 #include "cairo-xlib-xrender.h"
46 /* Vladimir Vukicevic reported that surfaces were being created with
47 * mismatching Visuals and XRenderPictFormats.
50 surface_compare_visual_and_format (cairo_surface_t *surface)
54 XRenderPictFormat *format;
56 dpy = cairo_xlib_surface_get_display (surface);
58 visual = cairo_xlib_surface_get_visual (surface);
62 format = cairo_xlib_surface_get_xrender_format (surface);
66 return format == XRenderFindVisualFormat (dpy, visual);
72 surface_compare_visual_and_format (cairo_surface_t *surface)
80 check_similar_visual_and_format (cairo_surface_t *surface)
82 cairo_surface_t *similar;
85 similar = cairo_surface_create_similar (surface,
86 CAIRO_CONTENT_COLOR_ALPHA,
88 if (cairo_surface_status (similar))
91 ret = surface_compare_visual_and_format (similar);
93 cairo_surface_destroy (similar);
100 draw_pattern (cairo_surface_t *surface)
102 cairo_t *cr = cairo_create (surface);
105 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
108 cairo_set_source_rgba (cr, 0, 0.0, 0.0, 0.50); /* half-alpha-black */
110 for (i = 1; i <= 3; i++) {
111 int inset = SIZE / 8 * i;
115 SIZE - 2 * inset, SIZE - 2 * inset);
123 erase_pattern (cairo_surface_t *surface)
125 cairo_t *cr = cairo_create (surface);
127 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
133 static cairo_test_status_t
134 do_test (const cairo_test_context_t *ctx,
136 unsigned char *reference_data,
137 unsigned char *test_data,
138 unsigned char *diff_data,
139 cairo_bool_t use_pixmap,
140 cairo_bool_t set_size,
141 cairo_bool_t offscreen)
143 cairo_surface_t *surface;
144 cairo_surface_t *test_surface;
146 buffer_diff_result_t result;
148 int screen = DefaultScreen (dpy);
150 if (use_pixmap && offscreen)
151 return CAIRO_TEST_SUCCESS;
154 drawable = XCreatePixmap (dpy, DefaultRootWindow (dpy),
155 SIZE, SIZE, DefaultDepth (dpy, screen));
157 XSetWindowAttributes xwa;
160 xwa.override_redirect = True;
163 x = - OFFSCREEN_OFFSET;
164 y = - OFFSCREEN_OFFSET;
170 drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
172 DefaultDepth (dpy, screen), InputOutput,
173 DefaultVisual (dpy, screen),
174 CWOverrideRedirect, &xwa);
175 XMapWindow (dpy, drawable);
178 surface = cairo_xlib_surface_create (dpy,
180 DefaultVisual (dpy, screen),
183 if (! surface_compare_visual_and_format (surface))
184 return CAIRO_TEST_FAILURE;
187 cairo_xlib_surface_set_size (surface, SIZE, SIZE);
189 if (cairo_xlib_surface_get_width (surface) != SIZE ||
190 cairo_xlib_surface_get_height (surface) != SIZE)
191 return CAIRO_TEST_FAILURE;
194 if (! check_similar_visual_and_format (surface))
195 return CAIRO_TEST_FAILURE;
197 draw_pattern (surface);
199 test_surface = cairo_image_surface_create_for_data (test_data,
204 test_cr = cairo_create (test_surface);
205 cairo_set_source_surface (test_cr, surface, 0, 0);
206 cairo_paint (test_cr);
208 cairo_destroy (test_cr);
209 cairo_surface_destroy (test_surface);
211 /* We erase the surface to black in case we get the same
212 * memory back again for the pixmap case.
214 erase_pattern (surface);
215 cairo_surface_destroy (surface);
218 XFreePixmap (dpy, drawable);
220 XDestroyWindow (dpy, drawable);
223 size_t offset = 4 * (SIZE * OFFSCREEN_OFFSET + OFFSCREEN_OFFSET);
225 buffer_diff_noalpha (reference_data + offset,
228 SIZE - OFFSCREEN_OFFSET,
229 SIZE - OFFSCREEN_OFFSET,
233 buffer_diff_noalpha (reference_data,
242 cairo_test_log (ctx, "xlib-surface: %s, %s, %s: %s\n",
243 set_size ? " size" : "no-size",
244 use_pixmap ? "pixmap" : "window",
245 use_pixmap ? " " : (offscreen ? ", offscreen" : ", onscreen"),
246 image_diff_is_failure (&result, 0) ? "FAIL" : "PASS");
248 if (image_diff_is_failure (&result, 0))
249 return CAIRO_TEST_FAILURE;
251 return CAIRO_TEST_SUCCESS;
255 check_visual (Display *dpy)
257 Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy));
259 if ((visual->red_mask == 0xff0000 &&
260 visual->green_mask == 0x00ff00 &&
261 visual->blue_mask == 0x0000ff) ||
262 (visual->red_mask == 0x0000ff &&
263 visual->green_mask == 0x00ff00 &&
264 visual->blue_mask == 0xff0000))
272 xcalloc (const cairo_test_context_t *ctx, size_t a, size_t b)
274 void *ptr = calloc (a, b);
276 cairo_test_log (ctx, "xlib-surface: unable to allocate memory, skipping\n");
282 static cairo_test_status_t
283 preamble (cairo_test_context_t *ctx)
286 unsigned char *reference_data;
287 unsigned char *test_data;
288 unsigned char *diff_data;
289 cairo_surface_t *reference_surface;
290 cairo_bool_t use_pixmap;
291 cairo_bool_t set_size;
292 cairo_bool_t offscreen;
293 cairo_test_status_t status, result = CAIRO_TEST_UNTESTED;
296 if (! cairo_test_is_target_enabled (ctx, "xlib"))
299 dpy = XOpenDisplay (NULL);
301 cairo_test_log (ctx, "xlib-surface: Cannot open display, skipping\n");
305 if (!check_visual (dpy)) {
306 cairo_test_log (ctx, "xlib-surface: default visual is not RGB24 or BGR24, skipping\n");
307 goto CLEANUP_DISPLAY;
310 stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, SIZE);
312 reference_data = xcalloc (ctx, SIZE, stride);
313 test_data = xcalloc (ctx, SIZE, stride);
314 diff_data = xcalloc (ctx, SIZE, stride);
316 reference_surface = cairo_image_surface_create_for_data (reference_data,
321 draw_pattern (reference_surface);
322 cairo_surface_destroy (reference_surface);
324 result = CAIRO_TEST_SUCCESS;
326 for (set_size = 0; set_size <= 1; set_size++)
327 for (use_pixmap = 0; use_pixmap <= 1; use_pixmap++)
328 for (offscreen = 0; offscreen <= 1; offscreen++) {
329 status = do_test (ctx, dpy,
330 reference_data, test_data, diff_data,
331 use_pixmap, set_size, offscreen);
336 free (reference_data);
347 CAIRO_TEST (xlib_surface,
348 "Check creating surfaces for various XWindows",
349 "xlib", /* keywords */
350 NULL, /* requirements */