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 © 2002 University of Southern California
  4.  * Copyright © 2009 Intel Corporation
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it either under the terms of the GNU Lesser General Public
  8.  * License version 2.1 as published by the Free Software Foundation
  9.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  10.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  11.  * notice, a recipient may use your version of this file under either
  12.  * the MPL or the LGPL.
  13.  *
  14.  * You should have received a copy of the LGPL along with this library
  15.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  17.  * You should have received a copy of the MPL along with this library
  18.  * in the file COPYING-MPL-1.1
  19.  *
  20.  * The contents of this file are subject to the Mozilla Public License
  21.  * Version 1.1 (the "License"); you may not use this file except in
  22.  * compliance with the License. You may obtain a copy of the License at
  23.  * http://www.mozilla.org/MPL/
  24.  *
  25.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  26.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  27.  * the specific language governing rights and limitations.
  28.  *
  29.  * The Original Code is the cairo graphics library.
  30.  *
  31.  * The Initial Developer of the Original Code is University of Southern
  32.  * California.
  33.  *
  34.  * Contributor(s):
  35.  *      Carl D. Worth <cworth@cworth.org>
  36.  *      Chris Wilson <chris@chris-wilson.co.uk>
  37.  */
  38.  
  39. #include "cairoint.h"
  40.  
  41. #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
  42.  
  43. #include "cairo-xlib.h"
  44. #include "cairo-xcb.h"
  45.  
  46. #include "cairo-xcb-private.h"
  47. #include "cairo-xlib-xrender-private.h"
  48.  
  49. #include "cairo-default-context-private.h"
  50. #include "cairo-list-inline.h"
  51. #include "cairo-image-surface-private.h"
  52. #include "cairo-surface-backend-private.h"
  53.  
  54. #include <X11/Xlib-xcb.h>
  55. #include <X11/Xlibint.h>        /* For XESetCloseDisplay */
  56.  
  57. struct cairo_xlib_xcb_display_t {
  58.     cairo_device_t  base;
  59.  
  60.     Display        *dpy;
  61.     cairo_device_t *xcb_device;
  62.     XExtCodes      *codes;
  63.  
  64.     cairo_list_t    link;
  65. };
  66. typedef struct cairo_xlib_xcb_display_t cairo_xlib_xcb_display_t;
  67.  
  68. /* List of all #cairo_xlib_xcb_display_t alive,
  69.  * protected by _cairo_xlib_display_mutex */
  70. static cairo_list_t displays;
  71.  
  72. static cairo_surface_t *
  73. _cairo_xlib_xcb_surface_create (void *dpy,
  74.                                 void *scr,
  75.                                 void *visual,
  76.                                 void *format,
  77.                                 cairo_surface_t *xcb);
  78.  
  79. static cairo_surface_t *
  80. _cairo_xlib_xcb_surface_create_similar (void                    *abstract_other,
  81.                                         cairo_content_t          content,
  82.                                         int                      width,
  83.                                         int                      height)
  84. {
  85.     cairo_xlib_xcb_surface_t *other = abstract_other;
  86.     cairo_surface_t *xcb;
  87.  
  88.     xcb = other->xcb->base.backend->create_similar (other->xcb, content, width, height);
  89.     if (unlikely (xcb == NULL || xcb->status))
  90.         return xcb;
  91.  
  92.     return _cairo_xlib_xcb_surface_create (other->display, other->screen, NULL, NULL, xcb);
  93. }
  94.  
  95. static cairo_status_t
  96. _cairo_xlib_xcb_surface_finish (void *abstract_surface)
  97. {
  98.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  99.     cairo_status_t status;
  100.  
  101.     cairo_surface_finish (&surface->xcb->base);
  102.     status = surface->xcb->base.status;
  103.     cairo_surface_destroy (&surface->xcb->base);
  104.     surface->xcb = NULL;
  105.  
  106.     return status;
  107. }
  108.  
  109. static cairo_surface_t *
  110. _cairo_xlib_xcb_surface_create_similar_image (void                      *abstract_other,
  111.                                               cairo_format_t             format,
  112.                                               int                        width,
  113.                                               int                        height)
  114. {
  115.     cairo_xlib_xcb_surface_t *surface = abstract_other;
  116.     return cairo_surface_create_similar_image (&surface->xcb->base, format, width, height);
  117. }
  118.  
  119. static cairo_image_surface_t *
  120. _cairo_xlib_xcb_surface_map_to_image (void *abstract_surface,
  121.                                       const cairo_rectangle_int_t *extents)
  122. {
  123.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  124.     return _cairo_surface_map_to_image (&surface->xcb->base, extents);
  125. }
  126.  
  127. static cairo_int_status_t
  128. _cairo_xlib_xcb_surface_unmap (void *abstract_surface,
  129.                                cairo_image_surface_t *image)
  130. {
  131.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  132.     return _cairo_surface_unmap_image (&surface->xcb->base, image);
  133. }
  134.  
  135. static cairo_surface_t *
  136. _cairo_xlib_xcb_surface_source (void *abstract_surface,
  137.                                 cairo_rectangle_int_t *extents)
  138. {
  139.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  140.     return _cairo_surface_get_source (&surface->xcb->base, extents);
  141. }
  142.  
  143. static cairo_status_t
  144. _cairo_xlib_xcb_surface_acquire_source_image (void *abstract_surface,
  145.                                               cairo_image_surface_t **image_out,
  146.                                               void **image_extra)
  147. {
  148.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  149.     return _cairo_surface_acquire_source_image (&surface->xcb->base,
  150.                                                 image_out, image_extra);
  151. }
  152.  
  153. static void
  154. _cairo_xlib_xcb_surface_release_source_image (void *abstract_surface,
  155.                                               cairo_image_surface_t *image_out,
  156.                                               void *image_extra)
  157. {
  158.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  159.     _cairo_surface_release_source_image (&surface->xcb->base, image_out, image_extra);
  160. }
  161.  
  162. static cairo_bool_t
  163. _cairo_xlib_xcb_surface_get_extents (void *abstract_surface,
  164.                                      cairo_rectangle_int_t *extents)
  165. {
  166.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  167.     return _cairo_surface_get_extents (&surface->xcb->base, extents);
  168. }
  169.  
  170. static void
  171. _cairo_xlib_xcb_surface_get_font_options (void *abstract_surface,
  172.                                           cairo_font_options_t *options)
  173. {
  174.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  175.     cairo_surface_get_font_options (&surface->xcb->base, options);
  176. }
  177.  
  178. static cairo_int_status_t
  179. _cairo_xlib_xcb_surface_paint (void                     *abstract_surface,
  180.                                cairo_operator_t          op,
  181.                                const cairo_pattern_t    *source,
  182.                                const cairo_clip_t       *clip)
  183. {
  184.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  185.     return _cairo_surface_paint (&surface->xcb->base, op, source, clip);
  186. }
  187.  
  188. static cairo_int_status_t
  189. _cairo_xlib_xcb_surface_mask (void                      *abstract_surface,
  190.                               cairo_operator_t           op,
  191.                               const cairo_pattern_t     *source,
  192.                               const cairo_pattern_t     *mask,
  193.                               const cairo_clip_t        *clip)
  194. {
  195.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  196.     return _cairo_surface_mask (&surface->xcb->base, op, source, mask, clip);
  197. }
  198.  
  199. static cairo_int_status_t
  200. _cairo_xlib_xcb_surface_stroke (void                            *abstract_surface,
  201.                                 cairo_operator_t                 op,
  202.                                 const cairo_pattern_t           *source,
  203.                                 const cairo_path_fixed_t        *path,
  204.                                 const cairo_stroke_style_t      *style,
  205.                                 const cairo_matrix_t            *ctm,
  206.                                 const cairo_matrix_t            *ctm_inverse,
  207.                                 double                           tolerance,
  208.                                 cairo_antialias_t                antialias,
  209.                                 const cairo_clip_t              *clip)
  210. {
  211.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  212.     return _cairo_surface_stroke (&surface->xcb->base,
  213.                                   op, source, path, style, ctm, ctm_inverse,
  214.                                   tolerance, antialias, clip);
  215. }
  216.  
  217. static cairo_int_status_t
  218. _cairo_xlib_xcb_surface_fill (void                      *abstract_surface,
  219.                               cairo_operator_t           op,
  220.                               const cairo_pattern_t     *source,
  221.                               const cairo_path_fixed_t  *path,
  222.                               cairo_fill_rule_t          fill_rule,
  223.                               double                     tolerance,
  224.                               cairo_antialias_t          antialias,
  225.                               const cairo_clip_t        *clip)
  226. {
  227.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  228.     return _cairo_surface_fill (&surface->xcb->base,
  229.                                 op, source, path,
  230.                                 fill_rule, tolerance,
  231.                                 antialias, clip);
  232. }
  233.  
  234. static cairo_int_status_t
  235. _cairo_xlib_xcb_surface_glyphs (void                    *abstract_surface,
  236.                                 cairo_operator_t         op,
  237.                                 const cairo_pattern_t   *source,
  238.                                 cairo_glyph_t           *glyphs,
  239.                                 int                      num_glyphs,
  240.                                 cairo_scaled_font_t     *scaled_font,
  241.                                 const cairo_clip_t      *clip)
  242. {
  243.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  244.     return _cairo_surface_show_text_glyphs (&surface->xcb->base, op, source,
  245.                                             NULL, 0,
  246.                                             glyphs, num_glyphs,
  247.                                             NULL, 0, 0,
  248.                                             scaled_font, clip);
  249. }
  250.  
  251. static cairo_status_t
  252. _cairo_xlib_xcb_surface_flush (void *abstract_surface, unsigned flags)
  253. {
  254.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  255.     /* We have to call cairo_surface_flush() to make sure snapshots are detached */
  256.     return _cairo_surface_flush (&surface->xcb->base, flags);
  257. }
  258.  
  259. static cairo_status_t
  260. _cairo_xlib_xcb_surface_mark_dirty (void *abstract_surface,
  261.                                     int x, int y,
  262.                                     int width, int height)
  263. {
  264.     cairo_xlib_xcb_surface_t *surface = abstract_surface;
  265.     cairo_surface_mark_dirty_rectangle (&surface->xcb->base, x, y, width, height);
  266.     return cairo_surface_status (&surface->xcb->base);
  267. }
  268.  
  269. static const cairo_surface_backend_t _cairo_xlib_xcb_surface_backend = {
  270.     CAIRO_SURFACE_TYPE_XLIB,
  271.     _cairo_xlib_xcb_surface_finish,
  272.  
  273.     _cairo_default_context_create, /* XXX */
  274.  
  275.     _cairo_xlib_xcb_surface_create_similar,
  276.     _cairo_xlib_xcb_surface_create_similar_image,
  277.     _cairo_xlib_xcb_surface_map_to_image,
  278.     _cairo_xlib_xcb_surface_unmap,
  279.  
  280.     _cairo_xlib_xcb_surface_source,
  281.     _cairo_xlib_xcb_surface_acquire_source_image,
  282.     _cairo_xlib_xcb_surface_release_source_image,
  283.     NULL, /* snapshot */
  284.  
  285.     NULL, /* copy_page */
  286.     NULL, /* show_page */
  287.  
  288.     _cairo_xlib_xcb_surface_get_extents,
  289.     _cairo_xlib_xcb_surface_get_font_options,
  290.  
  291.     _cairo_xlib_xcb_surface_flush,
  292.     _cairo_xlib_xcb_surface_mark_dirty,
  293.  
  294.     _cairo_xlib_xcb_surface_paint,
  295.     _cairo_xlib_xcb_surface_mask,
  296.     _cairo_xlib_xcb_surface_stroke,
  297.     _cairo_xlib_xcb_surface_fill,
  298.     NULL, /* fill_stroke */
  299.     _cairo_xlib_xcb_surface_glyphs,
  300. };
  301.  
  302. static void
  303. _cairo_xlib_xcb_display_finish (void *abstract_display)
  304. {
  305.     cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) abstract_display;
  306.  
  307.     CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
  308.     cairo_list_del (&display->link);
  309.     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
  310.  
  311.     cairo_device_destroy (display->xcb_device);
  312.     display->xcb_device = NULL;
  313.  
  314.     XESetCloseDisplay (display->dpy, display->codes->extension, NULL);
  315.     /* Drop the reference from _cairo_xlib_xcb_device_create */
  316.     cairo_device_destroy (&display->base);
  317. }
  318.  
  319. static int
  320. _cairo_xlib_xcb_close_display(Display *dpy, XExtCodes *codes)
  321. {
  322.     cairo_xlib_xcb_display_t *display;
  323.  
  324.     CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
  325.     cairo_list_foreach_entry (display,
  326.                               cairo_xlib_xcb_display_t,
  327.                               &displays,
  328.                               link)
  329.     {
  330.         if (display->dpy == dpy)
  331.         {
  332.             /* _cairo_xlib_xcb_display_finish will lock the mutex again
  333.              * -> deadlock (This mutex isn't recursive) */
  334.             cairo_device_reference (&display->base);
  335.             CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
  336.  
  337.             /* Make sure the xcb and xlib-xcb devices are finished */
  338.             cairo_device_finish (display->xcb_device);
  339.             cairo_device_finish (&display->base);
  340.  
  341.             cairo_device_destroy (&display->base);
  342.             return 0;
  343.         }
  344.     }
  345.     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
  346.  
  347.     return 0;
  348. }
  349.  
  350. static const cairo_device_backend_t _cairo_xlib_xcb_device_backend = {
  351.     CAIRO_DEVICE_TYPE_XLIB,
  352.  
  353.     NULL,
  354.     NULL,
  355.  
  356.     NULL, /* flush */
  357.     _cairo_xlib_xcb_display_finish,
  358.     free, /* destroy */
  359. };
  360.  
  361. static cairo_device_t *
  362. _cairo_xlib_xcb_device_create (Display *dpy, cairo_device_t *xcb_device)
  363. {
  364.     cairo_xlib_xcb_display_t *display = NULL;
  365.     cairo_device_t *device;
  366.  
  367.     if (xcb_device == NULL)
  368.         return NULL;
  369.  
  370.     CAIRO_MUTEX_INITIALIZE ();
  371.  
  372.     CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
  373.     if (displays.next == NULL) {
  374.         cairo_list_init (&displays);
  375.     }
  376.  
  377.     cairo_list_foreach_entry (display,
  378.                               cairo_xlib_xcb_display_t,
  379.                               &displays,
  380.                               link)
  381.     {
  382.         if (display->dpy == dpy) {
  383.             /* Maintain MRU order. */
  384.             if (displays.next != &display->link)
  385.                 cairo_list_move (&display->link, &displays);
  386.  
  387.             /* Grab a reference for our caller */
  388.             device = cairo_device_reference (&display->base);
  389.             assert (display->xcb_device == xcb_device);
  390.             goto unlock;
  391.         }
  392.     }
  393.  
  394.     display = malloc (sizeof (cairo_xlib_xcb_display_t));
  395.     if (unlikely (display == NULL)) {
  396.         device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
  397.         goto unlock;
  398.     }
  399.  
  400.     display->codes = XAddExtension (dpy);
  401.     if (unlikely (display->codes == NULL)) {
  402.         device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
  403.         free (display);
  404.         goto unlock;
  405.     }
  406.  
  407.     _cairo_device_init (&display->base, &_cairo_xlib_xcb_device_backend);
  408.  
  409.     XESetCloseDisplay (dpy, display->codes->extension, _cairo_xlib_xcb_close_display);
  410.     /* Add a reference for _cairo_xlib_xcb_display_finish. This basically means
  411.      * that the device's reference count never drops to zero
  412.      * as long as our Display* is alive. We need this because there is no
  413.      * "XDelExtension" to undo XAddExtension and having lots of registered
  414.      * extensions slows down libX11. */
  415.     cairo_device_reference (&display->base);
  416.  
  417.     display->dpy = dpy;
  418.     display->xcb_device = cairo_device_reference(xcb_device);
  419.  
  420.     cairo_list_add (&display->link, &displays);
  421.     device = &display->base;
  422.  
  423. unlock:
  424.     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
  425.  
  426.     return device;
  427. }
  428.  
  429. static cairo_surface_t *
  430. _cairo_xlib_xcb_surface_create (void *dpy,
  431.                                 void *scr,
  432.                                 void *visual,
  433.                                 void *format,
  434.                                 cairo_surface_t *xcb)
  435. {
  436.     cairo_xlib_xcb_surface_t *surface;
  437.  
  438.     if (unlikely (xcb->status))
  439.         return xcb;
  440.  
  441.     surface = malloc (sizeof (*surface));
  442.     if (unlikely (surface == NULL)) {
  443.         cairo_surface_destroy (xcb);
  444.         return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
  445.     }
  446.  
  447.     _cairo_surface_init (&surface->base,
  448.                          &_cairo_xlib_xcb_surface_backend,
  449.                          _cairo_xlib_xcb_device_create (dpy, xcb->device),
  450.                          xcb->content);
  451.  
  452.     /* _cairo_surface_init() got another reference to the device, drop ours */
  453.     cairo_device_destroy (surface->base.device);
  454.  
  455.     surface->display = dpy;
  456.     surface->screen = scr;
  457.     surface->visual = visual;
  458.     surface->format = format;
  459.     surface->xcb = (cairo_xcb_surface_t *) xcb;
  460.  
  461.     return &surface->base;
  462. }
  463.  
  464. static Screen *
  465. _cairo_xlib_screen_from_visual (Display *dpy, Visual *visual)
  466. {
  467.     int s, d, v;
  468.  
  469.     for (s = 0; s < ScreenCount (dpy); s++) {
  470.         Screen *screen;
  471.  
  472.         screen = ScreenOfDisplay (dpy, s);
  473.         if (visual == DefaultVisualOfScreen (screen))
  474.             return screen;
  475.  
  476.         for (d = 0; d < screen->ndepths; d++) {
  477.             Depth  *depth;
  478.  
  479.             depth = &screen->depths[d];
  480.             for (v = 0; v < depth->nvisuals; v++)
  481.                 if (visual == &depth->visuals[v])
  482.                     return screen;
  483.         }
  484.     }
  485.  
  486.     return NULL;
  487. }
  488.  
  489. cairo_surface_t *
  490. cairo_xlib_surface_create (Display     *dpy,
  491.                            Drawable     drawable,
  492.                            Visual      *visual,
  493.                            int          width,
  494.                            int          height)
  495. {
  496.     Screen *scr;
  497.     xcb_visualtype_t xcb_visual;
  498.  
  499.     scr = _cairo_xlib_screen_from_visual (dpy, visual);
  500.     if (scr == NULL)
  501.         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
  502.  
  503.     xcb_visual.visual_id = visual->visualid;
  504. #if defined(__cplusplus) || defined(c_plusplus)
  505.     xcb_visual._class = visual->c_class;
  506. #else
  507.     xcb_visual._class = visual->class;
  508. #endif
  509.     xcb_visual.bits_per_rgb_value = visual->bits_per_rgb;
  510.     xcb_visual.colormap_entries = visual->map_entries;
  511.     xcb_visual.red_mask = visual->red_mask;
  512.     xcb_visual.green_mask = visual->green_mask;
  513.     xcb_visual.blue_mask = visual->blue_mask;
  514.  
  515.     return _cairo_xlib_xcb_surface_create (dpy, scr, visual, NULL,
  516.                                            cairo_xcb_surface_create (XGetXCBConnection (dpy),
  517.                                                                      drawable,
  518.                                                                      &xcb_visual,
  519.                                                                      width, height));
  520. }
  521.  
  522. cairo_surface_t *
  523. cairo_xlib_surface_create_for_bitmap (Display  *dpy,
  524.                                       Pixmap    bitmap,
  525.                                       Screen   *scr,
  526.                                       int       width,
  527.                                       int       height)
  528. {
  529.     return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, NULL,
  530.                                            cairo_xcb_surface_create_for_bitmap (XGetXCBConnection (dpy),
  531.                                                                                 (xcb_screen_t *) scr,
  532.                                                                                 bitmap,
  533.                                                                                 width, height));
  534. }
  535.  
  536. #if CAIRO_HAS_XLIB_XRENDER_SURFACE
  537. static xcb_screen_t *
  538. _cairo_xcb_screen_from_root (xcb_connection_t *connection,
  539.                              xcb_window_t id)
  540. {
  541.     xcb_screen_iterator_t s;
  542.  
  543.     s = xcb_setup_roots_iterator (xcb_get_setup (connection));
  544.     for (; s.rem; xcb_screen_next (&s)) {
  545.         if (s.data->root == id)
  546.             return s.data;
  547.     }
  548.  
  549.     return NULL;
  550. }
  551. cairo_surface_t *
  552. cairo_xlib_surface_create_with_xrender_format (Display              *dpy,
  553.                                                Drawable             drawable,
  554.                                                Screen               *scr,
  555.                                                XRenderPictFormat    *format,
  556.                                                int                  width,
  557.                                                int                  height)
  558. {
  559.     xcb_render_pictforminfo_t xcb_format;
  560.     xcb_connection_t *connection;
  561.     xcb_screen_t *screen;
  562.  
  563.     xcb_format.id = format->id;
  564.     xcb_format.type = format->type;
  565.     xcb_format.depth = format->depth;
  566.     xcb_format.direct.red_shift = format->direct.red;
  567.     xcb_format.direct.red_mask = format->direct.redMask;
  568.     xcb_format.direct.green_shift = format->direct.green;
  569.     xcb_format.direct.green_mask = format->direct.greenMask;
  570.     xcb_format.direct.blue_shift = format->direct.blue;
  571.     xcb_format.direct.blue_mask = format->direct.blueMask;
  572.     xcb_format.direct.alpha_shift = format->direct.alpha;
  573.     xcb_format.direct.alpha_mask = format->direct.alphaMask;
  574.     xcb_format.colormap = format->colormap;
  575.  
  576.     connection = XGetXCBConnection (dpy);
  577.     screen = _cairo_xcb_screen_from_root (connection, (xcb_window_t) scr->root);
  578.  
  579.     return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, format,
  580.                                            cairo_xcb_surface_create_with_xrender_format (connection, screen,
  581.                                                                                          drawable,
  582.                                                                                          &xcb_format,
  583.                                                                                          width, height));
  584. }
  585.  
  586. XRenderPictFormat *
  587. cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
  588. {
  589.     cairo_xlib_xcb_surface_t *xlib_surface = (cairo_xlib_xcb_surface_t *) surface;
  590.  
  591.     /* Throw an error for a non-xlib surface */
  592.     if (surface->type != CAIRO_SURFACE_TYPE_XLIB) {
  593.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  594.         return NULL;
  595.     }
  596.  
  597.     return xlib_surface->format;
  598. }
  599. #endif
  600.  
  601. void
  602. cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
  603.                              int              width,
  604.                              int              height)
  605. {
  606.     cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
  607.     cairo_status_t status;
  608.  
  609.     if (unlikely (abstract_surface->status))
  610.         return;
  611.     if (unlikely (abstract_surface->finished)) {
  612.         status = _cairo_surface_set_error (abstract_surface,
  613.                                            _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
  614.         return;
  615.     }
  616.  
  617.     if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
  618.         status = _cairo_surface_set_error (abstract_surface,
  619.                                            CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  620.         return;
  621.     }
  622.  
  623.     cairo_xcb_surface_set_size (&surface->xcb->base, width, height);
  624.     if (unlikely (surface->xcb->base.status)) {
  625.         status = _cairo_surface_set_error (abstract_surface,
  626.                                            _cairo_error (surface->xcb->base.status));
  627.     }
  628. }
  629.  
  630. void
  631. cairo_xlib_surface_set_drawable (cairo_surface_t   *abstract_surface,
  632.                                  Drawable           drawable,
  633.                                  int                width,
  634.                                  int                height)
  635. {
  636.     cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *)abstract_surface;
  637.     cairo_status_t status;
  638.  
  639.     if (unlikely (abstract_surface->status))
  640.         return;
  641.     if (unlikely (abstract_surface->finished)) {
  642.         status = _cairo_surface_set_error (abstract_surface,
  643.                                            _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
  644.         return;
  645.     }
  646.  
  647.     if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
  648.         status = _cairo_surface_set_error (abstract_surface,
  649.                                            CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  650.         return;
  651.     }
  652.  
  653.     cairo_xcb_surface_set_drawable (&surface->xcb->base, drawable, width, height);
  654.     if (unlikely (surface->xcb->base.status)) {
  655.         status = _cairo_surface_set_error (abstract_surface,
  656.                                            _cairo_error (surface->xcb->base.status));
  657.     }
  658. }
  659.  
  660. Display *
  661. cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
  662. {
  663.     cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
  664.  
  665.     if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
  666.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  667.         return NULL;
  668.     }
  669.  
  670.     return surface->display;
  671. }
  672.  
  673. Drawable
  674. cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
  675. {
  676.     cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
  677.  
  678.     if (unlikely (abstract_surface->finished)) {
  679.         _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
  680.         return 0;
  681.     }
  682.     if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
  683.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  684.         return 0;
  685.     }
  686.     /* This can happen when e.g. create_similar falls back to an image surface
  687.      * because we don't have the RENDER extension. */
  688.     if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
  689.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  690.         return 0;
  691.     }
  692.  
  693.     return surface->xcb->drawable;
  694. }
  695.  
  696. Screen *
  697. cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
  698. {
  699.     cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
  700.  
  701.     if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
  702.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  703.         return NULL;
  704.     }
  705.  
  706.     return surface->screen;
  707. }
  708.  
  709. Visual *
  710. cairo_xlib_surface_get_visual (cairo_surface_t *abstract_surface)
  711. {
  712.     cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
  713.  
  714.     if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
  715.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  716.         return NULL;
  717.     }
  718.  
  719.     return surface->visual;
  720. }
  721.  
  722. int
  723. cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
  724. {
  725.     cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
  726.  
  727.     if (unlikely (abstract_surface->finished)) {
  728.         _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
  729.         return 0;
  730.     }
  731.     if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
  732.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  733.         return 0;
  734.     }
  735.     /* This can happen when e.g. create_similar falls back to an image surface
  736.      * because we don't have the RENDER extension. */
  737.     if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
  738.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  739.         return 0;
  740.     }
  741.  
  742.     return surface->xcb->depth;
  743. }
  744.  
  745. int
  746. cairo_xlib_surface_get_width (cairo_surface_t *abstract_surface)
  747. {
  748.     cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
  749.  
  750.     if (unlikely (abstract_surface->finished)) {
  751.         _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
  752.         return 0;
  753.     }
  754.     if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
  755.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  756.         return 0;
  757.     }
  758.     /* This can happen when e.g. create_similar falls back to an image surface
  759.      * because we don't have the RENDER extension. */
  760.     if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
  761.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  762.         return 0;
  763.     }
  764.  
  765.     return surface->xcb->width;
  766. }
  767.  
  768. int
  769. cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
  770. {
  771.     cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
  772.  
  773.     if (unlikely (abstract_surface->finished)) {
  774.         _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
  775.         return 0;
  776.     }
  777.     if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
  778.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  779.         return 0;
  780.     }
  781.     /* This can happen when e.g. create_similar falls back to an image surface
  782.      * because we don't have the RENDER extension. */
  783.     if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
  784.         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  785.         return 0;
  786.     }
  787.  
  788.     return surface->xcb->height;
  789. }
  790.  
  791. void
  792. cairo_xlib_device_debug_cap_xrender_version (cairo_device_t *device,
  793.                                              int major, int minor)
  794. {
  795.     cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
  796.  
  797.     if (device == NULL || device->status)
  798.         return;
  799.  
  800.     if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB)
  801.         return;
  802.  
  803.     cairo_xcb_device_debug_cap_xrender_version (display->xcb_device,
  804.                                                 major, minor);
  805. }
  806.  
  807. void
  808. cairo_xlib_device_debug_set_precision (cairo_device_t *device,
  809.                                        int precision)
  810. {
  811.     cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
  812.  
  813.     if (device == NULL || device->status)
  814.         return;
  815.     if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
  816.         cairo_status_t status;
  817.  
  818.         status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
  819.         (void) status;
  820.         return;
  821.     }
  822.  
  823.     cairo_xcb_device_debug_set_precision (display->xcb_device, precision);
  824. }
  825.  
  826. int
  827. cairo_xlib_device_debug_get_precision (cairo_device_t *device)
  828. {
  829.     cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
  830.  
  831.     if (device == NULL || device->status)
  832.         return -1;
  833.     if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
  834.         cairo_status_t status;
  835.  
  836.         status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
  837.         (void) status;
  838.         return -1;
  839.     }
  840.  
  841.     return cairo_xcb_device_debug_get_precision (display->xcb_device);
  842. }
  843.  
  844. #endif /* CAIRO_HAS_XLIB_XCB_FUNCTIONS */
  845.