]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdrawable-x11.c
Merge branch 'master' into client-side-windows
[~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 if (GDK_IS_WINDOW (src))
638     src_impl = GDK_DRAWABLE_IMPL_X11(((GdkWindowObject *)src)->impl);
639   else
640     src_impl = GDK_DRAWABLE_IMPL_X11(((GdkPixmapObject *)src)->impl);
641
642   if (GDK_IS_WINDOW_IMPL_X11 (impl) &&
643       GDK_IS_PIXMAP_IMPL_X11 (src_impl))
644     {
645       GdkPixmapImplX11 *src_pixmap = GDK_PIXMAP_IMPL_X11 (src_impl);
646       /* Work around an Xserver bug where non-visible areas from
647        * a pixmap to a window will clear the window background
648        * in destination areas that are supposed to be clipped out.
649        * This is a problem with client side windows as this means
650        * things may draw outside the virtual windows. This could
651        * also happen for window to window copies, but I don't
652        * think we generate any calls like that.
653        *
654        * See: 
655        * http://lists.freedesktop.org/archives/xorg/2009-February/043318.html
656        */
657       if (xsrc < 0)
658         {
659           width += xsrc;
660           xdest -= xsrc;
661           xsrc = 0;
662         }
663       
664       if (ysrc < 0)
665         {
666           height += ysrc;
667           ydest -= ysrc;
668           ysrc = 0;
669         }
670
671       if (xsrc + width > src_pixmap->width)
672         width = src_pixmap->width - xsrc;
673       if (ysrc + height > src_pixmap->height)
674         height = src_pixmap->height - ysrc;
675     }
676   
677   if (src_depth == 1)
678     {
679       XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
680                  src_impl->xid,
681                  impl->xid,
682                  GDK_GC_GET_XGC (gc),
683                  xsrc, ysrc,
684                  width, height,
685                  xdest, ydest);
686     }
687   else if (dest_depth != 0 && src_depth == dest_depth)
688     {
689       XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
690                  src_impl->xid,
691                  impl->xid,
692                  GDK_GC_GET_XGC (gc),
693                  xsrc, ysrc,
694                  width, height,
695                  xdest, ydest);
696     }
697   else
698     g_warning ("Attempt to draw a drawable with depth %d to a drawable with depth %d",
699                src_depth, dest_depth);
700 }
701
702 static void
703 gdk_x11_draw_points (GdkDrawable *drawable,
704                      GdkGC       *gc,
705                      GdkPoint    *points,
706                      gint         npoints)
707 {
708   GdkDrawableImplX11 *impl;
709
710   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
711
712   
713   /* We special-case npoints == 1, because X will merge multiple
714    * consecutive XDrawPoint requests into a PolyPoint request
715    */
716   if (npoints == 1)
717     {
718       XDrawPoint (GDK_SCREEN_XDISPLAY (impl->screen),
719                   impl->xid,
720                   GDK_GC_GET_XGC (gc),
721                   points[0].x, points[0].y);
722     }
723   else
724     {
725       gint i;
726       XPoint *tmp_points = g_new (XPoint, npoints);
727
728       for (i=0; i<npoints; i++)
729         {
730           tmp_points[i].x = points[i].x;
731           tmp_points[i].y = points[i].y;
732         }
733       
734       XDrawPoints (GDK_SCREEN_XDISPLAY (impl->screen),
735                    impl->xid,
736                    GDK_GC_GET_XGC (gc),
737                    tmp_points,
738                    npoints,
739                    CoordModeOrigin);
740
741       g_free (tmp_points);
742     }
743 }
744
745 static void
746 gdk_x11_draw_segments (GdkDrawable *drawable,
747                        GdkGC       *gc,
748                        GdkSegment  *segs,
749                        gint         nsegs)
750 {
751   GdkDrawableImplX11 *impl;
752
753   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
754
755   
756   /* We special-case nsegs == 1, because X will merge multiple
757    * consecutive XDrawLine requests into a PolySegment request
758    */
759   if (nsegs == 1)
760     {
761       XDrawLine (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
762                  GDK_GC_GET_XGC (gc), segs[0].x1, segs[0].y1,
763                  segs[0].x2, segs[0].y2);
764     }
765   else
766     {
767       gint i;
768       XSegment *tmp_segs = g_new (XSegment, nsegs);
769
770       for (i=0; i<nsegs; i++)
771         {
772           tmp_segs[i].x1 = segs[i].x1;
773           tmp_segs[i].x2 = segs[i].x2;
774           tmp_segs[i].y1 = segs[i].y1;
775           tmp_segs[i].y2 = segs[i].y2;
776         }
777       
778       XDrawSegments (GDK_SCREEN_XDISPLAY (impl->screen),
779                      impl->xid,
780                      GDK_GC_GET_XGC (gc),
781                      tmp_segs, nsegs);
782
783       g_free (tmp_segs);
784     }
785 }
786
787 static void
788 gdk_x11_draw_lines (GdkDrawable *drawable,
789                     GdkGC       *gc,
790                     GdkPoint    *points,
791                     gint         npoints)
792 {
793   gint i;
794   XPoint *tmp_points = g_new (XPoint, npoints);
795   GdkDrawableImplX11 *impl;
796
797   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
798
799   
800   for (i=0; i<npoints; i++)
801     {
802       tmp_points[i].x = points[i].x;
803       tmp_points[i].y = points[i].y;
804     }
805       
806   XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen),
807               impl->xid,
808               GDK_GC_GET_XGC (gc),
809               tmp_points, npoints,
810               CoordModeOrigin);
811
812   g_free (tmp_points);
813 }
814
815 static void
816 gdk_x11_draw_image     (GdkDrawable     *drawable,
817                         GdkGC           *gc,
818                         GdkImage        *image,
819                         gint             xsrc,
820                         gint             ysrc,
821                         gint             xdest,
822                         gint             ydest,
823                         gint             width,
824                         gint             height)
825 {
826   GdkDrawableImplX11 *impl;
827
828   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
829
830 #ifdef USE_SHM  
831   if (image->type == GDK_IMAGE_SHARED)
832     XShmPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
833                   GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
834                   xsrc, ysrc, xdest, ydest, width, height, False);
835   else
836 #endif
837     XPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
838                GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
839                xsrc, ysrc, xdest, ydest, width, height);
840 }
841
842 static gint
843 gdk_x11_get_depth (GdkDrawable *drawable)
844 {
845   /* This is a bit bogus but I'm not sure the other way is better */
846
847   return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
848 }
849
850 static GdkDrawable *
851 get_impl_drawable (GdkDrawable *drawable)
852 {
853   if (GDK_IS_WINDOW (drawable))
854     return ((GdkWindowObject *)drawable)->impl;
855   else if (GDK_IS_PIXMAP (drawable))
856     return ((GdkPixmapObject *)drawable)->impl;
857   else
858     {
859       g_warning (G_STRLOC " drawable is not a pixmap or window");
860       return NULL;
861     }
862 }
863
864 static GdkScreen*
865 gdk_x11_get_screen (GdkDrawable *drawable)
866 {
867   if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
868     return GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
869   else
870     return GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen;
871 }
872
873 static GdkVisual*
874 gdk_x11_get_visual (GdkDrawable    *drawable)
875 {
876   return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
877 }
878
879 /**
880  * gdk_x11_drawable_get_xdisplay:
881  * @drawable: a #GdkDrawable.
882  * 
883  * Returns the display of a #GdkDrawable.
884  * 
885  * Return value: an Xlib <type>Display*</type>.
886  **/
887 Display *
888 gdk_x11_drawable_get_xdisplay (GdkDrawable *drawable)
889 {
890   if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
891     return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
892   else
893     return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen);
894 }
895
896 /**
897  * gdk_x11_drawable_get_xid:
898  * @drawable: a #GdkDrawable.
899  * 
900  * Returns the X resource (window or pixmap) belonging to a #GdkDrawable.
901  * 
902  * Return value: the ID of @drawable's X resource.
903  **/
904 XID
905 gdk_x11_drawable_get_xid (GdkDrawable *drawable)
906 {
907   GdkDrawable *impl;
908   
909   if (GDK_IS_WINDOW (drawable))
910     {
911       GdkWindow *window = (GdkWindow *)drawable;
912       
913       /* Try to ensure the window has a native window */
914       if (!_gdk_window_has_impl (window))
915         {
916           gdk_window_set_has_native (window, TRUE);
917
918           /* We sync here to ensure the window is created in the Xserver when
919            * this function returns. This is required because the returned XID
920            * for this window must be valid immediately, even with another
921            * connection to the Xserver */
922           gdk_display_sync (gdk_drawable_get_display (window));
923         }
924       
925       if (!GDK_WINDOW_IS_X11 (window))
926         {
927           g_warning (G_STRLOC " drawable is not a native X11 window");
928           return None;
929         }
930       
931       impl = ((GdkWindowObject *)drawable)->impl;
932     }
933   else if (GDK_IS_PIXMAP (drawable))
934     impl = ((GdkPixmapObject *)drawable)->impl;
935   else
936     {
937       g_warning (G_STRLOC " drawable is not a pixmap or window");
938       return None;
939     }
940
941   return ((GdkDrawableImplX11 *)impl)->xid;
942 }
943
944 /* Code for accelerated alpha compositing using the RENDER extension.
945  * It's a bit long because there are lots of possibilities for
946  * what's the fastest depending on the available picture formats,
947  * whether we can used shared pixmaps, etc.
948  */
949
950 static GdkX11FormatType
951 select_format (GdkDisplay         *display,
952                XRenderPictFormat **format,
953                XRenderPictFormat **mask)
954 {
955   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
956   XRenderPictFormat pf;
957
958   if (!_gdk_x11_have_render (display))
959     return GDK_X11_FORMAT_NONE;
960   
961   /* Look for a 32-bit xRGB and Axxx formats that exactly match the
962    * in memory data format. We can use them as pixmap and mask
963    * to deal with non-premultiplied data.
964    */
965
966   pf.type = PictTypeDirect;
967   pf.depth = 32;
968   pf.direct.redMask = 0xff;
969   pf.direct.greenMask = 0xff;
970   pf.direct.blueMask = 0xff;
971   
972   pf.direct.alphaMask = 0;
973   if (ImageByteOrder (xdisplay) == LSBFirst)
974     {
975       /* ABGR */
976       pf.direct.red = 0;
977       pf.direct.green = 8;
978       pf.direct.blue = 16;
979     }
980   else
981     {
982       /* RGBA */
983       pf.direct.red = 24;
984       pf.direct.green = 16;
985       pf.direct.blue = 8;
986     }
987   
988   *format = XRenderFindFormat (xdisplay,
989                                (PictFormatType | PictFormatDepth |
990                                 PictFormatRedMask | PictFormatRed |
991                                 PictFormatGreenMask | PictFormatGreen |
992                                 PictFormatBlueMask | PictFormatBlue |
993                                 PictFormatAlphaMask),
994                                &pf,
995                                0);
996
997   pf.direct.alphaMask = 0xff;
998   if (ImageByteOrder (xdisplay) == LSBFirst)
999     {
1000       /* ABGR */
1001       pf.direct.alpha = 24;
1002     }
1003   else
1004     {
1005       pf.direct.alpha = 0;
1006     }
1007   
1008   *mask = XRenderFindFormat (xdisplay,
1009                              (PictFormatType | PictFormatDepth |
1010                               PictFormatAlphaMask | PictFormatAlpha),
1011                              &pf,
1012                              0);
1013
1014   if (*format && *mask)
1015     return GDK_X11_FORMAT_EXACT_MASK;
1016
1017   /* OK, that failed, now look for xRGB and Axxx formats in
1018    * RENDER's preferred order
1019    */
1020   pf.direct.alphaMask = 0;
1021   /* ARGB */
1022   pf.direct.red = 16;
1023   pf.direct.green = 8;
1024   pf.direct.blue = 0;
1025   
1026   *format = XRenderFindFormat (xdisplay,
1027                                (PictFormatType | PictFormatDepth |
1028                                 PictFormatRedMask | PictFormatRed |
1029                                 PictFormatGreenMask | PictFormatGreen |
1030                                 PictFormatBlueMask | PictFormatBlue |
1031                                 PictFormatAlphaMask),
1032                                &pf,
1033                                0);
1034
1035   pf.direct.alphaMask = 0xff;
1036   pf.direct.alpha = 24;
1037   
1038   *mask = XRenderFindFormat (xdisplay,
1039                              (PictFormatType | PictFormatDepth |
1040                               PictFormatAlphaMask | PictFormatAlpha),
1041                              &pf,
1042                              0);
1043
1044   if (*format && *mask)
1045     return GDK_X11_FORMAT_ARGB_MASK;
1046
1047   /* Finally, if neither of the above worked, fall back to
1048    * looking for combined ARGB -- we'll premultiply ourselves.
1049    */
1050
1051   pf.type = PictTypeDirect;
1052   pf.depth = 32;
1053   pf.direct.red = 16;
1054   pf.direct.green = 8;
1055   pf.direct.blue = 0;
1056   pf.direct.alphaMask = 0xff;
1057   pf.direct.alpha = 24;
1058
1059   *format = XRenderFindFormat (xdisplay,
1060                                (PictFormatType | PictFormatDepth |
1061                                 PictFormatRedMask | PictFormatRed |
1062                                 PictFormatGreenMask | PictFormatGreen |
1063                                 PictFormatBlueMask | PictFormatBlue |
1064                                 PictFormatAlphaMask | PictFormatAlpha),
1065                                &pf,
1066                                0);
1067   *mask = NULL;
1068
1069   if (*format)
1070     return GDK_X11_FORMAT_ARGB;
1071
1072   return GDK_X11_FORMAT_NONE;
1073 }
1074
1075 #if 0
1076 static void
1077 list_formats (XRenderPictFormat *pf)
1078 {
1079   gint i;
1080   
1081   for (i=0 ;; i++)
1082     {
1083       XRenderPictFormat *pf = XRenderFindFormat (impl->xdisplay, 0, NULL, i);
1084       if (pf)
1085         {
1086           g_print ("%2d R-%#06x/%#06x G-%#06x/%#06x B-%#06x/%#06x A-%#06x/%#06x\n",
1087                    pf->depth,
1088                    pf->direct.red,
1089                    pf->direct.redMask,
1090                    pf->direct.green,
1091                    pf->direct.greenMask,
1092                    pf->direct.blue,
1093                    pf->direct.blueMask,
1094                    pf->direct.alpha,
1095                    pf->direct.alphaMask);
1096         }
1097       else
1098         break;
1099     }
1100 }
1101 #endif  
1102
1103 void
1104 _gdk_x11_convert_to_format (guchar           *src_buf,
1105                             gint              src_rowstride,
1106                             guchar           *dest_buf,
1107                             gint              dest_rowstride,
1108                             GdkX11FormatType  dest_format,
1109                             GdkByteOrder      dest_byteorder,
1110                             gint              width,
1111                             gint              height)
1112 {
1113   gint i;
1114
1115   for (i=0; i < height; i++)
1116     {
1117       switch (dest_format)
1118         {
1119         case GDK_X11_FORMAT_EXACT_MASK:
1120           {
1121             memcpy (dest_buf + i * dest_rowstride,
1122                     src_buf + i * src_rowstride,
1123                     width * 4);
1124             break;
1125           }
1126         case GDK_X11_FORMAT_ARGB_MASK:
1127           {
1128             guchar *row = src_buf + i * src_rowstride;
1129             if (((gsize)row & 3) != 0)
1130               {
1131                 guchar *p = row;
1132                 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1133                 guchar *end = p + 4 * width;
1134
1135                 while (p < end)
1136                   {
1137                     *q = (p[3] << 24) | (p[0] << 16) | (p[1] << 8) | p[2];
1138                     p += 4;
1139                     q++;
1140                   }
1141               }
1142             else
1143               {
1144                 guint32 *p = (guint32 *)row;
1145                 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1146                 guint32 *end = p + width;
1147
1148 #if G_BYTE_ORDER == G_LITTLE_ENDIAN         
1149                 if (dest_byteorder == GDK_LSB_FIRST)
1150                   {
1151                     /* ABGR => ARGB */
1152                 
1153                     while (p < end)
1154                       {
1155                         *q = ( (*p & 0xff00ff00) |
1156                                ((*p & 0x000000ff) << 16) |
1157                                ((*p & 0x00ff0000) >> 16));
1158                         q++;
1159                         p++;
1160                       }
1161                   }
1162                 else
1163                   {
1164                     /* ABGR => BGRA */
1165                 
1166                     while (p < end)
1167                       {
1168                         *q = (((*p & 0xff000000) >> 24) |
1169                               ((*p & 0x00ffffff) << 8));
1170                         q++;
1171                         p++;
1172                       }
1173                   }
1174 #else /* G_BYTE_ORDER == G_BIG_ENDIAN */
1175                 if (dest_byteorder == GDK_LSB_FIRST)
1176                   {
1177                     /* RGBA => BGRA */
1178                 
1179                     while (p < end)
1180                       {
1181                         *q = ( (*p & 0x00ff00ff) |
1182                                ((*p & 0x0000ff00) << 16) |
1183                                ((*p & 0xff000000) >> 16));
1184                         q++;
1185                         p++;
1186                       }
1187                   }
1188                 else
1189                   {
1190                     /* RGBA => ARGB */
1191                 
1192                     while (p < end)
1193                       {
1194                         *q = (((*p & 0xffffff00) >> 8) |
1195                               ((*p & 0x000000ff) << 24));
1196                         q++;
1197                         p++;
1198                       }
1199                   }
1200 #endif /* G_BYTE_ORDER*/            
1201               }
1202             break;
1203           }
1204         case GDK_X11_FORMAT_ARGB:
1205           {
1206             guchar *p = (src_buf + i * src_rowstride);
1207             guchar *q = (dest_buf + i * dest_rowstride);
1208             guchar *end = p + 4 * width;
1209             guint t1,t2,t3;
1210             
1211 #define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END
1212             
1213             if (dest_byteorder == GDK_LSB_FIRST)
1214               {
1215                 while (p < end)
1216                   {
1217                     MULT(q[0], p[2], p[3], t1);
1218                     MULT(q[1], p[1], p[3], t2);
1219                     MULT(q[2], p[0], p[3], t3);
1220                     q[3] = p[3];
1221                     p += 4;
1222                     q += 4;
1223                   }
1224               }
1225             else
1226               {
1227                 while (p < end)
1228                   {
1229                     q[0] = p[3];
1230                     MULT(q[1], p[0], p[3], t1);
1231                     MULT(q[2], p[1], p[3], t2);
1232                     MULT(q[3], p[2], p[3], t3);
1233                     p += 4;
1234                     q += 4;
1235                   }
1236               }
1237 #undef MULT
1238             break;
1239           }
1240         case GDK_X11_FORMAT_NONE:
1241           g_assert_not_reached ();
1242           break;
1243         }
1244     }
1245 }
1246
1247 static void
1248 draw_with_images (GdkDrawable       *drawable,
1249                   GdkGC             *gc,
1250                   GdkX11FormatType   format_type,
1251                   XRenderPictFormat *format,
1252                   XRenderPictFormat *mask_format,
1253                   guchar            *src_rgb,
1254                   gint               src_rowstride,
1255                   gint               dest_x,
1256                   gint               dest_y,
1257                   gint               width,
1258                   gint               height)
1259 {
1260   GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1261   Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
1262   GdkImage *image;
1263   GdkPixmap *pix;
1264   GdkGC *pix_gc;
1265   Picture pict;
1266   Picture dest_pict;
1267   Picture mask = None;
1268   gint x0, y0;
1269
1270   pix = gdk_pixmap_new (gdk_screen_get_root_window (screen), width, height, 32);
1271                                                   
1272   pict = XRenderCreatePicture (xdisplay, 
1273                                GDK_PIXMAP_XID (pix),
1274                                format, 0, NULL);
1275   if (mask_format)
1276     mask = XRenderCreatePicture (xdisplay, 
1277                                  GDK_PIXMAP_XID (pix),
1278                                  mask_format, 0, NULL);
1279
1280   dest_pict = gdk_x11_drawable_get_picture (drawable);  
1281   
1282   pix_gc = _gdk_drawable_get_scratch_gc (pix, FALSE);
1283
1284   for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1285     {
1286       gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1287       for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1288         {
1289           gint xs0, ys0;
1290           
1291           gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1292           
1293           image = _gdk_image_get_scratch (screen, width1, height1, 32, &xs0, &ys0);
1294           
1295           _gdk_x11_convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1296                                       (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1297                                       format_type, image->byte_order, 
1298                                       width1, height1);
1299
1300           gdk_draw_image (pix, pix_gc,
1301                           image, xs0, ys0, x0, y0, width1, height1);
1302         }
1303     }
1304   
1305   XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict, 
1306                     0, 0, 0, 0, dest_x, dest_y, width, height);
1307
1308   XRenderFreePicture (xdisplay, pict);
1309   if (mask)
1310     XRenderFreePicture (xdisplay, mask);
1311   
1312   g_object_unref (pix);
1313 }
1314
1315 typedef struct _ShmPixmapInfo ShmPixmapInfo;
1316
1317 struct _ShmPixmapInfo
1318 {
1319   Display  *display;
1320   Pixmap    pix;
1321   Picture   pict;
1322   Picture   mask;
1323 };
1324
1325 static void
1326 shm_pixmap_info_destroy (gpointer data)
1327 {
1328   ShmPixmapInfo *info = data;
1329
1330   if (info->pict != None)
1331     XRenderFreePicture (info->display, info->pict);
1332   if (info->mask != None)
1333     XRenderFreePicture (info->display, info->mask);
1334
1335   g_free (data);
1336 }
1337
1338
1339 /* Returns FALSE if we can't get a shm pixmap */
1340 static gboolean
1341 get_shm_pixmap_for_image (Display           *xdisplay,
1342                           GdkImage          *image,
1343                           XRenderPictFormat *format,
1344                           XRenderPictFormat *mask_format,
1345                           Pixmap            *pix,
1346                           Picture           *pict,
1347                           Picture           *mask)
1348 {
1349   ShmPixmapInfo *info;
1350   
1351   if (image->type != GDK_IMAGE_SHARED)
1352     return FALSE;
1353   
1354   info = g_object_get_data (G_OBJECT (image), "gdk-x11-shm-pixmap");
1355   if (!info)
1356     {
1357       *pix = _gdk_x11_image_get_shm_pixmap (image);
1358       
1359       if (!*pix)
1360         return FALSE;
1361       
1362       info = g_new (ShmPixmapInfo, 1);
1363       info->display = xdisplay;
1364       info->pix = *pix;
1365       
1366       info->pict = XRenderCreatePicture (xdisplay, info->pix,
1367                                          format, 0, NULL);
1368       if (mask_format)
1369         info->mask = XRenderCreatePicture (xdisplay, info->pix,
1370                                            mask_format, 0, NULL);
1371       else
1372         info->mask = None;
1373
1374       g_object_set_data_full (G_OBJECT (image), "gdk-x11-shm-pixmap", info,
1375           shm_pixmap_info_destroy);
1376     }
1377
1378   *pix = info->pix;
1379   *pict = info->pict;
1380   *mask = info->mask;
1381
1382   return TRUE;
1383 }
1384
1385 #ifdef USE_SHM
1386 /* Returns FALSE if drawing with ShmPixmaps is not possible */
1387 static gboolean
1388 draw_with_pixmaps (GdkDrawable       *drawable,
1389                    GdkGC             *gc,
1390                    GdkX11FormatType   format_type,
1391                    XRenderPictFormat *format,
1392                    XRenderPictFormat *mask_format,
1393                    guchar            *src_rgb,
1394                    gint               src_rowstride,
1395                    gint               dest_x,
1396                    gint               dest_y,
1397                    gint               width,
1398                    gint               height)
1399 {
1400   Display *xdisplay = GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
1401   GdkImage *image;
1402   Pixmap pix;
1403   Picture pict;
1404   Picture dest_pict;
1405   Picture mask = None;
1406   gint x0, y0;
1407
1408   dest_pict = gdk_x11_drawable_get_picture (drawable);
1409   
1410   for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1411     {
1412       gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1413       for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1414         {
1415           gint xs0, ys0;
1416           
1417           gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1418           
1419           image = _gdk_image_get_scratch (GDK_DRAWABLE_IMPL_X11 (drawable)->screen,
1420                                           width1, height1, 32, &xs0, &ys0);
1421           if (!get_shm_pixmap_for_image (xdisplay, image, format, mask_format, &pix, &pict, &mask))
1422             return FALSE;
1423
1424           _gdk_x11_convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1425                                       (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1426                                       format_type, image->byte_order, 
1427                                       width1, height1);
1428
1429           XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict, 
1430                             xs0, ys0, xs0, ys0, x0 + dest_x, y0 + dest_y,
1431                             width1, height1);
1432         }
1433     }
1434
1435   return TRUE;
1436 }
1437 #endif
1438
1439 static void
1440 gdk_x11_draw_pixbuf (GdkDrawable     *drawable,
1441                      GdkGC           *gc,
1442                      GdkPixbuf       *pixbuf,
1443                      gint             src_x,
1444                      gint             src_y,
1445                      gint             dest_x,
1446                      gint             dest_y,
1447                      gint             width,
1448                      gint             height,
1449                      GdkRgbDither     dither,
1450                      gint             x_dither,
1451                      gint             y_dither)
1452 {
1453   GdkX11FormatType format_type;
1454   XRenderPictFormat *format, *mask_format;
1455   gint rowstride;
1456 #ifdef USE_SHM  
1457   gboolean use_pixmaps = TRUE;
1458 #endif /* USE_SHM */
1459     
1460   format_type = select_format (gdk_drawable_get_display (drawable),
1461                                &format, &mask_format);
1462
1463   if (format_type == GDK_X11_FORMAT_NONE ||
1464       !gdk_pixbuf_get_has_alpha (pixbuf) ||
1465       gdk_drawable_get_depth (drawable) == 1 ||
1466       (dither == GDK_RGB_DITHER_MAX && gdk_drawable_get_depth (drawable) != 24) ||
1467       gdk_x11_drawable_get_picture (drawable) == None)
1468     {
1469       GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
1470       GDK_DRAWABLE_CLASS (_gdk_drawable_impl_x11_parent_class)->draw_pixbuf (wrapper, gc, pixbuf,
1471                                                                              src_x, src_y, dest_x, dest_y,
1472                                                                              width, height,
1473                                                                              dither, x_dither, y_dither);
1474       return;
1475     }
1476
1477   gdk_x11_drawable_update_picture_clip (drawable, gc);
1478
1479   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1480
1481 #ifdef USE_SHM
1482   if (use_pixmaps)
1483     {
1484       if (!draw_with_pixmaps (drawable, gc,
1485                               format_type, format, mask_format,
1486                               gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1487                               rowstride,
1488                               dest_x, dest_y, width, height))
1489         use_pixmaps = FALSE;
1490     }
1491
1492   if (!use_pixmaps)
1493 #endif /* USE_SHM */
1494     draw_with_images (drawable, gc,
1495                       format_type, format, mask_format,
1496                       gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1497                       rowstride,
1498                       dest_x, dest_y, width, height);
1499 }
1500
1501 static void
1502 gdk_x11_cairo_surface_destroy (void *data)
1503 {
1504   GdkDrawableImplX11 *impl = data;
1505
1506   impl->cairo_surface = NULL;
1507 }
1508
1509 void
1510 _gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
1511                                        int width,
1512                                        int height)
1513 {
1514   cairo_xlib_surface_set_size (surface, width, height);
1515 }
1516
1517 cairo_surface_t *
1518 _gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
1519                                      int width,
1520                                      int height)
1521 {
1522   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
1523   GdkVisual *visual;
1524     
1525   visual = gdk_drawable_get_visual (drawable);
1526   if (visual) 
1527     return cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
1528                                       impl->xid,
1529                                       GDK_VISUAL_XVISUAL (visual),
1530                                       width, height);
1531   else if (gdk_drawable_get_depth (drawable) == 1)
1532     return cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
1533                                                     impl->xid,
1534                                                     GDK_SCREEN_XSCREEN (impl->screen),
1535                                                     width, height);
1536   else
1537     {
1538       g_warning ("Using Cairo rendering requires the drawable argument to\n"
1539                  "have a specified colormap. All windows have a colormap,\n"
1540                  "however, pixmaps only have colormap by default if they\n"
1541                  "were created with a non-NULL window argument. Otherwise\n"
1542                  "a colormap must be set on them with gdk_drawable_set_colormap");
1543       return NULL;
1544     }
1545   
1546 }
1547
1548 static cairo_surface_t *
1549 gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
1550 {
1551   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
1552
1553   if (GDK_IS_WINDOW_IMPL_X11 (drawable) &&
1554       GDK_WINDOW_DESTROYED (impl->wrapper))
1555     return NULL;
1556
1557   if (!impl->cairo_surface)
1558     {
1559       int width, height;
1560   
1561       gdk_drawable_get_size (drawable, &width, &height);
1562
1563       impl->cairo_surface = _gdk_windowing_create_cairo_surface (drawable, width, height);
1564       
1565       if (impl->cairo_surface)
1566         cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
1567                                      drawable, gdk_x11_cairo_surface_destroy);
1568     }
1569   else
1570     cairo_surface_reference (impl->cairo_surface);
1571
1572   return impl->cairo_surface;
1573 }
1574
1575 #define __GDK_DRAWABLE_X11_C__
1576 #include "gdkaliasdef.c"