diff options
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/Package_opengl.mk | 1 | ||||
-rw-r--r-- | vcl/inc/opengl/bmpop.hxx | 35 | ||||
-rw-r--r-- | vcl/inc/opengl/salbmp.hxx | 48 | ||||
-rw-r--r-- | vcl/inc/opengl/texture.hxx (renamed from vcl/opengl/texture.hxx) | 12 | ||||
-rw-r--r-- | vcl/opengl/convolutionFragmentShader.glsl | 28 | ||||
-rw-r--r-- | vcl/opengl/gdiimpl.cxx | 2 | ||||
-rw-r--r-- | vcl/opengl/salbmp.cxx | 136 | ||||
-rw-r--r-- | vcl/opengl/scale.cxx | 308 | ||||
-rw-r--r-- | vcl/opengl/texture.cxx | 56 | ||||
-rw-r--r-- | vcl/source/gdi/bitmap3.cxx | 17 |
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 |