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