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
#include "cairo-malloc-private.h"
30

            
31
#include <cairo-xlib.h>
32
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
33
#include <cairo-xlib-xrender.h>
34
#endif
35

            
36
#include <X11/Xutil.h> /* for XDestroyImage */
37

            
38
#if !CAIRO_HAS_XLIB_XRENDER_SURFACE
39
#define PolyModePrecise			    0
40
#endif
41

            
42
static const cairo_user_data_key_t key;
43

            
44
typedef struct _xlib_target_closure {
45
    Display *dpy;
46
    Drawable drawable;
47
    cairo_bool_t drawable_is_pixmap;
48
} xlib_target_closure_t;
49

            
50
static void
51
_cairo_boilerplate_xlib_cleanup (void *closure)
52
{
53
    xlib_target_closure_t *xtc = closure;
54

            
55
    if (xtc->drawable) {
56
	if (xtc->drawable_is_pixmap)
57
	    XFreePixmap (xtc->dpy, xtc->drawable);
58
	else
59
	    XDestroyWindow (xtc->dpy, xtc->drawable);
60
    }
61
    XCloseDisplay (xtc->dpy);
62
    free (xtc);
63
}
64

            
65
static void
66
_cairo_boilerplate_xlib_synchronize (void *closure)
67
{
68
    xlib_target_closure_t *xtc = closure;
69
    XImage *ximage;
70

            
71
    ximage = XGetImage (xtc->dpy, xtc->drawable,
72
			0, 0, 1, 1, AllPlanes, ZPixmap);
73
    if (ximage != NULL)
74
	XDestroyImage (ximage);
75
}
76

            
77
static cairo_bool_t
78
_cairo_boilerplate_xlib_check_screen_size (Display *dpy,
79
					   int	    screen,
80
					   int	    width,
81
					   int	    height)
82
{
83
    Screen *scr = XScreenOfDisplay (dpy, screen);
84
    return width <= WidthOfScreen (scr) && height <= HeightOfScreen (scr);
85
}
86

            
87
static void
88
_cairo_boilerplate_xlib_setup_test_surface (cairo_surface_t *surface)
89
{
90

            
91
    /* For testing purposes, tell the X server to strictly adhere to the
92
     * Render specification.
93
     */
94
    cairo_xlib_device_debug_set_precision(cairo_surface_get_device(surface),
95
					  PolyModePrecise);
96
}
97

            
98

            
99
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
100
/* For the xlib backend we distinguish between TEST and PERF mode in a
101
 * couple of ways.
102
 *
103
 * For TEST, we always test against pixmaps of depth 32 (for
104
 * COLOR_ALPHA) or 24 (for COLOR) and we use XSynchronize to make it
105
 * easier to debug problems.
106
 *
107
 * For PERF, we test against 32-bit pixmaps for COLOR_ALPHA, but for
108
 * COLOR we test against _windows_ at the depth of the default visual.
109
 * For obvious reasons, we don't use XSynchronize.
110
 */
111
static cairo_surface_t *
112
_cairo_boilerplate_xlib_test_create_surface (Display		   *dpy,
113
					     cairo_content_t	    content,
114
					     int		    width,
115
					     int		    height,
116
					     xlib_target_closure_t *xtc)
