1 /* cairo - a vector graphics library with display and print output
2 *
3 * Copyright © 2002 University of Southern California
4 * Copyright © 2009 Intel Corporation
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
13 *
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
19 *
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
24 *
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
28 *
29 * The Original Code is the cairo graphics library.
30 *
31 * The Initial Developer of the Original Code is University of Southern
32 * California.
33 *
34 * Contributor(s):
35 * Carl D. Worth <cworth@cworth.org>
36 * Chris Wilson <chris@chris-wilson.co.uk>
37 */
38
39 #include "cairoint.h"
40
41 #include "cairo-xlib.h"
42 #include "cairo-xcb.h"
43
44 #include "cairo-xcb-private.h"
45 #include "cairo-xlib-xrender-private.h"
46
47 #include <X11/Xlib-xcb.h>
48
49 static cairo_surface_t *
50 _cairo_xlib_xcb_surface_create (void *dpy,
51 void *scr,
52 void *visual,
53 void *format,
54 cairo_surface_t *xcb);
55
56 static cairo_surface_t *
_cairo_xlib_xcb_surface_create_similar(void * abstract_other,cairo_content_t content,int width,int height)57 _cairo_xlib_xcb_surface_create_similar (void *abstract_other,
58 cairo_content_t content,
59 int width,
60 int height)
61 {
62 cairo_xlib_xcb_surface_t *other = abstract_other;
63 cairo_surface_t *xcb;
64
65 xcb = other->xcb->base.backend->create_similar (other->xcb, content, width, height);
66 if (unlikely (xcb == NULL || xcb->status))
67 return xcb;
68
69 return _cairo_xlib_xcb_surface_create (other->display, other->screen, NULL, NULL, xcb);
70 }
71
72 static cairo_status_t
_cairo_xlib_xcb_surface_finish(void * abstract_surface)73 _cairo_xlib_xcb_surface_finish (void *abstract_surface)
74 {
75 cairo_xlib_xcb_surface_t *surface = abstract_surface;
76 cairo_status_t status;
77
78 cairo_surface_finish (&surface->xcb->base);
79 status = surface->xcb->base.status;
80 cairo_surface_destroy (&surface->xcb->base);
81
82 return status;
83 }
84
85 static cairo_status_t
_cairo_xlib_xcb_surface_acquire_source_image(void * abstract_surface,cairo_image_surface_t ** image_out,void ** image_extra)86 _cairo_xlib_xcb_surface_acquire_source_image (void *abstract_surface,
87 cairo_image_surface_t **image_out,
88 void **image_extra)
89 {
90 cairo_xlib_xcb_surface_t *surface = abstract_surface;
91 return _cairo_surface_acquire_source_image (&surface->xcb->base,
92 image_out, image_extra);
93 }
94
95 static void
_cairo_xlib_xcb_surface_release_source_image(void * abstract_surface,cairo_image_surface_t * image_out,void * image_extra)96 _cairo_xlib_xcb_surface_release_source_image (void *abstract_surface,
97 cairo_image_surface_t *image_out,
98 void *image_extra)
99 {
100 cairo_xlib_xcb_surface_t *surface = abstract_surface;
101 _cairo_surface_release_source_image (&surface->xcb->base, image_out, image_extra);
102 }
103
104 static cairo_bool_t
_cairo_xlib_xcb_surface_get_extents(void * abstract_surface,cairo_rectangle_int_t * extents)105 _cairo_xlib_xcb_surface_get_extents (void *abstract_surface,
106 cairo_rectangle_int_t *extents)
107 {
108 cairo_xlib_xcb_surface_t *surface = abstract_surface;
109 return _cairo_surface_get_extents (&surface->xcb->base, extents);
110 }
111
112 static void
_cairo_xlib_xcb_surface_get_font_options(void * abstract_surface,cairo_font_options_t * options)113 _cairo_xlib_xcb_surface_get_font_options (void *abstract_surface,
114 cairo_font_options_t *options)
115 {
116 cairo_xlib_xcb_surface_t *surface = abstract_surface;
117 surface->xcb->base.backend->get_font_options (surface->xcb, options);
118 }
119
120 static cairo_int_status_t
_cairo_xlib_xcb_surface_paint(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_clip_t * clip)121 _cairo_xlib_xcb_surface_paint (void *abstract_surface,
122 cairo_operator_t op,
123 const cairo_pattern_t *source,
124 cairo_clip_t *clip)
125 {
126 cairo_xlib_xcb_surface_t *surface = abstract_surface;
127 return surface->xcb->base.backend->paint (surface->xcb, op, source, clip);
128 }
129
130 static cairo_int_status_t
_cairo_xlib_xcb_surface_mask(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,const cairo_pattern_t * mask,cairo_clip_t * clip)131 _cairo_xlib_xcb_surface_mask (void *abstract_surface,
132 cairo_operator_t op,
133 const cairo_pattern_t *source,
134 const cairo_pattern_t *mask,
135 cairo_clip_t *clip)
136 {
137 cairo_xlib_xcb_surface_t *surface = abstract_surface;
138 return surface->xcb->base.backend->mask (surface->xcb, op, source, mask, clip);
139 }
140
141 static cairo_int_status_t
_cairo_xlib_xcb_surface_stroke(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_path_fixed_t * path,const cairo_stroke_style_t * style,const cairo_matrix_t * ctm,const cairo_matrix_t * ctm_inverse,double tolerance,cairo_antialias_t antialias,cairo_clip_t * clip)142 _cairo_xlib_xcb_surface_stroke (void *abstract_surface,
143 cairo_operator_t op,
144 const cairo_pattern_t *source,
145 cairo_path_fixed_t *path,
146 const cairo_stroke_style_t *style,
147 const cairo_matrix_t *ctm,
148 const cairo_matrix_t *ctm_inverse,
149 double tolerance,
150 cairo_antialias_t antialias,
151 cairo_clip_t *clip)
152 {
153 cairo_xlib_xcb_surface_t *surface = abstract_surface;
154 return surface->xcb->base.backend->stroke (surface->xcb,
155 op, source, path, style,
156 ctm, ctm_inverse,
157 tolerance, antialias, clip);
158 }
159
160 static cairo_int_status_t
_cairo_xlib_xcb_surface_fill(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_path_fixed_t * path,cairo_fill_rule_t fill_rule,double tolerance,cairo_antialias_t antialias,cairo_clip_t * clip)161 _cairo_xlib_xcb_surface_fill (void *abstract_surface,
162 cairo_operator_t op,
163 const cairo_pattern_t *source,
164 cairo_path_fixed_t *path,
165 cairo_fill_rule_t fill_rule,
166 double tolerance,
167 cairo_antialias_t antialias,
168 cairo_clip_t *clip)
169 {
170 cairo_xlib_xcb_surface_t *surface = abstract_surface;
171 return surface->xcb->base.backend->fill (surface->xcb,
172 op, source, path,
173 fill_rule, tolerance, antialias,
174 clip);
175 }
176
177 static cairo_int_status_t
_cairo_xlib_xcb_surface_glyphs(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_glyph_t * glyphs,int num_glyphs,cairo_scaled_font_t * scaled_font,cairo_clip_t * clip,int * num_remaining)178 _cairo_xlib_xcb_surface_glyphs (void *abstract_surface,
179 cairo_operator_t op,
180 const cairo_pattern_t *source,
181 cairo_glyph_t *glyphs,
182 int num_glyphs,
183 cairo_scaled_font_t *scaled_font,
184 cairo_clip_t *clip,
185 int *num_remaining)
186 {
187 cairo_xlib_xcb_surface_t *surface = abstract_surface;
188 return surface->xcb->base.backend->show_glyphs (surface->xcb, op, source,
189 glyphs, num_glyphs, scaled_font,
190 clip, num_remaining);
191 }
192
193 static cairo_status_t
_cairo_xlib_xcb_surface_flush(void * abstract_surface)194 _cairo_xlib_xcb_surface_flush (void *abstract_surface)
195 {
196 cairo_xlib_xcb_surface_t *surface = abstract_surface;
197 return surface->xcb->base.backend->flush (surface->xcb);
198 }
199
200 static cairo_status_t
_cairo_xlib_xcb_surface_mark_dirty(void * abstract_surface,int x,int y,int width,int height)201 _cairo_xlib_xcb_surface_mark_dirty (void *abstract_surface,
202 int x, int y,
203 int width, int height)
204 {
205 cairo_xlib_xcb_surface_t *surface = abstract_surface;
206 return surface->xcb->base.backend->mark_dirty_rectangle (surface->xcb, x, y, width, height);
207 }
208
209 static const cairo_surface_backend_t _cairo_xlib_xcb_surface_backend = {
210 CAIRO_SURFACE_TYPE_XLIB,
211 _cairo_xlib_xcb_surface_create_similar,
212 _cairo_xlib_xcb_surface_finish,
213 _cairo_xlib_xcb_surface_acquire_source_image,
214 _cairo_xlib_xcb_surface_release_source_image,
215 NULL, NULL, NULL, /* dest acquire/release/clone */
216
217 NULL, /* composite */
218 NULL, /* fill */
219 NULL, /* trapezoids */
220 NULL, /* span */
221 NULL, /* check-span */
222
223 NULL, /* copy_page */
224 NULL, /* show_page */
225 _cairo_xlib_xcb_surface_get_extents,
226 NULL, /* old-glyphs */
227 _cairo_xlib_xcb_surface_get_font_options,
228
229 _cairo_xlib_xcb_surface_flush,
230 _cairo_xlib_xcb_surface_mark_dirty,
231 NULL, NULL, /* font/glyph fini */
232
233 _cairo_xlib_xcb_surface_paint,
234 _cairo_xlib_xcb_surface_mask,
235 _cairo_xlib_xcb_surface_stroke,
236 _cairo_xlib_xcb_surface_fill,
237 _cairo_xlib_xcb_surface_glyphs,
238 };
239
240 static cairo_surface_t *
_cairo_xlib_xcb_surface_create(void * dpy,void * scr,void * visual,void * format,cairo_surface_t * xcb)241 _cairo_xlib_xcb_surface_create (void *dpy,
242 void *scr,
243 void *visual,
244 void *format,
245 cairo_surface_t *xcb)
246 {
247 cairo_xlib_xcb_surface_t *surface;
248
249 if (unlikely (xcb->status))
250 return xcb;
251
252 surface = malloc (sizeof (*surface));
253 if (unlikely (surface == NULL)) {
254 cairo_surface_destroy (xcb);
255 return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
256 }
257
258 _cairo_surface_init (&surface->base,
259 &_cairo_xlib_xcb_surface_backend,
260 xcb->device,
261 xcb->content);
262
263 surface->display = dpy;
264 surface->screen = scr;
265 surface->visual = visual;
266 surface->format = format;
267 surface->xcb = (cairo_xcb_surface_t *) xcb;
268
269 return &surface->base;
270 }
271
272 static Screen *
_cairo_xlib_screen_from_visual(Display * dpy,Visual * visual)273 _cairo_xlib_screen_from_visual (Display *dpy, Visual *visual)
274 {
275 int s, d, v;
276
277 for (s = 0; s < ScreenCount (dpy); s++) {
278 Screen *screen;
279
280 screen = ScreenOfDisplay (dpy, s);
281 if (visual == DefaultVisualOfScreen (screen))
282 return screen;
283
284 for (d = 0; d < screen->ndepths; d++) {
285 Depth *depth;
286
287 depth = &screen->depths[d];
288 for (v = 0; v < depth->nvisuals; v++)
289 if (visual == &depth->visuals[v])
290 return screen;
291 }
292 }
293
294 return NULL;
295 }
296
297 cairo_surface_t *
cairo_xlib_surface_create(Display * dpy,Drawable drawable,Visual * visual,int width,int height)298 cairo_xlib_surface_create (Display *dpy,
299 Drawable drawable,
300 Visual *visual,
301 int width,
302 int height)
303 {
304 Screen *scr;
305 xcb_visualtype_t xcb_visual;
306
307 scr = _cairo_xlib_screen_from_visual (dpy, visual);
308 if (scr == NULL)
309 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
310
311 xcb_visual.visual_id = visual->visualid;
312 #if defined(__cplusplus) || defined(c_plusplus)
313 xcb_visual._class = visual->c_class;
314 #else
315 xcb_visual._class = visual->class;
316 #endif
317 xcb_visual.bits_per_rgb_value = visual->bits_per_rgb;
318 xcb_visual.colormap_entries = visual->map_entries;
319 xcb_visual.red_mask = visual->red_mask;
320 xcb_visual.green_mask = visual->green_mask;
321 xcb_visual.blue_mask = visual->blue_mask;
322
323 return _cairo_xlib_xcb_surface_create (dpy, scr, visual, NULL,
324 cairo_xcb_surface_create (XGetXCBConnection (dpy),
325 drawable,
326 &xcb_visual,
327 width, height));
328 }
329
330 cairo_surface_t *
cairo_xlib_surface_create_for_bitmap(Display * dpy,Pixmap bitmap,Screen * scr,int width,int height)331 cairo_xlib_surface_create_for_bitmap (Display *dpy,
332 Pixmap bitmap,
333 Screen *scr,
334 int width,
335 int height)
336 {
337 return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, NULL,
338 cairo_xcb_surface_create_for_bitmap (XGetXCBConnection (dpy),
339 (xcb_screen_t *) scr,
340 bitmap,
341 width, height));
342 }
343
344 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
345 static xcb_screen_t *
_cairo_xcb_screen_from_root(xcb_connection_t * connection,xcb_window_t id)346 _cairo_xcb_screen_from_root (xcb_connection_t *connection,
347 xcb_window_t id)
348 {
349 xcb_screen_iterator_t s;
350
351 s = xcb_setup_roots_iterator (xcb_get_setup (connection));
352 for (; s.rem; xcb_screen_next (&s)) {
353 if (s.data->root == id)
354 return s.data;
355 }
356
357 return NULL;
358 }
359 cairo_surface_t *
cairo_xlib_surface_create_with_xrender_format(Display * dpy,Drawable drawable,Screen * scr,XRenderPictFormat * format,int width,int height)360 cairo_xlib_surface_create_with_xrender_format (Display *dpy,
361 Drawable drawable,
362 Screen *scr,
363 XRenderPictFormat *format,
364 int width,
365 int height)
366 {
367 xcb_render_pictforminfo_t xcb_format;
368 xcb_connection_t *connection;
369 xcb_screen_t *screen;
370
371 xcb_format.id = format->id;
372 xcb_format.type = format->type;
373 xcb_format.depth = format->depth;
374 xcb_format.direct.red_shift = format->direct.red;
375 xcb_format.direct.red_mask = format->direct.redMask;
376 xcb_format.direct.green_shift = format->direct.green;
377 xcb_format.direct.green_mask = format->direct.greenMask;
378 xcb_format.direct.blue_shift = format->direct.blue;
379 xcb_format.direct.blue_mask = format->direct.blueMask;
380 xcb_format.direct.alpha_shift = format->direct.alpha;
381 xcb_format.direct.alpha_mask = format->direct.alphaMask;
382 xcb_format.colormap = format->colormap;
383
384 connection = XGetXCBConnection (dpy);
385 screen = _cairo_xcb_screen_from_root (connection, (xcb_window_t) scr->root);
386
387 return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, format,
388 cairo_xcb_surface_create_with_xrender_format (connection, screen,
389 drawable,
390 &xcb_format,
391 width, height));
392 }
393
394 XRenderPictFormat *
cairo_xlib_surface_get_xrender_format(cairo_surface_t * surface)395 cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
396 {
397 cairo_xlib_xcb_surface_t *xlib_surface = (cairo_xlib_xcb_surface_t *) surface;
398
399 /* Throw an error for a non-xlib surface */
400 if (surface->type != CAIRO_SURFACE_TYPE_XLIB) {
401 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
402 return NULL;
403 }
404
405 return xlib_surface->format;
406 }
407 #endif
408
409 void
cairo_xlib_surface_set_size(cairo_surface_t * abstract_surface,int width,int height)410 cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
411 int width,
412 int height)
413 {
414 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
415 cairo_status_t status;
416
417 if (unlikely (abstract_surface->status))
418 return;
419
420 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
421 status = _cairo_surface_set_error (abstract_surface,
422 CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
423 return;
424 }
425
426 cairo_xcb_surface_set_size (&surface->xcb->base, width, height);
427 }
428
429 void
cairo_xlib_surface_set_drawable(cairo_surface_t * abstract_surface,Drawable drawable,int width,int height)430 cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
431 Drawable drawable,
432 int width,
433 int height)
434 {
435 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *)abstract_surface;
436 cairo_status_t status;
437
438 if (unlikely (abstract_surface->status))
439 return;
440
441 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
442 status = _cairo_surface_set_error (abstract_surface,
443 CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
444 return;
445 }
446
447 ASSERT_NOT_REACHED;
448 }
449
450 Display *
cairo_xlib_surface_get_display(cairo_surface_t * abstract_surface)451 cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
452 {
453 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
454
455 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
456 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
457 return NULL;
458 }
459
460 return surface->display;
461 }
462
463 Drawable
cairo_xlib_surface_get_drawable(cairo_surface_t * abstract_surface)464 cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
465 {
466 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
467
468 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
469 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
470 return 0;
471 }
472
473 return surface->xcb->drawable;
474 }
475
476 Screen *
cairo_xlib_surface_get_screen(cairo_surface_t * abstract_surface)477 cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
478 {
479 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
480
481 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
482 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
483 return NULL;
484 }
485
486 return surface->screen;
487 }
488
489 Visual *
cairo_xlib_surface_get_visual(cairo_surface_t * abstract_surface)490 cairo_xlib_surface_get_visual (cairo_surface_t *abstract_surface)
491 {
492 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
493
494 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
495 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
496 return NULL;
497 }
498
499 return surface->visual;
500 }
501
502 int
cairo_xlib_surface_get_depth(cairo_surface_t * abstract_surface)503 cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
504 {
505 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
506
507 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
508 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
509 return 0;
510 }
511
512 return surface->xcb->depth;
513 }
514
515 int
cairo_xlib_surface_get_width(cairo_surface_t * abstract_surface)516 cairo_xlib_surface_get_width (cairo_surface_t *abstract_surface)
517 {
518 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
519
520 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
521 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
522 return 0;
523 }
524
525 return surface->xcb->width;
526 }
527
528 int
cairo_xlib_surface_get_height(cairo_surface_t * abstract_surface)529 cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
530 {
531 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
532
533 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
534 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
535 return 0;
536 }
537
538 return surface->xcb->height;
539 }
540