diff --git a/lib/kwineffects.cpp b/lib/kwineffects.cpp index 1073670faa..702bf93209 100644 --- a/lib/kwineffects.cpp +++ b/lib/kwineffects.cpp @@ -64,11 +64,14 @@ WindowPaintData::WindowPaintData( EffectWindow* w ) , decoration_opacity( 1.0 ) , xScale( 1 ) , yScale( 1 ) + , zScale( 1 ) , xTranslate( 0 ) , yTranslate( 0 ) + , zTranslate( 0 ) , saturation( 1 ) , brightness( 1 ) , shader( NULL ) + , rotation( NULL ) { quads = w->buildQuads(); } @@ -76,8 +79,20 @@ WindowPaintData::WindowPaintData( EffectWindow* w ) ScreenPaintData::ScreenPaintData() : xScale( 1 ) , yScale( 1 ) + , zScale( 1 ) , xTranslate( 0 ) , yTranslate( 0 ) + , zTranslate( 0 ) + , rotation( NULL ) + { + } + +RotationData::RotationData() + : axis( ZAxis ) + , angle( 0.0 ) + , xRotationPoint( 0.0 ) + , yRotationPoint( 0.0 ) + , zRotationPoint( 0.0 ) { } diff --git a/lib/kwineffects.h b/lib/kwineffects.h index 058f704020..e0b971c8d7 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -56,6 +56,7 @@ class Effect; class WindowQuad; class GLRenderTarget; class GLShader; +class RotationData; class WindowQuadList; class WindowPrePaintData; class WindowPaintData; @@ -162,7 +163,7 @@ X-KDE-Library=kwin4_effect_cooleffect #define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor )) #define KWIN_EFFECT_API_VERSION_MAJOR 0 -#define KWIN_EFFECT_API_VERSION_MINOR 50 +#define KWIN_EFFECT_API_VERSION_MINOR 51 #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \ KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR ) @@ -873,8 +874,10 @@ class KWIN_EXPORT WindowPaintData double decoration_opacity; double xScale; double yScale; + double zScale; int xTranslate; int yTranslate; + double zTranslate; /** * Saturation of the window, in range [0; 1] * 1 means that the window is unchanged, 0 means that it's completely @@ -895,6 +898,7 @@ class KWIN_EXPORT WindowPaintData * Shader to be used for rendering, if any. */ GLShader* shader; + RotationData* rotation; }; class KWIN_EXPORT ScreenPaintData @@ -903,8 +907,11 @@ class KWIN_EXPORT ScreenPaintData ScreenPaintData(); double xScale; double yScale; + double zScale; int xTranslate; int yTranslate; + double zTranslate; + RotationData* rotation; }; class KWIN_EXPORT ScreenPrePaintData @@ -914,6 +921,23 @@ class KWIN_EXPORT ScreenPrePaintData QRegion paint; }; +class KWIN_EXPORT RotationData + { + public: + RotationData(); + enum RotationAxis + { + XAxis, + YAxis, + ZAxis + }; + RotationAxis axis; + float angle; + float xRotationPoint; + float yRotationPoint; + float zRotationPoint; + }; + /** * @short Helper class for restricting painting area only to allowed area. * diff --git a/scene_opengl.cpp b/scene_opengl.cpp index cb9dc33d14..e9424fd34c 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -159,8 +159,16 @@ SceneOpenGL::SceneOpenGL( Workspace* ws ) // OpenGL scene setup glMatrixMode( GL_PROJECTION ); glLoadIdentity(); + 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; // swap top and bottom to have OpenGL coordinate system match X system - glOrtho( 0, displayWidth(), displayHeight(), 0, 0, 65535 ); + glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); if( checkGLError( "Init" )) @@ -171,6 +179,9 @@ SceneOpenGL::SceneOpenGL( Workspace* ws ) kDebug( 1212 ) << "DB:" << db << ", TFP:" << tfp_mode << ", SHM:" << shm_mode << ", Direct:" << bool( glXIsDirect( display(), ctxbuffer )) << endl; init_ok = true; + float scaleFactor = 1.1 * tan( fovy * M_PI / 360.0f )/ymax; + glTranslatef( xmin*scaleFactor, ymax*scaleFactor, -1.1 ); + glScalef( (xmax-xmin)*scaleFactor/displayWidth(), -(ymax-ymin)*scaleFactor/displayHeight(), 0.001 ); } SceneOpenGL::~SceneOpenGL() @@ -715,8 +726,30 @@ void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data ) if( mask & PAINT_SCREEN_TRANSFORMED ) { // apply screen transformations glPushMatrix(); - glTranslatef( data.xTranslate, data.yTranslate, 0 ); - glScalef( data.xScale, data.yScale, 1 ); + glTranslatef( data.xTranslate, data.yTranslate, data.zTranslate ); + if( data.rotation ) + { + // translate to rotation point, rotate, translate back + glTranslatef( data.rotation->xRotationPoint, data.rotation->yRotationPoint, data.rotation->zRotationPoint ); + float xAxis = 0.0; + float yAxis = 0.0; + float 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; + } + glRotatef( data.rotation->angle, xAxis, yAxis, zAxis ); + glTranslatef( -data.rotation->xRotationPoint, -data.rotation->yRotationPoint, -data.rotation->zRotationPoint ); + } + glScalef( data.xScale, data.yScale, data.zScale ); } Scene::paintGenericScreen( mask, data ); if( mask & PAINT_SCREEN_TRANSFORMED ) @@ -1243,14 +1276,37 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat // do required transformations int x = toplevel->x(); int y = toplevel->y(); + double z = 0.0; if( mask & PAINT_WINDOW_TRANSFORMED ) { x += data.xTranslate; y += data.yTranslate; + z += data.zTranslate; + } + glTranslatef( x, y, z ); + if(( mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 || data.zScale != 1 )) + glScalef( data.xScale, data.yScale, data.zScale ); + if(( mask & PAINT_WINDOW_TRANSFORMED ) && data.rotation ) + { + glTranslatef( data.rotation->xRotationPoint, data.rotation->yRotationPoint, data.rotation->zRotationPoint ); + float xAxis = 0.0; + float yAxis = 0.0; + float 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; + } + glRotatef( data.rotation->angle, xAxis, yAxis, zAxis ); + glTranslatef( -data.rotation->xRotationPoint, -data.rotation->yRotationPoint, -data.rotation->zRotationPoint ); } - glTranslatef( x, y, 0 ); - if(( mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 )) - glScalef( data.xScale, data.yScale, 1 ); region.translate( toplevel->x(), toplevel->y() ); // Back to screen coords texture.bind();