[Libreoffice-commits] core.git: Branch 'private/mmeeks/opengl-backbuffer2' - 21 commits - chart2/source filter/source include/tools lotuswordpro/source sc/source sd/qa starmath/inc starmath/source sw/source unusedcode.easy unusedcode.exclude vcl/inc vcl/opengl vcl/qa vcl/README.vars vcl/source vcl/unx

Michael Meeks michael.meeks at collabora.com
Thu Dec 10 03:52:26 PST 2015


Rebased ref, commits from common ancestor:
commit b89920a6594c2d3271f4ab6877ec903d36594d2d
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Fri Nov 13 12:00:59 2015 +0000

    tdf#93529 - move to a Mac-like double-buffered OpenGL model.
    
    This moves us to always rendering to an off-screen texture, and then
    (at idle) blitting this to the screen & swapping buffers. Ideally we
    should never see any rendering, or flicker again with this approach.
    
    Several fixes are included:
       + avoid multiple OpenGL contexts being created for the same window,
         created excessive flicker problems.
       + de-virtualize UseContext - which context we use is less critical.
       + kill 'mbOffscreen' distinction - all VCL rendering is offscreen.
       + implement 'doFlush' and high priority idle flushing.
       + bind stencil buffer for clipping vs. textures - fixing complex
         clopping when rendering to virtual-devices, and off-screen.
       + document environment. variables.
       + use white as default background glClear color, but red for debug.
    
    Change-Id: I6be08595b6c8deb7e6db0dbd81308b2c97d2b4ff

diff --git a/vcl/README.vars b/vcl/README.vars
index 4f62333..bf85485 100644
--- a/vcl/README.vars
+++ b/vcl/README.vars
@@ -21,6 +21,8 @@ EMF_PLUS_DISABLE - use EMF rendering and ignore EMF+ specifics
 OpenGL
 ------
 SAL_FORCEGL - force enable OpenGL
+SAL_GL_NO_SWAP - disable buffer swapping if set (should show nothing)
+SAL_GL_SLEEP_ON_SWAP - sleep for half a second on each swap-buffers.
 SAL_WITHOUT_WIDGET_CACHE - disable LRU caching of native widget texutres
 SAL_DISABLE_GLYPH_CACHING - don't render glyphs through OpenGL textures
 SAL_DISABLE_GL_WATCHDOG - don't start the thread that watches for broken GL drivers
diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx
index f67b334..e57aa9e 100644
--- a/vcl/inc/opengl/texture.hxx
+++ b/vcl/inc/opengl/texture.hxx
@@ -37,6 +37,8 @@ public:
     int    mnWidth;
     int    mnHeight;
     GLenum mnFilter;
+    GLuint mnOptStencil;
+    bool   mbHasOptStencil;
 
     std::unique_ptr<std::vector<int>> mpSlotReferences;
     int mnFreeSlots;
@@ -76,7 +78,8 @@ public:
     }
 
     bool InitializeSlots(int nSlotSize);
-    int FindFreeSlot();
+    int  FindFreeSlot();
+    GLuint AddStencil();
 };
 
 class VCL_DLLPUBLIC OpenGLTexture
@@ -110,6 +113,9 @@ public:
     void            Bind();
     void            Unbind();
     void            Read( GLenum nFormat, GLenum nType, sal_uInt8* pData );
+    GLuint          AddStencil();
+    bool            HasStencil() const;
+    GLuint          StencilId() const;
 
     void            SaveToFile(const OUString& rFileName);
 
diff --git a/vcl/inc/opengl/win/gdiimpl.hxx b/vcl/inc/opengl/win/gdiimpl.hxx
index ecefede..8102d2e 100644
--- a/vcl/inc/opengl/win/gdiimpl.hxx
+++ b/vcl/inc/opengl/win/gdiimpl.hxx
@@ -31,7 +31,6 @@ public:
 
 protected:
     virtual rtl::Reference<OpenGLContext> CreateWinContext() override;
-    virtual bool UseContext( const rtl::Reference<OpenGLContext> &pContext ) override;
 
     bool RenderTextureCombo(TextureCombo& rCombo, int nX, int nY);
 
diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx
index f07468d..eccd0ef 100644
--- a/vcl/inc/opengl/x11/gdiimpl.hxx
+++ b/vcl/inc/opengl/x11/gdiimpl.hxx
@@ -29,7 +29,6 @@ public:
 
 protected:
     virtual rtl::Reference<OpenGLContext> CreateWinContext() override;
-    virtual bool UseContext( const rtl::Reference<OpenGLContext> &pContext ) override;
 
     bool RenderPixmap(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY, TextureCombo& rCombo);
 
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 667b2ec..b2969cc 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -52,12 +52,20 @@ struct TextureCombo
     std::unique_ptr<OpenGLTexture> mpMask;
 };
 
+class OpenGLFlushIdle;
+
 class VCL_DLLPUBLIC OpenGLSalGraphicsImpl : public SalGraphicsImpl
 {
     friend class OpenGLTests;
 protected:
 
+    /// This context is solely for blitting @maOffscreenTex
+    rtl::Reference<OpenGLContext> mpWindowContext;
+
+    /// This context is whatever is most convenient to render
+    /// to @maOffscreenTex with.
     rtl::Reference<OpenGLContext> mpContext;
+
     SalGraphics& mrParent;
     /// Pointer to the SalFrame or SalVirtualDevice
     SalGeometryProvider* mpProvider;
@@ -67,18 +75,27 @@ protected:
     /// Is it someone else's context we shouldn't be fiddling with ?
     static bool IsForeignContext(const rtl::Reference<OpenGLContext> &xContext);
 
+    /// This idle handler is used to swap buffers after rendering.
+    OpenGLFlushIdle *mpFlush;
+
     // clipping
     vcl::Region maClipRegion;
     bool mbUseScissor;
     bool mbUseStencil;
 
-    bool mbOffscreen;
+    /**
+     * All rendering happens to this off-screen texture. For
+     * non-virtual devices, ie. windows - we will blit it and
+     * swapBuffers later.
+     */
     OpenGLTexture maOffscreenTex;
 
     SalColor mnLineColor;
     SalColor mnFillColor;
 #ifdef DBG_UTIL
     bool mProgramIsSolidColor;
+    sal_uInt32 mnDrawCount;
+    sal_uInt32 mnDrawCountAtFlush;
 #endif
     SalColor mProgramSolidColor;
     double mProgramSolidTransparency;
@@ -131,7 +148,10 @@ public:
     // get the height of the device
     GLfloat GetHeight() const { return mpProvider ? mpProvider->GetHeight() : 1; }
 
-    // check whether this instance is used for offscreen rendering
+    /**
+     * check whether this instance is used for offscreen (Virtual Device)
+     * rendering ie. does it need its own context.
+     */
     bool IsOffscreen() const { return mpProvider == nullptr || mpProvider->IsOffScreen(); }
 
     // operations to do before painting
@@ -144,14 +164,18 @@ protected:
     bool AcquireContext();
     bool ReleaseContext();
 
-    // retrieve the default context for offscreen rendering
+    /// retrieve the default context for offscreen rendering
     static rtl::Reference<OpenGLContext> GetDefaultContext();
 
-    // create a new context for window rendering
+    /// create a new context for rendering to the underlying window
     virtual rtl::Reference<OpenGLContext> CreateWinContext() = 0;
 
-    // check whether the given context can be used by this instance
-    virtual bool UseContext( const rtl::Reference<OpenGLContext> &pContext ) = 0;
+    /// check whether the given context can be used for off-screen rendering
+    bool UseContext( const rtl::Reference<OpenGLContext> &pContext )
+    {
+        return pContext->isInitialized() &&  // not released by the OS etc.
+               IsForeignContext( pContext ); // a genuine VCL context.
+    }
 
 public:
     OpenGLSalGraphicsImpl(SalGraphics& pParent, SalGeometryProvider *pProvider);
@@ -328,8 +352,12 @@ public:
 
     virtual bool drawGradient(const tools::PolyPolygon& rPolygon, const Gradient& rGradient) override;
 
-    virtual OpenGLContext *beginPaint() override;
-private:
+    /// queue an idle flush of contents of the back-buffer to the screen
+    void flush();
+
+public:
+    /// do flush of contents of the back-buffer to the screen & swap.
+    void doFlush();
 };
 
 #endif
diff --git a/vcl/opengl/framebuffer.cxx b/vcl/opengl/framebuffer.cxx
index c009ccb..464662d 100644
--- a/vcl/opengl/framebuffer.cxx
+++ b/vcl/opengl/framebuffer.cxx
@@ -72,6 +72,16 @@ void OpenGLFramebuffer::AttachTexture( const OpenGLTexture& rTexture )
     mnHeight = rTexture.GetHeight();
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mnAttachedTexture, 0);
     CHECK_GL_ERROR();
+
+    GLuint nStencil = rTexture.StencilId();
+    if( nStencil )
+    {
+        VCL_GL_INFO( "Attaching stencil " << nStencil << " to framebuffer " << (int)mnId );
+        glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                   GL_RENDERBUFFER, nStencil );
+        CHECK_GL_ERROR();
+    }
+
     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
     CHECK_GL_ERROR();
     if (status != GL_FRAMEBUFFER_COMPLETE)
@@ -87,6 +97,11 @@ void OpenGLFramebuffer::DetachTexture()
         mnAttachedTexture = 0;
         glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0 );
         CHECK_GL_ERROR();
