vrj::GlWindowXWin Class Reference

A GLX-specific window for displaying OpenGL graphics. More...

#include <vrj/Draw/OGL/GlWindowXWin.h>

Inheritance diagram for vrj::GlWindowXWin:

Inheritance graph
[legend]
Collaboration diagram for vrj::GlWindowXWin:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 GlWindowXWin ()
virtual ~GlWindowXWin ()
virtual void swapBuffers ()
 Performs an OpenGL swap buffers command.
virtual bool open ()
 Opens the OpenGL window.
virtual bool close ()
 Closes the window given.
bool makeCurrent ()
 Sets the current OpenGL context to this window.
virtual void checkEvents ()
 Checks events.
void configWindow (vrj::Display *disp)
 Configure the window settings based on the display information.

Protected Member Functions

virtual void processEvent (::XEvent event)
 Do any extra event processing needed.
XVisualInfo * getGlxVisInfo (::Display *display, int screen)
void createEmptyCursor (::Display *display,::Window root)

Static Protected Member Functions

static int eventIsMapNotify (::Display *display, XEvent *e, XPointer window)
 
Precondition:
window is an xwindow under display.


Detailed Description

A GLX-specific window for displaying OpenGL graphics.

It holds all the information specific to dealing with a GLX window.

This class is responsbile for connecting to the X server, getting a GLX visual, opening a GL window and associated context, and handling all managment of that context.

Definition at line 74 of file GlWindowXWin.h.


Constructor & Destructor Documentation

vrj::GlWindowXWin::GlWindowXWin (  ) 

Definition at line 70 of file GlWindowXWin.cpp.

References vrj::GlWindow::mWindowHeight, vrj::GlWindow::mWindowIsOpen, and vrj::GlWindow::mWindowWidth.

00071    : GlWindow()
00072 //   , mXDisplay(NULL)
00073    , mVisualInfo(NULL)
00074    , mGlxContext(NULL)
00075 //   , mXWindow(0)
00076    , mWindowName("")
00077    , mPipe(-1)
00078    , mXDisplayName(""),
00079    mEmptyCursorSet(false)
00080 {
00081    mWindowIsOpen = false;
00082    mWindowWidth = mWindowHeight = -1;
00083 
00084    // XEvent processing is not blocking.
00085    mBlocking = false;
00086 }

vrj::GlWindowXWin::~GlWindowXWin (  )  [virtual]

Definition at line 88 of file GlWindowXWin.cpp.

References close().

00089 {
00090    close();
00091 }


Member Function Documentation

void vrj::GlWindowXWin::swapBuffers (  )  [virtual]

Performs an OpenGL swap buffers command.

Postcondition:
A glFlush must be called explicitly by the implementation or explicitly by the functions used in the implementation.

Reimplemented from vrj::GlWindow.

Definition at line 411 of file GlWindowXWin.cpp.

References vrj::GlWindow::swapBuffers().

00412 {
00413    GlWindow::swapBuffers();
00414    glXSwapBuffers(mXDisplay, mXWindow);
00415 }

bool vrj::GlWindowXWin::open (  )  [virtual]

Opens the OpenGL window.

Precondition:
this has been configured.

Reimplemented from vrj::GlWindow.

Definition at line 93 of file GlWindowXWin.cpp.

References close(), createEmptyCursor(), vrj::MotifWmHints::decorations, eventIsMapNotify(), vrj::MotifWmHints::flags, getGlxVisInfo(), vrj::GlxExtensionLoader::glXBindSwapBarrierNV(), vrj::GlxExtensionLoader::glXJoinSwapGroupNV(), vrj::GlxExtensionLoader::glXQueryMaxSwapGroupsNV(), vrj::GlxExtensionLoader::hasSwapGroupNV(), makeCurrent(), vrj::GlWindow::mHasBorder, vrj::GlWindow::mHideMouse, vrj::GlWindow::mOriginX, vrj::GlWindow::mOriginY, vrj::GlWindow::mWindowHeight, vrj::GlWindow::mWindowIsOpen, vrj::GlWindow::mWindowWidth, MWM_HINTS_DECORATIONS, vrj::GlxExtensionLoader::registerExtensions(), and vrjDBG_DRAW_MGR().

