From 717c023c984e7810395751d5b0e25e1356403142 Mon Sep 17 00:00:00 2001 From: Michael Meeks Date: Fri, 4 Dec 2015 01:50:05 +0000 Subject: Implement idle GL flushing. Change-Id: I1d3102149cba902e640cbd9bbf47ca66deedbe00 --- vcl/inc/openglgdiimpl.hxx | 11 ++++++++++- vcl/opengl/gdiimpl.cxx | 46 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index d28074364be1..fad5a07b6aef 100644 --- a/vcl/inc/openglgdiimpl.hxx +++ b/vcl/inc/openglgdiimpl.hxx @@ -52,6 +52,8 @@ struct TextureCombo std::unique_ptr mpMask; }; +class OpenGLFlushIdle; + class VCL_DLLPUBLIC OpenGLSalGraphicsImpl : public SalGraphicsImpl { friend class OpenGLTests; @@ -73,6 +75,9 @@ protected: /// Is it someone else's context we shouldn't be fiddling with ? static bool IsForeignContext(const rtl::Reference &xContext); + /// This idle handler is used to swap buffers after rendering. + OpenGLFlushIdle *mpFlush; + // clipping vcl::Region maClipRegion; bool mbUseScissor; @@ -347,8 +352,12 @@ public: virtual bool drawGradient(const tools::PolyPolygon& rPolygon, const Gradient& rGradient) override; - /// flush contents of the back-buffer to the screen & swap. + /// queue an idle flush of contents of the back-buffer to the screen virtual void flush() override; + +public: + /// do flush of contents of the back-buffer to the screen & swap. + void doFlush(); }; #endif diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 31813fb7a0af..13ba0c89bb82 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -39,12 +39,33 @@ #include +class OpenGLFlushIdle : public Idle +{ + OpenGLSalGraphicsImpl *m_pImpl; +public: + OpenGLFlushIdle( OpenGLSalGraphicsImpl *pImpl ) + : Idle( "gl idle swap" ) + , m_pImpl( pImpl ) + { + SetPriority( SchedulerPriority::HIGHEST ); + } + ~OpenGLFlushIdle() + { + } + virtual void Invoke() override + { + m_pImpl->doFlush(); + Stop(); + } +}; + OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGraphics& rParent, SalGeometryProvider *pProvider) : mpContext(nullptr) , mrParent(rParent) , mpProvider(pProvider) , mpFramebuffer(nullptr) , mpProgram(nullptr) + , mpFlush(new OpenGLFlushIdle(this)) , mbUseScissor(false) , mbUseStencil(false) , mnLineColor(SALCOLOR_NONE) @@ -61,13 +82,10 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGraphics& rParent, SalGeometryPr OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl() { -#ifdef DBG_UTIL - if( !IsOffscreen() ) - { - // Check that all SalGraphics have flushed before being destroyed - assert( mnDrawCountAtFlush == mnDrawCount ); - } -#endif + if( !IsOffscreen() && mnDrawCountAtFlush != mnDrawCount ) + VCL_GL_INFO( "Destroying un-flushed on-screen graphics" ); + + delete mpFlush; ReleaseContext(); } @@ -1942,6 +1960,20 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly, } void OpenGLSalGraphicsImpl::flush() +{ + if( IsOffscreen() ) + return; + + // outside of the application's event loop (e.g. IntroWindow) + // nothing would trigger paint event handling + // => fall back to synchronous painting + if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) + doFlush(); + else if( !mpFlush->IsActive() ) + mpFlush->Start(); +} + +void OpenGLSalGraphicsImpl::doFlush() { if( IsOffscreen() ) return; -- cgit