wglPipe.cpp

00001 
00002 /* Copyright (c) 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 "wglPipe.h"
00020 
00021 #include "global.h"
00022 #include "pipe.h"
00023 #include "wglEventHandler.h"
00024 
00025 namespace eq
00026 {
00027 
00028 WGLPipe::WGLPipe( Pipe* parent )
00029     : OSPipe( parent )
00030 {
00031 }
00032 
00033 WGLPipe::~WGLPipe( )
00034 {
00035 }
00036 
00037 using namespace std;
00038 
00039 //---------------------------------------------------------------------------
00040 // WGL init
00041 //---------------------------------------------------------------------------
00042 bool WGLPipe::configInit()
00043 {
00044     _configInitWGLEW();
00045 
00046     PixelViewport pvp = _pipe->getPixelViewport();
00047     if( pvp.isValid( ))
00048         return true;
00049 
00050     // setup pvp
00051     // ...using gpu affinity API
00052     HGPUNV hGPU = 0;
00053     if( !_getGPUHandle( hGPU ))
00054         return false;
00055 
00056     if( hGPU != 0 )
00057     {
00058         GPU_DEVICE gpuDevice;
00059         gpuDevice.cb = sizeof( gpuDevice );
00060         const bool found = wglEnumGpuDevicesNV( hGPU, 0, &gpuDevice );
00061         EQASSERT( found );
00062 
00063         if( gpuDevice.Flags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP )
00064         {
00065             const RECT& rect = gpuDevice.rcVirtualScreen;
00066             pvp.x = rect.left;
00067             pvp.y = rect.top;
00068             pvp.w = rect.right  - rect.left;
00069             pvp.h = rect.bottom - rect.top; 
00070         }
00071         else
00072         {
00073             pvp.x = 0;
00074             pvp.y = 0;
00075             pvp.w = 4096;
00076             pvp.h = 4096;
00077         }
00078     }
00079     else // ... using Win32 API
00080     {
00081         HDC dc = createWGLDisplayDC();
00082         EQASSERT( dc );
00083 
00084         pvp.x = 0;
00085         pvp.y = 0;
00086         pvp.w = GetDeviceCaps( dc, HORZRES );
00087         pvp.h = GetDeviceCaps( dc, VERTRES );
00088         _pipe->setPixelViewport( pvp );
00089 
00090         DeleteDC( dc );
00091     }
00092 
00093     _pipe->setPixelViewport( pvp );
00094     EQINFO << "Pipe pixel viewport " << pvp << endl;
00095     return true;
00096 }
00097 
00098 
00099 void WGLPipe::configExit()
00100 {
00101     _pipe->setPixelViewport( eq::PixelViewport( )); // invalidate
00102 }
00103 
00104 
00105 bool WGLPipe::createWGLAffinityDC( HDC& affinityDC )
00106 {
00107     affinityDC = 0;
00108 
00109     HGPUNV hGPU[2] = { 0 };
00110     if( !_getGPUHandle( hGPU[0] ))
00111         return false;
00112 
00113     if( hGPU[0] == 0 ) // no affinity DC needed
00114         return true;
00115 
00116     affinityDC = wglCreateAffinityDCNV( hGPU );
00117     if( !affinityDC )
00118     {
00119         setErrorMessage( "Can't create affinity DC: " +
00120                          base::getErrorString( GetLastError( )));
00121         return false;
00122     }
00123 
00124     return true;
00125 }
00126 
00127 HDC WGLPipe::createWGLDisplayDC()
00128 {
00129     uint32_t device = _pipe->getDevice();
00130     if( device == EQ_UNDEFINED_UINT32 )
00131         device = 0;
00132 
00133     DISPLAY_DEVICE devInfo;
00134     devInfo.cb = sizeof( devInfo );
00135 
00136     if( !EnumDisplayDevices( 0, device, &devInfo, 0 ))
00137     {
00138         _pipe->setErrorMessage( "Can't enumerate display devices: " + 
00139                                     base::getLastErrorString());
00140         return 0;
00141     }
00142 
00143     const HDC displayDC = CreateDC( "DISPLAY", devInfo.DeviceName, 0, 0 );
00144     if( !displayDC )
00145     {
00146         _pipe->setErrorMessage( "Can't create device context: " + 
00147                                      base::getLastErrorString( ));
00148         return 0;
00149     }
00150 
00151     return displayDC;
00152 }
00153 
00154 bool WGLPipe::_getGPUHandle( HGPUNV& handle )
00155 {
00156     handle = 0;
00157 
00158     const uint32_t device = _pipe->getDevice();
00159     if( device == EQ_UNDEFINED_UINT32 )
00160         return true;
00161 
00162     if( !WGLEW_NV_gpu_affinity )
00163     {
00164         EQWARN <<"WGL_NV_gpu_affinity unsupported, ignoring pipe device setting"
00165                << endl;
00166         return true;
00167     }
00168 
00169     if( !wglEnumGpusNV( device, &handle ))
00170     {
00171         stringstream error;
00172         error << "Can't enumerate GPU #" << device;
00173         setErrorMessage( error.str( ));
00174         return false;
00175     }
00176 
00177     return true;
00178 }
00179 
00180 
00181 void WGLPipe::_configInitWGLEW()
00182 {
00183     //----- Create and make current a temporary GL context to initialize WGLEW
00184 
00185     // window class
00186     ostringstream className;
00187     className << "TMP" << (void*)this;
00188     const string& classStr = className.str();
00189                                   
00190     HINSTANCE instance = GetModuleHandle( 0 );
00191     WNDCLASS  wc       = { 0 };
00192     wc.lpfnWndProc   = DefWindowProc;
00193     wc.hInstance     = instance; 
00194     wc.hIcon         = LoadIcon( 0, IDI_WINLOGO );
00195     wc.hCursor       = LoadCursor( 0, IDC_ARROW );
00196     wc.lpszClassName = classStr.c_str();       
00197 
00198     if( !RegisterClass( &wc ))
00199     {
00200         EQWARN << "Can't register temporary window class: " 
00201                << base::getErrorString( GetLastError( )) << endl;
00202         return;
00203     }
00204 
00205     // window
00206     DWORD windowStyleEx = WS_EX_APPWINDOW;
00207     DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
00208 
00209     HWND hWnd = CreateWindowEx( windowStyleEx,
00210                                 wc.lpszClassName, "TMP",
00211                                 windowStyle, 0, 0, 1, 1,
00212                                 0, 0, // parent, menu
00213                                 instance, 0 );
00214 
00215     if( !hWnd )
00216     {
00217         EQWARN << "Can't create temporary window: "
00218                << base::getErrorString( GetLastError( )) << endl;
00219         UnregisterClass( classStr.c_str(),  instance );
00220         return;
00221     }
00222 
00223     HDC                   dc  = GetDC( hWnd );
00224     PIXELFORMATDESCRIPTOR pfd = {0};
00225     pfd.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
00226     pfd.nVersion     = 1;
00227     pfd.dwFlags      = PFD_DRAW_TO_WINDOW |
00228                        PFD_SUPPORT_OPENGL;
00229 
00230     int pf = ChoosePixelFormat( dc, &pfd );
00231     if( pf == 0 )
00232     {
00233         EQWARN << "Can't find temporary pixel format: "
00234                << base::getErrorString( GetLastError( )) << endl;
00235         DestroyWindow( hWnd );
00236         UnregisterClass( classStr.c_str(),  instance );
00237         return;
00238     }
00239  
00240     if( !SetPixelFormat( dc, pf, &pfd ))
00241     {
00242         EQWARN << "Can't set pixel format: " 
00243                << base::getErrorString( GetLastError( )) << endl;
00244         ReleaseDC( hWnd, dc );
00245         DestroyWindow( hWnd );
00246         UnregisterClass( classStr.c_str(),  instance );
00247         return;
00248     }
00249 
00250     // context
00251     HGLRC context = wglCreateContext( dc );
00252     if( !context )
00253     {
00254          EQWARN << "Can't create temporary OpenGL context: " 
00255                 << base::getErrorString( GetLastError( )) << endl;
00256         ReleaseDC( hWnd, dc );
00257         DestroyWindow( hWnd );
00258         UnregisterClass( classStr.c_str(),  instance );
00259         return;
00260     }
00261 
00262     HDC   oldDC      = wglGetCurrentDC();
00263     HGLRC oldContext = wglGetCurrentContext();
00264 
00265     wglMakeCurrent( dc, context );
00266 
00267     const GLenum result = wglewInit();
00268     if( result != GLEW_OK )
00269         EQWARN << "Pipe WGLEW initialization failed with error " << result 
00270                << endl;
00271     else
00272         EQINFO << "Pipe WGLEW initialization successful" << endl;
00273 
00274     wglDeleteContext( context );
00275     ReleaseDC( hWnd, dc );
00276     DestroyWindow( hWnd );
00277     UnregisterClass( classStr.c_str(),  instance );
00278 
00279     wglMakeCurrent( oldDC, oldContext );
00280 }
00281 
00282 
00283 } //namespace eq
00284 
Generated on Mon Aug 10 18:58:41 2009 for Equalizer 0.9 by  doxygen 1.5.8