Tizen 2.0 Release
[framework/graphics/cairo.git] / src / cairo-xcb-surface.c
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  *      Behdad Esfahbod <behdad@behdad.org>
36  *      Carl D. Worth <cworth@cworth.org>
37  *      Chris Wilson <chris@chris-wilson.co.uk>
38  *      Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
39  */
40
41 #include "cairoint.h"
42
43 #include "cairo-xcb.h"
44 #include "cairo-xcb-private.h"
45
46 #include "cairo-composite-rectangles-private.h"
47 #include "cairo-default-context-private.h"
48 #include "cairo-image-surface-inline.h"
49 #include "cairo-list-inline.h"
50 #include "cairo-surface-backend-private.h"
51 #include "cairo-compositor-private.h"
52
53 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
54 slim_hidden_proto (cairo_xcb_surface_create);
55 slim_hidden_proto (cairo_xcb_surface_create_for_bitmap);
56 slim_hidden_proto (cairo_xcb_surface_create_with_xrender_format);
57 #endif
58
59 /**
60  * SECTION:cairo-xcb
61  * @Title: XCB Surfaces
62  * @Short_Description: X Window System rendering using the XCB library
63  * @See_Also: #cairo_surface_t
64  *
65  * The XCB surface is used to render cairo graphics to X Window System
66  * windows and pixmaps using the XCB library.
67  *
68  * Note that the XCB surface automatically takes advantage of the X render
69  * extension if it is available.
70  **/
71
72 /**
73  * CAIRO_HAS_XCB_SURFACE:
74  *
75  * Defined if the xcb surface backend is available.
76  * This macro can be used to conditionally compile backend-specific code.
77  *
78  * Since: 1.12
79  **/
80
81 cairo_surface_t *
82 _cairo_xcb_surface_create_similar (void                 *abstract_other,
83                                    cairo_content_t       content,
84                                    int                   width,
85                                    int                   height)
86 {
87     cairo_xcb_surface_t *other = abstract_other;
88     cairo_xcb_surface_t *surface;
89     cairo_xcb_connection_t *connection;
90     xcb_pixmap_t pixmap;
91     cairo_status_t status;
92
93     if (unlikely(width  > XLIB_COORD_MAX ||
94                  height > XLIB_COORD_MAX ||
95                  width  <= 0 ||
96                  height <= 0))
97         return cairo_image_surface_create (_cairo_format_from_content (content),
98                                            width, height);
99
100     if ((other->connection->flags & CAIRO_XCB_HAS_RENDER) == 0)
101         return _cairo_xcb_surface_create_similar_image (other,
102                                                         _cairo_format_from_content (content),
103                                                         width, height);
104
105     connection = other->connection;
106     status = _cairo_xcb_connection_acquire (connection);
107     if (unlikely (status))
108         return _cairo_surface_create_in_error (status);
109
110     if (content == other->base.content) {
111         pixmap = _cairo_xcb_connection_create_pixmap (connection,
112                                                       other->depth,
113                                                       other->drawable,
114                                                       width, height);
115
116         surface = (cairo_xcb_surface_t *)
117             _cairo_xcb_surface_create_internal (other->screen,
118                                                 pixmap, TRUE,
119                                                 other->pixman_format,
120                                                 other->xrender_format,
121                                                 width, height);
122     } else {
123         cairo_format_t format;
124         pixman_format_code_t pixman_format;
125
126         /* XXX find a compatible xrender format */
127         switch (content) {
128         case CAIRO_CONTENT_ALPHA:
129             pixman_format = PIXMAN_a8;
130             format = CAIRO_FORMAT_A8;
131             break;
132         case CAIRO_CONTENT_COLOR:
133             pixman_format = PIXMAN_x8r8g8b8;
134             format = CAIRO_FORMAT_RGB24;
135             break;
136         default:
137             ASSERT_NOT_REACHED;
138         case CAIRO_CONTENT_COLOR_ALPHA:
139             pixman_format = PIXMAN_a8r8g8b8;
140             format = CAIRO_FORMAT_ARGB32;
141             break;
142         }
143
144         pixmap = _cairo_xcb_connection_create_pixmap (connection,
145                                                       PIXMAN_FORMAT_DEPTH (pixman_format),
146                                                       other->drawable,
147                                                       width, height);
148
149         surface = (cairo_xcb_surface_t *)
150             _cairo_xcb_surface_create_internal (other->screen,
151                                                 pixmap, TRUE,
152                                                 pixman_format,
153                                                 connection->standard_formats[format],
154                                                 width, height);
155     }
156
157     if (unlikely (surface->base.status))
158         _cairo_xcb_connection_free_pixmap (connection, pixmap);
159
160     _cairo_xcb_connection_release (connection);
161
162     return &surface->base;
163 }
164
165 cairo_surface_t *
166 _cairo_xcb_surface_create_similar_image (void                   *abstract_other,
167                                          cairo_format_t          format,
168                                          int                     width,
169                                          int                     height)
170 {
171     cairo_xcb_surface_t *other = abstract_other;
172     cairo_xcb_connection_t *connection = other->connection;
173
174     cairo_xcb_shm_info_t *shm_info;
175     cairo_image_surface_t *image;
176     cairo_status_t status;
177     pixman_format_code_t pixman_format;
178
179     if (unlikely(width  > XLIB_COORD_MAX ||
180                  height > XLIB_COORD_MAX ||
181                  width  <= 0 ||
182                  height <= 0))
183         return NULL;
184
185     pixman_format = _cairo_format_to_pixman_format_code (format);
186
187     status = _cairo_xcb_shm_image_create (connection, pixman_format,
188                                           width, height, &image,
189                                           &shm_info);
190     if (unlikely (status))
191         return _cairo_surface_create_in_error (status);
192
193     if (! image->base.is_clear) {
194         memset (image->data, 0, image->stride * image->height);
195         image->base.is_clear = TRUE;
196     }
197
198     return &image->base;
199 }
200
201 static cairo_status_t
202 _cairo_xcb_surface_finish (void *abstract_surface)
203 {
204     cairo_xcb_surface_t *surface = abstract_surface;
205     cairo_status_t status;
206
207     if (surface->fallback != NULL) {
208         cairo_surface_finish (&surface->fallback->base);
209         cairo_surface_destroy (&surface->fallback->base);
210     }
211     _cairo_boxes_fini (&surface->fallback_damage);
212
213     cairo_list_del (&surface->link);
214
215     status = _cairo_xcb_connection_acquire (surface->connection);
216     if (status == CAIRO_STATUS_SUCCESS) {
217         if (surface->picture != XCB_NONE) {
218             _cairo_xcb_connection_render_free_picture (surface->connection,
219                                                        surface->picture);
220         }
221
222         if (surface->owns_pixmap)
223             _cairo_xcb_connection_free_pixmap (surface->connection, surface->drawable);
224         _cairo_xcb_connection_release (surface->connection);
225     }
226
227     _cairo_xcb_connection_destroy (surface->connection);
228
229     return status;
230 }
231
232 static void
233 _destroy_image (pixman_image_t *image, void *data)
234 {
235     free (data);
236 }
237
238 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
239 static cairo_surface_t *
240 _cairo_xcb_surface_create_shm_image (cairo_xcb_connection_t *connection,
241                                      pixman_format_code_t pixman_format,
242                                      int width, int height,
243                                      cairo_bool_t might_reuse,
244                                      cairo_xcb_shm_info_t **shm_info_out)
245 {
246     cairo_surface_t *image;
247     cairo_xcb_shm_info_t *shm_info;
248     cairo_int_status_t status;
249     size_t stride;
250
251     *shm_info_out = NULL;
252
253     stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width,
254                                          PIXMAN_FORMAT_BPP (pixman_format));
255     status = _cairo_xcb_connection_allocate_shm_info (connection,
256                                                       stride * height,
257                                                       might_reuse,
258                                                       &shm_info);
259     if (unlikely (status)) {
260         if (status == CAIRO_INT_STATUS_UNSUPPORTED)
261             return NULL;
262
263         return _cairo_surface_create_in_error (status);
264     }
265
266     image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
267                                                             pixman_format,
268                                                             width, height,
269                                                             stride);
270     if (unlikely (image->status)) {
271         _cairo_xcb_shm_info_destroy (shm_info);
272         return image;
273     }
274
275     status = _cairo_user_data_array_set_data (&image->user_data,
276                                               (const cairo_user_data_key_t *) connection,
277                                               shm_info,
278                                               (cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
279     if (unlikely (status)) {
280         cairo_surface_destroy (image);
281         _cairo_xcb_shm_info_destroy (shm_info);
282         return _cairo_surface_create_in_error (status);
283     }
284
285     *shm_info_out = shm_info;
286     return image;
287 }
288 #endif
289
290 static cairo_surface_t *
291 _get_shm_image (cairo_xcb_surface_t *surface,
292                 int x, int y,
293                 int width, int height)
294 {
295 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
296     cairo_xcb_shm_info_t *shm_info;
297     cairo_surface_t *image;
298     cairo_status_t status;
299
300     if ((surface->connection->flags & CAIRO_XCB_HAS_SHM) == 0)
301         return NULL;
302
303     image = _cairo_xcb_surface_create_shm_image (surface->connection,
304                                                  surface->pixman_format,
305                                                  width, height,
306                                                  TRUE,
307                                                  &shm_info);
308     if (unlikely (image == NULL || image->status))
309         goto done;
310
311     status = _cairo_xcb_connection_shm_get_image (surface->connection,
312                                                   surface->drawable,
313                                                   x, y,
314                                                   width, height,
315                                                   shm_info->shm,
316                                                   shm_info->offset);
317     if (unlikely (status)) {
318         cairo_surface_destroy (image);
319         image = _cairo_surface_create_in_error (status);
320     }
321
322 done:
323     return image;
324 #else
325     return NULL;
326 #endif
327 }
328
329 static cairo_surface_t *
330 _get_image (cairo_xcb_surface_t          *surface,
331             cairo_bool_t                  use_shm,
332             int x, int y,
333             int width, int height)
334 {
335     cairo_surface_t *image;
336     cairo_xcb_connection_t *connection;
337     xcb_get_image_reply_t *reply;
338     cairo_int_status_t status;
339
340     assert (surface->fallback == NULL);
341     assert (x >= 0);
342     assert (y >= 0);
343     assert (x + width <= surface->width);
344     assert (y + height <= surface->height);
345
346     if (surface->deferred_clear) {
347         image =
348             _cairo_image_surface_create_with_pixman_format (NULL,
349                                                             surface->pixman_format,
350                                                             width, height,
351                                                             0);
352         if (surface->deferred_clear_color.alpha_short > 0x00ff) {
353             cairo_solid_pattern_t solid;
354
355             _cairo_pattern_init_solid (&solid, &surface->deferred_clear_color);
356             status = _cairo_surface_paint (image,
357                                            CAIRO_OPERATOR_SOURCE,
358                                            &solid.base,
359                                            NULL);
360             if (unlikely (status)) {
361                 cairo_surface_destroy (image);
362                 image = _cairo_surface_create_in_error (status);
363             }
364         }
365         return image;
366     }
367
368     connection = surface->connection;
369
370     status = _cairo_xcb_connection_acquire (connection);
371     if (unlikely (status))
372         return _cairo_surface_create_in_error (status);
373
374     if (use_shm) {
375         image = _get_shm_image (surface, x, y, width, height);
376         if (image) {
377             if (image->status == CAIRO_STATUS_SUCCESS) {
378                 _cairo_xcb_connection_release (connection);
379                 return image;
380             }
381             cairo_surface_destroy (image);
382         }
383     }
384
385     status = _cairo_xcb_connection_get_image (connection,
386                                               surface->drawable,
387                                               x, y,
388                                               width, height,
389                                               &reply);
390     if (unlikely (status))
391         goto FAIL;
392
393     if (reply == NULL && ! surface->owns_pixmap) {
394         /* xcb_get_image_t from a window is dangerous because it can
395          * produce errors if the window is unmapped or partially
396          * outside the screen. We could check for errors and
397          * retry, but to keep things simple, we just create a
398          * temporary pixmap
399          *
400          * If we hit this fallback too often, we should remember so and
401          * skip the round-trip from the above GetImage request,
402          * similar to what cairo-xlib does.
403          */
404         xcb_pixmap_t pixmap;
405         xcb_gcontext_t gc;
406
407         gc = _cairo_xcb_screen_get_gc (surface->screen,
408                                        surface->drawable,
409                                        surface->depth);
410         pixmap = _cairo_xcb_connection_create_pixmap (connection,
411                                                       surface->depth,
412                                                       surface->drawable,
413                                                       width, height);
414
415         /* XXX IncludeInferiors? */
416         _cairo_xcb_connection_copy_area (connection,
417                                          surface->drawable,
418                                          pixmap, gc,
419                                          x, y,
420                                          0, 0,
421                                          width, height);
422
423         _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
424
425         status = _cairo_xcb_connection_get_image (connection,
426                                                   pixmap,
427                                                   0, 0,
428                                                   width, height,
429                                                   &reply);
430         _cairo_xcb_connection_free_pixmap (connection, pixmap);
431
432         if (unlikely (status))
433             goto FAIL;
434     }
435
436     if (unlikely (reply == NULL)) {
437         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
438         goto FAIL;
439     }
440
441     /* XXX byte swap */
442     /* XXX format conversion */
443     assert (reply->depth == surface->depth);
444
445     image = _cairo_image_surface_create_with_pixman_format
446         (xcb_get_image_data (reply),
447          surface->pixman_format,
448          width, height,
449          CAIRO_STRIDE_FOR_WIDTH_BPP (width,
450                                      PIXMAN_FORMAT_BPP (surface->pixman_format)));
451     status = image->status;
452     if (unlikely (status)) {
453         free (reply);
454         goto FAIL;
455     }
456
457     /* XXX */
458     pixman_image_set_destroy_function (((cairo_image_surface_t *)image)->pixman_image, _destroy_image, reply);
459
460     _cairo_xcb_connection_release (connection);
461
462     return image;
463
464 FAIL:
465     _cairo_xcb_connection_release (connection);
466     return _cairo_surface_create_in_error (status);
467 }
468
469 static cairo_surface_t *
470 _cairo_xcb_surface_source (void *abstract_surface,
471                            cairo_rectangle_int_t *extents)
472 {
473     cairo_xcb_surface_t *surface = abstract_surface;
474
475     if (extents) {
476         extents->x = extents->y = 0;
477         extents->width  = surface->width;
478         extents->height = surface->height;
479     }
480
481     return &surface->base;
482 }
483
484 static cairo_status_t
485 _cairo_xcb_surface_acquire_source_image (void *abstract_surface,
486                                          cairo_image_surface_t **image_out,
487                                          void **image_extra)
488 {
489     cairo_xcb_surface_t *surface = abstract_surface;
490     cairo_surface_t *image;
491
492     if (surface->fallback != NULL) {
493         image = cairo_surface_reference (&surface->fallback->base);
494         goto DONE;
495     }
496
497     image = _cairo_surface_has_snapshot (&surface->base,
498                                          &_cairo_image_surface_backend);
499     if (image != NULL) {
500         image = cairo_surface_reference (image);
501         goto DONE;
502     }
503
504     image = _get_image (surface, FALSE, 0, 0, surface->width, surface->height);
505     if (unlikely (image->status))
506         return image->status;
507
508     _cairo_surface_attach_snapshot (&surface->base, image, NULL);
509
510 DONE:
511     *image_out = (cairo_image_surface_t *) image;
512     *image_extra = NULL;
513     return CAIRO_STATUS_SUCCESS;
514 }
515
516 static void
517 _cairo_xcb_surface_release_source_image (void *abstract_surface,
518                                          cairo_image_surface_t *image,
519                                          void *image_extra)
520 {
521     cairo_surface_destroy (&image->base);
522 }
523
524 cairo_bool_t
525 _cairo_xcb_surface_get_extents (void *abstract_surface,
526                                 cairo_rectangle_int_t *extents)
527 {
528     cairo_xcb_surface_t *surface = abstract_surface;
529
530     extents->x = extents->y = 0;
531     extents->width  = surface->width;
532     extents->height = surface->height;
533     return TRUE;
534 }
535
536 static void
537 _cairo_xcb_surface_get_font_options (void *abstract_surface,
538                                      cairo_font_options_t *options)
539 {
540     /* XXX  copy from xlib */
541     _cairo_font_options_init_default (options);
542     _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
543 }
544
545 static cairo_status_t
546 _put_shm_image (cairo_xcb_surface_t    *surface,
547                 xcb_gcontext_t          gc,
548                 cairo_image_surface_t  *image)
549 {
550 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
551     cairo_xcb_shm_info_t *shm_info;
552
553     shm_info = _cairo_user_data_array_get_data (&image->base.user_data,
554                                                 (const cairo_user_data_key_t *) surface->connection);
555     if (shm_info == NULL)
556         return CAIRO_INT_STATUS_UNSUPPORTED;
557
558     _cairo_xcb_connection_shm_put_image (surface->connection,
559                                          surface->drawable,
560                                          gc,
561                                          surface->width, surface->height,
562                                          0, 0,
563                                          image->width, image->height,
564                                          image->base.device_transform_inverse.x0,
565                                          image->base.device_transform_inverse.y0,
566                                          image->depth,
567                                          shm_info->shm,
568                                          shm_info->offset);
569
570     return CAIRO_STATUS_SUCCESS;
571 #else
572     return CAIRO_INT_STATUS_UNSUPPORTED;
573 #endif
574 }
575
576 static cairo_status_t
577 _put_image (cairo_xcb_surface_t    *surface,
578             cairo_image_surface_t  *image)
579 {
580     cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
581
582     /* XXX track damaged region? */
583
584     status = _cairo_xcb_connection_acquire (surface->connection);
585     if (unlikely (status))
586         return status;
587
588     if (image->pixman_format == surface->pixman_format) {
589         xcb_gcontext_t gc;
590
591         assert (image->depth == surface->depth);
592         assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format)));
593
594         gc = _cairo_xcb_screen_get_gc (surface->screen,
595                                        surface->drawable,
596                                        surface->depth);
597
598         status = _put_shm_image (surface, gc, image);
599         if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
600             _cairo_xcb_connection_put_image (surface->connection,
601                                              surface->drawable, gc,
602                                              image->width, image->height,
603                                              image->base.device_transform_inverse.x0,
604                                              image->base.device_transform_inverse.y0,
605                                              image->depth,
606                                              image->stride,
607                                              image->data);
608             status = CAIRO_STATUS_SUCCESS;
609         }
610
611         _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
612     } else {
613         ASSERT_NOT_REACHED;
614     }
615
616     _cairo_xcb_connection_release (surface->connection);
617     return status;
618 }
619
620 static cairo_int_status_t
621 _put_shm_image_boxes (cairo_xcb_surface_t    *surface,
622                       cairo_image_surface_t  *image,
623                       xcb_gcontext_t gc,
624                       cairo_boxes_t *boxes)
625 {
626 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
627     cairo_xcb_shm_info_t *shm_info;
628
629     shm_info = _cairo_user_data_array_get_data (&image->base.user_data,
630                                                 (const cairo_user_data_key_t *) surface->connection);
631     if (shm_info != NULL) {
632         struct _cairo_boxes_chunk *chunk;
633
634         for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
635             int i;
636
637             for (i = 0; i < chunk->count; i++) {
638                 cairo_box_t *b = &chunk->base[i];
639                 int x = _cairo_fixed_integer_part (b->p1.x);
640                 int y = _cairo_fixed_integer_part (b->p1.y);
641                 int width = _cairo_fixed_integer_part (b->p2.x - b->p1.x);
642                 int height = _cairo_fixed_integer_part (b->p2.y - b->p1.y);
643
644                 _cairo_xcb_connection_shm_put_image (surface->connection,
645                                                      surface->drawable,
646                                                      gc,
647                                                      surface->width, surface->height,
648                                                      x, y,
649                                                      width, height,
650                                                      x, y,
651                                                      image->depth,
652                                                      shm_info->shm,
653                                                      shm_info->offset);
654             }
655         }
656     }
657
658     return CAIRO_INT_STATUS_SUCCESS;
659 #endif
660
661     return CAIRO_INT_STATUS_UNSUPPORTED;
662 }
663
664 static cairo_status_t
665 _put_image_boxes (cairo_xcb_surface_t    *surface,
666                   cairo_image_surface_t  *image,
667                   cairo_boxes_t *boxes)
668 {
669     cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
670     xcb_gcontext_t gc;
671
672     if (boxes->num_boxes == 0)
673             return CAIRO_STATUS_SUCCESS;
674
675     /* XXX track damaged region? */
676
677     status = _cairo_xcb_connection_acquire (surface->connection);
678     if (unlikely (status))
679         return status;
680
681     assert (image->pixman_format == surface->pixman_format);
682     assert (image->depth == surface->depth);
683     assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format)));
684
685     gc = _cairo_xcb_screen_get_gc (surface->screen,
686                                    surface->drawable,
687                                    surface->depth);
688
689     status = _put_shm_image_boxes (surface, image, gc, boxes);
690     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
691             struct _cairo_boxes_chunk *chunk;
692
693             for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
694                     int i;
695
696                     for (i = 0; i < chunk->count; i++) {
697                             cairo_box_t *b = &chunk->base[i];
698                             int x = _cairo_fixed_integer_part (b->p1.x);
699                             int y = _cairo_fixed_integer_part (b->p1.y);
700                             int width = _cairo_fixed_integer_part (b->p2.x - b->p1.x);
701                             int height = _cairo_fixed_integer_part (b->p2.y - b->p1.y);
702                             _cairo_xcb_connection_put_image (surface->connection,
703                                                              surface->drawable, gc,
704                                                              width, height,
705                                                              x, y,
706                                                              image->depth,
707                                                              image->stride,
708                                                              image->data +
709                                                              x * PIXMAN_FORMAT_BPP (image->pixman_format) / 8 +
710                                                              y * image->stride);
711
712                     }
713             }
714             status = CAIRO_STATUS_SUCCESS;
715     }
716
717     _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
718     _cairo_xcb_connection_release (surface->connection);
719     return status;
720 }
721
722 static cairo_status_t
723 _cairo_xcb_surface_flush (void *abstract_surface,
724                           unsigned flags)
725 {
726     cairo_xcb_surface_t *surface = abstract_surface;
727     cairo_status_t status;
728
729     if (flags)
730         return CAIRO_STATUS_SUCCESS;
731
732     if (likely (surface->fallback == NULL)) {
733         status = CAIRO_STATUS_SUCCESS;
734         if (! surface->base.finished && surface->deferred_clear)
735             status = _cairo_xcb_surface_clear (surface);
736
737         return status;
738     }
739
740     status = surface->base.status;
741     if (status == CAIRO_STATUS_SUCCESS &&
742         (! surface->base._finishing || ! surface->owns_pixmap)) {
743         status = cairo_surface_status (&surface->fallback->base);
744
745         if (status == CAIRO_STATUS_SUCCESS)
746                 status = _cairo_bentley_ottmann_tessellate_boxes (&surface->fallback_damage,
747                                                                   CAIRO_FILL_RULE_WINDING,
748                                                                   &surface->fallback_damage);
749
750         if (status == CAIRO_STATUS_SUCCESS)
751             status = _put_image_boxes (surface,
752                                        surface->fallback,
753                                        &surface->fallback_damage);
754
755         if (status == CAIRO_STATUS_SUCCESS && ! surface->base._finishing) {
756             _cairo_surface_attach_snapshot (&surface->base,
757                                             &surface->fallback->base,
758                                             cairo_surface_finish);
759         }
760     }
761
762     _cairo_boxes_clear (&surface->fallback_damage);
763     cairo_surface_destroy (&surface->fallback->base);
764     surface->fallback = NULL;
765
766     return status;
767 }
768
769 static cairo_image_surface_t *
770 _cairo_xcb_surface_map_to_image (void *abstract_surface,
771                                  const cairo_rectangle_int_t *extents)
772 {
773     cairo_xcb_surface_t *surface = abstract_surface;
774     cairo_surface_t *image;
775     cairo_status_t status;
776
777     if (surface->fallback)
778         return _cairo_surface_map_to_image (&surface->fallback->base, extents);
779
780     image = _get_image (surface, TRUE,
781                         extents->x, extents->y,
782                         extents->width, extents->height);
783     status = cairo_surface_status (image);
784     if (unlikely (status)) {
785         cairo_surface_destroy(image);
786         return _cairo_image_surface_create_in_error (status);
787     }
788
789     /* Do we have a deferred clear and this image surface does NOT cover the
790      * whole xcb surface? Have to apply the clear in that case, else
791      * uploading the image will handle the problem for us.
792      */
793     if (surface->deferred_clear &&
794         ! (extents->width == surface->width &&
795            extents->height == surface->height)) {
796         status = _cairo_xcb_surface_clear (surface);
797         if (unlikely (status)) {
798             cairo_surface_destroy(image);
799             return _cairo_image_surface_create_in_error (status);
800         }
801     }
802     surface->deferred_clear = FALSE;
803
804     cairo_surface_set_device_offset (image, -extents->x, -extents->y);
805     return (cairo_image_surface_t *) image;
806 }
807
808 static cairo_int_status_t
809 _cairo_xcb_surface_unmap (void *abstract_surface,
810                           cairo_image_surface_t *image)
811 {
812     cairo_xcb_surface_t *surface = abstract_surface;
813     cairo_int_status_t status;
814
815     if (surface->fallback)
816         return _cairo_surface_unmap_image (&surface->fallback->base, image);
817
818     status = _put_image (abstract_surface, image);
819
820     cairo_surface_finish (&image->base);
821     cairo_surface_destroy (&image->base);
822
823     return status;
824 }
825
826 static cairo_surface_t *
827 _cairo_xcb_surface_fallback (cairo_xcb_surface_t *surface,
828                              cairo_composite_rectangles_t *composite)
829 {
830     cairo_image_surface_t *image;
831     cairo_status_t status;
832
833     status = _cairo_composite_rectangles_add_to_damage (composite,
834                                                         &surface->fallback_damage);
835     if (unlikely (status))
836             return _cairo_surface_create_in_error (status);
837
838     if (surface->fallback)
839         return &surface->fallback->base;
840
841     image = (cairo_image_surface_t *)
842             _get_image (surface, TRUE, 0, 0, surface->width, surface->height);
843
844     /* If there was a deferred clear, _get_image applied it */
845     if (image->base.status == CAIRO_STATUS_SUCCESS) {
846         surface->deferred_clear = FALSE;
847
848         surface->fallback = image;
849     }
850
851     return &surface->fallback->base;
852 }
853
854 static cairo_int_status_t
855 _cairo_xcb_fallback_compositor_paint (const cairo_compositor_t     *compositor,
856                                       cairo_composite_rectangles_t *extents)
857 {
858     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
859     cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
860
861     return _cairo_surface_paint (fallback, extents->op,
862                                  &extents->source_pattern.base,
863                                  extents->clip);
864 }
865
866 static cairo_int_status_t
867 _cairo_xcb_fallback_compositor_mask (const cairo_compositor_t     *compositor,
868                                      cairo_composite_rectangles_t *extents)
869 {
870     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
871     cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
872
873     return _cairo_surface_mask (fallback, extents->op,
874                                  &extents->source_pattern.base,
875                                  &extents->mask_pattern.base,
876                                  extents->clip);
877 }
878
879 static cairo_int_status_t
880 _cairo_xcb_fallback_compositor_stroke (const cairo_compositor_t     *compositor,
881                                        cairo_composite_rectangles_t *extents,
882                                        const cairo_path_fixed_t     *path,
883                                        const cairo_stroke_style_t   *style,
884                                        const cairo_matrix_t         *ctm,
885                                        const cairo_matrix_t         *ctm_inverse,
886                                        double                        tolerance,
887                                        cairo_antialias_t             antialias)
888 {
889     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
890     cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
891
892     return _cairo_surface_stroke (fallback, extents->op,
893                                   &extents->source_pattern.base,
894                                   path, style, ctm, ctm_inverse,
895                                   tolerance, antialias,
896                                   extents->clip);
897 }
898
899 static cairo_int_status_t
900 _cairo_xcb_fallback_compositor_fill (const cairo_compositor_t     *compositor,
901                                      cairo_composite_rectangles_t *extents,
902                                      const cairo_path_fixed_t     *path,
903                                      cairo_fill_rule_t             fill_rule,
904                                      double                        tolerance,
905                                      cairo_antialias_t             antialias)
906 {
907     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
908     cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
909
910     return _cairo_surface_fill (fallback, extents->op,
911                                 &extents->source_pattern.base,
912                                 path, fill_rule, tolerance,
913                                 antialias, extents->clip);
914 }
915
916 static cairo_int_status_t
917 _cairo_xcb_fallback_compositor_glyphs (const cairo_compositor_t     *compositor,
918                                        cairo_composite_rectangles_t *extents,
919                                        cairo_scaled_font_t          *scaled_font,
920                                        cairo_glyph_t                *glyphs,
921                                        int                           num_glyphs,
922                                        cairo_bool_t                  overlap)
923 {
924     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
925     cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
926
927     return _cairo_surface_show_text_glyphs (fallback, extents->op,
928                                             &extents->source_pattern.base,
929                                             NULL, 0, glyphs, num_glyphs,
930                                             NULL, 0, 0,
931                                             scaled_font, extents->clip);
932 }
933
934 static const cairo_compositor_t _cairo_xcb_fallback_compositor = {
935     &__cairo_no_compositor,
936
937     _cairo_xcb_fallback_compositor_paint,
938     _cairo_xcb_fallback_compositor_mask,
939     _cairo_xcb_fallback_compositor_stroke,
940     _cairo_xcb_fallback_compositor_fill,
941     _cairo_xcb_fallback_compositor_glyphs,
942 };
943
944 static const cairo_compositor_t _cairo_xcb_render_compositor = {
945     &_cairo_xcb_fallback_compositor,
946
947     _cairo_xcb_render_compositor_paint,
948     _cairo_xcb_render_compositor_mask,
949     _cairo_xcb_render_compositor_stroke,
950     _cairo_xcb_render_compositor_fill,
951     _cairo_xcb_render_compositor_glyphs,
952 };
953
954 static inline const cairo_compositor_t *
955 get_compositor (cairo_surface_t **s)
956 {
957     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t * )*s;
958     if (surface->fallback) {
959         *s = &surface->fallback->base;
960         return ((cairo_image_surface_t *) *s)->compositor;
961     }
962
963     return &_cairo_xcb_render_compositor;
964 }
965
966 static cairo_int_status_t
967 _cairo_xcb_surface_paint (void                  *abstract_surface,
968                           cairo_operator_t       op,
969                           const cairo_pattern_t *source,
970                           const cairo_clip_t    *clip)
971 {
972     cairo_surface_t *surface = abstract_surface;
973     const cairo_compositor_t *compositor = get_compositor (&surface);
974     return _cairo_compositor_paint (compositor, surface, op, source, clip);
975 }
976
977 static cairo_int_status_t
978 _cairo_xcb_surface_mask (void                   *abstract_surface,
979                          cairo_operator_t        op,
980                          const cairo_pattern_t  *source,
981                          const cairo_pattern_t  *mask,
982                          const cairo_clip_t     *clip)
983 {
984     cairo_surface_t *surface = abstract_surface;
985     const cairo_compositor_t *compositor = get_compositor (&surface);
986     return _cairo_compositor_mask (compositor, surface, op, source, mask, clip);
987 }
988
989 static cairo_int_status_t
990 _cairo_xcb_surface_stroke (void                         *abstract_surface,
991                            cairo_operator_t              op,
992                            const cairo_pattern_t        *source,
993                            const cairo_path_fixed_t     *path,
994                            const cairo_stroke_style_t   *style,
995                            const cairo_matrix_t         *ctm,
996                            const cairo_matrix_t         *ctm_inverse,
997                            double                        tolerance,
998                            cairo_antialias_t             antialias,
999                            const cairo_clip_t           *clip)
1000 {
1001     cairo_surface_t *surface = abstract_surface;
1002     const cairo_compositor_t *compositor = get_compositor (&surface);
1003     return _cairo_compositor_stroke (compositor, surface, op, source,
1004                                      path, style, ctm, ctm_inverse,
1005                                      tolerance, antialias, clip);
1006 }
1007
1008 static cairo_int_status_t
1009 _cairo_xcb_surface_fill (void                   *abstract_surface,
1010                          cairo_operator_t        op,
1011                          const cairo_pattern_t  *source,
1012                          const cairo_path_fixed_t*path,
1013                          cairo_fill_rule_t       fill_rule,
1014                          double                  tolerance,
1015                          cairo_antialias_t       antialias,
1016                          const cairo_clip_t     *clip)
1017 {
1018     cairo_surface_t *surface = abstract_surface;
1019     const cairo_compositor_t *compositor = get_compositor (&surface);
1020     return _cairo_compositor_fill (compositor, surface, op,
1021                                    source, path, fill_rule,
1022                                    tolerance, antialias, clip);
1023 }
1024
1025 static cairo_int_status_t
1026 _cairo_xcb_surface_glyphs (void                         *abstract_surface,
1027                            cairo_operator_t              op,
1028                            const cairo_pattern_t        *source,
1029                            cairo_glyph_t                *glyphs,
1030                            int                           num_glyphs,
1031                            cairo_scaled_font_t          *scaled_font,
1032                            const cairo_clip_t           *clip)
1033 {
1034     cairo_surface_t *surface = abstract_surface;
1035     const cairo_compositor_t *compositor = get_compositor (&surface);
1036     return _cairo_compositor_glyphs (compositor, surface, op,
1037                                      source, glyphs, num_glyphs,
1038                                      scaled_font, clip);
1039 }
1040
1041 const cairo_surface_backend_t _cairo_xcb_surface_backend = {
1042     CAIRO_SURFACE_TYPE_XCB,
1043     _cairo_xcb_surface_finish,
1044     _cairo_default_context_create,
1045
1046     _cairo_xcb_surface_create_similar,
1047     _cairo_xcb_surface_create_similar_image,
1048     _cairo_xcb_surface_map_to_image,
1049     _cairo_xcb_surface_unmap,
1050
1051     _cairo_xcb_surface_source,
1052     _cairo_xcb_surface_acquire_source_image,
1053     _cairo_xcb_surface_release_source_image,
1054     NULL, /* snapshot */
1055
1056
1057     NULL, /* copy_page */
1058     NULL, /* show_page */
1059
1060     _cairo_xcb_surface_get_extents,
1061     _cairo_xcb_surface_get_font_options,
1062
1063     _cairo_xcb_surface_flush,
1064     NULL,
1065
1066     _cairo_xcb_surface_paint,
1067     _cairo_xcb_surface_mask,
1068     _cairo_xcb_surface_stroke,
1069     _cairo_xcb_surface_fill,
1070     NULL, /* fill-stroke */
1071     _cairo_xcb_surface_glyphs,
1072 };
1073
1074 cairo_surface_t *
1075 _cairo_xcb_surface_create_internal (cairo_xcb_screen_t          *screen,
1076                                     xcb_drawable_t               drawable,
1077                                     cairo_bool_t                 owns_pixmap,
1078                                     pixman_format_code_t         pixman_format,
1079                                     xcb_render_pictformat_t      xrender_format,
1080                                     int                          width,
1081                                     int                          height)
1082 {
1083     cairo_xcb_surface_t *surface;
1084
1085     surface = malloc (sizeof (cairo_xcb_surface_t));
1086     if (unlikely (surface == NULL))
1087         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1088
1089     _cairo_surface_init (&surface->base,
1090                          &_cairo_xcb_surface_backend,
1091                          &screen->connection->device,
1092                          _cairo_content_from_pixman_format (pixman_format));
1093
1094     surface->connection = _cairo_xcb_connection_reference (screen->connection);
1095     surface->screen = screen;
1096     cairo_list_add (&surface->link, &screen->surfaces);
1097
1098     surface->drawable = drawable;
1099     surface->owns_pixmap = owns_pixmap;
1100
1101     surface->deferred_clear = FALSE;
1102     surface->deferred_clear_color = *CAIRO_COLOR_TRANSPARENT;
1103
1104     surface->width  = width;
1105     surface->height = height;
1106     surface->depth  = PIXMAN_FORMAT_DEPTH (pixman_format);
1107
1108     surface->picture = XCB_NONE;
1109     if (screen->connection->force_precision != -1)
1110         surface->precision = screen->connection->force_precision;
1111     else
1112         surface->precision = XCB_RENDER_POLY_MODE_IMPRECISE;
1113
1114     surface->pixman_format = pixman_format;
1115     surface->xrender_format = xrender_format;
1116
1117     surface->fallback = NULL;
1118     _cairo_boxes_init (&surface->fallback_damage);
1119
1120     return &surface->base;
1121 }
1122
1123 static xcb_screen_t *
1124 _cairo_xcb_screen_from_visual (xcb_connection_t *connection,
1125                                xcb_visualtype_t *visual,
1126                                int *depth)
1127 {
1128     xcb_depth_iterator_t d;
1129     xcb_screen_iterator_t s;
1130
1131     s = xcb_setup_roots_iterator (xcb_get_setup (connection));
1132     for (; s.rem; xcb_screen_next (&s)) {
1133         if (s.data->root_visual == visual->visual_id) {
1134             *depth = s.data->root_depth;
1135             return s.data;
1136         }
1137
1138         d = xcb_screen_allowed_depths_iterator(s.data);
1139         for (; d.rem; xcb_depth_next (&d)) {
1140             xcb_visualtype_iterator_t v = xcb_depth_visuals_iterator (d.data);
1141
1142             for (; v.rem; xcb_visualtype_next (&v)) {
1143                 if (v.data->visual_id == visual->visual_id) {
1144                     *depth = d.data->depth;
1145                     return s.data;
1146                 }
1147             }
1148         }
1149     }
1150
1151     return NULL;
1152 }
1153
1154 /**
1155  * cairo_xcb_surface_create:
1156  * @connection: an XCB connection
1157  * @drawable: an XCB drawable
1158  * @visual: the visual to use for drawing to @drawable. The depth
1159  *          of the visual must match the depth of the drawable.
1160  *          Currently, only TrueColor visuals are fully supported.
1161  * @width: the current width of @drawable
1162  * @height: the current height of @drawable
1163  *
1164  * Creates an XCB surface that draws to the given drawable.
1165  * The way that colors are represented in the drawable is specified
1166  * by the provided visual.
1167  *
1168  * Note: If @drawable is a Window, then the function
1169  * cairo_xcb_surface_set_size() must be called whenever the size of the
1170  * window changes.
1171  *
1172  * When @drawable is a Window containing child windows then drawing to
1173  * the created surface will be clipped by those child windows.  When
1174  * the created surface is used as a source, the contents of the
1175  * children will be included.
1176  *
1177  * Return value: a pointer to the newly created surface. The caller
1178  * owns the surface and should call cairo_surface_destroy() when done
1179  * with it.
1180  *
1181  * This function always returns a valid pointer, but it will return a
1182  * pointer to a "nil" surface if an error such as out of memory
1183  * occurs. You can use cairo_surface_status() to check for this.
1184  *
1185  * Since: 1.12
1186  **/
1187 cairo_surface_t *
1188 cairo_xcb_surface_create (xcb_connection_t  *connection,
1189                           xcb_drawable_t     drawable,
1190                           xcb_visualtype_t  *visual,
1191                           int                width,
1192                           int                height)
1193 {
1194     cairo_xcb_screen_t *screen;
1195     xcb_screen_t *xcb_screen;
1196     cairo_format_masks_t image_masks;
1197     pixman_format_code_t pixman_format;
1198     xcb_render_pictformat_t xrender_format;
1199     int depth;
1200
1201     if (xcb_connection_has_error (connection))
1202         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1203
1204     if (unlikely (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX))
1205         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1206     if (unlikely (width <= 0 || height <= 0))
1207         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1208
1209     xcb_screen = _cairo_xcb_screen_from_visual (connection, visual, &depth);
1210     if (unlikely (xcb_screen == NULL))
1211         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
1212
1213     image_masks.alpha_mask = 0;
1214     image_masks.red_mask   = visual->red_mask;
1215     image_masks.green_mask = visual->green_mask;
1216     image_masks.blue_mask  = visual->blue_mask;
1217     if (depth == 32) /* XXX visuals have no alpha! */
1218         image_masks.alpha_mask =
1219             0xffffffff & ~(visual->red_mask | visual->green_mask | visual->blue_mask);
1220     if (depth > 16)
1221         image_masks.bpp = 32;
1222     else if (depth > 8)
1223         image_masks.bpp = 16;
1224     else if (depth > 1)
1225         image_masks.bpp = 8;
1226     else
1227         image_masks.bpp = 1;
1228
1229     if (! _pixman_format_from_masks (&image_masks, &pixman_format))
1230         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1231
1232     screen = _cairo_xcb_screen_get (connection, xcb_screen);
1233     if (unlikely (screen == NULL))
1234         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1235
1236     xrender_format =
1237         _cairo_xcb_connection_get_xrender_format_for_visual (screen->connection,
1238                                                              visual->visual_id);
1239
1240     return _cairo_xcb_surface_create_internal (screen, drawable, FALSE,
1241                                                pixman_format,
1242                                                xrender_format,
1243                                                width, height);
1244 }
1245 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1246 slim_hidden_def (cairo_xcb_surface_create);
1247 #endif
1248
1249 /**
1250  * cairo_xcb_surface_create_for_bitmap:
1251  * @connection: an XCB connection
1252  * @screen: the XCB screen associated with @bitmap
1253  * @bitmap: an XCB drawable (a Pixmap with depth 1)
1254  * @width: the current width of @bitmap
1255  * @height: the current height of @bitmap
1256  *
1257  * Creates an XCB surface that draws to the given bitmap.
1258  * This will be drawn to as a %CAIRO_FORMAT_A1 object.
1259  *
1260  * Return value: a pointer to the newly created surface. The caller
1261  * owns the surface and should call cairo_surface_destroy() when done
1262  * with it.
1263  *
1264  * This function always returns a valid pointer, but it will return a
1265  * pointer to a "nil" surface if an error such as out of memory
1266  * occurs. You can use cairo_surface_status() to check for this.
1267  *
1268  * Since: 1.12
1269  **/
1270 cairo_surface_t *
1271 cairo_xcb_surface_create_for_bitmap (xcb_connection_t   *connection,
1272                                      xcb_screen_t       *screen,
1273                                      xcb_pixmap_t        bitmap,
1274                                      int                 width,
1275                                      int                 height)
1276 {
1277     cairo_xcb_screen_t *cairo_xcb_screen;
1278
1279     if (xcb_connection_has_error (connection))
1280         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1281
1282     if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
1283         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1284     if (unlikely (width <= 0 || height <= 0))
1285         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1286
1287     cairo_xcb_screen = _cairo_xcb_screen_get (connection, screen);
1288     if (unlikely (cairo_xcb_screen == NULL))
1289         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1290
1291     return _cairo_xcb_surface_create_internal (cairo_xcb_screen, bitmap, FALSE,
1292                                                PIXMAN_a1,
1293                                                cairo_xcb_screen->connection->standard_formats[CAIRO_FORMAT_A1],
1294                                                width, height);
1295 }
1296 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1297 slim_hidden_def (cairo_xcb_surface_create_for_bitmap);
1298 #endif
1299
1300 /**
1301  * cairo_xcb_surface_create_with_xrender_format:
1302  * @connection: an XCB connection
1303  * @drawable: an XCB drawable
1304  * @screen: the XCB screen associated with @drawable
1305  * @format: the picture format to use for drawing to @drawable. The
1306  *          depth of @format mush match the depth of the drawable.
1307  * @width: the current width of @drawable
1308  * @height: the current height of @drawable
1309  *
1310  * Creates an XCB surface that draws to the given drawable.
1311  * The way that colors are represented in the drawable is specified
1312  * by the provided picture format.
1313  *
1314  * Note: If @drawable is a Window, then the function
1315  * cairo_xcb_surface_set_size() must be called whenever the size of the
1316  * window changes.
1317  *
1318  * When @drawable is a Window containing child windows then drawing to
1319  * the created surface will be clipped by those child windows.  When
1320  * the created surface is used as a source, the contents of the
1321  * children will be included.
1322  *
1323  * Return value: a pointer to the newly created surface. The caller
1324  * owns the surface and should call cairo_surface_destroy() when done
1325  * with it.
1326  *
1327  * This function always returns a valid pointer, but it will return a
1328  * pointer to a "nil" surface if an error such as out of memory
1329  * occurs. You can use cairo_surface_status() to check for this.
1330  *
1331  * Since: 1.12
1332  **/
1333 cairo_surface_t *
1334 cairo_xcb_surface_create_with_xrender_format (xcb_connection_t      *connection,
1335                                               xcb_screen_t          *screen,
1336                                               xcb_drawable_t         drawable,
1337                                               xcb_render_pictforminfo_t *format,
1338                                               int                    width,
1339                                               int                    height)
1340 {
1341     cairo_xcb_screen_t *cairo_xcb_screen;
1342     cairo_format_masks_t image_masks;
1343     pixman_format_code_t pixman_format;
1344
1345     if (xcb_connection_has_error (connection))
1346         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1347
1348     if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
1349         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1350     if (unlikely (width <= 0 || height <= 0))
1351         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1352
1353     image_masks.alpha_mask =
1354         (unsigned long) format->direct.alpha_mask << format->direct.alpha_shift;
1355     image_masks.red_mask =
1356         (unsigned long) format->direct.red_mask << format->direct.red_shift;
1357     image_masks.green_mask =
1358         (unsigned long) format->direct.green_mask << format->direct.green_shift;
1359     image_masks.blue_mask =
1360         (unsigned long) format->direct.blue_mask << format->direct.blue_shift;
1361 #if 0
1362     image_masks.bpp = format->depth;
1363 #else
1364     if (format->depth > 16)
1365         image_masks.bpp = 32;
1366     else if (format->depth > 8)
1367         image_masks.bpp = 16;
1368     else if (format->depth > 1)
1369         image_masks.bpp = 8;
1370     else
1371         image_masks.bpp = 1;
1372 #endif
1373
1374     if (! _pixman_format_from_masks (&image_masks, &pixman_format))
1375         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1376
1377     cairo_xcb_screen = _cairo_xcb_screen_get (connection, screen);
1378     if (unlikely (cairo_xcb_screen == NULL))
1379         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1380
1381     return _cairo_xcb_surface_create_internal (cairo_xcb_screen,
1382                                                drawable,
1383                                                FALSE,
1384                                                pixman_format,
1385                                                format->id,
1386                                                width, height);
1387 }
1388 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1389 slim_hidden_def (cairo_xcb_surface_create_with_xrender_format);
1390 #endif
1391
1392 /* This does the necessary fixup when a surface's drawable or size changed. */
1393 static void
1394 _drawable_changed (cairo_xcb_surface_t *surface)
1395 {
1396     _cairo_surface_set_error (&surface->base,
1397             _cairo_surface_begin_modification (&surface->base));
1398     _cairo_boxes_clear (&surface->fallback_damage);
1399     cairo_surface_destroy (&surface->fallback->base);
1400
1401     surface->deferred_clear = FALSE;
1402     surface->fallback = NULL;
1403 }
1404
1405 /**
1406  * cairo_xcb_surface_set_size:
1407  * @surface: a #cairo_surface_t for the XCB backend
1408  * @width: the new width of the surface
1409  * @height: the new height of the surface
1410  *
1411  * Informs cairo of the new size of the XCB drawable underlying the
1412  * surface. For a surface created for a window (rather than a pixmap),
1413  * this function must be called each time the size of the window
1414  * changes. (For a subwindow, you are normally resizing the window
1415  * yourself, but for a toplevel window, it is necessary to listen for
1416  * ConfigureNotify events.)
1417  *
1418  * A pixmap can never change size, so it is never necessary to call
1419  * this function on a surface created for a pixmap.
1420  *
1421  * If cairo_surface_flush() wasn't called, some pending operations
1422  * might be discarded.
1423  *
1424  * Since: 1.12
1425  **/
1426 void
1427 cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface,
1428                             int              width,
1429                             int              height)
1430 {
1431     cairo_xcb_surface_t *surface;
1432
1433     if (unlikely (abstract_surface->status))
1434         return;
1435     if (unlikely (abstract_surface->finished)) {
1436         _cairo_surface_set_error (abstract_surface,
1437                                   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1438         return;
1439     }
1440
1441
1442     if (abstract_surface->type != CAIRO_SURFACE_TYPE_XCB) {
1443         _cairo_surface_set_error (abstract_surface,
1444                                   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1445         return;
1446     }
1447
1448     if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX || width <= 0 || height <= 0) {
1449         _cairo_surface_set_error (abstract_surface,
1450                                   _cairo_error (CAIRO_STATUS_INVALID_SIZE));
1451         return;
1452     }
1453
1454     surface = (cairo_xcb_surface_t *) abstract_surface;
1455
1456     _drawable_changed(surface);
1457     surface->width  = width;
1458     surface->height = height;
1459 }
1460 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1461 slim_hidden_def (cairo_xcb_surface_set_size);
1462 #endif
1463
1464 /**
1465  * cairo_xcb_surface_set_drawable:
1466  * @surface: a #cairo_surface_t for the XCB backend
1467  * @drawable: the new drawable of the surface
1468  * @width: the new width of the surface
1469  * @height: the new height of the surface
1470  *
1471  * Informs cairo of the new drawable and size of the XCB drawable underlying the
1472  * surface.
1473  *
1474  * If cairo_surface_flush() wasn't called, some pending operations
1475  * might be discarded.
1476  *
1477  * Since: 1.12
1478  **/
1479 void
1480 cairo_xcb_surface_set_drawable (cairo_surface_t *abstract_surface,
1481                                 xcb_drawable_t  drawable,
1482                                 int             width,
1483                                 int             height)
1484 {
1485     cairo_xcb_surface_t *surface;
1486
1487     if (unlikely (abstract_surface->status))
1488         return;
1489     if (unlikely (abstract_surface->finished)) {
1490         _cairo_surface_set_error (abstract_surface,
1491                                   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1492         return;
1493     }
1494
1495
1496     if (abstract_surface->type != CAIRO_SURFACE_TYPE_XCB) {
1497         _cairo_surface_set_error (abstract_surface,
1498                                   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1499         return;
1500     }
1501
1502     if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX || width <= 0 || height <= 0) {
1503         _cairo_surface_set_error (abstract_surface,
1504                                   _cairo_error (CAIRO_STATUS_INVALID_SIZE));
1505         return;
1506     }
1507
1508     surface = (cairo_xcb_surface_t *) abstract_surface;
1509
1510     /* XXX: and what about this case? */
1511     if (surface->owns_pixmap)
1512             return;
1513
1514     _drawable_changed (surface);
1515
1516     if (surface->drawable != drawable) {
1517             cairo_status_t status;
1518             status = _cairo_xcb_connection_acquire (surface->connection);
1519             if (unlikely (status))
1520                     return;
1521
1522             if (surface->picture != XCB_NONE) {
1523                     _cairo_xcb_connection_render_free_picture (surface->connection,
1524                                                                surface->picture);
1525                     surface->picture = XCB_NONE;
1526             }
1527
1528             _cairo_xcb_connection_release (surface->connection);
1529
1530             surface->drawable = drawable;
1531     }
1532     surface->width  = width;
1533     surface->height = height;
1534 }
1535 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1536 slim_hidden_def (cairo_xcb_surface_set_drawable);
1537 #endif