1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /*
3  * Copyright © 2004,2006 Red Hat, Inc.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software
6  * and its documentation for any purpose is hereby granted without
7  * fee, provided that the above copyright notice appear in all copies
8  * and that both that copyright notice and this permission notice
9  * appear in supporting documentation, and that the name of
10  * Red Hat, Inc. not be used in advertising or publicity pertaining to
11  * distribution of the software without specific, written prior
12  * permission. Red Hat, Inc. makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as
14  * is" without express or implied warranty.
15  *
16  * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18  * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
19  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
20  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
22  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Author: Carl D. Worth <cworth@cworth.org>
25  */
26 
27 #include "cairo-boilerplate-private.h"
28 #include "cairo-boilerplate-xlib.h"
29 
30 #include <cairo-xlib.h>
31 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
32 #include <cairo-xlib-xrender.h>
33 #endif
34 
35 #include <X11/Xutil.h> /* for XDestroyImage */
36 
37 #if !CAIRO_HAS_XLIB_XRENDER_SURFACE
38 #define PolyModePrecise			    0
39 #endif
40 
41 static const cairo_user_data_key_t key;
42 
43 typedef struct _xlib_target_closure {
44     Display *dpy;
45     Drawable drawable;
46     cairo_bool_t drawable_is_pixmap;
47 } xlib_target_closure_t;
48 
49 static void
_cairo_boilerplate_xlib_cleanup(void * closure)50 _cairo_boilerplate_xlib_cleanup (void *closure)
51 {
52     xlib_target_closure_t *xtc = closure;
53 
54     if (xtc->drawable) {
55 	if (xtc->drawable_is_pixmap)
56 	    XFreePixmap (xtc->dpy, xtc->drawable);
57 	else
58 	    XDestroyWindow (xtc->dpy, xtc->drawable);
59     }
60     XCloseDisplay (xtc->dpy);
61     free (xtc);
62 }
63 
64 static void
_cairo_boilerplate_xlib_synchronize(void * closure)65 _cairo_boilerplate_xlib_synchronize (void *closure)
66 {
67     xlib_target_closure_t *xtc = closure;
68     XImage *ximage;
69 
70     ximage = XGetImage (xtc->dpy, xtc->drawable,
71 			0, 0, 1, 1, AllPlanes, ZPixmap);
72     if (ximage != NULL)
73 	XDestroyImage (ximage);
74 }
75 
76 static cairo_bool_t
_cairo_boilerplate_xlib_check_screen_size(Display * dpy,int screen,int width,int height)77 _cairo_boilerplate_xlib_check_screen_size (Display *dpy,
78 					   int	    screen,
79 					   int	    width,
80 					   int	    height)
81 {
82     Screen *scr = XScreenOfDisplay (dpy, screen);
83     return width <= WidthOfScreen (scr) && height <= HeightOfScreen (scr);
84 }
85 
86 static void
_cairo_boilerplate_xlib_setup_test_surface(cairo_surface_t * surface)87 _cairo_boilerplate_xlib_setup_test_surface (cairo_surface_t *surface)
88 {
89 
90     /* For testing purposes, tell the X server to strictly adhere to the
91      * Render specification.
92      */
93     cairo_xlib_device_debug_set_precision(cairo_surface_get_device(surface),
94 					  PolyModePrecise);
95 }
96 
97 
98 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
99 /* For the xlib backend we distinguish between TEST and PERF mode in a
100  * couple of ways.
101  *
102  * For TEST, we always test against pixmaps of depth 32 (for
103  * COLOR_ALPHA) or 24 (for COLOR) and we use XSynchronize to make it
104  * easier to debug problems.
105  *
106  * For PERF, we test against 32-bit pixmaps for COLOR_ALPHA, but for
107  * COLOR we test against _windows_ at the depth of the default visual.
108  * For obvious reasons, we don't use XSynchronize.
109  */
110 static cairo_surface_t *
_cairo_boilerplate_xlib_test_create_surface(Display * dpy,cairo_content_t content,int width,int height,xlib_target_closure_t * xtc)111 _cairo_boilerplate_xlib_test_create_surface (Display		   *dpy,
112 					     cairo_content_t	    content,
113 					     int		    width,
114 					     int		    height,
115 					     xlib_target_closure_t *xtc)
116 {
117     XRenderPictFormat *xrender_format;
118     cairo_surface_t *surface;
119 
120     /* This kills performance, but it makes debugging much
121      * easier. That's why we have it here when in TEST mode, but not
122      * over in PERF mode. */
123     XSynchronize (xtc->dpy, 1);
124 
125     /* XXX: Currently we don't do any xlib testing when the X server
126      * doesn't have the Render extension. We could do better here,
127      * (perhaps by converting the tests from ARGB32 to RGB24). One
128      * step better would be to always test the non-Render fallbacks
129      * for each test even if the server does have the Render
130      * extension. That would probably be through another
131      * cairo_boilerplate_target which would use an extended version of
132      * cairo_test_xlib_disable_render.	*/
133     switch (content) {
134     case CAIRO_CONTENT_COLOR_ALPHA:
135 	xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
136 	break;
137     case CAIRO_CONTENT_COLOR:
138 	xrender_format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
139 	break;
140     case CAIRO_CONTENT_ALPHA:
141     default:
142 	CAIRO_BOILERPLATE_DEBUG (("Invalid content for xlib test: %d\n", content));
143 	return NULL;
144     }
145     if (xrender_format == NULL) {
146 	CAIRO_BOILERPLATE_DEBUG (("X server does not have the Render extension.\n"));
147 	return NULL;
148     }
149 
150     xtc->drawable = XCreatePixmap (dpy, DefaultRootWindow (dpy),
151 				   width, height, xrender_format->depth);
152     xtc->drawable_is_pixmap = TRUE;
153 
154     surface = cairo_xlib_surface_create_with_xrender_format (dpy, xtc->drawable,
155 							  DefaultScreenOfDisplay (dpy),
156 							  xrender_format,
157 							  width, height);
158 
159     _cairo_boilerplate_xlib_setup_test_surface(surface);
160 
161     return surface;
162 }
163 
164 static cairo_surface_t *
_cairo_boilerplate_xlib_perf_create_surface(Display * dpy,cairo_content_t content,int width,int height,xlib_target_closure_t * xtc)165 _cairo_boilerplate_xlib_perf_create_surface (Display		   *dpy,
166 					     cairo_content_t	    content,
167 					     int		    width,
168 					     int		    height,
169 					     xlib_target_closure_t *xtc)
170 {
171     XSetWindowAttributes attr;
172     XRenderPictFormat *xrender_format;
173     Visual *visual;
174 
175     switch (content) {
176     case CAIRO_CONTENT_COLOR_ALPHA:
177 	xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
178 	if (xrender_format == NULL) {
179 	    CAIRO_BOILERPLATE_DEBUG (("X server does not have the Render extension.\n"));
180 	    return NULL;
181 	}
182 
183 	xtc->drawable = XCreatePixmap (dpy, DefaultRootWindow (dpy),
184 				       width, height, xrender_format->depth);
185 	xtc->drawable_is_pixmap = TRUE;
186 	break;
187 
188     case CAIRO_CONTENT_COLOR:
189 	if (! _cairo_boilerplate_xlib_check_screen_size (dpy,
190 							 DefaultScreen (dpy),
191 							 width, height)) {
192 	    CAIRO_BOILERPLATE_DEBUG (("Surface is larger than the Screen.\n"));
193 	    return NULL;
194 	}
195 
196 	visual = DefaultVisual (dpy, DefaultScreen (dpy));
197 	xrender_format = XRenderFindVisualFormat (dpy, visual);
198 	if (xrender_format == NULL) {
199 	    CAIRO_BOILERPLATE_DEBUG (("X server does not have the Render extension.\n"));
200 	    return NULL;
201 	}
202 
203 	attr.override_redirect = True;
204 	xtc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
205 				       width, height, 0, xrender_format->depth,
206 				       InputOutput, visual, CWOverrideRedirect, &attr);
207 	XMapWindow (dpy, xtc->drawable);
208 	xtc->drawable_is_pixmap = FALSE;
209 	break;
210 
211     case CAIRO_CONTENT_ALPHA:
212     default:
213 	CAIRO_BOILERPLATE_DEBUG (("Invalid content for xlib test: %d\n", content));
214 	return NULL;
215     }
216 
217     return cairo_xlib_surface_create_with_xrender_format (dpy, xtc->drawable,
218 							  DefaultScreenOfDisplay (dpy),
219 							  xrender_format,
220 							  width, height);
221 }
222 
223 struct similar {
224 	Display *dpy;
225 	Pixmap pixmap;
226 };
227 
_destroy_similar(void * closure)228 static void _destroy_similar (void *closure)
229 {
230     struct similar *similar = closure;
231 
232     XFreePixmap (similar->dpy, similar->pixmap);
233     free (similar);
234 }
235 
236 static cairo_surface_t *
_cairo_boilerplate_xlib_create_similar(cairo_surface_t * other,cairo_content_t content,int width,int height)237 _cairo_boilerplate_xlib_create_similar (cairo_surface_t		*other,
238 					cairo_content_t		 content,
239 					int			 width,
240 					int			 height)
241 {
242     XRenderPictFormat *xrender_format;
243     uint32_t format;
244     struct similar *similar;
245     cairo_surface_t *surface;
246 
247     similar = malloc (sizeof (*similar));
248     similar->dpy = cairo_xlib_surface_get_display (other);
249 
250     switch (content) {
251     case CAIRO_CONTENT_COLOR:
252         format = PictStandardRGB24;
253         break;
254     case CAIRO_CONTENT_ALPHA:
255         format = PictStandardA8;
256         break;
257     case CAIRO_CONTENT_COLOR_ALPHA:
258     default:
259         format = PictStandardARGB32;
260         break;
261     }
262 
263     xrender_format = XRenderFindStandardFormat (similar->dpy, format);
264     similar->pixmap = XCreatePixmap (similar->dpy,
265 				     DefaultRootWindow (similar->dpy),
266 				     width, height,
267 				     xrender_format->depth);
268 
269     surface =
270 	    cairo_xlib_surface_create_with_xrender_format (similar->dpy,
271 							   similar->pixmap,
272 							   DefaultScreenOfDisplay (similar->dpy),
273 							   xrender_format,
274 							   width, height);
275 
276     cairo_surface_set_user_data (surface, &key, similar, _destroy_similar);
277 
278     return surface;
279 }
280 
281 static cairo_surface_t *
_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)282 _cairo_boilerplate_xlib_create_surface (const char		  *name,
283 					cairo_content_t		   content,
284 					double			   width,
285 					double			   height,
286 					double			   max_width,
287 					double			   max_height,
288 					cairo_boilerplate_mode_t   mode,
289 					void			 **closure)
290 {
291     xlib_target_closure_t *xtc;
292     Display *dpy;
293     cairo_surface_t *surface;
294 
295     *closure = xtc = xcalloc (1, sizeof (xlib_target_closure_t));
296 
297     width = ceil (width);
298     if (width < 1)
299 	width = 1;
300 
301     height = ceil (height);
302     if (height < 1)
303 	height = 1;
304 
305     xtc->dpy = dpy = XOpenDisplay (NULL);
306     if (xtc->dpy == NULL) {
307 	free (xtc);
308 	CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", XDisplayName(0)));
309 	return NULL;
310     }
311 
312     if (mode == CAIRO_BOILERPLATE_MODE_TEST)
313 	surface = _cairo_boilerplate_xlib_test_create_surface (dpy, content, width, height, xtc);
314     else /* mode == CAIRO_BOILERPLATE_MODE_PERF */
315 	surface = _cairo_boilerplate_xlib_perf_create_surface (dpy, content, width, height, xtc);
316 
317     if (surface == NULL || cairo_surface_status (surface))
318 	_cairo_boilerplate_xlib_cleanup (xtc);
319 
320     return surface;
321 }
322 
323 static cairo_surface_t *
_cairo_boilerplate_xlib_render_0_0_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)324 _cairo_boilerplate_xlib_render_0_0_create_surface (const char		  *name,
325 						   cairo_content_t		   content,
326 						   double			   width,
327 						   double			   height,
328 						   double			   max_width,
329 						   double			   max_height,
330 						   cairo_boilerplate_mode_t   mode,
331 						   void			 **closure)
332 {
333     xlib_target_closure_t *xtc;
334     Display *dpy;
335     int screen;
336     Pixmap pixmap;
337     cairo_surface_t *surface, *dummy;
338 
339     *closure = xtc = xcalloc (1, sizeof (xlib_target_closure_t));
340 
341     width = ceil (width);
342     if (width < 1)
343 	width = 1;
344 
345     height = ceil (height);
346     if (height < 1)
347 	height = 1;
348 
349     xtc->dpy = dpy = XOpenDisplay (NULL);
350     if (xtc->dpy == NULL) {
351 	free (xtc);
352 	CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", XDisplayName(0)));
353 	return NULL;
354     }
355 
356 
357     screen = DefaultScreen (dpy);
358     pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy), 1, 1,
359 			    DefaultDepth (dpy, screen));
360     dummy = cairo_xlib_surface_create (dpy, pixmap,
361 				       DefaultVisual (dpy, screen),
362 				       1, 1);
363     cairo_xlib_device_debug_cap_xrender_version (cairo_surface_get_device (dummy),
364 						 0, 0);
365 
366     if (mode == CAIRO_BOILERPLATE_MODE_TEST)
367 	surface = _cairo_boilerplate_xlib_test_create_surface (dpy, content, width, height, xtc);
368     else /* mode == CAIRO_BOILERPLATE_MODE_PERF */
369 	surface = _cairo_boilerplate_xlib_perf_create_surface (dpy, content, width, height, xtc);
370 
371     cairo_surface_destroy (dummy);
372     XFreePixmap (dpy, pixmap);
373 
374     if (surface == NULL || cairo_surface_status (surface))
375 	_cairo_boilerplate_xlib_cleanup (xtc);
376 
377     return surface;
378 }
379 
380 static cairo_surface_t *
_cairo_boilerplate_xlib_window_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)381 _cairo_boilerplate_xlib_window_create_surface (const char		 *name,
382 					       cairo_content_t		  content,
383 					       double			  width,
384 					       double			  height,
385 					       double			  max_width,
386 					       double			  max_height,
387 					       cairo_boilerplate_mode_t   mode,
388 					       void			**closure)
389 {
390     xlib_target_closure_t *xtc;
391     Display *dpy;
392     int screen;
393     XSetWindowAttributes attr;
394     cairo_surface_t *surface;
395 
396     /* We're not yet bothering to support perf mode for the
397      * xlib-fallback surface. */
398     if (mode == CAIRO_BOILERPLATE_MODE_PERF)
399 	return NULL;
400 
401     /* We also don't support drawing with destination-alpha in the
402      * xlib-fallback surface. */
403     if (content == CAIRO_CONTENT_COLOR_ALPHA)
404 	return NULL;
405 
406     *closure = xtc = xmalloc (sizeof (xlib_target_closure_t));
407 
408     width = ceil (width);
409     if (width < 1)
410 	width = 1;
411 
412     height = ceil (height);
413     if (height < 1)
414 	height = 1;
415 
416     xtc->dpy = dpy = XOpenDisplay (NULL);
417     if (xtc->dpy == NULL) {
418 	CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", XDisplayName(0)));
419 	free (xtc);
420 	return NULL;
421     }
422 
423     /* This kills performance, but it makes debugging much
424      * easier. That's why we have it here only after explicitly not
425      * supporting PERF mode.*/
426     XSynchronize (dpy, 1);
427 
428     screen = DefaultScreen (dpy);
429     if (! _cairo_boilerplate_xlib_check_screen_size (dpy, screen,
430 						     width, height)) {
431 	CAIRO_BOILERPLATE_DEBUG (("Surface is larger than the Screen.\n"));
432 	XCloseDisplay (dpy);
433 	free (xtc);
434 	return NULL;
435     }
436 
437     attr.override_redirect = True;
438     xtc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
439 				   0, 0,
440 				   width, height, 0,
441 				   DefaultDepth (dpy, screen),
442 				   InputOutput,
443 				   DefaultVisual (dpy, screen),
444 				   CWOverrideRedirect, &attr);
445     XMapWindow (dpy, xtc->drawable);
446     xtc->drawable_is_pixmap = FALSE;
447 
448     surface = cairo_xlib_surface_create (dpy, xtc->drawable,
449 					 DefaultVisual (dpy, screen),
450 					 width, height);
451     if (cairo_surface_status (surface))
452 	_cairo_boilerplate_xlib_cleanup (xtc);
453 
454     _cairo_boilerplate_xlib_setup_test_surface(surface);
455 
456     return surface;
457 }
458 #endif
459 
460 
461 #if CAIRO_HAS_XLIB_SURFACE
462 /* The xlib-fallback target differs from the xlib target in two ways:
463  *
464  * 1. It creates its surfaces without relying on the Render extension
465  *
466  * 2. It disables use of the Render extension for its surfaces
467  *
468  * This provides testing of the non-Render fallback paths we have in
469  * cairo-xlib-surface.c
470  */
471 static cairo_surface_t *
_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)472 _cairo_boilerplate_xlib_fallback_create_surface (const char		   *name,
473 						 cairo_content_t	    content,
474 						 double 		    width,
475 						 double 		    height,
476 						 double 		    max_width,
477 						 double 		    max_height,
478 						 cairo_boilerplate_mode_t   mode,
479 						 void			  **closure)
480 {
481     xlib_target_closure_t *xtc;
482     Display *dpy;
483     int screen;
484     XSetWindowAttributes attr;
485     cairo_surface_t *surface, *dummy;
486 
487     /* We're not yet bothering to support perf mode for the
488      * xlib-fallback surface. */
489     if (mode == CAIRO_BOILERPLATE_MODE_PERF)
490 	return NULL;
491 
492     /* We also don't support drawing with destination-alpha in the
493      * xlib-fallback surface. */
494     if (content == CAIRO_CONTENT_COLOR_ALPHA)
495 	return NULL;
496 
497     *closure = xtc = xmalloc (sizeof (xlib_target_closure_t));
498 
499     width = ceil (width);
500     if (width < 1)
501 	width = 1;
502 
503     height = ceil (height);
504     if (height < 1)
505 	height = 1;
506 
507     xtc->dpy = dpy = XOpenDisplay (NULL);
508     if (xtc->dpy == NULL) {
509 	CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", XDisplayName(0)));
510 	free (xtc);
511 	return NULL;
512     }
513 
514     /* This kills performance, but it makes debugging much
515      * easier. That's why we have it here only after explicitly not
516      * supporting PERF mode.*/
517     XSynchronize (dpy, 1);
518 
519     screen = DefaultScreen (dpy);
520     if (! _cairo_boilerplate_xlib_check_screen_size (dpy, screen,
521 						     width, height)) {
522 	CAIRO_BOILERPLATE_DEBUG (("Surface is larger than the Screen.\n"));
523 	XCloseDisplay (dpy);
524 	free (xtc);
525 	return NULL;
526     }
527 
528     attr.override_redirect = True;
529     xtc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
530 				   0, 0,
531 				   width, height, 0,
532 				   DefaultDepth (dpy, screen),
533 				   InputOutput,
534 				   DefaultVisual (dpy, screen),
535 				   CWOverrideRedirect, &attr);
536     XMapWindow (dpy, xtc->drawable);
537     xtc->drawable_is_pixmap = FALSE;
538 
539     dummy = cairo_xlib_surface_create (dpy, xtc->drawable,
540 				       DefaultVisual (dpy, screen),
541 				       width, height);
542     cairo_xlib_device_debug_cap_xrender_version (cairo_surface_get_device (dummy),
543 						 -1, -1);
544 
545     surface = cairo_xlib_surface_create (dpy, xtc->drawable,
546 					 DefaultVisual (dpy, screen),
547 					 width, height);
548     cairo_surface_destroy (dummy);
549     if (cairo_surface_status (surface))
550 	_cairo_boilerplate_xlib_cleanup (xtc);
551 
552     _cairo_boilerplate_xlib_setup_test_surface(surface);
553 
554     return surface;
555 }
556 #endif
557 
558 static const cairo_boilerplate_target_t targets[] = {
559 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
560     /* Acceleration architectures may make the results differ by a
561      * bit, so we set the error tolerance to 1. */
562     {
563 	"xlib", "traps", NULL, "xlib-fallback",
564 	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA, 1,
565 	"cairo_xlib_surface_create_with_xrender_format",
566 	_cairo_boilerplate_xlib_create_surface,
567 	_cairo_boilerplate_xlib_create_similar,
568 	NULL, NULL,
569 	_cairo_boilerplate_get_image_surface,
570 	cairo_surface_write_to_png,
571 	_cairo_boilerplate_xlib_cleanup,
572 	_cairo_boilerplate_xlib_synchronize,
573         NULL,
574 	TRUE, FALSE, FALSE
575     },
576     {
577 	"xlib", "traps", NULL, "xlib-fallback",
578 	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
579 	"cairo_xlib_surface_create_with_xrender_format",
580 	_cairo_boilerplate_xlib_create_surface,
581 	_cairo_boilerplate_xlib_create_similar,
582 	NULL, NULL,
583 	_cairo_boilerplate_get_image_surface,
584 	cairo_surface_write_to_png,
585 	_cairo_boilerplate_xlib_cleanup,
586 	_cairo_boilerplate_xlib_synchronize,
587         NULL,
588 	FALSE, FALSE, FALSE
589     },
590     {
591 	"xlib-window", "traps", NULL, NULL,
592 	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
593 	"cairo_xlib_surface_create",
594 	_cairo_boilerplate_xlib_window_create_surface,
595 	cairo_surface_create_similar,
596 	NULL, NULL,
597 	_cairo_boilerplate_get_image_surface,
598 	cairo_surface_write_to_png,
599 	_cairo_boilerplate_xlib_cleanup,
600 	_cairo_boilerplate_xlib_synchronize,
601         NULL,
602 	FALSE, FALSE, FALSE
603     },
604     {
605 	"xlib-render-0_0", "mask", NULL, NULL,
606 	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
607 	"cairo_xlib_surface_create",
608 	_cairo_boilerplate_xlib_render_0_0_create_surface,
609 	cairo_surface_create_similar,
610 	NULL, NULL,
611 	_cairo_boilerplate_get_image_surface,
612 	cairo_surface_write_to_png,
613 	_cairo_boilerplate_xlib_cleanup,
614 	_cairo_boilerplate_xlib_synchronize,
615         NULL,
616 	FALSE, FALSE, FALSE
617     },
618 #endif
619 #if CAIRO_HAS_XLIB_SURFACE
620     /* This is a fallback surface which uses xlib fallbacks instead of
621      * the Render extension. */
622     {
623 	"xlib-fallback", "image", NULL, NULL,
624 	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
625 	"cairo_xlib_surface_create",
626 	_cairo_boilerplate_xlib_fallback_create_surface,
627 	cairo_surface_create_similar,
628 	NULL, NULL,
629 	_cairo_boilerplate_get_image_surface,
630 	cairo_surface_write_to_png,
631 	_cairo_boilerplate_xlib_cleanup,
632 	_cairo_boilerplate_xlib_synchronize,
633         NULL,
634 	FALSE, FALSE, FALSE
635     },
636 #endif
637 };
638 CAIRO_BOILERPLATE (xlib, targets)
639