Files
wmaker/wrlib/xutil.c
T

285 lines
7.5 KiB
C
Raw Normal View History

1998-09-29 22:36:29 +00:00
/* xutil.c - utility functions for X
2004-10-12 21:28:27 +00:00
*
2003-01-16 23:30:45 +00:00
* Raster graphics library
1998-09-29 22:36:29 +00:00
*
2003-01-16 23:30:45 +00:00
* Copyright (c) 1997-2003 Alfredo K. Kojima
1998-09-29 22:36:29 +00:00
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
2004-10-12 21:28:27 +00:00
*
1998-09-29 22:36:29 +00:00
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
2004-10-12 21:28:27 +00:00
*
1998-09-29 22:36:29 +00:00
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#ifdef XSHM
#include <sys/ipc.h>
#include <sys/shm.h>
#endif /* XSHM */
#include "wraster.h"
#ifdef XSHM
1998-10-21 14:43:47 +00:00
1998-09-29 22:36:29 +00:00
static int shmError;
static int (*oldErrorHandler)();
static int
errorHandler(Display *dpy, XErrorEvent *err)
{
shmError=1;
if(err->error_code!=BadAccess)
2004-10-12 21:28:27 +00:00
(*oldErrorHandler)(dpy, err);
1998-09-29 22:36:29 +00:00
return 0;
}
1998-10-21 14:43:47 +00:00
1998-09-29 22:36:29 +00:00
#endif
RXImage*
RCreateXImage(RContext *context, int depth, unsigned width, unsigned height)
{
RXImage *rximg;
1998-10-21 14:43:47 +00:00
Visual *visual = context->visual;
2004-10-12 21:28:27 +00:00
1998-09-29 22:36:29 +00:00
rximg = malloc(sizeof(RXImage));
if (!rximg) {
2004-10-12 21:28:27 +00:00
RErrorCode = RERR_NOMEMORY;
return NULL;
1998-09-29 22:36:29 +00:00
}
2004-10-12 21:28:27 +00:00
1998-09-29 22:36:29 +00:00
#ifndef XSHM
1998-10-21 14:43:47 +00:00
rximg->image = XCreateImage(context->dpy, visual, depth,
2004-10-12 21:28:27 +00:00
ZPixmap, 0, NULL, width, height, 8, 0);
1998-09-29 22:36:29 +00:00
if (!rximg->image) {
2004-10-12 21:28:27 +00:00
free(rximg);
RErrorCode = RERR_XERROR;
return NULL;
1998-09-29 22:36:29 +00:00
}
rximg->image->data = malloc(rximg->image->bytes_per_line*height);
if (!rximg->image->data) {
2004-10-12 21:28:27 +00:00
XDestroyImage(rximg->image);
free(rximg);
RErrorCode = RERR_NOMEMORY;
return NULL;
1998-09-29 22:36:29 +00:00
}
2004-10-12 21:28:27 +00:00
#else /* XSHM */
1998-09-29 22:36:29 +00:00
if (!context->attribs->use_shared_memory) {
retry_without_shm:
1998-11-23 11:32:19 +00:00
2004-10-12 21:28:27 +00:00
context->attribs->use_shared_memory = 0;
rximg->is_shared = 0;
rximg->image = XCreateImage(context->dpy, visual, depth,
ZPixmap, 0, NULL, width, height, 8, 0);
if (!rximg->image) {
free(rximg);
RErrorCode = RERR_XERROR;
return NULL;
}
rximg->image->data = malloc(rximg->image->bytes_per_line*height);
if (!rximg->image->data) {
XDestroyImage(rximg->image);
free(rximg);
RErrorCode = RERR_NOMEMORY;
return NULL;
}
1998-09-29 22:36:29 +00:00
} else {
2004-10-12 21:28:27 +00:00
rximg->is_shared = 1;
rximg->info.readOnly = False;
rximg->image = XShmCreateImage(context->dpy, visual, depth,
ZPixmap, NULL, &rximg->info, width,
height);
rximg->info.shmid = shmget(IPC_PRIVATE,
rximg->image->bytes_per_line*height,
IPC_CREAT|0777);
if (rximg->info.shmid < 0) {
context->attribs->use_shared_memory = 0;
perror("wrlib: could not allocate shared memory segment");
XDestroyImage(rximg->image);
goto retry_without_shm;
}
rximg->info.shmaddr = shmat(rximg->info.shmid, 0, 0);
if (rximg->info.shmaddr == (void*)-1) {
context->attribs->use_shared_memory = 0;
if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
perror("wrlib: shmctl");
perror("wrlib: could not allocate shared memory");
XDestroyImage(rximg->image);
goto retry_without_shm;
}
shmError = 0;
XSync(context->dpy, False);
oldErrorHandler = XSetErrorHandler(errorHandler);
XShmAttach(context->dpy, &rximg->info);
XSync(context->dpy, False);
XSetErrorHandler(oldErrorHandler);
rximg->image->data = rximg->info.shmaddr;
/* rximg->image->obdata = &(rximg->info);*/
if (shmError) {
context->attribs->use_shared_memory = 0;
XDestroyImage(rximg->image);
if (shmdt(rximg->info.shmaddr) < 0)
perror("wrlib: shmdt");
if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
perror("wrlib: shmctl");
/* printf("wrlib:error attaching shared memory segment to XImage\n");
*/
goto retry_without_shm;
}
1998-09-29 22:36:29 +00:00
}
#endif /* XSHM */
2004-10-12 21:28:27 +00:00
1998-09-29 22:36:29 +00:00
return rximg;
}
void
RDestroyXImage(RContext *context, RXImage *rximage)
{
#ifndef XSHM
XDestroyImage(rximage->image);
#else /* XSHM */
if (rximage->is_shared) {
2004-10-12 21:28:27 +00:00
XSync(context->dpy, False);
XShmDetach(context->dpy, &rximage->info);
XDestroyImage(rximage->image);
if (shmdt(rximage->info.shmaddr) < 0)
perror("wrlib: shmdt");
if (shmctl(rximage->info.shmid, IPC_RMID, 0) < 0)
perror("wrlib: shmctl");
1998-09-29 22:36:29 +00:00
} else {
2004-10-12 21:28:27 +00:00
XDestroyImage(rximage->image);
1998-09-29 22:36:29 +00:00
}
#endif
1999-04-20 14:45:36 +00:00
free(rximage);
1998-09-29 22:36:29 +00:00
}
static unsigned
getDepth(Display *dpy, Drawable d)
{
Window w;
int foo;
unsigned bar;
unsigned depth;
2004-10-12 21:28:27 +00:00
XGetGeometry(dpy, d, &w, &foo, &foo, &bar, &bar, &bar, &depth);
2004-10-12 21:28:27 +00:00
return depth;
}
RXImage*
RGetXImage(RContext *context, Drawable d, int x, int y,
2004-10-12 21:28:27 +00:00
unsigned width, unsigned height)
{
RXImage *ximg = NULL;
#ifdef XSHM
if (context->attribs->use_shared_memory && 0) {
2004-10-12 21:28:27 +00:00
ximg = RCreateXImage(context, getDepth(context->dpy, d),
width, height);
if (ximg && !ximg->is_shared) {
RDestroyXImage(context, ximg);
ximg = NULL;
}
if (ximg) {
XShmGetImage(context->dpy, d, ximg->image, x, y, AllPlanes);
}
}
if (!ximg) {
2004-10-12 21:28:27 +00:00
ximg = malloc(sizeof(RXImage));
if (!ximg) {
RErrorCode = RERR_NOMEMORY;
return NULL;
}
ximg->is_shared = 0;
ximg->image = XGetImage(context->dpy, d, x, y, width, height,
AllPlanes, ZPixmap);
}
return ximg;
#else /* !XSHM */
ximg = malloc(sizeof(RXImage));
if (!ximg) {
2004-10-12 21:28:27 +00:00
RErrorCode = RERR_NOMEMORY;
return NULL;
}
2004-10-12 21:28:27 +00:00
ximg->image = XGetImage(context->dpy, d, x, y, width, height,
2004-10-12 21:28:27 +00:00
AllPlanes, ZPixmap);
return ximg;
#endif /* !XSHM */
}
1998-09-29 22:36:29 +00:00
void
RPutXImage(RContext *context, Drawable d, GC gc, RXImage *ximage, int src_x,
2004-10-12 21:28:27 +00:00
int src_y, int dest_x, int dest_y,
unsigned int width, unsigned int height)
1998-09-29 22:36:29 +00:00
{
#ifndef XSHM
XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x,
2004-10-12 21:28:27 +00:00
dest_y, width, height);
1998-09-29 22:36:29 +00:00
#else
if (ximage->is_shared) {
2004-10-12 21:28:27 +00:00
XShmPutImage(context->dpy, d, gc, ximage->image, src_x, src_y,
dest_x, dest_y, width, height, False);
1998-09-29 22:36:29 +00:00
} else {
2004-10-12 21:28:27 +00:00
XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x,
dest_y, width, height);
1998-09-29 22:36:29 +00:00
}
XFlush(context->dpy);
#endif /* XSHM */
}
1998-10-21 14:43:47 +00:00
#ifdef XSHM
Pixmap
R_CreateXImageMappedPixmap(RContext *context, RXImage *rximage)
{
Pixmap pix;
2004-10-12 21:28:27 +00:00
pix = XShmCreatePixmap(context->dpy, context->drawable,
rximage->image->data, &rximage->info,
rximage->image->width, rximage->image->height,
rximage->image->depth);
1998-10-21 14:43:47 +00:00
return pix;
}
#endif /* XSHM */
1998-11-03 12:53:26 +00:00