wglWindow.cpp

00001 
00002 /* Copyright (c) 2005-2009, Stefan Eilemann <eile@equalizergraphics.com>
00003                           , Makhinya Maxim
00004  *
00005  * This library is free software; you can redistribute it and/or modify it under
00006  * the terms of the GNU Lesser General Public License version 2.1 as published
00007  * by the Free Software Foundation.
00008  *  
00009  * This library is distributed in the hope that it will be useful, but WITHOUT
00010  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00012  * details.
00013  * 
00014  * You should have received a copy of the GNU Lesser General Public License
00015  * along with this library; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017  */
00018 
00019 #include "wglWindow.h"
00020 
00021 #include "global.h"
00022 #include "pipe.h"
00023 #include "wglEventHandler.h"
00024 #include "wglPipe.h"
00025 
00026 #include <eq/base/log.h>
00027 
00028 using namespace std;
00029 
00030 namespace eq
00031 {
00032 
00033 WGLWindow::WGLWindow( Window* parent )
00034     : WGLWindowIF( parent )
00035     , _wglWindow( 0 )
00036     , _wglPBuffer( 0 )
00037     , _wglContext( 0 )
00038     , _wglDC( 0 )
00039     , _wglDCType( WGL_DC_NONE )
00040     , _wglAffinityDC( 0 )
00041     , _wglEventHandler( 0 )
00042     , _wglNVSwapGroup( 0 )
00043 {
00044     
00045 }
00046 
00047 WGLWindow::~WGLWindow( )
00048 {
00049     
00050 }
00051 
00052 void WGLWindow::configExit( )
00053 {
00054     leaveNVSwapBarrier();
00055     configExitFBO();
00056     exitGLEW();
00057     
00058     wglMakeCurrent( 0, 0 );
00059 
00060     HGLRC context        = getWGLContext();
00061     HWND  hWnd           = getWGLWindowHandle();
00062     HPBUFFERARB hPBuffer = getWGLPBufferHandle();
00063 
00064     exitWGLAffinityDC();
00065     setWGLDC( 0, WGL_DC_NONE );
00066     setWGLContext( 0 );
00067     setWGLWindowHandle( 0 );
00068     setWGLPBufferHandle( 0 );
00069 
00070     if( context )
00071         wglDeleteContext( context );
00072 
00073     if( hWnd )
00074     {
00075         // Re-enable screen saver
00076         if( getIAttribute( Window::IATTR_HINT_SCREENSAVER ) != ON )
00077             SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, _screenSaverActive, 
00078                                   0, 0 );
00079         
00080         char className[256] = {0};
00081         GetClassName( hWnd, className, 255 );
00082         DestroyWindow( hWnd );
00083 
00084         if( strlen( className ) > 0 )
00085             UnregisterClass( className, GetModuleHandle( 0 ));
00086     }
00087     if( hPBuffer )
00088         wglDestroyPbufferARB( hPBuffer );
00089 
00090     if( getIAttribute( Window::IATTR_HINT_FULLSCREEN ) == ON )
00091         ChangeDisplaySettings( 0, 0 );
00092 
00093     EQINFO << "Destroyed WGL context and window" << std::endl;
00094 }
00095 
00096 void WGLWindow::makeCurrent() const
00097 {
00098     EQCHECK( wglMakeCurrent( _wglDC, _wglContext ));
00099     WGLWindowIF::makeCurrent();
00100 }
00101 
00102 void WGLWindow::swapBuffers()
00103 {
00104     ::SwapBuffers( _wglDC );
00105 }
00106 
00107 void WGLWindow::setWGLContext( HGLRC context )
00108 {
00109     _wglContext = context; 
00110 }
00111 
00112 void WGLWindow::setWGLWindowHandle( HWND handle )
00113 {
00114     if( _wglWindow == handle )
00115         return;
00116 
00117     if( _wglWindow )
00118         exitEventHandler();
00119 
00120     if( !handle )
00121     {
00122         setWGLDC( 0, WGL_DC_NONE );
00123         _wglWindow = 0;
00124         return;
00125     }
00126 
00127     _wglWindow = handle;
00128     setWGLDC( GetDC( handle ), WGL_DC_WINDOW );
00129 
00130     initEventHandler();
00131 
00132     // query pixel viewport of window
00133     WINDOWINFO windowInfo;
00134     windowInfo.cbSize = sizeof( windowInfo );
00135 
00136     GetWindowInfo( handle, &windowInfo );
00137 
00138     PixelViewport pvp;
00139     pvp.x = windowInfo.rcClient.left;
00140     pvp.y = windowInfo.rcClient.top;
00141     pvp.w = windowInfo.rcClient.right  - windowInfo.rcClient.left;
00142     pvp.h = windowInfo.rcClient.bottom - windowInfo.rcClient.top;
00143     _window->setPixelViewport( pvp );
00144 }
00145 
00146 void WGLWindow::setWGLPBufferHandle( HPBUFFERARB handle )
00147 {
00148     if( _wglPBuffer == handle )
00149         return;
00150 
00151     if( !handle )
00152     {
00153         setWGLDC( 0, WGL_DC_NONE );
00154         _wglPBuffer = 0;
00155         return;
00156     }
00157 
00158     _wglPBuffer = handle;
00159     setWGLDC( wglGetPbufferDCARB( handle ), WGL_DC_PBUFFER );
00160 
00161     // query pixel viewport of PBuffer
00162     int w,h;
00163     wglQueryPbufferARB( handle, WGL_PBUFFER_WIDTH_ARB, &w );
00164     wglQueryPbufferARB( handle, WGL_PBUFFER_HEIGHT_ARB, &h );
00165 
00166     PixelViewport pvp;
00167     pvp.w = w;
00168     pvp.h = h;
00169     _window->setPixelViewport( pvp );
00170 }
00171 
00172 void WGLWindow::setWGLDC( HDC dc, const WGLDCType type )
00173 {
00174     if( ( type != WGL_DC_NONE && dc == 0 ) ||
00175         ( type == WGL_DC_NONE && dc != 0 ))
00176     {
00177         EQABORT( "Illegal combination of WGL device context and type" );
00178         return;
00179     }
00180 
00181     switch( _wglDCType )
00182     {
00183         case WGL_DC_NONE:
00184             break;
00185 
00186         case WGL_DC_WINDOW:
00187             EQASSERT( _wglWindow );
00188             EQASSERT( _wglDC );
00189             ReleaseDC( _wglWindow, _wglDC );
00190             break;
00191             
00192         case WGL_DC_PBUFFER:
00193             EQASSERT( _wglPBuffer );
00194             EQASSERT( _wglDC );
00195             wglReleasePbufferDCARB( _wglPBuffer, _wglDC );
00196             break;
00197 
00198         case WGL_DC_AFFINITY:
00199             EQASSERT( _wglDC );
00200             wglDeleteDCNV( _wglDC );
00201             break;
00202                 
00203         case WGL_DC_DISPLAY:
00204             EQASSERT( _wglDC );
00205             DeleteDC( _wglDC );
00206             break;
00207 
00208         default:
00209             EQUNIMPLEMENTED;
00210     }
00211 
00212     _wglDC     = dc;
00213     _wglDCType = type;
00214 }
00215 
00216 //---------------------------------------------------------------------------
00217 // WGL init
00218 //---------------------------------------------------------------------------
00219 bool WGLWindow::configInit()
00220 {
00221     if( !initWGLAffinityDC( ))
00222     {
00223         _window->setErrorMessage( "Can't create affinity dc" );
00224         return false;
00225     }
00226 
00227     int pixelFormat = chooseWGLPixelFormat();
00228     if( pixelFormat == 0 )
00229     {
00230         exitWGLAffinityDC();
00231         return false;
00232     }
00233 
00234     if( !configInitWGLDrawable( pixelFormat ))
00235     {
00236         exitWGLAffinityDC();
00237         return false;
00238     }
00239 
00240     if( !_wglDC )
00241     {
00242         exitWGLAffinityDC();
00243         setWGLDC( 0, WGL_DC_NONE );
00244         _window->setErrorMessage(
00245             "configInitWGLDrawable did not set a WGL drawable" );
00246         return false;
00247     }
00248 
00249     HGLRC context = createWGLContext();
00250     if( !context )
00251     {
00252         configExit();
00253         return false;
00254     }
00255 
00256     setWGLContext( context );
00257     makeCurrent();
00258     initGLEW();
00259 
00260     if( getIAttribute( Window::IATTR_HINT_SWAPSYNC ) != AUTO )
00261     {
00262         if( WGLEW_EXT_swap_control )
00263         {
00264             // set vsync on/off
00265             const GLint vsync = 
00266                 ( getIAttribute( Window::IATTR_HINT_SWAPSYNC )==OFF ) ? 0 : 1;
00267             wglSwapIntervalEXT( vsync );
00268         }
00269         else
00270             EQWARN << "WGLEW_EXT_swap_control not supported, ignoring window "
00271                    << "swapsync hint" << std::endl;
00272     }
00273     
00274     if( getIAttribute( Window::IATTR_HINT_DRAWABLE ) == FBO )
00275         return configInitFBO();
00276 
00277     return true;
00278 }
00279 
00280 bool WGLWindow::configInitWGLDrawable( int pixelFormat )
00281 {
00282     switch( getIAttribute( Window::IATTR_HINT_DRAWABLE ))
00283     {
00284         case PBUFFER:
00285             return configInitWGLPBuffer( pixelFormat );
00286 
00287         case FBO:
00288             return configInitWGLFBO( pixelFormat );
00289 
00290         default:
00291             EQWARN << "Unknown drawable type "
00292                    << getIAttribute(Window::IATTR_HINT_DRAWABLE )
00293                    << ", creating a window" << std::endl;
00294             // no break;
00295         case UNDEFINED:
00296         case WINDOW:
00297             return configInitWGLWindow( pixelFormat );
00298     }
00299 }
00300 
00301 bool WGLWindow::configInitWGLFBO( int pixelFormat )
00302 {
00303     if( _wglAffinityDC )
00304     {
00305         // move affinity DC to be our main DC
00306         // deletion is now taken care of by setWGLDC( 0 )
00307         setWGLDC( _wglAffinityDC, WGL_DC_AFFINITY );
00308         _wglAffinityDC = 0;
00309     }
00310     else // no affinity, use DC of nth device
00311     {
00312         const PixelViewport pvp( 0, 0, 1, 1 );
00313         _wglWindow = _createWGLWindow( pixelFormat, pvp );
00314         if( !_wglWindow )
00315             return false;
00316 
00317         const HDC dc = GetDC( _wglWindow );
00318         
00319         if( !dc )
00320             return false;
00321         
00322         setWGLDC( dc, WGL_DC_WINDOW );
00323     }
00324 
00325     PIXELFORMATDESCRIPTOR pfd = {0};
00326     pfd.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
00327     pfd.nVersion     = 1;
00328 
00329     DescribePixelFormat( _wglDC, pixelFormat, sizeof( pfd ), &pfd );
00330     if( !SetPixelFormat( _wglDC, pixelFormat, &pfd ))
00331     {
00332         _window->setErrorMessage( "Can't set window pixel format: " + 
00333             base::getErrorString( GetLastError( )));
00334         return false;
00335     }
00336 
00337     return true;
00338 }
00339 
00340 bool WGLWindow::configInitWGLWindow( int pixelFormat )
00341 {
00342     // adjust window size (adds border pixels)
00343     const PixelViewport& pvp = _window->getPixelViewport();
00344     HWND hWnd = _createWGLWindow( pixelFormat, pvp );
00345     if( !hWnd )
00346         return false;
00347         
00348     HDC windowDC = GetDC( hWnd );
00349     
00350     PIXELFORMATDESCRIPTOR pfd = {0};
00351     pfd.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
00352     pfd.nVersion     = 1;
00353 
00354     DescribePixelFormat( _wglAffinityDC ? _wglAffinityDC : windowDC, 
00355                          pixelFormat, sizeof(pfd), &pfd );
00356     if( !SetPixelFormat( windowDC, pixelFormat, &pfd ))
00357     {
00358         ReleaseDC( hWnd, windowDC );
00359         _window->setErrorMessage( "Can't set window pixel format: " + 
00360             base::getErrorString( GetLastError( )));
00361         return false;
00362     }
00363     ReleaseDC( hWnd, windowDC );
00364 
00365     ShowWindow( hWnd, SW_SHOW );
00366     UpdateWindow( hWnd );
00367 
00368     if( getIAttribute( Window::IATTR_HINT_SCREENSAVER ) != ON )
00369     {
00370         // Disable screen saver
00371         SystemParametersInfo( SPI_GETSCREENSAVEACTIVE, 0, &_screenSaverActive,
00372                               0 );
00373         SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, FALSE, 0, 0 );
00374         
00375         // Wake up monitor
00376         PostMessage( HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, -1 );
00377     }
00378 
00379     setWGLWindowHandle( hWnd );
00380     return true;
00381 }
00382 
00383 HWND WGLWindow::_createWGLWindow( int pixelFormat, const PixelViewport& pvp  )
00384 {
00385     // window class
00386     const std::string& name = _window->getName();
00387 
00388     std::ostringstream className;
00389     className << (name.empty() ? std::string("Equalizer") : name) 
00390               << (void*)this;
00391     const std::string& classStr = className.str();
00392                                   
00393     HINSTANCE instance = GetModuleHandle( 0 );
00394     WNDCLASS  wc = { 0 };
00395     wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
00396     wc.lpfnWndProc   = DefWindowProc;    
00397     wc.hInstance     = instance; 
00398     wc.hIcon         = LoadIcon( 0, IDI_WINLOGO );
00399     wc.hCursor       = LoadCursor( 0, IDC_ARROW );
00400     wc.lpszClassName = classStr.c_str();       
00401 
00402     if( !RegisterClass( &wc ))
00403     {
00404         _window->setErrorMessage( "Can't register window class: " + 
00405                                   base::getLastErrorString( ));
00406         return false;
00407     }
00408 
00409     // window
00410     DWORD windowStyleEx = WS_EX_APPWINDOW;
00411     DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
00412 
00413     if( getIAttribute( Window::IATTR_HINT_DECORATION ) == OFF )
00414         windowStyle = WS_POPUP;
00415 
00416     if( getIAttribute( Window::IATTR_HINT_FULLSCREEN ) == ON )
00417     {
00418         windowStyleEx |= WS_EX_TOPMOST;
00419 
00420         DEVMODE deviceMode = {0};
00421         deviceMode.dmSize = sizeof( DEVMODE );
00422         EnumDisplaySettings( 0, ENUM_CURRENT_SETTINGS, &deviceMode );
00423 
00424         if( ChangeDisplaySettings( &deviceMode, CDS_FULLSCREEN ) != 
00425             DISP_CHANGE_SUCCESSFUL )
00426         {
00427             _window->setErrorMessage( "Can't switch to fullscreen mode: " + 
00428                 base::getErrorString( GetLastError( )));
00429             return false;
00430         }
00431         windowStyle = WS_POPUP | WS_MAXIMIZE;
00432     }
00433 
00434     // adjust window size (adds border pixels)
00435     RECT rect;
00436     rect.left   = pvp.x;
00437     rect.top    = pvp.y;
00438     rect.right  = pvp.x + pvp.w;
00439     rect.bottom = pvp.y + pvp.h;
00440     AdjustWindowRectEx( &rect, windowStyle, FALSE, windowStyleEx );
00441 
00442     HWND hWnd = CreateWindowEx( windowStyleEx,
00443                                 wc.lpszClassName, 
00444                                 name.empty() ? "Equalizer" : name.c_str(),
00445                                 windowStyle, rect.left, rect.top, 
00446                                 rect.right - rect.left, rect.bottom - rect.top,
00447                                 0, 0, // parent, menu
00448                                 instance, 0 );
00449     if( !hWnd )
00450     {
00451         _window->setErrorMessage( "Can't create window: " );
00452         return false;
00453     }
00454 
00455     return hWnd;
00456 }
00457 
00458 bool WGLWindow::configInitWGLPBuffer( int pixelFormat )
00459 {
00460     if( !WGLEW_ARB_pbuffer )
00461     {
00462         _window->setErrorMessage( "WGL_ARB_pbuffer not supported" );
00463         return false;
00464     }
00465 
00466     const eq::PixelViewport& pvp = _window->getPixelViewport();
00467     EQASSERT( pvp.isValid( ));
00468 
00469     const HDC displayDC    = createWGLDisplayDC();
00470     if( !displayDC )
00471         return false;
00472 
00473     const HDC dc           = _wglAffinityDC ? _wglAffinityDC : displayDC;
00474     const int attributes[] = { WGL_PBUFFER_LARGEST_ARB, TRUE, 0 };
00475 
00476     HPBUFFERARB pBuffer = wglCreatePbufferARB( dc, pixelFormat, pvp.w, pvp.h,
00477                                                attributes );
00478     DeleteDC( displayDC );
00479     if( !pBuffer )
00480     {
00481         _window->setErrorMessage( "Can't create PBuffer: " + 
00482             base::getErrorString( GetLastError( )));
00483         return false;
00484     }
00485 
00486     setWGLPBufferHandle( pBuffer );
00487     return true;
00488 }
00489 
00490 void WGLWindow::exitWGLAffinityDC()
00491 {
00492     if( !_wglAffinityDC )
00493         return;
00494 
00495     wglDeleteDCNV( _wglAffinityDC );
00496     _wglAffinityDC = 0;
00497 }
00498 
00499 bool WGLWindow::initWGLAffinityDC()
00500 {
00501     // We need to create one DC per window, since the window DC pixel format and
00502     // the affinity RC pixel format have to match, and each window has
00503     // potentially a different pixel format.
00504     Pipe* pipe    = getPipe();
00505     EQASSERT( pipe );
00506     EQASSERT( pipe->getOSPipe( ));
00507     EQASSERT( dynamic_cast< WGLPipe* >( pipe->getOSPipe( )));
00508 
00509     WGLPipe* osPipe = static_cast< WGLPipe* >( pipe->getOSPipe( ));
00510 
00511     return osPipe->createWGLAffinityDC( _wglAffinityDC );
00512 }
00513 
00514 HDC WGLWindow::getWGLAffinityDC()
00515 {
00516     if( _wglAffinityDC )
00517         return _wglAffinityDC;
00518     if( _wglDCType == WGL_DC_AFFINITY )
00519         return _wglDC;
00520     return 0;
00521 }
00522 
00523 HDC WGLWindow::createWGLDisplayDC()
00524 {
00525     Pipe* pipe    = getPipe();
00526     EQASSERT( pipe );
00527     EQASSERT( pipe->getOSPipe( ));
00528     EQASSERT( dynamic_cast< WGLPipe* >( pipe->getOSPipe( )));
00529 
00530     WGLPipe* osPipe = static_cast< WGLPipe* >( pipe->getOSPipe( ));
00531 
00532     return osPipe->createWGLDisplayDC();
00533 }
00534 
00535 int WGLWindow::chooseWGLPixelFormat()
00536 {
00537     EQASSERT( WGLEW_ARB_pixel_format );
00538 
00539     std::vector< int > attributes;
00540     attributes.push_back( WGL_SUPPORT_OPENGL_ARB );
00541     attributes.push_back( 1 );
00542     attributes.push_back( WGL_ACCELERATION_ARB );
00543     attributes.push_back( WGL_FULL_ACCELERATION_ARB );
00544 
00545     const int colorSize = getIAttribute( Window::IATTR_PLANES_COLOR );
00546     const int colorBits = colorSize>0 ? colorSize : 8;
00547 
00548     if( colorSize > 0 || colorSize == AUTO ||
00549         getIAttribute( Window::IATTR_HINT_DRAWABLE ) == FBO )
00550     {
00551         attributes.push_back( WGL_COLOR_BITS_ARB );
00552         attributes.push_back( colorBits * 3 );
00553     }
00554     else if ( colorSize == RGBA16F || colorSize == RGBA32F )
00555     {
00556         const int colorBits = colorSize == RGBA16F ? 16 :  32;
00557 
00558         if ( !WGLEW_ARB_pixel_format_float )
00559         {
00560             _window->setErrorMessage( "Floating-point framebuffer unsupported" );
00561             return 0;
00562         }
00563         attributes.push_back( WGL_PIXEL_TYPE_ARB );
00564         attributes.push_back( WGL_TYPE_RGBA_FLOAT_ARB );
00565         
00566         attributes.push_back( WGL_COLOR_BITS_ARB );
00567         attributes.push_back( colorBits * 4);
00568     }
00569 
00570     const int alphaSize = getIAttribute( Window::IATTR_PLANES_ALPHA );
00571     if( alphaSize > 0 || alphaSize == AUTO )
00572     {
00573         attributes.push_back( WGL_ALPHA_BITS_ARB );
00574         attributes.push_back( alphaSize>0 ? alphaSize : 8 );
00575     }
00576 
00577     const int depthSize = getIAttribute( Window::IATTR_PLANES_DEPTH );
00578     if( depthSize > 0  || depthSize == AUTO )
00579     {
00580         attributes.push_back( WGL_DEPTH_BITS_ARB );
00581         attributes.push_back( depthSize>0 ? depthSize : 24 );
00582     }
00583 
00584     const int stencilSize = getIAttribute( Window::IATTR_PLANES_STENCIL );
00585     if( stencilSize >0 || stencilSize == AUTO )
00586     {
00587         attributes.push_back( WGL_STENCIL_BITS_ARB );
00588         attributes.push_back( stencilSize>0 ? stencilSize : 1 );
00589     }
00590 
00591     const int accumSize  = getIAttribute( Window::IATTR_PLANES_ACCUM );
00592     const int accumAlpha = getIAttribute( Window::IATTR_PLANES_ACCUM_ALPHA );
00593     if( accumSize >= 0 )
00594     {
00595         attributes.push_back( WGL_ACCUM_RED_BITS_ARB );
00596         attributes.push_back( accumSize );
00597         attributes.push_back( WGL_ACCUM_GREEN_BITS_ARB );
00598         attributes.push_back( accumSize );
00599         attributes.push_back( WGL_ACCUM_BLUE_BITS_ARB );
00600         attributes.push_back( accumSize );
00601         attributes.push_back( WGL_ACCUM_ALPHA_BITS_ARB );
00602         attributes.push_back( accumAlpha >= 0 ? accumAlpha : accumSize );
00603     }
00604     else if( accumAlpha >= 0 )
00605     {
00606         attributes.push_back( WGL_ACCUM_ALPHA_BITS_ARB );
00607         attributes.push_back( accumAlpha );
00608     }
00609 
00610     const int samplesSize  = getIAttribute( Window::IATTR_PLANES_SAMPLES );
00611     if( samplesSize >= 0 )
00612     {
00613         if( WGLEW_ARB_multisample )
00614         {
00615             attributes.push_back( WGL_SAMPLE_BUFFERS_ARB );
00616             attributes.push_back( 1 );
00617             attributes.push_back( WGL_SAMPLES_ARB );
00618             attributes.push_back( samplesSize );
00619         }
00620         else
00621             EQWARN << "WGLEW_ARB_multisample not supported, ignoring samples "
00622                    << "attribute" << std::endl;
00623     }
00624 
00625     if( getIAttribute( Window::IATTR_HINT_STEREO ) == ON ||
00626         ( getIAttribute( Window::IATTR_HINT_STEREO )   == AUTO && 
00627           getIAttribute( Window::IATTR_HINT_DRAWABLE ) == WINDOW ))
00628     {
00629         attributes.push_back( WGL_STEREO_ARB );
00630         attributes.push_back( 1 );
00631     }
00632 
00633     if( getIAttribute( Window::IATTR_HINT_DOUBLEBUFFER ) == ON ||
00634         ( getIAttribute( Window::IATTR_HINT_DOUBLEBUFFER ) == AUTO && 
00635           getIAttribute( Window::IATTR_HINT_DRAWABLE )     == WINDOW ))
00636     {
00637         attributes.push_back( WGL_DOUBLE_BUFFER_ARB );
00638         attributes.push_back( 1 );
00639     }
00640 
00641     if( getIAttribute( Window::IATTR_HINT_DRAWABLE ) == PBUFFER &&
00642         WGLEW_ARB_pbuffer )
00643     {
00644         attributes.push_back( WGL_DRAW_TO_PBUFFER_ARB );
00645         attributes.push_back( 1 );
00646     }
00647     else
00648     {
00649         attributes.push_back( WGL_DRAW_TO_WINDOW_ARB );
00650         attributes.push_back( 1 );
00651     }
00652 
00653     attributes.push_back( 0 );
00654 
00655     // build back off list, least important attribute last
00656     std::vector<int> backoffAttributes;
00657     if( getIAttribute( Window::IATTR_HINT_DRAWABLE ) == WINDOW )
00658     {
00659         if( getIAttribute( Window::IATTR_HINT_DOUBLEBUFFER ) == AUTO )
00660             backoffAttributes.push_back( WGL_DOUBLE_BUFFER_ARB );
00661 
00662         if( getIAttribute( Window::IATTR_HINT_STEREO ) == AUTO )
00663             backoffAttributes.push_back( WGL_STEREO_ARB );
00664     }
00665 
00666     if( stencilSize == AUTO )
00667         backoffAttributes.push_back( WGL_STENCIL_BITS_ARB );
00668 
00669     HDC screenDC    = GetDC( 0 );
00670     HDC pfDC        = _wglAffinityDC ? _wglAffinityDC : screenDC;
00671     int pixelFormat = 0;
00672 
00673     while( true )
00674     {
00675         UINT nFormats = 0;
00676     if( !wglChoosePixelFormatARB( pfDC, &attributes[0], 0, 1,
00677                                       &pixelFormat, &nFormats ))
00678         {
00679             EQWARN << "wglChoosePixelFormat failed: " 
00680                 << base::getLastErrorString() << std::endl;
00681         }
00682 
00683         if( (pixelFormat && nFormats > 0) ||  // found one or
00684             backoffAttributes.empty( ))       // nothing else to try
00685 
00686             break;
00687 
00688         // Gradually remove back off attributes
00689         const int attribute = backoffAttributes.back();
00690         backoffAttributes.pop_back();
00691 
00692         std::vector<GLint>::iterator iter = find( attributes.begin(), 
00693             attributes.end(), attribute );
00694         EQASSERT( iter != attributes.end( ));
00695 
00696         attributes.erase( iter, iter+2 ); // remove two items (attr, value)
00697 
00698     }
00699 
00700     ReleaseDC( 0, screenDC );
00701 
00702     if( pixelFormat == 0 )
00703     {
00704         _window->setErrorMessage( "Can't find matching pixel format: " + 
00705             base::getErrorString( GetLastError( )));
00706         return 0;
00707     }
00708  
00709     if( _wglAffinityDC ) // set pixel format on given device context
00710     {
00711         PIXELFORMATDESCRIPTOR pfd = {0};
00712         pfd.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
00713         pfd.nVersion     = 1;
00714 
00715         DescribePixelFormat( _wglAffinityDC, pixelFormat, sizeof(pfd), &pfd );
00716         if( !SetPixelFormat( _wglAffinityDC, pixelFormat, &pfd ))
00717         {
00718             _window->setErrorMessage( "Can't set device pixel format: " + 
00719                 base::getErrorString( GetLastError( )));
00720             return 0;
00721         }
00722     }
00723     
00724     return pixelFormat;
00725 }
00726 
00727 HGLRC WGLWindow::createWGLContext()
00728 {
00729     EQASSERT( _wglDC );
00730 
00731     // create context
00732     HGLRC context = wglCreateContext(_wglAffinityDC ? _wglAffinityDC : _wglDC );
00733     if( !context )
00734     {
00735         _window->setErrorMessage( "Can't create OpenGL context: " + 
00736             base::getErrorString( GetLastError( )));
00737         return 0;
00738     }
00739 
00740     // share context
00741     const Window* shareWindow = _window->getSharedContextWindow();
00742     if( shareWindow )
00743     {
00744         const OSWindow*  shareOSWindow = shareWindow->getOSWindow();
00745 
00746         EQASSERT( dynamic_cast< const WGLWindow* >( shareOSWindow ));
00747         const WGLWindow* shareWGLWindow = static_cast< const WGLWindow* >(
00748                                               shareOSWindow );
00749         HGLRC shareCtx = shareWGLWindow->getWGLContext();
00750 
00751         if( shareCtx && !wglShareLists( shareCtx, context ))
00752             EQWARN << "Context sharing failed: " << base::getLastErrorString()
00753                    << endl;
00754     }
00755 
00756     return context;
00757 }
00758 
00759 void WGLWindow::initEventHandler()
00760 {
00761     EQASSERT( !_wglEventHandler );
00762     _wglEventHandler = new WGLEventHandler( this );
00763 }
00764 
00765 void WGLWindow::exitEventHandler()
00766 {
00767     delete _wglEventHandler;
00768     _wglEventHandler = 0;
00769 }
00770 
00771 bool WGLWindow::processEvent( const WGLWindowEvent& event )
00772 {
00773     if( event.type == Event::WINDOW_EXPOSE )
00774     {
00775         EQASSERT( _wglWindow ); // PBuffers should not generate paint events
00776 
00777         // Invalidate update rectangle
00778         PAINTSTRUCT ps;
00779         BeginPaint( _wglWindow, &ps );
00780         EndPaint(   _wglWindow, &ps );
00781     }
00782 
00783     return WGLWindowIF::processEvent( event );
00784 }
00785 
00786 void WGLWindow::joinNVSwapBarrier( const uint32_t group, const uint32_t barrier)
00787 {
00788     if( group == 0 && barrier == 0 )
00789         return;
00790 
00791     if( !WGLEW_NV_swap_group )
00792     {
00793         EQWARN << "NV Swap group extension not supported" << endl;
00794         return;
00795     }
00796 
00797     const HDC dc = _wglAffinityDC ? _wglAffinityDC : _wglDC;
00798 
00799     uint32_t maxBarrier = 0;
00800     uint32_t maxGroup = 0;
00801     wglQueryMaxSwapGroupsNV( dc, &maxGroup, &maxBarrier );
00802 
00803     if( group > maxGroup )
00804     {
00805         EQWARN << "Failed to initialize WGL_NV_swap_group: requested group "
00806                << group << " greater than maxGroups (" << maxGroup << ")"
00807                << std::endl;
00808         return;
00809     }
00810 
00811     if( barrier > maxBarrier )
00812     {
00813         EQWARN << "Failed to initialize WGL_NV_swap_group: requested barrier "
00814                << barrier << "greater than maxBarriers (" << maxBarrier << ")"
00815                << std::endl;
00816         return;
00817     }
00818 
00819     if( !wglJoinSwapGroupNV( dc, group ))
00820     {
00821         EQWARN << "Failed to join swap group " << group << std::endl;
00822         return;
00823     }
00824     _wglNVSwapGroup = group;
00825 
00826     if( !wglBindSwapBarrierNV( group, barrier ))
00827     {
00828         EQWARN << "Failed to bind swap barrier " << barrier << std::endl;
00829         return;
00830     }
00831     
00832     EQINFO << "Joined swap group " << group << " and barrier " << barrier
00833            << std::endl;
00834 }
00835 
00836 void WGLWindow::leaveNVSwapBarrier()
00837 {
00838     if( _wglNVSwapGroup == 0 )
00839         return;
00840 
00841     const HDC dc = _wglAffinityDC ? _wglAffinityDC : _wglDC;
00842 
00843     wglBindSwapBarrierNV( _wglNVSwapGroup, 0 );
00844     wglJoinSwapGroupNV( dc, 0 );
00845 
00846     _wglNVSwapGroup = 0;
00847 }
00848 }
Generated on Mon Aug 10 18:58:41 2009 for Equalizer 0.9 by  doxygen 1.5.8