1
/*
2
 * Copyright © 2009 Chris Wilson
3
 *
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
 * Chris Wilson not be used in advertising or publicity pertaining to
10
 * distribution of the software without specific, written prior
11
 * permission. Chris Wilson makes no representations about the
12
 * suitability of this software for any purpose.  It is provided "as
13
 * is" without express or implied warranty.
14
 *
15
 * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17
 * FITNESS, IN NO EVENT SHALL CHRIS WILSON 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.
22
 *
23
 * Author: Chris Wilson <chris@chris-wilson.co.uk>
24
 */
25

            
26
#include "cairo-test.h"
27
#if CAIRO_HAS_XCB_SURFACE
28
#include <cairo-xcb.h>
29
#endif
30

            
31
#include "surface-source.c"
32

            
33
#if CAIRO_HAS_XCB_SURFACE
34
static cairo_user_data_key_t closure_key;
35

            
36
struct closure {
37
    cairo_device_t *device;
38
    xcb_connection_t *connection;
39
    xcb_pixmap_t pixmap;
40
};
41

            
42
static void
43
4
cleanup (void *data)
44
{
45
4
    struct closure *arg = data;
46

            
47
4
    cairo_device_finish (arg->device);
48
4
    cairo_device_destroy (arg->device);
49

            
50
4
    xcb_free_pixmap (arg->connection, arg->pixmap);
51
4
    xcb_disconnect (arg->connection);
52

            
53
4
    free (arg);
54
4
}
55

            
56
static xcb_render_pictforminfo_t *
57
4
find_depth (xcb_connection_t *connection, int depth, void **formats_out)
58
{
59
    xcb_render_query_pict_formats_reply_t	*formats;
60
    xcb_render_query_pict_formats_cookie_t cookie;
61
    xcb_render_pictforminfo_iterator_t i;
62

            
63
4
    cookie = xcb_render_query_pict_formats (connection);
64
4
    xcb_flush (connection);
65

            
66
4
    formats = xcb_render_query_pict_formats_reply (connection, cookie, 0);
67
4
    if (formats == NULL)
68
	return NULL;
69

            
70
4
    for (i = xcb_render_query_pict_formats_formats_iterator (formats);
71
16
	 i.rem;
72
12
	 xcb_render_pictforminfo_next (&i))
73
    {
74
16
	if (XCB_RENDER_PICT_TYPE_DIRECT != i.data->type)
75
	    continue;
76

            
77
16
	if (depth != i.data->depth)
78
12
	    continue;
79

            
80
4
	*formats_out = formats;
81
4
	return i.data;
82
    }
83

            
84
    free (formats);
85
    return NULL;
86
}
87
#endif
88

            
89
static cairo_surface_t *
90
4
create_source_surface (int size)
91
{
92
#if CAIRO_HAS_XCB_SURFACE
93
    xcb_connection_t *connection;
94
    xcb_render_pictforminfo_t *render_format;
95
    struct closure *data;
96
    cairo_surface_t *surface;
97
    xcb_screen_t *root;
98
    xcb_void_cookie_t cookie;
99
    void *formats;
100

            
101
4
    connection = xcb_connect (NULL, NULL);
102
4
    if (connection == NULL)
103
	return NULL;
104

            
105
4
    data = xmalloc (sizeof (struct closure));
106
4
    data->connection = connection;
107

            
108
4
    render_format = find_depth (connection, 32, &formats);
109
4
    if (render_format == NULL) {
110
	xcb_disconnect (connection);
111
	free (data);
112
	return NULL;
113
    }
114

            
115
4
    root = xcb_setup_roots_iterator (xcb_get_setup (connection)).data;
116

            
117
4
    data->pixmap = xcb_generate_id (connection);
118
4
    cookie = xcb_create_pixmap_checked (connection, 32,
119
					data->pixmap, root->root, size, size);
120
    /* slow, but sure */
121
4
    if (xcb_request_check (connection, cookie) != NULL) {
122
	free (formats);
123
	xcb_disconnect (connection);
124
	free (data);
125
	return NULL;
126
    }
127

            
128
4
    surface = cairo_xcb_surface_create_with_xrender_format (connection,
129
							    root,
130
							    data->pixmap,
131
							    render_format,
132
							    size, size);
133
4
    free (formats);
134

            
135
4
    data->device = cairo_device_reference (cairo_surface_get_device (surface));
136
4
    cairo_surface_set_user_data (surface, &closure_key, data, cleanup);
137

            
138
4
    return surface;
139
#else
140
    return NULL;
141
#endif
142
}
143

            
144
1
CAIRO_TEST (xcb_surface_source,
145
	    "Test using a XCB surface as the source",
146
	    "source", /* keywords */
147
	    NULL, /* requirements */
148
	    SIZE, SIZE,
149
	    preamble, draw)