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 Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 #include "../config.h"
20 #include <sys/types.h>
22 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
32 #include <X11/Xutil.h>
35 #include <X11/extensions/XShm.h>
39 #include "gdkprivate.h"
42 static void gdk_image_put_normal (GdkDrawable *drawable,
51 static void gdk_image_put_shared (GdkDrawable *drawable,
62 static GList *image_list = NULL;
72 image = image_list->data;
73 gdk_image_destroy (image);
78 gdk_image_new_bitmap(GdkVisual *visual, gpointer data, gint w, gint h)
80 * Desc: create a new bitmap image
85 GdkImagePrivate *private;
86 private = g_new(GdkImagePrivate, 1);
87 image = (GdkImage *) private;
88 private->xdisplay = gdk_display;
89 private->image_put = gdk_image_put_normal;
90 image->type = GDK_IMAGE_NORMAL;
91 image->visual = visual;
95 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
96 private->ximage = XCreateImage(private->xdisplay, xvisual, 1, XYBitmap,
98 private->ximage->data = data;
99 private->ximage->bitmap_bit_order = MSBFirst;
100 private->ximage->byte_order = MSBFirst;
101 image->byte_order = MSBFirst;
102 image->mem = private->ximage->data;
103 image->bpl = private->ximage->bytes_per_line;
106 } /* gdk_image_new_bitmap() */
109 gdk_image_check_xshm(Display *display)
111 * Desc: query the server for support for the MIT_SHM extension
112 * Return: 0 = not available
113 * 1 = shared XImage support available
114 * 2 = shared Pixmap support available also
118 int major, minor, ignore;
121 if (XQueryExtension(display, "MIT-SHM", &ignore, &ignore, &ignore))
123 if (XShmQueryVersion(display, &major, &minor, &pixmaps )==True)
125 return (pixmaps==True) ? 2 : 1;
137 if (!gdk_image_check_xshm (gdk_display))
139 g_warning ("MIT-SHM Extension not availible on server");
140 gdk_use_xshm = False;
146 gdk_image_new (GdkImageType type,
152 GdkImagePrivate *private;
154 XShmSegmentInfo *x_shm_info;
160 case GDK_IMAGE_FASTEST:
161 image = gdk_image_new (GDK_IMAGE_SHARED, visual, width, height);
164 image = gdk_image_new (GDK_IMAGE_NORMAL, visual, width, height);
168 private = g_new (GdkImagePrivate, 1);
169 image = (GdkImage*) private;
171 private->xdisplay = gdk_display;
172 private->image_put = NULL;
175 image->visual = visual;
176 image->width = width;
177 image->height = height;
178 image->depth = visual->depth;
180 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
184 case GDK_IMAGE_SHARED:
188 private->image_put = gdk_image_put_shared;
190 private->x_shm_info = g_new (XShmSegmentInfo, 1);
191 x_shm_info = private->x_shm_info;
193 private->ximage = XShmCreateImage (private->xdisplay, xvisual, visual->depth,
194 ZPixmap, NULL, x_shm_info, width, height);
195 if (private->ximage == NULL)
197 g_warning ("XShmCreateImage failed");
200 gdk_use_xshm = False;
204 x_shm_info->shmid = shmget (IPC_PRIVATE,
205 private->ximage->bytes_per_line * private->ximage->height,
208 if (x_shm_info->shmid == -1)
210 g_warning ("shmget failed!");
212 XDestroyImage (private->ximage);
213 g_free (private->x_shm_info);
216 gdk_use_xshm = False;
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 g_warning ("XShmAttach failed!");
254 XDestroyImage (private->ximage);
255 shmdt (x_shm_info->shmaddr);
256 shmctl (x_shm_info->shmid, IPC_RMID, 0);
258 g_free (private->x_shm_info);
261 gdk_use_xshm = False;
266 image_list = g_list_prepend (image_list, image);
278 case GDK_IMAGE_NORMAL:
279 private->image_put = gdk_image_put_normal;
281 private->ximage = XCreateImage (private->xdisplay, xvisual, visual->depth,
282 ZPixmap, 0, 0, width, height, 32, 0);
284 private->ximage->data = g_new (char, private->ximage->bytes_per_line *
285 private->ximage->height);
288 case GDK_IMAGE_FASTEST:
289 g_assert_not_reached ();
294 image->byte_order = private->ximage->byte_order;
295 image->mem = private->ximage->data;
296 image->bpl = private->ximage->bytes_per_line;
298 switch (private->ximage->bits_per_pixel)
320 gdk_image_get (GdkWindow *window,
327 GdkImagePrivate *private;
328 GdkWindowPrivate *win_private;
330 g_return_val_if_fail (window != NULL, NULL);
332 win_private = (GdkWindowPrivate *) window;
334 private = g_new (GdkImagePrivate, 1);
335 image = (GdkImage*) private;
337 private->xdisplay = gdk_display;
338 private->image_put = gdk_image_put_normal;
339 private->ximage = XGetImage (private->xdisplay,
340 win_private->xwindow,
344 image->type = GDK_IMAGE_NORMAL;
345 image->visual = gdk_window_get_visual (window);
346 image->width = width;
347 image->height = height;
348 image->depth = private->ximage->depth;
350 image->mem = private->ximage->data;
351 image->bpl = private->ximage->bytes_per_line;
358 gdk_image_get_pixel (GdkImage *image,
363 GdkImagePrivate *private;
365 g_return_val_if_fail (image != NULL, 0);
367 private = (GdkImagePrivate *) image;
369 pixel = XGetPixel (private->ximage, x, y);
375 gdk_image_put_pixel (GdkImage *image,
380 GdkImagePrivate *private;
382 g_return_if_fail (image != NULL);
384 private = (GdkImagePrivate *) image;
386 pixel = XPutPixel (private->ximage, x, y, pixel);
390 gdk_image_destroy (GdkImage *image)
392 GdkImagePrivate *private;
394 XShmSegmentInfo *x_shm_info;
397 g_return_if_fail (image != NULL);
399 private = (GdkImagePrivate*) image;
402 case GDK_IMAGE_NORMAL:
403 XDestroyImage (private->ximage);
406 case GDK_IMAGE_SHARED:
408 XShmDetach (private->xdisplay, private->x_shm_info);
409 XDestroyImage (private->ximage);
411 x_shm_info = private->x_shm_info;
412 shmdt (x_shm_info->shmaddr);
413 shmctl (x_shm_info->shmid, IPC_RMID, 0);
415 g_free (private->x_shm_info);
417 image_list = g_list_remove (image_list, image);
419 g_error ("trying to destroy shared memory image when gdk was compiled without shared memory support");
423 case GDK_IMAGE_FASTEST:
424 g_assert_not_reached ();
431 gdk_image_put_normal (GdkDrawable *drawable,
441 GdkWindowPrivate *drawable_private;
442 GdkImagePrivate *image_private;
443 GdkGCPrivate *gc_private;
445 g_return_if_fail (drawable != NULL);
446 g_return_if_fail (image != NULL);
447 g_return_if_fail (gc != NULL);
449 drawable_private = (GdkWindowPrivate*) drawable;
450 image_private = (GdkImagePrivate*) image;
451 gc_private = (GdkGCPrivate*) gc;
453 g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
455 XPutImage (drawable_private->xdisplay, drawable_private->xwindow,
456 gc_private->xgc, image_private->ximage,
457 xsrc, ysrc, xdest, ydest, width, height);
461 gdk_image_put_shared (GdkDrawable *drawable,
472 GdkWindowPrivate *drawable_private;
473 GdkImagePrivate *image_private;
474 GdkGCPrivate *gc_private;
476 g_return_if_fail (drawable != NULL);
477 g_return_if_fail (image != NULL);
478 g_return_if_fail (gc != NULL);
480 drawable_private = (GdkWindowPrivate*) drawable;
481 image_private = (GdkImagePrivate*) image;
482 gc_private = (GdkGCPrivate*) gc;
484 g_return_if_fail (image->type == GDK_IMAGE_SHARED);
486 XShmPutImage (drawable_private->xdisplay, drawable_private->xwindow,
487 gc_private->xgc, image_private->ximage,
488 xsrc, ysrc, xdest, ydest, width, height, False);
490 g_error ("trying to draw shared memory image when gdk was compiled without shared memory support");