diff -Naur source/Irrlicht.old/CIrrDeviceLinux.cpp source/Irrlicht/CIrrDeviceLinux.cpp --- source/Irrlicht.old/CIrrDeviceLinux.cpp 2005-04-04 11:01:38.501505032 +0200 +++ source/Irrlicht/CIrrDeviceLinux.cpp 2005-03-13 01:26:21.000000000 +0100 @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include #include "IEventReceiver.h" #include "irrList.h" #include "os.h" @@ -125,7 +128,20 @@ #endif if (DriverType == video::EDT_SOFTWARE || DriverType == video::EDT_SOFTWARE2) + { +#if 0 + if (doublebuffer) + XdbeDeallocateBackBufferName(display, bbuffer); +#endif + if (shmem) + { + XShmDetach(display, &shminfo); + XDestroyImage(SoftwareImage); + shmdt(shminfo.shmaddr); + } + else XDestroyImage(SoftwareImage); + } XDestroyWindow(display,window); XCloseDisplay(display); } @@ -142,6 +156,14 @@ return 0; } #endif + +bool shmemerror=false; +int IrrCatchXShmError(Display *display, XErrorEvent *event) +{ + if (event->error_code == BadAccess) + shmemerror=true; + return 0; +} bool CIrrDeviceLinux::createWindow(const core::dimension2d& windowSize, u32 bits) @@ -161,6 +183,7 @@ return false; } + XSetErrorHandler(IrrPrintXError); screennr = DefaultScreen(display); // query extension @@ -214,6 +237,8 @@ #ifdef _IRR_COMPILE_WITH_OPENGL_ + if (DriverType == video::EDT_OPENGL) + { Context=0; bool glxDrawable=false; GLXFBConfig glxFBConfig; @@ -305,6 +330,7 @@ } else os::Printer::log("No GLX support.", ELL_WARNING); + } #endif // _IRR_COMPILE_WITH_OPENGL_ @@ -323,6 +361,20 @@ visTempl.depth+=8; } } +#if 0 + if (visual && XdbeQueryExtension(display, &major, &minor)) + { + XdbeScreenVisualInfo *DBEVisuals; + int numScreens=1; + if (DBEVisuals = XdbeGetVisualInfo(display, &RootWindow(display, screennr), &numScreens)) + { + for (int i=0; icount; ++i) + if (DBEVisuals->visinfo[i].visual == visual->visualid) + doublebuffer=true; + } + XdbeFreeVisualInfo(DBEVisuals); + } +#endif if (!visual) { @@ -335,11 +387,22 @@ // create color map Colormap colormap; - colormap = XCreateColormap(display, + XStandardColormap *bestMapInfo; + int count; + + if (!XGetRGBColormaps(display, RootWindow(display, visual->screen), + &bestMapInfo, &count, XA_RGB_BEST_MAP)) + { + colormap = XCreateColormap(display, RootWindow(display, visual->screen), visual->visual, AllocNone); + attributes.colormap = colormap; + } + else + { + attributes.colormap = bestMapInfo->colormap; + } - attributes.colormap = colormap; attributes.border_pixel = 0; attributes.event_mask = KeyPressMask | ButtonPressMask | StructureNotifyMask | PointerMotionMask | @@ -424,6 +487,8 @@ #ifdef _IRR_COMPILE_WITH_OPENGL_ + if (DriverType == video::EDT_OPENGL) + { // connect glx context to window if (glxDrawable) { @@ -469,6 +532,7 @@ os::Printer::log("Could not create GLX rendering context.", ELL_WARNING); } } + } #endif // _IRR_COMPILE_WITH_OPENGL_ Window tmp; @@ -481,12 +543,65 @@ if (DriverType == video::EDT_SOFTWARE || DriverType == video::EDT_SOFTWARE2) { + if (doublebuffer) + bbuffer=XdbeAllocateBackBufferName(display, window, XdbeUndefined); - SoftwareImage = XCreateImage(display, - visual->visual, visual->depth, - ZPixmap, 0, 0, Width, Height, - BitmapPad(display), 0); + int pixmaps; - SoftwareImage->data = new char[SoftwareImage->bytes_per_line * SoftwareImage->height]; + SoftwareImage=NULL; +#if 1 + XSetErrorHandler(IrrCatchXShmError); + if (XShmQueryVersion(display, &major, &minor, &pixmaps)) + { + SoftwareImage = XShmCreateImage(display, + visual->visual, visual->depth, + ZPixmap, NULL, &shminfo, Width, Height); + if (SoftwareImage) + { + shminfo.shmid = shmget(IPC_PRIVATE, SoftwareImage->bytes_per_line * SoftwareImage->height, IPC_CREAT|0777); + if (shminfo.shmid != -1) + { + SoftwareImage->data = shminfo.shmaddr = (char*)shmat(shminfo.shmid, 0, 0); + if (shminfo.shmaddr != (char*)-1) + { + shminfo.readOnly = False; + if (XShmAttach(display, &shminfo)) + { + shmem=true; + XSync(display,False); + } + } + } + } + } + // According to the docs the area should be freed as + // soon as possible in case the application dies... + shmctl(shminfo.shmid, IPC_RMID, NULL); + XSetErrorHandler(IrrPrintXError); + if (shmemerror) + shmem=false; + if (!shmem) + { + XShmDetach(display, &shminfo); + if (SoftwareImage) + XDestroyImage(SoftwareImage); + SoftwareImage=NULL; + if (shminfo.shmaddr) + shmdt(shminfo.shmaddr); + } + else + { + os::Printer::log("Using XShmem Extension", ELL_WARNING); + } +#endif + if (!SoftwareImage) + { + SoftwareImage = XCreateImage(display, + visual->visual, visual->depth, + ZPixmap, 0, 0, Width, Height, + BitmapPad(display), 0); + SoftwareImage->data = new char[SoftwareImage->bytes_per_line * SoftwareImage->height]; + shmem=false; + } } XFree(visual); @@ -820,7 +935,20 @@ } GC gc = DefaultGC(display, DefaultScreen(display)); - XPutImage(display, window, gc, SoftwareImage, 0, 0, 0, 0, destwidth, destheight); + if (doublebuffer) + { +#if 0 + XdbeSwapInfo swapInfo; + swapInfo.swap_window=window; + swapInfo.swap_action=XdbeUndefined; + + XPutImage(display, bbuffer, gc, SoftwareImage, 0, 0, 0, 0, destwidth, destheight); + XdbeSwapBuffers(display, &swapInfo, 1); +#endif + } else if (shmem) + XShmPutImage(display, window, gc, SoftwareImage, 0, 0, 0, 0, destwidth, destheight, false); + else + XPutImage(display, window, gc, SoftwareImage, 0, 0, 0, 0, destwidth, destheight); } diff -Naur source/Irrlicht.old/CIrrDeviceLinux.h source/Irrlicht/CIrrDeviceLinux.h --- source/Irrlicht.old/CIrrDeviceLinux.h 2005-04-04 11:01:38.514503191 +0200 +++ source/Irrlicht/CIrrDeviceLinux.h 2005-03-11 16:31:46.000000000 +0100 @@ -24,6 +24,8 @@ #ifdef _IRR_LINUX_X11_VIDMODE_ #include #endif +#include +#include #include namespace irr @@ -212,11 +216,14 @@ XSetWindowAttributes attributes; bool Fullscreen; bool StencilBuffer; + bool shmem; #ifdef _IRR_LINUX_X11_VIDMODE_ XF86VidModeModeInfo oldVideoMode; #endif XEvent event; XImage* SoftwareImage; + XdbeBackBuffer bbuffer; + XShmSegmentInfo shminfo; video::E_DRIVER_TYPE DriverType; int x,y;