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.
19 #include "../config.h"
22 #include <sys/types.h>
24 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
34 #include <X11/Xutil.h>
37 #include <X11/extensions/XShm.h>
41 #include "gdkprivate.h"
44 static void gdk_image_put_normal (GdkDrawable *drawable,
53 static void gdk_image_put_shared (GdkDrawable *drawable,
64 static GList *image_list = NULL;
74 image = image_list->data;
75 gdk_image_destroy (image);
80 gdk_image_new_bitmap(GdkVisual *visual, gpointer data, gint w, gint h)
82 * Desc: create a new bitmap image
87 GdkImagePrivate *private;
88 private = g_new(GdkImagePrivate, 1);
89 image = (GdkImage *) private;
90 private->xdisplay = gdk_display;
91 private->image_put = gdk_image_put_normal;
92 image->type = GDK_IMAGE_NORMAL;
93 image->visual = visual;
97 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
98 private->ximage = XCreateImage(private->xdisplay, xvisual, 1, XYBitmap,
100 private->ximage->data = data;
101 private->ximage->bitmap_bit_order = MSBFirst;
102 private->ximage->byte_order = MSBFirst;
103 image->byte_order = MSBFirst;
104 image->mem = private->ximage->data;
105 image->bpl = private->ximage->bytes_per_line;
108 } /* gdk_image_new_bitmap() */
111 gdk_image_check_xshm(Display *display)
113 * Desc: query the server for support for the MIT_SHM extension
114 * Return: 0 = not available
115 * 1 = shared XImage support available
116 * 2 = shared Pixmap support available also
120 int major, minor, ignore;
123 if (XQueryExtension(display, "MIT-SHM", &ignore, &ignore, &ignore))
125 if (XShmQueryVersion(display, &major, &minor, &pixmaps )==True)
127 return (pixmaps==True) ? 2 : 1;
135 gdk_image_init (void)
139 if (!gdk_image_check_xshm (gdk_display))
141 gdk_use_xshm = False;
147 gdk_image_new (GdkImageType type,
153 GdkImagePrivate *private;
155 XShmSegmentInfo *x_shm_info;
161 case GDK_IMAGE_FASTEST:
162 image = gdk_image_new (GDK_IMAGE_SHARED, visual, width, height);
165 image = gdk_image_new (GDK_IMAGE_NORMAL, visual, width, height);
169 private = g_new (GdkImagePrivate, 1);
170 image = (GdkImage*) private;
172 private->xdisplay = gdk_display;
173 private->image_put = NULL;
176 image->visual = visual;
177 image->width = width;
178 image->height = height;
179 image->depth = visual->depth;
181 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
185 case GDK_IMAGE_SHARED:
189 private->image_put = gdk_image_put_shared;
191 private->x_shm_info = g_new (XShmSegmentInfo, 1);
192 x_shm_info = private->x_shm_info;
194 private->ximage = XShmCreateImage (private->xdisplay, xvisual, visual->depth,
195 ZPixmap, NULL, x_shm_info, width, height);
196 if (private->ximage == NULL)
198 g_warning ("XShmCreateImage failed");
201 gdk_use_xshm = False;
205 x_shm_info->shmid = shmget (IPC_PRIVATE,
206 private->ximage->bytes_per_line * private->ximage->height,
209 if (x_shm_info->shmid == -1)
211 g_warning ("shmget failed!");
213 XDestroyImage (private->ximage);
214 g_free (private->x_shm_info);
217 gdk_use_xshm = False;
221 x_shm_info->readOnly = False;
222 x_shm_info->shmaddr = shmat (x_shm_info->shmid, 0, 0);
223 private->ximage->data = x_shm_info->shmaddr;
225 if (x_shm_info->shmaddr == (char*) -1)
227 g_warning ("shmat failed!");
229 XDestroyImage (private->ximage);
230 shmctl (x_shm_info->shmid, IPC_RMID, 0);
232 g_free (private->x_shm_info);
238 #ifdef IPC_RMID_DEFERRED_RELEASE
239 if (x_shm_info->shmaddr != (char*) -1)
240 shmctl (x_shm_info->shmid, IPC_RMID, 0);
244 gdk_error_warnings = 0;
246 XShmAttach (private->xdisplay, x_shm_info);
247 XSync (private->xdisplay, False);
249 gdk_error_warnings = 1;
250 if (gdk_error_code == -1)
252 /* this is the common failure case so omit warning */
253 XDestroyImage (private->ximage);
254 shmdt (x_shm_info->shmaddr);
255 shmctl (x_shm_info->shmid, IPC_RMID, 0);
257 g_free (private->x_shm_info);
260 gdk_use_xshm = False;
265 image_list = g_list_prepend (image_list, image);
277 case GDK_IMAGE_NORMAL:
278 private->image_put = gdk_image_put_normal;
280 private->ximage = XCreateImage (private->xdisplay, xvisual, visual->depth,
281 ZPixmap, 0, 0, width, height, 32, 0);
283 /* Use malloc, not g_malloc here, because X will call free()
286 private->ximage->data = malloc (private->ximage->bytes_per_line *
287 private->ximage->height);
290 case GDK_IMAGE_FASTEST:
291 g_assert_not_reached ();
296 image->byte_order = private->ximage->byte_order;
297 image->mem = private->ximage->data;
298 image->bpl = private->ximage->bytes_per_line;
300 switch (private->ximage->bits_per_pixel)
322 gdk_image_get (GdkWindow *window,
329 GdkImagePrivate *private;
330 GdkWindowPrivate *win_private;
332 g_return_val_if_fail (window != NULL, NULL);
334 win_private = (GdkWindowPrivate *) window;
335 if (win_private->destroyed)
338 private = g_new (GdkImagePrivate, 1);
339 image = (GdkImage*) private;
341 private->xdisplay = gdk_display;
342 private->image_put = gdk_image_put_normal;
343 private->ximage = XGetImage (private->xdisplay,
344 win_private->xwindow,
348 image->type = GDK_IMAGE_NORMAL;
349 image->visual = gdk_window_get_visual (window);
350 image->width = width;
351 image->height = height;
352 image->depth = private->ximage->depth;
354 image->mem = private->ximage->data;
355 image->bpl = private->ximage->bytes_per_line;
362 gdk_image_get_pixel (GdkImage *image,
367 GdkImagePrivate *private;
369 g_return_val_if_fail (image != NULL, 0);
371 private = (GdkImagePrivate *) image;
373 pixel = XGetPixel (private->ximage, x, y);
379 gdk_image_put_pixel (GdkImage *image,
384 GdkImagePrivate *private;
386 g_return_if_fail (image != NULL);
388 private = (GdkImagePrivate *) image;
390 pixel = XPutPixel (private->ximage, x, y, pixel);
394 gdk_image_destroy (GdkImage *image)
396 GdkImagePrivate *private;
398 XShmSegmentInfo *x_shm_info;
401 g_return_if_fail (image != NULL);
403 private = (GdkImagePrivate*) image;
406 case GDK_IMAGE_NORMAL:
407 XDestroyImage (private->ximage);
410 case GDK_IMAGE_SHARED:
412 XShmDetach (private->xdisplay, private->x_shm_info);
413 XDestroyImage (private->ximage);
415 x_shm_info = private->x_shm_info;
416 shmdt (x_shm_info->shmaddr);
417 shmctl (x_shm_info->shmid, IPC_RMID, 0);
419 g_free (private->x_shm_info);
421 image_list = g_list_remove (image_list, image);
423 g_error ("trying to destroy shared memory image when gdk was compiled without shared memory support");
427 case GDK_IMAGE_FASTEST:
428 g_assert_not_reached ();
435 gdk_image_put_normal (GdkDrawable *drawable,
445 GdkWindowPrivate *drawable_private;
446 GdkImagePrivate *image_private;
447 GdkGCPrivate *gc_private;
449 g_return_if_fail (drawable != NULL);
450 g_return_if_fail (image != NULL);
451 g_return_if_fail (gc != NULL);
453 drawable_private = (GdkWindowPrivate*) drawable;
454 if (drawable_private->destroyed)
456 image_private = (GdkImagePrivate*) image;
457 gc_private = (GdkGCPrivate*) gc;
459 g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
461 XPutImage (drawable_private->xdisplay, drawable_private->xwindow,
462 gc_private->xgc, image_private->ximage,
463 xsrc, ysrc, xdest, ydest, width, height);
467 gdk_image_put_shared (GdkDrawable *drawable,
478 GdkWindowPrivate *drawable_private;
479 GdkImagePrivate *image_private;
480 GdkGCPrivate *gc_private;
482 g_return_if_fail (drawable != NULL);
483 g_return_if_fail (image != NULL);
484 g_return_if_fail (gc != NULL);
486 drawable_private = (GdkWindowPrivate*) drawable;
487 if (drawable_private->destroyed)
489 image_private = (GdkImagePrivate*) image;
490 gc_private = (GdkGCPrivate*) gc;
492 g_return_if_fail (image->type == GDK_IMAGE_SHARED);
494 XShmPutImage (drawable_private->xdisplay, drawable_private->xwindow,
495 gc_private->xgc, image_private->ximage,
496 xsrc, ysrc, xdest, ydest, width, height, False);
498 g_error ("trying to draw shared memory image when gdk was compiled without shared memory support");