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