[Libreoffice-commits] core.git: Branch 'feature/opengl-vcl' - 2 commits - vcl/inc vcl/Library_vcl.mk vcl/opengl vcl/Package_opengl.mk vcl/source

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Thu Nov 6 11:23:18 PST 2014


 vcl/Library_vcl.mk                        |    1 
 vcl/Package_opengl.mk                     |    1 
 vcl/inc/opengl/bmpop.hxx                  |   35 +++
 vcl/inc/opengl/salbmp.hxx                 |   48 +++-
 vcl/inc/opengl/texture.hxx                |   54 +++++
 vcl/opengl/convolutionFragmentShader.glsl |   28 ++
 vcl/opengl/gdiimpl.cxx                    |   22 +-
 vcl/opengl/salbmp.cxx                     |  136 +++++--------
 vcl/opengl/scale.cxx                      |  308 ++++++++++++++++++++++++++++++
 vcl/opengl/texture.cxx                    |   56 +++++
 vcl/opengl/texture.hxx                    |   48 ----
 vcl/source/gdi/bitmap3.cxx                |   17 +
 12 files changed, 608 insertions(+), 146 deletions(-)

New commits:
commit fd3855cc2bfd31d3d6792bc0d1dab85fcaf72b84
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Thu Nov 6 14:22:15 2014 -0500

    vcl: Add some debug trace
    
    Change-Id: Ie737e30bbd481be9d8f69179fe6ae27bcae8127e

diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index f2d53f5..868728d 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -57,7 +57,7 @@ bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
 {
     const basegfx::B2DPolyPolygon aClip( rClip.GetAsB2DPolyPolygon() );
 
-    glEnable(GL_STENCIL_TEST);
+    /*glEnable(GL_STENCIL_TEST);
 
     glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
     glDepthMask( GL_FALSE );
@@ -71,7 +71,7 @@ bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
     glDepthMask( GL_TRUE );
     glStencilMask( 0x00 );
-    glStencilFunc(GL_EQUAL, 1, 0xFF);
+    glStencilFunc(GL_EQUAL, 1, 0xFF);*/
 
     return true;
 }
@@ -166,6 +166,7 @@ bool OpenGLSalGraphicsImpl::CreateSolidProgram( void )
     if( mnSolidProgram == 0 )
         return false;
 
+    SAL_INFO( "vcl.opengl", "Solid Program Created" );
     glBindAttribLocation( mnSolidProgram, GL_ATTRIB_POS, "position" );
     mnColorUniform = glGetUniformLocation( mnSolidProgram, "color" );
     return true;