117
{
118
    XRenderPictFormat *xrender_format;
119
    cairo_surface_t *surface;
120

            
121
    /* This kills performance, but it makes debugging much
122
     * easier. That's why we have it here when in TEST mode, but not
123
     * over in PERF mode. */
124
    XSynchronize (xtc->dpy, 1);
125

            
126
    /* XXX: Currently we don't do any xlib testing when the X server
127
     * doesn't have the Render extension. We could do better here,
128
     * (perhaps by converting the tests from ARGB32 to RGB24). One
129
     * step better would be to always test the non-Render fallbacks
130
     * for each test even if the server does have the Render
131
     * extension. That would probably be through another
132
     * cairo_boilerplate_target which would use an extended version of
133
     * cairo_test_xlib_disable_render.	*/
134
    switch (content) {
135
    case CAIRO_CONTENT_COLOR_ALPHA:
136
	xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
137
	break;
138
    case CAIRO_CONTENT_COLOR:
139
	xrender_format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
140
	break;
141
    case CAIRO_CONTENT_ALPHA:
142
    default:
143
	CAIRO_BOILERPLATE_DEBUG (("Invalid content for xlib test: %d\n", content));
144
	return NULL;
145
    }
146
    if (xrender_format == NULL) {
147
	CAIRO_BOILERPLATE_DEBUG (("X server does not have the Render extension.\n"));
148
	return NULL;
149
    }
150

            
151
    xtc->drawable = XCreatePixmap (dpy, DefaultRootWindow (dpy),
152
				   width, height, xrender_format->depth);
153
    xtc->drawable_is_pixmap = TRUE;
154

            
155
    surface = cairo_xlib_surface_create_with_xrender_format (dpy, xtc->drawable,
156
							  DefaultScreenOfDisplay (dpy),
157
							  xrender_format,
158
							  width, height);
159

            
160
    _cairo_boilerplate_xlib_setup_test_surface(surface);
161

            
162
    return surface;
163
}
164

            
165
static cairo_surface_t *
166
_cairo_boilerplate_xlib_perf_create_surface (Display		   *dpy,
167
					     cairo_content_t	    content,
168
					     int		    width,
169
					     int		    height,
170
					     xlib_target_closure_t *xtc)
171
{
172
    XSetWindowAttributes attr;
173
    XRenderPictFormat *xrender_format;
174
    Visual *visual;
175

            
176
    switch (content) {
177
    case CAIRO_CONTENT_COLOR_ALPHA:
178
	xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
179
	if (xrender_format == NULL) {
180
	    CAIRO_BOILERPLATE_DEBUG (("X server does not have the Render extension.\n"));
181
	    return NULL;
182
	}
183

            
184
	xtc->drawable = XCreatePixmap (dpy, DefaultRootWindow (dpy),
185
				       width, height, xrender_format->depth);
186
	xtc->drawable_is_pixmap = TRUE;
187
	break;
188

            
189
    case CAIRO_CONTENT_COLOR:
190
	if (! _cairo_boilerplate_xlib_check_screen_size (dpy,
191
							 DefaultScreen (dpy),
192
							 width, height)) {
193
	    CAIRO_BOILERPLATE_DEBUG (("Surface is larger than the Screen.\n"));
194
	    return NULL;
195
	}
196

            
197
	visual = DefaultVisual (dpy, DefaultScreen (dpy));
198
	xrender_format = XRenderFindVisualFormat (dpy, visual);
199
	if (xrender_format == NULL) {
200
	    CAIRO_BOILERPLATE_DEBUG (("X server does not have the Render extension.\n"));
201
	    return NULL;
202
	}
203

            
204
	attr.override_redirect = True;
205
	xtc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
206
				       width, height, 0, xrender_format->depth,
207
				       InputOutput, visual, CWOverrideRedirect, &attr);
208
	XMapWindow (dpy, xtc->drawable);
209
	xtc->drawable_is_pixmap = FALSE;
210
	break;
211

            
212
    case CAIRO_CONTENT_ALPHA:
213
    default:
214
	CAIRO_BOILERPLATE_DEBUG (("Invalid content for xlib test: %d\n", content));
215
	return NULL;
216
    }
217

            
218
    return cairo_xlib_surface_create_with_xrender_format (dpy, xtc->drawable,
219
							  DefaultScreenOfDisplay (dpy),
220
							  xrender_format,
221
							  width, height);
