Lanczos filter available in GLES.

It uses a default vertex shader, so the existing shader can be dropped.
This commit is contained in:
Martin Gräßlin 2011-01-02 21:28:07 +01:00
parent c6dd3690f5
commit 78c4c7a86e
5 changed files with 81 additions and 50 deletions

View file

@ -2,12 +2,14 @@ uniform sampler2D texUnit;
uniform vec2 offsets[25];
uniform vec4 kernel[25];
varying vec2 varyingTexCoords;
void main(void)
{
vec4 sum = texture2D(texUnit, gl_TexCoord[0].st) * kernel[0];
vec4 sum = texture2D(texUnit, varyingTexCoords.st) * kernel[0];
for (int i = 1; i < 25; i++) {
sum += texture2D(texUnit, gl_TexCoord[0].st - offsets[i]) * kernel[i];
sum += texture2D(texUnit, gl_TexCoord[0].st + offsets[i]) * kernel[i];
sum += texture2D(texUnit, varyingTexCoords.st - offsets[i]) * kernel[i];
sum += texture2D(texUnit, varyingTexCoords.st + offsets[i]) * kernel[i];
}
gl_FragColor = sum;
}

View file

@ -1,6 +0,0 @@
void main(void)
{
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

View file

@ -38,11 +38,9 @@ namespace KWin
LanczosFilter::LanczosFilter( QObject* parent )
: QObject( parent )
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#ifndef KWIN_HAVE_OPENGLES
, m_offscreenTex( 0 )
, m_offscreenTarget( 0 )
, m_shader( 0 )
#endif
#endif
, m_inited( false)
{
@ -51,10 +49,8 @@ LanczosFilter::LanczosFilter( QObject* parent )
LanczosFilter::~LanczosFilter()
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#ifndef KWIN_HAVE_OPENGLES
delete m_offscreenTarget;
delete m_offscreenTex;
#endif
#endif
}
@ -64,7 +60,6 @@ void LanczosFilter::init()
return;
m_inited = true;
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#ifndef KWIN_HAVE_OPENGLES
KSharedConfigPtr config = KSharedConfig::openConfig( "kwinrc" );
@ -85,7 +80,6 @@ void LanczosFilter::init()
delete m_shader;
m_shader = 0;
}
#endif
#endif
}
@ -132,7 +126,6 @@ static float lanczos( float x, float a )
}
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#ifndef KWIN_HAVE_OPENGLES
void LanczosShader::createKernel( float delta, int *size )
{
const float a = 2.0;
@ -173,13 +166,11 @@ void LanczosShader::createOffsets( int count, float width, Qt::Orientation direc
}
}
#endif
#endif
void LanczosFilter::performPaint( EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data )
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#ifndef KWIN_HAVE_OPENGLES
if( effects->compositingType() == KWin::OpenGLCompositing && data.opacity == 1.0 &&
if( effects->compositingType() == KWin::OpenGLCompositing &&
KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects )
{
if (!m_inited)
@ -225,9 +216,23 @@ void LanczosFilter::performPaint( EffectWindowImpl* w, int mask, QRegion region,
if( cachedTexture->width() == tw && cachedTexture->height() == th )
{
cachedTexture->bind();
prepareRenderStates( cachedTexture, data.opacity, data.brightness, data.saturation );
cachedTexture->render( textureRect, textureRect );
restoreRenderStates( cachedTexture, data.opacity, data.brightness, data.saturation );
if (ShaderManager::instance()->isValid()) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader);
shader->setUniform("offset", QVector2D(0, 0));
shader->setUniform("opacity", (float)data.opacity);
shader->setUniform("brightness", (float)data.brightness);
shader->setUniform("saturation", (float)data.saturation);
shader->setUniform("u_forceAlpha", 0);
cachedTexture->render(textureRect, textureRect);
ShaderManager::instance()->popShader();
glDisable(GL_BLEND);
} else {
prepareRenderStates( cachedTexture, data.opacity, data.brightness, data.saturation );
cachedTexture->render( textureRect, textureRect );
restoreRenderStates( cachedTexture, data.opacity, data.brightness, data.saturation );
}
cachedTexture->unbind();
m_timer.start( 5000, this );
return;
@ -254,6 +259,7 @@ void LanczosFilter::performPaint( EffectWindowImpl* w, int mask, QRegion region,
updateOffscreenSurfaces();
effects->pushRenderTarget( m_offscreenTarget );
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear( GL_COLOR_BUFFER_BIT );
w->sceneWindow()->performPaint( mask, infiniteRegion(), thumbData );
@ -276,13 +282,21 @@ void LanczosFilter::performPaint( EffectWindowImpl* w, int mask, QRegion region,
// Draw the window back into the FBO, this time scaled horizontally
glClear( GL_COLOR_BUFFER_BIT );
QVector<float> verts;
QVector<float> texCoords;
verts.reserve(12);
texCoords.reserve(12);
glBegin( GL_QUADS );
glTexCoord2f( 0, 0 ); glVertex2i( 0, 0 ); // Top left
glTexCoord2f( 1, 0 ); glVertex2i( tw, 0 ); // Top right
glTexCoord2f( 1, 1 ); glVertex2i( tw, sh ); // Bottom right
glTexCoord2f( 0, 1 ); glVertex2i( 0, sh ); // Bottom left
glEnd();
texCoords << 1.0 << 0.0; verts << tw << 0.0; // Top right
texCoords << 0.0 << 0.0; verts << 0.0 << 0.0; // Top left
texCoords << 0.0 << 1.0; verts << 0.0 << sh; // Bottom left
texCoords << 0.0 << 1.0; verts << 0.0 << sh; // Bottom left
texCoords << 1.0 << 1.0; verts << tw << sh; // Bottom right
texCoords << 1.0 << 0.0; verts << tw << 0.0; // Top right
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
vbo->reset();
vbo->setData(6, 2, verts.constData(), texCoords.constData());
vbo->render(GL_TRIANGLES);
// At this point we don't need the scratch texture anymore
tex.unbind();
@ -306,12 +320,16 @@ void LanczosFilter::performPaint( EffectWindowImpl* w, int mask, QRegion region,
// coordinates on the screen, while scaling it vertically and blending it.
glClear( GL_COLOR_BUFFER_BIT );
glBegin( GL_QUADS );
glTexCoord2f( 0, 0 ); glVertex2i( 0, 0 ); // Top left
glTexCoord2f( 1, 0 ); glVertex2i( tw, 0 ); // Top right
glTexCoord2f( 1, 1 ); glVertex2i( tw, th ); // Bottom right
glTexCoord2f( 0, 1 ); glVertex2i( 0, th ); // Bottom left
glEnd();
verts.clear();
verts << tw << 0.0; // Top right
verts << 0.0 << 0.0; // Top left
verts << 0.0 << th; // Bottom left
verts << 0.0 << th; // Bottom left
verts << tw << th; // Bottom right
verts << tw << 0.0; // Top right
vbo->setData(6, 2, verts.constData(), texCoords.constData());
vbo->render(GL_TRIANGLES);
tex2.unbind();
tex2.discard();
@ -325,9 +343,23 @@ void LanczosFilter::performPaint( EffectWindowImpl* w, int mask, QRegion region,
cache->bind();
glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, m_offscreenTex->height() - th, tw, th );
effects->popRenderTarget();
prepareRenderStates( cache, data.opacity, data.brightness, data.saturation );
cache->render( textureRect, textureRect );
restoreRenderStates( cache, data.opacity, data.brightness, data.saturation );
if (ShaderManager::instance()->isValid()) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader);
shader->setUniform("offset", QVector2D(0, 0));
shader->setUniform("opacity", (float)data.opacity);
shader->setUniform("brightness", (float)data.brightness);
shader->setUniform("saturation", (float)data.saturation);
shader->setUniform("u_forceAlpha", 0);
cache->render(textureRect, textureRect);
ShaderManager::instance()->popShader();
glDisable(GL_BLEND);
} else {
prepareRenderStates( cache, data.opacity, data.brightness, data.saturation );
cache->render( textureRect, textureRect );
restoreRenderStates( cache, data.opacity, data.brightness, data.saturation );
}
cache->unbind();
w->setData( LanczosCacheRole, QVariant::fromValue( static_cast<void*>( cache )));
@ -336,7 +368,6 @@ void LanczosFilter::performPaint( EffectWindowImpl* w, int mask, QRegion region,
return;
}
} // if ( effects->compositingType() == KWin::OpenGLCompositing )
#endif
#endif
w->sceneWindow()->performPaint( mask, region, data );
} // End of function
@ -520,7 +551,6 @@ void LanczosFilter::restoreRenderStates( GLTexture* tex, double opacity, double
* LanczosShader
************************************************/
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#ifndef KWIN_HAVE_OPENGLES
LanczosShader::LanczosShader( QObject* parent )
: QObject( parent )
, m_shader( 0 )
@ -531,28 +561,33 @@ LanczosShader::LanczosShader( QObject* parent )
LanczosShader::~LanczosShader()
{
delete m_shader;
#ifndef KWIN_HAVE_OPENGLES
if( m_arbProgram )
{
glDeleteProgramsARB(1, &m_arbProgram);
m_arbProgram = 0;
}
#endif
}
void LanczosShader::bind()
{
if( m_shader )
m_shader->bind();
ShaderManager::instance()->pushShader(m_shader);
#ifndef KWIN_HAVE_OPENGLES
else
{
glEnable(GL_FRAGMENT_PROGRAM_ARB);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_arbProgram);
}
#endif
}
void LanczosShader::unbind()
{
if( m_shader )
m_shader->unbind();
ShaderManager::instance()->popShader();
#ifndef KWIN_HAVE_OPENGLES
else
{
int boundObject;
@ -563,6 +598,7 @@ void LanczosShader::unbind()
glDisable(GL_FRAGMENT_PROGRAM_ARB);
}
}
#endif
}
void LanczosShader::setUniforms()
@ -573,6 +609,7 @@ void LanczosShader::setUniforms()
glUniform2fv( m_uOffsets, 25, (const GLfloat*)m_offsets );
glUniform4fv( m_uKernel, 25, (const GLfloat*)m_kernel );
}
#ifndef KWIN_HAVE_OPENGLES
else
{
for( int i=0; i<25; ++i )
@ -584,6 +621,7 @@ void LanczosShader::setUniforms()
glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, i+25, m_kernel[i].x(), m_kernel[i].y(), m_kernel[i].z(), m_kernel[i].w() );
}
}
#endif
}
bool LanczosShader::init()
@ -592,7 +630,7 @@ bool LanczosShader::init()
GLShader::vertexShaderSupported() &&
GLRenderTarget::supported() )
{
m_shader = new GLShader(":/resources/lanczos-vertex.glsl", ":/resources/lanczos-fragment.glsl");
m_shader = ShaderManager::instance()->loadFragmentShader(ShaderManager::SimpleShader, ":/resources/lanczos-fragment.glsl");
if (m_shader->isValid())
{
m_shader->bind();
@ -610,6 +648,10 @@ bool LanczosShader::init()
}
}
#ifdef KWIN_HAVE_OPENGLES
// no ARB shader in GLES
return false;
#else
// try to create an ARB Shader
if( !hasGLExtension("GL_ARB_fragment_program") )
return false;
@ -652,8 +694,8 @@ bool LanczosShader::init()
glDisable(GL_FRAGMENT_PROGRAM_ARB);
kDebug( 1212 ) << "ARB Shader compiled, id: " << m_arbProgram;
return true;
}
#endif
}
#endif
} // namespace

View file

@ -39,10 +39,8 @@ class GLTexture;
class GLRenderTarget;
class GLShader;
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#ifndef KWIN_HAVE_OPENGLES
class LanczosShader;
#endif
#endif
class LanczosFilter
: public QObject
@ -64,16 +62,13 @@ class LanczosFilter
GLTexture *m_offscreenTex;
GLRenderTarget *m_offscreenTarget;
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#ifndef KWIN_HAVE_OPENGLES
LanczosShader *m_shader;
#endif
#endif
QBasicTimer m_timer;
bool m_inited;
};
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#ifndef KWIN_HAVE_OPENGLES
class LanczosShader
: public QObject
{
@ -100,7 +95,6 @@ class LanczosShader
uint m_arbProgram; // TODO: GLuint
};
#endif
#endif
} // namespace

View file

@ -1,6 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/resources">
<file>lanczos-vertex.glsl</file>
<file>lanczos-fragment.glsl</file>
<file>scene-vertex.glsl</file>
<file>scene-fragment.glsl</file>