+
+        // FIXME: we could make this conditional on having a stencil ?
+        glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                   GL_RENDERBUFFER, 0 );
+        CHECK_GL_ERROR();
     }
 }
 
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 3771d3c..05994dd 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -37,19 +37,43 @@
 
 #include <vector>
 
+#include <stdlib.h>
+
+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)
-    , mbOffscreen(false)
     , mnLineColor(SALCOLOR_NONE)
     , mnFillColor(SALCOLOR_NONE)
 #ifdef DBG_UTIL
     , mProgramIsSolidColor(false)
+    , mnDrawCount(0)
+    , mnDrawCountAtFlush(0)
 #endif
     , mProgramSolidColor(SALCOLOR_NONE)
     , mProgramSolidTransparency(0.0)
@@ -58,6 +82,11 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGraphics& rParent, SalGeometryPr
 
 OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl()
 {
+    if( !IsOffscreen() && mnDrawCountAtFlush != mnDrawCount )
+        VCL_GL_INFO( "Destroying un-flushed on-screen graphics" );
+
+    delete mpFlush;
+
     ReleaseContext();
 }
 
@@ -79,10 +108,9 @@ bool OpenGLSalGraphicsImpl::AcquireContext( )
 
     // We always prefer to bind our VirtualDevice / offscreen graphics
     // to the current OpenGLContext - to avoid switching contexts.
-    if (mpContext.is() && mbOffscreen)
+    if (mpContext.is() && OpenGLContext::hasCurrent() && !mpContext->isCurrent())
     {
-        if (OpenGLContext::hasCurrent() && !mpContext->isCurrent())
-            mpContext.clear();
+        mpContext.clear();
     }
 
     if( mpContext.is() )
@@ -97,15 +125,17 @@ bool OpenGLSalGraphicsImpl::AcquireContext( )
     while( pContext )
     {
         // check if this context can be used by this SalGraphicsImpl instance
-        if( UseContext( pContext )  )
+        if( UseContext( pContext ) )
             break;
         pContext = pContext->mpPrevContext;
     }
 
-    if( pContext )
+    if( mpContext.is() )
         mpContext = pContext;
+    else if( mpWindowContext.is() )
+        mpContext = mpWindowContext;
     else
-        mpContext = mbOffscreen ? GetDefaultContext() : CreateWinContext();
+        mpContext = GetDefaultContext();
 
     return mpContext.is();
 }
@@ -119,19 +149,20 @@ bool OpenGLSalGraphicsImpl::ReleaseContext()
 
 void OpenGLSalGraphicsImpl::Init()
 {
-    mbOffscreen = IsOffscreen();
+    // Our init phase is strange ::Init is called twice for vdevs.
+    // the first time around with a NULL geometry provider.
+    if( !mpProvider )
+        return;
 
     // check if we can simply re-use the same context
     if( mpContext.is() )
     {
-        if( !mpContext->isInitialized() ||
-            !UseContext( mpContext ) )
+        if( !UseContext( mpContext ) )
             ReleaseContext();
     }
 
-    // reset the offscreen texture
-    if( !mbOffscreen ||
-        maOffscreenTex.GetWidth()  != GetWidth() ||
+    // Always create the offscreen texture
+    if( maOffscreenTex.GetWidth()  != GetWidth() ||
         maOffscreenTex.GetHeight() != GetHeight() )
     {
         if( maOffscreenTex && // don't work to release empty textures
@@ -141,6 +172,14 @@ void OpenGLSalGraphicsImpl::Init()
             mpContext->ReleaseFramebuffer( maOffscreenTex );
         }
         maOffscreenTex = OpenGLTexture();
+        VCL_GL_INFO("::Init - re-size offscreen texture");
+    }
+
+    if( !IsOffscreen() )
+    {
+        if( mpWindowContext.is() )
+            mpWindowContext->reset();
+        mpWindowContext = CreateWinContext();
     }
 }
 
@@ -155,12 +194,15 @@ void OpenGLSalGraphicsImpl::DeInit()
     // get a shiny new context in AcquireContext:: next PreDraw.
     if( mpContext.is() && !IsOffscreen() )
         mpContext->reset();
+    mpContext.clear();
 }
 
 void OpenGLSalGraphicsImpl::PreDraw()
 {
     OpenGLZone::enter();
 
+    mnDrawCount++;
+
     if( !AcquireContext() )
     {
         SAL_WARN( "vcl.opengl", "Couldn't acquire context" );
@@ -170,10 +212,7 @@ void OpenGLSalGraphicsImpl::PreDraw()
     mpContext->makeCurrent();
     CHECK_GL_ERROR();
 
-    if( !mbOffscreen )
-        mpContext->AcquireDefaultFramebuffer();
-    else
-        CheckOffscreenTexture();
+    CheckOffscreenTexture();
     CHECK_GL_ERROR();
 
     glViewport( 0, 0, GetWidth(), GetHeight() );
@@ -185,15 +224,13 @@ void OpenGLSalGraphicsImpl::PreDraw()
 
 void OpenGLSalGraphicsImpl::PostDraw()
 {
-    if( !mbOffscreen && mpContext->mnPainting == 0 )
-        glFlush();
     if( mbUseScissor )
     {
         glDisable( GL_SCISSOR_TEST );
         CHECK_GL_ERROR();
     }
-   if( mbUseStencil )
-   {
+    if( mbUseStencil )
+    {
         glDisable( GL_STENCIL_TEST );
         CHECK_GL_ERROR();
     }
@@ -205,6 +242,18 @@ void OpenGLSalGraphicsImpl::PostDraw()
         mProgramIsSolidColor = false;
 #endif
     }
+
+    assert (maOffscreenTex);
+
+    if( IsOffscreen() )
+        assert( !mpWindowContext.is() );
+    else
+        assert( mpWindowContext.is() );
+
+    // Always queue the flush.
+    if( !IsOffscreen() )
+        flush();
+
     OpenGLZone::leave();
 }
 
@@ -216,8 +265,9 @@ void OpenGLSalGraphicsImpl::ApplyProgramMatrices(float fPixelOffset)
 void OpenGLSalGraphicsImpl::freeResources()
 {
     // TODO Delete shaders, programs and textures if not shared
-    if( mbOffscreen && mpContext.is() && mpContext->isInitialized() )
+    if( mpContext.is() && mpContext->isInitialized() )
     {
+        VCL_GL_INFO( "freeResources" );
         mpContext->makeCurrent();
         mpContext->ReleaseFramebuffer( maOffscreenTex );
     }
@@ -227,6 +277,20 @@ void OpenGLSalGraphicsImpl::freeResources()
 void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMask )
 {
     glEnable( GL_STENCIL_TEST );
+
+    VCL_GL_INFO( "Adding complex clip / stencil" );
+    GLuint nStencil = maOffscreenTex.StencilId();
+    if( nStencil == 0 )
+    {
+        nStencil = maOffscreenTex.AddStencil();
+        glFramebufferRenderbuffer(
+            GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+            GL_RENDERBUFFER, nStencil );
+        CHECK_GL_ERROR();
+    }
+    // else - we associated the stencil in
+    //        AcquireFrameBuffer / AttachTexture
+
     CHECK_GL_ERROR();
     glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
     CHECK_GL_ERROR();
@@ -261,7 +325,7 @@ void OpenGLSalGraphicsImpl::ImplInitClipRegion()
     if( maClipRegion != mpContext->maClipRegion )
     {
         mpContext->maClipRegion = maClipRegion;
-        if( maClipRegion.IsRectangle() )
+        if( mbUseScissor )
         {
             Rectangle aRect( maClipRegion.GetBoundRect() );
             glScissor( aRect.Left(), GetHeight() - aRect.Bottom() - 1, aRect.GetWidth() + 1, aRect.GetHeight() + 1 );
@@ -382,8 +446,29 @@ void OpenGLSalGraphicsImpl::SetROPFillColor( SalROPColor /*nROPColor*/ )
 
 bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
 {
+    bool bClearTexture = false;
+
+    VCL_GL_INFO( "Check Offscreen texture" );
+
+    // Always create the offscreen texture
+    if( maOffscreenTex )
+    {
+        if( maOffscreenTex.GetWidth()  != GetWidth() ||
+            maOffscreenTex.GetHeight() != GetHeight() )
+        {
+            mpContext->ReleaseFramebuffer( maOffscreenTex );
+            maOffscreenTex = OpenGLTexture();
+            VCL_GL_INFO( "re-size offscreen texture" );
+        }
+    }
+
     if( !maOffscreenTex )
+    {
+        VCL_GL_INFO( "create texture of size "
+                     << GetWidth() << " x " << GetHeight() );
         maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() );
+        bClearTexture = true;
+    }
 
     if( !maOffscreenTex.IsUnique() )
     {
@@ -400,8 +485,23 @@ bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
     else
     {
         mpFramebuffer = mpContext->AcquireFramebuffer( maOffscreenTex );
+        CHECK_GL_ERROR();
+
+        if( bClearTexture )
+        {
+            glDrawBuffer( GL_COLOR_ATTACHMENT0 );
+#if OSL_DEBUG_LEVEL > 0 // lets have some red debugging background.
+            GLfloat clearColor[4] = { 1.0, 0, 0, 0 };
+#else
+            GLfloat clearColor[4] = { 1.0, 1.0, 1.0, 0 };
+#endif
+            glClearBufferfv( GL_COLOR, 0, clearColor );
+            // FIXME: use glClearTexImage if we have it ?
+        }
     }
 
+    assert( maOffscreenTex );
+
     CHECK_GL_ERROR();
     return true;
 }
@@ -1541,17 +1641,9 @@ void OpenGLSalGraphicsImpl::DoCopyBits( const SalTwoRect& rPosAry, OpenGLSalGrap
         return;
     }
 
-    if( rImpl.mbOffscreen )
-    {
-        PreDraw();
-        DrawTexture( rImpl.maOffscreenTex, rPosAry );
-        PostDraw();
-        return;
-    }
-
-    SAL_WARN( "vcl.opengl", "*** NOT IMPLEMENTED *** copyBits" );
-    // TODO: Copy from one FBO to the other (glBlitFramebuffer)
-    //       ie. copying from one visible window to another visible window
+    PreDraw();
+    DrawTexture( rImpl.maOffscreenTex, rPosAry );
+    PostDraw();
 }
 
 void OpenGLSalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap )
@@ -1878,12 +1970,122 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly,
     return true;
 }
 
-OpenGLContext *OpenGLSalGraphicsImpl::beginPaint()
+void OpenGLSalGraphicsImpl::flush()
 {
-    if( mbOffscreen || !AcquireContext() )
-        return nullptr;
+    if( IsOffscreen() )
+        return;
+
+    if( !Application::IsInExecute() )
+    {
+        // otherwise nothing would trigger idle rendering
+        doFlush();
+    }
+    else if( !mpFlush->IsActive() )
+        mpFlush->Start();
+}
+
+void OpenGLSalGraphicsImpl::doFlush()
+{
+    if( IsOffscreen() )
+        return;
+
+    assert( mpWindowContext.is() );
+
+    if( !maOffscreenTex )
+    {
+        VCL_GL_INFO( "flushAndSwap - odd no texture !" );
+        return;
+    }
+
+    if (mnDrawCountAtFlush == mnDrawCount)
+    {
+        VCL_GL_INFO( "eliding redundant flushAndSwap, no drawing since last!" );
+        return;
+    }
+
+    mnDrawCountAtFlush = mnDrawCount;
+
+    OpenGLZone aZone;
+
+    VCL_GL_INFO( "flushAndSwap" );
+
+    // Interesting ! -> this destroys a context [ somehow ] ...
+    mpWindowContext->makeCurrent();
+    CHECK_GL_ERROR();
+
+    VCL_GL_INFO( "flushAndSwap - acquire default frame buffer" );
+
+    mpWindowContext->AcquireDefaultFramebuffer();
+    glBindFramebuffer( GL_FRAMEBUFFER, 0 ); // FIXME: paranoid double check.
+    CHECK_GL_ERROR();
+
+    VCL_GL_INFO( "flushAndSwap - acquired default frame buffer" );
+
+    glDisable( GL_SCISSOR_TEST ); // FIXME: paranoia ...
+    CHECK_GL_ERROR();
+    glDisable( GL_STENCIL_TEST ); // FIXME: paranoia ...
+    CHECK_GL_ERROR();
+
+    glViewport( 0, 0, GetWidth(), GetHeight() );
+    CHECK_GL_ERROR();
+
+    glClearColor((float)rand()/RAND_MAX, (float)rand()/RAND_MAX,
+                 (float)rand()/RAND_MAX, 1.0);
+    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
+    CHECK_GL_ERROR();
+
+    SalTwoRect aPosAry( 0, 0, maOffscreenTex.GetWidth(), maOffscreenTex.GetHeight(),
+                        0, 0, maOffscreenTex.GetWidth(), maOffscreenTex.GetHeight() );
+    VCL_GL_INFO( "Texture height " << maOffscreenTex.GetHeight() << " vs. window height " << GetHeight() );
+
+    OpenGLProgram *pProgram =
+        mpWindowContext->UseProgram( "textureVertexShader", "textureFragmentShader", "" );
+    if( !pProgram )
+        VCL_GL_INFO( "Can't compile simple copying shader !" );
     else
-        return mpContext.get();
+    {
+        pProgram->Use(); // FIXME: paranoia ...
+        VCL_GL_INFO( "done paranoid re-use." );
+        pProgram->SetTexture( "sampler", maOffscreenTex );
+        maOffscreenTex.Bind(); // FIXME: paranoia ...
+
+        VCL_GL_INFO( "bound bits etc." );
+
+        GLfloat aTexCoord[8];
+        maOffscreenTex.GetCoord( aTexCoord, aPosAry, false );
+        pProgram->SetTextureCoord( aTexCoord );
+
+        long nX1( aPosAry.mnDestX );
+        long nY1( aPosAry.mnDestY );
+        long nX2( nX1 + aPosAry.mnDestWidth );
+        long nY2( nY1 + aPosAry.mnDestHeight );
+        const SalPoint aPoints[] = { { nX1, nY2 }, { nX1, nY1 },
+                                     { nX2, nY1 }, { nX2, nY2 }};
+
+        sal_uInt32 nPoints = 4;
+        std::vector<GLfloat> aVertices(nPoints * 2);
+        sal_uInt32 i, j;
+
+        for( i = 0, j = 0; i < nPoints; i++, j += 2 )
+        {
+            aVertices[j]   = GLfloat(aPoints[i].mnX);
+            aVertices[j+1] = GLfloat(aPoints[i].mnY);
+        }
+
+        pProgram->ApplyMatrix(GetWidth(), GetHeight(), 0.0);
+        pProgram->SetVertices( &aVertices[0] );
+        glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
+
+        pProgram->Clean();
+
+        glBindTexture( GL_TEXTURE_2D, 0 );
+
+        static bool bNoSwap = getenv("SAL_GL_NO_SWAP");
+        if (!bNoSwap)
+            mpWindowContext->swapBuffers();
+    }
+
+    VCL_GL_INFO( "flushAndSwap - end." );
 }
 
 bool OpenGLSalGraphicsImpl::IsForeignContext(const rtl::Reference<OpenGLContext> &xContext)
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index 2d4cb40..bf4aa1d 100644
--- a/vcl/opengl/texture.cxx
+++ b/vcl/opengl/texture.cxx
@@ -35,6 +35,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate )
     mnWidth( nWidth ),
     mnHeight( nHeight ),
     mnFilter( GL_NEAREST ),
+    mnOptStencil( 0 ),
     mnFreeSlots(-1)
 {
     glGenTextures( 1, &mnTexture );
@@ -67,6 +68,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight )
     mnWidth( nWidth ),
     mnHeight( nHeight ),
     mnFilter( GL_NEAREST ),
+    mnOptStencil( 0 ),
     mnFreeSlots(-1)
 {
     // FIXME We need the window height here
@@ -99,6 +101,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int
     mnWidth( nWidth ),
     mnHeight( nHeight ),
     mnFilter( GL_NEAREST ),
+    mnOptStencil( 0 ),
     mnFreeSlots(-1)
 {
     if( !mnTexture )
@@ -126,6 +129,21 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int
     VCL_GL_INFO( "OpenGLTexture " << mnTexture << " " << nWidth << "x" << nHeight << " from data" );
 }
 
+GLuint ImplOpenGLTexture::AddStencil()
+{
+    assert( mnOptStencil == 0 );
+
+    glGenRenderbuffers( 1, &mnOptStencil );
+    glBindRenderbuffer( GL_RENDERBUFFER, mnOptStencil );
+    CHECK_GL_ERROR();
+    VCL_GL_INFO( "Allocate stencil " << mnWidth << " x " << mnHeight );
+    glRenderbufferStorage( GL_RENDERBUFFER, GL_STENCIL_INDEX,
+                           mnWidth, mnHeight );
+    CHECK_GL_ERROR();
+
+    return mnOptStencil;
+}
+
 ImplOpenGLTexture::~ImplOpenGLTexture()
 {
     VCL_GL_INFO( "~OpenGLTexture " << mnTexture );
@@ -136,9 +154,11 @@ ImplOpenGLTexture::~ImplOpenGLTexture()
         // Check we have been correctly un-bound from all framebuffers.
         ImplSVData* pSVData = ImplGetSVData();
         rtl::Reference<OpenGLContext> pContext = pSVData->maGDIData.mpLastContext;
-        if (pContext.is())
+        if( pContext.is() )
             pContext->UnbindTextureFromFramebuffers( mnTexture );
 
+        if( mnOptStencil != 0 )
+            glDeleteRenderbuffers( 1, &mnOptStencil );
         glDeleteTextures( 1, &mnTexture );
     }
 }
@@ -279,6 +299,24 @@ int OpenGLTexture::GetHeight() const
     return maRect.GetHeight();
 }
 
+bool OpenGLTexture::HasStencil() const
+{
+    return mpImpl && mpImpl->mnOptStencil != 0;
+}
+
+GLuint OpenGLTexture::StencilId() const
+{
+    return mpImpl ? mpImpl->mnOptStencil : 0;
+}
+
+GLuint OpenGLTexture::AddStencil()
+{
+    if (mpImpl)
+        return mpImpl->AddStencil();
+    else
+        return 0;
+}
+
 void OpenGLTexture::GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool bInverted ) const
 {
     VCL_GL_INFO( "Getting coord " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() );
@@ -349,6 +387,10 @@ void OpenGLTexture::Bind()
         glBindTexture( GL_TEXTURE_2D, mpImpl->mnTexture );
         CHECK_GL_ERROR();
     }
+    else
+        VCL_GL_INFO( "OpenGLTexture::Binding invalid texture" );
+
+    CHECK_GL_ERROR();
 }
 
 void OpenGLTexture::Unbind()
diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx
index f57c82d..666cdbf 100644
--- a/vcl/opengl/win/gdiimpl.cxx
+++ b/vcl/opengl/win/gdiimpl.cxx
@@ -29,21 +29,10 @@ void WinOpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics*
 rtl::Reference<OpenGLContext> WinOpenGLSalGraphicsImpl::CreateWinContext()
 {
     rtl::Reference<OpenGLContext> pContext = OpenGLContext::Create();
-    pContext->requestSingleBufferedRendering();
     pContext->init( mrParent.mhLocalDC, mrParent.mhWnd );
     return pContext;
 }
 
-bool WinOpenGLSalGraphicsImpl::UseContext( const rtl::Reference<OpenGLContext> &pContext )
-{
-    if( !pContext.is() || !pContext->isInitialized() || IsForeignContext( pContext ) )
-        return false;
-    if( IsOffscreen() )
-        return true;
-    return pContext->getOpenGLWindow().hWnd == mrParent.mhWnd &&
-           pContext->getOpenGLWindow().hDC == mrParent.mhLocalDC;
-}
-
 void WinOpenGLSalGraphicsImpl::Init()
 {
     if ( !IsOffscreen() && mpContext.is() && mpContext->isInitialized() &&
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 2418bc6..595ca45c 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -58,18 +58,6 @@ rtl::Reference<OpenGLContext> X11OpenGLSalGraphicsImpl::CreateWinContext()
     return pContext;
 }
 
-bool X11OpenGLSalGraphicsImpl::UseContext( const rtl::Reference<OpenGLContext> &pContext )
-{
-    X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
-
-    if( !pContext->isInitialized() || IsForeignContext( pContext ) )
-        return false;
-    if( !pProvider )
-        return pContext->getOpenGLWindow().win != None;
-    else
-        return pContext->getOpenGLWindow().win == pProvider->GetX11Window();
-}
-
 void X11OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
 {
     OpenGLSalGraphicsImpl *pImpl = pSrcGraphics ? static_cast< OpenGLSalGraphicsImpl* >(pSrcGraphics->GetImpl()) : static_cast< OpenGLSalGraphicsImpl *>(mrParent.GetImpl());
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index 26148a6..98be555 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -18,6 +18,8 @@
 #include <vcl/bmpacc.hxx>
 #include <vcl/graph.hxx>
 
+#include <osl/thread.hxx>
+
 #if defined(MACOSX)
 #include <premac.h>
 #include <AppKit/NSOpenGLView.h>
@@ -1487,6 +1489,14 @@ void OpenGLContext::swapBuffers()
 #elif defined( UNX )
     glXSwapBuffers(m_aGLWin.dpy, m_aGLWin.win);
 #endif
+
+    static bool bSleep = getenv("SAL_GL_SLEEP_ON_SWAP");
+    if (bSleep)
+    {
+        // half a second.
+        TimeValue aSleep( 0, 500*1000*1000 );
+        osl::Thread::wait( aSleep );
+    }
 }
 
 void OpenGLContext::sync()
commit 2f3358046e57588086785e6cfd2cbd6f6133e277
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Mon Nov 16 18:18:36 2015 +0000

    Get Double-buffered context creation working on linux.
    
    Change-Id: I3db1d6792fcd51577f047b82029124ec825ea319

diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index 8c5db0f..26148a6 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -706,9 +706,7 @@ bool GLWindow::HasGLXExtension( const char* name ) const
 bool OpenGLContext::ImplInit()
 {
     if (!m_aGLWin.dpy)
-    {
         return false;
-    }
 
     OpenGLZone aZone;
 
@@ -722,11 +720,10 @@ bool OpenGLContext::ImplInit()
     if (!g_vShareList.empty())
         pSharedCtx = g_vShareList.front();
 
-#ifdef DBG_UTIL
     if (glXCreateContextAttribsARB && !mbRequestLegacyContext)
     {
         int best_fbc = -1;
-        GLXFBConfig* pFBC = getFBConfig(m_aGLWin.dpy, m_aGLWin.win, best_fbc, mbUseDoubleBufferedRendering, true);
+        GLXFBConfig* pFBC = getFBConfig(m_aGLWin.dpy, m_aGLWin.win, best_fbc, mbUseDoubleBufferedRendering, false);
         if (!pFBC)
             return false;
 
@@ -734,24 +731,28 @@ bool OpenGLContext::ImplInit()
         {
             int pContextAttribs[] =
             {
+#if 0 // defined(DBG_UTIL)
                 GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
                 GLX_CONTEXT_MINOR_VERSION_ARB, 2,
+#endif
                 None
+
             };
             m_aGLWin.ctx = glXCreateContextAttribsARB(m_aGLWin.dpy, pFBC[best_fbc], pSharedCtx, /* direct, not via X */ GL_TRUE, pContextAttribs);
             SAL_INFO_IF(m_aGLWin.ctx, "vcl.opengl", "created a 3.2 core context");
         }
         else
             SAL_WARN("vcl.opengl", "unable to find correct FBC");
-
     }
-#endif
 
     if (!m_aGLWin.ctx)
     {
         if (!m_aGLWin.vi)
            return false;
 
+        SAL_WARN("vcl.opengl", "attempting to create a non-double-buffered "
+                               "visual matching the context");
+
         m_aGLWin.ctx = glXCreateContext(m_aGLWin.dpy,
                 m_aGLWin.vi,
                 pSharedCtx,
commit b52c240364d50292d4faa234699e5851a25764df
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Mon Nov 30 16:13:42 2015 +0000

    vcl: gtk frames should DeInitialize properly, to handle GL cleanup.
    
    Change-Id: Ie6a5464c28b89f08639939690052023e685a3d33

diff --git a/vcl/unx/gtk/gtksalframe.cxx b/vcl/unx/gtk/gtksalframe.cxx
index 085eb0e..1772990 100644
--- a/vcl/unx/gtk/gtksalframe.cxx
+++ b/vcl/unx/gtk/gtksalframe.cxx
@@ -777,8 +777,10 @@ void GtkSalFrame::InvalidateGraphics()
 {
     if( m_pGraphics )
     {
-        m_pGraphics->SetDrawable( None, m_nXScreen );
+        m_pGraphics->DeInit();
         m_pGraphics->SetWindow(nullptr);
+        delete m_pGraphics;
+        m_pGraphics = nullptr;
         m_bGraphics = false;
     }
 }
@@ -846,9 +848,6 @@ GtkSalFrame::~GtkSalFrame()
         g_object_unref( G_OBJECT( m_pForeignParent ) );
     if( m_pForeignTopLevel )
         g_object_unref( G_OBJECT( m_pForeignTopLevel) );
-
-    delete m_pGraphics;
-    m_pGraphics = nullptr;
 }
 
 void GtkSalFrame::moveWindow( long nX, long nY )
commit 484cee0e0c655cf1fc1bff4758e4eb6e4dd0184e
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Dec 9 17:43:44 2015 +0000

    writer: Defer update, until post first render to avoid flicker.
    
    Change-Id: Ib16f5b345901adc7036a8a90d0f46aa3499d66ae

diff --git a/sw/source/uibase/inc/conttree.hxx b/sw/source/uibase/inc/conttree.hxx
index 010b347..ca22dc7 100644
--- a/sw/source/uibase/inc/conttree.hxx
+++ b/sw/source/uibase/inc/conttree.hxx
@@ -137,6 +137,7 @@ protected:
                                     SvTreeListEntry*& rpNewParent,
                                     sal_uLong&        rNewChildPos
                                 ) override;
+    virtual void    Paint( vcl::RenderContext& rRenderContext, const Rectangle& rRect ) override;
     virtual void    MouseButtonDown( const MouseEvent& rMEvt ) override;
 
     void            EditEntry( SvTreeListEntry* pEntry, EditEntryMode nMode );
diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx
index 8536c4c..3feb1f9 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -2424,10 +2424,18 @@ void SwContentTree::ExecCommand(sal_uInt16 nCmd, bool bModifier)
 
 void    SwContentTree::ShowTree()
 {
-    m_aUpdTimer.Start();
     SvTreeListBox::Show();
 }
 
+void SwContentTree::Paint( vcl::RenderContext& rRenderContext,
+                           const Rectangle& rRect )
+{
+    // Start the update timer on the first paint; avoids
+    // flicker on the first reveal.
+    m_aUpdTimer.Start();
+    SvTreeListBox::Paint( rRenderContext, rRect );
+}
+
 // folded together will not be glidled
 
 void    SwContentTree::HideTree()
commit d4d247866eac108162f43dae2c6ddbd9c12382a6
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Dec 10 11:48:47 2015 +0000

    guard against missing geometry
    
    Change-Id: I6b2945f1d5a1654f6b5d6a5f5287b4cb9514d97c

diff --git a/lotuswordpro/source/filter/lwplayout.cxx b/lotuswordpro/source/filter/lwplayout.cxx
index 5fa4e2c..d5d17973 100644
--- a/lotuswordpro/source/filter/lwplayout.cxx
+++ b/lotuswordpro/source/filter/lwplayout.cxx
@@ -997,10 +997,10 @@ sal_Int32 LwpMiddleLayout::DetermineWidth()
     {
         assert(false);
     }
-    else
+    else if (LwpLayoutGeometry* pGeo = GetGeometry())
     {
         m_nAttributes3 |= STYLE3_WIDTHVALID;
-        return GetGeometry()->GetWidth();
+        return pGeo->GetWidth();
     }
     return 0;
 }
commit 65deab68f7918c82026951b04a414eefee2683b2
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Dec 10 11:42:46 2015 +0000

    use of uninitialized variable
    
    Change-Id: I1149eb9f5946228a2448c121e7ec7211861b3b3d

diff --git a/lotuswordpro/source/filter/bencont.cxx b/lotuswordpro/source/filter/bencont.cxx
index 9c45a0c..82551295 100644
--- a/lotuswordpro/source/filter/bencont.cxx
+++ b/lotuswordpro/source/filter/bencont.cxx
@@ -226,7 +226,7 @@ BenError LtcBenContainer::SeekFromEnd(long Offset)
 */
 LtcUtBenValueStream * LtcBenContainer::FindNextValueStreamWithPropertyName(const char * sPropertyName, LtcUtBenValueStream * pCurrentValueStream)
 {
-    CBenPropertyName * pPropertyName;
+    CBenPropertyName * pPropertyName(nullptr);
     RegisterPropertyName(sPropertyName, &pPropertyName);        // Get property name object
 
     if (nullptr == pPropertyName)
commit bae861b7ed36b963f7060d45c7d30fd2f3223db1
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Thu Dec 10 12:03:56 2015 +0100

    Missing include
    
    Change-Id: I74a3cd6bf6cd780040b2a9eaefb2bde9acbfd6dd

diff --git a/sc/source/core/tool/refdata.cxx b/sc/source/core/tool/refdata.cxx
index 9811c08..d977802 100644
--- a/sc/source/core/tool/refdata.cxx
+++ b/sc/source/core/tool/refdata.cxx
@@ -17,6 +17,10 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <sal/config.h>
+
+#include <algorithm>
+
 #include "refdata.hxx"
 
 void ScSingleRefData::InitAddress( const ScAddress& rAdr )
commit 28082ae6a13a3460e3945d5e90dc76689b98edd8
Author: Tor Lillqvist <tml at collabora.com>
Date:   Thu Dec 10 12:47:18 2015 +0200

    s/dobble/double
    
    Change-Id: Ie348c008ffec326c5c4429cfb1a791951dd8a16a

diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index d0bdbe4..344f71fe 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -2037,7 +2037,7 @@ void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventSta
         return;
     }
 
-            //      dobble click started ?
+            //      double click started ?
 
     // StopMarking can be called from DrawMouseButtonDown
 
@@ -2439,7 +2439,7 @@ void ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
         OUString aName, aUrl, aTarget;
         if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) )
         {
-            nMouseStatus = SC_GM_NONE;              // Ignore dobble-click
+            nMouseStatus = SC_GM_NONE;              // Ignore double-click
 
             // ScGlobal::OpenURL() only understands Calc A1 style syntax.
             // Convert it to Calc A1 before calling OpenURL().
diff --git a/sc/source/ui/view/gridwin3.cxx b/sc/source/ui/view/gridwin3.cxx
index 97d149c..4f97aa4 100644
--- a/sc/source/ui/view/gridwin3.cxx
+++ b/sc/source/ui/view/gridwin3.cxx
@@ -53,7 +53,7 @@ bool ScGridWindow::DrawMouseButtonDown(const MouseEvent& rMEvt)
         Point aLogicPos = PixelToLogic(rMEvt.GetPosPixel());
         if ( pDraw->IsDetectiveHit( aLogicPos ) )
         {
-            // nothing on detectiv arrows (dobble click is evaluated on ButtonUp)
+            // nothing on detective arrows (double click is evaluated on ButtonUp)
             bRet = true;
         }
         else
commit 434d8e2c7042a4d11b9d74ce84434e2bcc249038
Author: Takeshi Abe <tabe at fixedpoint.jp>
Date:   Wed Dec 9 17:59:04 2015 +0900

    starmath: SmElementPointer is not shared actually
    
    ... rather, it's owned by maElementList.
    So, use just std::unique_ptr<SmElement> instead.
    
    Change-Id: Id18466083535677e0f7d07f8c523b433c5e2a9ec
    Reviewed-on: https://gerrit.libreoffice.org/20490
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Noel Grandin <noelgrandin at gmail.com>

diff --git a/starmath/inc/ElementsDockingWindow.hxx b/starmath/inc/ElementsDockingWindow.hxx
index e57e50c..4e1652a 100644
--- a/starmath/inc/ElementsDockingWindow.hxx
+++ b/starmath/inc/ElementsDockingWindow.hxx
@@ -85,15 +85,12 @@ class SmElementsControl : public Control
     virtual void MouseButtonDown(const MouseEvent& rMEvt) override;
     virtual void MouseMove( const MouseEvent& rMEvt ) override;
 
-    typedef std::shared_ptr<SmElement>    SmElementPointer;
-    typedef std::vector< SmElementPointer > SmElementList;
-
     SmDocShell*   mpDocShell;
     SmFormat      maFormat;
     sal_uInt16    maCurrentSetId;
     SmElement*    mpCurrentElement;
 
-    SmElementList maElementList;
+    std::vector< std::unique_ptr<SmElement> > maElementList;
     Size          maMaxElementDimensions;
     bool          mbVerticalMode;
     VclPtr< ScrollBar > mxScroll;
diff --git a/starmath/source/ElementsDockingWindow.cxx b/starmath/source/ElementsDockingWindow.cxx
index 229eeedb..b3b0f2c 100644
--- a/starmath/source/ElementsDockingWindow.cxx
+++ b/starmath/source/ElementsDockingWindow.cxx
@@ -24,6 +24,7 @@
 #include <view.hxx>
 #include <visitors.hxx>
 
+#include <o3tl/make_unique.hxx>
 #include <svl/stritem.hxx>
 #include <sfx2/dispatch.hxx>
 #include <sfx2/sfxmodelfactory.hxx>
@@ -457,8 +458,7 @@ void SmElementsControl::DoScroll(long nDelta)
 
 void SmElementsControl::addSeparator()
 {
-    SmElementPointer pElement(new SmElementSeparator());
-    maElementList.push_back(pElement);
+    maElementList.push_back(o3tl::make_unique<SmElementSeparator>());
 }
 
 void SmElementsControl::addElement(const OUString& aElementVisual, const OUString& aElementSource, const OUString& aHelpText)
@@ -478,8 +478,7 @@ void SmElementsControl::addElement(const OUString& aElementVisual, const OUStrin
         maMaxElementDimensions.Height() = aSizePixel.Height();
     }
 
-    SmElementPointer pElement(new SmElement(pNode, aElementSource, aHelpText));
-    maElementList.push_back(pElement);
+    maElementList.push_back(o3tl::make_unique<SmElement>(pNode, aElementSource, aHelpText));
 }
 
 void SmElementsControl::setElementSetId(sal_uInt16 aSetId)