222
}
223

            
224
struct similar {
225
	Display *dpy;
226
	Pixmap pixmap;
227
};
228

            
229
static void _destroy_similar (void *closure)
230
{
231
    struct similar *similar = closure;
232

            
233
    XFreePixmap (similar->dpy, similar->pixmap);
234
    free (similar);
235
}
236

            
237
static cairo_surface_t *
238
_cairo_boilerplate_xlib_create_similar (cairo_surface_t		*other,
239
					cairo_content_t		 content,
240
					int			 width,
241
					int			 height)
242
{
243
    XRenderPictFormat *xrender_format;
244
    uint32_t format;
245
    struct similar *similar;
246
    cairo_surface_t *surface;
247

            
248
    similar = _cairo_malloc (sizeof (*similar));
249
    similar->dpy = cairo_xlib_surface_get_display (other);
250

            
251
    switch (content) {
252
    case CAIRO_CONTENT_COLOR:
253
        format = PictStandardRGB24;
254
        break;
255
    case CAIRO_CONTENT_ALPHA:
256
        format = PictStandardA8;
257
        break;
258
    case CAIRO_CONTENT_COLOR_ALPHA:
259
    default:
260
        format = PictStandardARGB32;
261
        break;
262
    }
263

            
264
    xrender_format = XRenderFindStandardFormat (similar->dpy, format);
265
    similar->pixmap = XCreatePixmap (similar->dpy,
266
				     DefaultRootWindow (similar->dpy),
267
				     width, height,
268
				     xrender_format->depth);
269

            
270
    surface =
271
	    cairo_xlib_surface_create_with_xrender_format (similar->dpy,
272
							   similar->pixmap,
273
							   DefaultScreenOfDisplay (similar->dpy),
274
							   xrender_format,
275
							   width, height);
276

            
277
    cairo_surface_set_user_data (surface, &key, similar, _destroy_similar);
278

            
279
    return surface;
280
}
281

            
282
static cairo_surface_t *
283
_cairo_boilerplate_xlib_create_surface (const char		  *name,
284
					cairo_content_t		   content,
285
					double			   width,
286
					double			   height,
287
					double			   max_width,
288
					double			   max_height,
289
					cairo_boilerplate_mode_t   mode,
290
					void			 **closure)
291
{
292
    xlib_target_closure_t *xtc;
293
    Display *dpy;
294
    cairo_surface_t *surface;
295

            
296
    *closure = xtc = xcalloc (1, sizeof (xlib_target_closure_t));
297

            
298
    width = ceil (width);
299
    if (width < 1)
300
	width = 1;
301

            
302
    height = ceil (height);
303
    if (height < 1)
304
	height = 1;
305

            
306
    xtc->dpy = dpy = XOpenDisplay (NULL);
307
    if (xtc->dpy == NULL) {
308
	free (xtc);
309
	CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", XDisplayName(0)));
310
	return NULL;
311
    }
312

            
313
    if (mode == CAIRO_BOILERPLATE_MODE_TEST)
314
	surface = _cairo_boilerplate_xlib_test_create_surface (dpy, content, width, height, xtc);
315
    else /* mode == CAIRO_BOILERPLATE_MODE_PERF */
316
	surface = _cairo_boilerplate_xlib_perf_create_surface (dpy, content, width, height, xtc);
317

            
318
    if (surface == NULL || cairo_surface_status (surface))
319
	_cairo_boilerplate_xlib_cleanup (xtc);
320

            
321
    return surface;
322
}
323

            
324
static cairo_surface_t *
325
_cairo_boilerplate_xlib_render_0_0_create_surface (const char		  *name,
326
						   cairo_content_t		   content,
327
						   double			   width,
328
						   double			   height,
329
						   double			   max_width,
330
						   double			   max_height,
331
						   cairo_boilerplate_mode_t   mode,
332
						   void			 **closure)
