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

GlWindowXWin.cpp

Go to the documentation of this file.
00001 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00002  *
00003  * VR Juggler is (C) Copyright 1998-2003 by Iowa State University
00004  *
00005  * Original Authors:
00006  *   Allen Bierbaum, Christopher Just,
00007  *   Patrick Hartling, Kevin Meinert,
00008  *   Carolina Cruz-Neira, Albert Baker
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Library General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Library General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Library General Public
00021  * License along with this library; if not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00023  * Boston, MA 02111-1307, USA.
00024  *
00025  * -----------------------------------------------------------------
00026  * File:          $RCSfile: GlWindowXWin.cpp,v $
00027  * Date modified: $Date: 2004/04/28 19:54:23 $
00028  * Version:       $Revision: 1.80 $
00029  * -----------------------------------------------------------------
00030  *
00031  *************** <auto-copyright.pl END do not edit this line> ***************/
00032 
00033 #include <vrj/vrjConfig.h>
00034 
00035 #include <X11/Xlib.h>
00036 #include <X11/Xutil.h>
00037 #include <GL/glx.h>
00038 #include <vector>
00039 
00040 #include <vpr/vpr.h>
00041 #include <jccl/Config/ConfigElement.h>
00042 
00043 #include <vrj/Draw/OGL/GlWindow.h>
00044 #include <vrj/Kernel/Kernel.h>
00045 #include <vrj/Util/Debug.h>
00046 #include <vrj/Display/Display.h>
00047 #include <vrj/Display/DisplayManager.h>
00048 
00049 #include <vrj/Draw/OGL/GlWindowXWin.h>
00050 
00051 #include <stdexcept>
00052 
00053 namespace
00054 {
00055    class glwinx_OpenFailureException : public std::runtime_error 
00056    {
00057    public:
00058       glwinx_OpenFailureException() throw()
00059          : std::runtime_error("Failed to open glx window")
00060       {;}
00061       ~glwinx_OpenFailureException() throw() {;}      
00062    };
00063 }
00064 
00065 namespace vrj
00066 {
00067 
00068 GlWindowXWin::GlWindowXWin()
00069    : GlWindow(), mXDisplay(NULL), mVisualInfo(NULL), mGlxContext(NULL),
00070      mXWindow(0), mWindowName(""), mPipe(-1), mXDisplayName("")
00071 {
00072    window_is_open = false;
00073    window_width = window_height = -1;
00074 }
00075 
00076 GlWindowXWin::~GlWindowXWin()
00077 {
00078    close();
00079 }
00080 
00081 int GlWindowXWin::open()
00082 {
00083    /* attempts to open the glxWindow & create the gl context.  Does nothing
00084     * if the window is already open (& returns true).
00085     * returns true for success, false for failure.
00086     * The newly opened window will be set as the calling proccess'
00087     * current gl context.
00088     */
00089 
00090    ::XEvent fooevent;
00091    ::XSetWindowAttributes w_attrib;
00092    int screen;
00093    char* foo;
00094    ::XSizeHints *sizehints;
00095    ::XClassHint *classhint;
00096    unsigned long event_mask(0);    // Event masks to use   
00097    bool ret_val(true);
00098 
00099    vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_STATE_LVL) << "glxWindow: Open window\n" << vprDEBUG_FLUSH;
00100 
00101    if ( window_is_open )
00102       return true;
00103 
00104    if ( window_width == -1 )
00105    {
00106       vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00107          << clrOutNORM(clrRED,"ERROR:")
00108          << "vrj::GlWindowXWin: Window has not been configured\n"
00109          << vprDEBUG_FLUSH;
00110       return false;
00111    }
00112 
00113    if ( ! (mXDisplay = ::XOpenDisplay(mXDisplayName.c_str())) )
00114    {
00115       vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00116          << clrOutNORM(clrRED,"ERROR:")
00117          << "vrj::GlWindowXWin: Unable to open display '" << mXDisplayName
00118          << "'.\n" << vprDEBUG_FLUSH;
00119       return false;
00120    }
00121    // Try initializing the window
00122    try
00123    {
00124       screen = DefaultScreen(mXDisplay);
00125    
00126       // get an XVisualInfo*, which we'll need below
00127       if ( (mVisualInfo = getGlxVisInfo(mXDisplay, screen)) == NULL )
00128       {
00129          vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00130             << clrOutNORM(clrRED,"ERROR:") << "glXChooseVisual failed\n"
00131             << vprDEBUG_FLUSH;
00132          throw glwinx_OpenFailureException();
00133       }
00134    
00135       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00136          << "Visual ID: 0x" << std::hex << mVisualInfo->visualid << std::dec
00137          << std::endl << vprDEBUG_FLUSH;
00138    
00139       // window attributes.
00140       w_attrib.colormap = ::XCreateColormap(mXDisplay,
00141                                             RootWindow(mXDisplay, screen),
00142                                             mVisualInfo->visual,
00143                                             AllocNone);
00144    
00145       if ( w_attrib.colormap == 0 )
00146       {
00147          vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00148             << clrOutNORM(clrRED,"ERROR:")
00149             << "vrj::GlWindowXWin: XCreateColorMap failed on '" << mXDisplayName
00150             << "'.\n" << vprDEBUG_FLUSH;
00151          throw glwinx_OpenFailureException();
00152       }
00153    
00154       event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
00155                    KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
00156                    ButtonMotionMask | PointerMotionMask | StructureNotifyMask;
00157       w_attrib.event_mask = event_mask;
00158       w_attrib.border_pixel = 0x0;
00159    
00160       // get screen dimensions for translating window origin.
00161       ::XWindowAttributes winattrs;
00162       ::XGetWindowAttributes(mXDisplay, RootWindow(mXDisplay, screen), &winattrs);
00163    
00164       // create window
00165       mXWindow = ::XCreateWindow(mXDisplay, RootWindow(mXDisplay, screen),
00166                                  origin_x, winattrs.height - origin_y - window_height,
00167                                  window_width, window_height, 0,
00168                                  mVisualInfo->depth, InputOutput,
00169                                  mVisualInfo->visual,
00170                                  CWEventMask | CWColormap | CWBorderPixel,
00171                                  &w_attrib);
00172    
00173       if ( 0 == mXWindow )
00174       {
00175          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00176             << clrOutNORM(clrRED,"ERROR:")
00177             << "vrj::GlWindowXWin: Couldn't create window for " << mXDisplayName
00178             << std::endl << vprDEBUG_FLUSH;
00179          throw glwinx_OpenFailureException();
00180       }
00181 
00182       createEmptyCursor(mXDisplay, mXWindow);
00183 
00184       /***************** Set Window Name/Class/Size/Pos *********************/
00185    
00186       /* Before we map the window, we need a name for it (this is also useful for
00187        * the resource cruft that'll get rid of the borders).
00188        */
00189       classhint = ::XAllocClassHint();
00190       classhint->res_name = (char*)mWindowName.c_str();
00191       classhint->res_class = "VRJ GLX";
00192       //XSetClassHint(mXDisplay, mXWindow, classhint);
00193    
00194       // InSoc makes things simple
00195       // X makes things complicated
00196       ::XTextProperty w_name;
00197       foo = (char*) mWindowName.c_str();
00198       ::XStringListToTextProperty(&foo, 1, &w_name);
00199    
00200       /* guarantee window position */
00201       sizehints = XAllocSizeHints();
00202       sizehints->flags = USPosition;
00203    
00204       ::XSetWMProperties(mXDisplay, mXWindow, &w_name, &w_name,
00205                          NULL, 0, sizehints, NULL, classhint);
00206    
00207       ::XFree(w_name.value);
00208       ::XFree(classhint);
00209       ::XFree(sizehints);
00210    
00211       /***************** Border Stuff ***************************/
00212    
00213       /* Get rid of window border, if configured to do so.
00214        * This technique doesn't require any modifications to the .XDefaults file
00215        * or anything, but it will only work with window managers based on MWM
00216        * (the Motif window manager).  That covers most cases.
00217        * Unfortunately, the generic X resources for communicating with a window
00218        * manager don't support this feature.
00219        */
00220       if ( !border )
00221       {
00222          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_HVERB_LVL) << "attempting to make window borderless"
00223             << std::endl << vprDEBUG_FLUSH;
00224          Atom MotifHints = XInternAtom(mXDisplay, "_MOTIF_WM_HINTS", 0);
00225          if ( MotifHints == None )
00226          {
00227             vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00228                << clrOutNORM(clrRED,"ERROR:")
00229                << "vrj::GlWindowXWin: Could not get X atom for _MOTIF_WM_HINTS."
00230                << std::endl << vprDEBUG_FLUSH;
00231          }
00232          else
00233          {
00234             MotifWmHints hints;
00235             hints.flags = MWM_HINTS_DECORATIONS;
00236             hints.decorations = 0;
00237             XChangeProperty(mXDisplay, mXWindow, MotifHints, MotifHints, 32,
00238                             PropModeReplace, (unsigned char *) &hints, 4);
00239          }
00240       }
00241    
00242       /********************* Mapping Window **************************/
00243    
00244       /* Open the window, select the input events, and wait until mapped (XIfEvent) */
00245       ::XSelectInput(mXDisplay, mXWindow, event_mask);
00246       ::XMapWindow(mXDisplay, mXWindow);
00247       ::XIfEvent(mXDisplay, &fooevent, EventIsMapNotify, (XPointer)mXWindow);
00248       ::XSync(mXDisplay, 0);
00249    
00250       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_VERB_LVL) << "vrj::GlWindowXWin: done mapping window\n"
00251                                   << vprDEBUG_FLUSH;
00252    
00253       /********************* OpenGL Context Stuff *********************/
00254    
00255       mGlxContext = glXCreateContext(mXDisplay, mVisualInfo, NULL, True);
00256       if ( NULL == mGlxContext )
00257       {
00258          vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00259             << clrOutNORM(clrRED,"ERROR:") << "Couldn't create GlxContext for '"
00260             << mXDisplayName << "'\n" << vprDEBUG_FLUSH;
00261          throw glwinx_OpenFailureException();      
00262       }
00263    
00264       window_is_open = true;
00265    
00266       // ----------- Event window device starting -------------- //
00267       if ( true == mAreEventSource )    // Are we going to act as an event source?
00268       {
00269          // Set the parameters that we will need to get events
00270          gadget::EventWindowXWin::mWindow  = mXWindow;
00271          gadget::EventWindowXWin::mVisual  = mVisualInfo;
00272          gadget::EventWindowXWin::mDisplay = mXDisplay;
00273    
00274          // Start up the device
00275          /*   Do it in out check event function
00276          gadget::EventWindowXWin::startSampling();
00277          */
00278    
00279          gadget::Input* dev_ptr = dynamic_cast<gadget::Input*>(this);
00280    
00281          // XXX: Possibly not the best way to add this to input manager
00282          // - What happens when the event window is removed at run-time???
00283          vrj::Kernel::instance()->getInputManager()->addDevice(dev_ptr);
00284       }
00285    
00286       ret_val = true;
00287    }
00288    catch (glwinx_OpenFailureException& openFailed)
00289    {
00290       // close() is coincidentally safe to call on a partially-opened
00291       // GlWindowXWin, and will deallocate all the stuff we might have
00292       // allocated above.
00293       close();
00294 
00295       ret_val = false;
00296    }
00297    
00298    return ret_val;
00299 }
00300 
00305 int GlWindowXWin::close()
00306 {
00307 
00308    //vprASSERT( !mXfuncLock.test() && "Attempting to close a display window that is locked" );
00309    // Assert that we have not impllemented correct shutdown for the case that we
00310    // are an event window as well
00311    //vprASSERT(!mAreEventSource  && "Need to implement GLX window close with gadget::EventWindow");
00312 
00313    // Remove any event device from the input manager
00314    if ( true == mAreEventSource )
00315    {
00316       gadget::Input* dev_ptr = dynamic_cast<gadget::Input*>(this);
00317 
00318       // XXX: Possibly not the best way to remove this to input manager
00319       // - This will internally call stop sampling (and stupify and proxies)
00320       //   Note: The stop sampling will not do anything since the event window does not own the window
00321       vrj::Kernel::instance()->getInputManager()->removeDevice(dev_ptr);
00322    }
00323 
00324    if ( mGlxContext )
00325    {
00326       makeCurrent();    // Might not need this
00327       //glFlush();      // This is done by the changing context
00328       glXMakeCurrent(mXDisplay, None, NULL);     // Release the context, and don't assign a new one
00329       glXDestroyContext(mXDisplay, mGlxContext);
00330       mGlxContext = NULL;
00331    }
00332    if ( mXWindow )
00333    {
00334       ::XDestroyWindow(mXDisplay, mXWindow);
00335       mXWindow = 0;
00336    }
00337    if ( mVisualInfo )
00338    {
00339       ::XFree(mVisualInfo);
00340       mVisualInfo = NULL;
00341    }
00342    if ( mXDisplay )
00343    {
00344       ::XCloseDisplay(mXDisplay);
00345       mXDisplay = NULL;
00346    }
00347 
00348    window_is_open = false;    // We are closed now
00349 
00350    return true;
00351 
00352 } /* close() */
00353 // Buffer swapping method
00354 void GlWindowXWin::swapBuffers()
00355 {
00356    glXSwapBuffers(mXDisplay, mXWindow);
00357 }
00358 // Make context current
00359 bool GlWindowXWin::makeCurrent()
00360 {
00361    /* returns true for success,
00362     * false for failure (eg window not open or glXMakeCurrent fails)
00363     */
00364    if ( !window_is_open )
00365    {
00366       return false;
00367    }
00368 
00369    vprASSERT(mGlxContext != NULL);
00370    vprASSERT(mXWindow != 0);
00371    vprASSERT(mXDisplay != NULL);
00372 
00373    return glXMakeCurrent(mXDisplay, mXWindow, mGlxContext);
00374 }
00375 
00376 void GlWindowXWin::configWindow(vrj::Display* disp)
00377 {
00378    const char neg_one_string[] = "-1";
00379    vrj::GlWindow::configWindow(disp);
00380 
00381    // Get the vector of display elements.
00382    jccl::ConfigElementPtr disp_sys_elt = DisplayManager::instance()->getDisplaySystemElement();
00383    jccl::ConfigElementPtr display_elt = disp->getConfigElement();
00384 
00385    mWindowName = disp->getName();
00386    mPipe = disp->getPipe();
00387    vprASSERT(mPipe >= 0);
00388 
00389    // NOTE: ConfigElements return the default value for a property if a value is
00390    //       not present. So if a pipe string is not specified for this pipe then
00391    //       it gets the default value of "-1".
00392    mXDisplayName = disp_sys_elt->getProperty<std::string>("x11_pipes", mPipe);
00393 
00394    if ( mXDisplayName == neg_one_string )    // Use display env
00395    {
00396       const std::string DISPLAY_str("DISPLAY");    // DISPLAY_str[] = "DISPLAY";
00397       const char* d = getenv(DISPLAY_str.c_str());
00398       if ( NULL != d )
00399       {
00400          mXDisplayName = std::string( d );
00401       }
00402    }
00403    vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_VERB_LVL) << "glxWindow::config: display name is: "
00404       << mXDisplayName << std::endl << vprDEBUG_FLUSH;
00405 
00406    mAreEventSource = display_elt->getProperty<bool>("act_as_event_source");
00407 
00408    // If should be an event source.
00409    if ( true == mAreEventSource )
00410    {
00411       // Configure event window device portion.
00412       jccl::ConfigElementPtr event_win_element =
00413          display_elt->getProperty<jccl::ConfigElementPtr>("event_window_device");
00414 
00415       // Set the name of the element to the same as the parent element (so we
00416       // can point at it).
00417       //event_win_element->setProperty("name", display_elt->getName();
00418 
00419       gadget::EventWindowXWin::config(event_win_element);
00420 
00421       // Custom configuration
00422       gadget::EventWindowXWin::mWidth  = GlWindowXWin::window_width;
00423       gadget::EventWindowXWin::mHeight = GlWindowXWin::window_height;
00424 
00425       mWeOwnTheWindow = false;      // Event window device does not own window
00426    }
00427 }
00428 
00429 bool GlWindowXWin::createHardwareSwapGroup(std::vector<vrj::GlWindow*> wins)
00430 {
00431    // Convert to glx windows
00432    std::vector<GlWindowXWin*> glx_wins;
00433    unsigned int i;
00434 
00435    if ( wins.size() <= 0 )
00436    {
00437       vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00438          << "WARNING: createHardwareSwapGroup called with no windows\n"
00439          << vprDEBUG_FLUSH;
00440    }
00441 
00442    for ( i = 0; i < wins.size(); ++i )
00443    {
00444       GlWindowXWin* glx_win = dynamic_cast<GlWindowXWin*>(wins[i]);
00445       vprASSERT(glx_win != NULL);    // Make sure we have the right type
00446       glx_wins.push_back(glx_win);
00447    }
00448 
00449    // Create hardware group
00450 #ifdef VPR_OS_IRIX
00451    for ( i = 0; i < glx_wins.size(); ++i )      // For each window
00452    {
00453       // If not me then add with me to the swap group.
00454       if ( glx_wins[i] != this )
00455       {
00456          glXJoinSwapGroupSGIX(mXDisplay, mXWindow, glx_wins[i]->mXWindow);
00457       }
00458    }
00459 
00460 #else
00461    vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00462       << "WARNING: createHardwareSwapGroup not supported.\n" << vprDEBUG_FLUSH;
00463 #endif
00464    return true;
00465 }
00466 
00467 void GlWindowXWin::checkEvents()
00468 {
00469    // Node, this will call processEvent() in the final phase (see below)
00470    if ( true == mAreEventSource )
00471    {
00472       gadget::EventWindowXWin::sample();    
00473    }
00474 
00475 }
00476 
00477 /***********************************************************/
00478 /* private member functions.  these get profoundly painful */
00479 /***********************************************************/
00480 ::XVisualInfo* GlWindowXWin::getGlxVisInfo(::Display *display, int screen)
00481 {
00482    /* pre:  screen is a screen on the current XDisplay, and
00483     *       XDisplay is already defined and valid.
00484     * post: returns a pointer to an XVisualInfo to be used for GLX.
00485     *       Note that it doesn't necessarily have _all_ of the requested
00486     *       features... it will attempt to get a visual in mono or
00487     *       without alpha if it's virst attempts fail.
00488     *       Returns NULL if it can't come up with a reasonably close
00489     *       XVisualInfo, or if the display in question doesn't support
00490     *       GLX
00491     */
00492 
00493    // Using 1 here requests the *largest* available size for each of these
00494    // buffers.  Refer to the glXChooseVisual() manual page for more details.
00495    int red_size(1), green_size(1), blue_size(1), alpha_size(1), db_size(1);
00496    bool want_fsaa(false);
00497 
00498    jccl::ConfigElementPtr gl_fb_elt = mVrjDisplay->getGlFrameBufferConfig();
00499 
00500    if ( gl_fb_elt.get() != NULL )
00501    {
00502       red_size   = gl_fb_elt->getProperty<int>("red_size");
00503       green_size = gl_fb_elt->getProperty<int>("green_size");
00504       blue_size  = gl_fb_elt->getProperty<int>("blue_size");
00505       alpha_size = gl_fb_elt->getProperty<int>("alpha_size");
00506       db_size    = gl_fb_elt->getProperty<int>("depth_buffer_size");
00507       want_fsaa  = gl_fb_elt->getProperty<bool>("fsaa_enable");
00508 
00509       if ( red_size < 0 )
00510       {
00511          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00512             << "WARNING: Red channel size was negative, set to: " << red_size
00513             << ".  Setting to 1.\n" << vprDEBUG_FLUSH;
00514          red_size = 1;
00515       }
00516 
00517       if ( green_size < 0 )
00518       {
00519          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00520             << "WARNING: Green channel size was negative, set to: "
00521             << green_size << ".  Setting to 1.\n" << vprDEBUG_FLUSH;
00522          green_size = 1;
00523       }
00524 
00525       if ( blue_size < 0 )
00526       {
00527          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00528             << "WARNING: Blue channel size was negative, set to: " << blue_size
00529             << ".  Setting to 1.\n" << vprDEBUG_FLUSH;
00530          blue_size = 1;
00531       }
00532 
00533       if ( alpha_size < 0 )
00534       {
00535          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00536             << "WARNING: Alpha channel size was negative, set to: "
00537             << alpha_size << ".  Setting to 1.\n" << vprDEBUG_FLUSH;
00538          alpha_size = 1;
00539       }
00540 
00541       if ( db_size < 0 )
00542       {
00543          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00544             << "WARNING: Depth buffer size was negative, set to: " << db_size
00545             << ".  Setting to 1.\n" << vprDEBUG_FLUSH;
00546          db_size = 1;
00547       }
00548    }
00549 
00550    vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00551       << "Frame buffer visual settings for " << mVrjDisplay->getName()
00552       << ": R:" << red_size << " G:" << green_size << " B:" << blue_size
00553       << " A:" << alpha_size << " DB:" << db_size << std::endl
00554       << vprDEBUG_FLUSH;
00555 
00556    ::XVisualInfo *vi;
00557    std::vector<int> viattrib;
00558    viattrib.push_back(GLX_DOUBLEBUFFER);
00559    viattrib.push_back(GLX_RGBA);
00560    viattrib.push_back(GLX_DEPTH_SIZE); viattrib.push_back(db_size);
00561    viattrib.push_back(GLX_RED_SIZE); viattrib.push_back(red_size);
00562    viattrib.push_back(GLX_GREEN_SIZE); viattrib.push_back(green_size);
00563    viattrib.push_back(GLX_BLUE_SIZE); viattrib.push_back(blue_size);
00564    viattrib.push_back(GLX_ALPHA_SIZE); viattrib.push_back(alpha_size);
00565    const unsigned int AlphaAttribIndex = 11;
00566 
00567    // Enable full-screen anti-aliasing if it is available and it was requested.
00568 #ifdef GLX_SAMPLES_SGIS
00569    // Save the current attribute vector size so we can try disabling FSAA if
00570    // necessary.
00571    const unsigned int fsaa_attrib_index = viattrib.size();
00572 
00573    if ( want_fsaa )
00574    {
00575       viattrib.push_back(GLX_SAMPLES_SGIS); viattrib.push_back(1);
00576       viattrib.push_back(GLX_SAMPLE_BUFFERS_SGIS); viattrib.push_back(1);
00577    }
00578 #else
00579    if ( want_fsaa )
00580    {
00581       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00582          << "WARNING: Full-screen anti-aliasing is not available\n"
00583          << vprDEBUG_FLUSH;
00584    }
00585 #endif
00586 
00587    /* Notes on viattrib:  by using 1 for GLX_RED_SIZE et.al. we ask
00588     * for the _largest_ available buffers.  If this fails,  we might
00589     * want to try setting alpha size to 0 (smallest possible, maybe 0)
00590     * which is required eg. for alpha on the indys.
00591     *
00592     * Implementation note: the code below makes assumptions about the
00593     * exact order of the arguments in viattrib.  Alter those, & you'll
00594     * Need to redo the indices used.
00595     */
00596 
00597    if ( !glXQueryExtension(display, NULL, NULL) )
00598    {
00599       vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00600          << clrOutNORM(clrRED, "ERROR:") << " X Display '" << mXDisplayName
00601          << "' doesn't support GLX.\n" << vprDEBUG_FLUSH;
00602       return NULL;
00603    }
00604 
00605    if ( mVrjDisplay->isStereoRequested() )
00606    {
00607       viattrib.push_back(GLX_STEREO);
00608       in_stereo = true;
00609    }
00610    else
00611    {
00612       in_stereo = false;
00613    }
00614 
00615    // Add terminator
00616    viattrib.push_back(None);
00617 
00618    // first, see if we can get exactly what we want.
00619    if ( (vi = glXChooseVisual(display, screen, &viattrib[0])) != NULL )
00620    {
00621       return vi;
00622    }
00623 
00624    // still no luck. if we were going for stereo, let's try without.
00625    if ( mVrjDisplay->isStereoRequested() )
00626    {
00627       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00628          << "WARNING: Display process for '" << mXDisplayName
00629          << "' couldn't get display in stereo - trying mono.\n"
00630          << vprDEBUG_FLUSH;
00631       in_stereo = false;
00632       viattrib[viattrib.size() - 1] = GLX_USE_GL; // should be a reasonable 'ignore' tag
00633 
00634       if ( (vi = glXChooseVisual(display, screen, &viattrib[0])) != NULL )
00635       {
00636          return vi;
00637       }
00638    }
00639 
00640    // if we reach here, we didn't.  Maybe we should make alpha optional.
00641    vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00642       << "WARNING: Display process for '" << mXDisplayName
00643       << "' couldn't get display with alpha channel - trying without.\n"
00644       << vprDEBUG_FLUSH;
00645    viattrib[AlphaAttribIndex] = 0;
00646 
00647    if ( (vi = glXChooseVisual(display, screen, &viattrib[0])) != NULL )
00648    {
00649       return vi;
00650    }
00651 
00652 #ifdef GLX_SAMPLES_SGIS
00653    // Last-ditch effort: try disabling FSAA if it was enabled.
00654    // XXX: It might be better to try disabling FSAA *first* instead of last.
00655    if ( want_fsaa )
00656    {
00657       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00658          << "WARNING: Display process for '" << mXDisplayName
00659      << "' couldn't get FSAA - trying without it.\n" << vprDEBUG_FLUSH;
00660 
00661       // Disabling is achieved by moving the terminator for the attribute
00662       // array up to the beginning of the FSAA attributes.  This effectively
00663       // blocks off anything that was added to the vector after the FSAA
00664       // attribute settings, so this isn't necessarily a good thing...
00665       viattrib[fsaa_attrib_index] = None;
00666 
00667       if ( (vi = glXChooseVisual(display, screen, &viattrib[0])) != NULL )
00668       {
00669          return vi;
00670       }
00671    }
00672 #endif
00673 
00674    // Failed, so return NULL
00675    return NULL;
00676 }
00677 
00684 int GlWindowXWin::EventIsMapNotify(::Display* display, ::XEvent* e,
00685                                    ::XPointer window)
00686 {
00687    boost::ignore_unused_variable_warning(display);
00688    return((e->type == MapNotify) && (e->xmap.window == (Window)window));
00689 }
00690 
00691 void GlWindowXWin::processEvent(XEvent event)
00692 {
00693    switch ( event.type )
00694    {
00695       case ConfigureNotify:
00696          //std::cout << "GlWindowXWin::processEvent: Got configure notify." << std::endl;
00697          updateOriginSize(vrj::GlWindow::origin_x, vrj::GlWindow::origin_y,
00698                           event.xconfigure.width, event.xconfigure.height);
00699          vrj::GlWindow::setDirtyViewport(true);
00700          break;
00701 
00702       default:
00703          break;
00704    }
00705 }
00706 
00707 } // namespace vrj

Generated on Sun May 2 15:10:17 2004 for VR Juggler by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002