Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* cairo - a vector graphics library with display and print output
  2.  *
  3.  * Copyright © 2009 Intel Corporation
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it either under the terms of the GNU Lesser General Public
  7.  * License version 2.1 as published by the Free Software Foundation
  8.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  9.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  10.  * notice, a recipient may use your version of this file under either
  11.  * the MPL or the LGPL.
  12.  *
  13.  * You should have received a copy of the LGPL along with this library
  14.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  15.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  16.  * You should have received a copy of the MPL along with this library
  17.  * in the file COPYING-MPL-1.1
  18.  *
  19.  * The contents of this file are subject to the Mozilla Public License
  20.  * Version 1.1 (the "License"); you may not use this file except in
  21.  * compliance with the License. You may obtain a copy of the License at
  22.  * http://www.mozilla.org/MPL/
  23.  *
  24.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  25.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  26.  * the specific language governing rights and limitations.
  27.  *
  28.  * Contributor(s):
  29.  *      Chris Wilson <chris@chris-wilson.co.uk>
  30.  */
  31.  
  32. #include "cairoint.h"
  33.  
  34. #include "cairo-boxes-private.h"
  35. #include "cairo-xcb-private.h"
  36. #include "cairo-image-surface-private.h"
  37. #include "cairo-surface-backend-private.h"
  38.  
  39. /* XXX dithering */
  40.  
  41. typedef struct _cairo_xcb_pixmap {
  42.     cairo_surface_t base;
  43.  
  44.     cairo_xcb_connection_t *connection;
  45.     cairo_xcb_screen_t *screen;
  46.  
  47.     cairo_surface_t *owner;
  48.     xcb_pixmap_t pixmap;
  49.     int width;
  50.     int height;
  51.     int depth;
  52.     int x0, y0;
  53.     cairo_bool_t repeat;
  54. } cairo_xcb_pixmap_t;
  55.  
  56. static cairo_status_t
  57. _cairo_xcb_pixmap_finish (void *abstract_surface)
  58. {
  59.     cairo_xcb_pixmap_t *surface = abstract_surface;
  60.     cairo_status_t status;
  61.  
  62.     if (surface->owner != NULL) {
  63.         cairo_surface_destroy (surface->owner);
  64.     } else {
  65.         status = _cairo_xcb_connection_acquire (surface->connection);
  66.         if (unlikely (status))
  67.             return status;
  68.  
  69.         _cairo_xcb_connection_free_pixmap (surface->connection,
  70.                                            surface->pixmap);
  71.         _cairo_xcb_connection_release (surface->connection);
  72.     }
  73.  
  74.     return CAIRO_STATUS_SUCCESS;
  75. }
  76.  
  77. static const cairo_surface_backend_t _cairo_xcb_pixmap_backend = {
  78.     CAIRO_SURFACE_TYPE_XCB,
  79.     _cairo_xcb_pixmap_finish,
  80. };
  81.  
  82. static cairo_xcb_pixmap_t *
  83. _cairo_xcb_pixmap_create (cairo_xcb_surface_t *target,
  84.                           int width, int height)
  85. {
  86.     cairo_xcb_pixmap_t *surface;
  87.  
  88.     surface = malloc (sizeof (cairo_xcb_pixmap_t));
  89.     if (unlikely (surface == NULL))
  90.         return (cairo_xcb_pixmap_t *)
  91.             _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
  92.  
  93.     _cairo_surface_init (&surface->base,
  94.                          &_cairo_xcb_pixmap_backend,
  95.                          NULL,
  96.                          target->base.content);
  97.  
  98.     surface->connection = target->connection;
  99.     surface->screen = target->screen;
  100.     surface->owner = NULL;
  101.     surface->width = width;
  102.     surface->height = height;
  103.     surface->depth = target->depth;
  104.     surface->x0 = surface->y0 = 0;
  105.     surface->repeat = FALSE;
  106.  
  107.     surface->pixmap =
  108.         _cairo_xcb_connection_create_pixmap (surface->connection,
  109.                                              surface->depth,
  110.                                              target->drawable,
  111.                                              width, height);
  112.  
  113.     return surface;
  114. }
  115.  
  116. static cairo_xcb_pixmap_t *
  117. _cairo_xcb_pixmap_copy (cairo_xcb_surface_t *target)
  118. {
  119.     cairo_xcb_pixmap_t *surface;
  120.  
  121.     surface = malloc (sizeof (cairo_xcb_pixmap_t));
  122.     if (unlikely (surface == NULL))
  123.         return (cairo_xcb_pixmap_t *)
  124.             _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
  125.  
  126.     _cairo_surface_init (&surface->base,
  127.                          &_cairo_xcb_pixmap_backend,
  128.                          NULL,
  129.                          target->base.content);
  130.  
  131.     surface->connection = target->connection;
  132.     surface->screen = target->screen;
  133.     surface->pixmap = target->drawable;
  134.     surface->owner = cairo_surface_reference (&target->base);
  135.     surface->width = target->width;
  136.     surface->height = target->height;
  137.     surface->depth = target->depth;
  138.     surface->x0 = surface->y0 = 0;
  139.     surface->repeat = FALSE;
  140.  
  141.     return surface;
  142. }
  143.  
  144. #if CAIRO_HAS_XCB_SHM_FUNCTIONS
  145. static cairo_status_t
  146. _cairo_xcb_shm_image_create_shm (cairo_xcb_connection_t *connection,
  147.                                  pixman_format_code_t pixman_format,
  148.                                  int width, int height,
  149.                                  cairo_image_surface_t **image_out,
  150.                                  cairo_xcb_shm_info_t **shm_info_out)
  151. {
  152.     cairo_surface_t *image = NULL;
  153.     cairo_xcb_shm_info_t *shm_info = NULL;
  154.     cairo_status_t status;
  155.     size_t size, stride;
  156.  
  157.     if (! (connection->flags & CAIRO_XCB_HAS_SHM))
  158.         return CAIRO_INT_STATUS_UNSUPPORTED;
  159.  
  160.     if (unlikely (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX))
  161.         return CAIRO_INT_STATUS_UNSUPPORTED;
  162.  
  163.     stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width, PIXMAN_FORMAT_BPP (pixman_format));
  164.     size = stride * height;
  165.     if (size <= CAIRO_XCB_SHM_SMALL_IMAGE)
  166.         return CAIRO_INT_STATUS_UNSUPPORTED;
  167.  
  168.     status = _cairo_xcb_connection_allocate_shm_info (connection, size,
  169.                                                       FALSE, &shm_info);
  170.     if (unlikely (status))
  171.         return status;
  172.  
  173.     image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
  174.                                                             pixman_format,
  175.                                                             width, height,
  176.                                                             stride);
  177.     status = image->status;
  178.     if (unlikely (status)) {
  179.         _cairo_xcb_shm_info_destroy (shm_info);
  180.         return status;
  181.     }
  182.  
  183.     status = _cairo_user_data_array_set_data (&image->user_data,
  184.                                               (const cairo_user_data_key_t *) connection,
  185.                                               shm_info,
  186.                                               (cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
  187.  
  188.     if (unlikely (status)) {
  189.         cairo_surface_destroy (image);
  190.         _cairo_xcb_shm_info_destroy (shm_info);
  191.         return status;
  192.     }
  193.  
  194.     *image_out = (cairo_image_surface_t *) image;
  195.     *shm_info_out = shm_info;
  196.     return CAIRO_STATUS_SUCCESS;
  197. }
  198. #else
  199. static cairo_status_t
  200. _cairo_xcb_shm_image_create_shm (cairo_xcb_connection_t *connection,
  201.                                  pixman_format_code_t pixman_format,
  202.                                  int width, int height,
  203.                                  cairo_image_surface_t **image_out,
  204.                                  cairo_xcb_shm_info_t **shm_info_out)
  205. {
  206.     return CAIRO_INT_STATUS_UNSUPPORTED;
  207. }
  208. #endif
  209.  
  210. cairo_status_t
  211. _cairo_xcb_shm_image_create (cairo_xcb_connection_t *connection,
  212.                              pixman_format_code_t pixman_format,
  213.                              int width, int height,
  214.                              cairo_image_surface_t **image_out,
  215.                              cairo_xcb_shm_info_t **shm_info_out)
  216. {
  217.     cairo_surface_t *image = NULL;
  218.     cairo_xcb_shm_info_t *shm_info = NULL;
  219.     cairo_status_t status;
  220.  
  221.     status = _cairo_xcb_shm_image_create_shm (connection,
  222.                                               pixman_format,
  223.                                               width,
  224.                                               height,
  225.                                               image_out,
  226.                                               shm_info_out);
  227.  
  228.     if (status != CAIRO_STATUS_SUCCESS) {
  229.         image = _cairo_image_surface_create_with_pixman_format (NULL,
  230.                                                                 pixman_format,
  231.                                                                 width, height,
  232.                                                                 0);
  233.         status = image->status;
  234.         if (unlikely (status))
  235.             return status;
  236.  
  237.         *image_out = (cairo_image_surface_t *) image;
  238.         *shm_info_out = shm_info;
  239.     }
  240.  
  241.     return CAIRO_STATUS_SUCCESS;
  242. }
  243.  
  244. static cairo_xcb_pixmap_t *
  245. _pixmap_from_image (cairo_xcb_surface_t *target,
  246.                     xcb_render_pictformat_t format,
  247.                     cairo_image_surface_t *image,
  248.                     cairo_xcb_shm_info_t *shm_info)
  249. {
  250.     xcb_gcontext_t gc;
  251.     cairo_xcb_pixmap_t *pixmap;
  252.  
  253.     pixmap = _cairo_xcb_pixmap_create (target,
  254.                                        image->width,
  255.                                        image->height);
  256.     if (unlikely (pixmap->base.status))
  257.         return pixmap;
  258.  
  259.     gc = _cairo_xcb_screen_get_gc (target->screen, pixmap->pixmap, image->depth);
  260.  
  261.     if (shm_info != NULL) {
  262.         _cairo_xcb_connection_shm_put_image (target->connection,
  263.                                              pixmap->pixmap, gc,
  264.                                              image->width, image->height,
  265.                                              0, 0,
  266.                                              image->width, image->height,
  267.                                              0, 0,
  268.                                              image->depth,
  269.                                              shm_info->shm,
  270.                                              shm_info->offset);
  271.     } else {
  272.         int len;
  273.  
  274.         /* Do we need to trim the image? */
  275.         len = CAIRO_STRIDE_FOR_WIDTH_BPP (image->width,
  276.                                           PIXMAN_FORMAT_BPP (image->pixman_format));
  277.         if (len == image->stride) {
  278.             _cairo_xcb_connection_put_image (target->connection,
  279.                                              pixmap->pixmap, gc,
  280.                                              image->width, image->height,
  281.                                              0, 0,
  282.                                              image->depth,
  283.                                              image->stride,
  284.                                              image->data);
  285.         } else {
  286.             _cairo_xcb_connection_put_subimage (target->connection,
  287.                                                 pixmap->pixmap, gc,
  288.                                                 0, 0,
  289.                                                 image->width, image->height,
  290.                                                 PIXMAN_FORMAT_BPP (image->pixman_format) / 8,
  291.                                                 image->stride,
  292.                                                 0, 0,
  293.                                                 image->depth,
  294.                                                 image->data);
  295.  
  296.         }
  297.     }
  298.  
  299.     _cairo_xcb_screen_put_gc (target->screen, image->depth, gc);
  300.  
  301.     return pixmap;
  302. }
  303.  
  304. static cairo_xcb_pixmap_t *
  305. _render_to_pixmap (cairo_xcb_surface_t *target,
  306.                    const cairo_pattern_t *pattern,
  307.                    const cairo_rectangle_int_t *extents)
  308. {
  309.     cairo_image_surface_t *image;
  310.     cairo_xcb_shm_info_t *shm_info;
  311.     cairo_pattern_union_t copy;
  312.     cairo_status_t status;
  313.     cairo_xcb_pixmap_t *pixmap;
  314.  
  315.     status = _cairo_xcb_shm_image_create (target->screen->connection,
  316.                                           target->pixman_format,
  317.                                           extents->width, extents->height,
  318.                                           &image, &shm_info);
  319.     if (unlikely (status))
  320.         return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (status);
  321.  
  322.     _cairo_pattern_init_static_copy (&copy.base, pattern);
  323.     cairo_matrix_translate (&copy.base.matrix, -extents->x, -extents->y);
  324.     status = _cairo_surface_paint (&image->base,
  325.                                    CAIRO_OPERATOR_SOURCE,
  326.                                    &copy.base,
  327.                                    NULL);
  328.     if (unlikely (status)) {
  329.         cairo_surface_destroy (&image->base);
  330.         return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (status);
  331.     }
  332.  
  333.     pixmap = _pixmap_from_image (target, target->xrender_format, image, shm_info);
  334.     cairo_surface_destroy (&image->base);
  335.  
  336.     if (unlikely (pixmap->base.status))
  337.         return pixmap;
  338.  
  339.     pixmap->x0 = -extents->x;
  340.     pixmap->y0 = -extents->y;
  341.     return pixmap;
  342. }
  343.  
  344. static cairo_xcb_pixmap_t *
  345. _copy_to_pixmap (cairo_xcb_surface_t *source)
  346. {
  347.     cairo_xcb_pixmap_t *pixmap;
  348.  
  349.     /* If the source may be a window, we need to copy it and its children
  350.      * via a temporary pixmap so that we can IncludeInferiors on the source
  351.      * and use ClipByChildren on the destination.
  352.      */
  353.     if (source->owns_pixmap) {
  354.         pixmap = _cairo_xcb_pixmap_copy (source);
  355.         if (unlikely (pixmap->base.status))
  356.             return pixmap;
  357.     } else {
  358.         uint32_t values[1];
  359.         xcb_gcontext_t gc;
  360.  
  361.         pixmap = _cairo_xcb_pixmap_create (source,
  362.                                            source->width,
  363.                                            source->height);
  364.         if (unlikely (pixmap->base.status))
  365.             return pixmap;
  366.  
  367.         gc = _cairo_xcb_screen_get_gc (source->screen,
  368.                                        pixmap->pixmap,
  369.                                        pixmap->depth);
  370.  
  371.         values[0] = TRUE;
  372.         _cairo_xcb_connection_change_gc (pixmap->connection, gc,
  373.                                          XCB_GC_SUBWINDOW_MODE, values);
  374.  
  375.         _cairo_xcb_connection_copy_area (pixmap->connection,
  376.                                          source->drawable,
  377.                                          pixmap->pixmap, gc,
  378.                                          0, 0,
  379.                                          0, 0,
  380.                                          source->width,
  381.                                          source->height);
  382.  
  383.         values[0] = FALSE;
  384.         _cairo_xcb_connection_change_gc (pixmap->connection, gc,
  385.                                          XCB_GC_SUBWINDOW_MODE, values);
  386.  
  387.         _cairo_xcb_screen_put_gc (source->screen,
  388.                                   pixmap->depth,
  389.                                   gc);
  390.     }
  391.  
  392.     return pixmap;
  393. }
  394. static cairo_xcb_pixmap_t *
  395. _cairo_xcb_surface_pixmap (cairo_xcb_surface_t *target,
  396.                            const cairo_surface_pattern_t *pattern,
  397.                            const cairo_rectangle_int_t *extents,
  398.                            int tx, int ty)
  399. {
  400.     cairo_surface_t *source;
  401.     cairo_xcb_pixmap_t *pixmap;
  402.  
  403.     source =  pattern->surface;
  404.     pixmap = (cairo_xcb_pixmap_t *)
  405.         _cairo_surface_has_snapshot (source, &_cairo_xcb_pixmap_backend);
  406.     if (pixmap != NULL && pixmap->screen == target->screen)
  407.         return (cairo_xcb_pixmap_t *) cairo_surface_reference (&pixmap->base);
  408.  
  409.     if (source->type == CAIRO_SURFACE_TYPE_XCB &&
  410.         ((cairo_xcb_surface_t *) source)->screen == target->screen)
  411.     {
  412.         cairo_xcb_surface_t *xcb_source = (cairo_xcb_surface_t *) source;
  413.  
  414.         if (xcb_source->depth == target->depth)
  415.             pixmap = _copy_to_pixmap (xcb_source);
  416.     }
  417. #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
  418.     else if (source->type == CAIRO_SURFACE_TYPE_XLIB &&
  419.              ((cairo_xlib_xcb_surface_t *) source)->xcb->screen == target->screen)
  420.     {
  421.         cairo_xcb_surface_t *xcb_source = ((cairo_xlib_xcb_surface_t *) source)->xcb;
  422.  
  423.         if (xcb_source->depth == target->depth)
  424.             pixmap = _copy_to_pixmap (xcb_source);
  425.     }
  426. #endif
  427.  
  428.     if (pixmap == NULL) {
  429.         cairo_rectangle_int_t rect;
  430.  
  431.         if (! _cairo_surface_get_extents (source, &rect)) {
  432.             rect.x = rect.y = 0;
  433.             rect.width  = target->width;
  434.             rect.height = target->height;
  435.         }
  436.  
  437.         pixmap = _render_to_pixmap (target, &pattern->base, &rect);
  438.     }
  439.  
  440.     if (unlikely (pixmap->base.status))
  441.         return pixmap;
  442.  
  443.     _cairo_surface_attach_snapshot (source, &pixmap->base, NULL);
  444.  
  445.     if (pattern->base.extend != CAIRO_EXTEND_NONE) {
  446.         if (extents->x < 0 || extents->y < 0 ||
  447.             extents->x + extents->width  > pixmap->width ||
  448.             extents->y + extents->height > pixmap->height)
  449.         {
  450.             pixmap->repeat = TRUE;
  451.         }
  452.     }
  453.  
  454.     pixmap->x0 += tx;
  455.     pixmap->y0 += ty;
  456.  
  457.     return pixmap;
  458. }
  459.  
  460. static cairo_xcb_pixmap_t *
  461. _cairo_xcb_pixmap_for_pattern (cairo_xcb_surface_t *target,
  462.                                const cairo_pattern_t *pattern,
  463.                                const cairo_rectangle_int_t *extents)
  464. {
  465.     int tx, ty;
  466.  
  467.     switch (pattern->type) {
  468.     case CAIRO_PATTERN_TYPE_SURFACE:
  469.         /* Core can only perform a native, unscaled blit, but can handle tiles */
  470.         if (_cairo_matrix_is_integer_translation (&pattern->matrix, &tx, &ty)) {
  471.             switch (pattern->extend) {
  472.             case CAIRO_EXTEND_NONE:
  473.             case CAIRO_EXTEND_REPEAT:
  474.                 return _cairo_xcb_surface_pixmap (target,
  475.                                                   (cairo_surface_pattern_t *) pattern,
  476.                                                   extents, tx, ty);
  477.  
  478.             default:
  479.             case CAIRO_EXTEND_PAD:
  480.             case CAIRO_EXTEND_REFLECT:
  481.                 break;
  482.             }
  483.         }
  484.         /* fallthrough */
  485.     case CAIRO_PATTERN_TYPE_LINEAR:
  486.     case CAIRO_PATTERN_TYPE_RADIAL:
  487.     case CAIRO_PATTERN_TYPE_MESH:
  488.     case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
  489.         return _render_to_pixmap (target, pattern, extents);
  490.  
  491.     default:
  492.     case CAIRO_PATTERN_TYPE_SOLID:
  493.         ASSERT_NOT_REACHED;
  494.         return NULL;
  495.     }
  496. }
  497.  
  498. cairo_status_t
  499. _cairo_xcb_surface_core_copy_boxes (cairo_xcb_surface_t         *dst,
  500.                                    const cairo_pattern_t        *src_pattern,
  501.                                    const cairo_rectangle_int_t  *extents,
  502.                                    const cairo_boxes_t          *boxes)
  503. {
  504.     cairo_xcb_pixmap_t *src;
  505.     const struct _cairo_boxes_chunk *chunk;
  506.     xcb_gcontext_t gc;
  507.     cairo_status_t status;
  508.  
  509.     status = _cairo_xcb_connection_acquire (dst->connection);
  510.     if (unlikely (status))
  511.         return status;
  512.  
  513.     src = _cairo_xcb_pixmap_for_pattern (dst, src_pattern, extents);
  514.     status = src->base.status;
  515.     if (unlikely (status))
  516.         goto CLEANUP_CONNECTION;
  517.  
  518.     assert (src->depth == dst->depth);
  519.  
  520.     gc = _cairo_xcb_screen_get_gc (dst->screen, src->pixmap, src->depth);
  521.  
  522.     if (src->repeat) {
  523.         uint32_t mask =
  524.             XCB_GC_FILL_STYLE |
  525.             XCB_GC_TILE |
  526.             XCB_GC_TILE_STIPPLE_ORIGIN_X |
  527.             XCB_GC_TILE_STIPPLE_ORIGIN_Y;
  528.         uint32_t values[] = {
  529.             XCB_FILL_STYLE_TILED,
  530.             src->pixmap,
  531.             - src->x0, - src->y0,
  532.         };
  533.         xcb_rectangle_t *xcb_rects;
  534.  
  535.         _cairo_xcb_connection_change_gc (dst->connection, gc, mask, values);
  536.  
  537.         for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
  538.             int i;
  539.  
  540.             xcb_rects = (xcb_rectangle_t *) chunk->base;
  541.  
  542.             for (i = 0; i < chunk->count; i++) {
  543.                 int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
  544.                 int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
  545.                 int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
  546.                 int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);
  547.  
  548.                 xcb_rects[i].x = x1;
  549.                 xcb_rects[i].y = y1;
  550.                 xcb_rects[i].width  = x2 - x1;
  551.                 xcb_rects[i].height = y2 - y1;
  552.             }
  553.             _cairo_xcb_connection_poly_fill_rectangle (dst->connection,
  554.                                                        dst->drawable,
  555.                                                        gc, chunk->count, xcb_rects);
  556.         }
  557.  
  558.         values[0] = 0;
  559.         _cairo_xcb_connection_change_gc (dst->connection, gc, XCB_GC_FILL_STYLE, values);
  560.     } else {
  561.         for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
  562.             int i;
  563.  
  564.             for (i = 0; i < chunk->count; i++) {
  565.                 int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
  566.                 int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
  567.                 int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
  568.                 int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);
  569.  
  570.                 _cairo_xcb_connection_copy_area (dst->connection,
  571.                                                  src->pixmap,
  572.                                                  dst->drawable, gc,
  573.                                                  src->x0 + x1,
  574.                                                  src->y0 + y1,
  575.                                                  x1, y1,
  576.                                                  x2 - x2, y2 - x2);
  577.             }
  578.         }
  579.     }
  580.  
  581.     _cairo_xcb_screen_put_gc (dst->screen, src->depth, gc);
  582.     cairo_surface_destroy (&src->base);
  583.  
  584.   CLEANUP_CONNECTION:
  585.     _cairo_xcb_connection_release (dst->connection);
  586.  
  587.     return status;
  588. }
  589.  
  590. cairo_status_t
  591. _cairo_xcb_surface_core_fill_boxes (cairo_xcb_surface_t *dst,
  592.                                     const cairo_color_t *color,
  593.                                     cairo_boxes_t *boxes)
  594. {
  595.     struct _cairo_boxes_chunk *chunk;
  596.     xcb_gcontext_t gc;
  597.     cairo_status_t status;
  598.  
  599.     status = _cairo_xcb_connection_acquire (dst->connection);
  600.     if (unlikely (status))
  601.         return status;
  602.  
  603.     gc = _cairo_xcb_screen_get_gc (dst->screen, dst->drawable, dst->depth);
  604.  
  605. #if 0
  606.     xcb_pixmap_t source;
  607.  
  608.     source = _dither_source (dst, color);
  609.     XSetTSOrigin (surface->dpy, gc, 0, 0);
  610.     XSetTile (surface->dpy, gc, source);
  611. #endif
  612.  
  613.     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
  614.         xcb_rectangle_t *xcb_rects;
  615.         int i;
  616.  
  617.         xcb_rects = (xcb_rectangle_t *) chunk->base;
  618.         for (i = 0; i < chunk->count; i++) {
  619.             int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
  620.             int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
  621.             int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
  622.             int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);
  623.  
  624.             xcb_rects[i].x = x1;
  625.             xcb_rects[i].y = y1;
  626.             xcb_rects[i].width  = x2 - x1;
  627.             xcb_rects[i].height = y2 - y1;
  628.         }
  629.  
  630.         _cairo_xcb_connection_poly_fill_rectangle (dst->connection,
  631.                                                    dst->drawable, gc,
  632.                                                    chunk->count, xcb_rects);
  633.     }
  634.  
  635.     _cairo_xcb_screen_put_gc (dst->screen, dst->depth, gc);
  636.     _cairo_xcb_connection_release (dst->connection);
  637.  
  638.     return CAIRO_STATUS_SUCCESS;
  639. }
  640.