1 /* xutil.c - utility functions for X
3 * Raster graphics library
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <X11/Xutil.h>
43 static int (*oldErrorHandler) ();
45 static int errorHandler(Display * dpy, XErrorEvent * err)
48 if (err->error_code != BadAccess)
49 (*oldErrorHandler) (dpy, err);
56 RXImage *RCreateXImage(RContext * context, int depth, unsigned width, unsigned height)
59 Visual *visual = context->visual;
61 rximg = malloc(sizeof(RXImage));
63 RErrorCode = RERR_NOMEMORY;
67 rximg->image = XCreateImage(context->dpy, visual, depth, ZPixmap, 0, NULL, width, height, 8, 0);
70 RErrorCode = RERR_XERROR;
73 rximg->image->data = malloc(rximg->image->bytes_per_line * height);
74 if (!rximg->image->data) {
75 XDestroyImage(rximg->image);
77 RErrorCode = RERR_NOMEMORY;
81 if (!context->attribs->use_shared_memory) {
84 context->attribs->use_shared_memory = 0;
86 rximg->image = XCreateImage(context->dpy, visual, depth, ZPixmap, 0, NULL, width, height, 8, 0);
89 RErrorCode = RERR_XERROR;
92 rximg->image->data = malloc(rximg->image->bytes_per_line * height);
93 if (!rximg->image->data) {
94 XDestroyImage(rximg->image);
96 RErrorCode = RERR_NOMEMORY;
100 rximg->is_shared = 1;
102 rximg->info.readOnly = False;
104 rximg->image = XShmCreateImage(context->dpy, visual, depth,
105 ZPixmap, NULL, &rximg->info, width, height);
107 rximg->info.shmid = shmget(IPC_PRIVATE, rximg->image->bytes_per_line * height, IPC_CREAT | 0777);
108 if (rximg->info.shmid < 0) {
109 context->attribs->use_shared_memory = 0;
110 perror("wrlib: could not allocate shared memory segment");
111 XDestroyImage(rximg->image);
112 goto retry_without_shm;
115 rximg->info.shmaddr = shmat(rximg->info.shmid, 0, 0);
116 if (rximg->info.shmaddr == (void *)-1) {
117 context->attribs->use_shared_memory = 0;
118 if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
119 perror("wrlib: shmctl");
120 perror("wrlib: could not allocate shared memory");
121 XDestroyImage(rximg->image);
122 goto retry_without_shm;
126 XSync(context->dpy, False);
127 oldErrorHandler = XSetErrorHandler(errorHandler);
128 XShmAttach(context->dpy, &rximg->info);
129 XSync(context->dpy, False);
130 XSetErrorHandler(oldErrorHandler);
132 rximg->image->data = rximg->info.shmaddr;
133 /* rximg->image->obdata = &(rximg->info); */
136 context->attribs->use_shared_memory = 0;
137 XDestroyImage(rximg->image);
138 if (shmdt(rximg->info.shmaddr) < 0)
139 perror("wrlib: shmdt");
140 if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
141 perror("wrlib: shmctl");
142 /* printf("wrlib:error attaching shared memory segment to XImage\n");
144 goto retry_without_shm;
152 void RDestroyXImage(RContext * context, RXImage * rximage)
155 XDestroyImage(rximage->image);
157 if (rximage->is_shared) {
158 XSync(context->dpy, False);
159 XShmDetach(context->dpy, &rximage->info);
160 XDestroyImage(rximage->image);
161 if (shmdt(rximage->info.shmaddr) < 0)
162 perror("wrlib: shmdt");
163 if (shmctl(rximage->info.shmid, IPC_RMID, 0) < 0)
164 perror("wrlib: shmctl");
166 XDestroyImage(rximage->image);
172 static unsigned getDepth(Display * dpy, Drawable d)
179 XGetGeometry(dpy, d, &w, &foo, &foo, &bar, &bar, &bar, &depth);
184 RXImage *RGetXImage(RContext * context, Drawable d, int x, int y, unsigned width, unsigned height)
186 RXImage *ximg = NULL;
189 if (context->attribs->use_shared_memory && 0) {
190 ximg = RCreateXImage(context, getDepth(context->dpy, d), width, height);
192 if (ximg && !ximg->is_shared) {
193 RDestroyXImage(context, ximg);
197 XShmGetImage(context->dpy, d, ximg->image, x, y, AllPlanes);
201 ximg = malloc(sizeof(RXImage));
203 RErrorCode = RERR_NOMEMORY;
207 ximg->image = XGetImage(context->dpy, d, x, y, width, height, AllPlanes, ZPixmap);
211 ximg = malloc(sizeof(RXImage));
213 RErrorCode = RERR_NOMEMORY;
217 ximg->image = XGetImage(context->dpy, d, x, y, width, height, AllPlanes, ZPixmap);
224 RPutXImage(RContext * context, Drawable d, GC gc, RXImage * ximage, int src_x,
225 int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)
228 XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x, dest_y, width, height);
230 if (ximage->is_shared) {
231 XShmPutImage(context->dpy, d, gc, ximage->image, src_x, src_y,
232 dest_x, dest_y, width, height, False);
234 XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x, dest_y, width, height);
236 XFlush(context->dpy);
241 Pixmap R_CreateXImageMappedPixmap(RContext * context, RXImage * rximage)
245 pix = XShmCreatePixmap(context->dpy, context->drawable,
246 rximage->image->data, &rximage->info,
247 rximage->image->width, rximage->image->height, rximage->image->depth);