00094 {
00095    /* attempts to open the glxWindow & create the gl context.  Does nothing
00096     * if the window is already open (& returns true).
00097     * returns true for success, false for failure.
00098     * The newly opened window will be set as the calling proccess'
00099     * current gl context.
00100     */
00101 
00102    ::XEvent map_event;
00103    ::XSetWindowAttributes w_attrib;
00104    int screen;
00105    ::XSizeHints *sizehints;
00106    ::XClassHint *classhint;
00107    unsigned long event_mask(0);    // Event masks to use
00108    bool ret_val(true);
00109 
00110    vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_STATE_LVL)
00111       << "[vrj::GlWindowXWin::open()] Open window\n" << vprDEBUG_FLUSH;
00112 
00113    if ( mWindowIsOpen )
00114    {
00115       return true;
00116    }
00117 
00118    if ( mWindowWidth == -1 )
00119    {
00120       vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00121          << clrOutNORM(clrRED,"ERROR:")
00122          << " [vrj::GlWindowXWin::open()] Window has not been configured\n"
00123          << vprDEBUG_FLUSH;
00124       return false;
00125    }
00126 
00127    if ( ! (mXDisplay = ::XOpenDisplay(mXDisplayName.c_str())) )
00128    {
00129       vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00130          << clrOutNORM(clrRED,"ERROR:")
00131          << " [vrj::GlWindowXWin::open()] Unable to open display '"
00132          << mXDisplayName << "'.\n" << vprDEBUG_FLUSH;
00133       return false;
00134    }
00135    // Try initializing the window
00136    try
00137    {
00138       screen = DefaultScreen(mXDisplay);
00139 
00140       // get an XVisualInfo*, which we'll need below
00141       if ( (mVisualInfo = getGlxVisInfo(mXDisplay, screen)) == NULL )
00142       {
00143          vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00144             << clrOutNORM(clrRED,"ERROR:") << " Failed to get a GLX visual\n"
00145             << vprDEBUG_FLUSH;
00146          throw glwinx_OpenFailureException();
00147       }
00148 
00149       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00150          << "Visual ID: 0x" << std::hex << mVisualInfo->visualid << std::dec
00151          << std::endl << vprDEBUG_FLUSH;
00152 
00153       // window attributes.
00154       w_attrib.colormap = ::XCreateColormap(mXDisplay,
00155                                             RootWindow(mXDisplay, screen),
00156                                             mVisualInfo->visual,
00157                                             AllocNone);
00158 
00159       if ( w_attrib.colormap == 0 )
00160       {
00161          vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00162             << clrOutNORM(clrRED,"ERROR:")
00163             << " vrj::GlWindowXWin: XCreateColorMap failed on '"
00164             << mXDisplayName << "'.\n" << vprDEBUG_FLUSH;
00165          throw glwinx_OpenFailureException();
00166       }
00167 
00168       event_mask = ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask |
00169                    ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
00170                    PointerMotionMask | StructureNotifyMask;
00171 //      event_mask = ExposureMask | StructureNotifyMask;   // Don't request buttons or keys since that will be handled elsewhere
00172       w_attrib.event_mask = event_mask;
00173       w_attrib.border_pixel = 0x0;
00174 
00175       // get screen dimensions for translating window origin.
00176       ::XWindowAttributes winattrs;
00177       ::XGetWindowAttributes(mXDisplay, RootWindow(mXDisplay, screen),
00178                              &winattrs);
00179 
00180       // create window
00181       mXWindow = ::XCreateWindow(mXDisplay, RootWindow(mXDisplay, screen),
00182                                  mOriginX,
00183                                  winattrs.height - mOriginY - mWindowHeight,
00184                                  mWindowWidth, mWindowHeight, 0,
00185                                  mVisualInfo->depth, InputOutput,
00186                                  mVisualInfo->visual,
00187                                  CWEventMask | CWColormap | CWBorderPixel,
00188                                  &w_attrib);
00189 
00190       if ( 0 == mXWindow )
00191       {
00192          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00193             << clrOutNORM(clrRED,"ERROR:")
00194             << "vrj::GlWindowXWin: Couldn't create window for " << mXDisplayName
00195             << std::endl << vprDEBUG_FLUSH;
00196          throw glwinx_OpenFailureException();
00197       }
00198 
00199       createEmptyCursor(mXDisplay, mXWindow);
00200       /***************** Set Window Name/Class/Size/Pos *********************/
00201 
00202       /* Before we map the window, we need a name for it (this is also useful for
00203        * the resource cruft that'll get rid of the borders).
00204        */
00205       classhint = ::XAllocClassHint();
00206       classhint->res_name = (char*)mWindowName.c_str();
00207       classhint->res_class = "VRJ GLX";
00208       //XSetClassHint(mXDisplay, mXWindow, classhint);
00209 
00210       // InSoc makes things simple
00211       // X makes things complicated
00212       ::XTextProperty w_name;
00213       ::XStringListToTextProperty(&(classhint->res_name), 1, &w_name);
00214 
00215       /* guarantee window position */
00216       sizehints = XAllocSizeHints();
00217       sizehints->flags = USPosition;
00218 
00219       ::XSetWMProperties(mXDisplay, mXWindow, &w_name, &w_name,
00220                          NULL, 0, sizehints, NULL, classhint);
00221 
00222       ::XFree(w_name.value);
00223       ::XFree(classhint);
00224       ::XFree(sizehints);
00225 
00226       /***************** Border Stuff ***************************/
00227 
00228       /* Get rid of window border, if configured to do so.
00229        * This technique doesn't require any modifications to the .XDefaults file
00230        * or anything, but it will only work with window managers based on MWM
00231        * (the Motif window manager).  That covers most cases.
00232        * Unfortunately, the generic X resources for communicating with a window
00233        * manager don't support this feature.
00234        */
00235       if ( ! mHasBorder )
00236       {
00237          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_HVERB_LVL)
00238             << "[vrj::GlWindowXWin::open()] Attempting to make window borderless"
00239             << std::endl << vprDEBUG_FLUSH;
00240          Atom MotifHints = XInternAtom(mXDisplay, "_MOTIF_WM_HINTS", 0);
00241          if ( MotifHints == None )
00242          {
00243             vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00244                << clrOutNORM(clrRED,"ERROR:")
00245                << "vrj::GlWindowXWin: Could not get X atom for _MOTIF_WM_HINTS."
00246                << std::endl << vprDEBUG_FLUSH;
00247          }
00248          else
00249          {
00250             MotifWmHints hints;
00251             hints.flags = MWM_HINTS_DECORATIONS;
00252             hints.decorations = 0;
00253             XChangeProperty(mXDisplay, mXWindow, MotifHints, MotifHints, 32,
00254                             PropModeReplace, (unsigned char *) &hints, 4);
00255          }
00256       }
00257 
00258       /********************* Mapping Window **************************/
00259 
00260       /* Open the window, select the input events, and wait until mapped (XIfEvent) */
00261       ::XSelectInput(mXDisplay, mXWindow, event_mask);
00262       ::XMapWindow(mXDisplay, mXWindow);
00263       ::XIfEvent(mXDisplay, &map_event, eventIsMapNotify, (XPointer)mXWindow);
00264       ::XSync(mXDisplay, 0);
00265 
00266       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_VERB_LVL) << "vrj::GlWindowXWin: done mapping window\n"
00267                                   << vprDEBUG_FLUSH;
00268 
00269       /********************* OpenGL Context Stuff *********************/
00270 
00271       mGlxContext = glXCreateContext(mXDisplay, mVisualInfo, NULL, True);
00272       if ( NULL == mGlxContext )
00273       {
00274          vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00275             << clrOutNORM(clrRED,"ERROR:") << "Couldn't create GlxContext for '"
00276             << mXDisplayName << "'\n" << vprDEBUG_FLUSH;
00277          throw glwinx_OpenFailureException();
00278       }
00279 
00280       mWindowIsOpen = true;
00281 
00282       if( mHideMouse )
00283       {
00284          XDefineCursor(mXDisplay, mXWindow, mEmptyCursor);
00285       }
00286 
00287       // ----------- Register this window with XEvent Device registry --------- //
00288       /*
00289       gadget::EventWindowXWin::WindowRegistry::WindowInfo xwin_info;
00290       xwin_info.displayName = mXDisplayName;
00291       xwin_info.xWindow = mXWindow;
00292       gadget::EventWindowXWin::WindowRegistry::instance()->addWindow(mVrjDisplay->getName(), xwin_info);
00293       */
00294 
00295       ret_val = true;
00296    }
00297    catch (glwinx_OpenFailureException& openFailed)
00298    {
00299       // close() is coincidentally safe to call on a partially-opened
00300       // GlWindowXWin, and will deallocate all the stuff we might have
00301       // allocated above.
00302       close();
00303 
00304       ret_val = false;
00305    }
00306 
00307    // Register extensions in this window
00308    makeCurrent();
00309    mExtensions.registerExtensions();
00310 
00311      // Check on using swap group
00312    jccl::ConfigElementPtr disp_sys_elt =
00313       DisplayManager::instance()->getDisplaySystemElement();
00314    bool use_swap_group = disp_sys_elt->getProperty<bool>("use_swap_group");
00315 
00316    if ( use_swap_group )
00317    {
00318       vprDEBUG_OutputGuard(vprDBG_ALL, vprDBG_CONFIG_STATUS_LVL,
00319                            "Attempting to set up GLX swap group.\n", "");
00320        
00321       // Try NV swap group extension
00322       if(mExtensions.hasSwapGroupNV())
00323       {
00324          vprDEBUG(vprDBG_ALL, vprDBG_CONFIG_STATUS_LVL)
00325             << "SwapGroupNV: " << mExtensions.hasSwapGroupNV() << std::endl
00326             << vprDEBUG_FLUSH;
00327          GLuint max_groups, max_barriers;
00328          mExtensions.glXQueryMaxSwapGroupsNV(mXDisplay, screen, &max_groups,
00329                                              &max_barriers);
00330          vprDEBUG(vprDBG_ALL, vprDBG_CONFIG_STATUS_LVL)
00331             << "Max groups: " << max_groups << " Max Barriers:" << max_barriers
00332             << std::endl << vprDEBUG_FLUSH;
00333 
00334          vprDEBUG(vprDBG_ALL, vprDBG_CONFIG_STATUS_LVL)
00335             << "Setting up NV swap group and barrier group. "
00336             << "Group: 1, Barrier: 1\n" << vprDEBUG_FLUSH;
00337          // For now, just assume both groups are group 1
00338          // Note: In the future this code may need to be refactored to be
00339          //   controlled from the GlPipe class since it is really the thing
00340          //   that would correspond to the group and could group the correct
00341          //   windows to a group id.
00342          mExtensions.glXJoinSwapGroupNV(mXDisplay, mXWindow, 1);
00343          mExtensions.glXBindSwapBarrierNV(mXDisplay, 1, 1);
00344       }
00345       else
00346       {
00347          vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL)
00348             << "Could not detect any GLX extensions that support swap groups.\n"
00349             << vprDEBUG_FLUSH;
00350          vprDEBUG_NEXT(vprDBG_ALL, vprDBG_WARNING_LVL)
00351             << "Proceeding with no swap locking.\n" << vprDEBUG_FLUSH;
00352       }
00353    }
00354 
00355    return ret_val;
00356 }

