Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/* cairo - a vector graphics library with display and print output
2
 *
3
 * Copyright © 2009 Intel Corporation
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it either under the terms of the GNU Lesser General Public
7
 * License version 2.1 as published by the Free Software Foundation
8
 * (the "LGPL") or, at your option, under the terms of the Mozilla
9
 * Public License Version 1.1 (the "MPL"). If you do not alter this
10
 * notice, a recipient may use your version of this file under either
11
 * the MPL or the LGPL.
12
 *
13
 * You should have received a copy of the LGPL along with this library
14
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16
 * You should have received a copy of the MPL along with this library
17
 * in the file COPYING-MPL-1.1
18
 *
19
 * The contents of this file are subject to the Mozilla Public License
20
 * Version 1.1 (the "License"); you may not use this file except in
21
 * compliance with the License. You may obtain a copy of the License at
22
 * http://www.mozilla.org/MPL/
23
 *
24
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26
 * the specific language governing rights and limitations.
27
 *
28
 * Contributor(s):
29
 *	Chris Wilson 
30
 */
31
 
32
#include "cairoint.h"
33
 
34
#include "cairo-xcb-private.h"
35
 
36
#include 
37
 
38
xcb_pixmap_t
39
_cairo_xcb_connection_create_pixmap (cairo_xcb_connection_t *connection,
40
				     uint8_t depth,
41
				     xcb_drawable_t drawable,
42
				     uint16_t width,
43
				     uint16_t height)
44
{
45
    xcb_pixmap_t pixmap = _cairo_xcb_connection_get_xid (connection);
46
 
47
    assert (width > 0);
48
    assert (height > 0);
49
    xcb_create_pixmap (connection->xcb_connection,
50
		       depth, pixmap, drawable,
51
		       width, height);
52
    return pixmap;
53
}
54
 
55
void
56
_cairo_xcb_connection_free_pixmap (cairo_xcb_connection_t *connection,
57
				   xcb_pixmap_t pixmap)
58
{
59
    xcb_free_pixmap (connection->xcb_connection, pixmap);
60
    _cairo_xcb_connection_put_xid (connection, pixmap);
61
}
62
 
63
xcb_gcontext_t
64
_cairo_xcb_connection_create_gc (cairo_xcb_connection_t *connection,
65
				 xcb_drawable_t drawable,
66
				 uint32_t value_mask,
67
				 uint32_t *values)
68
{
69
    xcb_gcontext_t gc = _cairo_xcb_connection_get_xid (connection);
70
    xcb_create_gc (connection->xcb_connection, gc, drawable,
71
		   value_mask, values);
72
    return gc;
73
}
74
 
75
void
76
_cairo_xcb_connection_free_gc (cairo_xcb_connection_t *connection,
77
			       xcb_gcontext_t gc)
78
{
79
    xcb_free_gc (connection->xcb_connection, gc);
80
    _cairo_xcb_connection_put_xid (connection, gc);
81
}
82
 
83
void
84
_cairo_xcb_connection_change_gc (cairo_xcb_connection_t *connection,
85
				 xcb_gcontext_t gc,
86
				 uint32_t value_mask,
87
				 uint32_t *values)
88
{
89
    xcb_change_gc (connection->xcb_connection, gc,
90
		   value_mask, values);
91
}
92
 
93
void
94
_cairo_xcb_connection_copy_area (cairo_xcb_connection_t *connection,
95
				 xcb_drawable_t src,
96
				 xcb_drawable_t dst,
97
				 xcb_gcontext_t gc,
98
				 int16_t src_x,
99
				 int16_t src_y,
100
				 int16_t dst_x,
101
				 int16_t dst_y,
102
				 uint16_t width,
103
				 uint16_t height)
104
{
105
    xcb_copy_area (connection->xcb_connection, src, dst, gc,
106
		   src_x, src_y, dst_x, dst_y, width, height);
107
}
108
 
109
void
110
_cairo_xcb_connection_poly_fill_rectangle (cairo_xcb_connection_t *connection,
111
					   xcb_drawable_t dst,
112
					   xcb_gcontext_t gc,
113
					   uint32_t num_rectangles,
114
					   xcb_rectangle_t *rectangles)
115
{
116
    xcb_poly_fill_rectangle (connection->xcb_connection, dst, gc,
117
			     num_rectangles, rectangles);
118
}
119
 
120
void
121
_cairo_xcb_connection_put_image (cairo_xcb_connection_t *connection,
122
				 xcb_drawable_t dst,
123
				 xcb_gcontext_t gc,
124
				 uint16_t width,
125
				 uint16_t height,
126
				 int16_t dst_x,
127
				 int16_t dst_y,
128
				 uint8_t depth,
129
				 uint32_t stride,
130
				 void *data)
131
{
132
    const uint32_t req_size = 18;
133
    uint32_t length = height * stride;
134
    uint32_t len = (req_size + length) >> 2;
135
 
136
    if (len < connection->maximum_request_length) {
137
	xcb_put_image (connection->xcb_connection, XCB_IMAGE_FORMAT_Z_PIXMAP,
138
		       dst, gc, width, height, dst_x, dst_y, 0, depth,
139
		       length, data);
140
    } else {
141
	int rows = (connection->maximum_request_length - req_size - 4) / stride;
142
	if (rows > 0) {
143
	    do {
144
		if (rows > height)
145
		    rows = height;
146
 
147
		length = rows * stride;
148
 
149
		xcb_put_image (connection->xcb_connection, XCB_IMAGE_FORMAT_Z_PIXMAP,
150
			       dst, gc, width, rows, dst_x, dst_y, 0, depth, length, data);
151
 
152
		height -= rows;
153
		dst_y += rows;
154
		data = (char *) data + length;
155
	    } while (height);
156
	} else {
157
	    ASSERT_NOT_REACHED;
158
	}
159
    }
160
}
161
 
