LCOV - code coverage report
Current view: top level - eq - glWindow.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 2 170 1.2 %
Date: 2016-09-29 05:02:09 Functions: 2 26 7.7 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2016, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                          Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *                          Makhinya Maxim
       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 "glWindow.h"
      21             : 
      22             : #include "error.h"
      23             : #include "gl.h"
      24             : #include "global.h"
      25             : #include "pipe.h"
      26             : 
      27             : #include <eq/fabric/drawableConfig.h>
      28             : #include <eq/util/frameBufferObject.h>
      29             : #include <lunchbox/os.h>
      30             : #include <lunchbox/perThread.h>
      31             : 
      32             : template
      33             : void lunchbox::perThreadNoDelete< const eq::GLWindow >( const eq::GLWindow* );
      34             : 
      35             : namespace eq
      36             : {
      37             : namespace
      38             : {
      39          14 : lunchbox::PerThread< const GLWindow, lunchbox::perThreadNoDelete > _current;
      40             : }
      41             : namespace detail
      42             : {
      43             : class GLWindow
      44             : {
      45             : public:
      46           0 :     GLWindow()
      47             :         : glewContext( nullptr )
      48             :         , fbo( nullptr )
      49           0 :         , fboMultiSample( nullptr )
      50           0 :     {}
      51             : 
      52           0 :     ~GLWindow()
      53             :     {
      54           0 :         delete glewContext;
      55           0 :     }
      56             : 
      57             :     /** Extended OpenGL function entries when window has a context. */
      58             :     GLEWContext* glewContext;
      59             : 
      60             :     /** Frame buffer object for FBO drawables. */
      61             :     util::FrameBufferObject* fbo;
      62             : 
      63             :     util::FrameBufferObject* fboMultiSample;
      64             : };
      65             : }
      66             : 
      67           0 : GLWindow::GLWindow( NotifierInterface& parent, const WindowSettings& settings )
      68             :     : SystemWindow( parent, settings )
      69           0 :     , _impl( new detail::GLWindow )
      70             : {
      71           0 : }
      72             : 
      73           0 : GLWindow::~GLWindow()
      74             : {
      75           0 :     if( _current == this )
      76           0 :         _current = 0;
      77           0 :     delete _impl;
      78           0 : }
      79             : 
      80           0 : void GLWindow::makeCurrent( const bool useCache ) const
      81             : {
      82           0 :     if( useCache && _current == this )
      83           0 :         return;
      84             : 
      85           0 :     bindFrameBuffer();
      86           0 :     _current = this;
      87             : }
      88             : 
      89           0 : void GLWindow::doneCurrent() const
      90             : {
      91           0 :     if( !_current )
      92           0 :         return;
      93             : 
      94           0 :     if( _impl->fbo )
      95           0 :         _impl->fbo->unbind();
      96           0 :     _current = 0;
      97             : }
      98             : 
      99           0 : bool GLWindow::isCurrent() const
     100             : {
     101           0 :     return _current == this;
     102             : }
     103             : 
     104           0 : void GLWindow::initGLEW()
     105             : {
     106           0 :     if( _impl->glewContext )
     107           0 :         return;
     108             : 
     109           0 :     _impl->glewContext = new GLEWContext;
     110             : 
     111             : #ifdef __linux__
     112             :     // http://sourceforge.net/p/glew/patches/40/
     113           0 :     glewExperimental = true;
     114             : #endif
     115             : 
     116           0 :     const GLenum result = glewInit();
     117           0 :     glGetError(); // eat GL errors from buggy glew implementation
     118           0 :     if( result == GLEW_OK )
     119           0 :         return;
     120             : 
     121           0 :     LBWARN << "GLEW initialization failed: " << std::endl;
     122           0 :     delete _impl->glewContext;
     123           0 :     _impl->glewContext = nullptr;
     124             : }
     125             : 
     126           0 : void GLWindow::exitGLEW()
     127             : {
     128           0 :     delete _impl->glewContext;
     129           0 :     _impl->glewContext = nullptr;
     130           0 : }
     131             : 
     132           0 : const util::FrameBufferObject* GLWindow::getFrameBufferObject() const
     133             : {
     134           0 :     return _impl->fbo;
     135             : }
     136             : 
     137           0 : util::FrameBufferObject* GLWindow::getFrameBufferObject()
     138             : {
     139           0 :     return _impl->fbo;
     140             : }
     141             : 
     142           0 : const GLEWContext* GLWindow::glewGetContext() const
     143             : {
     144           0 :     return _impl->glewContext;
     145             : }
     146             : 
     147           0 : GLEWContext* GLWindow::glewGetContext()
     148             : {
     149           0 :     return _impl->glewContext;
     150             : }
     151             : 
     152           0 : bool GLWindow::configInitFBO()
     153             : {
     154           0 :     if( !_impl->glewContext || !GLEW_EXT_framebuffer_object )
     155             :     {
     156           0 :         sendError( ERROR_FBO_UNSUPPORTED );
     157           0 :         return false;
     158             :     }
     159             : 
     160           0 :     if( !_createFBO( _impl->fbo, 0 ))
     161           0 :         return false;
     162             : 
     163           0 :     const int samplesSize = getIAttribute(WindowSettings::IATTR_PLANES_SAMPLES);
     164           0 :     if( samplesSize <= 0 )
     165           0 :         return true;
     166             : 
     167           0 :     return _createFBO( _impl->fboMultiSample, samplesSize );
     168             : }
     169             : 
     170           0 : void GLWindow::configExitFBO()
     171             : {
     172           0 :     _destroyFBO( _impl->fboMultiSample );
     173           0 :     _destroyFBO( _impl->fbo );
     174           0 : }
     175             : 
     176           0 : bool GLWindow::_createFBO( util::FrameBufferObject*& fbo, const int samplesSize)
     177             : {
     178           0 :     const PixelViewport& pvp = getPixelViewport();
     179           0 :     const GLuint colorFormat = getColorFormat();
     180             : 
     181           0 :     int depthSize = getIAttribute( WindowSettings::IATTR_PLANES_DEPTH );
     182           0 :     if( depthSize == AUTO )
     183           0 :         depthSize = 24;
     184             : 
     185           0 :     int stencilSize = getIAttribute( WindowSettings::IATTR_PLANES_STENCIL );
     186           0 :     if( stencilSize == AUTO )
     187           0 :         stencilSize = 1;
     188             : 
     189             :     fbo = new util::FrameBufferObject( _impl->glewContext,
     190             :                                        samplesSize ? GL_TEXTURE_2D_MULTISAMPLE
     191           0 :                                                   : GL_TEXTURE_RECTANGLE_ARB );
     192             :     Error error = fbo->init( pvp.w, pvp.h, colorFormat, depthSize,
     193           0 :                              stencilSize, samplesSize );
     194           0 :     if( !error )
     195           0 :         return true;
     196             : 
     197           0 :     if( getIAttribute( WindowSettings::IATTR_PLANES_STENCIL ) == AUTO )
     198           0 :         error = fbo->init( pvp.w, pvp.h, colorFormat, depthSize, 0,
     199           0 :                            samplesSize );
     200             : 
     201           0 :     if( !error )
     202           0 :         return true;
     203             : 
     204           0 :     sendError( error.getCode( ));
     205           0 :     delete fbo;
     206           0 :     fbo = 0;
     207           0 :     return false;
     208             : }
     209             : 
     210           0 : void GLWindow::_destroyFBO( util::FrameBufferObject*& fbo )
     211             : {
     212           0 :     if( !fbo )
     213           0 :         return;
     214             : 
     215           0 :     fbo->exit();
     216           0 :     delete fbo;
     217           0 :     fbo = 0;
     218             : }
     219             : 
     220           0 : void GLWindow::bindFrameBuffer() const
     221             : {
     222           0 :    if( !_impl->glewContext )
     223           0 :        return;
     224             : 
     225           0 :    if( _impl->fbo )
     226           0 :        _impl->fbo->bind();
     227           0 :    else if( GLEW_EXT_framebuffer_object )
     228           0 :        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
     229             : }
     230             : 
     231           0 : void GLWindow::bindDrawFrameBuffer() const
     232             : {
     233           0 :     if( !_impl->glewContext )
     234           0 :         return;
     235             : 
     236           0 :     if( _impl->fboMultiSample )
     237           0 :         _impl->fboMultiSample->bind( GL_DRAW_FRAMEBUFFER_EXT );
     238           0 :     else if( _impl->fbo )
     239           0 :         _impl->fbo->bind( GL_DRAW_FRAMEBUFFER_EXT );
     240           0 :     else if( GLEW_EXT_framebuffer_object )
     241           0 :         glBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, 0 );
     242             : }
     243             : 
     244           0 : void GLWindow::updateFrameBuffer() const
     245             : {
     246           0 :     if( !_impl->glewContext || !_impl->fboMultiSample )
     247           0 :         return;
     248             : 
     249           0 :     _impl->fboMultiSample->bind( GL_READ_FRAMEBUFFER_EXT );
     250           0 :     _impl->fbo->bind( GL_DRAW_FRAMEBUFFER_EXT );
     251           0 :     const PixelViewport& pvp = getPixelViewport();
     252           0 :     EQ_GL_CALL( glBlitFramebuffer( 0, 0, pvp.w, pvp.h,
     253             :                                    0, 0, pvp.w, pvp.h,
     254             :                                    GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
     255             :                                    GL_STENCIL_BUFFER_BIT, GL_NEAREST ));
     256             : }
     257             : 
     258           0 : void GLWindow::flush()
     259             : {
     260           0 :     glFlush();
     261           0 : }
     262             : 
     263           0 : void GLWindow::finish()
     264             : {
     265           0 :     glFinish();
     266           0 : }
     267             : 
     268             : #define TEST_GLEW_VERSION( MAJOR, MINOR ) \
     269             :     if( GLEW_VERSION_ ## MAJOR ## _ ## MINOR )  \
     270             :         dc.glewGLVersion = MAJOR ## . ## MINOR ## f;    \
     271             : 
     272           0 : void GLWindow::queryDrawableConfig( DrawableConfig& dc )
     273             : {
     274           0 :     dc = DrawableConfig();
     275             : 
     276             :     // GL version
     277           0 :     const char* glVersion = (const char*)glGetString( GL_VERSION );
     278           0 :     if( !glVersion ) // most likely no context
     279             :     {
     280           0 :         LBWARN << "glGetString(GL_VERSION) returned 0, assuming GL version 1.1"
     281           0 :                << std::endl;
     282           0 :         dc.glVersion = 1.1f;
     283             :     }
     284             :     else
     285           0 :         dc.glVersion = static_cast<float>( std::atof( glVersion ));
     286             : 
     287           0 :     if( dc.glVersion >= 3.2f )
     288             :     {
     289             :         GLint mask;
     290           0 :         EQ_GL_CALL( glGetIntegerv( GL_CONTEXT_PROFILE_MASK, &mask ));
     291           0 :         dc.coreProfile = mask & GL_CONTEXT_CORE_PROFILE_BIT;
     292             :     }
     293             : 
     294           0 :     TEST_GLEW_VERSION( 1, 1 );
     295           0 :     TEST_GLEW_VERSION( 1, 2 );
     296           0 :     TEST_GLEW_VERSION( 1, 3 );
     297           0 :     TEST_GLEW_VERSION( 1, 4 );
     298           0 :     TEST_GLEW_VERSION( 1, 5 );
     299           0 :     TEST_GLEW_VERSION( 2, 0 );
     300           0 :     TEST_GLEW_VERSION( 2, 1 );
     301           0 :     TEST_GLEW_VERSION( 3, 0 );
     302           0 :     TEST_GLEW_VERSION( 3, 1 );
     303           0 :     TEST_GLEW_VERSION( 3, 2 );
     304           0 :     TEST_GLEW_VERSION( 3, 3 );
     305           0 :     TEST_GLEW_VERSION( 4, 0 );
     306           0 :     TEST_GLEW_VERSION( 4, 1 );
     307           0 :     TEST_GLEW_VERSION( 4, 2 );
     308           0 :     TEST_GLEW_VERSION( 4, 3 );
     309             : #ifdef GLEW_VERSION_4_5
     310             :     TEST_GLEW_VERSION( 4, 4 );
     311             :     TEST_GLEW_VERSION( 4, 5 );
     312             : #endif
     313             : 
     314             :     // Framebuffer capabilities
     315             :     GLboolean result;
     316           0 :     EQ_GL_CALL( glGetBooleanv( GL_STEREO, &result ));
     317           0 :     dc.stereo = result;
     318             : 
     319           0 :     EQ_GL_CALL( glGetBooleanv( GL_DOUBLEBUFFER, &result ));
     320           0 :     dc.doublebuffered = result;
     321             : 
     322           0 :     if( dc.coreProfile )
     323             :     {
     324           0 :         if( getFrameBufferObject( ))
     325             :         {
     326             :             glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER,
     327             :                 GL_DEPTH_STENCIL_ATTACHMENT,
     328           0 :                 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &dc.stencilBits );
     329             :             // eat GL error if no stencil attachment; should return '0' bits
     330             :             // according to spec, but gives GL_INVALID_OPERATION
     331           0 :             glGetError();
     332           0 :             EQ_GL_CALL( glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER,
     333             :                 GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
     334             :                                                                &dc.colorBits ));
     335           0 :             EQ_GL_CALL( glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER,
     336             :                 GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
     337             :                                                                &dc.alphaBits ));
     338             :         }
     339             :         else
     340             :         {
     341           0 :             EQ_GL_CALL( glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER,
     342             :                 GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
     343             :                                                                &dc.stencilBits ));
     344           0 :             EQ_GL_CALL( glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER,
     345             :                 GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
     346             :                                                                &dc.colorBits ));
     347           0 :             EQ_GL_CALL( glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER,
     348             :                 GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
     349             :                                                                &dc.alphaBits ));
     350             :         }
     351             :     }
     352             :     else
     353             :     {
     354           0 :         EQ_GL_CALL( glGetIntegerv( GL_STENCIL_BITS, &dc.stencilBits ));
     355           0 :         EQ_GL_CALL( glGetIntegerv( GL_RED_BITS, &dc.colorBits ));
     356           0 :         EQ_GL_CALL( glGetIntegerv( GL_ALPHA_BITS, &dc.alphaBits ));
     357           0 :         EQ_GL_CALL( glGetIntegerv( GL_ACCUM_RED_BITS, &dc.accumBits ));
     358             :     }
     359             : 
     360           0 :     dc.accumBits *= 4;
     361           0 :     LBDEBUG << "Window drawable config: " << dc << std::endl;
     362           0 : }
     363             : 
     364          42 : }

Generated by: LCOV version 1.11