@@ -213,6 +214,8 @@ void OpenGLSalGraphicsImpl::BeginSolid( SalColor nColor, sal_uInt8 nTransparency
 {
     if( mnSolidProgram == 0 )
     {
+        glClearColor( 1, 1, 1, 1 );
+        glClear( GL_COLOR_BUFFER_BIT );
         if( !CreateSolidProgram() )
             return;
     }
@@ -410,9 +413,11 @@ void OpenGLSalGraphicsImpl::DrawTexture( GLuint nTexture, const Size& rSize, con
     glUseProgram( mnTextureProgram );
     glUniform1i( mnSamplerUniform, 0 );
     glActiveTexture( GL_TEXTURE0 );
+    CHECK_GL_ERROR();
     glBindTexture( GL_TEXTURE_2D, nTexture );
 
     DrawTextureRect( rSize, pPosAry );
+    CHECK_GL_ERROR();
 
     glBindTexture( GL_TEXTURE_2D, 0 );
     glUseProgram( 0 );
@@ -468,6 +473,7 @@ void OpenGLSalGraphicsImpl::DrawMask( GLuint nMask, SalColor nMaskColor, const S
 // draw --> LineColor and FillColor and RasterOp and ClipRegion
 void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY )
 {
+    SAL_INFO( "vcl.opengl", "::drawPixel" );
     if( mnLineColor != SALCOLOR_NONE )
     {
         maContext.makeCurrent();
@@ -479,6 +485,7 @@ void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY )
 
 void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY, SalColor nSalColor )
 {
+    SAL_INFO( "vcl.opengl", "::drawPixel" );
     if( nSalColor != SALCOLOR_NONE )
     {
         maContext.makeCurrent();
@@ -490,6 +497,7 @@ void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY, SalColor nSalColor )
 
 void OpenGLSalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 )
 {
+    SAL_INFO( "vcl.opengl", "::drawLine" );
     if( mnLineColor != SALCOLOR_NONE )
     {
         maContext.makeCurrent();
@@ -501,6 +509,7 @@ void OpenGLSalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 )
 
 void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeight )
 {
+    SAL_INFO( "vcl.opengl", "::drawRect" );
     maContext.makeCurrent();
     glViewport( 0, 0, GetWidth(), GetHeight() );
 
@@ -528,6 +537,7 @@ void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeigh
 
 void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
 {
+    SAL_INFO( "vcl.opengl", "::drawPolyLine" );
     maContext.makeCurrent();
 
     if( mnLineColor != SALCOLOR_NONE && nPoints > 1 )
@@ -540,6 +550,7 @@ void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pP
 
 void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
 {
+    SAL_INFO( "vcl.opengl", "::drawPolygon" );
     if( nPoints == 0 )
         return;
     if( nPoints == 1 )
@@ -573,6 +584,7 @@ void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPt
 
 void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry )
 {
+    SAL_INFO( "vcl.opengl", "::drawPolyPolygon" );
     if( nPoly <= 0 )
         return;
 
@@ -643,6 +655,7 @@ void OpenGLSalGraphicsImpl::copyArea(
             long /*nSrcWidth*/, long /*nSrcHeight*/,
             sal_uInt16 /*nFlags*/ )
 {
+    SAL_INFO( "vcl.opengl", "::copyArea" );
 }
 
 // CopyBits and DrawBitmap --> RasterOp and ClipRegion
@@ -652,6 +665,7 @@ void OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* /*
     // TODO Check if SalGraphicsImpl is the same
     const bool bSameGraphics( false );
 
+    SAL_INFO( "vcl.opengl", "::copyBits" );
     if( bSameGraphics &&
         (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) &&
         (rPosAry.mnSrcHeight == rPosAry.mnDestHeight))
@@ -712,6 +726,7 @@ void OpenGLSalGraphicsImpl::drawMask(
     const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
     const GLuint nTexture( rBitmap.GetTexture( maContext ) );
 
+    SAL_INFO( "vcl.opengl", "::drawMask" );
     maContext.makeCurrent();
     DrawMask( nTexture, nMaskColor, rPosAry );
 }
@@ -719,6 +734,7 @@ void OpenGLSalGraphicsImpl::drawMask(
 SalBitmap* OpenGLSalGraphicsImpl::getBitmap( long nX, long nY, long nWidth, long nHeight )
 {
     OpenGLSalBitmap* pBitmap = new OpenGLSalBitmap;
+    SAL_INFO( "vcl.opengl", "::getBitmap" );
     if( !pBitmap->Create( maContext, nX, nY, nWidth, nHeight ) )
     {
         delete pBitmap;
commit e12d7993865763087ea2b456cd6c5c2cced066d2
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date:   Thu Nov 6 14:17:24 2014 -0500

    vcl: Add a way to resize an image using the GPU
    
    Change-Id: I949e13277fa176d64d7fba9a57e3ca6f3f0dd732

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 28e6328..efe0986 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -124,6 +124,7 @@ $(eval $(call gb_Library_use_externals,vcl,\
 $(eval $(call gb_Library_add_exception_objects,vcl,\
 	vcl/opengl/gdiimpl \
 	vcl/opengl/salbmp \
+	vcl/opengl/scale \
 	vcl/opengl/texture \
     vcl/source/opengl/OpenGLContext \
     vcl/source/opengl/OpenGLHelper \
diff --git a/vcl/Package_opengl.mk b/vcl/Package_opengl.mk
index 9b8f745..79dabb7 100644
--- a/vcl/Package_opengl.mk
+++ b/vcl/Package_opengl.mk
@@ -10,6 +10,7 @@
 $(eval $(call gb_Package_Package,vcl_opengl_shader,$(SRCDIR)/vcl/opengl))
 
 $(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\
+	convolutionFragmentShader.glsl \
 	maskFragmentShader.glsl \
 	maskVertexShader.glsl \
 	maskedTextureFragmentShader.glsl \
diff --git a/vcl/inc/opengl/bmpop.hxx b/vcl/inc/opengl/bmpop.hxx
new file mode 100644
index 0000000..d19410b
--- /dev/null
+++ b/vcl/inc/opengl/bmpop.hxx
@@ -0,0 +1,35 @@
+/* -*- 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_VCL_INC_OPENGL_BMPOP_H
+#define INCLUDED_VCL_INC_OPENGL_BMPOP_H
+
+class OpenGLSalBitmapOp
+{
+public:
+    OpenGLSalBitmapOp() {};
+    virtual ~OpenGLSalBitmapOp() {};
+
+    virtual bool Execute() = 0;
+    virtual void GetSize( Size& rSize ) const = 0;
+};
+
+#endif // INCLUDED_VCL_INC_OPENGL_BMPOP_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/salbmp.hxx b/vcl/inc/opengl/salbmp.hxx
index 74c0fda..6f7a03a 100644
--- a/vcl/inc/opengl/salbmp.hxx
+++ b/vcl/inc/opengl/salbmp.hxx
@@ -24,9 +24,13 @@
 #include <vcl/opengl/OpenGLContext.hxx>
 
 #include "vcl/salbtype.hxx"
+#include "opengl/bmpop.hxx"
+#include "opengl/texture.hxx"
 
 #include <salbmp.hxx>
 
+#include <deque>
+
 // - SalBitmap  -
 
 struct  BitmapBuffer;
@@ -35,17 +39,18 @@ class   BitmapPalette;
 class VCL_PLUGIN_PUBLIC OpenGLSalBitmap : public SalBitmap
 {
 private:
-    OpenGLContext*                  mpContext;
-    GLuint                          mnTexture;
-    bool                            mbDirtyTexture;
-    BitmapPalette                   maPalette;
-    basebmp::RawMemorySharedArray   maUserBuffer;
-    sal_uInt16                      mnBits;
-    sal_uInt16                      mnBytesPerRow;
-    int                             mnWidth;
-    int                             mnHeight;
-    int                             mnTexWidth;
-    int                             mnTexHeight;
+    OpenGLContext*                      mpContext;
+    OpenGLTextureSharedPtr              mpTexture;
+    bool                                mbDirtyTexture;
+    BitmapPalette                       maPalette;
+    basebmp::RawMemorySharedArray       maUserBuffer;
+    sal_uInt16                          mnBits;
+    sal_uInt16                          mnBytesPerRow;
+    int                                 mnWidth;
+    int                                 mnHeight;
+    int                                 mnBufWidth;
+    int                                 mnBufHeight;
+    std::deque< OpenGLSalBitmapOp* >    maPendingOps;
 
 public:
     OpenGLSalBitmap();
@@ -87,6 +92,27 @@ private:
     void            DrawTexture( GLuint nTexture, const SalTwoRect& rPosAry );
     bool            AllocateUserData();
     bool            ReadTexture();
+
+private:
+
+    GLuint          ImplGetTextureProgram();
+    GLuint          mnTexProgram;
+    GLuint          mnTexSamplerUniform;
+
+    GLuint          ImplGetConvolutionProgram();
+    GLuint          mnConvProgram;
+    GLuint          mnConvSamplerUniform;
+    GLuint          mnConvKernelUniform;
+    GLuint          mnConvKernelSizeUniform;
+    GLuint          mnConvOffsetsUniform;
+
+    bool ImplScaleFilter( GLenum nFilter );
+    void ImplCreateKernel( const double& fScale, const Kernel& rKernel, GLfloat*& pWeights, sal_uInt32& aKernelSize );
+    bool ImplScaleConvolution( const double& rScaleX, const double& rScaleY, const Kernel& aKernel );
+
+public:
+
+    bool ImplScale( const double& rScaleX, const double& rScaleY, sal_uInt32 nScaleFlag );
 };
 
 #endif // INCLUDED_VCL_INC_OPENGL_SALBMP_H
diff --git a/vcl/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx
similarity index 78%
rename from vcl/opengl/texture.hxx
rename to vcl/inc/opengl/texture.hxx
index 6eb2473..f9d3ad8 100644
--- a/vcl/opengl/texture.hxx
+++ b/vcl/inc/opengl/texture.hxx
@@ -17,8 +17,8 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#ifndef INCLUDED_VCL_OPENGL_TEXTURE_H
-#define INCLUDED_VCL_OPENGL_TEXTURE_H
+#ifndef INCLUDED_VCL_INC_OPENGL_TEXTURE_H
+#define INCLUDED_VCL_INC_OPENGL_TEXTURE_H
 
 #include <boost/shared_ptr.hpp>
 #include <GL/glew.h>
@@ -29,20 +29,26 @@ private:
     GLuint mnTexture;
     int    mnWidth;
     int    mnHeight;
+    GLenum mnFilter;
 
 public:
     OpenGLTexture();
     OpenGLTexture( int nWidth, int nHeight );
+    OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData );
+    OpenGLTexture( int nX, int nY, int nWidth, int nHeight );
     virtual ~OpenGLTexture();
 
     GLuint Id() const;
     void Bind();
     void Unbind();
     bool Draw();
+
+    GLenum GetFilter() const;
+    void SetFilter( GLenum nFilter );
 };
 
 typedef boost::shared_ptr< OpenGLTexture > OpenGLTextureSharedPtr;
 
-#endif // INCLUDED_VCL_OPENGL_TEXTURE_H
+#endif // INCLUDED_VCL_INC_OPENGL_TEXTURE_H
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/convolutionFragmentShader.glsl b/vcl/opengl/convolutionFragmentShader.glsl
new file mode 100644
index 0000000..d4f7802
--- /dev/null
+++ b/vcl/opengl/convolutionFragmentShader.glsl
@@ -0,0 +1,28 @@
+/* -*- 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/.
+ */
+
+/* TODO Use textureOffset for newest version of GLSL */
+
+uniform sampler2D sampler;
+uniform vec2 offsets[16];
+uniform float kernel[16];
+
+varying vec2 tex_coord;
+
+void main(void)
+{
+    vec4 sum = texture2D(sampler, tex_coord.st) * kernel[0];
+    for (int i = 1; i < 16; i++) {
+        sum += texture2D(sampler, tex_coord.st - offsets[i]) * kernel[i];
+        sum += texture2D(sampler, tex_coord.st + offsets[i]) * kernel[i];
+    }
+    gl_FragColor = sum;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 82b3393..f2d53f5 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -502,6 +502,7 @@ void OpenGLSalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 )
 void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeight )
 {
     maContext.makeCurrent();
+    glViewport( 0, 0, GetWidth(), GetHeight() );
 
     if( mnFillColor != SALCOLOR_NONE )
     {
@@ -676,6 +677,7 @@ void OpenGLSalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitm
 
     SAL_INFO( "vcl.opengl", "::drawBitmap" );
     maContext.makeCurrent();
+    glViewport( 0, 0, GetWidth(), GetHeight() );
     DrawTexture( nTexture, aSize, rPosAry );
 }
 
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index 14807ca..46c2b0c 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -34,20 +34,22 @@ static bool isValidBitCount( sal_uInt16 nBitCount )
 
 OpenGLSalBitmap::OpenGLSalBitmap()
 : mpContext(NULL)
-, mnTexture(0)
 , mbDirtyTexture(true)
 , mnBits(0)
 , mnBytesPerRow(0)
 , mnWidth(0)
 , mnHeight(0)
-, mnTexWidth(0)
-, mnTexHeight(0)
+, mnBufWidth(0)
+, mnBufHeight(0)
+, mnTexProgram(0)
+, mnConvProgram(0)
 {
 }
 
 OpenGLSalBitmap::~OpenGLSalBitmap()
 {
     Destroy();
+    SAL_INFO( "vcl.opengl", "~OpenGLSalBitmap" );
 }
 
 bool OpenGLSalBitmap::Create( OpenGLContext& rContext, long nX, long nY, long nWidth, long nHeight )
@@ -55,20 +57,20 @@ bool OpenGLSalBitmap::Create( OpenGLContext& rContext, long nX, long nY, long nW
     static const BitmapPalette aEmptyPalette;
 
     Destroy();
+    SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::Create from FBO" );
 
     mpContext = &rContext;
     mpContext->makeCurrent();
-    mnWidth = mnTexWidth = nWidth;
-    mnHeight = mnTexHeight = nHeight;
+    mnWidth = nWidth;
+    mnHeight = nHeight;
+    mnBufWidth = 0;
+    mnBufHeight = 0;
 
     // TODO Check the framebuffer configuration
     mnBits = 32;
     maPalette = aEmptyPalette;
 
-    glGenTextures( 1, &mnTexture );
-    glBindTexture( GL_TEXTURE_2D, mnTexture );
-    glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nX, nY, nWidth, nHeight, 0 );
-    glBindTexture( GL_TEXTURE_2D, 0 );
+    mpTexture.reset( new OpenGLTexture( nX, nY, nWidth, nHeight ) );
 
     return true;
 }
@@ -76,13 +78,14 @@ bool OpenGLSalBitmap::Create( OpenGLContext& rContext, long nX, long nY, long nW
 bool OpenGLSalBitmap::Create( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rBitmapPalette )
 {
     Destroy();
+    SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::Create with size" );
 
     if( !isValidBitCount( nBits ) )
         return false;
     maPalette = rBitmapPalette;
     mnBits = nBits;
-    mnWidth = mnTexWidth = rSize.Width();
-    mnHeight = mnTexHeight = rSize.Height();
+    mnWidth = mnBufWidth = rSize.Width();
+    mnHeight = mnBufHeight = rSize.Height();
     return false;
 }
 
@@ -100,15 +103,20 @@ bool OpenGLSalBitmap::Create( const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount
 {
     const OpenGLSalBitmap& rSourceBitmap = static_cast<const OpenGLSalBitmap&>(rSalBmp);
 
+    SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::Create from BMP " << rSourceBitmap.mnHeight );
+
     if( isValidBitCount( nNewBitCount ) )
     {
         mnBits = nNewBitCount;
-        mnTexWidth = rSourceBitmap.mnTexWidth;
-        mnTexHeight = rSourceBitmap.mnTexHeight;
+        mnBytesPerRow = rSourceBitmap.mnBytesPerRow;
         mnWidth = rSourceBitmap.mnWidth;
         mnHeight = rSourceBitmap.mnHeight;
+        mnBufWidth = rSourceBitmap.mnBufWidth;
+        mnBufHeight = rSourceBitmap.mnBufHeight;
         maPalette = rSourceBitmap.maPalette;
-        mnTexture = rSourceBitmap.mnTexture;
+        mpContext = rSourceBitmap.mpContext;
+        mpTexture = rSourceBitmap.mpTexture;
+        maUserBuffer = rSourceBitmap.maUserBuffer;
 
         // TODO Copy buffer data if the bitcount and palette are the same
         return true;
@@ -127,13 +135,13 @@ bool OpenGLSalBitmap::Draw( OpenGLContext& rContext, const SalTwoRect& rPosAry )
     if( !mpContext )
         mpContext = &rContext;
 
-    if( !mnTexture || mbDirtyTexture )
+    if( !mpTexture || mbDirtyTexture )
     {
         if( !CreateTexture() )
             return false;
     }
 
-    DrawTexture( mnTexture, rPosAry );
+    //DrawTexture( mnTexture, rPosAry );
     return true;
 }
 
@@ -141,20 +149,23 @@ GLuint OpenGLSalBitmap::GetTexture( OpenGLContext& rContext ) const
 {
     if( !mpContext )
         const_cast<OpenGLSalBitmap*>(this)->mpContext = &rContext;
-    if( !mnTexture || mbDirtyTexture )
+    if( !mpTexture || mbDirtyTexture )
         const_cast<OpenGLSalBitmap*>(this)->CreateTexture();
-    return mnTexture;
+    return mpTexture->Id();
 }
 
 void OpenGLSalBitmap::Destroy()
 {
-    DeleteTexture();
+    SAL_INFO( "vcl.opengl", "Destroy OpenGLSalBitmap" );
+    maPendingOps.clear();
+    mpTexture.reset();
     maUserBuffer.reset();
 }
 
 bool OpenGLSalBitmap::AllocateUserData()
 {
     Destroy();
+    SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::AllocateUserData" );
 
     if( mnWidth && mnHeight )
     {
@@ -295,7 +306,13 @@ ImplPixelFormat* ImplPixelFormat::GetFormat( sal_uInt16 nBits, const BitmapPalet
 
 Size OpenGLSalBitmap::GetSize() const
 {
-    return Size( mnWidth, mnHeight );
+    std::deque< OpenGLSalBitmapOp* >::const_iterator it = maPendingOps.begin();
+    Size aSize( mnWidth, mnHeight );
+
+    while( it != maPendingOps.end() )
+        (*it++)->GetSize( aSize );
+
+    return aSize;
 }
 
 GLuint OpenGLSalBitmap::CreateTexture()
@@ -334,7 +351,7 @@ GLuint OpenGLSalBitmap::CreateTexture()
         else
         {
             // convert to 32 bits RGBA using palette
-            pData = new sal_uInt8[ mnTexHeight * (mnTexWidth << 2) ];
+            pData = new sal_uInt8[ mnBufHeight * (mnBufWidth << 2) ];
             bAllocated = true;
             nFormat = GL_RGBA;
             nType = GL_UNSIGNED_BYTE;
@@ -343,12 +360,12 @@ GLuint OpenGLSalBitmap::CreateTexture()
             sal_uInt8* pSrcData = maUserBuffer.get();
             sal_uInt8* pDstData = pData;
 
-            sal_uInt32 nY = mnTexHeight;
+            sal_uInt32 nY = mnBufHeight;
             while( nY-- )
             {
                 pSrcFormat->StartLine( pSrcData );
 
-                sal_uInt32 nX = mnTexWidth;
+                sal_uInt32 nX = mnBufWidth;
                 while( nX-- )
                 {
                     const BitmapColor& c = pSrcFormat->ReadPixel();
@@ -364,59 +381,22 @@ GLuint OpenGLSalBitmap::CreateTexture()
         }
     }
 
+    SAL_INFO( "vcl.opengl", "::CreateTexture" );
     mpContext->makeCurrent();
-    if( !mnTexture )
-        glGenTextures( 1, &mnTexture );
-    glBindTexture( GL_TEXTURE_2D, mnTexture );
-    glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
-    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
-    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
-    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
-    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
-    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, mnTexWidth, mnTexHeight, 0, nFormat, nType, pData );
-    glBindTexture( GL_TEXTURE_2D, 0 );
+    mpTexture.reset( new OpenGLTexture (mnBufWidth, mnBufHeight, nFormat, nType, pData ) );
 
     if( bAllocated )
         delete pData;
 
-    mbDirtyTexture = false;
-    return mnTexture;
-}
-
-void OpenGLSalBitmap::DeleteTexture()
-{
-    if( mnTexture )
+    while( !maPendingOps.empty() )
     {
-        mpContext->makeCurrent();
-        glDeleteTextures( 1, &mnTexture );
-        mnTexture = 0;
+        OpenGLSalBitmapOp* pOp = maPendingOps.front();
+        pOp->Execute();
+        maPendingOps.pop_front();
     }
-}
 
-void OpenGLSalBitmap::DrawTexture( GLuint nTexture, const SalTwoRect& /*rPosAry*/ )
-{
-    GLushort aTexCoord[8];
-    GLushort aVertices[8];
-
-    /*if( mnTextureProgram == 0 )
-    {
-        if( !CreateTextureProgram() )
-            return;
-    }*/
-
-    //glUseProgram( mnTextureProgram );
-    //glUniform1i( mnSamplerUniform, 0 );
-    glActiveTexture( GL_TEXTURE0 );
-    glBindTexture( GL_TEXTURE_2D, nTexture );
-    glEnableVertexAttribArray( 0 );
-    glVertexAttribPointer( 0, 8, GL_UNSIGNED_SHORT, GL_FALSE, 0, aTexCoord );
-    glEnableVertexAttribArray( 1 );
-    glVertexAttribPointer( 1, 8, GL_UNSIGNED_SHORT, GL_FALSE, 0, aVertices );
-    glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
-    glDisableVertexAttribArray( 0 );
-    glDisableVertexAttribArray( 1 );
-    glBindTexture( GL_TEXTURE_2D, 0 );
-    glUseProgram( 0 );
+    mbDirtyTexture = false;
+    return mpTexture->Id();
 }
 
 bool OpenGLSalBitmap::ReadTexture()
@@ -428,17 +408,17 @@ bool OpenGLSalBitmap::ReadTexture()
     // TODO Check mnTexWidth and mnTexHeight
 
     mpContext->makeCurrent();
-    OpenGLHelper::createFramebuffer( mnTexWidth, mnTexHeight, nFramebufferId,
+    OpenGLHelper::createFramebuffer( mnWidth, mnHeight, nFramebufferId,
         nRenderbufferDepthId, nRenderbufferColorId, true );
     glBindFramebuffer( GL_FRAMEBUFFER, nFramebufferId );
 
     aPosAry.mnSrcX = aPosAry.mnDestX = 0;
     aPosAry.mnSrcY = aPosAry.mnDestY = 0;
-    aPosAry.mnSrcWidth = aPosAry.mnDestWidth = mnTexWidth;
-    aPosAry.mnSrcHeight = aPosAry.mnDestHeight = mnTexHeight;
+    aPosAry.mnSrcWidth = aPosAry.mnDestWidth = mnWidth;
+    aPosAry.mnSrcHeight = aPosAry.mnDestHeight = mnHeight;
 
-    DrawTexture( mnTexture, aPosAry );
-    glReadPixels( 0, 0, mnTexWidth, mnTexHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData );
+    //DrawTexture( mnTexture, aPosAry );
+    glReadPixels( 0, 0, mnWidth, mnHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData );
 
     glBindFramebuffer( GL_FRAMEBUFFER, 0 );
     glDeleteFramebuffers( 1, &nFramebufferId );
@@ -459,7 +439,7 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
     {
         if( !AllocateUserData() )
             return NULL;
-        if( mnTexture && !ReadTexture() )
+        if( mpTexture && !ReadTexture() )
             return NULL;
     }
 
@@ -528,12 +508,4 @@ bool OpenGLSalBitmap::GetSystemData( BitmapSystemData& /*rData*/ )
 #endif
 }
 
-bool OpenGLSalBitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 /*nScaleFlag*/ )
-{
-    SAL_INFO( "vcl.opengl", "::Scale" );
-    mnWidth *= rScaleX;
-    mnHeight *= rScaleY;
-    return true;
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/scale.cxx b/vcl/opengl/scale.cxx
new file mode 100644
index 0000000..16710b4
--- /dev/null
+++ b/vcl/opengl/scale.cxx
@@ -0,0 +1,308 @@
+/* -*- 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 .
+ */
+
+#include <sal/config.h>
+
+#include <vcl/opengl/OpenGLHelper.hxx>
+
+#include "vcl/bitmap.hxx"
+
+#include "opengl/bmpop.hxx"
+#include "opengl/salbmp.hxx"
+#include "opengl/texture.hxx"
+
+class ScaleOp : public OpenGLSalBitmapOp
+{
+private:
+    OpenGLSalBitmap*    mpBitmap;
+    double              mfScaleX;
+    double              mfScaleY;
+    sal_uInt32          mnScaleFlag;
+
+public:
+    ScaleOp( OpenGLSalBitmap* pBitmap, const double& rScaleX, const double& rScaleY, sal_uInt32 nScaleFlag );
+
+    bool Execute() SAL_OVERRIDE;
+    void GetSize( Size& rSize ) const SAL_OVERRIDE;
+};
+
+
+GLuint OpenGLSalBitmap::ImplGetTextureProgram()
+{
+    if( mnTexProgram == 0 )
+    {
+        mnTexProgram = OpenGLHelper::LoadShaders( "textureVertexShader",
+                                                  "textureFragmentShader" );
+        if( mnTexProgram == 0 )
+            return 0;
+
+        glBindAttribLocation( mnTexProgram, 0, "position" );
+        glBindAttribLocation( mnTexProgram, 1, "tex_coord_in" );
+        mnTexSamplerUniform = glGetUniformLocation( mnTexProgram, "sampler" );
+    }
+
+    return mnTexProgram;
+}
+
+GLuint OpenGLSalBitmap::ImplGetConvolutionProgram()
+{
+    if( mnConvProgram == 0 )
+    {
+        mnConvProgram = OpenGLHelper::LoadShaders( "textureVertexShader",
+                                                   "convolutionFragmentShader" );
+        if( mnConvProgram == 0 )
+            return 0;
+
+        glBindAttribLocation( mnConvProgram, 0, "position" );
+        glBindAttribLocation( mnConvProgram, 1, "tex_coord_in" );
+        mnConvSamplerUniform = glGetUniformLocation( mnConvProgram, "sampler" );
+        mnConvKernelUniform = glGetUniformLocation( mnConvProgram, "kernel" );
+        mnConvOffsetsUniform = glGetUniformLocation( mnConvProgram, "offsets" );
+    }
+
+    return mnConvProgram;
+}
+
+bool OpenGLSalBitmap::ImplScaleFilter( GLenum nFilter )
+{
+    OpenGLTexture* pNewTex;
+    GLuint nProgram;
+    GLuint nFramebufferId;
+    GLenum nOldFilter;
+
+    nProgram = ImplGetTextureProgram();
+    if( nProgram == 0 )
+        return false;
+
+    glGenFramebuffers( 1, &nFramebufferId );
+    glBindFramebuffer( GL_FRAMEBUFFER, nFramebufferId );
+    glUseProgram( nProgram );
+    glUniform1i( mnTexSamplerUniform, 0 );
+
+    pNewTex = new OpenGLTexture( mnWidth, mnHeight );
+    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pNewTex->Id(), 0 );
+
+    mpTexture->Bind();
+    nOldFilter = mpTexture->GetFilter();
+    mpTexture->SetFilter( nFilter );
+    mpTexture->Draw();
+    mpTexture->SetFilter( nOldFilter );
+    mpTexture->Unbind();
+
+    glUseProgram( 0 );
+    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+    glDeleteFramebuffers( 1, &nFramebufferId );
+
+    mpTexture.reset( pNewTex );
+    return true;
+}
+
+void OpenGLSalBitmap::ImplCreateKernel(
+    const double& fScale,
+    const Kernel& rKernel,
+    GLfloat*& pWeights,
+    sal_uInt32& aKernelSize )
+{
+    const double fSamplingRadius(rKernel.GetWidth());
+    const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius);
+    const double fFilterFactor((fScale < 1.0) ? fScale : 1.0);
+    int aNumberOfContributions;
+    double aSum( 0 );
+
+    aNumberOfContributions = (static_cast< sal_uInt32 >(fabs(ceil(fScaledRadius))) * 2) + 1 - 6;
+    aKernelSize = aNumberOfContributions / 2 + 1;
+
+    pWeights = new GLfloat[16];
+    memset( pWeights, 0, 16 * sizeof( GLfloat ) );
+
+    for( sal_uInt32 i(0); i < aKernelSize; i++ )
+    {
+        const GLfloat aWeight( rKernel.Calculate( fFilterFactor * i ) );
+        if( fabs( aWeight ) >= 0.0001 )
+        {
+            pWeights[i] = aWeight;
+            aSum += i > 0 ? aWeight * 2 : aWeight;
+        }
+    }
+
+    for( sal_uInt32 i(0); i < aKernelSize; i++ )
+    {
+        pWeights[i] /= aSum;
+    }
+}
+
+bool OpenGLSalBitmap::ImplScaleConvolution(
+    const double& rScaleX,
+    const double& rScaleY,
+    const Kernel& aKernel )
+{
+    OpenGLTexture* pScratchTex;
+    OpenGLTexture* pNewTex;
+    GLfloat* pWeights( 0 );
+    GLuint nFramebufferId;
+    GLuint nProgram;
+    sal_uInt32 nKernelSize;
+    GLfloat aOffsets[32];
+    int nNewWidth( mnWidth * rScaleX );
+    int nNewHeight( mnHeight * rScaleY );
+
+    // TODO Make sure the framebuffer is alright
+
+    nProgram = ImplGetConvolutionProgram();
+    if( nProgram == 0 )
+        return false;
+
+    glGenFramebuffers( 1, &nFramebufferId );
+    glBindFramebuffer( GL_FRAMEBUFFER, nFramebufferId );
+    glUseProgram( nProgram );
+    glUniform1i( mnConvSamplerUniform, 0 );
+    CHECK_GL_ERROR();
+
+    // horizontal scaling in scratch texture
+    pScratchTex = new OpenGLTexture( nNewWidth, mnHeight );
+    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pScratchTex->Id(), 0 );
+    CHECK_GL_ERROR();
+
+    for( sal_uInt32 i = 0; i < 16; i++ )
+    {
+        aOffsets[i * 2] = i / (double) mnWidth;
+        aOffsets[i * 2 + 1] = 0;
+    }
+    ImplCreateKernel( rScaleX, aKernel, pWeights, nKernelSize );
+    glUniform1fv( mnConvKernelUniform, 16, pWeights );
+    CHECK_GL_ERROR();
+    glUniform2fv( mnConvOffsetsUniform, 16, aOffsets );
+    CHECK_GL_ERROR();
+
+    glViewport( 0, 0, nNewWidth, mnHeight );
+    mpTexture->Bind();
+    mpTexture->Draw();
+    mpTexture->Unbind();
+
+    // vertical scaling in final texture
+    pNewTex = new OpenGLTexture( nNewWidth, nNewHeight );
+    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pNewTex->Id(), 0 );
+
+    for( sal_uInt32 i = 0; i < 16; i++ )
+    {
+        aOffsets[i * 2] = 0;
+        aOffsets[i * 2 + 1] = i / (double) mnHeight;
+    }
+    ImplCreateKernel( rScaleY, aKernel, pWeights, nKernelSize );
+    glUniform1fv( mnConvKernelUniform, 16, pWeights );
+    glUniform2fv( mnConvOffsetsUniform, 16, aOffsets );
+    CHECK_GL_ERROR();
+
+    glViewport( 0, 0, nNewWidth, nNewHeight );
+    pScratchTex->Bind();
+    pScratchTex->Draw();
+    pScratchTex->Unbind();
+
+    glUseProgram( 0 );
+    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+    glDeleteFramebuffers( 1, &nFramebufferId );
+
+    delete pScratchTex;
+    mpTexture.reset( pNewTex );
+    mnWidth = nNewWidth;
+    mnHeight = nNewHeight;
+
+    return true;
+}
+
+bool OpenGLSalBitmap::ImplScale( const double& rScaleX, const double& rScaleY, sal_uInt32 nScaleFlag )
+{
+    SAL_INFO( "vcl.opengl", "::ImplScale" );
+
+    if( nScaleFlag == BMP_SCALE_FAST )
+    {
+        return ImplScaleFilter( GL_NEAREST );
+    }
+    if( nScaleFlag == BMP_SCALE_BILINEAR )
+    {
+        return ImplScaleFilter( GL_LINEAR );
+    }
+    else if( nScaleFlag == BMP_SCALE_SUPER )
+    {
+        const Lanczos3Kernel aKernel;
+
+        return ImplScaleConvolution( rScaleX, rScaleY, aKernel );
+    }
+    else if( nScaleFlag == BMP_SCALE_LANCZOS )
+    {
+        const Lanczos3Kernel aKernel;
+
+        return ImplScaleConvolution( rScaleX, rScaleY, aKernel );
+    }
+
+    SAL_WARN( "vcl.opengl", "Invalid flag for scaling operation" );
+    return false;
+}
+
+ScaleOp::ScaleOp(
+    OpenGLSalBitmap* pBitmap,
+    const double& rScaleX,
+    const double& rScaleY,
+    sal_uInt32 nScaleFlag )
+: mpBitmap( pBitmap )
+, mfScaleX( rScaleX )
+, mfScaleY( rScaleY )
+, mnScaleFlag( nScaleFlag )
+{
+}
+
+bool ScaleOp::Execute()
+{
+    SAL_INFO( "vcl.opengl", "::Execute" );
+    return mpBitmap->ImplScale( mfScaleX, mfScaleY, mnScaleFlag );
+}
+
+void ScaleOp::GetSize( Size& rSize ) const
+{
+    SAL_INFO( "vcl.opengl", "::GetSize" );
+    rSize.setWidth( rSize.Width() * mfScaleX );
+    rSize.setHeight( rSize.Height() * mfScaleY );
+}
+
+bool OpenGLSalBitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 nScaleFlag )
+{
+    SAL_INFO( "vcl.opengl", "::Scale " << nScaleFlag );
+
+    if( nScaleFlag == BMP_SCALE_FAST ||
+        nScaleFlag == BMP_SCALE_BILINEAR ||
+        nScaleFlag == BMP_SCALE_SUPER ||
+        nScaleFlag == BMP_SCALE_LANCZOS )
+    {
+        //TODO maUserBuffer.reset();
+        if( mpContext == NULL )
+        {
+            SAL_INFO( "vcl.opengl", "Add ScaleOp to pending operations" );
+            maPendingOps.push_back( new ScaleOp( this, rScaleX, rScaleY, nScaleFlag ) );
+        }
+        else
+        {
+            ImplScale( rScaleX, rScaleY, nScaleFlag );
+        }
+        return true;
+    }
+
+    return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index 5968cf7..ad1b8c9 100644
--- a/vcl/opengl/texture.cxx
+++ b/vcl/opengl/texture.cxx
@@ -17,12 +17,16 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#include "texture.hxx"
+#include <sal/config.h>
+#include "vcl/salbtype.hxx"
+
+#include "opengl/texture.hxx"
 
 OpenGLTexture::OpenGLTexture()
 : mnTexture( 0 )
 , mnWidth( -1 )
 , mnHeight( -1 )
+, mnFilter( GL_NEAREST )
 {
 }
 
@@ -30,6 +34,7 @@ OpenGLTexture::OpenGLTexture( int nWidth, int nHeight )
 : mnTexture( 0 )
 , mnWidth( nWidth )
 , mnHeight( nHeight )
+, mnFilter( GL_NEAREST )
 {
     glGenTextures( 1, &mnTexture );
     glBindTexture( GL_TEXTURE_2D, mnTexture );
@@ -41,6 +46,40 @@ OpenGLTexture::OpenGLTexture( int nWidth, int nHeight )
     glBindTexture( GL_TEXTURE_2D, 0 );
 }
 
+OpenGLTexture::OpenGLTexture( int nX, int nY, int nWidth, int nHeight )
+: mnTexture( 0 )
+, mnWidth( nWidth )
+, mnHeight( nHeight )
+, mnFilter( GL_NEAREST )
+{
+    glGenTextures( 1, &mnTexture );
+    glBindTexture( GL_TEXTURE_2D, mnTexture );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+    glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nX, nY, nWidth, nHeight, 0 );
+    glBindTexture( GL_TEXTURE_2D, 0 );
+}
+
+OpenGLTexture::OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData )
+: mnTexture( 0 )
+, mnWidth( nWidth )
+, mnHeight( nHeight )
+, mnFilter( GL_NEAREST )
+{
+    if( !mnTexture )
+        glGenTextures( 1, &mnTexture );
+    glBindTexture( GL_TEXTURE_2D, mnTexture );
+    glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, mnWidth, mnHeight, 0, nFormat, nType, pData );
+    glBindTexture( GL_TEXTURE_2D, 0 );
+}
+
 OpenGLTexture::~OpenGLTexture()
 {
     if( mnTexture != 0 )
@@ -52,6 +91,21 @@ GLuint OpenGLTexture::Id() const
     return mnTexture;
 }
 
+GLenum OpenGLTexture::GetFilter() const
+{
+    return mnFilter;
+}
+
+void OpenGLTexture::SetFilter( GLenum nFilter )
+{
+    mnFilter = nFilter;
+    if( mnTexture )
+    {
+        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, nFilter );
+        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, nFilter );
+    }
+}
+
 void OpenGLTexture::Bind()
 {
     glBindTexture( GL_TEXTURE_2D, mnTexture );
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index 3437730..fbba6b7 100644
--- a/vcl/source/gdi/bitmap3.cxx
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -874,10 +874,23 @@ bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 nSc
         bRetval = true;
     }
 
-    if( mpImpBmp && mpImpBmp->ImplScale( rScaleX, rScaleY, nScaleFlag ) )
+    if( mpImpBmp )
     {
         // implementation specific scaling
-        return true;
+        ImpBitmap* pImpBmp = new ImpBitmap;
+
+        if( pImpBmp->ImplCreate( *mpImpBmp ) && pImpBmp->ImplScale( rScaleX, rScaleY, nScaleFlag ) )
+        {
+            ImplSetImpBitmap( pImpBmp );
+            SAL_INFO( "vcl.opengl", "Ref count: " << mpImpBmp->ImplGetRefCount() );
+            maPrefMapMode = MapMode( MAP_PIXEL );
+            maPrefSize = pImpBmp->ImplGetSize();
+            return true;
+        }
+        else
+        {
+            delete pImpBmp;
+        }
     }
 
     //fdo#33455


More information about the Libreoffice-commits mailing list