diff --git a/resources.qrc b/resources.qrc index 2c73d4d9d0..4ddc63a92d 100644 --- a/resources.qrc +++ b/resources.qrc @@ -4,5 +4,6 @@ lanczos-fragment.glsl scene-vertex.glsl scene-fragment.glsl + scene-generic-vertex.glsl diff --git a/scene-generic-vertex.glsl b/scene-generic-vertex.glsl new file mode 100644 index 0000000000..d05062cb70 --- /dev/null +++ b/scene-generic-vertex.glsl @@ -0,0 +1,19 @@ +#ifdef GL_ES +precision highp float; +#endif +uniform mat4 projection; +uniform mat4 modelview; +uniform mat4 windowTransformation; + +// passed in vertex - only x and y are used +attribute vec4 vertex; +// passed in texCoords - to be forwarded +attribute vec2 texCoord; + +// texCoords passed to fragment shader +varying vec2 varyingTexCoords; + +void main() { + varyingTexCoords = texCoord; + gl_Position = vertex*(windowTransformation*modelview)*projection; +} diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 7fb95aa2fa..c957fc8c57 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -92,6 +92,7 @@ Sources and other compositing managers: #include #include #include +#include namespace KWin { @@ -115,6 +116,59 @@ XShmSegmentInfo SceneOpenGL::shm; #include "scene_opengl_glx.cpp" #endif + +bool SceneOpenGL::setupSceneShaders() +{ + m_sceneShader = new GLShader(":/resources/scene-vertex.glsl", ":/resources/scene-fragment.glsl"); + if (m_sceneShader->isValid()) { + m_sceneShader->bind(); + m_sceneShader->setUniform("sample", 0); + m_sceneShader->setUniform("displaySize", QVector2D(displayWidth(), displayHeight())); + m_sceneShader->setUniform("debug", debug ? 1 : 0); + m_sceneShader->unbind(); + kDebug(1212) << "Scene Shader is valid"; + } + else { + delete m_sceneShader; + m_sceneShader = NULL; + kDebug(1212) << "Scene Shader is not valid"; + return false; + } + m_genericSceneShader = new GLShader( ":/resources/scene-generic-vertex.glsl", ":/resources/scene-fragment.glsl" ); + if (m_genericSceneShader->isValid()) { + m_genericSceneShader->bind(); + m_genericSceneShader->setUniform("sample", 0); + m_genericSceneShader->setUniform("debug", debug ? 1 : 0); + QMatrix4x4 projection; + float fovy = 60.0f; + float aspect = 1.0f; + float zNear = 0.1f; + float zFar = 100.0f; + float ymax = zNear * tan(fovy * M_PI / 360.0f); + float ymin = -ymax; + float xmin = ymin * aspect; + float xmax = ymax * aspect; + projection.frustum(xmin, xmax, ymin, ymax, zNear, zFar); + m_genericSceneShader->setUniform("projection", projection); + QMatrix4x4 modelview; + float scaleFactor = 1.1 * tan( fovy * M_PI / 360.0f )/ymax; + modelview.translate(xmin*scaleFactor, ymax*scaleFactor, -1.1); + modelview.scale((xmax-xmin)*scaleFactor/displayWidth(), -(ymax-ymin)*scaleFactor/displayHeight(), 0.001); + m_genericSceneShader->setUniform("modelview", modelview); + m_genericSceneShader->unbind(); + kDebug(1212) << "Generic Scene Shader is valid"; + } + else { + delete m_genericSceneShader; + m_genericSceneShader = NULL; + delete m_sceneShader; + m_sceneShader = NULL; + kDebug(1212) << "Generic Scene Shader is not valid"; + return false; + } + return true; +} + bool SceneOpenGL::initFailed() const { return !init_ok; @@ -458,20 +512,51 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat int y = toplevel->y(); double z = 0.0; bool sceneShader = false; - if( !data.shader && !( mask & PAINT_WINDOW_TRANSFORMED ) && !( mask & PAINT_SCREEN_TRANSFORMED ) ) - { + if (!data.shader) { // set the shader for uniform initialising in paint decoration - data.shader = static_cast(scene)->m_sceneShader; - sceneShader = true; - data.shader->bind(); - data.shader->setUniform("geometry", QVector4D(x, y, toplevel->width(), toplevel->height())); + if ((mask & PAINT_WINDOW_TRANSFORMED) || (mask & PAINT_SCREEN_TRANSFORMED)) { + data.shader = static_cast(scene)->m_genericSceneShader; + data.shader->bind(); + } else { + data.shader = static_cast(scene)->m_sceneShader; + data.shader->bind(); + data.shader->setUniform("geometry", QVector4D(x, y, toplevel->width(), toplevel->height())); } - if( mask & PAINT_WINDOW_TRANSFORMED ) - { + sceneShader = true; + } + if (mask & PAINT_WINDOW_TRANSFORMED) { x += data.xTranslate; y += data.yTranslate; z += data.zTranslate; + QMatrix4x4 windowTransformation; + windowTransformation.translate(x, y, z); + if ((mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 || data.zScale != 1)) { + windowTransformation.scale(data.xScale, data.yScale, data.zScale); } + if ((mask & PAINT_WINDOW_TRANSFORMED) && data.rotation) { + windowTransformation.translate(data.rotation->xRotationPoint, data.rotation->yRotationPoint, data.rotation->zRotationPoint); + qreal xAxis = 0.0; + qreal yAxis = 0.0; + qreal zAxis = 0.0; + switch( data.rotation->axis ) + { + case RotationData::XAxis: + xAxis = 1.0; + break; + case RotationData::YAxis: + yAxis = 1.0; + break; + case RotationData::ZAxis: + zAxis = 1.0; + break; + } + windowTransformation.rotate(data.rotation->angle, xAxis, yAxis, zAxis); + windowTransformation.translate(-data.rotation->xRotationPoint, -data.rotation->yRotationPoint, -data.rotation->zRotationPoint); + } + if (sceneShader) { + data.shader->setUniform("windowTransformation", windowTransformation); + } + } if( !sceneShader ) { #ifndef KWIN_HAVE_OPENGLES diff --git a/scene_opengl.h b/scene_opengl.h index b47b745fd7..690db41f71 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -69,6 +69,7 @@ class SceneOpenGL bool selfCheck(); void selfCheckSetup(); bool selfCheckFinish(); + bool setupSceneShaders(); GC gcroot; class FBConfigInfo { @@ -104,6 +105,7 @@ class SceneOpenGL bool init_ok; bool selfCheckDone; GLShader* m_sceneShader; + GLShader* m_genericSceneShader; bool debug; }; diff --git a/scene_opengl_egl.cpp b/scene_opengl_egl.cpp index febc7a28c6..c76fd1a0be 100644 --- a/scene_opengl_egl.cpp +++ b/scene_opengl_egl.cpp @@ -32,30 +32,18 @@ SceneOpenGL::SceneOpenGL( Workspace* ws ) , init_ok( false ) , selfCheckDone( true ) , m_sceneShader( NULL ) + , m_genericSceneShader( NULL ) { if( !initRenderingContext() ) return; initGL(); debug = qstrcmp( qgetenv( "KWIN_GL_DEBUG" ), "1" ) == 0; - - m_sceneShader = new GLShader( ":/resources/scene-vertex.glsl", ":/resources/scene-fragment.glsl" ); - if( m_sceneShader->isValid() ) - { - m_sceneShader->bind(); - m_sceneShader->setUniform( "sample", 0 ); - m_sceneShader->setUniform( "displaySize", QVector2D(displayWidth(), displayHeight())); - m_sceneShader->setUniform( "debug", debug ? 1 : 0 ); - m_sceneShader->unbind(); - kDebug(1212) << "Scene Shader is valid"; - } - else - { - delete m_sceneShader; - m_sceneShader = NULL; - kDebug(1212) << "Scene Shader is not valid"; + if (!setupSceneShaders()) { + kError( 1212 ) << "Shaders not valid, ES compositing not possible"; return; - } + } + if( checkGLError( "Init" )) { diff --git a/scene_opengl_glx.cpp b/scene_opengl_glx.cpp index 0a237a9124..3a559c95f0 100644 --- a/scene_opengl_glx.cpp +++ b/scene_opengl_glx.cpp @@ -40,6 +40,7 @@ SceneOpenGL::SceneOpenGL( Workspace* ws ) , init_ok( false ) , selfCheckDone( false ) , m_sceneShader( NULL ) + , m_genericSceneShader( NULL ) { if( !Extensions::glxAvailable()) { @@ -99,24 +100,7 @@ SceneOpenGL::SceneOpenGL( Workspace* ws ) GLPlatform::instance()->detect(); if( GLPlatform::instance()->supports( GLSL ) ) { - m_sceneShader = new GLShader( ":/resources/scene-vertex.glsl", ":/resources/scene-fragment.glsl" ); - if( m_sceneShader->isValid() ) - { - m_sceneShader->bind(); - m_sceneShader->setUniform( "sample", 0 ); - m_sceneShader->setUniform( "displaySize", QVector2D(displayWidth(), displayHeight())); - m_sceneShader->setUniform( "debug", debug ? 1 : 0 ); - m_sceneShader->bindAttributeLocation( 0, "vertex" ); - m_sceneShader->bindAttributeLocation( 1, "texCoord" ); - m_sceneShader->unbind(); - kDebug(1212) << "Scene Shader is valid"; - } - else - { - delete m_sceneShader; - m_sceneShader = NULL; - kDebug(1212) << "Scene Shader is not valid"; - } + setupSceneShader(); } // OpenGL scene setup