commit 363a9c05fa074df5551bef7876654b38eaca4060
Author: Juergen Funk <juergen.funk_ml at cib.de>
Date:   Mon Dec 7 20:02:10 2015 +0100

    Add FontCharMap::GetDefaultMap(bool) to unusedcode.exclude
    
    This function ist uesed under windows here (only once)
    
    http://opengrok.libreoffice.org/xref/core/vcl/win/gdi/salgdi3.cxx#1205
    
    Change-Id: I03d48535d7ffd3bc148ccc637a7cc3cf94fceaeb
    Reviewed-on: https://gerrit.libreoffice.org/20458
    Reviewed-by: Noel Grandin <noelgrandin at gmail.com>
    Tested-by: Noel Grandin <noelgrandin at gmail.com>

diff --git a/unusedcode.easy b/unusedcode.easy
index d5dfbd9..8e015d3 100644
--- a/unusedcode.easy
+++ b/unusedcode.easy
@@ -1,6 +1,5 @@
 BigInt::BigInt(unsigned int)
 BitmapFilterStackBlur::filter(BitmapEx&)
-FontCharMap::GetDefaultMap(bool)
 NotifyEvent::NotifyEvent()
 OpenGLContext::init(_XDisplay*, unsigned long, unsigned int, unsigned int, int)
 OpenGLContext::renderToFile()
diff --git a/unusedcode.exclude b/unusedcode.exclude
index dc8ec70..0862690 100644
--- a/unusedcode.exclude
+++ b/unusedcode.exclude
@@ -27,3 +27,5 @@ apitest::XSpreadsheetDocument::testGetSheets()
 comphelper::detail::ConfigurationWrapper::getGroupReadWrite(boost::shared_ptr<comphelper::ConfigurationChanges> const&, rtl::OUString const&) const
 comphelper::detail::ConfigurationWrapper::getLocalizedPropertyValue(rtl::OUString const&) const
 comphelper::detail::ConfigurationWrapper::setLocalizedPropertyValue(boost::shared_ptr<comphelper::ConfigurationChanges> const&, rtl::OUString const&, com::sun::star::uno::Any const&) const
+FontCharMap::GetDefaultMap(bool)
+
commit d64e535fe9a00b671cf1be3eb5632c0d5f4b8bea
Author: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
Date:   Thu Dec 10 10:03:31 2015 +0100

    Remove unused rtti.hxx
    
    Change-Id: I19ae28665e8835461ccc6b9872002f557c65fa5d
    Reviewed-on: https://gerrit.libreoffice.org/20562
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
    Reviewed-by: Noel Grandin <noelgrandin at gmail.com>