bool vrj::GlWindowXWin::close (  )  [virtual]

Closes the window given.

Note:
this function mucks with the current rendering context

Reimplemented from vrj::GlWindow.

Definition at line 362 of file GlWindowXWin.cpp.

References makeCurrent(), vrj::GlWindow::mIsEventSource, and vrj::GlWindow::mWindowIsOpen.

Referenced by open(), and ~GlWindowXWin().

00363 {
00364 
00365    //vprASSERT( !mXfuncLock.test() && "Attempting to close a display window that is locked" );
00366    // Assert that we have not impllemented correct shutdown for the case that we
00367    // are an event source as well
00368    //vprASSERT(!mIsEventSource  && "Need to implement GLX window close with gadget::EventWindow");
00369 
00370    // Remove any event device from the input manager
00371    if ( true == mIsEventSource )
00372    {
00373       gadget::Input* dev_ptr = dynamic_cast<gadget::Input*>(this);
00374 
00375       // XXX: Possibly not the best way to remove this to input manager
00376       // - This will internally call stop sampling (and stupify and proxies)
00377       //   Note: The stop sampling will not do anything since the event window does not own the window
00378       vrj::Kernel::instance()->getInputManager()->removeDevice(dev_ptr);
00379    }
00380 
00381    if ( mGlxContext )
00382    {
00383       makeCurrent();    // Might not need this
00384       //glFlush();      // This is done by the changing context
00385       glXMakeCurrent(mXDisplay, None, NULL);     // Release the context, and don't assign a new one
00386       glXDestroyContext(mXDisplay, mGlxContext);
00387       mGlxContext = NULL;
00388    }
00389    if ( mXWindow )
00390    {
00391       ::XDestroyWindow(mXDisplay, mXWindow);
00392       mXWindow = 0;
00393    }
00394    if ( mVisualInfo )
00395    {
00396       ::XFree(mVisualInfo);
00397       mVisualInfo = NULL;
00398    }
00399    if ( mXDisplay )
00400    {
00401       ::XCloseDisplay(mXDisplay);
00402       mXDisplay = NULL;
00403    }
00404 
00405    mWindowIsOpen = false;    // We are closed now
00406 
00407    return true;
00408 
00409 } /* close() */

