[Libreoffice-commits] core.git: include/vcl vcl/inc vcl/opengl vcl/source

Michael Meeks michael.meeks at collabora.com
Wed Jan 6 01:17:38 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                 |   37 ++++++++++++----------
 vcl/opengl/texture.cxx               |   14 ++++++++
 vcl/source/opengl/OpenGLContext.cxx  |   38 +++++++++++++++++++++++
 vcl/source/opengl/OpenGLHelper.cxx   |    5 +++
 10 files changed, 120 insertions(+), 97 deletions(-)

New commits:
commit 1479ad1c632a7511468fc5133e4fd747062c376f
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Tue Jan 5 16:17:41 2016 +0000

    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.
    
    Change-Id: Ibbb2358c47156cd078ad28b6aad4f03af36aaf23
    Reviewed-on: https://gerrit.libreoffice.org/21127
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
    Tested-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index b2a0f09..de22444 100644
--- a/include/vcl/opengl/OpenGLContext.hxx
+++ b/include/vcl/opengl/OpenGLContext.hxx
@@ -174,6 +174,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 e9fd6f7..19dfa3c 100644
--- a/vcl/inc/opengl/salbmp.hxx
+++ b/vcl/inc/opengl/salbmp.hxx
@@ -37,7 +37,6 @@ class   BitmapPalette;
 class VCL_PLUGIN_PUBLIC OpenGLSalBitmap : public SalBitmap
 {
 private:
-    rtl::Reference<OpenGLContext>       mpContext;
     OpenGLTexture                       maTexture;
     bool                                mbDirtyTexture;
     BitmapPalette                       maPalette;
@@ -50,7 +49,6 @@ private:
     int                                 mnBufHeight;
     std::deque< OpenGLSalBitmapOp* >    maPendingOps;
 
-    void makeSomeOpenGLContextCurrent();
     virtual void updateChecksum() const override;
 
     bool calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType& rChecksum) const;
@@ -98,10 +96,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 63bebdc..0220758 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 7cbf73f..96fe028 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();
 }
@@ -2077,7 +2047,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 31038c3..9e59e23 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -104,8 +104,7 @@ static vcl::DeleteOnDeinit< TextureAtlasVector > gTextureAtlases(new TextureAtla
 }
 
 OpenGLSalBitmap::OpenGLSalBitmap()
-: mpContext(nullptr)
-, mbDirtyTexture(true)
+: mbDirtyTexture(true)
 , mnBits(0)
 , mnBytesPerRow(0)
 , mnWidth(0)
@@ -124,7 +123,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: ["
@@ -151,7 +150,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 );
@@ -421,7 +420,6 @@ Size OpenGLSalBitmap::GetSize() const
 
 void OpenGLSalBitmap::ExecuteOperations()
 {
-    makeSomeOpenGLContextCurrent();
     while( !maPendingOps.empty() )
     {
         OpenGLSalBitmapOp* pOp = maPendingOps.front();
@@ -488,7 +486,7 @@ GLuint OpenGLSalBitmap::CreateTexture()
         }
     }
 
-    makeSomeOpenGLContextCurrent();
+    OpenGLVCLContextZone aContextZone;
 
     lclInstantiateTexture(maTexture, mnBufWidth, mnBufHeight, nFormat, nType, pData);
 
@@ -516,11 +514,12 @@ bool OpenGLSalBitmap::ReadTexture()
     if( pData == nullptr )
         return false;
 
+    OpenGLVCLContextZone aContextZone;
+
     if (mnBits == 8 || mnBits == 16 || mnBits == 24 || mnBits == 32)
     {
         determineTextureFormat(mnBits, nFormat, nType);
 
-        makeSomeOpenGLContextCurrent();
         maTexture.Read(nFormat, nType, pData);
         mnBufWidth = mnWidth;
         mnBufHeight = mnHeight;
@@ -529,7 +528,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);
-        makeSomeOpenGLContextCurrent();
+
         sal_uInt8* pBuffer = aBuffer.data();
         determineTextureFormat(24, nFormat, nType);
         maTexture.Read(nFormat, nType, pBuffer);