333
{
334
    xlib_target_closure_t *xtc;
335
    Display *dpy;
336
    int screen;
337
    Pixmap pixmap;
338
    cairo_surface_t *surface, *dummy;
339

            
340
    *closure = xtc = xcalloc (1, sizeof (xlib_target_closure_t));
341

            
342
    width = ceil (width);
343
    if (width < 1)
344
	width = 1;
345

            
346
    height = ceil (height);
347
    if (height < 1)
348
	height = 1;
349

            
350
    xtc->dpy = dpy = XOpenDisplay (NULL);
351
    if (xtc->dpy == NULL) {
352
	free (xtc);
353
	CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", XDisplayName(0)));
354
	return NULL;
355
    }
356

            
357

            
358
    screen = DefaultScreen (dpy);
359
    pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy), 1, 1,
360
			    DefaultDepth (dpy, screen));
361
    dummy = cairo_xlib_surface_create (dpy, pixmap,
362
				       DefaultVisual (dpy, screen),
363
				       1, 1);
364
    cairo_xlib_device_debug_cap_xrender_version (cairo_surface_get_device (dummy),
365
						 0, 0);
366

            
367
    if (mode == CAIRO_BOILERPLATE_MODE_TEST)
368
	surface = _cairo_boilerplate_xlib_test_create_surface (dpy, content, width, height, xtc);
369
    else /* mode == CAIRO_BOILERPLATE_MODE_PERF */
370
	surface = _cairo_boilerplate_xlib_perf_create_surface (dpy, content, width, height, xtc);
371

            
372
    cairo_surface_destroy (dummy);
373
    XFreePixmap (dpy, pixmap);
374

            
375
    if (surface == NULL || cairo_surface_status (surface))
376
	_cairo_boilerplate_xlib_cleanup (xtc);
377

            
378
    return surface;
379
}
380

            
381
static cairo_surface_t *
382
_cairo_boilerplate_xlib_window_create_surface (const char		 *name,
383
					       cairo_content_t		  content,
384
					       double			  width,
385
					       double			  height,
386
					       double			  max_width,
387
					       double			  max_height,
388
					       cairo_boilerplate_mode_t   mode,
389
					       void			**closure)
390
{
391
    xlib_target_closure_t *xtc;
392
    Display *dpy;
393
    int screen;
394
    XSetWindowAttributes attr;
395
    cairo_surface_t *surface;
396

            
397
    /* We're not yet bothering to support perf mode for the
398
     * xlib-fallback surface. */
399
    if (mode == CAIRO_BOILERPLATE_MODE_PERF)
400
	return NULL;
401

            
402
    /* We also don't support drawing with destination-alpha in the
403
     * xlib-fallback surface. */
404
    if (content == CAIRO_CONTENT_COLOR_ALPHA)
405
	return NULL;
406

            
407
    *closure = xtc = xmalloc (sizeof (xlib_target_closure_t));
408

            
409
    width = ceil (width);
410
    if (width < 1)
411
	width = 1;
412

            
413
    height = ceil (height);
414
    if (height < 1)
415
	height = 1;
416

            
417
    xtc->dpy = dpy = XOpenDisplay (NULL);
418
    if (xtc->dpy == NULL) {
419
	CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", XDisplayName(0)));
420
	free (xtc);
421
	return NULL;
422
    }
423

            
424
    /* This kills performance, but it makes debugging much
425
     * easier. That's why we have it here only after explicitly not
426
     * supporting PERF mode.*/
427
    XSynchronize (dpy, 1);
428

            
429
    screen = DefaultScreen (dpy);
430
    if (! _cairo_boilerplate_xlib_check_screen_size (dpy, screen,
431
						     width, height)) {
432
	CAIRO_BOILERPLATE_DEBUG (("Surface is larger than the Screen.\n"));
433
	XCloseDisplay (dpy);
434
	free (xtc);
435
	return NULL;
436
    }
437

            
438
    attr.override_redirect = True;
439
    xtc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
440
				   0, 0,
441
				   width, height, 0,
442
				   DefaultDepth (dpy, screen),
443
				   InputOutput,
444
				   DefaultVisual (dpy, screen),
445
				   CWOverrideRedirect, &attr);
