[Libreoffice-commits] core.git: Branch 'libreoffice-5-1' - include/vcl vcl/inc vcl/opengl vcl/source

Michael Meeks michael.meeks at collabora.com
Wed Jan 6 22:18:07 PST 2016


 include/vcl/opengl/OpenGLContext.hxx |    5 +
 vcl/inc/opengl/salbmp.hxx            |    9 +--
 vcl/inc/opengl/zone.hxx              |    7 ++
 vcl/inc/openglgdiimpl.hxx            |    3 -
 vcl/opengl/gdiimpl.cxx               |   42 ++--------------
 vcl/opengl/salbmp.cxx                |   57 ++++++++--------------
 vcl/opengl/scale.cxx                 |   88 ++++++++---------------------------
 vcl/opengl/texture.cxx               |   14 +++++
 vcl/source/opengl/OpenGLContext.cxx  |   38 +++++++++++++++
 vcl/source/opengl/OpenGLHelper.cxx   |    5 +
 10 files changed, 121 insertions(+), 147 deletions(-)

New commits:
commit 342930aaa26ec1a66f432435c7b0f962007b44a8
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Tue Dec 8 16:44:19 2015 +0200

    vcl: opengl - Kill the last glErrors on common paths.
    
    Re-work the makeSomeOpenGLContextCurrent logic into a shared function
    with the existing AcquireContext logic in the SalOpenGLGraphics impl.
    Use an OpenGLVCLContextZone placeholder to do both context and zone
    management - to include destructors into the zone.
    
    Fix a number of error cases around SalBitmaps where we did not have
    a GL context associated when allocating, and/or freeing textures..
    
    Don't drag a (potentially) slower context around in the
    OpenGLSalBitmap when we're going to check / fetch a better VCL
    context anyway.
    
    Remove ScaleOp pieces to synchronize with master for maintenance.
    
    Change-Id: Ibbb2358c47156cd078ad28b6aad4f03af36aaf23
    Reviewed-on: https://gerrit.libreoffice.org/21149
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index a6d753f..a565f5b 100644
--- a/include/vcl/opengl/OpenGLContext.hxx
+++ b/include/vcl/opengl/OpenGLContext.hxx
@@ -177,6 +177,11 @@ public:
     static void prepareForYield();
     /// Is there a current GL context ?
     static bool hasCurrent();
+
+    /// make a VCL context (any context) current, create it if necessary.
+    static void makeVCLCurrent();
+    /// fetch any VCL context, creating one if @bMakeIfNecessary is set.
+    static rtl::Reference<OpenGLContext> getVCLContext(bool bMakeIfNecessary = true);
     /// make this GL context current - so it is implicit in subsequent GL calls
     void makeCurrent();
     /// Put this GL context to the end of the context list.
diff --git a/vcl/inc/opengl/salbmp.hxx b/vcl/inc/opengl/salbmp.hxx
index dcf2f17..7d1efa3 100644
--- a/vcl/inc/opengl/salbmp.hxx
+++ b/vcl/inc/opengl/salbmp.hxx
@@ -39,7 +39,6 @@ class   BitmapPalette;
 class VCL_PLUGIN_PUBLIC OpenGLSalBitmap : public SalBitmap
 {
 private:
-    rtl::Reference<OpenGLContext>       mpContext;
     OpenGLTexture                       maTexture;
     bool                                mbDirtyTexture;
     BitmapPalette                       maPalette;
@@ -52,7 +51,6 @@ private:
     int                                 mnBufHeight;
     std::deque< OpenGLSalBitmapOp* >    maPendingOps;
 
-    void makeCurrent();
     virtual void updateChecksum() const override;
 
     bool calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType& rChecksum) const;
@@ -100,10 +98,11 @@ private:
 
 private:
 
-    bool ImplScaleFilter( const double& rScaleX, const double& rScaleY, GLenum nFilter );
+    bool ImplScaleFilter( const rtl::Reference< OpenGLContext > &xContext, const double& rScaleX, const double& rScaleY, GLenum nFilter );
     static void ImplCreateKernel( const double& fScale, const vcl::Kernel& rKernel, GLfloat*& pWeights, sal_uInt32& aKernelSize );
