Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreGLXWindow.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006  
00007 Copyright ? 2000-2004 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009  
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014  
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018  
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 
00026 #include "OgreGLXWindow.h"
00027 #include "OgreRoot.h"
00028 #include "OgreRenderSystem.h"
00029 #include "OgreImageCodec.h"
00030 #include "OgreException.h"
00031 #include "OgreLogManager.h"
00032 #include "OgreStringConverter.h"
00033 
00034 #include <iostream>
00035 #include <algorithm>
00036 #include <sys/time.h>
00037 #include <climits>
00038 
00039 #include <X11/Xlib.h>
00040 #include <X11/keysym.h>
00041 
00042 #ifndef NO_XRANDR
00043 #include <X11/extensions/Xrandr.h>
00044 #endif
00045 
00046 #include <GL/gl.h>
00047 #include <GL/glu.h>
00048 #include <GL/glx.h>
00049 
00050 
00051 namespace Ogre {
00052 
00053 GLXWindow::GLXWindow(Display *display) :
00054         mDisplay(display),
00055         mWindow(0),
00056         mGlxContext(0),
00057 mActive(false), mClosed(false),mFullScreen(false), mOldMode(-1) {}
00058 
00059 GLXWindow::~GLXWindow() {
00060     if(mGlxContext)
00061         glXDestroyContext(mDisplay, mGlxContext);
00062     if(mWindow)
00063         XDestroyWindow(mDisplay, mWindow);
00064 #ifndef NO_XRANDR
00065 
00066     if(mFullScreen) {
00067         // Restore original video mode.
00068         Window rootWindow = DefaultRootWindow(mDisplay);
00069         XRRScreenConfiguration *config;
00070 
00071         // Get current screen info
00072         config = XRRGetScreenInfo(mDisplay, rootWindow);
00073         if(config) {
00074             Rotation current_rotation;
00075             XRRConfigCurrentConfiguration (config, &current_rotation);
00076             //std::cerr << "Restore mode " << mOldMode << std::endl;
00077             LogManager::getSingleton().logMessage("GLXWindow::~GLXWindow -- Leaving full screen mode");
00078             XRRSetScreenConfig(mDisplay, config, rootWindow, mOldMode, current_rotation, CurrentTime);
00079             XRRFreeScreenConfigInfo(config);
00080         } else {
00081             LogManager::getSingleton().logMessage("GLXWindow::~GLXWindow -- Could not switch from full screen mode: XRRGetScreenInfo failed");
00082         }
00083     }
00084 #endif
00085 }
00086 
00087 namespace {
00088 
00100 bool LoadIcon(Display *mDisplay, Window rootWindow, const std::string &name, Pixmap *pix, Pixmap *mask) {
00101     Image img;
00102     int mWidth, mHeight;
00103     char *data, *bitmap;
00104     try {
00105         // Try to load image
00106         img.load(name);
00107         mWidth = img.getWidth();
00108         mHeight = img.getHeight();
00109         if(img.getFormat() != PF_A8R8G8B8)
00110             // Image format must be RGBA
00111             return 0;
00112     } catch(Exception &e) {
00113         // Could not find image; never mind
00114         return false;
00115     }
00116 
00117     // Allocate space for image data
00118     data = (char*)malloc(mWidth * mHeight * 4); // Must be allocated with malloc
00119     // Allocate space for transparency bitmap
00120     int wbits = (mWidth+7)/8;
00121     bitmap = (char*)malloc(wbits * mHeight);
00122 
00123     // Convert and copy image
00124     const char *imgdata = (const char*)img.getData();
00125     int sptr = 0, dptr = 0;
00126     for(int y=0; y<mHeight; y++) {
00127         for(int x=0; x<mWidth; x++) {
00128             data[dptr + 0] = 0;
00129             data[dptr + 1] = imgdata[sptr + 0];
00130             data[dptr + 2] = imgdata[sptr + 1];
00131             data[dptr + 3] = imgdata[sptr + 2];
00132             // Alpha threshold
00133             if(((unsigned char)imgdata[sptr + 3])<128) {
00134                 bitmap[y*wbits+(x>>3)] &= ~(1<<(x&7));
00135             } else {
00136                 bitmap[y*wbits+(x>>3)] |= 1<<(x&7);
00137             }
00138             sptr += 4;
00139             dptr += 4;
00140         }
00141     }
00142 
00143     /* put my pixmap data into the client side X image data structure */
00144     XImage *image = XCreateImage (mDisplay, NULL, 24, ZPixmap, 0,
00145                                   data,
00146                                   mWidth, mHeight, 8,
00147                                   mWidth*4);
00148     image->byte_order = MSBFirst; // 0RGB format
00149 
00150     /* tell server to start managing my pixmap */
00151     Pixmap retval = XCreatePixmap(mDisplay, rootWindow, mWidth,
00152                                   mHeight, 24);
00153 
00154     /* copy from client to server */
00155     GC context = XCreateGC (mDisplay, rootWindow, 0, NULL);
00156     XPutImage(mDisplay, retval, context, image, 0, 0, 0, 0,
00157               mWidth, mHeight);
00158 
00159     /* free up the client side pixmap data area */
00160     XDestroyImage(image); // also cleans data
00161     XFreeGC(mDisplay, context);
00162 
00163     *pix = retval;
00164     *mask = XCreateBitmapFromData(mDisplay, rootWindow, bitmap, mWidth, mHeight);
00165     free(bitmap);
00166     return true;
00167 }
00168 
00169 struct visual_attribs
00170 {
00171    /* X visual attribs */
00172    int id;
00173    int klass;
00174    int depth;
00175    int redMask, greenMask, blueMask;
00176    int colormapSize;
00177    int bitsPerRGB;
00178 
00179    /* GL visual attribs */
00180    int supportsGL;
00181    int transparentType;
00182    int transparentRedValue;
00183    int transparentGreenValue;
00184    int transparentBlueValue;
00185    int transparentAlphaValue;
00186    int transparentIndexValue;
00187    int bufferSize;
00188    int level;
00189    int rgba;
00190    int doubleBuffer;
00191    int stereo;
00192    int auxBuffers;
00193    int redSize, greenSize, blueSize, alphaSize;
00194    int depthSize;
00195    int stencilSize;
00196    int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
00197    int numSamples, numMultisample;
00198    int visualCaveat;
00199 };
00200 
00201 
00202 static void
00203 get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
00204                    struct visual_attribs *attribs) {
00205     const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
00206 
00207     memset(attribs, 0, sizeof(struct visual_attribs));
00208 
00209     attribs->id = vInfo->visualid;
00210 #if defined(__cplusplus) || defined(c_plusplus)
00211 
00212     attribs->klass = vInfo->c_class;
00213 #else
00214 
00215     attribs->klass = vInfo->class;
00216 #endif
00217 
00218     attribs->depth = vInfo->depth;
00219     attribs->redMask = vInfo->red_mask;
00220     attribs->greenMask = vInfo->green_mask;
00221     attribs->blueMask = vInfo->blue_mask;
00222     attribs->colormapSize = vInfo->colormap_size;
00223     attribs->bitsPerRGB = vInfo->bits_per_rgb;
00224 
00225     if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0)
00226         return;
00227     glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
00228     glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
00229     glXGetConfig(dpy, vInfo, GLX_RGBA, &attribs->rgba);
00230     glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
00231     glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
00232     glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
00233     glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
00234     glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
00235     glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
00236     glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
00237     glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
00238     glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
00239     glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
00240     glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
00241     glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
00242     glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
00243 
00244     /* get transparent pixel stuff */
00245     glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
00246     if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
00247         glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
00248         glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
00249         glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
00250         glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
00251     } else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
00252         glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
00253     }
00254 
00255     /* multisample attribs */
00256 #ifdef GLX_ARB_multisample
00257     if (ext && strstr("GLX_ARB_multisample", ext) == 0) {
00258         glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
00259         glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
00260     }
00261 #endif
00262     else {
00263         attribs->numSamples = 0;
00264         attribs->numMultisample = 0;
00265     }
00266 
00267 #if defined(GLX_EXT_visual_rating)
00268     if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
00269         glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
00270     } else {
00271         attribs->visualCaveat = GLX_NONE_EXT;
00272     }
00273 #else
00274     attribs->visualCaveat = 0;
00275 #endif
00276 }
00277 
00278 /*
00279  * Examine all visuals to find the so-called best one.
00280  * We prefer deepest RGBA buffer with depth, stencil and accum
00281  * that has no caveats.
00282  * @author Brian Paul (from the glxinfo source)
00283  */
00284 int find_best_visual(Display *dpy, int scrnum) {
00285     XVisualInfo theTemplate;
00286     XVisualInfo *visuals;
00287     int numVisuals;
00288     long mask;
00289     int i;
00290     struct visual_attribs bestVis;
00291 
00292     /* get list of all visuals on this screen */
00293     theTemplate.screen = scrnum;
00294     mask = VisualScreenMask;
00295     visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
00296     if(numVisuals == 0 || visuals == 0) {
00297         /* something went wrong */
00298         if(visuals)
00299             XFree(visuals);
00300         return -1;
00301     }
00302 
00303     /* init bestVis with first visual info */
00304     get_visual_attribs(dpy, &visuals[0], &bestVis);
00305 
00306     /* try to find a "better" visual */
00307     for (i = 1; i < numVisuals; i++) {
00308         struct visual_attribs vis;
00309 
00310         get_visual_attribs(dpy, &visuals[i], &vis);
00311 
00312         /* always skip visuals with caveats */
00313         if (vis.visualCaveat != GLX_NONE_EXT)
00314             continue;
00315 
00316         /* see if this vis is better than bestVis */
00317         if ((!bestVis.supportsGL && vis.supportsGL) ||
00318                         (bestVis.visualCaveat != GLX_NONE_EXT) ||
00319                         (!bestVis.rgba && vis.rgba) ||
00320                         (!bestVis.doubleBuffer && vis.doubleBuffer) ||
00321                         (bestVis.redSize < vis.redSize) ||
00322                         (bestVis.greenSize < vis.greenSize) ||
00323                         (bestVis.blueSize < vis.blueSize) ||
00324                         (bestVis.alphaSize < vis.alphaSize) ||
00325                         (bestVis.depthSize < vis.depthSize) ||
00326                         (bestVis.stencilSize < vis.stencilSize) ||
00327                         (bestVis.accumRedSize < vis.accumRedSize)) {
00328             /* found a better visual */
00329             bestVis = vis;
00330         }
00331     }
00332 
00333     XFree(visuals);
00334 
00335     return bestVis.id;
00336 }
00337 
00338 };
00339 
00340 void GLXWindow::create(const String& name, unsigned int width, unsigned int height, unsigned int colourDepth,
00341                        bool fullScreen, int left, int top, bool depthBuffer,
00342                        void* miscParam, ...) {
00343     std::cerr << "GLXWindow::create" << std::endl;
00344 
00345     // We will attempt to create new window on default screen op display 0
00346     int screen = DefaultScreen(mDisplay);
00347     int depth = DisplayPlanes(mDisplay, screen);
00348     Window rootWindow = RootWindow(mDisplay,screen);
00349 #ifndef NO_XRANDR
00350     // Attempt mode switch for fullscreen -- only if RANDR extension is there
00351     int dummy;
00352     if(fullScreen && ! XQueryExtension(mDisplay, "RANDR", &dummy, &dummy, &dummy)) {
00353             LogManager::getSingleton().logMessage("GLXWindow::create -- Could not switch to full screen mode: No XRANDR extension found");      
00354     } else if(fullScreen) {
00355         // Use Xrandr extension to switch video modes. This is much better than
00356         // XVidMode as you can't scroll away from the full-screen applications.
00357         XRRScreenConfiguration *config;
00358         XRRScreenSize *sizes;
00359         Rotation current_rotation;
00360         int current_size;
00361         int nsizes;
00362 
00363         // Get current screen info
00364         config = XRRGetScreenInfo(mDisplay, rootWindow);
00365         // Get available sizes
00366         if(config)
00367             sizes = XRRConfigSizes (config, &nsizes);
00368 
00369         if(config && nsizes > 0) {
00370             // Get current size and rotation
00371             mOldMode = XRRConfigCurrentConfiguration (config, &current_rotation);
00372             // Find smallest matching mode
00373             int mode = -1;
00374             int mode_width = INT_MAX;
00375             int mode_height = INT_MAX;
00376             for(int i=0; i<nsizes; i++) {
00377                 if(sizes[i].width >= width && sizes[i].height >= height &&
00378                                 sizes[i].width < mode_width && sizes[i].height < mode_height) {
00379                     mode = i;
00380                     mode_width = sizes[i].width;
00381                     mode_height = sizes[i].height;
00382                 }
00383             }
00384             if(mode >= 0) {
00385                 // Finally, set the screen configuration
00386                 LogManager::getSingleton().logMessage("GLXWindow::create -- Entering full screen mode");
00387                 XRRSetScreenConfig(mDisplay, config, rootWindow, mode, current_rotation, CurrentTime);
00388             } else {
00389                 LogManager::getSingleton().logMessage("GLXWindow::create -- Could not switch to full screen mode: No conforming mode was found");
00390             }
00391             // Free configuration data
00392             XRRFreeScreenConfigInfo(config);
00393         } else {
00394             LogManager::getSingleton().logMessage("GLXWindow::create -- Could not switch to full screen mode: XRRGetScreenInfo failed");
00395         }
00396     }
00397 #endif
00398     // Apply some magic algorithm to get the best visual
00399     int best_visual = find_best_visual(mDisplay, screen);
00400     LogManager::getSingleton().logMessage("GLXWindow::create -- Best visual is "+StringConverter::toString(best_visual));
00401 
00402     // Get information about this so-called-best visual
00403     XVisualInfo templ;
00404     int nmatch;
00405     templ.visualid = best_visual;
00406     XVisualInfo *visualInfo = XGetVisualInfo(mDisplay, VisualIDMask, &templ, &nmatch);
00407     if(visualInfo==0 || nmatch==0) {
00408         Except(999, "GLXWindow: error choosing visual", "GLXWindow::create");
00409     }
00410 
00411     XSetWindowAttributes attr;
00412     unsigned long mask;
00413     attr.background_pixel = 0;
00414     attr.border_pixel = 0;
00415     attr.colormap = XCreateColormap(mDisplay,rootWindow,visualInfo->visual,AllocNone);
00416     attr.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
00417     if(fullScreen) {
00418         mask = CWBackPixel | CWColormap | CWOverrideRedirect | CWSaveUnder | CWBackingStore | CWEventMask;
00419         attr.override_redirect = True;
00420         attr.backing_store = NotUseful;
00421         attr.save_under = False;
00422         // Fullscreen windows are always in the top left origin
00423         left = top = 0;
00424     } else
00425         mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
00426 
00427     // Create window on server
00428     mWindow = XCreateWindow(mDisplay,rootWindow,left,top,width,height,0,visualInfo->depth,InputOutput,visualInfo->visual,mask,&attr);
00429     if(!mWindow) {
00430         Except(999, "GLXWindow: XCreateWindow failed", "GLXWindow::create");
00431     }
00432 
00433     // Make sure the window is in normal state
00434     XWMHints *wm_hints;
00435     if ((wm_hints = XAllocWMHints()) != NULL) {
00436         wm_hints->initial_state = NormalState;
00437         wm_hints->input = True;
00438         wm_hints->flags = StateHint | InputHint;
00439 
00440         // Check if we can give it an icon
00441         if(depth == 24 || depth == 32) {
00442             // Woot! The right bit depth, we can load an icon
00443             if(LoadIcon(mDisplay, rootWindow, "GLX_icon.png", &wm_hints->icon_pixmap, &wm_hints->icon_mask))
00444                 wm_hints->flags |= IconPixmapHint | IconMaskHint;
00445         }
00446     }
00447 
00448     // Set size and location hints
00449     XSizeHints *size_hints;
00450     if ((size_hints = XAllocSizeHints()) != NULL) {
00451         // Otherwise some window managers ignore our position request
00452         size_hints->flags = USPosition;
00453     }
00454 
00455     // Make text property from title
00456     XTextProperty titleprop;
00457     char *lst = (char*)name.c_str();
00458     XStringListToTextProperty((char **)&lst, 1, &titleprop);
00459 
00460     XSetWMProperties(mDisplay, mWindow, &titleprop, NULL, NULL, 0, size_hints, wm_hints, NULL);
00461 
00462     // We don't like memory leaks. Free the clientside storage, but not the
00463     // pixmaps as they're still being used by the server.
00464     XFree(titleprop.value);
00465     XFree(wm_hints);
00466     XFree(size_hints);
00467 
00468     // Acquire atom to recognize window close events
00469     mAtomDeleteWindow = XInternAtom(mDisplay,"WM_DELETE_WINDOW",False);
00470     XSetWMProtocols(mDisplay,mWindow,&mAtomDeleteWindow,1);
00471 
00472     // Map window unto screen and focus it.
00473     XMapWindow(mDisplay,mWindow);
00474 
00475     // Make sure the server is up to date and focus the window
00476     XFlush(mDisplay);
00477 
00478     // Finally, create a GL context
00479     mGlxContext = glXCreateContext(mDisplay,visualInfo,NULL,True);
00480     if(!mGlxContext) {
00481         Except(999, "glXCreateContext failed", "GLXWindow::create");
00482     }
00483     glXMakeCurrent(mDisplay,mWindow,mGlxContext);
00484 
00485     // Free visual info
00486     XFree(visualInfo);
00487 
00488     mName = name;
00489     mWidth = width;
00490     mHeight = height;
00491     mFullScreen = fullScreen;
00492 }
00493 
00494 void GLXWindow::destroy(void) {
00495     if(mGlxContext)
00496         glXDestroyContext(mDisplay, mGlxContext);
00497     if(mWindow)
00498         XDestroyWindow(mDisplay, mWindow);
00499     mWindow = 0;
00500     mGlxContext = 0;
00501     mActive = false;
00502 
00503     Root::getSingleton().getRenderSystem()->detachRenderTarget( this->getName() );
00504 }
00505 
00506 bool GLXWindow::isActive() const {
00507     return mActive;
00508 }
00509 
00510 bool GLXWindow::isClosed() const {
00511     return mClosed;
00512 }
00513 
00514 void GLXWindow::reposition(int left, int top) {
00515     XMoveWindow(mDisplay,mWindow,left,top);
00516 }
00517 
00518 void GLXWindow::resize(unsigned int width, unsigned int height) {
00519     XResizeWindow(mDisplay,mWindow,width,height);
00520 }
00521 
00522 void GLXWindow::swapBuffers(bool waitForVSync) {
00523     glXSwapBuffers(mDisplay,mWindow);
00524 }
00525 
00526 void GLXWindow::processEvent(const XEvent &event) {
00527     // Process only events for this window
00528     switch(event.type) {
00529     case ClientMessage:
00530         if(event.xclient.display != mDisplay || event.xclient.window != mWindow)
00531             // Not for me
00532             break;
00533         if(event.xclient.format == 32 && event.xclient.data.l[0] == (long)mAtomDeleteWindow)  {
00534             // Window deleted -- oops, this does not work, ogre doesn't register the close
00535             //mClosed = true;
00536             //mActive = false;
00537             //Root::getSingleton().getRenderSystem()->detachRenderTarget( this->getName() );
00538         }
00539         break;
00540     case ConfigureNotify:
00541         if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
00542             // Not for me
00543             break;
00544         // Check if the window size really changed
00545         if(mWidth == event.xconfigure.width && mHeight == event.xconfigure.height)
00546             break;
00547         mWidth = event.xconfigure.width;
00548         mHeight = event.xconfigure.height;
00549 
00550         for (ViewportList::iterator it = mViewportList.begin();
00551                         it != mViewportList.end(); ++it) {
00552             (*it).second->_updateDimensions();
00553         }
00554 
00555         break;
00556     case MapNotify:
00557         if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
00558             // Not for me
00559             break;
00560         // Window was mapped to the screen
00561         mActive = true;
00562         break;
00563     case UnmapNotify:
00564         if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
00565             // Not for me
00566             break;
00567         // Window was unmapped from the screen (user switched
00568         // to another workspace, for example)
00569         mActive = false;
00570         break;
00571     }
00572 }
00573 
00574 
00575 void GLXWindow::getCustomAttribute( const String& name, void* pData ) {
00576     if( name == "GLXWINDOW" ) {
00577         *static_cast<Window*>(pData) = mWindow;
00578         return;
00579     } else if( name == "GLXDISPLAY" ) {
00580         *static_cast<Display**>(pData) = mDisplay;
00581         return;
00582     }
00583     RenderWindow::getCustomAttribute(name, pData);
00584 }
00585 
00586 void GLXWindow::writeContentsToFile(const String& filename) {
00587 
00588     ImageCodec::ImageData imgData;
00589     imgData.width = mWidth;
00590     imgData.height = mHeight;
00591     imgData.format = PF_R8G8B8;
00592 
00593     // Allocate buffer
00594     uchar* pBuffer = new uchar[mWidth * mHeight * 3];
00595 
00596     // Read pixels
00597     // I love GL: it does all the locking & colour conversion for us
00598     glReadPixels(0,0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
00599 
00600     // Wrap buffer in a chunk
00601     DataChunk chunk(pBuffer, mWidth * mHeight * 3);
00602 
00603     // Need to flip the read data over in Y though
00604     Image img;
00605     img.loadRawData(chunk, mWidth, mHeight, PF_R8G8B8 );
00606     img.flipAroundX();
00607 
00608     DataChunk chunkFlipped(img.getData(), chunk.getSize());
00609 
00610     // Get codec
00611     size_t pos = filename.find_last_of(".");
00612     String extension;
00613     if( pos == String::npos )
00614         Except(
00615                 Exception::ERR_INVALIDPARAMS,
00616                 "Unable to determine image type for '" + filename + "' - invalid extension.",
00617                 "GLXWindow::writeContentsToFile" );
00618 
00619     while( pos != filename.length() - 1 )
00620         extension += filename[++pos];
00621 
00622     // Get the codec
00623     Codec * pCodec = Codec::getCodec(extension);
00624 
00625     // Write out
00626     pCodec->codeToFile(chunkFlipped, filename, &imgData);
00627 
00628     delete [] pBuffer;
00629 
00630 
00631 }
00632 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:27 2004