diff --git a/include/tools/rtti.hxx b/include/tools/rtti.hxx
deleted file mode 100644
index 3c89685..0000000
--- a/include/tools/rtti.hxx
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#ifndef INCLUDED_TOOLS_RTTI_HXX
-#define INCLUDED_TOOLS_RTTI_HXX
-
-#include <string.h>
-#include <tools/solar.h>
-
-typedef void* (*TypeId)();
-
-#define TYPEINFO() \
-        static  void*  CreateType(); \
-        static  TypeId StaticType(); \
-        static  bool   IsOf( TypeId aSameOrSuperType ); \
-        virtual TypeId Type() const; \
-        virtual bool   IsA( TypeId aSameOrSuperType ) const
-
-#define TYPEINFO_OVERRIDE() \
-        static  void*  CreateType(); \
-        static  TypeId StaticType(); \
-        static  bool   IsOf( TypeId aSameOrSuperType ); \
-        virtual TypeId Type() const override; \
-        virtual bool   IsA( TypeId aSameOrSuperType ) const override
-
-#define TYPEINFO_VISIBILITY_OVERRIDE(visibility) \
-        visibility static  void*  CreateType(); \
-        visibility static  TypeId StaticType(); \
-        visibility static  bool   IsOf( TypeId aSameOrSuperType ); \
-        visibility virtual TypeId Type() const override; \
-        visibility virtual bool   IsA( TypeId aSameOrSuperType ) const override
-
-#define TYPEINIT_FACTORY(sType, Factory ) \
-        void*  sType::CreateType() { return Factory; } \
-        TypeId sType::StaticType() { return &CreateType; } \
-        TypeId sType::Type() const { return &CreateType; } \
-        bool sType::IsOf( TypeId aSameOrSuperType ) \
-        { \
-            if ( aSameOrSuperType == StaticType() ) \
-                return true
-
-#define STATICTYPE(sType) (sType::StaticType())
-
-#define SUPERTYPE(sSuper) \
-            if ( sSuper::IsOf(aSameOrSuperType ) ) \
-                return true
-
-#define TYPEINIT_END(sType) \
-            return false; \
-        } \
-        bool sType::IsA( TypeId aSameOrSuperType ) const \
-        { return IsOf( aSameOrSuperType ); }
-
-#define TYPEINIT0_FACTORY(sType, Factory) \
-        TYPEINIT_FACTORY(sType, Factory); \
-        TYPEINIT_END(sType)
-#define TYPEINIT0_AUTOFACTORY(sType) TYPEINIT0_FACTORY(sType, new sType)
-#define TYPEINIT0(sType) TYPEINIT0_FACTORY(sType, nullptr)
-
-#define TYPEINIT1_FACTORY(sType, sSuper, Factory) \
-        TYPEINIT_FACTORY(sType, Factory); \
-            SUPERTYPE(sSuper); \
-        TYPEINIT_END(sType)
-#define TYPEINIT1_AUTOFACTORY(sType, sSuper) \
-            TYPEINIT1_FACTORY(sType, sSuper, new sType)
-#define TYPEINIT1(sType, sSuper) \
-            TYPEINIT1_FACTORY(sType, sSuper, nullptr)
-
-#define TYPEINIT2_FACTORY(sType, sSuper1, sSuper2, Factory) \
-        TYPEINIT_FACTORY(sType, Factory); \
-            SUPERTYPE(sSuper1); \
-            SUPERTYPE(sSuper2); \
-        TYPEINIT_END(sType)
-#define TYPEINIT2_AUTOFACTORY(sType, sSuper1, sSuper2) \
-            TYPEINIT2_FACTORY(sType, sSuper1, sSuper2, new sType)
-#define TYPEINIT2(sType, sSuper1, sSuper2) \
-            TYPEINIT2_FACTORY(sType, sSuper1, sSuper2, nullptr)
-
-#define TYPEINIT3_FACTORY(sType, sSuper1, sSuper2, sSuper3, Factory) \
-        TYPEINIT_FACTORY(sType, Factory); \
-            SUPERTYPE(sSuper1); \
-            SUPERTYPE(sSuper2); \
-            SUPERTYPE(sSuper3); \
-        TYPEINIT_END(sType)
-#define TYPEINIT3(sType, sSuper1, sSuper2, sSuper3) \
-            TYPEINIT3_FACTORY(sType, sSuper1, sSuper2, sSuper3, nullptr)
-
-#define TYPE(sType) (sType::StaticType())
-#define ISA(sType) IsA(sType::StaticType())
-#define ISOF(sType) IsOf(sType::StaticType())
-#define CREATE(TypeId) (TypeId())
-
-/** Exemplary application macros for pointers
-    (can be extended for use with references)
-
-    PTR_CAST: Safe pointer casting to a derived class.
-              Returns NULL pointer on cast error
-
-    T: Target type to cast into
-    p: Pointer to be cast into T
-*/
-#define PTR_CAST( T, pObj ) rttiCast<T>(pObj, TYPE(T))
-
-/** Check whether object pObj has a Base Class T
-    (or if pObj is an instance of T) */
-#define HAS_BASE( T, pObj ) \
-        ( pObj && (pObj)->IsA( TYPE(T) ) )
-
-/** Check whether a pointer is targeting an object of type T. */
-#define IS_TYPE(T,pObj) \
-        ( pObj && (pObj)->Type() == TYPE(T) )
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 2afead78b346f13030ad43589da9bc389c3c4c32
Author: Noel Grandin <noel at peralex.com>
Date:   Wed Dec 9 14:57:20 2015 +0200

    tdf#69977: constructing and destructing AccessibleElementInfo...
    
    ... is surprisingly expensive
    shaves about 5% off the time to build this chart
    
    Change-Id: I8e5d071edba50d264c2ab01c6bc0b2cad0e41ec6
    Reviewed-on: https://gerrit.libreoffice.org/20588
    Reviewed-by: Noel Grandin <noelgrandin at gmail.com>
    Tested-by: Noel Grandin <noelgrandin at gmail.com>

diff --git a/chart2/source/controller/inc/AccessibleBase.hxx b/chart2/source/controller/inc/AccessibleBase.hxx
index 398f200..e8f4f8b 100644
--- a/chart2/source/controller/inc/AccessibleBase.hxx
+++ b/chart2/source/controller/inc/AccessibleBase.hxx
@@ -217,7 +217,7 @@ protected:
     virtual sal_Int32 ImplGetAccessibleChildCount() const
         throw (::com::sun::star::uno::RuntimeException);
 
-    AccessibleElementInfo GetInfo() const { return m_aAccInfo;}
+    const AccessibleElementInfo& GetInfo() const { return m_aAccInfo;}
     void SetInfo( const AccessibleElementInfo & rNewInfo );
     AccessibleUniqueId GetId() const { return m_aAccInfo.m_aOID;}
 
commit 975b14df8e9bd7fa701a6b028d4d85aada02a65b
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Dec 9 17:43:23 2015 +0000

    Calm unit test down for GL row-strides.
    
    Change-Id: Ie4123fc692f4fac33f082bb2d86b949d834f1858

diff --git a/vcl/qa/cppunit/BitmapTest.cxx b/vcl/qa/cppunit/BitmapTest.cxx
index eb393bc..fe8c933 100644
--- a/vcl/qa/cppunit/BitmapTest.cxx
+++ b/vcl/qa/cppunit/BitmapTest.cxx
@@ -55,7 +55,8 @@ void BitmapTest::testConvert()
         //it would be nice to find and change the stride for quartz to be the same as everyone else
         CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(10), pReadAccess->GetScanlineSize());
 #else
-        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(12), pReadAccess->GetScanlineSize());
+        if (!OpenGLHelper::isVCLOpenGLEnabled())
+            CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong>(12), pReadAccess->GetScanlineSize());
 #endif
         CPPUNIT_ASSERT(pReadAccess->HasPalette());
         const BitmapColor& rColor = pReadAccess->GetPaletteColor(pReadAccess->GetPixelIndex(1, 1));
commit 713d737b1ff73e76c6543198ce9299e1c83ac147
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Dec 10 10:24:19 2015 +0000

    guard against missing parent layout
    
    Change-Id: Ib08403edf805367c7392325fcfb66bc7ed4d6f6a

