LCOV - code coverage report
Current view: top level - eq/glx - window.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 1 443 0.2 %
Date: 2016-09-29 05:02:09 Functions: 2 30 6.7 %

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

Generated by: LCOV version 1.11