diff -Naur Irrlicht.old/CIrrDeviceLinux.cpp Irrlicht/CIrrDeviceLinux.cpp --- Irrlicht.old/CIrrDeviceLinux.cpp 2005-04-04 11:01:38.501505032 +0200 +++ Irrlicht/CIrrDeviceLinux.cpp 2005-03-13 01:26:21.000000000 +0100 @@ -13,6 +13,9 @@ #include "irrString.h" #include "Keycodes.h" #include +#include +#include +#include #include "COSOperator.h" #include "CColorConverter.h" #include "irrlicht.h" @@ -112,17 +115,45 @@ } #endif // #ifdef _IRR_COMPILE_WITH_OPENGL_ +#ifdef __IRR_VMODE__ if (fullscreen) { XF86VidModeSwitchToMode(display, screennr, &oldVideoMode); XF86VidModeSetViewPort(display, screennr, 0, 0); } +#endif + if (doublebuffer) + XdbeDeallocateBackBufferName(display, bbuffer); + if (shmem) + { + XShmDetach(display, &shminfo); + XDestroyImage(SoftwareImage); + shmdt(shminfo.shmaddr); + } + else + XDestroyImage(SoftwareImage); XCloseDisplay(display); } } +int IrrPrintXError(Display *display, XErrorEvent *event) +{ + char msg[256]; + + XGetErrorText(display, event->error_code, msg, 256); + os::Printer::log("XErrorEvent", msg, ELL_WARNING); + return 0; +} + +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, bool fullscr, bool stencilBuffer) @@ -140,18 +171,22 @@ return false; } + XSetErrorHandler(IrrPrintXError); screennr = DefaultScreen(display); // query extension s32 minor, major; +#ifdef __IRR_VMODE__ if (fullscreen && !XF86VidModeQueryVersion(display, &major, &minor)) +#endif { os::Printer::log("VidMode extension must be intalled to let irrlicht " " be able to switch to fullscreen mode. Running in window mode.", ELL_WARNING); fullscreen = false; } +#ifdef __IRR_VMODE__ // enumerate video modes s32 modeCount; @@ -166,12 +201,14 @@ VideoModeList.addMode(core::dimension2d( modes[i]->hdisplay, modes[i]->vdisplay), 0); } +#endif // get visual XVisualInfo* visual = 0; #ifdef _IRR_COMPILE_WITH_OPENGL_ - + if (DriverType == video::EDT_OPENGL) + { // no double buffer, 4 bits per color, 16 bit zbuffer int visualAttrNoDoubleBuffer[] = { @@ -235,9 +272,10 @@ visual = glXChooseVisual(display, screennr, visualAttrNoDoubleBuffer); } } - -#else // _IRR_COMPILE_WITH_OPENGL_ - + } +#endif // _IRR_COMPILE_WITH_OPENGL_ + if (!visual) + { XVisualInfo visTempl; //Template to hold requested values int visNumber; // Return value of available visuals @@ -245,8 +283,33 @@ visTempl.depth = 16; visual = XGetVisualInfo(display, VisualScreenMask|VisualDepthMask, &visTempl, &visNumber); - + if (!visual) + { + visTempl.depth = 32; + visual = XGetVisualInfo(display, VisualScreenMask|VisualDepthMask, + &visTempl, &visNumber); + } + if (!visual) + { + visTempl.depth = 24; + visual = XGetVisualInfo(display, VisualScreenMask|VisualDepthMask, + &visTempl, &visNumber); + } +#if 0 + if (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 + } -#endif // _IRR_COMPILE_WITH_OPENGL_ if (!visual) { @@ -265,26 +328,36 @@ if (context == NULL) { os::Printer::log("Could not create GLX rendering context.", ELL_WARNING); + XFree(visual); return false; } #endif // _IRR_COMPILE_WITH_OPENGL_ // 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 | ButtonReleaseMask | KeyReleaseMask; +#ifdef __IRR_VMODE__ // switch to fullscreen if extension is installed. - if (fullscreen && bestMode != -1) { os::Printer::log("Starting fullscreen mode...", ELL_INFORMATION); @@ -314,6 +387,7 @@ GrabModeAsync, GrabModeAsync, window, None, CurrentTime); } else +#endif { // we want windowed mode if (fullscreen) @@ -344,6 +418,9 @@ //os::Printer::log("Connecting glx context to window...", ELL_INFORMATION); glXMakeCurrent(display, window, context); +#else + if (doublebuffer) + bbuffer=XdbeAllocateBackBufferName(display, window, XdbeUndefined); #endif // _IRR_COMPILE_WITH_OPENGL_ Window tmp; @@ -353,18 +430,68 @@ //os::Printer::log("Window created.", ELL_INFORMATION); - // create an XImage for the software renderer //(thx to Nadav for some clues on how to do that!) if ((DriverType == video::EDT_SOFTWARE)||(DriverType == video::EDT_SOFTWARE2)) { - 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); @@ -511,14 +638,13 @@ close = true; } break; - default: break; } // end switch } // end while - - XSync(display, false); +// TODO: Is this really needed? +// XFlush(display); } return !close; @@ -615,7 +741,18 @@ image->unlock(); GC gc = DefaultGC(display, DefaultScreen(display)); - XPutImage(display, window, gc, SoftwareImage, 0, 0, 0, 0, destwidth, destheight); + if (doublebuffer) + { + 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); + } 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 Irrlicht.old/CIrrDeviceLinux.h Irrlicht/CIrrDeviceLinux.h --- Irrlicht.old/CIrrDeviceLinux.h 2005-04-04 11:01:38.514503191 +0200 +++ Irrlicht/CIrrDeviceLinux.h 2005-03-11 16:31:46.000000000 +0100 @@ -18,7 +18,11 @@ #include #include #include +#ifdef __IRR_VMODE__ #include +#endif +#include +#include #include namespace irr @@ -212,10 +216,15 @@ XSetWindowAttributes attributes; bool fullscreen; bool doublebuffer; + bool shmem; bool stencilbuffer; +#ifdef __IRR_VMODE__ XF86VidModeModeInfo oldVideoMode; +#endif XEvent event; XImage* SoftwareImage; + XdbeBackBuffer bbuffer; + XShmSegmentInfo shminfo; video::E_DRIVER_TYPE DriverType; int x,y; diff -Naur Irrlicht.old/IrrCompileConfig.h Irrlicht/IrrCompileConfig.h --- Irrlicht.old/include/IrrCompileConfig.h 2005-03-01 14:43:46.769325279 +0100 +++ Irrlicht/include/IrrCompileConfig.h 2005-03-14 16:32:22.455959120 +0100 @@ -14,6 +14,7 @@ #if !defined(WIN32) && !defined(_XBOX) && !defined(OS2) && !defined(MACOS) #define LINUX +#define __IRR_VMODE__ #endif