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