2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
30 #include "gdkregion-generic.h"
32 #include <pango/pangoxft.h>
35 #include <string.h> /* for memcpy() */
37 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
42 #include <X11/extensions/XShm.h>
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"
51 static void gdk_x11_draw_rectangle (GdkDrawable *drawable,
58 static void gdk_x11_draw_arc (GdkDrawable *drawable,
67 static void gdk_x11_draw_polygon (GdkDrawable *drawable,
72 static void gdk_x11_draw_text (GdkDrawable *drawable,
79 static void gdk_x11_draw_text_wc (GdkDrawable *drawable,
86 static void gdk_x11_draw_drawable (GdkDrawable *drawable,
95 static void gdk_x11_draw_points (GdkDrawable *drawable,
99 static void gdk_x11_draw_segments (GdkDrawable *drawable,
103 static void gdk_x11_draw_lines (GdkDrawable *drawable,
107 static void gdk_x11_draw_glyphs (GdkDrawable *drawable,
112 PangoGlyphString *glyphs);
113 static void gdk_x11_draw_image (GdkDrawable *drawable,
122 static void gdk_x11_draw_pixbuf (GdkDrawable *drawable,
135 static void gdk_x11_set_colormap (GdkDrawable *drawable,
136 GdkColormap *colormap);
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);
143 static void gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass);
145 static void gdk_drawable_impl_x11_finalize (GObject *object);
147 static gpointer parent_class = NULL;
150 _gdk_drawable_impl_x11_get_type (void)
152 static GType object_type = 0;
156 static const GTypeInfo object_info =
158 sizeof (GdkDrawableImplX11Class),
159 (GBaseInitFunc) NULL,
160 (GBaseFinalizeFunc) NULL,
161 (GClassInitFunc) gdk_drawable_impl_x11_class_init,
162 NULL, /* class_finalize */
163 NULL, /* class_data */
164 sizeof (GdkDrawableImplX11),
166 (GInstanceInitFunc) NULL,
169 object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
170 "GdkDrawableImplX11",
178 gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
180 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
181 GObjectClass *object_class = G_OBJECT_CLASS (klass);
183 parent_class = g_type_class_peek_parent (klass);
185 object_class->finalize = gdk_drawable_impl_x11_finalize;
187 drawable_class->create_gc = _gdk_x11_gc_new;
188 drawable_class->draw_rectangle = gdk_x11_draw_rectangle;
189 drawable_class->draw_arc = gdk_x11_draw_arc;
190 drawable_class->draw_polygon = gdk_x11_draw_polygon;
191 drawable_class->draw_text = gdk_x11_draw_text;
192 drawable_class->draw_text_wc = gdk_x11_draw_text_wc;
193 drawable_class->draw_drawable = gdk_x11_draw_drawable;
194 drawable_class->draw_points = gdk_x11_draw_points;
195 drawable_class->draw_segments = gdk_x11_draw_segments;
196 drawable_class->draw_lines = gdk_x11_draw_lines;
197 drawable_class->draw_glyphs = gdk_x11_draw_glyphs;
198 drawable_class->draw_image = gdk_x11_draw_image;
199 drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf;
201 drawable_class->set_colormap = gdk_x11_set_colormap;
202 drawable_class->get_colormap = gdk_x11_get_colormap;
204 drawable_class->get_depth = gdk_x11_get_depth;
205 drawable_class->get_screen = gdk_x11_get_screen;
206 drawable_class->get_visual = gdk_x11_get_visual;
208 drawable_class->_copy_to_image = _gdk_x11_copy_to_image;
212 gdk_drawable_impl_x11_finalize (GObject *object)
214 gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
216 G_OBJECT_CLASS (parent_class)->finalize (object);
220 try_pixmap (Display *xdisplay,
224 Pixmap pixmap = XCreatePixmap (xdisplay,
225 RootWindow (xdisplay, screen),
227 XFreePixmap (xdisplay, pixmap);
231 _gdk_x11_have_render (GdkDisplay *display)
233 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
234 GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
236 if (x11display->have_render == GDK_UNKNOWN)
238 int event_base, error_base;
239 x11display->have_render =
240 XRenderQueryExtension (xdisplay, &event_base, &error_base)
243 if (x11display->have_render == GDK_YES)
246 * Sun advertises RENDER, but fails to support 32-bit pixmaps.
247 * That is just no good. Therefore, we check all screens
248 * for proper support.
252 for (screen = 0; screen < ScreenCount (xdisplay); screen++)
255 int *depths = XListDepths (xdisplay, screen, &count);
256 gboolean has_8 = FALSE, has_32 = FALSE;
262 for (i = 0; i < count; i++)
266 else if (depths[i] == 32)
272 /* At this point, we might have a false positive;
273 * buggy versions of Xinerama only report depths for
274 * which there is an associated visual; so we actually
275 * go ahead and try create pixmaps.
277 if (!(has_8 && has_32))
279 gdk_error_trap_push ();
281 try_pixmap (xdisplay, screen, 8);
283 try_pixmap (xdisplay, screen, 32);
284 XSync (xdisplay, False);
285 if (gdk_error_trap_pop () == 0)
292 if (!(has_8 && has_32))
294 g_warning ("The X server advertises that RENDER support is present,\n"
295 "but fails to supply the necessary pixmap support. In\n"
296 "other words, it is buggy.");
297 x11display->have_render = GDK_NO;
304 return x11display->have_render == GDK_YES;
308 gdk_x11_drawable_get_xft_draw (GdkDrawable *drawable)
310 GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
312 if (impl->xft_draw == NULL)
314 GdkColormap *colormap = gdk_drawable_get_colormap (drawable);
320 visual = gdk_colormap_get_visual (colormap);
322 impl->xft_draw = XftDrawCreate (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
323 GDK_VISUAL_XVISUAL (visual), GDK_COLORMAP_XCOLORMAP (colormap));
325 else if (gdk_drawable_get_depth (drawable) == 1)
327 impl->xft_draw = XftDrawCreateBitmap (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid);
331 g_warning ("Using Xft rendering requires the drawable argument to\n"
332 "have a specified colormap. All windows have a colormap,\n"
333 "however, pixmaps only have colormap by default if they\n"
334 "were created with a non-NULL window argument. Otherwise\n"
335 "a colormap must be set on them with gdk_drawable_set_colormap");
340 return impl->xft_draw;
344 gdk_x11_drawable_get_picture (GdkDrawable *drawable)
346 XftDraw *draw = gdk_x11_drawable_get_xft_draw (drawable);
348 return draw ? XftDrawPicture (draw) : None;
352 gdk_x11_drawable_update_xft_clip (GdkDrawable *drawable,
355 GdkGCX11 *gc_private = gc ? GDK_GC_X11 (gc) : NULL;
356 XftDraw *xft_draw = gdk_x11_drawable_get_xft_draw (drawable);
358 if (gc && gc_private->clip_region)
360 GdkRegionBox *boxes = gc_private->clip_region->rects;
361 gint n_boxes = gc_private->clip_region->numRects;
362 #if 0 /* Until XftDrawSetClipRectangles is there */
363 XRectangle *rects = g_new (XRectangle, n_boxes);
366 for (i=0; i < n_boxes; i++)
368 rects[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
369 rects[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
370 rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x;
371 rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y;
373 XftDrawSetClipRectangles (xft_draw, 0, 0, rects, n_boxes);
377 Region xregion = XCreateRegion ();
380 for (i=0; i < n_boxes; i++)
384 rect.x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
385 rect.y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
386 rect.width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rect.x;
387 rect.height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rect.y;
389 XUnionRectWithRegion (&rect, xregion, xregion);
392 XftDrawSetClip (xft_draw, xregion);
393 XDestroyRegion (xregion);
398 XftDrawSetClip (xft_draw, NULL);
402 /*****************************************************
403 * X11 specific implementations of generic functions *
404 *****************************************************/
407 gdk_x11_get_colormap (GdkDrawable *drawable)
409 GdkDrawableImplX11 *impl;
411 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
413 return impl->colormap;
417 gdk_x11_set_colormap (GdkDrawable *drawable,
418 GdkColormap *colormap)
420 GdkDrawableImplX11 *impl;
422 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
424 if (impl->colormap == colormap)
428 g_object_unref (impl->colormap);
429 impl->colormap = colormap;
431 g_object_ref (impl->colormap);
438 gdk_x11_draw_rectangle (GdkDrawable *drawable,
446 GdkDrawableImplX11 *impl;
448 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
451 XFillRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
452 GDK_GC_GET_XGC (gc), x, y, width, height);
454 XDrawRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
455 GDK_GC_GET_XGC (gc), x, y, width, height);
459 gdk_x11_draw_arc (GdkDrawable *drawable,
469 GdkDrawableImplX11 *impl;
471 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
475 XFillArc (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
476 GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
478 XDrawArc (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
479 GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
483 gdk_x11_draw_polygon (GdkDrawable *drawable,
491 GdkDrawableImplX11 *impl;
493 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
497 (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y))
499 tmp_npoints = npoints + 1;
500 tmp_points = g_new (XPoint, tmp_npoints);
501 tmp_points[npoints].x = points[0].x;
502 tmp_points[npoints].y = points[0].y;
506 tmp_npoints = npoints;
507 tmp_points = g_new (XPoint, tmp_npoints);
510 for (i=0; i<npoints; i++)
512 tmp_points[i].x = points[i].x;
513 tmp_points[i].y = points[i].y;
517 XFillPolygon (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
518 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, Complex, CoordModeOrigin);
520 XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
521 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, CoordModeOrigin);
528 * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
530 * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
533 gdk_x11_draw_text (GdkDrawable *drawable,
541 GdkDrawableImplX11 *impl;
544 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
545 xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
547 if (font->type == GDK_FONT_FONT)
549 XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
550 XSetFont(xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
551 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
553 XDrawString (xdisplay, impl->xid,
554 GDK_GC_GET_XGC (gc), x, y, text, text_length);
558 XDrawString16 (xdisplay, impl->xid,
559 GDK_GC_GET_XGC (gc), x, y, (XChar2b *) text, text_length / 2);
562 else if (font->type == GDK_FONT_FONTSET)
564 XFontSet fontset = (XFontSet) GDK_FONT_XFONT (font);
565 XmbDrawString (xdisplay, impl->xid,
566 fontset, GDK_GC_GET_XGC (gc), x, y, text, text_length);
569 g_error("undefined font type\n");
573 gdk_x11_draw_text_wc (GdkDrawable *drawable,
578 const GdkWChar *text,
581 GdkDrawableImplX11 *impl;
584 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
585 xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
587 if (font->type == GDK_FONT_FONT)
589 XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
592 XSetFont(xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
593 text_8bit = g_new (gchar, text_length);
594 for (i=0; i<text_length; i++) text_8bit[i] = text[i];
595 XDrawString (xdisplay, impl->xid,
596 GDK_GC_GET_XGC (gc), x, y, text_8bit, text_length);
599 else if (font->type == GDK_FONT_FONTSET)
601 if (sizeof(GdkWChar) == sizeof(wchar_t))
603 XwcDrawString (xdisplay, impl->xid,
604 (XFontSet) GDK_FONT_XFONT (font),
605 GDK_GC_GET_XGC (gc), x, y, (wchar_t *)text, text_length);
611 text_wchar = g_new (wchar_t, text_length);
612 for (i=0; i<text_length; i++) text_wchar[i] = text[i];
613 XwcDrawString (xdisplay, impl->xid,
614 (XFontSet) GDK_FONT_XFONT (font),
615 GDK_GC_GET_XGC (gc), x, y, text_wchar, text_length);
620 g_error("undefined font type\n");
624 gdk_x11_draw_drawable (GdkDrawable *drawable,
634 int src_depth = gdk_drawable_get_depth (src);
635 int dest_depth = gdk_drawable_get_depth (drawable);
636 GdkDrawableImplX11 *impl;
637 GdkDrawableImplX11 *src_impl;
639 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
641 if (GDK_IS_DRAWABLE_IMPL_X11 (src))
642 src_impl = GDK_DRAWABLE_IMPL_X11 (src);
648 XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
649 src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
656 else if (dest_depth != 0 && src_depth == dest_depth)
658 XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
659 src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
667 g_warning ("Attempt to draw a drawable with depth %d to a drawable with depth %d",
668 src_depth, dest_depth);
672 gdk_x11_draw_points (GdkDrawable *drawable,
677 GdkDrawableImplX11 *impl;
679 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
682 /* We special-case npoints == 1, because X will merge multiple
683 * consecutive XDrawPoint requests into a PolyPoint request
687 XDrawPoint (GDK_SCREEN_XDISPLAY (impl->screen),
690 points[0].x, points[0].y);
695 XPoint *tmp_points = g_new (XPoint, npoints);
697 for (i=0; i<npoints; i++)
699 tmp_points[i].x = points[i].x;
700 tmp_points[i].y = points[i].y;
703 XDrawPoints (GDK_SCREEN_XDISPLAY (impl->screen),
715 gdk_x11_draw_segments (GdkDrawable *drawable,
720 GdkDrawableImplX11 *impl;
722 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
725 /* We special-case nsegs == 1, because X will merge multiple
726 * consecutive XDrawLine requests into a PolySegment request
730 XDrawLine (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
731 GDK_GC_GET_XGC (gc), segs[0].x1, segs[0].y1,
732 segs[0].x2, segs[0].y2);
737 XSegment *tmp_segs = g_new (XSegment, nsegs);
739 for (i=0; i<nsegs; i++)
741 tmp_segs[i].x1 = segs[i].x1;
742 tmp_segs[i].x2 = segs[i].x2;
743 tmp_segs[i].y1 = segs[i].y1;
744 tmp_segs[i].y2 = segs[i].y2;
747 XDrawSegments (GDK_SCREEN_XDISPLAY (impl->screen),
757 gdk_x11_draw_lines (GdkDrawable *drawable,
763 XPoint *tmp_points = g_new (XPoint, npoints);
764 GdkDrawableImplX11 *impl;
766 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
769 for (i=0; i<npoints; i++)
771 tmp_points[i].x = points[i].x;
772 tmp_points[i].y = points[i].y;
775 XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen),
785 gdk_x11_draw_glyphs (GdkDrawable *drawable,
790 PangoGlyphString *glyphs)
792 GdkDrawableImplX11 *impl;
796 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
798 g_return_if_fail (PANGO_XFT_IS_FONT (font));
800 _gdk_gc_x11_get_fg_xft_color (gc, &color);
802 gdk_x11_drawable_update_xft_clip (drawable, gc);
803 draw = gdk_x11_drawable_get_xft_draw (drawable);
805 pango_xft_render (draw, &color, font, glyphs, x, y);
809 gdk_x11_draw_image (GdkDrawable *drawable,
819 GdkDrawableImplX11 *impl;
821 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
824 if (image->type == GDK_IMAGE_SHARED)
825 XShmPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
826 GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
827 xsrc, ysrc, xdest, ydest, width, height, False);
830 XPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
831 GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
832 xsrc, ysrc, xdest, ydest, width, height);
836 gdk_x11_get_depth (GdkDrawable *drawable)
838 /* This is a bit bogus but I'm not sure the other way is better */
840 return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
844 static GdkDrawable * get_impl_drawable (GdkDrawable *drawable)
848 if (GDK_IS_WINDOW (drawable))
849 impl = ((GdkPixmapObject *)drawable)->impl;
850 else if (GDK_IS_PIXMAP (drawable))
851 impl = ((GdkPixmapObject *)drawable)->impl;
854 g_warning (G_STRLOC " drawable is not a pixmap or window");
862 gdk_x11_get_screen (GdkDrawable *drawable)
864 if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
865 return GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
867 return GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen;
871 gdk_x11_get_visual (GdkDrawable *drawable)
873 return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
877 * gdk_x11_drawable_get_xdisplay:
878 * @drawable: a #GdkDrawable.
880 * Returns the display of a #GdkDrawable.
882 * Return value: an Xlib <type>Display*</type>.
885 gdk_x11_drawable_get_xdisplay (GdkDrawable *drawable)
887 if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
888 return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
890 return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen);
894 * gdk_x11_drawable_get_xid:
895 * @drawable: a #GdkDrawable.
897 * Returns the X resource (window or pixmap) belonging to a #GdkDrawable.
899 * Return value: the ID of @drawable's X resource.
902 gdk_x11_drawable_get_xid (GdkDrawable *drawable)
906 if (GDK_IS_WINDOW (drawable))
907 impl = ((GdkPixmapObject *)drawable)->impl;
908 else if (GDK_IS_PIXMAP (drawable))
909 impl = ((GdkPixmapObject *)drawable)->impl;
912 g_warning (G_STRLOC " drawable is not a pixmap or window");
916 return ((GdkDrawableImplX11 *)impl)->xid;
919 /* Code for accelerated alpha compositing using the RENDER extension.
920 * It's a bit long because there are lots of possibilities for
921 * what's the fastest depending on the available picture formats,
922 * whether we can used shared pixmaps, etc.
932 select_format (GdkDisplay *display,
933 XRenderPictFormat **format,
934 XRenderPictFormat **mask)
936 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
937 XRenderPictFormat pf;
939 if (!_gdk_x11_have_render (display))
942 /* Look for a 32-bit xRGB and Axxx formats that exactly match the
943 * in memory data format. We can use them as pixmap and mask
944 * to deal with non-premultiplied data.
947 pf.type = PictTypeDirect;
949 pf.direct.redMask = 0xff;
950 pf.direct.greenMask = 0xff;
951 pf.direct.blueMask = 0xff;
953 pf.direct.alphaMask = 0;
954 if (ImageByteOrder (xdisplay) == LSBFirst)
965 pf.direct.green = 16;
969 *format = XRenderFindFormat (xdisplay,
970 (PictFormatType | PictFormatDepth |
971 PictFormatRedMask | PictFormatRed |
972 PictFormatGreenMask | PictFormatGreen |
973 PictFormatBlueMask | PictFormatBlue |
974 PictFormatAlphaMask),
978 pf.direct.alphaMask = 0xff;
979 if (ImageByteOrder (xdisplay) == LSBFirst)
982 pf.direct.alpha = 24;
989 *mask = XRenderFindFormat (xdisplay,
990 (PictFormatType | PictFormatDepth |
991 PictFormatAlphaMask | PictFormatAlpha),
995 if (*format && *mask)
996 return FORMAT_EXACT_MASK;
998 /* OK, that failed, now look for xRGB and Axxx formats in
999 * RENDER's preferred order
1001 pf.direct.alphaMask = 0;
1004 pf.direct.green = 8;
1007 *format = XRenderFindFormat (xdisplay,
1008 (PictFormatType | PictFormatDepth |
1009 PictFormatRedMask | PictFormatRed |
1010 PictFormatGreenMask | PictFormatGreen |
1011 PictFormatBlueMask | PictFormatBlue |
1012 PictFormatAlphaMask),
1016 pf.direct.alphaMask = 0xff;
1017 pf.direct.alpha = 24;
1019 *mask = XRenderFindFormat (xdisplay,
1020 (PictFormatType | PictFormatDepth |
1021 PictFormatAlphaMask | PictFormatAlpha),
1025 if (*format && *mask)
1026 return FORMAT_ARGB_MASK;
1028 /* Finally, if neither of the above worked, fall back to
1029 * looking for combined ARGB -- we'll premultiply ourselves.
1032 pf.type = PictTypeDirect;
1035 pf.direct.green = 8;
1037 pf.direct.alphaMask = 0xff;
1038 pf.direct.alpha = 24;
1040 *format = XRenderFindFormat (xdisplay,
1041 (PictFormatType | PictFormatDepth |
1042 PictFormatRedMask | PictFormatRed |
1043 PictFormatGreenMask | PictFormatGreen |
1044 PictFormatBlueMask | PictFormatBlue |
1045 PictFormatAlphaMask | PictFormatAlpha),
1058 list_formats (XRenderPictFormat *pf)
1064 XRenderPictFormat *pf = XRenderFindFormat (impl->xdisplay, 0, NULL, i);
1067 g_print ("%2d R-%#06x/%#06x G-%#06x/%#06x B-%#06x/%#06x A-%#06x/%#06x\n",
1072 pf->direct.greenMask,
1074 pf->direct.blueMask,
1076 pf->direct.alphaMask);
1085 convert_to_format (guchar *src_buf,
1088 gint dest_rowstride,
1089 FormatType dest_format,
1090 GdkByteOrder dest_byteorder,
1096 for (i=0; i < height; i++)
1098 switch (dest_format)
1100 case FORMAT_EXACT_MASK:
1102 memcpy (dest_buf + i * dest_rowstride,
1103 src_buf + i * src_rowstride,
1107 case FORMAT_ARGB_MASK:
1109 guchar *row = src_buf + i * src_rowstride;
1110 if (((gsize)row & 3) != 0)
1113 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1114 guchar *end = p + 4 * width;
1118 *q = (p[3] << 24) | (p[0] << 16) | (p[1] << 8) | p[2];
1125 guint32 *p = (guint32 *)row;
1126 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1127 guint32 *end = p + width;
1129 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1130 if (dest_byteorder == GDK_LSB_FIRST)
1136 *q = ( (*p & 0xff00ff00) |
1137 ((*p & 0x000000ff) << 16) |
1138 ((*p & 0x00ff0000) >> 16));
1149 *q = (((*p & 0xff000000) >> 24) |
1150 ((*p & 0x00ffffff) << 8));
1155 #else /* G_BYTE_ORDER == G_BIG_ENDIAN */
1156 if (dest_byteorder == GDK_LSB_FIRST)
1162 *q = ( (*p & 0x00ff00ff) |
1163 ((*p & 0x0000ff00) << 16) |
1164 ((*p & 0xff000000) >> 16));
1175 *q = (((*p & 0xffffff00) >> 8) |
1176 ((*p & 0x000000ff) << 24));
1181 #endif /* G_BYTE_ORDER*/
1187 guchar *p = (src_buf + i * src_rowstride);
1188 guchar *q = (dest_buf + i * dest_rowstride);
1189 guchar *end = p + 4 * width;
1192 #define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END
1194 if (dest_byteorder == GDK_LSB_FIRST)
1198 MULT(q[0], p[2], p[3], t1);
1199 MULT(q[1], p[1], p[3], t2);
1200 MULT(q[2], p[0], p[3], t3);
1211 MULT(q[1], p[0], p[3], t1);
1212 MULT(q[2], p[1], p[3], t2);
1213 MULT(q[3], p[2], p[3], t3);
1222 g_assert_not_reached ();
1229 draw_with_images (GdkDrawable *drawable,
1231 FormatType format_type,
1232 XRenderPictFormat *format,
1233 XRenderPictFormat *mask_format,
1241 GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1242 Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
1248 Picture mask = None;
1251 pix = gdk_pixmap_new (gdk_screen_get_root_window (screen), width, height, 32);
1253 pict = XRenderCreatePicture (xdisplay,
1254 GDK_PIXMAP_XID (pix),
1257 mask = XRenderCreatePicture (xdisplay,
1258 GDK_PIXMAP_XID (pix),
1259 mask_format, 0, NULL);
1261 dest_pict = gdk_x11_drawable_get_picture (drawable);
1263 pix_gc = _gdk_drawable_get_scratch_gc (pix, FALSE);
1265 for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1267 gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1268 for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1272 gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1274 image = _gdk_image_get_scratch (screen, width1, height1, 32, &xs0, &ys0);
1276 convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1277 (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1278 format_type, image->byte_order,
1281 gdk_draw_image (pix, pix_gc,
1282 image, xs0, ys0, x0, y0, width1, height1);
1286 XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict,
1287 0, 0, 0, 0, dest_x, dest_y, width, height);
1289 XRenderFreePicture (xdisplay, pict);
1291 XRenderFreePicture (xdisplay, mask);
1293 g_object_unref (pix);
1296 typedef struct _ShmPixmapInfo ShmPixmapInfo;
1298 struct _ShmPixmapInfo
1306 /* Returns FALSE if we can't get a shm pixmap */
1308 get_shm_pixmap_for_image (Display *xdisplay,
1310 XRenderPictFormat *format,
1311 XRenderPictFormat *mask_format,
1316 ShmPixmapInfo *info;
1318 if (image->type != GDK_IMAGE_SHARED)
1321 info = g_object_get_data (G_OBJECT (image), "gdk-x11-shm-pixmap");
1324 *pix = _gdk_x11_image_get_shm_pixmap (image);
1329 info = g_new (ShmPixmapInfo, 1);
1332 info->pict = XRenderCreatePicture (xdisplay, info->pix,
1335 info->mask = XRenderCreatePicture (xdisplay, info->pix,
1336 mask_format, 0, NULL);
1340 g_object_set_data (G_OBJECT (image), "gdk-x11-shm-pixmap", info);
1351 /* Returns FALSE if drawing with ShmPixmaps is not possible */
1353 draw_with_pixmaps (GdkDrawable *drawable,
1355 FormatType format_type,
1356 XRenderPictFormat *format,
1357 XRenderPictFormat *mask_format,
1365 Display *xdisplay = GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
1370 Picture mask = None;
1373 dest_pict = gdk_x11_drawable_get_picture (drawable);
1375 for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1377 gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1378 for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1382 gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1384 image = _gdk_image_get_scratch (GDK_DRAWABLE_IMPL_X11 (drawable)->screen,
1385 width1, height1, 32, &xs0, &ys0);
1386 if (!get_shm_pixmap_for_image (xdisplay, image, format, mask_format, &pix, &pict, &mask))
1389 convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1390 (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1391 format_type, image->byte_order,
1394 XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict,
1395 xs0, ys0, xs0, ys0, x0 + dest_x, y0 + dest_y,
1405 gdk_x11_draw_pixbuf (GdkDrawable *drawable,
1414 GdkRgbDither dither,
1418 FormatType format_type;
1419 XRenderPictFormat *format, *mask_format;
1422 gboolean use_pixmaps = TRUE;
1423 #endif /* USE_SHM */
1425 format_type = select_format (gdk_drawable_get_display (drawable),
1426 &format, &mask_format);
1428 if (format_type == FORMAT_NONE ||
1429 !gdk_pixbuf_get_has_alpha (pixbuf) ||
1430 gdk_drawable_get_depth (drawable) == 1 ||
1431 (dither == GDK_RGB_DITHER_MAX && gdk_drawable_get_depth (drawable) != 24) ||
1432 gdk_x11_drawable_get_picture (drawable) == None)
1434 GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
1435 GDK_DRAWABLE_CLASS (parent_class)->draw_pixbuf (wrapper, gc, pixbuf,
1436 src_x, src_y, dest_x, dest_y,
1438 dither, x_dither, y_dither);
1442 gdk_x11_drawable_update_xft_clip (drawable, gc);
1444 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1449 if (!draw_with_pixmaps (drawable, gc,
1450 format_type, format, mask_format,
1451 gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1453 dest_x, dest_y, width, height))
1454 use_pixmaps = FALSE;
1458 #endif /* USE_SHM */
1459 draw_with_images (drawable, gc,
1460 format_type, format, mask_format,
1461 gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1463 dest_x, dest_y, width, height);