wglPipe.cpp

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