diff --git a/effects/coverswitch/CMakeLists.txt b/effects/coverswitch/CMakeLists.txt index cc08dcbe12..9a264915f6 100644 --- a/effects/coverswitch/CMakeLists.txt +++ b/effects/coverswitch/CMakeLists.txt @@ -11,6 +11,11 @@ install( FILES coverswitch/coverswitch.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kwin ) +install( FILES + coverswitch/coverswitch-reflection.glsl + DESTINATION ${DATA_INSTALL_DIR}/kwin ) + + ####################################### # Config diff --git a/effects/coverswitch/coverswitch-reflection.glsl b/effects/coverswitch/coverswitch-reflection.glsl new file mode 100644 index 0000000000..bce5b7557d --- /dev/null +++ b/effects/coverswitch/coverswitch-reflection.glsl @@ -0,0 +1,9 @@ +uniform vec4 u_frontColor; +uniform vec4 u_backColor; + +varying vec2 varyingTexCoords; + +void main() +{ + gl_FragColor = u_frontColor*(1.0-varyingTexCoords.s) + u_backColor*varyingTexCoords.s; +} diff --git a/effects/coverswitch/coverswitch.cpp b/effects/coverswitch/coverswitch.cpp index 23fd297c7e..6784cd192b 100644 --- a/effects/coverswitch/coverswitch.cpp +++ b/effects/coverswitch/coverswitch.cpp @@ -26,6 +26,8 @@ along with this program. If not, see . #include #include #include +#include +#include #include @@ -65,11 +67,15 @@ CoverSwitchEffect::CoverSwitchEffect() captionFont.setPointSize( captionFont.pointSize() * 2 ); captionFrame->setFont( captionFont ); captionFrame->enableCrossFade( true ); + + const QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/coverswitch-reflection.glsl"); + m_reflectionShader = ShaderManager::instance()->loadFragmentShader(ShaderManager::GenericShader, fragmentshader); } CoverSwitchEffect::~CoverSwitchEffect() { delete captionFrame; + delete m_reflectionShader; } bool CoverSwitchEffect::supported() @@ -257,33 +263,28 @@ void CoverSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& if( (!start && !stop) || ShaderManager::instance()->isValid() ) paintScene( frontWindow, leftWindows, rightWindows, true ); PaintClipper::pop( clip ); -#ifndef KWIN_HAVE_OPENGLES glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA ); +#ifndef KWIN_HAVE_OPENGLES glPolygonMode( GL_FRONT, GL_FILL ); - glPushMatrix(); +#endif QRect fullRect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() ); // we can use a huge scale factor (needed to calculate the rearground vertices) // as we restrict with a PaintClipper painting on the current screen float reflectionScaleFactor = 100000 * tan( 60.0 * M_PI / 360.0f )/area.width(); - if( effects->numScreens() > 1 && area.x() != fullRect.x() ) - { - // have to change the reflection area in horizontal layout and right screen - glTranslatef( -area.x(), 0.0, 0.0 ); - } - glTranslatef( area.x() + area.width()*0.5f, 0.0, 0.0 ); float vertices[] = { -area.width()*0.5f, area.height(), 0.0, area.width()*0.5f, area.height(), 0.0, (float)area.width()*reflectionScaleFactor, area.height(), -5000, -(float)area.width()*reflectionScaleFactor, area.height(), -5000 }; // foreground - if( start ) + if (start) { mirrorColor[0][3] = timeLine.value(); - else if( stop ) + } else if (stop) { mirrorColor[0][3] = 1.0 - timeLine.value(); - glColor4fv( mirrorColor[0] ); - mirrorColor[0][3] = 1.0; + } else { + mirrorColor[0][3] = 1.0; + } int y = 0; // have to adjust the y values to fit OpenGL @@ -302,20 +303,68 @@ void CoverSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& // use scissor to restrict painting of the reflection plane to current screen glScissor( area.x(), y, area.width(), area.height() ); glEnable( GL_SCISSOR_TEST ); - glBegin( GL_POLYGON ); - glVertex3f( vertices[0], vertices[1], vertices[2] ); - glVertex3f( vertices[3], vertices[4], vertices[5] ); - // rearground - glColor4fv( mirrorColor[1] ); - glVertex3f( vertices[6], vertices[7], vertices[8] ); - glVertex3f( vertices[9], vertices[10], vertices[11] ); - glEnd(); - glDisable( GL_SCISSOR_TEST ); - glPopMatrix(); - glDisable( GL_BLEND ); + ShaderManager *shaderManager = ShaderManager::instance(); + if (shaderManager->isValid() && m_reflectionShader->isValid()) { + shaderManager->pushShader(m_reflectionShader); + QMatrix4x4 windowTransformation; + if (effects->numScreens() > 1 && area.x() != fullRect.x()) { + // have to change the reflection area in horizontal layout and right screen + windowTransformation.translate(-area.x(), 0.0, 0.0); + } + windowTransformation.translate(area.x() + area.width()*0.5f, 0.0, 0.0); + m_reflectionShader->setUniform("windowTransformation", windowTransformation); + m_reflectionShader->setUniform("u_frontColor", QVector4D(mirrorColor[0][0], mirrorColor[0][1], mirrorColor[0][2], mirrorColor[0][3])); + m_reflectionShader->setUniform("u_backColor", QVector4D(mirrorColor[1][0], mirrorColor[1][1], mirrorColor[1][2], mirrorColor[1][3])); + // TODO: make this one properly + QVector verts; + QVector texcoords; + verts.reserve(18); + texcoords.reserve(12); + texcoords << 1.0 << 0.0; + verts << vertices[6] << vertices[7] << vertices[8]; + texcoords << 1.0 << 0.0; + verts << vertices[9] << vertices[10] << vertices[11]; + texcoords << 0.0 << 0.0; + verts << vertices[0] << vertices[1] << vertices[2]; + texcoords << 0.0 << 0.0; + verts << vertices[0] << vertices[1] << vertices[2]; + texcoords << 0.0 << 0.0; + verts << vertices[3] << vertices[4] << vertices[5]; + texcoords << 1.0 << 0.0; + verts << vertices[6] << vertices[7] << vertices[8]; + GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); + vbo->reset(); + vbo->setUseShader(true); + vbo->setData(6, 3, verts.data(), texcoords.data()); + vbo->render(GL_TRIANGLES); + + shaderManager->popShader(); + } else { +#ifndef KWIN_HAVE_OPENGLES + glPushMatrix(); + if( effects->numScreens() > 1 && area.x() != fullRect.x() ) + { + // have to change the reflection area in horizontal layout and right screen + glTranslatef( -area.x(), 0.0, 0.0 ); + } + glTranslatef( area.x() + area.width()*0.5f, 0.0, 0.0 ); + glColor4fv( mirrorColor[0] ); + glBegin( GL_POLYGON ); + glVertex3f( vertices[0], vertices[1], vertices[2] ); + glVertex3f( vertices[3], vertices[4], vertices[5] ); + // rearground + glColor4fv( mirrorColor[1] ); + glVertex3f( vertices[6], vertices[7], vertices[8] ); + glVertex3f( vertices[9], vertices[10], vertices[11] ); + glEnd(); + + glPopMatrix(); #endif } + glDisable( GL_SCISSOR_TEST ); + glDisable( GL_BLEND ); + } paintScene( frontWindow, leftWindows, rightWindows ); if( effects->numScreens() > 1 ) diff --git a/effects/coverswitch/coverswitch.h b/effects/coverswitch/coverswitch.h index a4a8d33cb7..e6311af07c 100644 --- a/effects/coverswitch/coverswitch.h +++ b/effects/coverswitch/coverswitch.h @@ -102,6 +102,8 @@ class CoverSwitchEffect bool primaryTabBox; bool secondaryTabBox; + + GLShader *m_reflectionShader; }; } // namespace