bool vrj::GlWindowXWin::makeCurrent (  )  [virtual]

Sets the current OpenGL context to this window.

Postcondition:
this.context is active context.

Reimplemented from vrj::GlWindow.

Definition at line 417 of file GlWindowXWin.cpp.

References vrj::GlWindow::mWindowIsOpen.

Referenced by close(), and open().

00418 {
00419    /* returns true for success,
00420     * false for failure (eg window not open or glXMakeCurrent fails)
00421     */
00422    if ( !mWindowIsOpen )
00423    {
00424       return false;
00425    }
00426 
00427    vprASSERT(mGlxContext != NULL);
00428    vprASSERT(mXWindow != 0);
00429    vprASSERT(mXDisplay != NULL);
00430 
00431    return glXMakeCurrent(mXDisplay, mXWindow, mGlxContext);
00432 }

void vrj::GlWindowXWin::checkEvents (  )  [virtual]

Checks events.

Processes window systems events each frame.

Reimplemented from vrj::GlWindow.

Definition at line 469 of file GlWindowXWin.cpp.

References vrj::GlWindow::mOriginX, vrj::GlWindow::mOriginY, vrj::GlWindow::setDirtyViewport(), and vrj::GlWindow::updateOriginSize().

00470 {
00471    // XXX: Move this all down sooner or later.
00472    if (NULL != mKeyboardMouseDevice)
00473    {
00474       handleEvents();
00475    }
00476    else
00477    {
00478       XEvent event;
00479 
00480       while( XPending(mXDisplay))
00481       {
00482          XNextEvent(mXDisplay,&event);
00483 
00484          switch ( event.type )
00485          {
00486             case ConfigureNotify:
00487                updateOriginSize(vrj::GlWindow::mOriginX, vrj::GlWindow::mOriginY,
00488                                 event.xconfigure.width, event.xconfigure.height);
00489                vrj::GlWindow::setDirtyViewport(true);
00490                break;
00491 
00492             default:
00493                break;
00494          }
00495       }
00496    }
00497 }

void vrj::GlWindowXWin::configWindow ( vrj::Display disp  )  [virtual]

Configure the window settings based on the display information.

Reimplemented from vrj::GlWindow.

Definition at line 434 of file GlWindowXWin.cpp.

References vrj::GlWindow::configWindow(), vrj::Display::getConfigElement(), vrj::Display::getName(), vrj::Display::getPipe(), and vrjDBG_DRAW_MGR().

00435 {
00436    const char neg_one_string[] = "-1";
00437    vrj::GlWindow::configWindow(disp);
00438 
00439    // Get the vector of display elements.
00440    jccl::ConfigElementPtr disp_sys_elt = DisplayManager::instance()->getDisplaySystemElement();
00441    jccl::ConfigElementPtr display_elt = disp->getConfigElement();
00442 
00443    // Get the lock and KeyboardMouseDevice information
00444    gadget::InputArea::config(display_elt);
00445    
00446    mWindowName = disp->getName();
00447    mPipe = disp->getPipe();
00448    vprASSERT(mPipe >= 0);
00449 
00450    // NOTE: ConfigElements return the default value for a property if a value is
00451    //       not present. So if a pipe string is not specified for this pipe then
00452    //       it gets the default value of "-1".
00453    mXDisplayName = disp_sys_elt->getProperty<std::string>("x11_pipes", mPipe);
00454 
00455    if ( mXDisplayName == neg_one_string )    // Use display env
00456    {
00457       const std::string DISPLAY_str("DISPLAY");    // DISPLAY_str[] = "DISPLAY";
00458       const char* d = getenv(DISPLAY_str.c_str());
00459       if ( NULL != d )
00460       {
00461          mXDisplayName = std::string( d );
00462       }
00463    }
00464    vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_VERB_LVL)
00465       << "[vrj::GlWindowXWin::config] Display name is '" << mXDisplayName
00466       << "'" << std::endl << vprDEBUG_FLUSH;
00467 }

virtual void vrj::GlWindowXWin::processEvent ( ::XEvent  event  )  [inline, protected, virtual]

Do any extra event processing needed.

Definition at line 96 of file GlWindowXWin.h.

References vrj::GlWindow::mOriginX, vrj::GlWindow::mOriginY, vrj::GlWindow::setDirtyViewport(), and vrj::GlWindow::updateOriginSize().