-    bool ImplScaleConvolution(const double& rScaleX, const double& rScaleY, const vcl::Kernel& rKernel);
-    bool ImplScaleArea( double rScaleX, double rScaleY );
+    bool ImplScaleConvolution(const rtl::Reference< OpenGLContext > &xContext, const double& rScaleX, const double& rScaleY, const vcl::Kernel& rKernel);
+    bool ImplScaleArea( const rtl::Reference< OpenGLContext > &xContext,
+                        double rScaleX, double rScaleY );
 
 public:
 
diff --git a/vcl/inc/opengl/zone.hxx b/vcl/inc/opengl/zone.hxx
index 44265c5..c6ba0ccc7 100644
--- a/vcl/inc/opengl/zone.hxx
+++ b/vcl/inc/opengl/zone.hxx
@@ -40,6 +40,13 @@ public:
     static void hardDisable();
 };
 
+/// Create this to not only enter the zone, but set VCL context.
+class OpenGLVCLContextZone {
+    OpenGLZone aZone;
+public:
+    OpenGLVCLContextZone();
+};
+
 #endif // INCLUDED_VCL_INC_OPENGL_ZONE_H
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 647c83f..14beab5 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -162,9 +162,6 @@ protected:
     bool AcquireContext(bool bForceCreate = false);
     bool ReleaseContext();
 
-    /// retrieve the default context for offscreen rendering
-    static rtl::Reference<OpenGLContext> GetDefaultContext();
-
     /// create a new context for rendering to the underlying window
     virtual rtl::Reference<OpenGLContext> CreateWinContext() = 0;
 
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index c236125..8c31f5e 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -97,52 +97,22 @@ rtl::Reference<OpenGLContext> OpenGLSalGraphicsImpl::GetOpenGLContext()
     return mpContext;
 }
 
-rtl::Reference<OpenGLContext> OpenGLSalGraphicsImpl::GetDefaultContext()
-{
-    return ImplGetDefaultWindow()->GetGraphics()->GetOpenGLContext();
-}
-
 bool OpenGLSalGraphicsImpl::AcquireContext( bool bForceCreate )
 {
-    ImplSVData* pSVData = ImplGetSVData();
-
-    // We always prefer to bind our VirtualDevice / offscreen graphics
-    // to the current OpenGLContext - to avoid switching contexts.
-    if (mpContext.is() && OpenGLContext::hasCurrent() && !mpContext->isCurrent())
-    {
-        mpContext.clear();
-    }
+    mpContext = OpenGLContext::getVCLContext( false );
 
-    if( mpContext.is() )
+    if( !mpContext.is() && mpWindowContext.is() )
     {
-        // Check whether the context was reset underneath us.
-        if( mpContext->isInitialized() )
-            return true;
-        mpContext.clear();
-    }
-
-    // We don't care what context we have - but not switching context
-    // is rather useful from a performance perspective.
-    OpenGLContext *pContext = pSVData->maGDIData.mpLastContext;
-    while( pContext )
-    {
-        // check if this context can be used by this SalGraphicsImpl instance
-        if( UseContext( pContext ) )
-            break;
-        pContext = pContext->mpPrevContext;
-    }
-
-    if( mpContext.is() )
-        mpContext = pContext;
-    else if( mpWindowContext.is() )
         mpContext = mpWindowContext;
+    }
     else if( bForceCreate && !IsOffscreen() )
     {
         mpWindowContext = CreateWinContext();
         mpContext = mpWindowContext;
     }
+
     if( !mpContext.is() )
-        mpContext = GetDefaultContext();
+        mpContext = OpenGLContext::getVCLContext( true );
 
     return mpContext.is();
 }
@@ -2060,7 +2030,7 @@ void OpenGLSalGraphicsImpl::doFlush()
     VCL_GL_INFO( "Texture height " << maOffscreenTex.GetHeight() << " vs. window height " << GetHeight() );
 
     OpenGLProgram *pProgram =
-        mpWindowContext->UseProgram( "textureVertexShader", "textureFragmentShader", "" );
+        mpWindowContext->UseProgram( "textureVertexShader", "textureFragmentShader", "// flush shader\n" ); // flush helps profiling
     if( !pProgram )
         VCL_GL_INFO( "Can't compile simple copying shader !" );
     else
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index 0c6ea6d..e9608a6 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -102,8 +102,7 @@ static std::vector<std::unique_ptr<FixedTextureAtlasManager>> sTextureAtlases;
 }
 
 OpenGLSalBitmap::OpenGLSalBitmap()
