From 56900a441de1d4cc896ad1e36a44622ed1598fad Mon Sep 17 00:00:00 2001 From: Michael Meeks Date: Tue, 8 Sep 2015 11:46:13 +0100 Subject: tdf#94006 - fix OpenGLContext mis-use in several places. gltf rendering, OpenGL canvas, GL transitions & GL capable (charts) Avoid GLX operations on un-initialized contexts. Change-Id: I7f523640f66ab656896181e5c865879234f6640e --- avmedia/source/opengl/oglplayer.cxx | 15 +++++----- avmedia/source/opengl/oglplayer.hxx | 2 +- avmedia/source/opengl/oglwindow.cxx | 10 +++---- avmedia/source/opengl/oglwindow.hxx | 4 +-- canvas/source/opengl/ogl_spritedevicehelper.cxx | 33 +++++++++++----------- canvas/source/opengl/ogl_spritedevicehelper.hxx | 2 +- include/vcl/opengl/OpenGLContext.hxx | 2 +- .../OGLTrans/generic/OGLTrans_TransitionerImpl.cxx | 8 +++--- vcl/source/opengl/OpenGLContext.cxx | 11 +++++--- vcl/source/window/openglwin.cxx | 7 +++-- 10 files changed, 50 insertions(+), 44 deletions(-) diff --git a/avmedia/source/opengl/oglplayer.cxx b/avmedia/source/opengl/oglplayer.cxx index a8a9f7d56db2..c7bb7fb1adf8 100644 --- a/avmedia/source/opengl/oglplayer.cxx +++ b/avmedia/source/opengl/oglplayer.cxx @@ -28,6 +28,7 @@ namespace avmedia { namespace ogl { OGLPlayer::OGLPlayer() : Player_BASE(m_aMutex) , m_pHandle(NULL) + , m_xContext(OpenGLContext::Create()) , m_pOGLWindow(NULL) , m_bIsRendering(false) { @@ -38,7 +39,7 @@ OGLPlayer::~OGLPlayer() osl::MutexGuard aGuard(m_aMutex); if( m_pHandle ) { - m_aContext.makeCurrent(); + m_xContext->makeCurrent(); gltf_renderer_release(m_pHandle); } releaseInputFiles(); @@ -258,13 +259,13 @@ uno::Reference< media::XPlayerWindow > SAL_CALL OGLPlayer::createPlayerWindow( c } assert(pChildWindow->GetParent()); - if( !m_aContext.init(pChildWindow) ) + if( !m_xContext->init(pChildWindow) ) { SAL_WARN("avmedia.opengl", "Context initialization failed"); return uno::Reference< media::XPlayerWindow >(); } - if( !m_aContext.supportMultiSampling() ) + if( !m_xContext->supportMultiSampling() ) { SAL_WARN("avmedia.opengl", "Context does not support multisampling!"); return uno::Reference< media::XPlayerWindow >(); @@ -277,7 +278,7 @@ uno::Reference< media::XPlayerWindow > SAL_CALL OGLPlayer::createPlayerWindow( c } Size aSize = pChildWindow->GetSizePixel(); - m_aContext.setWinSize(aSize); + m_xContext->setWinSize(aSize); m_pHandle->viewport.x = 0; m_pHandle->viewport.y = 0; m_pHandle->viewport.width = aSize.Width(); @@ -294,7 +295,7 @@ uno::Reference< media::XPlayerWindow > SAL_CALL OGLPlayer::createPlayerWindow( c // The background color is white by default, but we need to separate the // OpenGL window from the main window so set background color to grey glClearColor(0.5f, 0.5f, 0.5f, 0.5f); - m_pOGLWindow = new OGLWindow(*m_pHandle, m_aContext, *pChildWindow->GetParent()); + m_pOGLWindow = new OGLWindow(*m_pHandle, m_xContext, *pChildWindow->GetParent()); return uno::Reference< media::XPlayerWindow >( m_pOGLWindow ); } @@ -304,13 +305,13 @@ uno::Reference< media::XFrameGrabber > SAL_CALL OGLPlayer::createFrameGrabber() osl::MutexGuard aGuard(m_aMutex); assert(m_pHandle); - if( !m_aContext.init() ) + if( !m_xContext->init() ) { SAL_WARN("avmedia.opengl", "Offscreen context initialization failed"); return uno::Reference< media::XFrameGrabber >(); } - if( !m_aContext.supportMultiSampling() ) + if( !m_xContext->supportMultiSampling() ) { SAL_WARN("avmedia.opengl", "Context does not support multisampling!"); return uno::Reference< media::XFrameGrabber >(); diff --git a/avmedia/source/opengl/oglplayer.hxx b/avmedia/source/opengl/oglplayer.hxx index 64f85400e071..1a90f7bf1faa 100644 --- a/avmedia/source/opengl/oglplayer.hxx +++ b/avmedia/source/opengl/oglplayer.hxx @@ -68,7 +68,7 @@ private: libgltf::glTFHandle* m_pHandle; std::vector m_vInputFiles; - OpenGLContext m_aContext; + rtl::Reference m_xContext; AutoTimer m_aTimer; OGLWindow* m_pOGLWindow; bool m_bIsRendering; diff --git a/avmedia/source/opengl/oglwindow.cxx b/avmedia/source/opengl/oglwindow.cxx index 956ce967d0b1..fe637f882c46 100644 --- a/avmedia/source/opengl/oglwindow.cxx +++ b/avmedia/source/opengl/oglwindow.cxx @@ -15,9 +15,9 @@ using namespace libgltf; namespace avmedia { namespace ogl { -OGLWindow::OGLWindow( glTFHandle& rHandle, OpenGLContext& rContext, vcl::Window& rEventHandlerParent ) +OGLWindow::OGLWindow( glTFHandle& rHandle, const rtl::Reference &rContext, vcl::Window& rEventHandlerParent ) : m_rHandle( rHandle ) - , m_rContext( rContext ) + , m_xContext( rContext ) , m_rEventHandler( rEventHandlerParent ) , m_bVisible ( false ) , m_aLastMousePos(Point(0,0)) @@ -32,7 +32,7 @@ OGLWindow::~OGLWindow() void SAL_CALL OGLWindow::update() throw (css::uno::RuntimeException, std::exception) { - m_rContext.makeCurrent(); + m_xContext->makeCurrent(); int nRet = gltf_prepare_renderer(&m_rHandle); if( nRet != 0 ) { @@ -41,7 +41,7 @@ void SAL_CALL OGLWindow::update() throw (css::uno::RuntimeException, std::except } gltf_renderer(&m_rHandle); gltf_complete_renderer(&m_rHandle); - m_rContext.swapBuffers(); + m_xContext->swapBuffers(); } sal_Bool SAL_CALL OGLWindow::setZoomLevel( css::media::ZoomLevel /*eZoomLevel*/ ) throw (css::uno::RuntimeException, std::exception) @@ -98,7 +98,7 @@ void SAL_CALL OGLWindow::setPosSize( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidt if( m_rHandle.viewport.x != nX || m_rHandle.viewport.x != nY || m_rHandle.viewport.width != nWidth || m_rHandle.viewport.height != nHeight ) { - m_rContext.setWinSize(Size(nWidth,nHeight)); + m_xContext->setWinSize(Size(nWidth,nHeight)); m_rHandle.viewport.x = nX; m_rHandle.viewport.y = nY; m_rHandle.viewport.width = nWidth; diff --git a/avmedia/source/opengl/oglwindow.hxx b/avmedia/source/opengl/oglwindow.hxx index 9abc30776418..71ca91adf03d 100644 --- a/avmedia/source/opengl/oglwindow.hxx +++ b/avmedia/source/opengl/oglwindow.hxx @@ -27,7 +27,7 @@ namespace avmedia { namespace ogl { class OGLWindow : public ::cppu::WeakImplHelper< css::media::XPlayerWindow, css::lang::XServiceInfo > { public: - OGLWindow( libgltf::glTFHandle& rHandle, OpenGLContext& rContext, vcl::Window& rEventHandlerParent ); + OGLWindow( libgltf::glTFHandle& rHandle, const rtl::Reference & rContext, vcl::Window& rEventHandlerParent ); virtual ~OGLWindow(); virtual void SAL_CALL update() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; @@ -66,7 +66,7 @@ private: DECL_LINK( CameraHandler, VclWindowEvent* ); libgltf::glTFHandle& m_rHandle; - OpenGLContext& m_rContext; + rtl::Reference m_xContext; vcl::Window& m_rEventHandler; bool m_bVisible; diff --git a/canvas/source/opengl/ogl_spritedevicehelper.cxx b/canvas/source/opengl/ogl_spritedevicehelper.cxx index 3c58b4051bb5..ab7e76493f23 100644 --- a/canvas/source/opengl/ogl_spritedevicehelper.cxx +++ b/canvas/source/opengl/ogl_spritedevicehelper.cxx @@ -85,7 +85,8 @@ namespace oglcanvas mnRadialTwoColorGradientProgram(0), mnRadialMultiColorGradientProgram(0), mnRectangularTwoColorGradientProgram(0), - mnRectangularMultiColorGradientProgram(0) + mnRectangularMultiColorGradientProgram(0), + mxContext(OpenGLContext::Create()) {} SpriteDeviceHelper::~SpriteDeviceHelper() @@ -102,8 +103,8 @@ namespace oglcanvas VCLUnoHelper::GetInterface(&rWindow), uno::UNO_QUERY_THROW) ); - maContext.requestLegacyContext(); - maContext.init(&rWindow); + mxContext->requestLegacyContext(); + mxContext->init(&rWindow); // init window context initContext(); @@ -125,7 +126,7 @@ namespace oglcanvas mnRectangularTwoColorGradientProgram = OpenGLHelper::LoadShaders("dummyVertexShader", "rectangularTwoColorGradientFragmentShader"); - maContext.makeCurrent(); + mxContext->makeCurrent(); notifySizeUpdate(rViewArea); // TODO(E3): check for GL_ARB_imaging extension @@ -138,7 +139,7 @@ namespace oglcanvas mpDevice = NULL; mpTextureCache.reset(); - if( maContext.isInitialized() ) + if( mxContext->isInitialized() ) { glDeleteProgram( mnRectangularTwoColorGradientProgram ); glDeleteProgram( mnRectangularMultiColorGradientProgram ); @@ -151,11 +152,11 @@ namespace oglcanvas geometry::RealSize2D SpriteDeviceHelper::getPhysicalResolution() { - if( !maContext.isInitialized() ) + if( !mxContext->isInitialized() ) return ::canvas::tools::createInfiniteSize2D(); // we're disposed // Map a one-by-one millimeter box to pixel - SystemChildWindow* pChildWindow = maContext.getChildWindow(); + SystemChildWindow* pChildWindow = mxContext->getChildWindow(); const MapMode aOldMapMode( pChildWindow->GetMapMode() ); pChildWindow->SetMapMode( MapMode(MAP_MM) ); const Size aPixelSize( pChildWindow->LogicToPixel(Size(1,1)) ); @@ -166,11 +167,11 @@ namespace oglcanvas geometry::RealSize2D SpriteDeviceHelper::getPhysicalSize() { - if( !maContext.isInitialized() ) + if( !mxContext->isInitialized() ) return ::canvas::tools::createInfiniteSize2D(); // we're disposed // Map the pixel dimensions of the output window to millimeter - SystemChildWindow* pChildWindow = maContext.getChildWindow(); + SystemChildWindow* pChildWindow = mxContext->getChildWindow(); const MapMode aOldMapMode( pChildWindow->GetMapMode() ); pChildWindow->SetMapMode( MapMode(MAP_MM) ); const Size aLogSize( pChildWindow->PixelToLogic(pChildWindow->GetOutputSizePixel()) ); @@ -271,13 +272,13 @@ namespace oglcanvas bool SpriteDeviceHelper::showBuffer( bool bIsVisible, bool /*bUpdateAll*/ ) { // hidden or disposed? - if( !bIsVisible || !maContext.isInitialized() || !mpSpriteCanvas ) + if( !bIsVisible || !mxContext->isInitialized() || !mpSpriteCanvas ) return false; if( !activateWindowContext() ) return false; - SystemChildWindow* pChildWindow = maContext.getChildWindow(); + SystemChildWindow* pChildWindow = mxContext->getChildWindow(); const ::Size& rOutputSize = pChildWindow->GetSizePixel(); initTransformation(rOutputSize); @@ -326,7 +327,7 @@ namespace oglcanvas unx::glXWaitGL(); XSync( reinterpret_cast(mpDisplay), false ); */ - maContext.swapBuffers(); + mxContext->swapBuffers(); // flush texture cache, such that it does not build up // indefinitely. @@ -350,7 +351,7 @@ namespace oglcanvas uno::Any SpriteDeviceHelper::getDeviceHandle() const { - const SystemChildWindow* pChildWindow = maContext.getChildWindow(); + const SystemChildWindow* pChildWindow = mxContext->getChildWindow(); return uno::makeAny( reinterpret_cast< sal_Int64 >(pChildWindow) ); } @@ -369,9 +370,9 @@ namespace oglcanvas void SpriteDeviceHelper::notifySizeUpdate( const awt::Rectangle& rBounds ) { - if( maContext.isInitialized() ) + if( mxContext->isInitialized() ) { - SystemChildWindow* pChildWindow = maContext.getChildWindow(); + SystemChildWindow* pChildWindow = mxContext->getChildWindow(); pChildWindow->setPosSizePixel( 0,0,rBounds.Width,rBounds.Height); } @@ -506,7 +507,7 @@ namespace oglcanvas bool SpriteDeviceHelper::activateWindowContext() { - maContext.makeCurrent(); + mxContext->makeCurrent(); return true; } diff --git a/canvas/source/opengl/ogl_spritedevicehelper.hxx b/canvas/source/opengl/ogl_spritedevicehelper.hxx index ba85f542fbc5..2a9914506aeb 100644 --- a/canvas/source/opengl/ogl_spritedevicehelper.hxx +++ b/canvas/source/opengl/ogl_spritedevicehelper.hxx @@ -140,7 +140,7 @@ namespace oglcanvas unsigned int mnRectangularTwoColorGradientProgram; unsigned int mnRectangularMultiColorGradientProgram; - OpenGLContext maContext; + rtl::Reference mxContext; }; } diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx index b520d2c6434a..0addfcb848f7 100644 --- a/include/vcl/opengl/OpenGLContext.hxx +++ b/include/vcl/opengl/OpenGLContext.hxx @@ -169,8 +169,8 @@ struct GLWindow class VCL_DLLPUBLIC OpenGLContext { friend class OpenGLTests; -public: OpenGLContext(); +public: static rtl::Reference Create(); ~OpenGLContext(); void acquire() { mnRefCount++; } diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx index 78f897519c4f..5ac45f376eb9 100644 --- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx +++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx @@ -228,7 +228,7 @@ private: void impl_finishTransition(); private: - boost::shared_ptr mpContext; + rtl::Reference mpContext; /** OpenGL handle to the leaving slide's texture */ @@ -368,7 +368,7 @@ bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presenta sal_Int64 aVal = 0; aDeviceParams[1] >>= aVal; - mpContext = boost::make_shared(); + mpContext = OpenGLContext::Create(); mpContext->requestLegacyContext(); if( !mpContext->init( reinterpret_cast< vcl::Window* >( aVal ) ) ) @@ -1323,7 +1323,7 @@ void OGLTransitionerImpl::impl_dispose() { impl_finishTransition(); disposeTextures(); - mpContext.reset(); + mpContext.clear(); } // we are about to be disposed (someone call dispose() on us) @@ -1350,7 +1350,7 @@ void OGLTransitionerImpl::disposing() #endif #if defined( UNX ) && !defined( MACOSX ) - if( mbRestoreSync && bool(mpContext) ) { + if( mbRestoreSync && bool(mpContext.is()) ) { // try to reestablish synchronize state char* sal_synchronize = getenv("SAL_SYNCHRONIZE"); XSynchronize( mpContext->getOpenGLWindow().dpy, sal_synchronize && *sal_synchronize == '1' ); diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx index d070e3fb3b6b..432241f03817 100644 --- a/vcl/source/opengl/OpenGLContext.cxx +++ b/vcl/source/opengl/OpenGLContext.cxx @@ -1362,11 +1362,14 @@ void OpenGLContext::makeCurrent() TempErrorHandler aErrorHandler(m_aGLWin.dpy, unxErrorHandler); #endif - GLXDrawable nDrawable = mbPixmap ? m_aGLWin.glPix : m_aGLWin.win; - if (!glXMakeCurrent( m_aGLWin.dpy, nDrawable, m_aGLWin.ctx )) + if (m_aGLWin.dpy) { - SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent failed on drawable " << nDrawable << " pixmap? " << mbPixmap); - return; + GLXDrawable nDrawable = mbPixmap ? m_aGLWin.glPix : m_aGLWin.win; + if (!glXMakeCurrent( m_aGLWin.dpy, nDrawable, m_aGLWin.ctx )) + { + SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent failed on drawable " << nDrawable << " pixmap? " << mbPixmap); + return; + } } #endif diff --git a/vcl/source/window/openglwin.cxx b/vcl/source/window/openglwin.cxx index 46628c6d7929..e07937538d7c 100644 --- a/vcl/source/window/openglwin.cxx +++ b/vcl/source/window/openglwin.cxx @@ -17,18 +17,19 @@ class OpenGLWindowImpl public: explicit OpenGLWindowImpl(vcl::Window* pWindow); ~OpenGLWindowImpl() { mxChildWindow.disposeAndClear(); } - OpenGLContext& getContext() { return maContext;} + OpenGLContext& getContext() { return *mxContext.get(); } private: - OpenGLContext maContext; + rtl::Reference mxContext; VclPtr mxChildWindow; }; OpenGLWindowImpl::OpenGLWindowImpl(vcl::Window* pWindow) + : mxContext(OpenGLContext::Create()) { SystemWindowData aData = OpenGLContext::generateWinData(pWindow, false); mxChildWindow.reset(VclPtr::Create(pWindow, 0, &aData)); mxChildWindow->Show(); - maContext.init(mxChildWindow.get()); + mxContext->init(mxChildWindow.get()); pWindow->SetMouseTransparent(false); } -- cgit