diff --git a/lotuswordpro/source/filter/lwpframelayout.cxx b/lotuswordpro/source/filter/lwpframelayout.cxx
index d15e024..eef52a9 100644
--- a/lotuswordpro/source/filter/lwpframelayout.cxx
+++ b/lotuswordpro/source/filter/lwpframelayout.cxx
@@ -186,8 +186,10 @@ void  LwpFrame::RegisterStyle(XFFrameStyle* pFrameStyle)
 */
  void LwpFrame::XFConvert(XFContentContainer* pCont)
  {
-     //parse the frame which anchor to page
+    // parse the frame which anchor to page
     LwpVirtualLayout* pParent = m_pLayout->GetParentLayout();
+    if (!pParent)
+        throw std::runtime_error("missing Parent Layout");
     if(pParent->IsPage()&& pParent->GetParentLayout()->IsPage())
     {
         //for mirror page, problems exist if the parent layout is header or footer layout,
commit 215516a52fd01170bb4a79828b0f0948884b727a
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Dec 10 10:19:12 2015 +0000

    protect against missing Ruby Marker
    
    Change-Id: I04809443b5dc50904654936e608360b57c2e85c3

diff --git a/lotuswordpro/source/filter/lwpframelayout.cxx b/lotuswordpro/source/filter/lwpframelayout.cxx
index 1182172..d15e024 100644
--- a/lotuswordpro/source/filter/lwpframelayout.cxx
+++ b/lotuswordpro/source/filter/lwpframelayout.cxx
@@ -1235,6 +1235,8 @@ void LwpRubyLayout::ConvertContentText()
 void LwpRubyLayout::RegisterStyle()
 {
     LwpRubyMarker* pMarker = GetMarker();
+    if (!pMarker)
+        throw std::runtime_error("missing Ruby Marker");
 
     XFRubyStyle* pRubyStyle = new XFRubyStyle;
 
commit 338c6ba3a0983009cfd1faff52ac56d6ea092d6f
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Dec 10 10:13:51 2015 +0000

    guard against infinite recursion
    
    Change-Id: I43e195df570990f21c780311a98be64b682e5315

diff --git a/lotuswordpro/source/filter/lwpdoc.cxx b/lotuswordpro/source/filter/lwpdoc.cxx
index 2eb0c92..4757f10 100644
--- a/lotuswordpro/source/filter/lwpdoc.cxx
+++ b/lotuswordpro/source/filter/lwpdoc.cxx
@@ -540,7 +540,7 @@ LwpDocument* LwpDocument::GetPreviousDivision()
 
     LwpDocument* pDivision = GetLastDivision();
 
-    while(pDivision)
+    while (pDivision && pDivision != this)
     {
         LwpDocument* pContentDivision = pDivision->GetLastDivisionWithContents();
         if(pContentDivision)
commit c732a1ae8cc0cc94bfeddba243657a0b9e52a0f9
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Dec 10 10:06:58 2015 +0000

    guard against missing table container
    
    Change-Id: I11f6381374c7fc12374cd5089e581ddc777005e2

diff --git a/lotuswordpro/source/filter/lwptablelayout.cxx b/lotuswordpro/source/filter/lwptablelayout.cxx
index 469555f..0a2f789 100644
--- a/lotuswordpro/source/filter/lwptablelayout.cxx
+++ b/lotuswordpro/source/filter/lwptablelayout.cxx
@@ -716,7 +716,7 @@ void LwpTableLayout::RegisterStyle()
     // If the table is not "with paragraph above" placement, create an frame style
     // by supertable layout
     if ( LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE == nType
-        && !pSuper->GetContainerLayout()->IsCell())
+        && (!pSuper->GetContainerLayout() || !pSuper->GetContainerLayout()->IsCell()) )
     {
         //with para above
 //      pSuper->ApplyBackColor(pTableStyle);
commit fbd329800340a496def839181858964b1e3709a5
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Dec 10 10:00:58 2015 +0000

    guard against infinite recursion on parsing objects
    
    Change-Id: Ia6502afde54dbf379bc9951c80c6594f1f436ef5

diff --git a/lotuswordpro/source/filter/lwpdoc.cxx b/lotuswordpro/source/filter/lwpdoc.cxx
index a343f9c..2eb0c92 100644
--- a/lotuswordpro/source/filter/lwpdoc.cxx
+++ b/lotuswordpro/source/filter/lwpdoc.cxx
@@ -166,7 +166,7 @@ void LwpDocument::Parse(IXFStream* pOutputStream)
     rtl::Reference<LwpObject> pDocSock = GetSocket().obj( VO_DOCSOCK );
     if(pDocSock.is())
     {
-        pDocSock->Parse(pOutputStream);
+        pDocSock->DoParse(pOutputStream);
     }
 }
 
@@ -412,7 +412,7 @@ void LwpDocument::ParseDocContent(IXFStream* pOutputStream)
         return;
     }
     pLayoutObj->SetFoundry(m_pFoundry);
-    pLayoutObj->Parse(pOutputStream);
+    pLayoutObj->DoParse(pOutputStream);
 }
 
 /**
@@ -795,11 +795,11 @@ void LwpDocSock::Parse(IXFStream* pOutputStream)
 {
     rtl::Reference<LwpObject> pDoc = GetChildHead().obj();
     if(pDoc.is())
-        pDoc->Parse(pOutputStream);
+        pDoc->DoParse(pOutputStream);
 
     pDoc = GetNext().obj();
     if(pDoc.is())
-        pDoc->Parse(pOutputStream);
+        pDoc->DoParse(pOutputStream);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/lotuswordpro/source/filter/lwpframelayout.cxx b/lotuswordpro/source/filter/lwpframelayout.cxx
index 996673de..1182172 100644
--- a/lotuswordpro/source/filter/lwpframelayout.cxx
+++ b/lotuswordpro/source/filter/lwpframelayout.cxx
@@ -1148,7 +1148,7 @@ void LwpDropcapLayout::Parse(IXFStream* pOutputStream)
     if(pPara.is())
     {
         pPara->SetFoundry(m_pFoundry);
-        pPara->Parse(pOutputStream);
+        pPara->DoParse(pOutputStream);
     }
 }
 
diff --git a/lotuswordpro/source/filter/lwpobj.cxx b/lotuswordpro/source/filter/lwpobj.cxx
index e049a82..8839702 100644
--- a/lotuswordpro/source/filter/lwpobj.cxx
+++ b/lotuswordpro/source/filter/lwpobj.cxx
@@ -60,7 +60,8 @@
  * @descr  construct lwpobject from stream
  */
 LwpObject::LwpObject(LwpObjectHeader objHdr, LwpSvStream* pStrm)
-    : m_ObjHdr(objHdr), m_pObjStrm(nullptr), m_pFoundry(nullptr), m_pStrm(pStrm), m_bRegisteringStyle(false)
+    : m_ObjHdr(objHdr), m_pObjStrm(nullptr), m_pFoundry(nullptr)
+    , m_pStrm(pStrm), m_bRegisteringStyle(false), m_bParsingStyle(false)
 {
     m_pObjStrm = new LwpObjectStream(pStrm, m_ObjHdr.IsCompressed(),
             static_cast<sal_uInt16>(m_ObjHdr.GetSize()) );
diff --git a/lotuswordpro/source/filter/lwpobj.hxx b/lotuswordpro/source/filter/lwpobj.hxx
index 884ab42..bcd6136 100644
--- a/lotuswordpro/source/filter/lwpobj.hxx
+++ b/lotuswordpro/source/filter/lwpobj.hxx
@@ -91,9 +91,11 @@ protected:
     LwpFoundry* m_pFoundry;
     LwpSvStream* m_pStrm;
     bool m_bRegisteringStyle;
+    bool m_bParsingStyle;
 protected:
     virtual void Read();
     virtual void RegisterStyle();
+    virtual void Parse(IXFStream* pOutputStream);
 public:
     void QuickRead();
     //calls RegisterStyle but bails if DoRegisterStyle is called
@@ -106,7 +108,17 @@ public:
         RegisterStyle();
         m_bRegisteringStyle = false;
     }
-    virtual void Parse(IXFStream* pOutputStream);
+    //calls Parse but bails if DoParse is called
+    //on the same object recursively
+    void DoParse(IXFStream* pOutputStream)
+    {
+        if (m_bParsingStyle)
+            throw std::runtime_error("recursion in parsing");
+        m_bParsingStyle = true;
+        Parse(pOutputStream);
+        m_bParsingStyle = false;
+    }
+
     virtual void XFConvert(XFContentContainer* pCont);
 
     LwpFoundry* GetFoundry(){return m_pFoundry;}
diff --git a/lotuswordpro/source/filter/lwppagelayout.cxx b/lotuswordpro/source/filter/lwppagelayout.cxx
index 7674868..3547661 100644
--- a/lotuswordpro/source/filter/lwppagelayout.cxx
+++ b/lotuswordpro/source/filter/lwppagelayout.cxx
@@ -124,7 +124,7 @@ void LwpPageLayout::Parse(IXFStream* pOutputStream)
     if(pStory.is())
     {
         pStory->SetFoundry(m_pFoundry);
-        pStory->Parse(pOutputStream);   //Do not parse the next story
+        pStory->DoParse(pOutputStream);   //Do not parse the next story
     }
 }
 
commit b8d86c976c2356bb3c63830ffed204a397ffd0ae
Author: Marco Cecchetti <marco.cecchetti at collabora.com>
Date:   Wed Dec 9 21:50:39 2015 +0100

    svg export: transition on first slide are not run - fixed
    
    A dummy slide has been added to be used as leaving slide for transition
    on first slide.
    
    SVGExportTextDecorations unit test - fixed wrong XPath.
    The new dummy slide group element caused the xpath to the slide
    group to be wrong.
    
    Change-Id: I6c1a0a80f71a79668c309bc0bcb3d5e588ef3a39
    Reviewed-on: https://gerrit.libreoffice.org/20560
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 569a562..c1cc82b 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -1215,6 +1215,9 @@ function MetaDocument()
     this.aSlideAnimationsMap = new Object();
     this.initSlideAnimationsMap();
 
+    // We initialize dummy slide - used as leaving slide for transition on the first slide
+    this.theMetaDummySlide = new MetaSlide( 'ooo:meta_dummy_slide', this );
+
     // We initialize the set of MetaSlide objects that handle the meta
     // information for each slide.
     for( var i = 0; i < this.nNumberOfSlides; ++i )
@@ -1316,7 +1319,11 @@ function MetaSlide( sMetaSlideId, aMetaDoc )
     this.slideElement = this.theDocument.getElementById( this.slideId );
     assert( this.slideElement,
             'MetaSlide: slide element <' + this.slideId + '> not found.' );
-    this.nSlideNumber = parseInt( this.slideId.substr(2) );
+
+    if( this.slideId !== 'dummy_slide' )
+        this.nSlideNumber = parseInt( this.slideId.substr(2) );
+    else
+        this.nSlideNumber= -1;
 
     // Each slide element is wrapped by a <g> element that is responsible for
     // the slide element visibility. In fact the visibility attribute has