-: mpContext(nullptr)
-, mbDirtyTexture(true)
+: mbDirtyTexture(true)
 , mnBits(0)
 , mnBytesPerRow(0)
 , mnWidth(0)
@@ -122,7 +121,7 @@ OpenGLSalBitmap::~OpenGLSalBitmap()
 bool OpenGLSalBitmap::Create( const OpenGLTexture& rTex, long nX, long nY, long nWidth, long nHeight )
 {
     static const BitmapPalette aEmptyPalette;
-    OpenGLZone aZone;
+    OpenGLVCLContextZone aContextZone;
 
     Destroy();
     VCL_GL_INFO( "OpenGLSalBitmap::Create from FBO: ["
@@ -149,7 +148,7 @@ bool OpenGLSalBitmap::Create( const OpenGLTexture& rTex, long nX, long nY, long
 
 bool OpenGLSalBitmap::Create( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rBitmapPalette )
 {
-    OpenGLZone aZone;
+    OpenGLVCLContextZone aContextZone;
 
     Destroy();
     VCL_GL_INFO( "OpenGLSalBitmap::Create with size: " << rSize );
@@ -418,7 +417,6 @@ Size OpenGLSalBitmap::GetSize() const
 
 void OpenGLSalBitmap::ExecuteOperations()
 {
-    makeCurrent();
     while( !maPendingOps.empty() )
     {
         OpenGLSalBitmapOp* pOp = maPendingOps.front();
@@ -485,7 +483,7 @@ GLuint OpenGLSalBitmap::CreateTexture()
         }
     }
 
-    makeCurrent();
+    OpenGLVCLContextZone aContextZone;
 
     lclInstantiateTexture(maTexture, mnBufWidth, mnBufHeight, nFormat, nType, pData);
 
@@ -513,11 +511,12 @@ bool OpenGLSalBitmap::ReadTexture()
     if( pData == nullptr )
         return false;
 
+    OpenGLVCLContextZone aContextZone;
+
     if (mnBits == 8 || mnBits == 16 || mnBits == 24 || mnBits == 32)
     {
         determineTextureFormat(mnBits, nFormat, nType);
 
-        makeCurrent();
         maTexture.Read(nFormat, nType, pData);
         mnBufWidth = mnWidth;
         mnBufHeight = mnHeight;
@@ -526,7 +525,7 @@ bool OpenGLSalBitmap::ReadTexture()
     else if (mnBits == 1)
     {   // convert buffers from 24-bit RGB to 1-bit Mask
         std::vector<sal_uInt8> aBuffer(mnWidth * mnHeight * 3);
-        makeCurrent();
+
         sal_uInt8* pBuffer = aBuffer.data();
         determineTextureFormat(24, nFormat, nType);
         maTexture.Read(nFormat, nType, pBuffer);
@@ -582,6 +581,9 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
 {
     OUString FragShader("areaHashCRC64TFragmentShader");
 
+    OpenGLZone aZone;
+    rtl::Reference< OpenGLContext > xContext = OpenGLContext::getVCLContext();
+
     static const OpenGLTexture aCRCTableTexture(512, 1, GL_RGBA, GL_UNSIGNED_BYTE,
             vcl_get_crc64_table());
 
@@ -590,7 +592,7 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
     int nWidth = rInputTexture.GetWidth();
     int nHeight = rInputTexture.GetHeight();
 
-    OpenGLProgram* pProgram = mpContext->UseProgram("textureVertexShader", FragShader);
+    OpenGLProgram* pProgram = xContext->UseProgram("textureVertexShader", FragShader);
     if (pProgram == nullptr)
         return false;
 
@@ -598,7 +600,7 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
     int nNewHeight = ceil( nHeight / 4.0 );
 
     OpenGLTexture aFirstPassTexture = OpenGLTexture(nNewWidth, nNewHeight);
-    OpenGLFramebuffer* pFramebuffer = mpContext->AcquireFramebuffer(aFirstPassTexture);
+    OpenGLFramebuffer* pFramebuffer = xContext->AcquireFramebuffer(aFirstPassTexture);
 
     pProgram->SetUniform1f( "xstep", 1.0 / mnWidth );
     pProgram->SetUniform1f( "ystep", 1.0 / mnHeight );
@@ -618,7 +620,7 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
     nWidth = aFirstPassTexture.GetWidth();
     nHeight = aFirstPassTexture.GetHeight();
 
-    pProgram = mpContext->UseProgram("textureVertexShader", FragShader);
+    pProgram = xContext->UseProgram("textureVertexShader", FragShader);
     if (pProgram == nullptr)
         return false;
 
@@ -626,7 +628,7 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
     nNewHeight = ceil( nHeight / 4.0 );
 
     OpenGLTexture aSecondPassTexture = OpenGLTexture(nNewWidth, nNewHeight);
-    pFramebuffer = mpContext->AcquireFramebuffer(aSecondPassTexture);
+    pFramebuffer = xContext->AcquireFramebuffer(aSecondPassTexture);
 
     pProgram->SetUniform1f( "xstep", 1.0 / mnWidth );
     pProgram->SetUniform1f( "ystep", 1.0 / mnHeight );
@@ -658,7 +660,7 @@ void OpenGLSalBitmap::updateChecksum() const
 
     OpenGLSalBitmap* pThis = const_cast<OpenGLSalBitmap*>(this);
 
-    if (!mpContext.is())
+    if (!mbDirtyTexture)
     {
         pThis->CreateTexture();
     }
@@ -682,25 +684,9 @@ rtl::Reference<OpenGLContext> OpenGLSalBitmap::GetBitmapContext()
     return ImplGetDefaultWindow()->GetGraphics()->GetOpenGLContext();
 }
 
-void OpenGLSalBitmap::makeCurrent()
-{
-    ImplSVData* pSVData = ImplGetSVData();
-
-    // TODO: make sure we can really use the last used context
-    OpenGLContext *pContext = pSVData->maGDIData.mpLastContext;
-    while( pContext && !pContext->isInitialized() )
-        pContext = pContext->mpPrevContext;
-    if( pContext )
-        mpContext = pContext;
-    else
-        mpContext = GetBitmapContext();
-    assert(mpContext.is() && "Couldn't get an OpenGL context");
-    mpContext->makeCurrent();
-}
-
 BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( BitmapAccessMode nMode )
 {
-    OpenGLZone aZone;
+    OpenGLVCLContextZone aContextZone;
 
     if( nMode != BITMAP_INFO_ACCESS )
     {
@@ -811,7 +797,7 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( BitmapAccessMode nMode )
 
 void OpenGLSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode )
 {
-    OpenGLZone aZone;
+    OpenGLVCLContextZone aContextZone;
 
     if( nMode == BITMAP_WRITE_ACCESS )
     {
@@ -866,23 +852,22 @@ bool OpenGLSalBitmap::GetSystemData( BitmapSystemData& /*rData*/ )
 
 bool OpenGLSalBitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
 {
-
     VCL_GL_INFO("::Replace");
 
     OpenGLZone aZone;
+    rtl::Reference< OpenGLContext > xContext = OpenGLContext::getVCLContext();
 
     OpenGLFramebuffer* pFramebuffer;
     OpenGLProgram* pProgram;
 
     GetTexture();
-    makeCurrent();
-    pProgram = mpContext->UseProgram( "textureVertexShader",
-                                      "replaceColorFragmentShader" );
+    pProgram = xContext->UseProgram( "textureVertexShader",
+                                     "replaceColorFragmentShader" );
     if( !pProgram )
         return false;
 
     OpenGLTexture aNewTex = OpenGLTexture( mnWidth, mnHeight );
-    pFramebuffer = mpContext->AcquireFramebuffer( aNewTex );
+    pFramebuffer = xContext->AcquireFramebuffer( aNewTex );
 
     pProgram->SetTexture( "sampler", maTexture );
     pProgram->SetColor( "search_color", rSearchColor );
diff --git a/vcl/opengl/scale.cxx b/vcl/opengl/scale.cxx
index 102ec73..80bbdd6 100644
--- a/vcl/opengl/scale.cxx
+++ b/vcl/opengl/scale.cxx
@@ -24,7 +24,6 @@
 #include "vcl/bitmap.hxx"
 
 #include "opengl/zone.hxx"
-#include "opengl/bmpop.hxx"
 #include "opengl/salbmp.hxx"
 #include "opengl/program.hxx"
 #include "opengl/texture.hxx"
@@ -37,22 +36,8 @@ using vcl::BicubicKernel;
 using vcl::BilinearKernel;
 using vcl::BoxKernel;
 
-class ScaleOp : public OpenGLSalBitmapOp
-{
-private:
-    OpenGLSalBitmap*    mpBitmap;
-    double              mfScaleX;
-    double              mfScaleY;
-    BmpScaleFlag        mnScaleFlag;
-
-public:
-    ScaleOp( OpenGLSalBitmap* pBitmap, const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag );
-
-    bool Execute() override;
-    void GetSize( Size& rSize ) const override;
-};
-
 bool OpenGLSalBitmap::ImplScaleFilter(
+    const rtl::Reference< OpenGLContext > &xContext,
     const double& rScaleX,
     const double& rScaleY,
     GLenum        nFilter )
@@ -63,13 +48,13 @@ bool OpenGLSalBitmap::ImplScaleFilter(
     int nNewWidth( mnWidth * rScaleX );
     int nNewHeight( mnHeight * rScaleY );
 
-    pProgram = mpContext->UseProgram( "textureVertexShader",
-                                      "textureFragmentShader" );
+    pProgram = xContext->UseProgram( "textureVertexShader",
+                                     "textureFragmentShader" );
     if( !pProgram )
         return false;
 
     OpenGLTexture aNewTex(nNewWidth, nNewHeight);
-    pFramebuffer = mpContext->AcquireFramebuffer( aNewTex );
+    pFramebuffer = xContext->AcquireFramebuffer( aNewTex );
 
     pProgram->SetTexture( "sampler", maTexture );
     nOldFilter = maTexture.GetFilter();
@@ -128,6 +113,7 @@ void OpenGLSalBitmap::ImplCreateKernel(
 }
 
 bool OpenGLSalBitmap::ImplScaleConvolution(
+    const rtl::Reference< OpenGLContext > &xContext,
     const double& rScaleX,
     const double& rScaleY,
     const Kernel& aKernel )
@@ -142,7 +128,7 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
 
     // TODO Make sure the framebuffer is alright
 
-    pProgram = mpContext->UseProgram( "textureVertexShader",
+    pProgram = xContext->UseProgram( "textureVertexShader",
                                       "convolutionFragmentShader" );
     if( pProgram == nullptr )
         return false;
@@ -152,7 +138,7 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
     {
         OpenGLTexture aScratchTex(nNewWidth, nNewHeight);
 
-        pFramebuffer = mpContext->AcquireFramebuffer( aScratchTex );
+        pFramebuffer = xContext->AcquireFramebuffer( aScratchTex );
 
         for( sal_uInt32 i = 0; i < 16; i++ )
         {
@@ -175,7 +161,7 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
     {
         OpenGLTexture aScratchTex(nNewWidth, nNewHeight);
 
-        pFramebuffer = mpContext->AcquireFramebuffer( aScratchTex );
+        pFramebuffer = xContext->AcquireFramebuffer( aScratchTex );
 
         for( sal_uInt32 i = 0; i < 16; i++ )
         {
@@ -208,7 +194,8 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
  the generic case needs to also consider that some source pixels contribute
  only partially to their resulting pixels (because of non-integer multiples).
 */
-bool OpenGLSalBitmap::ImplScaleArea( double rScaleX, double rScaleY )
+bool OpenGLSalBitmap::ImplScaleArea( const rtl::Reference< OpenGLContext > &xContext,
+                                     double rScaleX, double rScaleY )
 {
     int nNewWidth( mnWidth * rScaleX );
     int nNewHeight( mnHeight * rScaleY );
@@ -229,14 +216,14 @@ bool OpenGLSalBitmap::ImplScaleArea( double rScaleX, double rScaleY )
 
     // TODO Make sure the framebuffer is alright
 
-    OpenGLProgram* pProgram = mpContext->UseProgram( "textureVertexShader",
+    OpenGLProgram* pProgram = xContext->UseProgram( "textureVertexShader",
         fast ? OUString( "areaScaleFastFragmentShader" ) : OUString( "areaScaleFragmentShader" ));
     if( pProgram == nullptr )
         return false;
 
     OpenGLTexture aScratchTex(nNewWidth, nNewHeight);
 
-    OpenGLFramebuffer* pFramebuffer = mpContext->AcquireFramebuffer( aScratchTex );
+    OpenGLFramebuffer* pFramebuffer = xContext->AcquireFramebuffer( aScratchTex );
 
     // NOTE: This setup is also done in OpenGLSalGraphicsImpl::DrawTransformedTexture().
     if( fast )
@@ -279,65 +266,41 @@ bool OpenGLSalBitmap::ImplScale( const double& rScaleX, const double& rScaleY, B
     VCL_GL_INFO( "::ImplScale" );
 
     maUserBuffer.reset();
-    makeCurrent();
+    OpenGLVCLContextZone aContextZone;
+    rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
 
     if( nScaleFlag == BmpScaleFlag::Fast )
     {
-        return ImplScaleFilter( rScaleX, rScaleY, GL_NEAREST );
+        return ImplScaleFilter( xContext, rScaleX, rScaleY, GL_NEAREST );
     }
     if( nScaleFlag == BmpScaleFlag::BiLinear )
     {
-        return ImplScaleFilter( rScaleX, rScaleY, GL_LINEAR );
+        return ImplScaleFilter( xContext, rScaleX, rScaleY, GL_LINEAR );
     }
     else if( nScaleFlag == BmpScaleFlag::Super || nScaleFlag == BmpScaleFlag::Default )
     {
         const Lanczos3Kernel aKernel;
 
-        return ImplScaleConvolution( rScaleX, rScaleY, aKernel );
+        return ImplScaleConvolution( xContext, rScaleX, rScaleY, aKernel );
     }
     else if( nScaleFlag == BmpScaleFlag::BestQuality && rScaleX <= 1 && rScaleY <= 1 )
     { // Use are scaling for best quality, but only if downscaling.
-        return ImplScaleArea( rScaleX, rScaleY );
+        return ImplScaleArea( xContext, rScaleX, rScaleY );
     }
     else if( nScaleFlag == BmpScaleFlag::Lanczos || nScaleFlag == BmpScaleFlag::BestQuality  )
     {
         const Lanczos3Kernel aKernel;
 
-        return ImplScaleConvolution( rScaleX, rScaleY, aKernel );
+        return ImplScaleConvolution( xContext, rScaleX, rScaleY, aKernel );
     }
 
     SAL_WARN( "vcl.opengl", "Invalid flag for scaling operation" );
     return false;
 }
 
-ScaleOp::ScaleOp(
-    OpenGLSalBitmap* pBitmap,
-    const double& rScaleX,
-    const double& rScaleY,
-    BmpScaleFlag nScaleFlag )
-: mpBitmap( pBitmap )
-, mfScaleX( rScaleX )
-, mfScaleY( rScaleY )
-, mnScaleFlag( nScaleFlag )
-{
-}
-
-bool ScaleOp::Execute()
-{
-    VCL_GL_INFO( "::Execute" );
-    return mpBitmap->ImplScale( mfScaleX, mfScaleY, mnScaleFlag );
-}
-
-void ScaleOp::GetSize( Size& rSize ) const
-{
-    VCL_GL_INFO( "::GetSize" );
-    rSize.setWidth( rSize.Width() * mfScaleX );
-    rSize.setHeight( rSize.Height() * mfScaleY );
-}
-
 bool OpenGLSalBitmap::Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag )
 {
-    OpenGLZone aZone;
+    OpenGLVCLContextZone aContextZone;
 
     VCL_GL_INFO("::Scale " << int(nScaleFlag)
              << " from " << mnWidth << "x" << mnHeight
@@ -350,16 +313,7 @@ bool OpenGLSalBitmap::Scale( const double& rScaleX, const double& rScaleY, BmpSc
         nScaleFlag == BmpScaleFlag::Default ||
         nScaleFlag == BmpScaleFlag::BestQuality )
     {
-        makeCurrent();
-        if( mpContext == nullptr )
-        {
-            VCL_GL_INFO( "Add ScaleOp to pending operations" );
-            maPendingOps.push_back( new ScaleOp( this, rScaleX, rScaleY, nScaleFlag ) );
-        }
-        else
-        {
-            ImplScale( rScaleX, rScaleY, nScaleFlag );
-        }
+        ImplScale( rScaleX, rScaleY, nScaleFlag );
         return true;
     }
 
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index bf4aa1d..3edd1ba 100644
--- a/vcl/opengl/texture.cxx
+++ b/vcl/opengl/texture.cxx
@@ -28,6 +28,7 @@
 
 #include "opengl/framebuffer.hxx"
 #include "opengl/texture.hxx"
+#include "opengl/zone.hxx"
 
 // texture with allocated size
 ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate ) :
@@ -38,6 +39,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate )
     mnOptStencil( 0 ),
     mnFreeSlots(-1)
 {
+    OpenGLVCLContextZone aContextZone;
+
     glGenTextures( 1, &mnTexture );
     CHECK_GL_ERROR();
     glBindTexture( GL_TEXTURE_2D, mnTexture );
@@ -71,6 +74,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight )
     mnOptStencil( 0 ),
     mnFreeSlots(-1)
 {
+    OpenGLVCLContextZone aContextZone;
+
     // FIXME We need the window height here
     // nY = GetHeight() - nHeight - nY;
 
@@ -104,6 +109,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int
     mnOptStencil( 0 ),
     mnFreeSlots(-1)
 {
+    OpenGLVCLContextZone aContextZone;
+
     if( !mnTexture )
     {
         glGenTextures( 1, &mnTexture );
@@ -149,13 +156,18 @@ ImplOpenGLTexture::~ImplOpenGLTexture()
     VCL_GL_INFO( "~OpenGLTexture " << mnTexture );
     if( mnTexture != 0 )
     {
+        OpenGLVCLContextZone aContextZone;
+
         // FIXME: this is really not optimal performance-wise.
 
         // Check we have been correctly un-bound from all framebuffers.
         ImplSVData* pSVData = ImplGetSVData();
         rtl::Reference<OpenGLContext> pContext = pSVData->maGDIData.mpLastContext;
         if( pContext.is() )
+        {
+            pContext->makeCurrent();
             pContext->UnbindTextureFromFramebuffers( mnTexture );
+        }
 
         if( mnOptStencil != 0 )
             glDeleteRenderbuffers( 1, &mnOptStencil );
@@ -428,6 +440,8 @@ void OpenGLTexture::Read( GLenum nFormat, GLenum nType, sal_uInt8* pData )
         return;
     }
 
+    OpenGLVCLContextZone aContextZone;
+
     VCL_GL_INFO( "Reading texture " << Id() << " " << GetWidth() << "x" << GetHeight() );
 
     if( GetWidth() == mpImpl->mnWidth && GetHeight() == mpImpl->mnHeight )
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index 771b548..80c0173 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -31,6 +31,7 @@
 #endif
 
 #include "svdata.hxx"
+#include "salgdi.hxx"
 
 #include <opengl/framebuffer.hxx>
 #include <opengl/program.hxx>
@@ -1434,6 +1435,43 @@ void OpenGLContext::makeCurrent()
     registerAsCurrent();
 }
 
+rtl::Reference<OpenGLContext> OpenGLContext::getVCLContext(bool bMakeIfNecessary)
+{
+    ImplSVData* pSVData = ImplGetSVData();
+    OpenGLContext *pContext = pSVData->maGDIData.mpLastContext;
+    while( pContext )
+    {
+        // check if this context is usable
+        if( pContext->isInitialized() && pContext->isVCLOnly() )
+            break;
+        pContext = pContext->mpPrevContext;
+    }
+    rtl::Reference<OpenGLContext> xContext;
+    if( !pContext && bMakeIfNecessary )
+    {
+        // create our magic fallback window context.
+        xContext = ImplGetDefaultContextWindow()->GetGraphics()->GetOpenGLContext();
+        assert(xContext.is());
+    }
+    else
+        xContext = pContext;
+
+    if( xContext.is() )
+        xContext->makeCurrent();
+
+    return xContext;
+}
+
+/*
+ * We don't care what context we have, but we want one that is live,
+ * ie. not reset underneath us, and is setup for VCL usage - ideally
+ * not swapping context at all.
+ */
+void OpenGLContext::makeVCLCurrent()
+{
+    getVCLContext(true);
+}
+
 void OpenGLContext::registerAsCurrent()
 {
     ImplSVData* pSVData = ImplGetSVData();
diff --git a/vcl/source/opengl/OpenGLHelper.cxx b/vcl/source/opengl/OpenGLHelper.cxx
index f1e1660..ee3e1b6 100644
--- a/vcl/source/opengl/OpenGLHelper.cxx
+++ b/vcl/source/opengl/OpenGLHelper.cxx
@@ -943,6 +943,11 @@ void OpenGLZone::hardDisable()
     }
 }
 
+OpenGLVCLContextZone::OpenGLVCLContextZone()
+{
+    OpenGLContext::makeVCLCurrent();
+}
+
 bool OpenGLHelper::isVCLOpenGLEnabled()
 {
     /**


More information about the Libreoffice-commits mailing list