162
static void
163
_cairo_xcb_connection_do_put_subimage (cairo_xcb_connection_t *connection,
164
				       xcb_drawable_t dst,
165
				       xcb_gcontext_t gc,
166
				       int16_t src_x,
167
				       int16_t src_y,
168
				       uint16_t width,
169
				       uint16_t height,
170
				       uint16_t cpp,
171
				       int stride,
172
				       int16_t dst_x,
173
				       int16_t dst_y,
174
				       uint8_t depth,
175
				       void *_data)
176
{
177
    xcb_protocol_request_t xcb_req = {
178
 
179
 
180
	XCB_PUT_IMAGE /* opcode */,
181
	1 /* isvoid (doesn't cause a reply) */
182
    };
183
    xcb_put_image_request_t req;
184
    struct iovec vec_stack[CAIRO_STACK_ARRAY_LENGTH (struct iovec)];
185
    struct iovec *vec = vec_stack;
186
    uint32_t len = 0;
187
    uint8_t *data = _data;
188
    int n = 3;
189
    /* Two extra entries are needed for xcb, two for us */
190
    int entries_needed = height + 2 + 2;
191
 
192
    req.format = XCB_IMAGE_FORMAT_Z_PIXMAP;
193
    req.drawable = dst;
194
    req.gc = gc;
195
    req.width = width;
196
    req.height = height;
197
    req.dst_x = dst_x;
198
    req.dst_y = dst_y;
199
    req.left_pad = 0;
200
    req.depth = depth;
201
    req.pad0[0] = 0;
202
    req.pad0[1] = 0;
203
 
204
    if (entries_needed > ARRAY_LENGTH (vec_stack)) {
205
	vec = _cairo_malloc_ab (entries_needed, sizeof (struct iovec));
206
	if (unlikely (vec == NULL)) {
207
	    /* XXX loop over ARRAY_LENGTH (vec_stack) */
208
	    return;
209
	}
210
    }
211
 
212
    data += src_y * stride + src_x * cpp;
213
    /* vec[1] will be used in XCB if it has to use BigRequests or insert a sync,
214
     * vec[0] is used if the internal queue needs to be flushed. */
215
    vec[2].iov_base = (char *) &req;
216
    vec[2].iov_len = sizeof (req);
217
 
218
    /* Now comes the actual data */
219
    while (height--) {
220
	vec[n].iov_base = data;
221
	vec[n].iov_len = cpp * width;
222
	len += cpp * width;
223
	data += stride;
224
	n++;
225
    }
226
 
227
    /* And again some padding */
228
    vec[n].iov_base = 0;
229
    vec[n].iov_len = -len & 3;
230
    n++;
231
 
232
    /* For efficiency reasons, this functions writes the request "directly" to
233
     * the xcb connection to avoid having to copy the data around. */
234
    assert (n == entries_needed);
235
    xcb_req.count = n - 2;
236
    xcb_send_request (connection->xcb_connection, 0, &vec[2], &xcb_req);
237
 
238
    if (vec != vec_stack)
239
	free (vec);
240
}
241
 
242
void
243
_cairo_xcb_connection_put_subimage (cairo_xcb_connection_t *connection,
244
				    xcb_drawable_t dst,
245
				    xcb_gcontext_t gc,
246
				    int16_t src_x,
247
				    int16_t src_y,
248
				    uint16_t width,
249
				    uint16_t height,
250
				    uint16_t cpp,
251
				    int stride,
252
				    int16_t dst_x,
253
				    int16_t dst_y,
254
				    uint8_t depth,
255
				    void *_data)
256
{
257
    const uint32_t req_size = sizeof(xcb_put_image_request_t);
258
    uint32_t length = height * cpp * width;
259
    uint32_t len = (req_size + length) >> 2;
260
 
261
    if (len < connection->maximum_request_length) {
262
	_cairo_xcb_connection_do_put_subimage (connection, dst, gc, src_x, src_y,
263
			width, height, cpp, stride, dst_x, dst_y, depth, _data);
264
    } else {
265
	int rows = (connection->maximum_request_length - req_size - 4) / (cpp * width);
266
	if (rows > 0) {
267
	    do {
268
		if (rows > height)
269
		    rows = height;
270
 
271
		length = rows * cpp * width;
272
 
273
		_cairo_xcb_connection_do_put_subimage (connection, dst, gc, src_x, src_y,
274
			width, rows, cpp, stride, dst_x, dst_y, depth, _data);
275
 
276
		height -= rows;
277
		dst_y += rows;
278
		_data = (char *) _data + stride * rows;
279
	    } while (height);
280
	} else {
281
	    ASSERT_NOT_REACHED;
282
	}
283
    }
284
}
285
 
286
cairo_status_t
287
_cairo_xcb_connection_get_image (cairo_xcb_connection_t *connection,
288
				 xcb_drawable_t src,
289
				 int16_t src_x,
290
				 int16_t src_y,
291
				 uint16_t width,
292
				 uint16_t height,
293
				 xcb_get_image_reply_t **reply)
294
{
295
    xcb_generic_error_t *error;
296
 
297
    *reply = xcb_get_image_reply (connection->xcb_connection,
298
				  xcb_get_image (connection->xcb_connection,
299
						 XCB_IMAGE_FORMAT_Z_PIXMAP,
300
						 src,
301
						 src_x, src_y,
302
						 width, height,
303
						 (uint32_t) -1),
304
 
305
				  &error);
306
    if (error) {
307
	free (error);
308
 
309
	free (*reply);
310
	*reply = NULL;
311
    }
312
 
313
    return CAIRO_STATUS_SUCCESS;
314
}