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 /* gcc -ansi -pedantic on GNU/Linux causes warnings and errors
22 * unless this is defined:
23 * warning: #warning "Files using this header must be compiled with _SVID_SOURCE or _XOPEN_SOURCE"
26 # define _XOPEN_SOURCE 1
30 #include <sys/types.h>
32 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
42 #include <X11/Xutil.h>
45 #include <X11/extensions/XShm.h>
49 #include "gdkprivate.h"
52 static void gdk_image_put_normal (GdkDrawable *drawable,
61 static void gdk_image_put_shared (GdkDrawable *drawable,
72 static GList *image_list = NULL;
82 image = image_list->data;
83 gdk_image_destroy (image);
88 gdk_image_new_bitmap(GdkVisual *visual, gpointer data, gint w, gint h)
90 * Desc: create a new bitmap image
95 GdkImagePrivate *private;
96 private = g_new(GdkImagePrivate, 1);
97 image = (GdkImage *) private;
98 private->xdisplay = gdk_display;
99 private->image_put = gdk_image_put_normal;
100 image->type = GDK_IMAGE_NORMAL;
101 image->visual = visual;
105 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
106 private->ximage = XCreateImage(private->xdisplay, xvisual, 1, XYBitmap,
108 private->ximage->data = data;
109 private->ximage->bitmap_bit_order = MSBFirst;
110 private->ximage->byte_order = MSBFirst;
111 image->byte_order = MSBFirst;
112 image->mem = private->ximage->data;
113 image->bpl = private->ximage->bytes_per_line;
116 } /* gdk_image_new_bitmap() */
119 gdk_image_check_xshm(Display *display)
121 * Desc: query the server for support for the MIT_SHM extension
122 * Return: 0 = not available
123 * 1 = shared XImage support available
124 * 2 = shared Pixmap support available also
128 int major, minor, ignore;
131 if (XQueryExtension(display, "MIT-SHM", &ignore, &ignore, &ignore))
133 if (XShmQueryVersion(display, &major, &minor, &pixmaps )==True)
135 return (pixmaps==True) ? 2 : 1;
143 gdk_image_init (void)
147 if (!gdk_image_check_xshm (gdk_display))
149 gdk_use_xshm = False;
155 gdk_image_new (GdkImageType type,
161 GdkImagePrivate *private;
163 XShmSegmentInfo *x_shm_info;
169 case GDK_IMAGE_FASTEST:
170 image = gdk_image_new (GDK_IMAGE_SHARED, visual, width, height);
173 image = gdk_image_new (GDK_IMAGE_NORMAL, visual, width, height);
177 private = g_new (GdkImagePrivate, 1);
178 image = (GdkImage*) private;
180 private->xdisplay = gdk_display;
181 private->image_put = NULL;
184 image->visual = visual;
185 image->width = width;
186 image->height = height;
187 image->depth = visual->depth;
189 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
193 case GDK_IMAGE_SHARED:
197 private->image_put = gdk_image_put_shared;
199 private->x_shm_info = g_new (XShmSegmentInfo, 1);
200 x_shm_info = private->x_shm_info;
202 private->ximage = XShmCreateImage (private->xdisplay, xvisual, visual->depth,
203 ZPixmap, NULL, x_shm_info, width, height);
204 if (private->ximage == NULL)
206 g_warning ("XShmCreateImage failed");
209 gdk_use_xshm = False;
213 x_shm_info->shmid = shmget (IPC_PRIVATE,
214 private->ximage->bytes_per_line * private->ximage->height,
217 if (x_shm_info->shmid == -1)
219 g_warning ("shmget failed!");
221 XDestroyImage (private->ximage);
222 g_free (private->x_shm_info);
225 gdk_use_xshm = False;
229 x_shm_info->readOnly = False;
230 x_shm_info->shmaddr = shmat (x_shm_info->shmid, 0, 0);
231 private->ximage->data = x_shm_info->shmaddr;
233 if (x_shm_info->shmaddr == (char*) -1)
235 g_warning ("shmat failed!");
237 XDestroyImage (private->ximage);
238 shmctl (x_shm_info->shmid, IPC_RMID, 0);
240 g_free (private->x_shm_info);
247 gdk_error_warnings = 0;
249 XShmAttach (private->xdisplay, x_shm_info);
250 XSync (private->xdisplay, False);
252 gdk_error_warnings = 1;
253 if (gdk_error_code == -1)
255 /* this is the common failure case so omit warning */
256 XDestroyImage (private->ximage);
257 shmdt (x_shm_info->shmaddr);
258 shmctl (x_shm_info->shmid, IPC_RMID, 0);
260 g_free (private->x_shm_info);
263 gdk_use_xshm = False;
267 /* We mark the segment as destroyed so that when
268 * the last process detaches, it will be deleted.
269 * There is a small possibility of leaking if
270 * we die in XShmAttach. In theory, a signal handler
273 shmctl (x_shm_info->shmid, IPC_RMID, 0);
276 image_list = g_list_prepend (image_list, image);
288 case GDK_IMAGE_NORMAL:
289 private->image_put = gdk_image_put_normal;
291 private->ximage = XCreateImage (private->xdisplay, xvisual, visual->depth,
292 ZPixmap, 0, 0, width, height, 32, 0);
294 /* Use malloc, not g_malloc here, because X will call free()
297 private->ximage->data = malloc (private->ximage->bytes_per_line *
298 private->ximage->height);
301 case GDK_IMAGE_FASTEST:
302 g_assert_not_reached ();
307 image->byte_order = private->ximage->byte_order;
308 image->mem = private->ximage->data;
309 image->bpl = private->ximage->bytes_per_line;
311 switch (private->ximage->bits_per_pixel)
333 gdk_image_get (GdkWindow *window,
340 GdkImagePrivate *private;
341 GdkWindowPrivate *win_private;
343 g_return_val_if_fail (window != NULL, NULL);
345 win_private = (GdkWindowPrivate *) window;
346 if (win_private->destroyed)
349 private = g_new (GdkImagePrivate, 1);
350 image = (GdkImage*) private;
352 private->xdisplay = gdk_display;
353 private->image_put = gdk_image_put_normal;
354 private->ximage = XGetImage (private->xdisplay,
355 win_private->xwindow,
359 image->type = GDK_IMAGE_NORMAL;
360 image->visual = gdk_window_get_visual (window);
361 image->width = width;
362 image->height = height;
363 image->depth = private->ximage->depth;
365 image->mem = private->ximage->data;
366 image->bpl = private->ximage->bytes_per_line;
367 image->bpp = private->ximage->bits_per_pixel;
368 image->byte_order = private->ximage->byte_order;
374 gdk_image_get_pixel (GdkImage *image,
379 GdkImagePrivate *private;
381 g_return_val_if_fail (image != NULL, 0);
383 private = (GdkImagePrivate *) image;
385 pixel = XGetPixel (private->ximage, x, y);
391 gdk_image_put_pixel (GdkImage *image,
396 GdkImagePrivate *private;
398 g_return_if_fail (image != NULL);
400 private = (GdkImagePrivate *) image;
402 pixel = XPutPixel (private->ximage, x, y, pixel);
406 gdk_image_destroy (GdkImage *image)
408 GdkImagePrivate *private;
410 XShmSegmentInfo *x_shm_info;
413 g_return_if_fail (image != NULL);
415 private = (GdkImagePrivate*) image;
418 case GDK_IMAGE_NORMAL:
419 XDestroyImage (private->ximage);
422 case GDK_IMAGE_SHARED:
426 XShmDetach (private->xdisplay, private->x_shm_info);
427 XDestroyImage (private->ximage);
429 x_shm_info = private->x_shm_info;
430 shmdt (x_shm_info->shmaddr);
432 g_free (private->x_shm_info);
434 image_list = g_list_remove (image_list, image);
436 g_error ("trying to destroy shared memory image when gdk was compiled without shared memory support");
440 case GDK_IMAGE_FASTEST:
441 g_assert_not_reached ();
448 gdk_image_put_normal (GdkDrawable *drawable,
458 GdkWindowPrivate *drawable_private;
459 GdkImagePrivate *image_private;
460 GdkGCPrivate *gc_private;
462 g_return_if_fail (drawable != NULL);
463 g_return_if_fail (image != NULL);
464 g_return_if_fail (gc != NULL);
466 drawable_private = (GdkWindowPrivate*) drawable;
467 if (drawable_private->destroyed)
469 image_private = (GdkImagePrivate*) image;
470 gc_private = (GdkGCPrivate*) gc;
472 g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
474 XPutImage (drawable_private->xdisplay, drawable_private->xwindow,
475 gc_private->xgc, image_private->ximage,
476 xsrc, ysrc, xdest, ydest, width, height);
480 gdk_image_put_shared (GdkDrawable *drawable,
491 GdkWindowPrivate *drawable_private;
492 GdkImagePrivate *image_private;
493 GdkGCPrivate *gc_private;
495 g_return_if_fail (drawable != NULL);
496 g_return_if_fail (image != NULL);
497 g_return_if_fail (gc != NULL);
499 drawable_private = (GdkWindowPrivate*) drawable;
500 if (drawable_private->destroyed)
502 image_private = (GdkImagePrivate*) image;
503 gc_private = (GdkGCPrivate*) gc;
505 g_return_if_fail (image->type == GDK_IMAGE_SHARED);
507 XShmPutImage (drawable_private->xdisplay, drawable_private->xwindow,
508 gc_private->xgc, image_private->ximage,
509 xsrc, ysrc, xdest, ydest, width, height, False);
511 g_error ("trying to draw shared memory image when gdk was compiled without shared memory support");