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-xcb-private.h"
  35.  
  36. #include <xcb/xcbext.h>
  37.  
  38. xcb_pixmap_t
  39. _cairo_xcb_connection_create_pixmap (cairo_xcb_connection_t *connection,
  40.                                      uint8_t depth,
  41.                                      xcb_drawable_t drawable,
  42.                                      uint16_t width,
  43.                                      uint16_t height)
  44. {
  45.     xcb_pixmap_t pixmap = _cairo_xcb_connection_get_xid (connection);
  46.  
  47.     assert (width > 0);
  48.     assert (height > 0);
  49.     xcb_create_pixmap (connection->xcb_connection,
  50.                        depth, pixmap, drawable,
  51.                        width, height);
  52.     return pixmap;
  53. }
  54.  
  55. void
  56. _cairo_xcb_connection_free_pixmap (cairo_xcb_connection_t *connection,
  57.                                    xcb_pixmap_t pixmap)
  58. {
  59.     xcb_free_pixmap (connection->xcb_connection, pixmap);
  60.     _cairo_xcb_connection_put_xid (connection, pixmap);
  61. }
  62.  
  63. xcb_gcontext_t
  64. _cairo_xcb_connection_create_gc (cairo_xcb_connection_t *connection,
  65.                                  xcb_drawable_t drawable,
  66.                                  uint32_t value_mask,
  67.                                  uint32_t *values)
  68. {
  69.     xcb_gcontext_t gc = _cairo_xcb_connection_get_xid (connection);
  70.     xcb_create_gc (connection->xcb_connection, gc, drawable,
  71.                    value_mask, values);
  72.     return gc;
  73. }
  74.  
  75. void
  76. _cairo_xcb_connection_free_gc (cairo_xcb_connection_t *connection,
  77.                                xcb_gcontext_t gc)
  78. {
  79.     xcb_free_gc (connection->xcb_connection, gc);
  80.     _cairo_xcb_connection_put_xid (connection, gc);
  81. }
  82.  
  83. void
  84. _cairo_xcb_connection_change_gc (cairo_xcb_connection_t *connection,
  85.                                  xcb_gcontext_t gc,
  86.                                  uint32_t value_mask,
  87.                                  uint32_t *values)
  88. {
  89.     xcb_change_gc (connection->xcb_connection, gc,
  90.                    value_mask, values);
  91. }
  92.  
  93. void
  94. _cairo_xcb_connection_copy_area (cairo_xcb_connection_t *connection,
  95.                                  xcb_drawable_t src,
  96.                                  xcb_drawable_t dst,
  97.                                  xcb_gcontext_t gc,
  98.                                  int16_t src_x,
  99.                                  int16_t src_y,
  100.                                  int16_t dst_x,
  101.                                  int16_t dst_y,
  102.                                  uint16_t width,
  103.                                  uint16_t height)
  104. {
  105.     xcb_copy_area (connection->xcb_connection, src, dst, gc,
  106.                    src_x, src_y, dst_x, dst_y, width, height);
  107. }
  108.  
  109. void
  110. _cairo_xcb_connection_poly_fill_rectangle (cairo_xcb_connection_t *connection,
  111.                                            xcb_drawable_t dst,
  112.                                            xcb_gcontext_t gc,
  113.                                            uint32_t num_rectangles,
  114.                                            xcb_rectangle_t *rectangles)
  115. {
  116.     xcb_poly_fill_rectangle (connection->xcb_connection, dst, gc,
  117.                              num_rectangles, rectangles);
  118. }
  119.  
  120. void
  121. _cairo_xcb_connection_put_image (cairo_xcb_connection_t *connection,
  122.                                  xcb_drawable_t dst,
  123.                                  xcb_gcontext_t gc,
  124.                                  uint16_t width,
  125.                                  uint16_t height,
  126.                                  int16_t dst_x,
  127.                                  int16_t dst_y,
  128.                                  uint8_t depth,
  129.                                  uint32_t stride,
  130.                                  void *data)
  131. {
  132.     const uint32_t req_size = 18;
  133.     uint32_t length = height * stride;
  134.     uint32_t len = (req_size + length) >> 2;
  135.  
  136.     if (len < connection->maximum_request_length) {
  137.         xcb_put_image (connection->xcb_connection, XCB_IMAGE_FORMAT_Z_PIXMAP,
  138.                        dst, gc, width, height, dst_x, dst_y, 0, depth,
  139.                        length, data);
  140.     } else {
  141.         int rows = (connection->maximum_request_length - req_size - 4) / stride;
  142.         if (rows > 0) {
  143.             do {
  144.                 if (rows > height)
  145.                     rows = height;
  146.  
  147.                 length = rows * stride;
  148.  
  149.                 xcb_put_image (connection->xcb_connection, XCB_IMAGE_FORMAT_Z_PIXMAP,
  150.                                dst, gc, width, rows, dst_x, dst_y, 0, depth, length, data);
  151.  
  152.                 height -= rows;
  153.                 dst_y += rows;
  154.                 data = (char *) data + length;
  155.             } while (height);
  156.         } else {
  157.             ASSERT_NOT_REACHED;
  158.         }
  159.     }
  160. }
  161.  
  162. static void
  163. _cairo_xcb_connection_do_put_subimage (cairo_xcb_connection_t *connection,
  164.                                        xcb_drawable_t dst,
  165.                                        xcb_gcontext_t gc,
  166.                                        int16_t src_x,
  167.                                        int16_t src_y,
  168.                                        uint16_t width,
  169.                                        uint16_t height,
  170.                                        uint16_t cpp,
  171.                                        int stride,
  172.                                        int16_t dst_x,
  173.                                        int16_t dst_y,
  174.                                        uint8_t depth,
  175.                                        void *_data)
  176. {
  177.     xcb_protocol_request_t xcb_req = {
  178.         0 /* count */,
  179.         0 /* ext */,
  180.         XCB_PUT_IMAGE /* opcode */,
  181.         1 /* isvoid (doesn't cause a reply) */
  182.     };
  183.     xcb_put_image_request_t req;
  184.     struct iovec vec_stack[CAIRO_STACK_ARRAY_LENGTH (struct iovec)];
  185.     struct iovec *vec = vec_stack;
  186.     uint32_t len = 0;
  187.     uint8_t *data = _data;
  188.     int n = 3;
  189.     /* Two extra entries are needed for xcb, two for us */
  190.     int entries_needed = height + 2 + 2;
  191.  
  192.     req.format = XCB_IMAGE_FORMAT_Z_PIXMAP;
  193.     req.drawable = dst;
  194.     req.gc = gc;
  195.     req.width = width;
  196.     req.height = height;
  197.     req.dst_x = dst_x;
  198.     req.dst_y = dst_y;
  199.     req.left_pad = 0;
  200.     req.depth = depth;
  201.     req.pad0[0] = 0;
  202.     req.pad0[1] = 0;
  203.  
  204.     if (entries_needed > ARRAY_LENGTH (vec_stack)) {
  205.         vec = _cairo_malloc_ab (entries_needed, sizeof (struct iovec));
  206.         if (unlikely (vec == NULL)) {
  207.             /* XXX loop over ARRAY_LENGTH (vec_stack) */
  208.             return;
  209.         }
  210.     }
  211.  
  212.     data += src_y * stride + src_x * cpp;
  213.     /* vec[1] will be used in XCB if it has to use BigRequests or insert a sync,
  214.      * vec[0] is used if the internal queue needs to be flushed. */
  215.     vec[2].iov_base = (char *) &req;
  216.     vec[2].iov_len = sizeof (req);
  217.  
  218.     /* Now comes the actual data */
  219.     while (height--) {
  220.         vec[n].iov_base = data;
  221.         vec[n].iov_len = cpp * width;
  222.         len += cpp * width;
  223.         data += stride;
  224.         n++;
  225.     }
  226.  
  227.     /* And again some padding */
  228.     vec[n].iov_base = 0;
  229.     vec[n].iov_len = -len & 3;
  230.     n++;
  231.  
  232.     /* For efficiency reasons, this functions writes the request "directly" to
  233.      * the xcb connection to avoid having to copy the data around. */
  234.     assert (n == entries_needed);
  235.     xcb_req.count = n - 2;
  236.     xcb_send_request (connection->xcb_connection, 0, &vec[2], &xcb_req);
  237.  
  238.     if (vec != vec_stack)
  239.         free (vec);
  240. }
  241.  
  242. void
  243. _cairo_xcb_connection_put_subimage (cairo_xcb_connection_t *connection,
  244.                                     xcb_drawable_t dst,
  245.                                     xcb_gcontext_t gc,
  246.                                     int16_t src_x,
  247.                                     int16_t src_y,
  248.                                     uint16_t width,
  249.                                     uint16_t height,
  250.                                     uint16_t cpp,
  251.                                     int stride,
  252.                                     int16_t dst_x,
  253.                                     int16_t dst_y,
  254.                                     uint8_t depth,
  255.                                     void *_data)
  256. {
  257.     const uint32_t req_size = sizeof(xcb_put_image_request_t);
  258.     uint32_t length = height * cpp * width;
  259.     uint32_t len = (req_size + length) >> 2;
  260.  
  261.     if (len < connection->maximum_request_length) {
  262.         _cairo_xcb_connection_do_put_subimage (connection, dst, gc, src_x, src_y,
  263.                         width, height, cpp, stride, dst_x, dst_y, depth, _data);
  264.     } else {
  265.         int rows = (connection->maximum_request_length - req_size - 4) / (cpp * width);
  266.         if (rows > 0) {
  267.             do {
  268.                 if (rows > height)
  269.                     rows = height;
  270.  
  271.                 length = rows * cpp * width;
  272.  
  273.                 _cairo_xcb_connection_do_put_subimage (connection, dst, gc, src_x, src_y,
  274.                         width, rows, cpp, stride, dst_x, dst_y, depth, _data);
  275.  
  276.                 height -= rows;
  277.                 dst_y += rows;
  278.                 _data = (char *) _data + stride * rows;
  279.             } while (height);
  280.         } else {
  281.             ASSERT_NOT_REACHED;
  282.         }
  283.     }
  284. }
  285.  
  286. cairo_status_t
  287. _cairo_xcb_connection_get_image (cairo_xcb_connection_t *connection,
  288.                                  xcb_drawable_t src,
  289.                                  int16_t src_x,
  290.                                  int16_t src_y,
  291.                                  uint16_t width,
  292.                                  uint16_t height,
  293.                                  xcb_get_image_reply_t **reply)
  294. {
  295.     xcb_generic_error_t *error;
  296.  
  297.     *reply = xcb_get_image_reply (connection->xcb_connection,
  298.                                   xcb_get_image (connection->xcb_connection,
  299.                                                  XCB_IMAGE_FORMAT_Z_PIXMAP,
  300.                                                  src,
  301.                                                  src_x, src_y,
  302.                                                  width, height,
  303.                                                  (uint32_t) -1),
  304.  
  305.                                   &error);
  306.     if (error) {
  307.         free (error);
  308.  
  309.         free (*reply);
  310.         *reply = NULL;
  311.     }
  312.  
  313.     return CAIRO_STATUS_SUCCESS;
  314. }
  315.