446
    XMapWindow (dpy, xtc->drawable);
447
    xtc->drawable_is_pixmap = FALSE;
448

            
449
    surface = cairo_xlib_surface_create (dpy, xtc->drawable,
450
					 DefaultVisual (dpy, screen),
451
					 width, height);
452
    if (cairo_surface_status (surface))
453
	_cairo_boilerplate_xlib_cleanup (xtc);
454

            
455
    _cairo_boilerplate_xlib_setup_test_surface(surface);
456

            
457
    return surface;
458
}
459
#endif
460

            
461

            
462
#if CAIRO_HAS_XLIB_SURFACE
463
/* The xlib-fallback target differs from the xlib target in two ways:
464
 *
465
 * 1. It creates its surfaces without relying on the Render extension
466
 *
467
 * 2. It disables use of the Render extension for its surfaces
468
 *
469
 * This provides testing of the non-Render fallback paths we have in
470
 * cairo-xlib-surface.c
471
 */
472
static cairo_surface_t *
473
_cairo_boilerplate_xlib_fallback_create_surface (const char		   *name,
474
						 cairo_content_t	    content,
475
						 double 		    width,
476
						 double 		    height,
477
						 double 		    max_width,
478
						 double 		    max_height,
479
						 cairo_boilerplate_mode_t   mode,
480
						 void			  **closure)
481
{
482
    xlib_target_closure_t *xtc;
483
    Display *dpy;
484
    int screen;
485
    XSetWindowAttributes attr;
486
    cairo_surface_t *surface, *dummy;
487

            
488
    /* We're not yet bothering to support perf mode for the
489
     * xlib-fallback surface. */
490
    if (mode == CAIRO_BOILERPLATE_MODE_PERF)
491
	return NULL;
492

            
493
    /* We also don't support drawing with destination-alpha in the
494
     * xlib-fallback surface. */
495
    if (content == CAIRO_CONTENT_COLOR_ALPHA)
496
	return NULL;
497

            
498
    *closure = xtc = xmalloc (sizeof (xlib_target_closure_t));
499

            
500
    width = ceil (width);
501
    if (width < 1)
502
	width = 1;
503

            
504
    height = ceil (height);
505
    if (height < 1)
506
	height = 1;
507

            
508
    xtc->dpy = dpy = XOpenDisplay (NULL);
509
    if (xtc->dpy == NULL) {
510
	CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", XDisplayName(0)));
511
	free (xtc);
512
	return NULL;
513
    }
514

            
515
    /* This kills performance, but it makes debugging much
516
     * easier. That's why we have it here only after explicitly not
517
     * supporting PERF mode.*/
518
    XSynchronize (dpy, 1);
519

            
520
    screen = DefaultScreen (dpy);
521
    if (! _cairo_boilerplate_xlib_check_screen_size (dpy, screen,
522
						     width, height)) {
523
	CAIRO_BOILERPLATE_DEBUG (("Surface is larger than the Screen.\n"));
524
	XCloseDisplay (dpy);
525
	free (xtc);
526
	return NULL;
527
    }
528

            
529
    attr.override_redirect = True;
530
    xtc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
531
				   0, 0,
532
				   width, height, 0,
533
				   DefaultDepth (dpy, screen),
534
				   InputOutput,
535
				   DefaultVisual (dpy, screen),
536
				   CWOverrideRedirect, &attr);
537
    XMapWindow (dpy, xtc->drawable);
538
    xtc->drawable_is_pixmap = FALSE;
539

            
540
    dummy = cairo_xlib_surface_create (dpy, xtc->drawable,
541
				       DefaultVisual (dpy, screen),
542
				       width, height);
543
    cairo_xlib_device_debug_cap_xrender_version (cairo_surface_get_device (dummy),
544
						 -1, -1);
