]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdrawable-x11.c
gdk/: fully remove gdkalias hacks
[~andy/gtk] / gdk / x11 / gdkdrawable-x11.c
1 /* GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28
29 #include "gdkx.h"
30
31 #include <cairo-xlib.h>
32
33 #include <stdlib.h>
34 #include <string.h>             /* for memcpy() */
35
36 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
37 #define USE_SHM
38 #endif
39
40 #ifdef USE_SHM
41 #include <X11/extensions/XShm.h>
42 #endif /* USE_SHM */
43
44 #include "gdkprivate-x11.h"
45 #include "gdkdrawable-x11.h"
46 #include "gdkpixmap-x11.h"
47 #include "gdkscreen-x11.h"
48 #include "gdkdisplay-x11.h"
49
50
51 static void gdk_x11_draw_rectangle (GdkDrawable    *drawable,
52                                     GdkGC          *gc,
53                                     gboolean        filled,
54                                     gint            x,
55                                     gint            y,
56                                     gint            width,
57                                     gint            height);
58 static void gdk_x11_draw_arc       (GdkDrawable    *drawable,
59                                     GdkGC          *gc,
60                                     gboolean        filled,
61                                     gint            x,
62                                     gint            y,
63                                     gint            width,
64                                     gint            height,
65                                     gint            angle1,
66                                     gint            angle2);
67 static void gdk_x11_draw_polygon   (GdkDrawable    *drawable,
68                                     GdkGC          *gc,
69                                     gboolean        filled,
70                                     GdkPoint       *points,
71                                     gint            npoints);
72 static void gdk_x11_draw_drawable  (GdkDrawable    *drawable,
73                                     GdkGC          *gc,
74                                     GdkPixmap      *src,
75                                     gint            xsrc,
76                                     gint            ysrc,
77                                     gint            xdest,
78                                     gint            ydest,
79                                     gint            width,
80                                     gint            height,
81                                     GdkDrawable    *original_src);
82 static void gdk_x11_draw_points    (GdkDrawable    *drawable,
83                                     GdkGC          *gc,
84                                     GdkPoint       *points,
85                                     gint            npoints);
86 static void gdk_x11_draw_segments  (GdkDrawable    *drawable,
87                                     GdkGC          *gc,
88                                     GdkSegment     *segs,
89                                     gint            nsegs);
90 static void gdk_x11_draw_lines     (GdkDrawable    *drawable,
91                                     GdkGC          *gc,
92                                     GdkPoint       *points,
93                                     gint            npoints);
94
95 static void gdk_x11_draw_image     (GdkDrawable     *drawable,
96                                     GdkGC           *gc,
97                                     GdkImage        *image,
98                                     gint             xsrc,
99                                     gint             ysrc,
100                                     gint             xdest,
101                                     gint             ydest,
102                                     gint             width,
103                                     gint             height);
104 static void gdk_x11_draw_pixbuf    (GdkDrawable     *drawable,
105                                     GdkGC           *gc,
106                                     GdkPixbuf       *pixbuf,
107                                     gint             src_x,
108                                     gint             src_y,
109                                     gint             dest_x,
110                                     gint             dest_y,
111                                     gint             width,
112                                     gint             height,
113                                     GdkRgbDither     dither,
114                                     gint             x_dither,
115                                     gint             y_dither);
116
117 static cairo_surface_t *gdk_x11_ref_cairo_surface (GdkDrawable *drawable);
118      
119 static void gdk_x11_set_colormap   (GdkDrawable    *drawable,
120                                     GdkColormap    *colormap);
121
122 static GdkColormap* gdk_x11_get_colormap   (GdkDrawable    *drawable);
123 static gint         gdk_x11_get_depth      (GdkDrawable    *drawable);
124 static GdkScreen *  gdk_x11_get_screen     (GdkDrawable    *drawable);
125 static GdkVisual*   gdk_x11_get_visual     (GdkDrawable    *drawable);
126
127 static void gdk_drawable_impl_x11_finalize   (GObject *object);
128
129 static const cairo_user_data_key_t gdk_x11_cairo_key;
130
131 G_DEFINE_TYPE (GdkDrawableImplX11, _gdk_drawable_impl_x11, GDK_TYPE_DRAWABLE)
132
133 static void
134 _gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
135 {
136   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
137   GObjectClass *object_class = G_OBJECT_CLASS (klass);
138   
139   object_class->finalize = gdk_drawable_impl_x11_finalize;
140   
141   drawable_class->create_gc = _gdk_x11_gc_new;
142   drawable_class->draw_rectangle = gdk_x11_draw_rectangle;
143   drawable_class->draw_arc = gdk_x11_draw_arc;
144   drawable_class->draw_polygon = gdk_x11_draw_polygon;
145   drawable_class->draw_drawable_with_src = gdk_x11_draw_drawable;
146   drawable_class->draw_points = gdk_x11_draw_points;
147   drawable_class->draw_segments = gdk_x11_draw_segments;
148   drawable_class->draw_lines = gdk_x11_draw_lines;
149   drawable_class->draw_image = gdk_x11_draw_image;
150   drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf;
151   
152   drawable_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
153
154   drawable_class->set_colormap = gdk_x11_set_colormap;
155   drawable_class->get_colormap = gdk_x11_get_colormap;
156
157   drawable_class->get_depth = gdk_x11_get_depth;
158   drawable_class->get_screen = gdk_x11_get_screen;
159   drawable_class->get_visual = gdk_x11_get_visual;
160   
161   drawable_class->_copy_to_image = _gdk_x11_copy_to_image;
162 }
163
164 static void
165 _gdk_drawable_impl_x11_init (GdkDrawableImplX11 *impl)
166 {
167 }
168
169 static void
170 gdk_drawable_impl_x11_finalize (GObject *object)
171 {
172   gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
173
174   G_OBJECT_CLASS (_gdk_drawable_impl_x11_parent_class)->finalize (object);
175 }
176
177 /**
178  * _gdk_x11_drawable_finish:
179  * @drawable: a #GdkDrawableImplX11.
180  * 
181  * Performs necessary cleanup prior to freeing a pixmap or
182  * destroying a window.
183  **/
184 void
185 _gdk_x11_drawable_finish (GdkDrawable *drawable)
186 {
187   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
188   
189   if (impl->picture)
190     {
191       XRenderFreePicture (GDK_SCREEN_XDISPLAY (impl->screen),
192                           impl->picture);
193       impl->picture = None;
194     }
195   
196   if (impl->cairo_surface)
197     {
198       cairo_surface_finish (impl->cairo_surface);
199       cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
200                                    NULL, NULL);
201     }
202 }
203
204 /**
205  * _gdk_x11_drawable_update_size:
206  * @drawable: a #GdkDrawableImplX11.
207  * 
208  * Updates the state of the drawable (in particular the drawable's
209  * cairo surface) when its size has changed.
210  **/
211 void
212 _gdk_x11_drawable_update_size (GdkDrawable *drawable)
213 {
214   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
215   
216   if (impl->cairo_surface)
217     {
218       int width, height;
219       
220       gdk_drawable_get_size (drawable, &width, &height);
221       cairo_xlib_surface_set_size (impl->cairo_surface, width, height);
222     }
223 }
224
225 static void
226 try_pixmap (Display *xdisplay,
227             int      screen,
228             int      depth)
229 {
230   Pixmap pixmap = XCreatePixmap (xdisplay,
231                                  RootWindow (xdisplay, screen),
232                                  1, 1, depth);
233   XFreePixmap (xdisplay, pixmap);
234 }
235
236 gboolean
237 _gdk_x11_have_render (GdkDisplay *display)
238 {
239   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
240   GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
241
242   if (x11display->have_render == GDK_UNKNOWN)
243     {
244       int event_base, error_base;
245       x11display->have_render =
246         XRenderQueryExtension (xdisplay, &event_base, &error_base)
247         ? GDK_YES : GDK_NO;
248
249       if (x11display->have_render == GDK_YES)
250         {
251           /*
252            * Sun advertises RENDER, but fails to support 32-bit pixmaps.
253            * That is just no good.  Therefore, we check all screens
254            * for proper support.
255            */
256
257           int screen;
258           for (screen = 0; screen < ScreenCount (xdisplay); screen++)
259             {
260               int count;
261               int *depths = XListDepths (xdisplay, screen, &count);
262               gboolean has_8 = FALSE, has_32 = FALSE;
263
264               if (depths)
265                 {
266                   int i;
267
268                   for (i = 0; i < count; i++)
269                     {
270                       if (depths[i] == 8)
271                         has_8 = TRUE;
272                       else if (depths[i] == 32)
273                         has_32 = TRUE;
274                     }
275                   XFree (depths);
276                 }
277
278               /* At this point, we might have a false positive;
279                * buggy versions of Xinerama only report depths for
280                * which there is an associated visual; so we actually
281                * go ahead and try create pixmaps.
282                */
283               if (!(has_8 && has_32))
284                 {
285                   gdk_error_trap_push ();
286                   if (!has_8)
287                     try_pixmap (xdisplay, screen, 8);
288                   if (!has_32)
289                     try_pixmap (xdisplay, screen, 32);
290                   XSync (xdisplay, False);
291                   if (gdk_error_trap_pop () == 0)
292                     {
293                       has_8 = TRUE;
294                       has_32 = TRUE;
295                     }
296                 }
297               
298               if (!(has_8 && has_32))
299                 {
300                   g_warning ("The X server advertises that RENDER support is present,\n"
301                              "but fails to supply the necessary pixmap support.  In\n"
302                              "other words, it is buggy.");
303                   x11display->have_render = GDK_NO;
304                   break;
305                 }
306             }
307         }
308     }
309
310   return x11display->have_render == GDK_YES;
311 }
312
313 static Picture
314 gdk_x11_drawable_get_picture (GdkDrawable *drawable)
315 {
316   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
317   
318   if (!impl->picture)
319     {
320       Display *xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
321       XRenderPictFormat *format;
322       
323       GdkVisual *visual = gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
324       if (!visual)
325         return None;
326
327       format = XRenderFindVisualFormat (xdisplay, GDK_VISUAL_XVISUAL (visual));
328       if (format)
329         {
330           XRenderPictureAttributes attributes;
331           attributes.graphics_exposures = False;
332           
333           impl->picture = XRenderCreatePicture (xdisplay, impl->xid, format,
334                                                 CPGraphicsExposure, &attributes);
335         }
336     }
337   
338   return impl->picture;
339 }
340
341 static void
342 gdk_x11_drawable_update_picture_clip (GdkDrawable *drawable,
343                                       GdkGC       *gc)
344 {
345   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
346   Display *xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
347   Picture picture = gdk_x11_drawable_get_picture (drawable);
348   cairo_region_t *clip_region = gc ? _gdk_gc_get_clip_region (gc) : NULL;
349
350   if (clip_region)
351     {
352       XRectangle *rects;
353       int n_rects;
354
355       _gdk_region_get_xrectangles (clip_region, 
356                                    gc->clip_x_origin,
357                                    gc->clip_y_origin,
358                                    &rects,
359                                    &n_rects);
360       XRenderSetPictureClipRectangles (xdisplay, picture,
361                                        0, 0, rects, n_rects);
362       g_free (rects);
363     }
364   else
365     {
366       XRenderPictureAttributes pa;
367       GdkBitmap *mask;
368       gulong pa_mask;
369
370       pa_mask = CPClipMask;
371       if (gc && (mask = _gdk_gc_get_clip_mask (gc)))
372         {
373           pa.clip_mask = GDK_PIXMAP_XID (mask);
374           pa.clip_x_origin = gc->clip_x_origin;
375           pa.clip_y_origin = gc->clip_y_origin;
376           pa_mask |= CPClipXOrigin | CPClipYOrigin;
377         }
378       else
379         pa.clip_mask = None;
380
381       XRenderChangePicture (xdisplay, picture,
382                             pa_mask, &pa);
383     }
384 }
385
386 /*****************************************************
387  * X11 specific implementations of generic functions *
388  *****************************************************/
389
390 static GdkColormap*
391 gdk_x11_get_colormap (GdkDrawable *drawable)
392 {
393   GdkDrawableImplX11 *impl;
394
395   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
396
397   return impl->colormap;
398 }
399
400 static void
401 gdk_x11_set_colormap (GdkDrawable *drawable,
402                       GdkColormap *colormap)
403 {
404   GdkDrawableImplX11 *impl;
405
406   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
407
408   if (impl->colormap == colormap)
409     return;
410   
411   if (impl->colormap)
412     g_object_unref (impl->colormap);
413   impl->colormap = colormap;
414   if (impl->colormap)
415     g_object_ref (impl->colormap);
416 }
417
418 /* Drawing
419  */
420
421 static void
422 gdk_x11_draw_rectangle (GdkDrawable *drawable,
423                         GdkGC       *gc,
424                         gboolean     filled,
425                         gint         x,
426                         gint         y,
427                         gint         width,
428                         gint         height)
429 {
430   GdkDrawableImplX11 *impl;
431
432   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
433   
434   if (filled)
435     XFillRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
436                     GDK_GC_GET_XGC (gc), x, y, width, height);
437   else
438     XDrawRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
439                     GDK_GC_GET_XGC (gc), x, y, width, height);
440 }
441
442 static void
443 gdk_x11_draw_arc (GdkDrawable *drawable,
444                   GdkGC       *gc,
445                   gboolean     filled,
446                   gint         x,
447                   gint         y,
448                   gint         width,
449                   gint         height,
450                   gint         angle1,
451                   gint         angle2)
452 {
453   GdkDrawableImplX11 *impl;
454
455   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
456
457   
458   if (filled)
459     XFillArc (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
460               GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
461   else
462     XDrawArc (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
463               GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
464 }
465
466 static void
467 gdk_x11_draw_polygon (GdkDrawable *drawable,
468                       GdkGC       *gc,
469                       gboolean     filled,
470                       GdkPoint    *points,
471                       gint         npoints)
472 {
473   XPoint *tmp_points;
474   gint tmp_npoints, i;
475   GdkDrawableImplX11 *impl;
476
477   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
478
479   
480   if (!filled &&
481       (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y))
482     {
483       tmp_npoints = npoints + 1;
484       tmp_points = g_new (XPoint, tmp_npoints);
485       tmp_points[npoints].x = points[0].x;
486       tmp_points[npoints].y = points[0].y;
487     }
488   else
489     {
490       tmp_npoints = npoints;
491       tmp_points = g_new (XPoint, tmp_npoints);
492     }
493
494   for (i=0; i<npoints; i++)
495     {
496       tmp_points[i].x = points[i].x;
497       tmp_points[i].y = points[i].y;
498     }
499   
500   if (filled)
501     XFillPolygon (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
502                   GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, Complex, CoordModeOrigin);
503   else
504     XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
505                 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, CoordModeOrigin);
506
507   g_free (tmp_points);
508 }
509
510 static void
511 gdk_x11_draw_drawable (GdkDrawable *drawable,
512                        GdkGC       *gc,
513                        GdkPixmap   *src,
514                        gint         xsrc,
515                        gint         ysrc,
516                        gint         xdest,
517                        gint         ydest,
518                        gint         width,
519                        gint         height,
520                        GdkDrawable *original_src)
521 {
522   int src_depth = gdk_drawable_get_depth (src);
523   int dest_depth = gdk_drawable_get_depth (drawable);
524   GdkDrawableImplX11 *impl;
525   GdkDrawableImplX11 *src_impl;
526   
527   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
528
529   if (GDK_IS_DRAWABLE_IMPL_X11 (src))
530     src_impl = GDK_DRAWABLE_IMPL_X11 (src);
531   else if (GDK_IS_WINDOW (src))
532     src_impl = GDK_DRAWABLE_IMPL_X11(((GdkWindowObject *)src)->impl);
533   else
534     src_impl = GDK_DRAWABLE_IMPL_X11(((GdkPixmapObject *)src)->impl);
535
536   if (GDK_IS_WINDOW_IMPL_X11 (impl) &&
537       GDK_IS_PIXMAP_IMPL_X11 (src_impl))
538     {
539       GdkPixmapImplX11 *src_pixmap = GDK_PIXMAP_IMPL_X11 (src_impl);
540       /* Work around an Xserver bug where non-visible areas from
541        * a pixmap to a window will clear the window background
542        * in destination areas that are supposed to be clipped out.
543        * This is a problem with client side windows as this means
544        * things may draw outside the virtual windows. This could
545        * also happen for window to window copies, but I don't
546        * think we generate any calls like that.
547        *
548        * See: 
549        * http://lists.freedesktop.org/archives/xorg/2009-February/043318.html
550        */
551       if (xsrc < 0)
552         {
553           width += xsrc;
554           xdest -= xsrc;
555           xsrc = 0;
556         }
557       
558       if (ysrc < 0)
559         {
560           height += ysrc;
561           ydest -= ysrc;
562           ysrc = 0;
563         }
564
565       if (xsrc + width > src_pixmap->width)
566         width = src_pixmap->width - xsrc;
567       if (ysrc + height > src_pixmap->height)
568         height = src_pixmap->height - ysrc;
569     }
570   
571   if (src_depth == 1)
572     {
573       XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
574                  src_impl->xid,
575                  impl->xid,
576                  GDK_GC_GET_XGC (gc),
577                  xsrc, ysrc,
578                  width, height,
579                  xdest, ydest);
580     }
581   else if (dest_depth != 0 && src_depth == dest_depth)
582     {
583       XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
584                  src_impl->xid,
585                  impl->xid,
586                  GDK_GC_GET_XGC (gc),
587                  xsrc, ysrc,
588                  width, height,
589                  xdest, ydest);
590     }
591   else
592     g_warning ("Attempt to draw a drawable with depth %d to a drawable with depth %d",
593                src_depth, dest_depth);
594 }
595
596 static void
597 gdk_x11_draw_points (GdkDrawable *drawable,
598                      GdkGC       *gc,
599                      GdkPoint    *points,
600                      gint         npoints)
601 {
602   GdkDrawableImplX11 *impl;
603
604   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
605
606   
607   /* We special-case npoints == 1, because X will merge multiple
608    * consecutive XDrawPoint requests into a PolyPoint request
609    */
610   if (npoints == 1)
611     {
612       XDrawPoint (GDK_SCREEN_XDISPLAY (impl->screen),
613                   impl->xid,
614                   GDK_GC_GET_XGC (gc),
615                   points[0].x, points[0].y);
616     }
617   else
618     {
619       gint i;
620       XPoint *tmp_points = g_new (XPoint, npoints);
621
622       for (i=0; i<npoints; i++)
623         {
624           tmp_points[i].x = points[i].x;
625           tmp_points[i].y = points[i].y;
626         }
627       
628       XDrawPoints (GDK_SCREEN_XDISPLAY (impl->screen),
629                    impl->xid,
630                    GDK_GC_GET_XGC (gc),
631                    tmp_points,
632                    npoints,
633                    CoordModeOrigin);
634
635       g_free (tmp_points);
636     }
637 }
638
639 static void
640 gdk_x11_draw_segments (GdkDrawable *drawable,
641                        GdkGC       *gc,
642                        GdkSegment  *segs,
643                        gint         nsegs)
644 {
645   GdkDrawableImplX11 *impl;
646
647   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
648
649   
650   /* We special-case nsegs == 1, because X will merge multiple
651    * consecutive XDrawLine requests into a PolySegment request
652    */
653   if (nsegs == 1)
654     {
655       XDrawLine (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
656                  GDK_GC_GET_XGC (gc), segs[0].x1, segs[0].y1,
657                  segs[0].x2, segs[0].y2);
658     }
659   else
660     {
661       gint i;
662       XSegment *tmp_segs = g_new (XSegment, nsegs);
663
664       for (i=0; i<nsegs; i++)
665         {
666           tmp_segs[i].x1 = segs[i].x1;
667           tmp_segs[i].x2 = segs[i].x2;
668           tmp_segs[i].y1 = segs[i].y1;
669           tmp_segs[i].y2 = segs[i].y2;
670         }
671       
672       XDrawSegments (GDK_SCREEN_XDISPLAY (impl->screen),
673                      impl->xid,
674                      GDK_GC_GET_XGC (gc),
675                      tmp_segs, nsegs);
676
677       g_free (tmp_segs);
678     }
679 }
680
681 static void
682 gdk_x11_draw_lines (GdkDrawable *drawable,
683                     GdkGC       *gc,
684                     GdkPoint    *points,
685                     gint         npoints)
686 {
687   gint i;
688   XPoint *tmp_points = g_new (XPoint, npoints);
689   GdkDrawableImplX11 *impl;
690
691   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
692
693   
694   for (i=0; i<npoints; i++)
695     {
696       tmp_points[i].x = points[i].x;
697       tmp_points[i].y = points[i].y;
698     }
699       
700   XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen),
701               impl->xid,
702               GDK_GC_GET_XGC (gc),
703               tmp_points, npoints,
704               CoordModeOrigin);
705
706   g_free (tmp_points);
707 }
708
709 static void
710 gdk_x11_draw_image     (GdkDrawable     *drawable,
711                         GdkGC           *gc,
712                         GdkImage        *image,
713                         gint             xsrc,
714                         gint             ysrc,
715                         gint             xdest,
716                         gint             ydest,
717                         gint             width,
718                         gint             height)
719 {
720   GdkDrawableImplX11 *impl;
721
722   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
723
724 #ifdef USE_SHM  
725   if (image->type == GDK_IMAGE_SHARED)
726     XShmPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
727                   GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
728                   xsrc, ysrc, xdest, ydest, width, height, False);
729   else
730 #endif
731     XPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
732                GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
733                xsrc, ysrc, xdest, ydest, width, height);
734 }
735
736 static gint
737 gdk_x11_get_depth (GdkDrawable *drawable)
738 {
739   /* This is a bit bogus but I'm not sure the other way is better */
740
741   return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
742 }
743
744 static GdkDrawable *
745 get_impl_drawable (GdkDrawable *drawable)
746 {
747   if (GDK_IS_WINDOW (drawable))
748     return ((GdkWindowObject *)drawable)->impl;
749   else if (GDK_IS_PIXMAP (drawable))
750     return ((GdkPixmapObject *)drawable)->impl;
751   else
752     {
753       g_warning (G_STRLOC " drawable is not a pixmap or window");
754       return NULL;
755     }
756 }
757
758 static GdkScreen*
759 gdk_x11_get_screen (GdkDrawable *drawable)
760 {
761   if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
762     return GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
763   else
764     return GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen;
765 }
766
767 static GdkVisual*
768 gdk_x11_get_visual (GdkDrawable    *drawable)
769 {
770   return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
771 }
772
773 /**
774  * gdk_x11_drawable_get_xdisplay:
775  * @drawable: a #GdkDrawable.
776  * 
777  * Returns the display of a #GdkDrawable.
778  * 
779  * Return value: an Xlib <type>Display*</type>.
780  **/
781 Display *
782 gdk_x11_drawable_get_xdisplay (GdkDrawable *drawable)
783 {
784   if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
785     return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
786   else
787     return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen);
788 }
789
790 /**
791  * gdk_x11_drawable_get_xid:
792  * @drawable: a #GdkDrawable.
793  * 
794  * Returns the X resource (window or pixmap) belonging to a #GdkDrawable.
795  * 
796  * Return value: the ID of @drawable's X resource.
797  **/
798 XID
799 gdk_x11_drawable_get_xid (GdkDrawable *drawable)
800 {
801   GdkDrawable *impl;
802   
803   if (GDK_IS_WINDOW (drawable))
804     {
805       GdkWindow *window = (GdkWindow *)drawable;
806       
807       /* Try to ensure the window has a native window */
808       if (!_gdk_window_has_impl (window))
809         {
810           gdk_window_ensure_native (window);
811
812           /* We sync here to ensure the window is created in the Xserver when
813            * this function returns. This is required because the returned XID
814            * for this window must be valid immediately, even with another
815            * connection to the Xserver */
816           gdk_display_sync (gdk_drawable_get_display (window));
817         }
818       
819       if (!GDK_WINDOW_IS_X11 (window))
820         {
821           g_warning (G_STRLOC " drawable is not a native X11 window");
822           return None;
823         }
824       
825       impl = ((GdkWindowObject *)drawable)->impl;
826     }
827   else if (GDK_IS_PIXMAP (drawable))
828     impl = ((GdkPixmapObject *)drawable)->impl;
829   else
830     {
831       g_warning (G_STRLOC " drawable is not a pixmap or window");
832       return None;
833     }
834
835   return ((GdkDrawableImplX11 *)impl)->xid;
836 }
837
838 GdkDrawable *
839 gdk_x11_window_get_drawable_impl (GdkWindow *window)
840 {
841   return ((GdkWindowObject *)window)->impl;
842 }
843 GdkDrawable *
844 gdk_x11_pixmap_get_drawable_impl (GdkPixmap *pixmap)
845 {
846   return ((GdkPixmapObject *)pixmap)->impl;
847 }
848
849 /* Code for accelerated alpha compositing using the RENDER extension.
850  * It's a bit long because there are lots of possibilities for
851  * what's the fastest depending on the available picture formats,
852  * whether we can used shared pixmaps, etc.
853  */
854
855 static GdkX11FormatType
856 select_format (GdkDisplay         *display,
857                XRenderPictFormat **format,
858                XRenderPictFormat **mask)
859 {
860   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
861   XRenderPictFormat pf;
862
863   if (!_gdk_x11_have_render (display))
864     return GDK_X11_FORMAT_NONE;
865   
866   /* Look for a 32-bit xRGB and Axxx formats that exactly match the
867    * in memory data format. We can use them as pixmap and mask
868    * to deal with non-premultiplied data.
869    */
870
871   pf.type = PictTypeDirect;
872   pf.depth = 32;
873   pf.direct.redMask = 0xff;
874   pf.direct.greenMask = 0xff;
875   pf.direct.blueMask = 0xff;
876   
877   pf.direct.alphaMask = 0;
878   if (ImageByteOrder (xdisplay) == LSBFirst)
879     {
880       /* ABGR */
881       pf.direct.red = 0;
882       pf.direct.green = 8;
883       pf.direct.blue = 16;
884     }
885   else
886     {
887       /* RGBA */
888       pf.direct.red = 24;
889       pf.direct.green = 16;
890       pf.direct.blue = 8;
891     }
892   
893   *format = XRenderFindFormat (xdisplay,
894                                (PictFormatType | PictFormatDepth |
895                                 PictFormatRedMask | PictFormatRed |
896                                 PictFormatGreenMask | PictFormatGreen |
897                                 PictFormatBlueMask | PictFormatBlue |
898                                 PictFormatAlphaMask),
899                                &pf,
900                                0);
901
902   pf.direct.alphaMask = 0xff;
903   if (ImageByteOrder (xdisplay) == LSBFirst)
904     {
905       /* ABGR */
906       pf.direct.alpha = 24;
907     }
908   else
909     {
910       pf.direct.alpha = 0;
911     }
912   
913   *mask = XRenderFindFormat (xdisplay,
914                              (PictFormatType | PictFormatDepth |
915                               PictFormatAlphaMask | PictFormatAlpha),
916                              &pf,
917                              0);
918
919   if (*format && *mask)
920     return GDK_X11_FORMAT_EXACT_MASK;
921
922   /* OK, that failed, now look for xRGB and Axxx formats in
923    * RENDER's preferred order
924    */
925   pf.direct.alphaMask = 0;
926   /* ARGB */
927   pf.direct.red = 16;
928   pf.direct.green = 8;
929   pf.direct.blue = 0;
930   
931   *format = XRenderFindFormat (xdisplay,
932                                (PictFormatType | PictFormatDepth |
933                                 PictFormatRedMask | PictFormatRed |
934                                 PictFormatGreenMask | PictFormatGreen |
935                                 PictFormatBlueMask | PictFormatBlue |
936                                 PictFormatAlphaMask),
937                                &pf,
938                                0);
939
940   pf.direct.alphaMask = 0xff;
941   pf.direct.alpha = 24;
942   
943   *mask = XRenderFindFormat (xdisplay,
944                              (PictFormatType | PictFormatDepth |
945                               PictFormatAlphaMask | PictFormatAlpha),
946                              &pf,
947                              0);
948
949   if (*format && *mask)
950     return GDK_X11_FORMAT_ARGB_MASK;
951
952   /* Finally, if neither of the above worked, fall back to
953    * looking for combined ARGB -- we'll premultiply ourselves.
954    */
955
956   pf.type = PictTypeDirect;
957   pf.depth = 32;
958   pf.direct.red = 16;
959   pf.direct.green = 8;
960   pf.direct.blue = 0;
961   pf.direct.alphaMask = 0xff;
962   pf.direct.alpha = 24;
963
964   *format = XRenderFindFormat (xdisplay,
965                                (PictFormatType | PictFormatDepth |
966                                 PictFormatRedMask | PictFormatRed |
967                                 PictFormatGreenMask | PictFormatGreen |
968                                 PictFormatBlueMask | PictFormatBlue |
969                                 PictFormatAlphaMask | PictFormatAlpha),
970                                &pf,
971                                0);
972   *mask = NULL;
973
974   if (*format)
975     return GDK_X11_FORMAT_ARGB;
976
977   return GDK_X11_FORMAT_NONE;
978 }
979
980 #if 0
981 static void
982 list_formats (XRenderPictFormat *pf)
983 {
984   gint i;
985   
986   for (i=0 ;; i++)
987     {
988       XRenderPictFormat *pf = XRenderFindFormat (impl->xdisplay, 0, NULL, i);
989       if (pf)
990         {
991           g_print ("%2d R-%#06x/%#06x G-%#06x/%#06x B-%#06x/%#06x A-%#06x/%#06x\n",
992                    pf->depth,
993                    pf->direct.red,
994                    pf->direct.redMask,
995                    pf->direct.green,
996                    pf->direct.greenMask,
997                    pf->direct.blue,
998                    pf->direct.blueMask,
999                    pf->direct.alpha,
1000                    pf->direct.alphaMask);
1001         }
1002       else
1003         break;
1004     }
1005 }
1006 #endif  
1007
1008 void
1009 _gdk_x11_convert_to_format (guchar           *src_buf,
1010                             gint              src_rowstride,
1011                             guchar           *dest_buf,
1012                             gint              dest_rowstride,
1013                             GdkX11FormatType  dest_format,
1014                             GdkByteOrder      dest_byteorder,
1015                             gint              width,
1016                             gint              height)
1017 {
1018   gint i;
1019
1020   for (i=0; i < height; i++)
1021     {
1022       switch (dest_format)
1023         {
1024         case GDK_X11_FORMAT_EXACT_MASK:
1025           {
1026             memcpy (dest_buf + i * dest_rowstride,
1027                     src_buf + i * src_rowstride,
1028                     width * 4);
1029             break;
1030           }
1031         case GDK_X11_FORMAT_ARGB_MASK:
1032           {
1033             guchar *row = src_buf + i * src_rowstride;
1034             if (((gsize)row & 3) != 0)
1035               {
1036                 guchar *p = row;
1037                 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1038                 guchar *end = p + 4 * width;
1039
1040                 while (p < end)
1041                   {
1042                     *q = (p[3] << 24) | (p[0] << 16) | (p[1] << 8) | p[2];
1043                     p += 4;
1044                     q++;
1045                   }
1046               }
1047             else
1048               {
1049                 guint32 *p = (guint32 *)row;
1050                 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1051                 guint32 *end = p + width;
1052
1053 #if G_BYTE_ORDER == G_LITTLE_ENDIAN         
1054                 if (dest_byteorder == GDK_LSB_FIRST)
1055                   {
1056                     /* ABGR => ARGB */
1057                 
1058                     while (p < end)
1059                       {
1060                         *q = ( (*p & 0xff00ff00) |
1061                                ((*p & 0x000000ff) << 16) |
1062                                ((*p & 0x00ff0000) >> 16));
1063                         q++;
1064                         p++;
1065                       }
1066                   }
1067                 else
1068                   {
1069                     /* ABGR => BGRA */
1070                 
1071                     while (p < end)
1072                       {
1073                         *q = (((*p & 0xff000000) >> 24) |
1074                               ((*p & 0x00ffffff) << 8));
1075                         q++;
1076                         p++;
1077                       }
1078                   }
1079 #else /* G_BYTE_ORDER == G_BIG_ENDIAN */
1080                 if (dest_byteorder == GDK_LSB_FIRST)
1081                   {
1082                     /* RGBA => BGRA */
1083                 
1084                     while (p < end)
1085                       {
1086                         *q = ( (*p & 0x00ff00ff) |
1087                                ((*p & 0x0000ff00) << 16) |
1088                                ((*p & 0xff000000) >> 16));
1089                         q++;
1090                         p++;
1091                       }
1092                   }
1093                 else
1094                   {
1095                     /* RGBA => ARGB */
1096                 
1097                     while (p < end)
1098                       {
1099                         *q = (((*p & 0xffffff00) >> 8) |
1100                               ((*p & 0x000000ff) << 24));
1101                         q++;
1102                         p++;
1103                       }
1104                   }
1105 #endif /* G_BYTE_ORDER*/            
1106               }
1107             break;
1108           }
1109         case GDK_X11_FORMAT_ARGB:
1110           {
1111             guchar *p = (src_buf + i * src_rowstride);
1112             guchar *q = (dest_buf + i * dest_rowstride);
1113             guchar *end = p + 4 * width;
1114             guint t1,t2,t3;
1115             
1116 #define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END
1117             
1118             if (dest_byteorder == GDK_LSB_FIRST)
1119               {
1120                 while (p < end)
1121                   {
1122                     MULT(q[0], p[2], p[3], t1);
1123                     MULT(q[1], p[1], p[3], t2);
1124                     MULT(q[2], p[0], p[3], t3);
1125                     q[3] = p[3];
1126                     p += 4;
1127                     q += 4;
1128                   }
1129               }
1130             else
1131               {
1132                 while (p < end)
1133                   {
1134                     q[0] = p[3];
1135                     MULT(q[1], p[0], p[3], t1);
1136                     MULT(q[2], p[1], p[3], t2);
1137                     MULT(q[3], p[2], p[3], t3);
1138                     p += 4;
1139                     q += 4;
1140                   }
1141               }
1142 #undef MULT
1143             break;
1144           }
1145         case GDK_X11_FORMAT_NONE:
1146           g_assert_not_reached ();
1147           break;
1148         }
1149     }
1150 }
1151
1152 static void
1153 draw_with_images (GdkDrawable       *drawable,
1154                   GdkGC             *gc,
1155                   GdkX11FormatType   format_type,
1156                   XRenderPictFormat *format,
1157                   XRenderPictFormat *mask_format,
1158                   guchar            *src_rgb,
1159                   gint               src_rowstride,
1160                   gint               dest_x,
1161                   gint               dest_y,
1162                   gint               width,
1163                   gint               height)
1164 {
1165   GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1166   Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
1167   GdkImage *image;
1168   GdkPixmap *pix;
1169   GdkGC *pix_gc;
1170   Picture pict;
1171   Picture dest_pict;
1172   Picture mask = None;
1173   gint x0, y0;
1174
1175   pix = gdk_pixmap_new (gdk_screen_get_root_window (screen), width, height, 32);
1176                                                   
1177   pict = XRenderCreatePicture (xdisplay, 
1178                                GDK_PIXMAP_XID (pix),
1179                                format, 0, NULL);
1180   if (mask_format)
1181     mask = XRenderCreatePicture (xdisplay, 
1182                                  GDK_PIXMAP_XID (pix),
1183                                  mask_format, 0, NULL);
1184
1185   dest_pict = gdk_x11_drawable_get_picture (drawable);  
1186   
1187   pix_gc = _gdk_drawable_get_scratch_gc (pix, FALSE);
1188
1189   for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1190     {
1191       gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1192       for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1193         {
1194           gint xs0, ys0;
1195           
1196           gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1197           
1198           image = _gdk_image_get_scratch (screen, width1, height1, 32, &xs0, &ys0);
1199           
1200           _gdk_x11_convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1201                                       (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1202                                       format_type, image->byte_order, 
1203                                       width1, height1);
1204
1205           gdk_draw_image (pix, pix_gc,
1206                           image, xs0, ys0, x0, y0, width1, height1);
1207         }
1208     }
1209   
1210   XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict, 
1211                     0, 0, 0, 0, dest_x, dest_y, width, height);
1212
1213   XRenderFreePicture (xdisplay, pict);
1214   if (mask)
1215     XRenderFreePicture (xdisplay, mask);
1216   
1217   g_object_unref (pix);
1218 }
1219
1220 typedef struct _ShmPixmapInfo ShmPixmapInfo;
1221
1222 struct _ShmPixmapInfo
1223 {
1224   Display  *display;
1225   Pixmap    pix;
1226   Picture   pict;
1227   Picture   mask;
1228 };
1229
1230 static void
1231 shm_pixmap_info_destroy (gpointer data)
1232 {
1233   ShmPixmapInfo *info = data;
1234
1235   if (info->pict != None)
1236     XRenderFreePicture (info->display, info->pict);
1237   if (info->mask != None)
1238     XRenderFreePicture (info->display, info->mask);
1239
1240   g_free (data);
1241 }
1242
1243
1244 /* Returns FALSE if we can't get a shm pixmap */
1245 static gboolean
1246 get_shm_pixmap_for_image (Display           *xdisplay,
1247                           GdkImage          *image,
1248                           XRenderPictFormat *format,
1249                           XRenderPictFormat *mask_format,
1250                           Pixmap            *pix,
1251                           Picture           *pict,
1252                           Picture           *mask)
1253 {
1254   ShmPixmapInfo *info;
1255   
1256   if (image->type != GDK_IMAGE_SHARED)
1257     return FALSE;
1258   
1259   info = g_object_get_data (G_OBJECT (image), "gdk-x11-shm-pixmap");
1260   if (!info)
1261     {
1262       *pix = _gdk_x11_image_get_shm_pixmap (image);
1263       
1264       if (!*pix)
1265         return FALSE;
1266       
1267       info = g_new (ShmPixmapInfo, 1);
1268       info->display = xdisplay;
1269       info->pix = *pix;
1270       
1271       info->pict = XRenderCreatePicture (xdisplay, info->pix,
1272                                          format, 0, NULL);
1273       if (mask_format)
1274         info->mask = XRenderCreatePicture (xdisplay, info->pix,
1275                                            mask_format, 0, NULL);
1276       else
1277         info->mask = None;
1278
1279       g_object_set_data_full (G_OBJECT (image), "gdk-x11-shm-pixmap", info,
1280           shm_pixmap_info_destroy);
1281     }
1282
1283   *pix = info->pix;
1284   *pict = info->pict;
1285   *mask = info->mask;
1286
1287   return TRUE;
1288 }
1289
1290 #ifdef USE_SHM
1291 /* Returns FALSE if drawing with ShmPixmaps is not possible */
1292 static gboolean
1293 draw_with_pixmaps (GdkDrawable       *drawable,
1294                    GdkGC             *gc,
1295                    GdkX11FormatType   format_type,
1296                    XRenderPictFormat *format,
1297                    XRenderPictFormat *mask_format,
1298                    guchar            *src_rgb,
1299                    gint               src_rowstride,
1300                    gint               dest_x,
1301                    gint               dest_y,
1302                    gint               width,
1303                    gint               height)
1304 {
1305   Display *xdisplay = GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
1306   GdkImage *image;
1307   Pixmap pix;
1308   Picture pict;
1309   Picture dest_pict;
1310   Picture mask = None;
1311   gint x0, y0;
1312
1313   dest_pict = gdk_x11_drawable_get_picture (drawable);
1314   
1315   for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1316     {
1317       gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1318       for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1319         {
1320           gint xs0, ys0;
1321           
1322           gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1323           
1324           image = _gdk_image_get_scratch (GDK_DRAWABLE_IMPL_X11 (drawable)->screen,
1325                                           width1, height1, 32, &xs0, &ys0);
1326           if (!get_shm_pixmap_for_image (xdisplay, image, format, mask_format, &pix, &pict, &mask))
1327             return FALSE;
1328
1329           _gdk_x11_convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1330                                       (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1331                                       format_type, image->byte_order, 
1332                                       width1, height1);
1333
1334           XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict, 
1335                             xs0, ys0, xs0, ys0, x0 + dest_x, y0 + dest_y,
1336                             width1, height1);
1337         }
1338     }
1339
1340   return TRUE;
1341 }
1342 #endif
1343
1344 static void
1345 gdk_x11_draw_pixbuf (GdkDrawable     *drawable,
1346                      GdkGC           *gc,
1347                      GdkPixbuf       *pixbuf,
1348                      gint             src_x,
1349                      gint             src_y,
1350                      gint             dest_x,
1351                      gint             dest_y,
1352                      gint             width,
1353                      gint             height,
1354                      GdkRgbDither     dither,
1355                      gint             x_dither,
1356                      gint             y_dither)
1357 {
1358   GdkX11FormatType format_type;
1359   XRenderPictFormat *format, *mask_format;
1360   gint rowstride;
1361 #ifdef USE_SHM  
1362   gboolean use_pixmaps = TRUE;
1363 #endif /* USE_SHM */
1364     
1365   format_type = select_format (gdk_drawable_get_display (drawable),
1366                                &format, &mask_format);
1367
1368   if (format_type == GDK_X11_FORMAT_NONE ||
1369       !gdk_pixbuf_get_has_alpha (pixbuf) ||
1370       gdk_drawable_get_depth (drawable) == 1 ||
1371       (dither == GDK_RGB_DITHER_MAX && gdk_drawable_get_depth (drawable) != 24) ||
1372       gdk_x11_drawable_get_picture (drawable) == None)
1373     {
1374       GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
1375       GDK_DRAWABLE_CLASS (_gdk_drawable_impl_x11_parent_class)->draw_pixbuf (wrapper, gc, pixbuf,
1376                                                                              src_x, src_y, dest_x, dest_y,
1377                                                                              width, height,
1378                                                                              dither, x_dither, y_dither);
1379       return;
1380     }
1381
1382   gdk_x11_drawable_update_picture_clip (drawable, gc);
1383
1384   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1385
1386 #ifdef USE_SHM
1387   if (use_pixmaps)
1388     {
1389       if (!draw_with_pixmaps (drawable, gc,
1390                               format_type, format, mask_format,
1391                               gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1392                               rowstride,
1393                               dest_x, dest_y, width, height))
1394         use_pixmaps = FALSE;
1395     }
1396
1397   if (!use_pixmaps)
1398 #endif /* USE_SHM */
1399     draw_with_images (drawable, gc,
1400                       format_type, format, mask_format,
1401                       gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1402                       rowstride,
1403                       dest_x, dest_y, width, height);
1404 }
1405
1406 static void
1407 gdk_x11_cairo_surface_destroy (void *data)
1408 {
1409   GdkDrawableImplX11 *impl = data;
1410
1411   impl->cairo_surface = NULL;
1412 }
1413
1414 void
1415 _gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
1416                                        int width,
1417                                        int height)
1418 {
1419   cairo_xlib_surface_set_size (surface, width, height);
1420 }
1421
1422 cairo_surface_t *
1423 _gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
1424                                      int width,
1425                                      int height)
1426 {
1427   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
1428   GdkVisual *visual;
1429     
1430   visual = gdk_drawable_get_visual (drawable);
1431   if (visual) 
1432     return cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
1433                                       impl->xid,
1434                                       GDK_VISUAL_XVISUAL (visual),
1435                                       width, height);
1436   else if (gdk_drawable_get_depth (drawable) == 1)
1437     return cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
1438                                                     impl->xid,
1439                                                     GDK_SCREEN_XSCREEN (impl->screen),
1440                                                     width, height);
1441   else
1442     {
1443       g_warning ("Using Cairo rendering requires the drawable argument to\n"
1444                  "have a specified colormap. All windows have a colormap,\n"
1445                  "however, pixmaps only have colormap by default if they\n"
1446                  "were created with a non-NULL window argument. Otherwise\n"
1447                  "a colormap must be set on them with gdk_drawable_set_colormap");
1448       return NULL;
1449     }
1450   
1451 }
1452
1453 static cairo_surface_t *
1454 gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
1455 {
1456   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
1457
1458   if (GDK_IS_WINDOW_IMPL_X11 (drawable) &&
1459       GDK_WINDOW_DESTROYED (impl->wrapper))
1460     return NULL;
1461
1462   if (!impl->cairo_surface)
1463     {
1464       int width, height;
1465   
1466       gdk_drawable_get_size (drawable, &width, &height);
1467
1468       impl->cairo_surface = _gdk_windowing_create_cairo_surface (drawable, width, height);
1469       
1470       if (impl->cairo_surface)
1471         cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
1472                                      drawable, gdk_x11_cairo_surface_destroy);
1473     }
1474   else
1475     cairo_surface_reference (impl->cairo_surface);
1476
1477   return impl->cairo_surface;
1478 }