@@ -12588,11 +12595,22 @@ SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
     if( this.isEnabled() && !bSkipSlideTransition  )
     {
         // create slide transition and add to activity queue
-        if ( ( nOldSlide !== undefined ) &&
-            ( ( nNewSlide > nOldSlide ) ||
-              ( ( nNewSlide == 0) && ( nOldSlide == (aMetaDoc.nNumberOfSlides - 1) ) ) ) )
+        if ( ( ( nOldSlide !== undefined ) &&
+               ( ( nNewSlide > nOldSlide ) ||
+               ( ( nNewSlide == 0) && ( nOldSlide == (aMetaDoc.nNumberOfSlides - 1) ) ) ) ) ||
+             (  ( nOldSlide === undefined ) &&  ( nNewSlide == 0) )  // for transition on first slide
+           )
         {
-            var aOldMetaSlide = aMetaDoc.aMetaSlideSet[nOldSlide];
+
+            var aOldMetaSlide = null;
+            if( nOldSlide === undefined ) // for transition on first slide
+            {
+                aOldMetaSlide = aMetaDoc.theMetaDummySlide;
+            }
+            else
+            {
+                aOldMetaSlide = aMetaDoc.aMetaSlideSet[nOldSlide];
+            }
             var aNewMetaSlide = aMetaDoc.aMetaSlideSet[nNewSlide];
 
             var aSlideTransitionHandler = aNewMetaSlide.aTransitionHandler;
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index ce31b26..21a9b83 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -1010,6 +1010,18 @@ bool SVGFilter::implGenerateMetaData()
             const OUString                aElemTextFieldId( aOOOElemTextField );
             std::vector< TextField* >     aFieldSet;
 
+            // dummy slide - used as leaving slide for transition on the first slide
+            if( mbPresentation )
+            {
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", NSPREFIX "meta_dummy_slide" );
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlide, "dummy-slide" );
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrMaster, "dummy-master-page" );
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrBackgroundVisibility, "hidden" );
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrMasterObjectsVisibility, "hidden" );
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrHasTransition, "false" );
+                SvXMLElementExport aMetaDummySlideElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+            }
+
             for( sal_Int32 i = 0; i < nCount; ++i )
             {
                 const Reference< XDrawPage > &    xDrawPage = mSelectedPages[i];
@@ -1487,6 +1499,27 @@ bool SVGFilter::implExportMasterPages( const std::vector< Reference< XDrawPage >
     OUString aContainerTag = (!mbPresentation) ? OUString( "g" ) : OUString( "defs" );
     SvXMLElementExport aContainerElement( *mpSVGExport, XML_NAMESPACE_NONE, aContainerTag, true, true );
 
+    // dummy slide - used as leaving slide for transition on the first slide
+    if( mbPresentation )
+    {
+        mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "dummy-master-page" );
+        mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrName, "dummy-master-page" );
+        mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Master_Slide" );
+        SvXMLElementExport aMasterSlideElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+        {
+            mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "bg-dummy-master-page" );
+            mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Background" );
+            mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
+            SvXMLElementExport aBackgroundElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+        }
+        {
+            mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "bo-dummy-master-page" );
+            mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "BackgroundObjects" );
+            mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
+            SvXMLElementExport aBackgroundObjectElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+        }
+    }
+
     bool bRet = false;
     for( sal_Int32 i = nFirstPage; i <= nLastPage; ++i )
     {
@@ -1515,6 +1548,28 @@ bool SVGFilter::implExportDrawPages( const SVGFilter::XDrawPageSequence & rxPage
     DBG_ASSERT( nFirstPage <= nLastPage,
                 "SVGFilter::implExportDrawPages: nFirstPage > nLastPage" );
 
+    // dummy slide - used as leaving slide for transition on the first slide
+    if( mbPresentation )
+    {
+        mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "DummySlide" );
+        SvXMLElementExport aDummySlideElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+        {
+           SvXMLElementExport aGElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+            {
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "dummy-slide" );
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Slide" );
+                OUString sClipPathAttrValue = "url(#" + msClipPathId + ")";
+                mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "clip-path", sClipPathAttrValue );
+                SvXMLElementExport aSlideElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+                {
+                    mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrName, "dummy-page" );
+                    mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Page" );
+                    SvXMLElementExport aPageElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+                }
+            }
+        }
+    }
+
     // We wrap all slide in a group element with class name "SlideGroup".
     mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "SlideGroup" );
     SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
diff --git a/sd/qa/unit/SVGExportTests.cxx b/sd/qa/unit/SVGExportTests.cxx
index 5fa19a9..cd4259c 100644
--- a/sd/qa/unit/SVGExportTests.cxx
+++ b/sd/qa/unit/SVGExportTests.cxx
@@ -99,16 +99,16 @@ public:
         svgDoc->name = reinterpret_cast<char *>(xmlStrdup(reinterpret_cast<xmlChar const *>(OUStringToOString(maTempFile.GetURL(), RTL_TEXTENCODING_UTF8).getStr())));
 
         assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG ), 1);
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[1] ), "class", "SlideGroup");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[1]/SVG_G/SVG_G ), "class", "Slide");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[1]/SVG_G/SVG_G/SVG_G/SVG_G[1] ), "class", "TitleText");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[1]/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT ), "class", "TextShape");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[1]/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT/SVG_TSPAN ), "class", "TextParagraph");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[1]/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT/SVG_TSPAN ), "text-decoration", "underline");
-
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[1]/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT ), "class", "TextShape");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[1]/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT/SVG_TSPAN ), "class", "TextParagraph");
-        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[1]/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT/SVG_TSPAN ), "text-decoration", "line-through");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2] ), "class", "SlideGroup");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G ), "class", "Slide");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[1] ), "class", "TitleText");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT ), "class", "TextShape");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT/SVG_TSPAN ), "class", "TextParagraph");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[1]/SVG_G/SVG_TEXT/SVG_TSPAN ), "text-decoration", "underline");
+
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT ), "class", "TextShape");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT/SVG_TSPAN ), "class", "TextParagraph");
+        assertXPath(svgDoc, MAKE_PATH_STRING( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G[2]/SVG_G/SVG_TEXT/SVG_TSPAN ), "text-decoration", "line-through");
     }
 
     CPPUNIT_TEST_SUITE(SdSVGFilterTest);
commit 0c876483d278e3e5ba43e9eaf40ca713b6099703
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Dec 10 09:49:07 2015 +0000

    guard against missing table layout
    
    Change-Id: I4bc7a7283f63124ccb50957ea64791644e01e267

diff --git a/lotuswordpro/source/filter/lwpcelllayout.cxx b/lotuswordpro/source/filter/lwpcelllayout.cxx
index abe2c02..3848cb6 100644
--- a/lotuswordpro/source/filter/lwpcelllayout.cxx
+++ b/lotuswordpro/source/filter/lwpcelllayout.cxx
@@ -696,6 +696,9 @@ void LwpConnectedCellLayout::SetCellMap()
 {
     // this function is called from LwpTableLayout, so it can't be NULL
     LwpTableLayout * pTableLayout = GetTableLayout();
+    if (!pTableLayout)
+        return;
+
     sal_uInt16 nRowSpan = m_nRealrowspan;
 
     for (sal_uInt16 iLoop = 0; iLoop < nRowSpan; iLoop ++)
diff --git a/lotuswordpro/source/filter/lwprowlayout.cxx b/lotuswordpro/source/filter/lwprowlayout.cxx
index 507a849..906c09c 100644
--- a/lotuswordpro/source/filter/lwprowlayout.cxx
+++ b/lotuswordpro/source/filter/lwprowlayout.cxx
@@ -363,11 +363,14 @@ sal_uInt16 LwpRowLayout::GetCurMaxSpannedRows(sal_uInt8 nStartCol,sal_uInt8 nEnd
  */
 void LwpRowLayout::ConvertCommonRow(XFTable* pXFTable,sal_uInt8 nStartCol,sal_uInt8 nEndCol)
 {
+    LwpTableLayout* pTableLayout = GetParentTableLayout();
+    if (!pTableLayout)
+        return;
+
     XFRow* pRow = new XFRow;
     pRow->SetStyleName(m_StyleName);
 
     XFCell * pCell = nullptr;
-    LwpTableLayout* pTableLayout = GetParentTableLayout();
     LwpTable* pTable = pTableLayout->GetTable();
     sal_uInt8 nCellStartCol,nCellEndCol;
 
commit 22ee3194c930682ad8ac7f994084e877aa00d191
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Dec 10 09:42:04 2015 +0000

    guard against missing Foundry
    
    Change-Id: I9147dc2bab312639a04d2e822cf99745d38d3b8d

diff --git a/lotuswordpro/source/filter/lwppagelayout.cxx b/lotuswordpro/source/filter/lwppagelayout.cxx
index 8499126..7674868 100644
--- a/lotuswordpro/source/filter/lwppagelayout.cxx
+++ b/lotuswordpro/source/filter/lwppagelayout.cxx
@@ -264,8 +264,8 @@ void LwpPageLayout::ParseBackColor(XFPageMaster* pm1)
 void LwpPageLayout::ParseFootNoteSeparator(XFPageMaster * pm1)
 {
     //Get the footnoteoptions for the root document
-    LwpDocument* pDocument = m_pFoundry->GetDocument();
-    if(pDocument)
+    LwpDocument* pDocument = m_pFoundry ? m_pFoundry->GetDocument() : nullptr;
+    if (pDocument)
     {
         LwpObjectID* pFontnodeId = pDocument->GetValidFootnoteOpts();
 


More information about the Libreoffice-commits mailing list