00097    {
00098       switch ( event.type )
00099       {
00100          case ConfigureNotify:
00101             updateOriginSize(vrj::GlWindow::mOriginX, vrj::GlWindow::mOriginY,
00102                              event.xconfigure.width, event.xconfigure.height);
00103             vrj::GlWindow::setDirtyViewport(true);
00104             break;
00105 
00106          default:
00107             break;
00108       }
00109    }

XVisualInfo * vrj::GlWindowXWin::getGlxVisInfo ( ::Display display,
int  screen 
) [protected]

Definition at line 502 of file GlWindowXWin.cpp.

References vrj::Display::getGlFrameBufferConfig(), vrj::Display::getName(), vrj::Display::isStereoRequested(), vrj::GlWindow::mInStereo, vrj::GlWindow::mVrjDisplay, and vrjDBG_DRAW_MGR().

Referenced by open().

00503 {
00504    /* pre:  screen is a screen on the current XDisplay, and
00505     *       XDisplay is already defined and valid.
00506     * post: returns a pointer to an XVisualInfo to be used for GLX.
00507     *       Note that it doesn't necessarily have _all_ of the requested
00508     *       features... it will attempt to get a visual in mono or
00509     *       without alpha if it's virst attempts fail.
00510     *       Returns NULL if it can't come up with a reasonably close
00511     *       XVisualInfo, or if the display in question doesn't support
00512     *       GLX
00513     */
00514 
00515    if ( !glXQueryExtension(display, NULL, NULL) )
00516    {
00517       vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00518          << clrOutNORM(clrRED, "ERROR:") << " X Display '" << mXDisplayName
00519          << "' doesn't support GLX.\n" << vprDEBUG_FLUSH;
00520       return NULL;
00521    }
00522 
00523    // Using 1 here requests the *largest* available size for each of these
00524    // buffers.  Refer to the glXChooseVisual() manual page for more details.
00525    int visual_id(-1);
00526    int red_size(1), green_size(1), blue_size(1), alpha_size(1), db_size(1),
00527        accum_red_size(1), accum_green_size(1), accum_blue_size(1),
00528        accum_alpha_size(1), stencil_size(1);
00529    // glXChooseVisual() will return the visual with the smallest number of
00530    // auxiliary buffers that meets or exceeds the requested count.
00531    int num_aux_bufs(0);
00532    bool want_fsaa(false);
00533 
00534    jccl::ConfigElementPtr gl_fb_elt = mVrjDisplay->getGlFrameBufferConfig();
00535 
00536    if ( gl_fb_elt.get() != NULL )
00537    {
00538       if ( gl_fb_elt->getVersion() < 2 )
00539       {
00540          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00541             << clrOutBOLD(clrYELLOW, "WARNING:") << " Display window '"
00542             << mVrjDisplay->getName() << "'" << std::endl;
00543          vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00544             << "has an out of date OpenGL frame buffer configuration."
00545             << std::endl;
00546          vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00547             << "Expected version 2 but found version "
00548             << gl_fb_elt->getVersion() << ".\n";
00549          vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00550             << "Default values will be used for some frame buffer settings.\n"
00551             << vprDEBUG_FLUSH;
00552       }
00553 
00554       visual_id        = gl_fb_elt->getProperty<int>("visual_id");
00555       red_size         = gl_fb_elt->getProperty<int>("red_size");
00556       green_size       = gl_fb_elt->getProperty<int>("green_size");
00557       blue_size        = gl_fb_elt->getProperty<int>("blue_size");
00558       alpha_size       = gl_fb_elt->getProperty<int>("alpha_size");
00559       num_aux_bufs     = gl_fb_elt->getProperty<int>("auxiliary_buffer_count");
00560       db_size          = gl_fb_elt->getProperty<int>("depth_buffer_size");
00561       stencil_size     = gl_fb_elt->getProperty<int>("stencil_buffer_size");
00562       accum_red_size   = gl_fb_elt->getProperty<int>("accum_red_size");
00563       accum_green_size = gl_fb_elt->getProperty<int>("accum_green_size");
00564       accum_blue_size  = gl_fb_elt->getProperty<int>("accum_blue_size");
00565       accum_alpha_size = gl_fb_elt->getProperty<int>("accum_alpha_size");
00566       want_fsaa        = gl_fb_elt->getProperty<bool>("fsaa_enable");
00567    }
00568 
00569    if ( visual_id != -1 )
00570    {
00571       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00572          << "Requesting visual 0x" << std::hex << visual_id << std::dec
00573          << " from GLX." << std::endl << vprDEBUG_FLUSH;
00574 
00575       XVisualInfo vinfo_template;
00576       long mask(VisualIDMask);
00577       int nitems;
00578 
00579       vinfo_template.visualid = visual_id;
00580 
00581       XVisualInfo* vi = XGetVisualInfo(display, mask, &vinfo_template, &nitems);
00582 
00583       // If we got a valid visual using the requested ID, test to see if it
00584       // supports stereo.  this->mInStereo needs to be set correctly based on
00585       // what is requested of the display window by the configuration and based
00586       // on what our chosen visual actually supports.
00587       if ( NULL != vi )
00588       {
00589          int has_stereo;
00590 
00591          if ( glXGetConfig(display, vi, GLX_STEREO, &has_stereo) == 0 )
00592          {
00593             mInStereo = (mVrjDisplay->isStereoRequested() &&
00594                          has_stereo == True);
00595          }
00596       }
00597       // If XGetVisualInfo(3) returned NULL, print an error message.
00598       else
00599       {
00600          vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00601             << clrOutBOLD(clrRED, "ERROR:")
00602             << " Failed to get X11 visual info for visual ID 0x"
00603             << std::hex << visual_id << std::dec << std::endl
00604             << vprDEBUG_FLUSH;
00605          vprDEBUG_NEXT(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00606             << "Window '" << mVrjDisplay->getName() << "' cannot be opened"
00607             << std::endl << vprDEBUG_FLUSH;
00608       }
00609 
00610       return vi;
00611    }
00612    else
00613    {
00614       if ( red_size < 0 )
00615       {
00616          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00617             << clrOutBOLD(clrYELLOW, "WARNING:")
00618             << " Color buffer red channel size was negative ("
00619             << red_size << ").  Setting to 1.\n" << vprDEBUG_FLUSH;
00620          red_size = 1;
00621       }
00622 
00623       if ( green_size < 0 )
00624       {
00625          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00626             << clrOutBOLD(clrYELLOW, "WARNING:")
00627             << " Color buffer green channel size was negative ("
00628             << green_size << ").  Setting to 1.\n" << vprDEBUG_FLUSH;
00629          green_size = 1;
00630       }
00631 
00632       if ( blue_size < 0 )
00633       {
00634          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00635             << clrOutBOLD(clrYELLOW, "WARNING:")
00636             << " Color buffer blue channel size was negative ("
00637             << blue_size << ").  Setting to 1.\n" << vprDEBUG_FLUSH;
00638          blue_size = 1;
00639       }
00640 
00641       if ( alpha_size < 0 )
00642       {
00643          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00644             << clrOutBOLD(clrYELLOW, "WARNING:")
00645             << " Color buffer alpha channel size was negative ("
00646             << alpha_size << ").  Setting to 1.\n" << vprDEBUG_FLUSH;
00647          alpha_size = 1;
00648       }
00649 
00650       if ( num_aux_bufs < 0 )
00651       {
00652          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00653             << clrOutBOLD(clrYELLOW, "WARNING:")
00654             << " Auxiliary buffer count was negative (" << num_aux_bufs
00655             << ").  Setting to 0.\n" << vprDEBUG_FLUSH;
00656          num_aux_bufs = 0;
00657       }
00658 
00659       if ( db_size < 0 )
00660       {
00661          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00662             << clrOutBOLD(clrYELLOW, "WARNING:")
00663             << " Depth buffer size was negative (" << db_size
00664             << ").  Setting to 1.\n" << vprDEBUG_FLUSH;
00665          db_size = 1;
00666       }
00667 
00668       if ( stencil_size < 0 )
00669       {
00670          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00671             << clrOutBOLD(clrYELLOW, "WARNING:")
00672             << " Stencil buffer size was negative (" << stencil_size
00673             << ").  Setting to 1.\n" << vprDEBUG_FLUSH;
00674          stencil_size = 1;
00675       }
00676 
00677       if ( accum_red_size < 0 )
00678       {
00679          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00680             << clrOutBOLD(clrYELLOW, "WARNING:")
00681             << " Accumulation buffer red channel size was negative ("
00682             << accum_red_size << ").  Setting to 1.\n" << vprDEBUG_FLUSH;
00683          accum_red_size = 1;
00684       }
00685 
00686       if ( accum_green_size < 0 )
00687       {
00688          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00689             << clrOutBOLD(clrYELLOW, "WARNING:")
00690             << " Accumulation buffer green channel size was negative ("
00691             << accum_green_size << ").  Setting to 1.\n" << vprDEBUG_FLUSH;
00692          accum_green_size = 1;
00693       }
00694 
00695       if ( accum_blue_size < 0 )
00696       {
00697          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00698             << clrOutBOLD(clrYELLOW, "WARNING:")
00699             << " Accumulation buffer blue channel size was negative ("
00700             << accum_blue_size << ").  Setting to 1.\n" << vprDEBUG_FLUSH;
00701          accum_blue_size = 1;
00702       }
00703 
00704       if ( accum_alpha_size < 0 )
00705       {
00706          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00707             << clrOutBOLD(clrYELLOW, "WARNING:")
00708             << " Accumulation buffer alpha channel size was negative ("
00709             << accum_alpha_size << ").  Setting to 1.\n" << vprDEBUG_FLUSH;
00710          accum_alpha_size = 1;
00711       }
00712 
00713       const unsigned int indent_level(2);
00714       const std::string indent_text(indent_level, ' ');
00715       const int pad_width_dot(40 - indent_level);
00716       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00717          << "OpenGL visual request settings for " << mVrjDisplay->getName()
00718          << ":\n";
00719       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00720          << std::setiosflags(std::ios::left) << std::setfill('.')
00721          << indent_text << std::setw(pad_width_dot)
00722          << "Color buffer red size " << " " << red_size << std::endl;
00723       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00724          << std::setiosflags(std::ios::left) << std::setfill('.')
00725          << indent_text << std::setw(pad_width_dot)
00726          << "Color buffer green size " << " " << green_size << std::endl;
00727       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00728          << std::setiosflags(std::ios::left) << std::setfill('.')
00729          << indent_text << std::setw(pad_width_dot)
00730          << "Color buffer blue size " << " " << blue_size << std::endl;
00731       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00732          << std::setiosflags(std::ios::left) << std::setfill('.')
00733          << indent_text << std::setw(pad_width_dot)
00734          << "Color buffer alpha size " << " " << alpha_size << std::endl;
00735       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00736          << std::setiosflags(std::ios::left) << std::setfill('.')
00737          << indent_text << std::setw(pad_width_dot)
00738          << "Auxiliary buffer count " << " " << num_aux_bufs << std::endl;
00739       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00740          << std::setiosflags(std::ios::left) << std::setfill('.')
00741          << indent_text << std::setw(pad_width_dot)
00742          << "Depth buffer size " << " " << db_size << std::endl;
00743       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00744          << std::setiosflags(std::ios::left) << std::setfill('.')
00745          << indent_text << std::setw(pad_width_dot)
00746          << "Stencil buffer size " << " " << stencil_size << std::endl;
00747       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00748          << std::setiosflags(std::ios::left) << std::setfill('.')
00749          << indent_text << std::setw(pad_width_dot)
00750          << "Accumulation buffer red size " << " " << accum_red_size
00751          << std::endl;
00752       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00753          << std::setiosflags(std::ios::left) << std::setfill('.')
00754          << indent_text << std::setw(pad_width_dot)
00755          << "Accumulation buffer green size " << " " << accum_green_size
00756          << std::endl;
00757       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00758          << std::setiosflags(std::ios::left) << std::setfill('.')
00759          << indent_text << std::setw(pad_width_dot)
00760          << "Accumulation buffer blue size " << " " << accum_blue_size
00761          << std::endl;
00762       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00763          << std::setiosflags(std::ios::left) << std::setfill('.')
00764          << indent_text << std::setw(pad_width_dot)
00765          << "Accumulation buffer alpha size " << " " << accum_alpha_size
00766          << std::endl;
00767       vprDEBUG_CONTnl(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00768          << vprDEBUG_FLUSH;
00769 
00770       // Notes on viattrib:  by using 1 for GLX_RED_SIZE et.al. we ask
00771       // for the _largest_ available buffers.  If this fails,  we might
00772       // want to try setting alpha size to 0 (smallest possible, maybe 0)
00773       // which is required eg. for alpha on the indys.
00774       std::vector<int> viattrib;
00775       viattrib.push_back(GLX_DOUBLEBUFFER);
00776       viattrib.push_back(GLX_RGBA);
00777       viattrib.push_back(GLX_DEPTH_SIZE); viattrib.push_back(db_size);
00778       viattrib.push_back(GLX_RED_SIZE); viattrib.push_back(red_size);
00779       viattrib.push_back(GLX_GREEN_SIZE); viattrib.push_back(green_size);
00780       viattrib.push_back(GLX_BLUE_SIZE); viattrib.push_back(blue_size);
00781 
00782       // Record the index for the alpha attribute using the current size of the
00783       // vector *before* the attribute is actually added.
00784       const unsigned int alpha_attrib_index = viattrib.size();
00785       viattrib.push_back(GLX_ALPHA_SIZE); viattrib.push_back(alpha_size);
00786 
00787       viattrib.push_back(GLX_AUX_BUFFERS); viattrib.push_back(num_aux_bufs);
00788       viattrib.push_back(GLX_STENCIL_SIZE); viattrib.push_back(stencil_size);
00789 
00790       const unsigned int accum_red_attrib_index = viattrib.size();
00791       viattrib.push_back(GLX_ACCUM_RED_SIZE);
00792       viattrib.push_back(accum_red_size);
00793 
00794       const unsigned int accum_green_attrib_index = viattrib.size();
00795       viattrib.push_back(GLX_ACCUM_GREEN_SIZE);
00796       viattrib.push_back(accum_green_size);
00797 
00798       const unsigned int accum_blue_attrib_index = viattrib.size();
00799       viattrib.push_back(GLX_ACCUM_BLUE_SIZE);
00800       viattrib.push_back(accum_blue_size);
00801 
00802       const unsigned int accum_alpha_attrib_index = viattrib.size();
00803       viattrib.push_back(GLX_ACCUM_ALPHA_SIZE);
00804       viattrib.push_back(accum_alpha_size);
00805 
00806       // Enable full-screen anti-aliasing if it is available and it was
00807       // requested.
00808 #ifdef GLX_SAMPLES_SGIS
00809       // Save the current attribute vector size so we can try disabling FSAA if
00810       // necessary.
00811       const unsigned int fsaa_attrib_index = viattrib.size();
00812 
00813       if ( want_fsaa )
00814       {
00815          viattrib.push_back(GLX_SAMPLES_SGIS); viattrib.push_back(1);
00816          viattrib.push_back(GLX_SAMPLE_BUFFERS_SGIS); viattrib.push_back(1);
00817       }
00818 #else
00819       if ( want_fsaa )
00820       {
00821          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00822             << "WARNING: Full-screen anti-aliasing is not available\n"
00823             << vprDEBUG_FLUSH;
00824       }
00825 #endif
00826 
00827       // Record the index for the stereo attribute using the current size of
00828       // the vector *before* the attribute is actually added.  If stereo is
00829       // not added, this variable will just be ignored.
00830       const unsigned int stereo_attrib_index = viattrib.size();
00831 
00832       if ( mVrjDisplay->isStereoRequested() )
00833       {
00834          viattrib.push_back(GLX_STEREO);
00835          mInStereo = true;
00836       }
00837       else
00838       {
00839          mInStereo = false;
00840       }
00841 
00842       // Add terminator
00843       viattrib.push_back(None);
00844 
00845       XVisualInfo* vi(NULL);
00846 
00847       // First, see if we can get exactly what we want.
00848       if ( (vi = glXChooseVisual(display, screen, &viattrib[0])) != NULL )
00849       {
00850          return vi;
00851       }
00852 
00853       // If we have reached this point, our first attempt to get a visual
00854       // failed.  If stereo is enabled, we try disabling it and requesting
00855       // another visual.
00856       if ( mVrjDisplay->isStereoRequested() )
00857       {
00858          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00859             << "WARNING: Could not get an OpenGL visual for '" << mXDisplayName
00860             << "'\n";
00861          vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00862             << "with stereo rendering enabled; trying without.\n"
00863             << vprDEBUG_FLUSH;
00864          mInStereo = false;
00865 
00866          // GLX_USE_GL will be ignored by glXChooseVisual(3).
00867          viattrib[stereo_attrib_index] = GLX_USE_GL;
00868 
00869          if ( (vi = glXChooseVisual(display, screen, &viattrib[0])) != NULL )
00870          {
00871             return vi;
00872          }
00873 
00874          // Stereo must not have been the problem, re-enable it.
00875          viattrib[stereo_attrib_index] = GLX_STEREO;
00876       }
00877 
00878       // If we reached this point, we still do not have a usable GLX visual.
00879       // Disabling the accumulation buffer settings may give us something
00880       // usable.
00881       if ( accum_red_size > 0 || accum_green_size > 0 ||
00882            accum_blue_size > 0 || accum_alpha_size > 0 )
00883       {
00884          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00885             << "WARNING: Could not get an OpenGL visual for '" << mXDisplayName
00886             << "'\n";
00887          vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00888             << "with accumulation buffer settings; trying without.\n"
00889             << vprDEBUG_FLUSH;
00890 
00891          viattrib[accum_red_attrib_index + 1]   = 0;
00892          viattrib[accum_blue_attrib_index + 1]  = 0;
00893          viattrib[accum_green_attrib_index + 1] = 0;
00894          viattrib[accum_alpha_attrib_index + 1] = 0;
00895 
00896          // XXX: If this fails, should we restore the accumulation buffer
00897          // settings?
00898          if ( (vi = glXChooseVisual(display, screen, &viattrib[0])) != NULL )
00899          {
00900             return vi;
00901          }
00902       }
00903 
00904       // If we reached this point, we still do not have a usable GLX visual.
00905       // Disabling the alpha channel may give us something usable.
00906       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00907          << "WARNING: Could not get an OpenGL visual for '" << mXDisplayName
00908          << "'\n";
00909       vprDEBUG_NEXTnl(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00910          << "with a color buffer alpha channel; trying without.\n"
00911          << vprDEBUG_FLUSH;
00912 
00913       // There are two values in viattrib related to the alpha channel.
00914       viattrib[alpha_attrib_index    ] = GLX_USE_GL;
00915       viattrib[alpha_attrib_index + 1] = GLX_USE_GL;
00916 
00917       if ( (vi = glXChooseVisual(display, screen, &viattrib[0])) != NULL )
00918       {
00919          return vi;
00920       }
00921 
00922 #ifdef GLX_SAMPLES_SGIS
00923       // Last-ditch effort: try disabling FSAA if it was enabled.
00924       // XXX: It might be better to try disabling FSAA *first* instead of last.
00925       if ( want_fsaa )
00926       {
00927          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CRITICAL_LVL)
00928             << "WARNING: Display process for '" << mXDisplayName
00929             << "' couldn't get FSAA - trying without it.\n" << vprDEBUG_FLUSH;
00930 
00931          // There are four values in viattrib related to FSAA.
00932          viattrib[fsaa_attrib_index    ] = GLX_USE_GL;
00933          viattrib[fsaa_attrib_index + 1] = GLX_USE_GL;
00934          viattrib[fsaa_attrib_index + 2] = GLX_USE_GL;
00935          viattrib[fsaa_attrib_index + 3] = GLX_USE_GL;
00936 
00937          if ( (vi = glXChooseVisual(display, screen, &viattrib[0])) != NULL )
00938          {
00939             return vi;
00940          }
00941       }
00942 #endif
00943    }
00944 
00945    // Failed, so return NULL
00946    return NULL;
00947 }

int vrj::GlWindowXWin::eventIsMapNotify ( ::Display display,
XEvent *  e,
XPointer  window 
) [static, protected]

Precondition:
window is an xwindow under display.

Postcondition:
Returns true if e is a mapnotify event for window, else false.
Note:
This is a utility function for open(). It is used to wait until a window has actually been mapped.

Definition at line 955 of file GlWindowXWin.cpp.

Referenced by open().

00957 {
00958    boost::ignore_unused_variable_warning(display);
00959    return((e->type == MapNotify) && (e->xmap.window == (Window)window));
00960 }

void vrj::GlWindowXWin::createEmptyCursor ( ::Display display,
::Window  root 
) [protected]

Definition at line 962 of file GlWindowXWin.cpp.

Referenced by open().

00963 {
00964    Pixmap cursormask;
00965    XGCValues xgc;
00966    GC gc;
00967    XColor dummycolour;
00968 
00969    cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
00970    xgc.function = GXclear;
00971    gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
00972    XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
00973    dummycolour.pixel = 0;
00974    dummycolour.red = 0;
00975    dummycolour.flags = 04;
00976    mEmptyCursor = XCreatePixmapCursor(display, cursormask, cursormask,
00977                                       &dummycolour,&dummycolour, 0,0);
00978    XFreePixmap(display,cursormask);
00979    XFreeGC(display,gc);
00980 
00981    mEmptyCursorSet = true;
00982 }


The documentation for this class was generated from the following files:
Generated on Thu Jan 4 10:58:22 2007 for VR Juggler by  doxygen 1.5.1