Adding a generic scene shader able to handle transformation

Currently only window transformations are supported.
icc-effect-5.14.5
Martin Gräßlin 2010-12-04 12:31:18 +01:00 committed by Martin Gräßlin
parent a2e214d326
commit eb7d06d22f
6 changed files with 122 additions and 43 deletions

View File

@ -4,5 +4,6 @@
<file>lanczos-fragment.glsl</file>
<file>scene-vertex.glsl</file>
<file>scene-fragment.glsl</file>
<file>scene-generic-vertex.glsl</file>
</qresource>
</RCC>

19
scene-generic-vertex.glsl Normal file
View File

@ -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;
}

View File

@ -92,6 +92,7 @@ Sources and other compositing managers:
#include <qpainter.h>
#include <QVector2D>
#include <QVector4D>
#include <QMatrix4x4>
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<SceneOpenGL*>(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<SceneOpenGL*>(scene)->m_genericSceneShader;
data.shader->bind();
} else {
data.shader = static_cast<SceneOpenGL*>(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

View File

@ -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;
};

View File

@ -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" ))
{

View File

@ -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