@@ -585,6 +584,9 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
 {
     OUString FragShader("areaHashCRC64TFragmentShader");
 
+    OpenGLZone aZone;
+    rtl::Reference< OpenGLContext > xContext = OpenGLContext::getVCLContext();
+
     static vcl::DeleteOnDeinit<OpenGLTexture> gCRCTableTexture(
         new OpenGLTexture(512, 1, GL_RGBA, GL_UNSIGNED_BYTE,
                            vcl_get_crc64_table()));
@@ -595,7 +597,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;
 
@@ -603,7 +605,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 );
@@ -623,7 +625,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;
 
@@ -631,7 +633,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 );
@@ -663,7 +665,7 @@ void OpenGLSalBitmap::updateChecksum() const
 
     OpenGLSalBitmap* pThis = const_cast<OpenGLSalBitmap*>(this);
 
-    if (!mpContext.is())
+    if (!mbDirtyTexture)
     {
         pThis->CreateTexture();
     }
@@ -687,25 +689,9 @@ rtl::Reference<OpenGLContext> OpenGLSalBitmap::GetBitmapContext()
     return ImplGetDefaultWindow()->GetGraphics()->GetOpenGLContext();
 }
 
-void OpenGLSalBitmap::makeSomeOpenGLContextCurrent()
-{
-    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 )
     {
@@ -816,7 +802,7 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( BitmapAccessMode nMode )
 
 void OpenGLSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode )
 {
-    OpenGLZone aZone;
+    OpenGLVCLContextZone aContextZone;
 
     if( nMode == BITMAP_WRITE_ACCESS )
     {
@@ -871,23 +857,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();
-    makeSomeOpenGLContextCurrent();
-    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 6fab405..80bbdd6 100644
--- a/vcl/opengl/scale.cxx
+++ b/vcl/opengl/scale.cxx
@@ -37,6 +37,7 @@ using vcl::BilinearKernel;
 using vcl::BoxKernel;
 
 bool OpenGLSalBitmap::ImplScaleFilter(
+    const rtl::Reference< OpenGLContext > &xContext,
     const double& rScaleX,
     const double& rScaleY,
     GLenum        nFilter )
@@ -47,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();
@@ -112,6 +113,7 @@ void OpenGLSalBitmap::ImplCreateKernel(
 }
 
 bool OpenGLSalBitmap::ImplScaleConvolution(
+    const rtl::Reference< OpenGLContext > &xContext,
     const double& rScaleX,
     const double& rScaleY,
     const Kernel& aKernel )
@@ -126,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;
@@ -136,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++ )
         {
@@ -159,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++ )
         {
@@ -192,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 );
@@ -213,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 )
@@ -263,31 +266,32 @@ bool OpenGLSalBitmap::ImplScale( const double& rScaleX, const double& rScaleY, B
     VCL_GL_INFO( "::ImplScale" );
 
     maUserBuffer.reset();
-    makeSomeOpenGLContextCurrent();
+    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" );
@@ -296,7 +300,7 @@ bool OpenGLSalBitmap::ImplScale( const double& rScaleX, const double& rScaleY, B
 
 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
@@ -309,7 +313,6 @@ bool OpenGLSalBitmap::Scale( const double& rScaleX, const double& rScaleY, BmpSc
         nScaleFlag == BmpScaleFlag::Default ||
         nScaleFlag == BmpScaleFlag::BestQuality )
     {
-        makeSomeOpenGLContextCurrent();
         ImplScale( rScaleX, rScaleY, nScaleFlag );
         return true;
     }
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index 83aa3d4..303b8b8 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 );
@@ -152,13 +159,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 );
@@ -426,6 +438,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 1dc7d61..911a14d0 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -32,6 +32,7 @@
 #endif
 
 #include "svdata.hxx"
+#include "salgdi.hxx"
 
 #include <opengl/framebuffer.hxx>
 #include <opengl/program.hxx>
@@ -1443,6 +1444,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 32f2994..a8a62fc 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