545

            
546
    surface = cairo_xlib_surface_create (dpy, xtc->drawable,
547
					 DefaultVisual (dpy, screen),
548
					 width, height);
549
    cairo_surface_destroy (dummy);
550
    if (cairo_surface_status (surface))
551
	_cairo_boilerplate_xlib_cleanup (xtc);
552

            
553
    _cairo_boilerplate_xlib_setup_test_surface(surface);
554

            
555
    return surface;
556
}
557
#endif
558

            
559
static const cairo_boilerplate_target_t targets[] = {
560
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
561
    /* Acceleration architectures may make the results differ by a
562
     * bit, so we set the error tolerance to 1. */
563
    {
564
	"xlib", "traps", NULL, "xlib-fallback",
565
	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA, 1,
566
	"cairo_xlib_surface_create_with_xrender_format",
567
	_cairo_boilerplate_xlib_create_surface,
568
	_cairo_boilerplate_xlib_create_similar,
569
	NULL, NULL,
570
	_cairo_boilerplate_get_image_surface,
571
	cairo_surface_write_to_png,
572
	_cairo_boilerplate_xlib_cleanup,
573
	_cairo_boilerplate_xlib_synchronize,
574
        NULL,
575
	TRUE, FALSE, FALSE
576
    },
577
    {
578
	"xlib", "traps", NULL, "xlib-fallback",
579
	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
580
	"cairo_xlib_surface_create_with_xrender_format",
581
	_cairo_boilerplate_xlib_create_surface,
582
	_cairo_boilerplate_xlib_create_similar,
583
	NULL, NULL,
584
	_cairo_boilerplate_get_image_surface,
585
	cairo_surface_write_to_png,
586
	_cairo_boilerplate_xlib_cleanup,
587
	_cairo_boilerplate_xlib_synchronize,
588
        NULL,
589
	FALSE, FALSE, FALSE
590
    },
591
    {
592
	"xlib-window", "traps", NULL, NULL,
593
	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
594
	"cairo_xlib_surface_create",
595
	_cairo_boilerplate_xlib_window_create_surface,
596
	cairo_surface_create_similar,
597
	NULL, NULL,
598
	_cairo_boilerplate_get_image_surface,
599
	cairo_surface_write_to_png,
600
	_cairo_boilerplate_xlib_cleanup,
601
	_cairo_boilerplate_xlib_synchronize,
602
        NULL,
603
	FALSE, FALSE, FALSE
604
    },
605
    {
606
	"xlib-render-0_0", "mask", NULL, NULL,
607
	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
608
	"cairo_xlib_surface_create",
609
	_cairo_boilerplate_xlib_render_0_0_create_surface,
610
	cairo_surface_create_similar,
611
	NULL, NULL,
612
	_cairo_boilerplate_get_image_surface,
613
	cairo_surface_write_to_png,
614
	_cairo_boilerplate_xlib_cleanup,
615
	_cairo_boilerplate_xlib_synchronize,
616
        NULL,
617
	FALSE, FALSE, FALSE
618
    },
619
#endif
620
#if CAIRO_HAS_XLIB_SURFACE
621
    /* This is a fallback surface which uses xlib fallbacks instead of
622
     * the Render extension. */
623
    {
624
	"xlib-fallback", "image", NULL, NULL,
625
	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
626
	"cairo_xlib_surface_create",
627
	_cairo_boilerplate_xlib_fallback_create_surface,
628
	cairo_surface_create_similar,
629
	NULL, NULL,
630
	_cairo_boilerplate_get_image_surface,
631
	cairo_surface_write_to_png,
632
	_cairo_boilerplate_xlib_cleanup,
633
	_cairo_boilerplate_xlib_synchronize,
634
        NULL,
635
	FALSE, FALSE, FALSE
636
    },
637
#endif
638
};
639
1
CAIRO_BOILERPLATE (xlib, targets)