Kaydet (Commit) 6282509c authored tarafından Louis-Francis Ratté-Boulianne's avatar Louis-Francis Ratté-Boulianne Kaydeden (comit) Markus Mohrhard

vcl: Add a way to resize an image using the GPU

Change-Id: I949e13277fa176d64d7fba9a57e3ca6f3f0dd732
üst b4daf82f
...@@ -124,6 +124,7 @@ $(eval $(call gb_Library_use_externals,vcl,\ ...@@ -124,6 +124,7 @@ $(eval $(call gb_Library_use_externals,vcl,\
$(eval $(call gb_Library_add_exception_objects,vcl,\ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/opengl/gdiimpl \ vcl/opengl/gdiimpl \
vcl/opengl/salbmp \ vcl/opengl/salbmp \
vcl/opengl/scale \
vcl/opengl/texture \ vcl/opengl/texture \
vcl/source/opengl/OpenGLContext \ vcl/source/opengl/OpenGLContext \
vcl/source/opengl/OpenGLHelper \ vcl/source/opengl/OpenGLHelper \
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
$(eval $(call gb_Package_Package,vcl_opengl_shader,$(SRCDIR)/vcl/opengl)) $(eval $(call gb_Package_Package,vcl_opengl_shader,$(SRCDIR)/vcl/opengl))
$(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\ $(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\
convolutionFragmentShader.glsl \
maskFragmentShader.glsl \ maskFragmentShader.glsl \
maskVertexShader.glsl \ maskVertexShader.glsl \
maskedTextureFragmentShader.glsl \ maskedTextureFragmentShader.glsl \
......
/* -*- 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: */
...@@ -24,9 +24,13 @@ ...@@ -24,9 +24,13 @@
#include <vcl/opengl/OpenGLContext.hxx> #include <vcl/opengl/OpenGLContext.hxx>
#include "vcl/salbtype.hxx" #include "vcl/salbtype.hxx"
#include "opengl/bmpop.hxx"
#include "opengl/texture.hxx"
#include <salbmp.hxx> #include <salbmp.hxx>
#include <deque>
// - SalBitmap - // - SalBitmap -
struct BitmapBuffer; struct BitmapBuffer;
...@@ -35,17 +39,18 @@ class BitmapPalette; ...@@ -35,17 +39,18 @@ class BitmapPalette;
class VCL_PLUGIN_PUBLIC OpenGLSalBitmap : public SalBitmap class VCL_PLUGIN_PUBLIC OpenGLSalBitmap : public SalBitmap
{ {
private: private:
OpenGLContext* mpContext; OpenGLContext* mpContext;
GLuint mnTexture; OpenGLTextureSharedPtr mpTexture;
bool mbDirtyTexture; bool mbDirtyTexture;
BitmapPalette maPalette; BitmapPalette maPalette;
basebmp::RawMemorySharedArray maUserBuffer; basebmp::RawMemorySharedArray maUserBuffer;
sal_uInt16 mnBits; sal_uInt16 mnBits;
sal_uInt16 mnBytesPerRow; sal_uInt16 mnBytesPerRow;
int mnWidth; int mnWidth;
int mnHeight; int mnHeight;
int mnTexWidth; int mnBufWidth;
int mnTexHeight; int mnBufHeight;
std::deque< OpenGLSalBitmapOp* > maPendingOps;
public: public:
OpenGLSalBitmap(); OpenGLSalBitmap();
...@@ -87,6 +92,27 @@ private: ...@@ -87,6 +92,27 @@ private:
void DrawTexture( GLuint nTexture, const SalTwoRect& rPosAry ); void DrawTexture( GLuint nTexture, const SalTwoRect& rPosAry );
bool AllocateUserData(); bool AllocateUserData();
bool ReadTexture(); 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 #endif // INCLUDED_VCL_INC_OPENGL_SALBMP_H
......
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 . * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/ */
#ifndef INCLUDED_VCL_OPENGL_TEXTURE_H #ifndef INCLUDED_VCL_INC_OPENGL_TEXTURE_H
#define INCLUDED_VCL_OPENGL_TEXTURE_H #define INCLUDED_VCL_INC_OPENGL_TEXTURE_H
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <GL/glew.h> #include <GL/glew.h>
...@@ -29,20 +29,26 @@ private: ...@@ -29,20 +29,26 @@ private:
GLuint mnTexture; GLuint mnTexture;
int mnWidth; int mnWidth;
int mnHeight; int mnHeight;
GLenum mnFilter;
public: public:
OpenGLTexture(); OpenGLTexture();
OpenGLTexture( int nWidth, int nHeight ); 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(); virtual ~OpenGLTexture();
GLuint Id() const; GLuint Id() const;
void Bind(); void Bind();
void Unbind(); void Unbind();
bool Draw(); bool Draw();
GLenum GetFilter() const;
void SetFilter( GLenum nFilter );
}; };
typedef boost::shared_ptr< OpenGLTexture > OpenGLTextureSharedPtr; 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: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- 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: */
...@@ -502,6 +502,7 @@ void OpenGLSalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 ) ...@@ -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 ) void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeight )
{ {
maContext.makeCurrent(); maContext.makeCurrent();
glViewport( 0, 0, GetWidth(), GetHeight() );
if( mnFillColor != SALCOLOR_NONE ) if( mnFillColor != SALCOLOR_NONE )
{ {
...@@ -676,6 +677,7 @@ void OpenGLSalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitm ...@@ -676,6 +677,7 @@ void OpenGLSalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitm
SAL_INFO( "vcl.opengl", "::drawBitmap" ); SAL_INFO( "vcl.opengl", "::drawBitmap" );
maContext.makeCurrent(); maContext.makeCurrent();
glViewport( 0, 0, GetWidth(), GetHeight() );
DrawTexture( nTexture, aSize, rPosAry ); DrawTexture( nTexture, aSize, rPosAry );
} }
......
...@@ -34,20 +34,22 @@ static bool isValidBitCount( sal_uInt16 nBitCount ) ...@@ -34,20 +34,22 @@ static bool isValidBitCount( sal_uInt16 nBitCount )
OpenGLSalBitmap::OpenGLSalBitmap() OpenGLSalBitmap::OpenGLSalBitmap()
: mpContext(NULL) : mpContext(NULL)
, mnTexture(0)
, mbDirtyTexture(true) , mbDirtyTexture(true)
, mnBits(0) , mnBits(0)
, mnBytesPerRow(0) , mnBytesPerRow(0)
, mnWidth(0) , mnWidth(0)
, mnHeight(0) , mnHeight(0)
, mnTexWidth(0) , mnBufWidth(0)
, mnTexHeight(0) , mnBufHeight(0)
, mnTexProgram(0)
, mnConvProgram(0)
{ {
} }
OpenGLSalBitmap::~OpenGLSalBitmap() OpenGLSalBitmap::~OpenGLSalBitmap()
{ {
Destroy(); Destroy();
SAL_INFO( "vcl.opengl", "~OpenGLSalBitmap" );
} }
bool OpenGLSalBitmap::Create( OpenGLContext& rContext, long nX, long nY, long nWidth, long nHeight ) 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 ...@@ -55,20 +57,20 @@ bool OpenGLSalBitmap::Create( OpenGLContext& rContext, long nX, long nY, long nW
static const BitmapPalette aEmptyPalette; static const BitmapPalette aEmptyPalette;
Destroy(); Destroy();
SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::Create from FBO" );
mpContext = &rContext; mpContext = &rContext;
mpContext->makeCurrent(); mpContext->makeCurrent();
mnWidth = mnTexWidth = nWidth; mnWidth = nWidth;
mnHeight = mnTexHeight = nHeight; mnHeight = nHeight;
mnBufWidth = 0;
mnBufHeight = 0;
// TODO Check the framebuffer configuration // TODO Check the framebuffer configuration
mnBits = 32; mnBits = 32;
maPalette = aEmptyPalette; maPalette = aEmptyPalette;
glGenTextures( 1, &mnTexture ); mpTexture.reset( new OpenGLTexture( nX, nY, nWidth, nHeight ) );
glBindTexture( GL_TEXTURE_2D, mnTexture );
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nX, nY, nWidth, nHeight, 0 );
glBindTexture( GL_TEXTURE_2D, 0 );
return true; return true;
} }
...@@ -76,13 +78,14 @@ bool OpenGLSalBitmap::Create( OpenGLContext& rContext, long nX, long nY, long nW ...@@ -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 ) bool OpenGLSalBitmap::Create( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rBitmapPalette )
{ {
Destroy(); Destroy();
SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::Create with size" );
if( !isValidBitCount( nBits ) ) if( !isValidBitCount( nBits ) )
return false; return false;
maPalette = rBitmapPalette; maPalette = rBitmapPalette;
mnBits = nBits; mnBits = nBits;
mnWidth = mnTexWidth = rSize.Width(); mnWidth = mnBufWidth = rSize.Width();
mnHeight = mnTexHeight = rSize.Height(); mnHeight = mnBufHeight = rSize.Height();
return false; return false;
} }
...@@ -100,15 +103,20 @@ bool OpenGLSalBitmap::Create( const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount ...@@ -100,15 +103,20 @@ bool OpenGLSalBitmap::Create( const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount
{ {
const OpenGLSalBitmap& rSourceBitmap = static_cast<const OpenGLSalBitmap&>(rSalBmp); const OpenGLSalBitmap& rSourceBitmap = static_cast<const OpenGLSalBitmap&>(rSalBmp);
SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::Create from BMP " << rSourceBitmap.mnHeight );
if( isValidBitCount( nNewBitCount ) ) if( isValidBitCount( nNewBitCount ) )
{ {
mnBits = nNewBitCount; mnBits = nNewBitCount;
mnTexWidth = rSourceBitmap.mnTexWidth; mnBytesPerRow = rSourceBitmap.mnBytesPerRow;
mnTexHeight = rSourceBitmap.mnTexHeight;
mnWidth = rSourceBitmap.mnWidth; mnWidth = rSourceBitmap.mnWidth;
mnHeight = rSourceBitmap.mnHeight; mnHeight = rSourceBitmap.mnHeight;
mnBufWidth = rSourceBitmap.mnBufWidth;
mnBufHeight = rSourceBitmap.mnBufHeight;
maPalette = rSourceBitmap.maPalette; 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 // TODO Copy buffer data if the bitcount and palette are the same
return true; return true;
...@@ -127,13 +135,13 @@ bool OpenGLSalBitmap::Draw( OpenGLContext& rContext, const SalTwoRect& rPosAry ) ...@@ -127,13 +135,13 @@ bool OpenGLSalBitmap::Draw( OpenGLContext& rContext, const SalTwoRect& rPosAry )
if( !mpContext ) if( !mpContext )
mpContext = &rContext; mpContext = &rContext;
if( !mnTexture || mbDirtyTexture ) if( !mpTexture || mbDirtyTexture )
{ {
if( !CreateTexture() ) if( !CreateTexture() )
return false; return false;
} }
DrawTexture( mnTexture, rPosAry ); //DrawTexture( mnTexture, rPosAry );
return true; return true;
} }
...@@ -141,20 +149,23 @@ GLuint OpenGLSalBitmap::GetTexture( OpenGLContext& rContext ) const ...@@ -141,20 +149,23 @@ GLuint OpenGLSalBitmap::GetTexture( OpenGLContext& rContext ) const
{ {
if( !mpContext ) if( !mpContext )
const_cast<OpenGLSalBitmap*>(this)->mpContext = &rContext; const_cast<OpenGLSalBitmap*>(this)->mpContext = &rContext;
if( !mnTexture || mbDirtyTexture ) if( !mpTexture || mbDirtyTexture )
const_cast<OpenGLSalBitmap*>(this)->CreateTexture(); const_cast<OpenGLSalBitmap*>(this)->CreateTexture();
return mnTexture; return mpTexture->Id();
} }
void OpenGLSalBitmap::Destroy() void OpenGLSalBitmap::Destroy()
{ {
DeleteTexture(); SAL_INFO( "vcl.opengl", "Destroy OpenGLSalBitmap" );
maPendingOps.clear();
mpTexture.reset();
maUserBuffer.reset(); maUserBuffer.reset();
} }
bool OpenGLSalBitmap::AllocateUserData() bool OpenGLSalBitmap::AllocateUserData()
{ {
Destroy(); Destroy();
SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::AllocateUserData" );
if( mnWidth && mnHeight ) if( mnWidth && mnHeight )
{ {
...@@ -295,7 +306,13 @@ ImplPixelFormat* ImplPixelFormat::GetFormat( sal_uInt16 nBits, const BitmapPalet ...@@ -295,7 +306,13 @@ ImplPixelFormat* ImplPixelFormat::GetFormat( sal_uInt16 nBits, const BitmapPalet
Size OpenGLSalBitmap::GetSize() const 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() GLuint OpenGLSalBitmap::CreateTexture()
...@@ -334,7 +351,7 @@ GLuint OpenGLSalBitmap::CreateTexture() ...@@ -334,7 +351,7 @@ GLuint OpenGLSalBitmap::CreateTexture()
else else
{ {
// convert to 32 bits RGBA using palette // convert to 32 bits RGBA using palette
pData = new sal_uInt8[ mnTexHeight * (mnTexWidth << 2) ]; pData = new sal_uInt8[ mnBufHeight * (mnBufWidth << 2) ];
bAllocated = true; bAllocated = true;
nFormat = GL_RGBA; nFormat = GL_RGBA;
nType = GL_UNSIGNED_BYTE; nType = GL_UNSIGNED_BYTE;
...@@ -343,12 +360,12 @@ GLuint OpenGLSalBitmap::CreateTexture() ...@@ -343,12 +360,12 @@ GLuint OpenGLSalBitmap::CreateTexture()
sal_uInt8* pSrcData = maUserBuffer.get(); sal_uInt8* pSrcData = maUserBuffer.get();
sal_uInt8* pDstData = pData; sal_uInt8* pDstData = pData;
sal_uInt32 nY = mnTexHeight; sal_uInt32 nY = mnBufHeight;
while( nY-- ) while( nY-- )
{ {
pSrcFormat->StartLine( pSrcData ); pSrcFormat->StartLine( pSrcData );
sal_uInt32 nX = mnTexWidth; sal_uInt32 nX = mnBufWidth;
while( nX-- ) while( nX-- )
{ {
const BitmapColor& c = pSrcFormat->ReadPixel(); const BitmapColor& c = pSrcFormat->ReadPixel();
...@@ -364,59 +381,22 @@ GLuint OpenGLSalBitmap::CreateTexture() ...@@ -364,59 +381,22 @@ GLuint OpenGLSalBitmap::CreateTexture()
} }
} }
SAL_INFO( "vcl.opengl", "::CreateTexture" );
mpContext->makeCurrent(); mpContext->makeCurrent();
if( !mnTexture ) mpTexture.reset( new OpenGLTexture (mnBufWidth, mnBufHeight, nFormat, nType, pData ) );
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 );
if( bAllocated ) if( bAllocated )
delete pData; delete pData;
mbDirtyTexture = false; while( !maPendingOps.empty() )
return mnTexture;
}
void OpenGLSalBitmap::DeleteTexture()
{
if( mnTexture )
{ {
mpContext->makeCurrent(); OpenGLSalBitmapOp* pOp = maPendingOps.front();
glDeleteTextures( 1, &mnTexture ); pOp->Execute();
mnTexture = 0; maPendingOps.pop_front();
} }
}
void OpenGLSalBitmap::DrawTexture( GLuint nTexture, const SalTwoRect& /*rPosAry*/ ) mbDirtyTexture = false;
{ return mpTexture->Id();
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 );
} }
bool OpenGLSalBitmap::ReadTexture() bool OpenGLSalBitmap::ReadTexture()
...@@ -428,17 +408,17 @@ bool OpenGLSalBitmap::ReadTexture() ...@@ -428,17 +408,17 @@ bool OpenGLSalBitmap::ReadTexture()
// TODO Check mnTexWidth and mnTexHeight // TODO Check mnTexWidth and mnTexHeight
mpContext->makeCurrent(); mpContext->makeCurrent();
OpenGLHelper::createFramebuffer( mnTexWidth, mnTexHeight, nFramebufferId, OpenGLHelper::createFramebuffer( mnWidth, mnHeight, nFramebufferId,
nRenderbufferDepthId, nRenderbufferColorId, true ); nRenderbufferDepthId, nRenderbufferColorId, true );
glBindFramebuffer( GL_FRAMEBUFFER, nFramebufferId ); glBindFramebuffer( GL_FRAMEBUFFER, nFramebufferId );
aPosAry.mnSrcX = aPosAry.mnDestX = 0; aPosAry.mnSrcX = aPosAry.mnDestX = 0;
aPosAry.mnSrcY = aPosAry.mnDestY = 0; aPosAry.mnSrcY = aPosAry.mnDestY = 0;
aPosAry.mnSrcWidth = aPosAry.mnDestWidth = mnTexWidth; aPosAry.mnSrcWidth = aPosAry.mnDestWidth = mnWidth;
aPosAry.mnSrcHeight = aPosAry.mnDestHeight = mnTexHeight; aPosAry.mnSrcHeight = aPosAry.mnDestHeight = mnHeight;
DrawTexture( mnTexture, aPosAry ); //DrawTexture( mnTexture, aPosAry );
glReadPixels( 0, 0, mnTexWidth, mnTexHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData ); glReadPixels( 0, 0, mnWidth, mnHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData );
glBindFramebuffer( GL_FRAMEBUFFER, 0 ); glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glDeleteFramebuffers( 1, &nFramebufferId ); glDeleteFramebuffers( 1, &nFramebufferId );
...@@ -459,7 +439,7 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( bool /*bReadOnly*/ ) ...@@ -459,7 +439,7 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
{ {
if( !AllocateUserData() ) if( !AllocateUserData() )
return NULL; return NULL;
if( mnTexture && !ReadTexture() ) if( mpTexture && !ReadTexture() )
return NULL; return NULL;
} }
...@@ -528,12 +508,4 @@ bool OpenGLSalBitmap::GetSystemData( BitmapSystemData& /*rData*/ ) ...@@ -528,12 +508,4 @@ bool OpenGLSalBitmap::GetSystemData( BitmapSystemData& /*rData*/ )
#endif #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: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- 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: */
...@@ -17,12 +17,16 @@ ...@@ -17,12 +17,16 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 . * 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() OpenGLTexture::OpenGLTexture()
: mnTexture( 0 ) : mnTexture( 0 )
, mnWidth( -1 ) , mnWidth( -1 )
, mnHeight( -1 ) , mnHeight( -1 )
, mnFilter( GL_NEAREST )
{ {
} }
...@@ -30,6 +34,7 @@ OpenGLTexture::OpenGLTexture( int nWidth, int nHeight ) ...@@ -30,6 +34,7 @@ OpenGLTexture::OpenGLTexture( int nWidth, int nHeight )
: mnTexture( 0 ) : mnTexture( 0 )
, mnWidth( nWidth ) , mnWidth( nWidth )
, mnHeight( nHeight ) , mnHeight( nHeight )
, mnFilter( GL_NEAREST )
{ {
glGenTextures( 1, &mnTexture ); glGenTextures( 1, &mnTexture );
glBindTexture( GL_TEXTURE_2D, mnTexture ); glBindTexture( GL_TEXTURE_2D, mnTexture );
...@@ -41,6 +46,40 @@ OpenGLTexture::OpenGLTexture( int nWidth, int nHeight ) ...@@ -41,6 +46,40 @@ OpenGLTexture::OpenGLTexture( int nWidth, int nHeight )
glBindTexture( GL_TEXTURE_2D, 0 ); 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() OpenGLTexture::~OpenGLTexture()
{ {
if( mnTexture != 0 ) if( mnTexture != 0 )
...@@ -52,6 +91,21 @@ GLuint OpenGLTexture::Id() const ...@@ -52,6 +91,21 @@ GLuint OpenGLTexture::Id() const
return mnTexture; 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() void OpenGLTexture::Bind()
{ {
glBindTexture( GL_TEXTURE_2D, mnTexture ); glBindTexture( GL_TEXTURE_2D, mnTexture );
......
...@@ -874,10 +874,23 @@ bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 nSc ...@@ -874,10 +874,23 @@ bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 nSc
bRetval = true; bRetval = true;
} }
if( mpImpBmp && mpImpBmp->ImplScale( rScaleX, rScaleY, nScaleFlag ) ) if( mpImpBmp )
{ {
// implementation specific scaling // 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 //fdo#33455
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment