LCOV - code coverage report
Current view: top level - eq/client/glx - pipe.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 115 141 81.6 %
Date: 2014-06-18 Functions: 15 15 100.0 %

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

Generated by: LCOV version 1.10