/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at golgotha_source@usa.net (Subject should have "GOLG" in it) ***********************************************************************/ #include "video/x11/mitshm.hh" #include "video/x11/x11devs.hh" #include "error/error.hh" #include#include #include #include #include #include #include #include class x11_shm_image_actual_class : public x11_shm_image_class { public : XShmSegmentInfo X_shminfo; XImage *im; Display *display; GC gc; Window window; x11_shm_image_actual_class(Display *display, Window window, GC gc) : display(display), window(window), gc(gc) { ; } i4_bool copy_part_to_vram(x11_shm_extension_class *use, i4_coord x, i4_coord y, i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2); ~x11_shm_image_actual_class(); } ; class x11_shm_extension_actual_class : public x11_shm_extension_class { public : virtual void init() { x11_display_instance.shm_extension=this; // tell the display this extension exsist } void note_event(XEvent &ev) { if (ev.type==shm_base+ShmCompletion) need_sync_event=i4_F; } virtual i4_bool available(Display *display, char *display_name); // actual width and height set by X are returned x11_shm_image_class *create_shm_image(Display *display, Window window, GC gc, Visual *X_visual, int visual_depth, w16 &width, w16 &height); virtual void shutdown(Display *display) { XFlush(display); XSync(display,False); // maker sure anything with this image is drawn! need_sync_event=i4_F; } void destroy_shm_image(Display *display, x11_shm_image_class *im); } shm_instance; x11_shm_extension_class::x11_shm_extension_class() { need_sync_event=i4_F; } i4_bool x11_shm_extension_actual_class::available(Display *display, char *display_name) { int major_op; if (XQueryExtension(display,"MIT-SHM",&major_op,&shm_base,&shm_error_base)) { char *d = display_name; // make sure the display is local while (*d && (*d != ':')) d++; if (*d) *d = 0; if (strcasecmp(display_name, "unix") && display_name[0]!=0) return i4_F; return i4_T; } else return i4_F; } void x11_shm_extension_actual_class::destroy_shm_image(Display *display, x11_shm_image_class *im) { XFlush(display); XSync(display,False); // maker sure anything with this image is drawn! // Dettach the memory from the server XShmDetach(display, &((x11_shm_image_actual_class *)im)->X_shminfo); // detach the memory from us, it will be deleted! shmdt(((x11_shm_image_actual_class *)im)->X_shminfo.shmaddr); delete im; } x11_shm_image_class *x11_shm_extension_actual_class::create_shm_image(Display *display, Window window, GC gc, Visual *X_visual, int visual_depth, w16 &width, w16 &height) // actual width and height set by X are returned { width=(width+3)&(~3); x11_shm_image_actual_class *im=new x11_shm_image_actual_class(display,window,gc); im->im = XShmCreateImage(display, X_visual, visual_depth, ZPixmap, 0, &im->X_shminfo, width, height ); // create the shared memory segment im->X_shminfo.shmid = shmget (IPC_PRIVATE, width*height*I4_BYTES_PER_PIXEL, IPC_CREAT | 0777); if (im->X_shminfo.shmid<0) i4_error("shmget() failed, go figure"); im->X_shminfo.readOnly=False; // attach to the shared memory segment to us im->im->data = im->X_shminfo.shmaddr = (char *) shmat(im->X_shminfo.shmid, 0, 0); if (!im->im->data) i4_error("shmat() failed, go figure"); // get the X server to attach to it to the X server if (!XShmAttach(display, &im->X_shminfo)) i4_error("XShmAttach() failed, go figure"); XSync(display,False); // make sure segment gets attached if (shmctl(im->X_shminfo.shmid,IPC_RMID,NULL)!=0) i4_error("shmctl failed, why?"); im->data=(w8 *) (im->im->data); return im; } x11_shm_image_actual_class::~x11_shm_image_actual_class() { XFlush(display); XSync(display,False); // maker sure anything with this image is drawn! // Dettach the memory from the server if (!XShmDetach(display, &X_shminfo)) i4_error("XShmDetach() failed, go figure"); XSync(display,False); // maker sure server detached // detach the memory from us, it will be deleted! if (shmdt(X_shminfo.shmaddr)<0) i4_error("shmdt failed, oops"); im->data=0; // tell X not to try to free the memory, cause we already did. XDestroyImage(im); } #include i4_bool x11_shm_image_actual_class::copy_part_to_vram(x11_shm_extension_class *use, i4_coord x, i4_coord y, i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2) { XEvent ev; XSync(display,False); if (y1>y2 || x1>x2) return i4_T; if (use->need_sync_event) { XEvent ev; while (XCheckTypedEvent(display,use->shm_base+ShmCompletion,&ev)==False) XSync(display,False); use->need_sync_event=i4_F; } if (XCheckTypedEvent(display, ConfigureNotify,&ev)==False) { XShmPutImage(display,window,gc,im,x1,y1,x,y,x2-x1+1,y2-y1+1,True); XSync(display,False); use->need_sync_event=i4_T; return i4_T; } else // screen size changed, better wait till this event is handled cause put might be invalid { XPutBackEvent(display,&ev); return i4_F; } }