LCOV - code coverage report
Current view: top level - eq/client/glx - window.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 256 425 60.2 %
Date: 2014-06-18 Functions: 27 29 93.1 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009-2014, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                    2014, Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *                    2009, Maxim Makhinya
       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 "window.h"
      21             : 
      22             : #include "eventHandler.h"
      23             : #include "messagePump.h"
      24             : #include "pipe.h"
      25             : #include "windowEvent.h"
      26             : 
      27             : #include "../global.h"
      28             : #include "../pipe.h"
      29             : 
      30             : 
      31             : namespace eq
      32             : {
      33             : namespace glx
      34             : {
      35             : namespace detail
      36             : {
      37             : class Window
      38             : {
      39             : public:
      40          17 :     Window( Display* xDisplay_, const GLXEWContext* glxewContext_,
      41             :             MessagePump* messagePump_ )
      42             :         : xDisplay( xDisplay_ )
      43             :         , xDrawable ( 0 )
      44             :         , glXContext( 0 )
      45             :         , glXNVSwapGroup( 0 )
      46             :         , glXEventHandler( 0 )
      47             :         , glxewContext( glxewContext_ )
      48          17 :         , messagePump( messagePump_ )
      49          17 :     {}
      50             : 
      51             :     /** The display connection (maintained by GLXPipe) */
      52             :     Display*   xDisplay;
      53             :     /** The X11 drawable ID of the window. */
      54             :     XID        xDrawable;
      55             :     /** The glX rendering context. */
      56             :     GLXContext glXContext;
      57             :     /** The currently joined swap group. */
      58             :     uint32_t glXNVSwapGroup;
      59             : 
      60             :     /** The event handler. */
      61             :     EventHandler* glXEventHandler;
      62             : 
      63             :     /** The glX extension pointer table. */
      64             :     const GLXEWContext* glxewContext;
      65             : 
      66             :     MessagePump* const messagePump;
      67             : };
      68             : }
      69             : 
      70          17 : Window::Window( NotifierInterface& parent, const WindowSettings& settings,
      71             :                 Display* xDisplay, const GLXEWContext* glxewContext,
      72             :                 MessagePump* messagePump )
      73             :     : WindowIF( parent, settings )
      74          17 :     , _impl( new detail::Window( xDisplay, glxewContext, messagePump ))
      75             : {
      76          17 : }
      77             : 
      78          51 : Window::~Window()
      79             : {
      80          17 :     delete _impl;
      81          34 : }
      82             : 
      83             : //---------------------------------------------------------------------------
      84             : // GLX init
      85             : //---------------------------------------------------------------------------
      86             : namespace
      87             : {
      88           8 : static Bool WaitForNotify( Display*, XEvent *e, char *arg )
      89           8 : { return (e->type == MapNotify) && (e->xmap.window == (::Window)arg); }
      90             : }
      91             : 
      92          17 : bool Window::configInit()
      93             : {
      94          17 :     GLXFBConfig* fbConfig = chooseGLXFBConfig();
      95          17 :     if( !fbConfig )
      96             :     {
      97           0 :         sendError( ERROR_SYSTEMWINDOW_PIXELFORMAT_NOTFOUND );
      98           0 :         return false;
      99             :     }
     100             : 
     101          17 :     GLXContext context = createGLXContext( fbConfig );
     102          17 :     setGLXContext( context );
     103          17 :     if( !context )
     104             :     {
     105           0 :         XFree( fbConfig );
     106           0 :         return false;
     107             :     }
     108             : 
     109          17 :     const bool success = configInitGLXDrawable( fbConfig );
     110          17 :     XFree( fbConfig );
     111             : 
     112          17 :     if( !success || !_impl->xDrawable )
     113             :     {
     114           0 :         sendError( ERROR_GLXWINDOW_NO_DRAWABLE );
     115           0 :         return false;
     116             :     }
     117             : 
     118          17 :     makeCurrent();
     119          17 :     initGLEW();
     120          17 :     _initSwapSync();
     121          17 :     if( getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ) == FBO )
     122          13 :         configInitFBO();
     123             : 
     124          17 :     return success;
     125             : }
     126             : 
     127          17 : GLXFBConfig* Window::chooseGLXFBConfig()
     128             : {
     129          17 :     if( !_impl->xDisplay )
     130             :     {
     131           0 :         sendError( ERROR_GLXWINDOW_NO_DISPLAY );
     132           0 :         return 0;
     133             :     }
     134          17 :     if( !GLXEW_VERSION_1_3 && !GLXEW_SGIX_fbconfig )
     135             :     {
     136           0 :         sendError( ERROR_GLXWINDOW_FBCONFIG_REQUIRED );
     137           0 :         return 0;
     138             :     }
     139             : 
     140             :     // build attribute list
     141          17 :     std::vector< int > attributes;
     142          17 :     const int32_t drawableHint = getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE );
     143          17 :     switch( drawableHint )
     144             :     {
     145             :       case PBUFFER:
     146           0 :         attributes.push_back ( GLX_DRAWABLE_TYPE );
     147           0 :         attributes.push_back ( GLX_PBUFFER_BIT );
     148           0 :         break;
     149             : 
     150             :       default:
     151           0 :         LBWARN << "Unknown drawable type " << drawableHint << ", using window"
     152           0 :                << std::endl;
     153             :         // no break;
     154             :       case UNDEFINED:
     155             :       case OFF: // needs fbConfig with visual for dummy window
     156             :       case FBO: // No typo - FBO needs fbConfig with visual for dummy window
     157             :       case WINDOW:
     158          17 :         attributes.push_back( GLX_X_RENDERABLE );
     159          17 :         attributes.push_back( True );
     160             :     }
     161             : 
     162          17 :     int colorSize = getIAttribute( WindowSettings::IATTR_PLANES_COLOR );
     163          17 :     if( colorSize != OFF )
     164             :     {
     165          17 :         if( drawableHint == FBO || drawableHint == OFF )
     166          15 :             colorSize = 8; // Create FBO dummy window with 8bpp
     167           2 :         else switch( colorSize )
     168             :         {
     169             :           case RGBA16F:
     170             :           case RGBA32F:
     171           0 :             if( !GLXEW_ARB_fbconfig_float )
     172             :             {
     173           0 :                 sendError( ERROR_SYSTEMWINDOW_ARB_FLOAT_FB_REQUIRED );
     174           0 :                 return 0;
     175             :             }
     176           0 :             attributes.push_back( GLX_RENDER_TYPE );
     177           0 :             attributes.push_back( GLX_RGBA_FLOAT_BIT );
     178           0 :             colorSize = colorSize == RGBA16F ? 16 : 32;
     179           0 :             break;
     180             : 
     181             :           case AUTO:
     182             :           case ON:
     183           2 :             colorSize = 8;
     184           2 :             break;
     185             :           default:
     186           0 :             break;
     187             :         }
     188             : 
     189          17 :         LBASSERT( colorSize > 0 );
     190          17 :         attributes.push_back( GLX_RED_SIZE );
     191          17 :         attributes.push_back( colorSize );
     192          17 :         attributes.push_back( GLX_GREEN_SIZE );
     193          17 :         attributes.push_back( colorSize );
     194          17 :         attributes.push_back( GLX_BLUE_SIZE );
     195          17 :         attributes.push_back( colorSize );
     196             : 
     197          17 :         const int alphaSize = getIAttribute( WindowSettings::IATTR_PLANES_ALPHA );
     198          17 :         switch( alphaSize )
     199             :         {
     200             :           case AUTO:
     201             :           case UNDEFINED:
     202             :           case ON:
     203          17 :             attributes.push_back( GLX_ALPHA_SIZE );
     204          17 :             attributes.push_back( colorSize );
     205          17 :             break;
     206             : 
     207             :           case OFF:
     208           0 :               break;
     209             : 
     210             :           default:
     211           0 :             LBASSERT( alphaSize > 0 );
     212           0 :             attributes.push_back( GLX_ALPHA_SIZE );
     213           0 :             attributes.push_back( alphaSize > 0 ? alphaSize : colorSize );
     214             :         }
     215             :     }
     216          17 :     const int depthSize = getIAttribute( WindowSettings::IATTR_PLANES_DEPTH );
     217          17 :     if( depthSize > 0  || depthSize == AUTO )
     218             :     {
     219          17 :         attributes.push_back( GLX_DEPTH_SIZE );
     220          17 :         attributes.push_back( depthSize > 0 ? depthSize : 1 );
     221             :     }
     222          17 :     const int stencilSize = getIAttribute( WindowSettings::IATTR_PLANES_STENCIL );
     223          17 :     if( stencilSize > 0 || stencilSize == AUTO )
     224             :     {
     225          17 :         attributes.push_back( GLX_STENCIL_SIZE );
     226          17 :         attributes.push_back( stencilSize>0 ? stencilSize : 1 );
     227             :     }
     228          17 :     const int accumSize = getIAttribute( WindowSettings::IATTR_PLANES_ACCUM );
     229          17 :     const int accumAlpha = getIAttribute( WindowSettings::IATTR_PLANES_ACCUM_ALPHA );
     230          17 :     if( accumSize >= 0 )
     231             :     {
     232           0 :         attributes.push_back( GLX_ACCUM_RED_SIZE );
     233           0 :         attributes.push_back( accumSize );
     234           0 :         attributes.push_back( GLX_ACCUM_GREEN_SIZE );
     235           0 :         attributes.push_back( accumSize );
     236           0 :         attributes.push_back( GLX_ACCUM_BLUE_SIZE );
     237           0 :         attributes.push_back( accumSize );
     238           0 :         attributes.push_back( GLX_ACCUM_ALPHA_SIZE );
     239           0 :         attributes.push_back( accumAlpha >= 0 ? accumAlpha : accumSize );
     240             :     }
     241          17 :     else if( accumAlpha >= 0 )
     242             :     {
     243           0 :         attributes.push_back( GLX_ACCUM_ALPHA_SIZE );
     244           0 :         attributes.push_back( accumAlpha );
     245             :     }
     246             : 
     247          17 :     const int samplesSize  = getIAttribute( WindowSettings::IATTR_PLANES_SAMPLES );
     248          17 :     if( samplesSize >= 0 )
     249             :     {
     250           0 :         attributes.push_back( GLX_SAMPLE_BUFFERS );
     251           0 :         attributes.push_back( 1 );
     252           0 :         attributes.push_back( GLX_SAMPLES );
     253           0 :         attributes.push_back( samplesSize );
     254             :     }
     255             : 
     256             : #ifdef Darwin
     257             :     // WAR: glDrawBuffer( GL_BACK ) renders only to the left back buffer on a
     258             :     // stereo visual on Darwin which creates ugly flickering on mono configs
     259             :     if( getIAttribute( WindowSettings::IATTR_HINT_STEREO ) == ON )
     260             :     {
     261             :         attributes.push_back( GLX_STEREO );
     262             :         attributes.push_back( true );
     263             :     }
     264             : #else
     265          36 :     if( getIAttribute( WindowSettings::IATTR_HINT_STEREO ) == ON ||
     266          34 :         ( getIAttribute( WindowSettings::IATTR_HINT_STEREO )   == AUTO &&
     267          17 :           getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ) == WINDOW ))
     268             :     {
     269           2 :         attributes.push_back( GLX_STEREO );
     270           2 :         attributes.push_back( true );
     271             :     }
     272             : #endif
     273          36 :     if( getIAttribute( WindowSettings::IATTR_HINT_DOUBLEBUFFER ) == ON ||
     274          34 :         ( getIAttribute( WindowSettings::IATTR_HINT_DOUBLEBUFFER ) == AUTO &&
     275          17 :           getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE )     == WINDOW ))
     276             :     {
     277           2 :         attributes.push_back( GLX_DOUBLEBUFFER );
     278           2 :         attributes.push_back( true );
     279             :     }
     280          17 :     attributes.push_back( None );
     281             : 
     282             :     // build backoff list, least important attribute last
     283          17 :     std::vector<int> backoffAttributes;
     284          17 :     if( getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ) == WINDOW )
     285             :     {
     286           2 :         if( getIAttribute( WindowSettings::IATTR_HINT_DOUBLEBUFFER ) == AUTO )
     287           2 :             backoffAttributes.push_back( GLX_DOUBLEBUFFER );
     288             : 
     289             : #ifndef Darwin
     290           2 :         if( getIAttribute( WindowSettings::IATTR_HINT_STEREO ) == AUTO )
     291           2 :             backoffAttributes.push_back( GLX_STEREO );
     292             : #endif
     293             :     }
     294             : 
     295          17 :     if( stencilSize == AUTO )
     296          10 :         backoffAttributes.push_back( GLX_STENCIL_SIZE );
     297             : 
     298          17 :     PFNGLXCHOOSEFBCONFIGSGIXPROC chooseFBConfig = GLXEW_VERSION_1_3 ?
     299          17 :         glXChooseFBConfig : glXChooseFBConfigSGIX;
     300             : 
     301          17 :     const int screen = DefaultScreen( _impl->xDisplay );
     302          17 :     int nConfigs = 0;
     303             :     GLXFBConfig* configs = chooseFBConfig( _impl->xDisplay, screen,
     304          17 :                                            &attributes[0], &nConfigs );
     305             : 
     306          37 :     while(( nConfigs == 0 || !configs ) && !backoffAttributes.empty( ))
     307             :     {
     308             :         // Gradually remove backoff attributes
     309           3 :         const int attribute = backoffAttributes.back();
     310           3 :         backoffAttributes.pop_back();
     311             : 
     312             :         std::vector<int>::iterator iter = find( attributes.begin(),
     313           3 :                                                 attributes.end(), attribute );
     314           3 :         LBASSERT( iter != attributes.end( ));
     315           3 :         attributes.erase( iter, iter+2 );
     316           3 :         configs = chooseFBConfig( _impl->xDisplay, screen, &attributes[0],
     317           3 :                                   &nConfigs );
     318             :     }
     319             : 
     320          17 :     return configs;
     321             : }
     322             : 
     323          17 : GLXContext Window::createGLXContext( GLXFBConfig* fbConfig )
     324             : {
     325          17 :     if( !_impl->xDisplay )
     326             :     {
     327           0 :         sendError( ERROR_GLXWINDOW_NO_DISPLAY );
     328           0 :         return 0;
     329             :     }
     330          17 :     if( !fbConfig )
     331             :     {
     332           0 :         sendError( ERROR_SYSTEMWINDOW_NO_PIXELFORMAT );
     333           0 :         return 0;
     334             :     }
     335             : 
     336          17 :     GLXContext shCtx = 0;
     337             :     const WindowIF* shareGLXWindow =
     338          17 :             dynamic_cast< const WindowIF* >( getSharedContextWindow( ));
     339          17 :     if( shareGLXWindow )
     340           2 :         shCtx = shareGLXWindow->getGLXContext();
     341             : 
     342          17 :     int type = GLX_RGBA_TYPE;
     343          17 :     if( getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ) == PBUFFER &&
     344           0 :         ( getIAttribute( WindowSettings::IATTR_PLANES_COLOR ) == RGBA16F ||
     345           0 :           getIAttribute( WindowSettings::IATTR_PLANES_COLOR ) == RGBA32F ))
     346             :     {
     347           0 :         type = GLX_RGBA_FLOAT_TYPE;
     348             :     }
     349             : 
     350          17 :     GLXContext context = GLXEW_VERSION_1_3 ?
     351          17 :         glXCreateNewContext( _impl->xDisplay, fbConfig[0], type, shCtx, True ):
     352             :         glXCreateContextWithConfigSGIX( _impl->xDisplay, fbConfig[0], type,
     353          34 :                                         shCtx, True );
     354             : 
     355             : #ifdef Darwin
     356             :     // WAR http://xquartz.macosforge.org/trac/ticket/466
     357             :     if( !context )
     358             :     {
     359             :         XVisualInfo* visInfo = GLXEW_VERSION_1_3 ?
     360             :             glXGetVisualFromFBConfig( _impl->xDisplay, fbConfig[0] ) :
     361             :             glXGetVisualFromFBConfigSGIX( _impl->xDisplay, fbConfig[0] );
     362             :         if( !visInfo )
     363             :         {
     364             :             std::vector<int> attributes;
     365             :             attributes.push_back( GLX_RGBA );
     366             :             attributes.push_back( GLX_RED_SIZE );
     367             :             attributes.push_back( 1 );
     368             :             attributes.push_back( GLX_ALPHA_SIZE );
     369             :             attributes.push_back( 1 );
     370             :             attributes.push_back( GLX_DEPTH_SIZE );
     371             :             attributes.push_back( 1 );
     372             :             attributes.push_back( GLX_DOUBLEBUFFER );
     373             :             attributes.push_back( None );
     374             : 
     375             :             const int screen = DefaultScreen( _impl->xDisplay );
     376             :             visInfo = glXChooseVisual( _impl->xDisplay, screen,
     377             :                                        &attributes.front( ));
     378             :             if( !visInfo )
     379             :             {
     380             :                 sendError( ERROR_GLXWINDOW_NO_VISUAL );
     381             :                 return 0;
     382             :             }
     383             :         }
     384             : 
     385             :         context = glXCreateContext( _impl->xDisplay, visInfo, shCtx, True );
     386             :         XFree( visInfo );
     387             :     }
     388             : #endif
     389             : 
     390          17 :     if( !context )
     391             :     {
     392           0 :         sendError( ERROR_GLXWINDOW_CREATECONTEXT_FAILED );
     393           0 :         return 0;
     394             :     }
     395          17 :     return context;
     396             : }
     397             : 
     398          17 : bool Window::configInitGLXDrawable( GLXFBConfig* fbConfig )
     399             : {
     400          17 :     switch( getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ))
     401             :     {
     402             :         case PBUFFER:
     403           0 :             return configInitGLXPBuffer( fbConfig );
     404             : 
     405             :         case FBO:
     406             :         case OFF:
     407             :         {
     408          15 :             const PixelViewport pvp( 0, 0, 1, 1 );
     409          15 :             setXDrawable( _createGLXWindow( fbConfig, pvp ));
     410          15 :             return _impl->xDrawable != 0;
     411             :         }
     412             : 
     413             :         default:
     414           0 :             LBWARN << "Unknown drawable type "
     415           0 :                    << getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE )
     416           0 :                    << ", using window" << std::endl;
     417             :             // no break;
     418             :         case UNDEFINED:
     419             :         case WINDOW:
     420           2 :             return configInitGLXWindow( fbConfig );
     421             :     }
     422             : }
     423             : 
     424           2 : bool Window::configInitGLXWindow( GLXFBConfig* fbConfig )
     425             : {
     426           2 :     if( !_impl->xDisplay )
     427             :     {
     428           0 :         sendError( ERROR_GLXWINDOW_NO_DISPLAY );
     429           0 :         return false;
     430             :     }
     431             : 
     432           2 :     PixelViewport pvp = getPixelViewport();
     433           2 :     if( getIAttribute( WindowSettings::IATTR_HINT_FULLSCREEN ) == ON )
     434             :     {
     435           0 :         const int screen = DefaultScreen( _impl->xDisplay );
     436           0 :         pvp.h = DisplayHeight( _impl->xDisplay, screen );
     437           0 :         pvp.w = DisplayWidth( _impl->xDisplay, screen );
     438           0 :         pvp.x = 0;
     439           0 :         pvp.y = 0;
     440             : 
     441           0 :         setPixelViewport( pvp );
     442             :     }
     443             : 
     444           2 :     XID drawable = _createGLXWindow( fbConfig, pvp );
     445           2 :     if( !drawable )
     446           0 :         return false;
     447             : 
     448             :     // map and wait for MapNotify event
     449           2 :     XMapWindow( _impl->xDisplay, drawable );
     450             : 
     451             :     XEvent event;
     452           2 :     XIfEvent( _impl->xDisplay, &event, WaitForNotify, (XPointer)(drawable) );
     453             : 
     454           2 :     XMoveResizeWindow( _impl->xDisplay, drawable, pvp.x, pvp.y, pvp.w, pvp.h );
     455           2 :     XFlush( _impl->xDisplay );
     456             : 
     457             :     // Grab keyboard focus in fullscreen mode
     458           4 :     if( getIAttribute( WindowSettings::IATTR_HINT_FULLSCREEN ) == ON ||
     459           2 :         getIAttribute( WindowSettings::IATTR_HINT_DECORATION ) == OFF )
     460             :     {
     461             :         XGrabKeyboard( _impl->xDisplay, drawable, True, GrabModeAsync,
     462           0 :                        GrabModeAsync, CurrentTime );
     463             :     }
     464           2 :     setXDrawable( drawable );
     465             : 
     466           2 :     LBVERB << "Created X11 drawable " << drawable << std::endl;
     467           2 :     return true;
     468             : }
     469             : 
     470          17 : XID Window::_createGLXWindow( GLXFBConfig* fbConfig, const PixelViewport& pvp )
     471             : {
     472          17 :     LBASSERT( getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ) != PBUFFER );
     473             : 
     474          17 :     if( !_impl->xDisplay )
     475             :     {
     476           0 :         sendError( ERROR_GLXWINDOW_NO_DISPLAY );
     477           0 :         return 0;
     478             :     }
     479          17 :     if( !fbConfig )
     480             :     {
     481           0 :         sendError( ERROR_SYSTEMWINDOW_NO_PIXELFORMAT );
     482           0 :         return 0;
     483             :     }
     484             : 
     485          17 :     XVisualInfo* visInfo = GLXEW_VERSION_1_3 ?
     486          17 :         glXGetVisualFromFBConfig( _impl->xDisplay, fbConfig[0] ) :
     487          34 :         glXGetVisualFromFBConfigSGIX( _impl->xDisplay, fbConfig[0]);
     488          17 :     if( !visInfo )
     489             :     {
     490           0 :         sendError( ERROR_GLXWINDOW_NO_VISUAL );
     491           0 :         return 0;
     492             :     }
     493             : 
     494          17 :     const int screen = DefaultScreen( _impl->xDisplay );
     495          17 :     XID parent = RootWindow( _impl->xDisplay, screen );
     496             :     XSetWindowAttributes wa;
     497             :     wa.colormap = XCreateColormap( _impl->xDisplay, parent, visInfo->visual,
     498          17 :                                    AllocNone );
     499          17 :     wa.background_pixmap = None;
     500          17 :     wa.border_pixel = 0;
     501             :     wa.event_mask = StructureNotifyMask | VisibilityChangeMask | ExposureMask |
     502             :                     KeyPressMask | KeyReleaseMask | PointerMotionMask |
     503          17 :                     ButtonPressMask | ButtonReleaseMask;
     504             : 
     505          17 :     switch( getIAttribute( WindowSettings::IATTR_HINT_DECORATION ))
     506             :     {
     507             :       case ON:
     508           0 :           wa.override_redirect = False;
     509           0 :           break;
     510             : 
     511             :       case OFF:
     512           0 :           wa.override_redirect = True;
     513           0 :           break;
     514             : 
     515             :       case AUTO:
     516             :       default:
     517             :           wa.override_redirect =
     518          17 :               getIAttribute( WindowSettings::IATTR_HINT_FULLSCREEN ) == ON ?
     519          17 :               True : False;
     520          17 :           break;
     521             :     }
     522             : 
     523             :     XID drawable = XCreateWindow( _impl->xDisplay, parent,
     524             :                                   pvp.x, pvp.y, pvp.w, pvp.h,
     525             :                                   0, visInfo->depth, InputOutput,
     526             :                                   visInfo->visual,
     527             :                                   CWBackPixmap | CWBorderPixel | CWEventMask |
     528          17 :                                   CWColormap | CWOverrideRedirect, &wa );
     529          17 :     XFree( visInfo );
     530          17 :     if( !drawable )
     531             :     {
     532           0 :         sendError( ERROR_GLXWINDOW_CREATEWINDOW_FAILED );
     533           0 :         return 0;
     534             :     }
     535             : 
     536          17 :     std::stringstream windowTitle;
     537          17 :     const std::string& name = getName();
     538             : 
     539          17 :     if( name.empty( ))
     540             :     {
     541           1 :         windowTitle << "Equalizer";
     542             : #ifndef NDEBUG
     543           1 :         windowTitle << " (" << getpid() << ")";
     544             : #endif
     545             :     }
     546             :     else
     547          16 :         windowTitle << name;
     548             : 
     549          17 :     XStoreName( _impl->xDisplay, drawable, windowTitle.str().c_str( ));
     550             : 
     551             :     // Register for close window request from the window manager
     552          17 :     Atom deleteAtom = XInternAtom( _impl->xDisplay, "WM_DELETE_WINDOW", False );
     553          17 :     XSetWMProtocols( _impl->xDisplay, drawable, &deleteAtom, 1 );
     554             : 
     555          17 :     return drawable;
     556             : }
     557             : 
     558           0 : bool Window::configInitGLXPBuffer( GLXFBConfig* fbConfig )
     559             : {
     560           0 :     if( !_impl->xDisplay )
     561             :     {
     562           0 :         sendError( ERROR_GLXWINDOW_NO_DISPLAY );
     563           0 :         return false;
     564             :     }
     565           0 :     if( !fbConfig )
     566             :     {
     567           0 :         sendError( ERROR_SYSTEMWINDOW_NO_PIXELFORMAT );
     568           0 :         return false;
     569             :     }
     570           0 :     if( !GLXEW_VERSION_1_3 )
     571             :     {
     572           0 :         sendError( ERROR_GLXWINDOW_GLX_1_3_REQUIRED );
     573           0 :         return false;
     574             :     }
     575             : 
     576             :     // Create PBuffer
     577           0 :     const PixelViewport& pvp = getPixelViewport();
     578             :     const int attributes[] = { GLX_PBUFFER_WIDTH, pvp.w,
     579             :                                GLX_PBUFFER_HEIGHT, pvp.h,
     580             :                                GLX_LARGEST_PBUFFER, True,
     581             :                                GLX_PRESERVED_CONTENTS, True,
     582           0 :                                0 };
     583             : 
     584             :     // TODO: Could check for GLX_SGIX_pbuffer, but the only GLX 1.2 platform at
     585             :     // hand is OS X, which does not support this extension.
     586             : 
     587           0 :     XID pbuffer = glXCreatePbuffer( _impl->xDisplay, fbConfig[ 0 ], attributes );
     588           0 :     if ( !pbuffer )
     589             :     {
     590           0 :         sendError( ERROR_GLXWINDOW_CREATEPBUFFER_FAILED );
     591           0 :         return false;
     592             :     }
     593             : 
     594           0 :     XFlush( _impl->xDisplay );
     595           0 :     setXDrawable( pbuffer );
     596             : 
     597           0 :     LBVERB << "Created X11 PBuffer " << pbuffer << std::endl;
     598           0 :     return true;
     599             : }
     600             : 
     601          34 : void Window::setXDrawable( XID drawable )
     602             : {
     603          34 :     LBASSERT( _impl->xDisplay );
     604             : 
     605          34 :     if( _impl->xDrawable == drawable )
     606           0 :         return;
     607             : 
     608          34 :     if( _impl->xDrawable )
     609          17 :         exitEventHandler();
     610             : 
     611          34 :     _impl->xDrawable = drawable;
     612             : 
     613          34 :     if( !drawable )
     614          17 :         return;
     615             : 
     616             :     const int32_t drawableType =
     617          17 :                            getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE );
     618          17 :     if( drawableType != OFF )
     619          15 :         initEventHandler();
     620             : 
     621             :     // query pixel viewport of window
     622          17 :     switch( drawableType )
     623             :     {
     624             :         case PBUFFER:
     625             :         {
     626           0 :             unsigned width = 0;
     627           0 :             unsigned height = 0;
     628           0 :             glXQueryDrawable( _impl->xDisplay, drawable, GLX_WIDTH,  &width );
     629           0 :             glXQueryDrawable( _impl->xDisplay, drawable, GLX_HEIGHT, &height );
     630             : 
     631             :             setPixelViewport(
     632           0 :                 PixelViewport( 0, 0, int32_t( width ), int32_t( height )));
     633           0 :             break;
     634             :         }
     635             :         case WINDOW:
     636             :         case AUTO:
     637             :         case UNDEFINED:
     638             :         {
     639             :             XWindowAttributes wa;
     640           2 :             XGetWindowAttributes( _impl->xDisplay, drawable, &wa );
     641             : 
     642             :             // position is relative to parent: translate to absolute coords
     643             :             ::Window root, parent, *children;
     644             :             unsigned nChildren;
     645             : 
     646             :             XQueryTree( _impl->xDisplay, drawable, &root, &parent, &children,
     647           2 :                         &nChildren );
     648           2 :             if( children != 0 )
     649           0 :                 XFree( children );
     650             : 
     651             :             int x,y;
     652             :             ::Window childReturn;
     653             :             XTranslateCoordinates( _impl->xDisplay, parent, root, wa.x, wa.y,
     654           2 :                                    &x, &y, &childReturn );
     655             : 
     656           2 :             setPixelViewport( PixelViewport( x, y, wa.width, wa.height ));
     657           2 :             break;
     658             :         }
     659             :         default:
     660           0 :             LBERROR << "Unknown drawable type " << drawableType << std::endl;
     661           0 :             LBUNIMPLEMENTED;
     662             :         case OFF:
     663             :         case FBO:
     664          15 :             LBASSERT( getPixelViewport().hasArea( ));
     665             :     }
     666             : }
     667             : 
     668          34 : void Window::setGLXContext( GLXContext context )
     669             : {
     670          34 :     _impl->glXContext = context;
     671          34 : }
     672             : 
     673          19 : GLXContext Window::getGLXContext() const
     674             : {
     675          19 :     return _impl->glXContext;
     676             : }
     677             : 
     678          42 : XID Window::getXDrawable() const
     679             : {
     680          42 :     return _impl->xDrawable;
     681             : }
     682             : 
     683        5469 : Display* Window::getXDisplay()
     684             : {
     685        5469 :     return _impl->xDisplay;
     686             : }
     687             : 
     688          83 : const GLXEWContext* Window::glxewGetContext() const
     689             : {
     690          83 :     return _impl->glxewContext;
     691             : }
     692             : 
     693          17 : void Window::_initSwapSync()
     694             : {
     695          17 :     if( getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ) == OFF )
     696           2 :         return;
     697             : 
     698          15 :     const int32_t swapSync = getIAttribute( WindowSettings::IATTR_HINT_SWAPSYNC );
     699          15 :     if( swapSync == AUTO ) // leave it alone
     700           0 :         return;
     701             : 
     702          15 :     if( GLXEW_SGI_swap_control )
     703             :     {
     704          15 :         glXSwapIntervalSGI( (swapSync < 0) ? 1 : swapSync );
     705             :     }
     706             :     else
     707           0 :         LBWARN << "GLX_SGI_swap_control not supported, ignoring window "
     708           0 :                << "swapsync hint " << IAttribute( swapSync ) << std::endl;
     709             : }
     710             : 
     711             : 
     712          17 : void Window::configExit()
     713             : {
     714          17 :     if( !_impl->xDisplay )
     715          17 :         return;
     716             : 
     717          17 :     leaveNVSwapBarrier();
     718          17 :     configExitFBO();
     719          17 :     exitGLEW();
     720             : 
     721          17 :     glXMakeCurrent( _impl->xDisplay, None, 0 );
     722             : 
     723          17 :     GLXContext context = getGLXContext();
     724          17 :     XID drawable = getXDrawable();
     725             : 
     726          17 :     setGLXContext( 0 );
     727          17 :     setXDrawable( 0 );
     728             : 
     729             :     // WAR assert in glXDestroyContext/xcb_io.c:183
     730          17 :     XSync( _impl->xDisplay, False );
     731             : 
     732          17 :     if( context )
     733          17 :         glXDestroyContext( _impl->xDisplay, context );
     734             : 
     735          17 :     if( drawable )
     736             :     {
     737          17 :         if( getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ) == PBUFFER )
     738           0 :             glXDestroyPbuffer( _impl->xDisplay, drawable );
     739             :         else
     740          17 :             XDestroyWindow( _impl->xDisplay, drawable );
     741             :     }
     742             : 
     743          17 :     LBVERB << "Destroyed GLX context and X drawable " << std::endl;
     744             : }
     745             : 
     746          71 : void Window::makeCurrent( const bool cache ) const
     747             : {
     748          71 :     LBASSERT( _impl->xDisplay );
     749          71 :     if( cache && isCurrent( ))
     750         121 :         return;
     751             : 
     752          21 :     glXMakeCurrent( _impl->xDisplay, _impl->xDrawable, _impl->glXContext );
     753          21 :     WindowIF::makeCurrent();
     754          21 :     if( _impl->glXContext )
     755             :     {
     756          21 :         EQ_GL_ERROR( "After glXMakeCurrent" );
     757             :     }
     758             : }
     759             : 
     760          19 : void Window::swapBuffers()
     761             : {
     762          19 :     LBASSERT( _impl->xDisplay );
     763          19 :     glXSwapBuffers( _impl->xDisplay, _impl->xDrawable );
     764          19 : }
     765             : 
     766           0 : void Window::joinNVSwapBarrier( const uint32_t group, const uint32_t barrier)
     767             : {
     768           0 :     if( group == 0 )
     769           0 :         return;
     770             : 
     771             : #if 1
     772           0 :     LBWARN << "Entering untested function GLXWindow::joinNVSwapBarrier"
     773           0 :            << std::endl;
     774             : 
     775           0 :     if ( !GLXEW_NV_swap_group )
     776             :     {
     777           0 :         LBWARN << "NV Swap group extension not supported" << std::endl;
     778           0 :         return;
     779             :     }
     780             : 
     781           0 :     const int screen = DefaultScreen( _impl->xDisplay );
     782           0 :     uint32_t maxBarrier = 0;
     783           0 :     uint32_t maxGroup = 0;
     784             : 
     785           0 :     glXQueryMaxSwapGroupsNV( _impl->xDisplay, screen, &maxGroup, &maxBarrier );
     786             : 
     787           0 :     if( group > maxGroup )
     788             :     {
     789           0 :         LBWARN << "Failed to initialize GLX_NV_swap_group: requested group "
     790           0 :                << group << " greater than maxGroups (" << maxGroup << ")"
     791           0 :                << std::endl;
     792           0 :         return;
     793             :     }
     794             : 
     795           0 :     if( barrier > maxBarrier )
     796             :     {
     797           0 :         LBWARN << "Failed to initialize GLX_NV_swap_group: requested barrier "
     798           0 :                << barrier << "greater than maxBarriers (" << maxBarrier << ")"
     799           0 :                << std::endl;
     800           0 :         return;
     801             :     }
     802             : 
     803           0 :     if( !glXJoinSwapGroupNV( _impl->xDisplay, _impl->xDrawable, group ))
     804             :     {
     805           0 :         LBWARN << "Failed to join swap group " << group << std::endl;
     806           0 :         return;
     807             :     }
     808             : 
     809           0 :     _impl->glXNVSwapGroup = group;
     810             : 
     811           0 :     if( !glXBindSwapBarrierNV( _impl->xDisplay, group, barrier ))
     812             :     {
     813           0 :         LBWARN << "Failed to bind swap barrier " << barrier << std::endl;
     814           0 :         return;
     815             :     }
     816             : 
     817           0 :     LBVERB << "Joined swap group " << group << " and barrier " << barrier
     818           0 :            << std::endl;
     819             : #else
     820             :     LBUNIMPLEMENTED;
     821             : #endif
     822             : }
     823             : 
     824          17 : void Window::leaveNVSwapBarrier()
     825             : {
     826          17 :     if( _impl->glXNVSwapGroup == 0 )
     827          34 :         return;
     828             : 
     829           0 :     glXBindSwapBarrierNV( _impl->xDisplay, _impl->glXNVSwapGroup, 0 );
     830           0 :     glXJoinSwapGroupNV( _impl->xDisplay, _impl->xDrawable, 0 );
     831             : 
     832           0 :     _impl->glXNVSwapGroup = 0;
     833             : }
     834             : 
     835          10 : bool Window::processEvent( const WindowEvent& event )
     836             : {
     837          10 :     switch( event.type )
     838             :     {
     839             :       case Event::WINDOW_POINTER_BUTTON_PRESS:
     840           0 :         if( getIAttribute( WindowSettings::IATTR_HINT_GRAB_POINTER ) == ON &&
     841           0 :             getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ) == WINDOW &&
     842             :             // If no other button was pressed already, capture the mouse
     843           0 :             event.pointerButtonPress.buttons == event.pointerButtonPress.button)
     844             :         {
     845             :             const unsigned int eventMask = ButtonPressMask | ButtonReleaseMask |
     846           0 :                                            ButtonMotionMask;
     847           0 :             const int result = XGrabPointer( getXDisplay(), getXDrawable(),
     848             :                                              False, eventMask, GrabModeAsync,
     849             :                                              GrabModeAsync, None, None,
     850           0 :                                              CurrentTime );
     851           0 :             if( result == GrabSuccess )
     852             :             {
     853           0 :                 WindowEvent grabEvent = event;
     854           0 :                 grabEvent.type = Event::WINDOW_POINTER_GRAB;
     855           0 :                 processEvent( grabEvent );
     856             :             }
     857             :             else
     858             :             {
     859           0 :                 LBWARN << "Failed to grab mouse: XGrabPointer returned "
     860           0 :                        << result << std::endl;
     861             :             }
     862             :         }
     863           0 :         break;
     864             : 
     865             :       case Event::WINDOW_POINTER_BUTTON_RELEASE:
     866           0 :         if( getIAttribute( WindowSettings::IATTR_HINT_GRAB_POINTER ) == ON &&
     867           0 :             getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ) == WINDOW &&
     868             :             // If no button is pressed anymore, release the mouse
     869           0 :             event.pointerButtonRelease.buttons == PTR_BUTTON_NONE )
     870             :         {
     871             :             // Call early for consistent ordering
     872           0 :             const bool result = SystemWindow::processEvent( event );
     873             : 
     874           0 :             WindowEvent ungrabEvent = event;
     875           0 :             ungrabEvent.type = Event::WINDOW_POINTER_UNGRAB;
     876           0 :             processEvent( ungrabEvent );
     877           0 :             XUngrabPointer( getXDisplay(), CurrentTime );
     878           0 :             return result;
     879             :         }
     880           0 :         break;
     881             :     }
     882          10 :     return SystemWindow::processEvent( event );
     883             : }
     884             : 
     885          15 : void Window::initEventHandler()
     886             : {
     887          15 :     LBASSERT( !_impl->glXEventHandler );
     888          15 :     _impl->glXEventHandler = new EventHandler( this );
     889             : 
     890          15 :     Display* display = getXDisplay();
     891          15 :     LBASSERT( display );
     892          15 :     if( _impl->messagePump )
     893          15 :         _impl->messagePump->register_( display );
     894             :     else
     895           0 :         LBINFO << "Using glx::EventHandler without glx::MessagePump, external "
     896           0 :                << "event dispatch assumed" << std::endl;
     897          15 : }
     898             : 
     899          17 : void Window::exitEventHandler()
     900             : {
     901          17 :     if( _impl->messagePump )
     902             :     {
     903          15 :         Display* display = getXDisplay();
     904          15 :         LBASSERT( display );
     905          15 :         _impl->messagePump->deregister( display );
     906             :     }
     907             : 
     908          17 :     delete _impl->glXEventHandler;
     909          17 :     _impl->glXEventHandler = 0;
     910          17 : }
     911             : 
     912             : }
     913          36 : }

Generated by: LCOV version 1.10