Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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
  1538.