summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
Diffstat (limited to 'vcl')
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/Package_opengl.mk1
-rw-r--r--vcl/inc/opengl/bmpop.hxx35
-rw-r--r--vcl/inc/opengl/salbmp.hxx48
-rw-r--r--vcl/inc/opengl/texture.hxx (renamed from vcl/opengl/texture.hxx)12
-rw-r--r--vcl/opengl/convolutionFragmentShader.glsl28
-rw-r--r--vcl/opengl/gdiimpl.cxx2
-rw-r--r--vcl/opengl/salbmp.cxx136
-rw-r--r--vcl/opengl/scale.cxx308
-rw-r--r--vcl/opengl/texture.cxx56
-rw-r--r--vcl/source/gdi/bitmap3.cxx17
11 files changed, 545 insertions, 99 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 28e63282c164..efe0986f1746 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 9b8f745ded66..79dabb70bbb6 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 000000000000..d19410b2f253
--- /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 74c0fda4e9cb..6f7a03af09d4 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
index 6eb2473fe91f..f9d3ad864291 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 000000000000..d4f78027faa3
--- /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 82b339358d6d..f2d53f56948e 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 14807ca80cc9..46c2b0cb6d04 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 000000000000..16710b41bdd1
--- /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 5968cf7e4d11..ad1b8c9b925b 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 657c3ac2d863..335d625b29ab 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