LCOV - code coverage report
Current view: top level - eq/glx - pipe.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 29 148 19.6 %
Date: 2016-09-29 05:02:09 Functions: 9 16 56.2 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2015, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                          Maxim Makhinya
       4             :  *                          Daniel Nachbaur <danielnachbaur@gmail.com>
       5             :  *
       6             :  * This library is free software; you can redistribute it and/or modify it under
       7             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       8             :  * by the Free Software Foundation.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      11             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      12             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      13             :  * details.
      14             :  *
      15             :  * You should have received a copy of the GNU Lesser General Public License
      16             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      17             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             :  */
      19             : 
      20             : #include "pipe.h"
      21             : 
      22             : #include "../gl.h"
      23             : #include "../global.h"
      24             : #include "../log.h"
      25             : #include "../pipe.h"
      26             : 
      27             : #include <eq/fabric/gpuInfo.h>
      28             : #include <lunchbox/os.h>
      29             : #include <boost/lexical_cast.hpp>
      30             : 
      31             : using boost::lexical_cast;
      32             : 
      33             : namespace eq
      34             : {
      35             : namespace glx
      36             : {
      37             : #ifndef NDEBUG
      38             : static int XErrorHandler( Display* display, XErrorEvent* event );
      39             : #endif
      40             : 
      41             : namespace detail
      42             : {
      43             : class Pipe
      44             : {
      45             : public:
      46           1 :     Pipe()
      47           1 :         : xDisplay( 0 )
      48             :     {
      49           1 :         lunchbox::setZero( &glxewContext, sizeof( GLXEWContext ));
      50           1 :     }
      51             : 
      52           1 :     ~Pipe()
      53             :     {
      54             : #ifndef NDEBUG
      55           1 :         lunchbox::setZero( &glxewContext, sizeof( GLXEWContext ));
      56             : #endif
      57           1 :     }
      58             : 
      59             :     /** Window-system specific display information. */
      60             :     Display* xDisplay;
      61             : 
      62             :     /** Extended GLX function entries. */
      63             :     GLXEWContext glxewContext;
      64             : };
      65             : }
      66             : 
      67           1 : Pipe::Pipe( eq::Pipe* parent )
      68             :     : SystemPipe( parent )
      69           1 :     , _impl( new detail::Pipe )
      70             : {
      71           1 : }
      72             : 
      73           3 : Pipe::~Pipe( )
      74             : {
      75           1 :     delete _impl;
      76           2 : }
      77             : 
      78           0 : Display* Pipe::getXDisplay() const
      79             : {
      80           0 :     return _impl->xDisplay;
      81             : }
      82             : 
      83           0 : GLXEWContext* Pipe::glxewGetContext()
      84             : {
      85           0 :     return &_impl->glxewContext;
      86             : }
      87             : 
      88             : //---------------------------------------------------------------------------
      89             : // GLX init
      90             : //---------------------------------------------------------------------------
      91           1 : bool Pipe::configInit()
      92             : {
      93           1 :     const std::string displayName = getXDisplayString();
      94           1 :     Display* xDisplay = XOpenDisplay( displayName.c_str( ));
      95             : 
      96           1 :     if( !xDisplay )
      97             :     {
      98             :         sendError( ERROR_GLXPIPE_DEVICE_NOTFOUND )
      99           1 :             << displayName << lunchbox::sysError();
     100           1 :         return false;
     101             :     }
     102             : 
     103             :     int major, event, error;
     104           0 :     if( !XQueryExtension( xDisplay, "GLX", &major, &event, &error ))
     105             :     {
     106           0 :         sendError( ERROR_GLXPIPE_GLX_NOTFOUND );
     107           0 :         XCloseDisplay( xDisplay );
     108           0 :         return false;
     109             :     }
     110             : 
     111           0 :     setXDisplay( xDisplay );
     112           0 :     LBVERB << "Opened X display " << displayName << " @" << xDisplay
     113           0 :            << ", device " << getPipe()->getDevice() << std::endl;
     114             : 
     115           0 :     return _configInitGLXEW();
     116             : }
     117             : 
     118           0 : void Pipe::configExit()
     119             : {
     120           0 :     Display* xDisplay = getXDisplay();
     121           0 :     if( !xDisplay )
     122           0 :         return;
     123             : 
     124           0 :     setXDisplay( 0 );
     125           0 :     XCloseDisplay( xDisplay );
     126           0 :     LBVERB << "Closed X display " << xDisplay << std::endl;
     127             : }
     128             : 
     129           1 : std::string Pipe::getXDisplayString()
     130             : {
     131           1 :     std::ostringstream  stringStream;
     132             : 
     133           1 :     const uint32_t port   = getPipe()->getPort();
     134           1 :     const uint32_t device = getPipe()->getDevice();
     135             : 
     136           1 :     if( port != LB_UNDEFINED_UINT32 )
     137             :     {
     138           0 :         if( device == LB_UNDEFINED_UINT32 )
     139           0 :             stringStream << ":" << port;
     140             :         else
     141           0 :             stringStream << ":" << port << "." << device;
     142             :     }
     143           1 :     else if( device != LB_UNDEFINED_UINT32 )
     144           1 :         stringStream << ":0." << device;
     145             : 
     146           2 :     const std::string name( XDisplayName( stringStream.str().c_str( )));
     147           2 :     return name.empty() ? ":0" : name;
     148             : }
     149             : 
     150           0 : void Pipe::setXDisplay( Display* display )
     151             : {
     152           0 :     if( _impl->xDisplay == display )
     153           0 :         return;
     154             : 
     155           0 :     _impl->xDisplay = display;
     156           0 :     XSetCurrentDisplay( display );
     157             : 
     158           0 :     GPUInfo info;
     159           0 :     if( getGPUInfo( display, info ))
     160             :     {
     161             : #ifndef NDEBUG
     162             :         // somewhat reduntant since it is a global handler
     163           0 :         XSetErrorHandler( XErrorHandler );
     164             : #endif
     165           0 :         const uint32_t port = getPipe()->getPort();
     166           0 :         const uint32_t device = getPipe()->getDevice();
     167             : 
     168           0 :         if( port != LB_UNDEFINED_UINT32 && info.port != port )
     169           0 :             LBWARN << "Display mismatch: provided display connection uses"
     170           0 :                    << " display " << info.port << ", but pipe has port " << port
     171           0 :                    << std::endl;
     172             : 
     173           0 :         if( device != LB_UNDEFINED_UINT32 && info.device != device )
     174           0 :             LBWARN << "Screen mismatch: provided display connection uses "
     175           0 :                    << "default screen " << info.device
     176           0 :                    << ", but pipe has screen " << device << std::endl;
     177             :     }
     178             : 
     179           0 :     const PixelViewport& pvp = getPipe()->getPixelViewport();
     180           0 :     if( !pvp.isValid( ))
     181           0 :         getPipe()->setPixelViewport( info.pvp );
     182             : }
     183             : 
     184           0 : bool Pipe::getGPUInfo( Display* display, GPUInfo& info )
     185             : {
     186           0 :     if( !display )
     187           0 :         return false;
     188             : 
     189           0 :     std::string displayString = DisplayString( display );
     190           0 :     const size_t colonPos = displayString.find( ':' );
     191           0 :     if( colonPos != std::string::npos )
     192             :     {
     193           0 :         const std::string displayNumber = displayString.substr( colonPos+1 );
     194           0 :         info.port = atoi( displayNumber.c_str( ));
     195           0 :         info.device = DefaultScreen( display );
     196             :     }
     197             : 
     198           0 :     info.pvp.x = 0;
     199           0 :     info.pvp.y = 0;
     200           0 :     info.pvp.w = DisplayWidth(  display, DefaultScreen( display ));
     201           0 :     info.pvp.h = DisplayHeight( display, DefaultScreen( display ));
     202             : 
     203           0 :     return true;
     204             : }
     205             : 
     206           0 : bool Pipe::_configInitGLXEW()
     207             : {
     208           0 :     LBASSERT( _impl->xDisplay );
     209             : 
     210             :     //----- Create and make current a temporary GL context to initialize GLXEW
     211             :     // visual
     212           0 :     std::vector<int> attributes;
     213           0 :     attributes.push_back( GLX_RGBA );
     214           0 :     attributes.push_back( None );
     215             : 
     216           0 :     const int screen = DefaultScreen( _impl->xDisplay );
     217             :     XVisualInfo *visualInfo = glXChooseVisual( _impl->xDisplay, screen,
     218           0 :                                                &attributes.front( ));
     219           0 :     if( !visualInfo )
     220             :     {
     221           0 :         sendError( ERROR_SYSTEMPIPE_PIXELFORMAT_NOTFOUND );
     222           0 :         return false;
     223             :     }
     224             : 
     225             :     //context
     226             :     GLXContext context = glXCreateContext( _impl->xDisplay, visualInfo, 0,
     227           0 :                                            True );
     228           0 :     if( !context )
     229             :     {
     230           0 :         sendError( ERROR_SYSTEMPIPE_CREATECONTEXT_FAILED );
     231           0 :         return false;
     232             :     }
     233             : 
     234             :     // window
     235           0 :     const XID parent = RootWindow( _impl->xDisplay, screen );
     236             :     XSetWindowAttributes wa;
     237             :     wa.colormap = XCreateColormap( _impl->xDisplay, parent, visualInfo->visual,
     238           0 :                                    AllocNone );
     239           0 :     wa.background_pixmap = None;
     240           0 :     wa.border_pixel = 0;
     241             :     XID drawable = XCreateWindow( _impl->xDisplay, parent, 0, 0, 16, 16,
     242             :                                   0, visualInfo->depth, InputOutput,
     243             :                                   visualInfo->visual,
     244             :                                   CWBackPixmap | CWBorderPixel | CWColormap,
     245           0 :                                   &wa );
     246           0 :     if( !drawable )
     247             :     {
     248           0 :         sendError( ERROR_SYSTEMPIPE_CREATEWINDOW_FAILED );
     249           0 :         return false;
     250             :     }
     251             : 
     252           0 :     XFree( visualInfo );
     253           0 :     XSync( _impl->xDisplay, False );
     254             : 
     255           0 :     glXMakeCurrent( _impl->xDisplay, drawable, context );
     256             : 
     257           0 :     const GLenum result = glxewInit();
     258           0 :     bool success = result == GLEW_OK;
     259           0 :     if( success )
     260             :     {
     261           0 :         LBVERB << "Pipe GLXEW initialization successful" << std::endl;
     262           0 :         success = configInitGL();
     263             : 
     264           0 :         const char* glVersion = (const char*)glGetString( GL_VERSION );
     265           0 :         if( success && glVersion )
     266           0 :             _maxOpenGLVersion = static_cast<float>( atof( glVersion ));
     267             :     }
     268             :     else
     269             :         sendError( ERROR_GLXPIPE_GLXEWINIT_FAILED )
     270           0 :             << lexical_cast< std::string >( result );
     271             : 
     272           0 :     XSync( _impl->xDisplay, False );
     273           0 :     glXDestroyContext( _impl->xDisplay, context );
     274           0 :     XDestroyWindow( _impl->xDisplay, drawable );
     275             : 
     276           0 :     return success;
     277             : }
     278             : 
     279             : #ifndef NDEBUG
     280           0 : int XErrorHandler( Display* display, XErrorEvent* event )
     281             : {
     282           0 :     LBWARN << lunchbox::disableFlush;
     283           0 :     LBWARN << "X Error occured: " << lunchbox::disableHeader
     284           0 :            << lunchbox::indent;
     285             : 
     286             :     char buffer[256];
     287           0 :     XGetErrorText( display, event->error_code, buffer, 256);
     288             : 
     289           0 :     LBWARN << buffer << std::endl;
     290           0 :     LBWARN << "Major opcode: " << (int)event->request_code << std::endl;
     291           0 :     LBWARN << "Minor opcode: " << (int)event->minor_code << std::endl;
     292           0 :     LBWARN << "Error code: " << (int)event->error_code << std::endl;
     293           0 :     LBWARN << "Request serial: " << event->serial << std::endl;
     294           0 :     LBWARN << "Current serial: " << NextRequest( display ) - 1 << std::endl;
     295             : 
     296           0 :     switch( event->error_code )
     297             :     {
     298             :         case BadValue:
     299           0 :             LBWARN << "  Value: " << event->resourceid << std::endl;
     300           0 :             break;
     301             : 
     302             :         case BadAtom:
     303           0 :             LBWARN << "  AtomID: " << event->resourceid << std::endl;
     304           0 :             break;
     305             : 
     306             :         default:
     307           0 :             LBWARN << "  ResourceID: " << event->resourceid << std::endl;
     308           0 :             break;
     309             :     }
     310           0 :     LBWARN << lunchbox::enableFlush << lunchbox::exdent
     311           0 :            << lunchbox::enableHeader;
     312             : 
     313             : #ifndef NDEBUG
     314           0 :     if( getenv( "EQ_ABORT_WAIT" ))
     315             :     {
     316           0 :         LBWARN << "Caught X Error, entering infinite loop for debugging"
     317           0 :                << std::endl;
     318             :         while( true ) ;
     319             :     }
     320             : #endif
     321             : 
     322           0 :     return 0;
     323             : }
     324             : #endif // !NDEBUG
     325             : 
     326             : }
     327          42 : }

Generated by: LCOV version 1.11