1 /* GDK - The GIMP Drawing Kit
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 Library 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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library 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-1999. 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/.
29 /* gcc -ansi -pedantic on GNU/Linux causes warnings and errors
30 * unless this is defined:
31 * warning: #warning "Files using this header must be compiled with _SVID_SOURCE or _XOPEN_SOURCE"
34 # define _XOPEN_SOURCE 1
38 #include <sys/types.h>
40 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
50 #include <X11/Xutil.h>
53 #include <X11/extensions/XShm.h>
57 #include "gdkprivate.h"
60 static void gdk_image_put_normal (GdkDrawable *drawable,
69 static void gdk_image_put_shared (GdkDrawable *drawable,
80 static GList *image_list = NULL;
90 image = image_list->data;
91 gdk_image_destroy (image);
96 gdk_image_new_bitmap(GdkVisual *visual, gpointer data, gint w, gint h)
98 * Desc: create a new bitmap image
103 GdkImagePrivate *private;
104 private = g_new(GdkImagePrivate, 1);
105 image = (GdkImage *) private;
106 private->xdisplay = gdk_display;
107 private->image_put = gdk_image_put_normal;
108 image->type = GDK_IMAGE_NORMAL;
109 image->visual = visual;
113 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
114 private->ximage = XCreateImage(private->xdisplay, xvisual, 1, XYBitmap,
116 private->ximage->data = data;
117 private->ximage->bitmap_bit_order = MSBFirst;
118 private->ximage->byte_order = MSBFirst;
119 image->byte_order = MSBFirst;
120 image->mem = private->ximage->data;
121 image->bpl = private->ximage->bytes_per_line;
124 } /* gdk_image_new_bitmap() */
127 gdk_image_check_xshm(Display *display)
129 * Desc: query the server for support for the MIT_SHM extension
130 * Return: 0 = not available
131 * 1 = shared XImage support available
132 * 2 = shared Pixmap support available also
136 int major, minor, ignore;
139 if (XQueryExtension(display, "MIT-SHM", &ignore, &ignore, &ignore))
141 if (XShmQueryVersion(display, &major, &minor, &pixmaps )==True)
143 return (pixmaps==True) ? 2 : 1;
151 gdk_image_init (void)
155 if (!gdk_image_check_xshm (gdk_display))
157 gdk_use_xshm = False;
163 gdk_image_new (GdkImageType type,
169 GdkImagePrivate *private;
171 XShmSegmentInfo *x_shm_info;
177 case GDK_IMAGE_FASTEST:
178 image = gdk_image_new (GDK_IMAGE_SHARED, visual, width, height);
181 image = gdk_image_new (GDK_IMAGE_NORMAL, visual, width, height);
185 private = g_new (GdkImagePrivate, 1);
186 image = (GdkImage*) private;
188 private->xdisplay = gdk_display;
189 private->image_put = NULL;
192 image->visual = visual;
193 image->width = width;
194 image->height = height;
195 image->depth = visual->depth;
197 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
201 case GDK_IMAGE_SHARED:
205 private->image_put = gdk_image_put_shared;
207 private->x_shm_info = g_new (XShmSegmentInfo, 1);
208 x_shm_info = private->x_shm_info;
210 private->ximage = XShmCreateImage (private->xdisplay, xvisual, visual->depth,
211 ZPixmap, NULL, x_shm_info, width, height);
212 if (private->ximage == NULL)
214 g_warning ("XShmCreateImage failed");
217 gdk_use_xshm = False;
221 x_shm_info->shmid = shmget (IPC_PRIVATE,
222 private->ximage->bytes_per_line * private->ximage->height,
225 if (x_shm_info->shmid == -1)
227 g_warning ("shmget failed!");
229 XDestroyImage (private->ximage);
230 g_free (private->x_shm_info);
233 gdk_use_xshm = False;
237 x_shm_info->readOnly = False;
238 x_shm_info->shmaddr = shmat (x_shm_info->shmid, 0, 0);
239 private->ximage->data = x_shm_info->shmaddr;
241 if (x_shm_info->shmaddr == (char*) -1)
243 g_warning ("shmat failed!");
245 XDestroyImage (private->ximage);
246 shmctl (x_shm_info->shmid, IPC_RMID, 0);
248 g_free (private->x_shm_info);
254 gdk_error_trap_push ();
256 XShmAttach (private->xdisplay, x_shm_info);
257 XSync (private->xdisplay, False);
259 if (gdk_error_trap_pop ())
261 /* this is the common failure case so omit warning */
262 XDestroyImage (private->ximage);
263 shmdt (x_shm_info->shmaddr);
264 shmctl (x_shm_info->shmid, IPC_RMID, 0);
266 g_free (private->x_shm_info);
269 gdk_use_xshm = False;
274 /* We mark the segment as destroyed so that when
275 * the last process detaches, it will be deleted.
276 * There is a small possibility of leaking if
277 * we die in XShmAttach. In theory, a signal handler
280 shmctl (x_shm_info->shmid, IPC_RMID, 0);
283 image_list = g_list_prepend (image_list, image);
295 case GDK_IMAGE_NORMAL:
296 private->image_put = gdk_image_put_normal;
298 private->ximage = XCreateImage (private->xdisplay, xvisual, visual->depth,
299 ZPixmap, 0, 0, width, height, 32, 0);
301 /* Use malloc, not g_malloc here, because X will call free()
304 private->ximage->data = malloc (private->ximage->bytes_per_line *
305 private->ximage->height);
308 case GDK_IMAGE_FASTEST:
309 g_assert_not_reached ();
314 image->byte_order = private->ximage->byte_order;
315 image->mem = private->ximage->data;
316 image->bpl = private->ximage->bytes_per_line;
317 image->bpp = (private->ximage->bits_per_pixel + 7) / 8;
325 gdk_image_get (GdkWindow *window,
332 GdkImagePrivate *private;
333 GdkWindowPrivate *win_private;
335 g_return_val_if_fail (window != NULL, NULL);
337 win_private = (GdkWindowPrivate *) window;
338 if (win_private->destroyed)
341 private = g_new (GdkImagePrivate, 1);
342 image = (GdkImage*) private;
344 private->xdisplay = gdk_display;
345 private->image_put = gdk_image_put_normal;
346 private->ximage = XGetImage (private->xdisplay,
347 win_private->xwindow,
351 image->type = GDK_IMAGE_NORMAL;
352 image->visual = gdk_window_get_visual (window);
353 image->width = width;
354 image->height = height;
355 image->depth = private->ximage->depth;
357 image->mem = private->ximage->data;
358 image->bpl = private->ximage->bytes_per_line;
359 if (private->ximage->bits_per_pixel <= 8)
361 else if (private->ximage->bits_per_pixel <= 16)
363 else if (private->ximage->bits_per_pixel <= 24)
367 image->byte_order = private->ximage->byte_order;
373 gdk_image_get_pixel (GdkImage *image,
378 GdkImagePrivate *private;
380 g_return_val_if_fail (image != NULL, 0);
382 private = (GdkImagePrivate *) image;
384 pixel = XGetPixel (private->ximage, x, y);
390 gdk_image_put_pixel (GdkImage *image,
395 GdkImagePrivate *private;
397 g_return_if_fail (image != NULL);
399 private = (GdkImagePrivate *) image;
401 pixel = XPutPixel (private->ximage, x, y, pixel);
405 gdk_image_destroy (GdkImage *image)
407 GdkImagePrivate *private;
409 XShmSegmentInfo *x_shm_info;
412 g_return_if_fail (image != NULL);
414 private = (GdkImagePrivate*) image;
417 case GDK_IMAGE_NORMAL:
418 XDestroyImage (private->ximage);
421 case GDK_IMAGE_SHARED:
425 XShmDetach (private->xdisplay, private->x_shm_info);
426 XDestroyImage (private->ximage);
428 x_shm_info = private->x_shm_info;
429 shmdt (x_shm_info->shmaddr);
431 g_free (private->x_shm_info);
433 image_list = g_list_remove (image_list, image);
435 g_error ("trying to destroy shared memory image when gdk was compiled without shared memory support");
439 case GDK_IMAGE_FASTEST:
440 g_assert_not_reached ();
447 gdk_image_put_normal (GdkDrawable *drawable,
457 GdkWindowPrivate *drawable_private;
458 GdkImagePrivate *image_private;
459 GdkGCPrivate *gc_private;
461 g_return_if_fail (drawable != NULL);
462 g_return_if_fail (image != NULL);
463 g_return_if_fail (gc != NULL);
465 drawable_private = (GdkWindowPrivate*) drawable;
466 if (drawable_private->destroyed)
468 image_private = (GdkImagePrivate*) image;
469 gc_private = (GdkGCPrivate*) gc;
471 g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
473 XPutImage (drawable_private->xdisplay, drawable_private->xwindow,
474 gc_private->xgc, image_private->ximage,
475 xsrc, ysrc, xdest, ydest, width, height);
479 gdk_image_put_shared (GdkDrawable *drawable,
490 GdkWindowPrivate *drawable_private;
491 GdkImagePrivate *image_private;
492 GdkGCPrivate *gc_private;
494 g_return_if_fail (drawable != NULL);
495 g_return_if_fail (image != NULL);
496 g_return_if_fail (gc != NULL);
498 drawable_private = (GdkWindowPrivate*) drawable;
499 if (drawable_private->destroyed)
501 image_private = (GdkImagePrivate*) image;
502 gc_private = (GdkGCPrivate*) gc;
504 g_return_if_fail (image->type == GDK_IMAGE_SHARED);
506 XShmPutImage (drawable_private->xdisplay, drawable_private->xwindow,
507 gc_private->xgc, image_private->ximage,
508 xsrc, ysrc, xdest, ydest, width, height, False);
510 g_error ("trying to draw shared memory image when gdk was compiled without shared memory support");