Cover+Flip, multiscreen: fix matrix manipulation
Moves calculation of projection and modelview matrix (aligned to new scene_opengl code) to effect start, caches the matrices in private members and sets them on WindowPaintData BUG: 343509 REVIEW: 122355 FIXED-IN: 5.3
This commit is contained in:
parent
2e820dbdef
commit
9f3656c917
4 changed files with 139 additions and 127 deletions
|
@ -139,61 +139,6 @@ void CoverSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& d
|
|||
effects->paintScreen(mask, region, data);
|
||||
|
||||
if (mActivated || stop || stopRequested) {
|
||||
QMatrix4x4 origProjection;
|
||||
QMatrix4x4 origModelview;
|
||||
ShaderManager *shaderManager = ShaderManager::instance();
|
||||
if (effects->numScreens() > 1) {
|
||||
// unfortunatelly we have to change the projection matrix in dual screen mode
|
||||
QRect fullRect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
||||
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;
|
||||
float xTranslate = 0.0;
|
||||
float yTranslate = 0.0;
|
||||
float xminFactor = 1.0;
|
||||
float xmaxFactor = 1.0;
|
||||
float yminFactor = 1.0;
|
||||
float ymaxFactor = 1.0;
|
||||
if (area.x() == 0 && area.width() != fullRect.width()) {
|
||||
// horizontal layout: left screen
|
||||
xminFactor = (float)area.width() / (float)fullRect.width();
|
||||
xmaxFactor = ((float)fullRect.width() - (float)area.width() * 0.5f) / ((float)fullRect.width() * 0.5f);
|
||||
xTranslate = (float)fullRect.width() * 0.5f - (float)area.width() * 0.5f;
|
||||
}
|
||||
if (area.x() != 0 && area.width() != fullRect.width()) {
|
||||
// horizontal layout: right screen
|
||||
xminFactor = ((float)fullRect.width() - (float)area.width() * 0.5f) / ((float)fullRect.width() * 0.5f);
|
||||
xmaxFactor = (float)area.width() / (float)fullRect.width();
|
||||
xTranslate = (float)fullRect.width() * 0.5f - (float)area.width() * 0.5f;
|
||||
}
|
||||
if (area.y() == 0 && area.height() != fullRect.height()) {
|
||||
// vertical layout: top screen
|
||||
yminFactor = ((float)fullRect.height() - (float)area.height() * 0.5f) / ((float)fullRect.height() * 0.5f);
|
||||
ymaxFactor = (float)area.height() / (float)fullRect.height();
|
||||
yTranslate = (float)fullRect.height() * 0.5f - (float)area.height() * 0.5f;
|
||||
}
|
||||
if (area.y() != 0 && area.height() != fullRect.height()) {
|
||||
// vertical layout: bottom screen
|
||||
yminFactor = (float)area.height() / (float)fullRect.height();
|
||||
ymaxFactor = ((float)fullRect.height() - (float)area.height() * 0.5f) / ((float)fullRect.height() * 0.5f);
|
||||
yTranslate = (float)fullRect.height() * 0.5f - (float)area.height() * 0.5f;
|
||||
}
|
||||
QMatrix4x4 projection;
|
||||
projection.frustum(xmin * xminFactor, xmax * xmaxFactor, ymin * yminFactor, ymax * ymaxFactor, zNear, zFar);
|
||||
QMatrix4x4 modelview;
|
||||
modelview.translate(xTranslate, yTranslate, 0.0);
|
||||
GLShader *shader = shaderManager->pushShader(ShaderManager::GenericShader);
|
||||
origProjection = shader->getUniformMatrix4x4("projection");
|
||||
origModelview = shader->getUniformMatrix4x4("modelview");
|
||||
shader->setUniform("projection", projection);
|
||||
shader->setUniform("modelview", origModelview * modelview);
|
||||
shaderManager->popShader();
|
||||
}
|
||||
|
||||
QList< EffectWindow* > tempList = currentWindowList;
|
||||
int index = tempList.indexOf(selected_window);
|
||||
|
@ -296,7 +241,7 @@ void CoverSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& d
|
|||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
if (m_reflectionShader && m_reflectionShader->isValid()) {
|
||||
shaderManager->pushShader(m_reflectionShader);
|
||||
ShaderManager::instance()->pushShader(m_reflectionShader);
|
||||
QMatrix4x4 windowTransformation;
|
||||
windowTransformation.translate(area.x() + area.width() * 0.5f, 0.0, 0.0);
|
||||
m_reflectionShader->setUniform("windowTransformation", windowTransformation);
|
||||
|
@ -324,20 +269,13 @@ void CoverSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& d
|
|||
vbo->setData(6, 3, verts.data(), texcoords.data());
|
||||
vbo->render(GL_TRIANGLES);
|
||||
|
||||
shaderManager->popShader();
|
||||
ShaderManager::instance()->popShader();
|
||||
}
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
paintScene(frontWindow, leftWindows, rightWindows);
|
||||
|
||||
if (effects->numScreens() > 1) {
|
||||
GLShader *shader = shaderManager->pushShader(ShaderManager::GenericShader);
|
||||
shader->setUniform("projection", origProjection);
|
||||
shader->setUniform("modelview", origModelview);
|
||||
shaderManager->popShader();
|
||||
}
|
||||
|
||||
// Render the caption frame
|
||||
if (windowTitle) {
|
||||
double opacity = 1.0;
|
||||
|
@ -518,6 +456,62 @@ void CoverSwitchEffect::slotTabBoxAdded(int mode)
|
|||
}
|
||||
}
|
||||
|
||||
if (effects->numScreens() > 1) {
|
||||
// unfortunatelly we have to change the projection matrix in dual screen mode
|
||||
// code is adapted from SceneOpenGL2::createProjectionMatrix()
|
||||
QRect fullRect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
||||
float fovy = 60.0f;
|
||||
float aspect = 1.0f;
|
||||
float zNear = 0.1f;
|
||||
float zFar = 100.0f;
|
||||
|
||||
float ymax = zNear * std::tan(fovy * M_PI / 360.0f);
|
||||
float ymin = -ymax;
|
||||
float xmin = ymin * aspect;
|
||||
float xmax = ymax * aspect;
|
||||
|
||||
if (area.width() != fullRect.width()) {
|
||||
if (area.x() == 0) {
|
||||
// horizontal layout: left screen
|
||||
xmin *= (float)area.width() / (float)fullRect.width();
|
||||
xmax *= (fullRect.width() - 0.5f * area.width()) / (0.5f * fullRect.width());
|
||||
} else {
|
||||
// horizontal layout: right screen
|
||||
xmin *= (fullRect.width() - 0.5f * area.width()) / (0.5f * fullRect.width());
|
||||
xmax *= (float)area.width() / (float)fullRect.width();
|
||||
}
|
||||
}
|
||||
if (area.height() != fullRect.height()) {
|
||||
if (area.y() == 0) {
|
||||
// vertical layout: top screen
|
||||
ymin *= (fullRect.height() - 0.5f * area.height()) / (0.5f * fullRect.height());
|
||||
ymax *= (float)area.height() / (float)fullRect.height();
|
||||
} else {
|
||||
// vertical layout: bottom screen
|
||||
ymin *= (float)area.height() / (float)fullRect.height();
|
||||
ymax *= (fullRect.height() - 0.5f * area.height()) / (0.5f * fullRect.height());
|
||||
}
|
||||
}
|
||||
|
||||
m_projectionMatrix = QMatrix4x4();
|
||||
m_projectionMatrix.frustum(xmin, xmax, ymin, ymax, zNear, zFar);
|
||||
|
||||
const float scaleFactor = 1.1f / zNear;
|
||||
|
||||
// Create a second matrix that transforms screen coordinates
|
||||
// to world coordinates.
|
||||
QMatrix4x4 matrix;
|
||||
matrix.translate(xmin * scaleFactor, ymax * scaleFactor, -1.1);
|
||||
matrix.scale( (xmax - xmin) * scaleFactor / fullRect.width(),
|
||||
-(ymax - ymin) * scaleFactor / fullRect.height(),
|
||||
0.001);
|
||||
// Combine the matrices
|
||||
m_projectionMatrix *= matrix;
|
||||
|
||||
m_modelviewMatrix = QMatrix4x4();
|
||||
m_modelviewMatrix.translate(area.x(), area.y(), 0.0);
|
||||
}
|
||||
|
||||
// Setup caption frame geometry
|
||||
if (windowTitle) {
|
||||
QRect frameRect = QRect(area.width() * 0.25f + area.x(),
|
||||
|
@ -715,6 +709,10 @@ void CoverSwitchEffect::paintFrontWindow(EffectWindow* frontWindow, int width, i
|
|||
return;
|
||||
bool specialHandlingForward = false;
|
||||
WindowPaintData data(frontWindow);
|
||||
if (effects->numScreens() > 1) {
|
||||
data.setProjectionMatrix(m_projectionMatrix);
|
||||
data.setModelViewMatrix(m_modelviewMatrix);
|
||||
}
|
||||
data.setXTranslation(area.width() * 0.5 - frontWindow->geometry().x() - frontWindow->geometry().width() * 0.5);
|
||||
if (leftWindows == 0) {
|
||||
leftWindows = 1;
|
||||
|
@ -773,6 +771,10 @@ void CoverSwitchEffect::paintWindows(const EffectWindowList& windows, bool left,
|
|||
// has to appear on this side after half of the time
|
||||
if (animation && timeLine.currentValue() >= 0.5 && additionalWindow != NULL) {
|
||||
WindowPaintData data(additionalWindow);
|
||||
if (effects->numScreens() > 1) {
|
||||
data.setProjectionMatrix(m_projectionMatrix);
|
||||
data.setModelViewMatrix(m_modelviewMatrix);
|
||||
}
|
||||
data.setRotationAxis(Qt::YAxis);
|
||||
data.setRotationAngle(angle * rotateFactor);
|
||||
if (left) {
|
||||
|
@ -793,6 +795,10 @@ void CoverSwitchEffect::paintWindows(const EffectWindowList& windows, bool left,
|
|||
continue;
|
||||
}
|
||||
WindowPaintData data(window);
|
||||
if (effects->numScreens() > 1) {
|
||||
data.setProjectionMatrix(m_projectionMatrix);
|
||||
data.setModelViewMatrix(m_modelviewMatrix);
|
||||
}
|
||||
data.setRotationAxis(Qt::YAxis);
|
||||
data.setRotationAngle(angle);
|
||||
if (left)
|
||||
|
|
|
@ -157,6 +157,8 @@ private:
|
|||
bool secondaryTabBox;
|
||||
|
||||
GLShader *m_reflectionShader;
|
||||
QMatrix4x4 m_projectionMatrix;
|
||||
QMatrix4x4 m_modelviewMatrix;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -192,62 +192,6 @@ void FlipSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da
|
|||
}
|
||||
}
|
||||
|
||||
// multiscreen part taken from coverswitch.cpp
|
||||
// TODO: move to kwinglutils
|
||||
QMatrix4x4 origProjection;
|
||||
QMatrix4x4 origModelview;
|
||||
if (effects->numScreens() > 1) {
|
||||
// unfortunatelly we have to change the projection matrix in dual screen mode
|
||||
QRect fullRect = effects->clientArea(FullArea, effects->activeScreen(), effects->currentDesktop());
|
||||
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;
|
||||
float xTranslate = 0.0;
|
||||
float yTranslate = 0.0;
|
||||
float xminFactor = 1.0;
|
||||
float xmaxFactor = 1.0;
|
||||
float yminFactor = 1.0;
|
||||
float ymaxFactor = 1.0;
|
||||
if (m_screenArea.x() == 0 && m_screenArea.width() != fullRect.width()) {
|
||||
// horizontal layout: left screen
|
||||
xminFactor = (float)m_screenArea.width() / (float)fullRect.width();
|
||||
xmaxFactor = ((float)fullRect.width() - (float)m_screenArea.width() * 0.5f) / ((float)fullRect.width() * 0.5f);
|
||||
xTranslate = (float)fullRect.width() * 0.5f - (float)m_screenArea.width() * 0.5f;
|
||||
}
|
||||
if (m_screenArea.x() != 0 && m_screenArea.width() != fullRect.width()) {
|
||||
// horizontal layout: right screen
|
||||
xminFactor = ((float)fullRect.width() - (float)m_screenArea.width() * 0.5f) / ((float)fullRect.width() * 0.5f);
|
||||
xmaxFactor = (float)m_screenArea.width() / (float)fullRect.width();
|
||||
xTranslate = (float)fullRect.width() * 0.5f - (float)m_screenArea.width() * 0.5f;
|
||||
}
|
||||
if (m_screenArea.y() == 0 && m_screenArea.height() != fullRect.height()) {
|
||||
// vertical layout: top screen
|
||||
yminFactor = ((float)fullRect.height() - (float)m_screenArea.height() * 0.5f) / ((float)fullRect.height() * 0.5f);
|
||||
ymaxFactor = (float)m_screenArea.height() / (float)fullRect.height();
|
||||
yTranslate = (float)fullRect.height() * 0.5f - (float)m_screenArea.height() * 0.5f;
|
||||
}
|
||||
if (m_screenArea.y() != 0 && m_screenArea.height() != fullRect.height()) {
|
||||
// vertical layout: bottom screen
|
||||
yminFactor = (float)m_screenArea.height() / (float)fullRect.height();
|
||||
ymaxFactor = ((float)fullRect.height() - (float)m_screenArea.height() * 0.5f) / ((float)fullRect.height() * 0.5f);
|
||||
yTranslate = (float)fullRect.height() * 0.5f - (float)m_screenArea.height() * 0.5f;
|
||||
}
|
||||
QMatrix4x4 projection;
|
||||
projection.frustum(xmin * xminFactor, xmax * xmaxFactor, ymin * yminFactor, ymax * ymaxFactor, zNear, zFar);
|
||||
QMatrix4x4 modelview;
|
||||
modelview.translate(xTranslate, yTranslate, 0.0);
|
||||
ShaderBinder binder(ShaderManager::GenericShader);
|
||||
GLShader *shader = binder.shader();
|
||||
origProjection = shader->getUniformMatrix4x4("projection");
|
||||
origModelview = shader->getUniformMatrix4x4("modelview");
|
||||
shader->setUniform("projection", projection);
|
||||
shader->setUniform("modelview", origModelview * modelview);
|
||||
}
|
||||
|
||||
int winMask = PAINT_WINDOW_TRANSFORMED | PAINT_WINDOW_TRANSLUCENT;
|
||||
// fade in/out one window at the end of the stack during animation
|
||||
|
@ -255,6 +199,10 @@ void FlipSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da
|
|||
EffectWindow* w = m_flipOrderedWindows.last();
|
||||
if (ItemInfo *info = m_windows.value(w,0)) {
|
||||
WindowPaintData data(w);
|
||||
if (effects->numScreens() > 1) {
|
||||
data.setProjectionMatrix(m_projectionMatrix);
|
||||
data.setModelViewMatrix(m_modelviewMatrix);
|
||||
}
|
||||
data.setRotationAxis(Qt::YAxis);
|
||||
data.setRotationAngle(m_angle * m_startStopTimeLine.currentValue());
|
||||
data.setOpacity(info->opacity);
|
||||
|
@ -286,6 +234,10 @@ void FlipSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da
|
|||
if (!info)
|
||||
continue;
|
||||
WindowPaintData data(w);
|
||||
if (effects->numScreens() > 1) {
|
||||
data.setProjectionMatrix(m_projectionMatrix);
|
||||
data.setModelViewMatrix(m_modelviewMatrix);
|
||||
}
|
||||
data.setRotationAxis(Qt::YAxis);
|
||||
data.setRotationAngle(m_angle * m_startStopTimeLine.currentValue());
|
||||
data.setOpacity(info->opacity);
|
||||
|
@ -342,13 +294,6 @@ void FlipSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da
|
|||
effects->drawWindow(w, winMask, infiniteRegion(), data);
|
||||
}
|
||||
|
||||
if (effects->numScreens() > 1) {
|
||||
ShaderBinder binder(ShaderManager::GenericShader);
|
||||
GLShader *shader = binder.shader();
|
||||
shader->setUniform("projection", origProjection);
|
||||
shader->setUniform("modelview", origModelview);
|
||||
}
|
||||
|
||||
if (m_windowTitle) {
|
||||
// Render the caption frame
|
||||
if (m_animation) {
|
||||
|
@ -581,6 +526,62 @@ void FlipSwitchEffect::setActive(bool activate, FlipSwitchMode mode)
|
|||
m_activeScreen = effects->activeScreen();
|
||||
m_screenArea = effects->clientArea(ScreenArea, m_activeScreen, effects->currentDesktop());
|
||||
|
||||
if (effects->numScreens() > 1) {
|
||||
// unfortunatelly we have to change the projection matrix in dual screen mode
|
||||
// code is copied from Coverswitch
|
||||
QRect fullRect = effects->clientArea(FullArea, m_activeScreen, effects->currentDesktop());
|
||||
float fovy = 60.0f;
|
||||
float aspect = 1.0f;
|
||||
float zNear = 0.1f;
|
||||
float zFar = 100.0f;
|
||||
|
||||
float ymax = zNear * std::tan(fovy * M_PI / 360.0f);
|
||||
float ymin = -ymax;
|
||||
float xmin = ymin * aspect;
|
||||
float xmax = ymax * aspect;
|
||||
|
||||
if (m_screenArea.width() != fullRect.width()) {
|
||||
if (m_screenArea.x() == 0) {
|
||||
// horizontal layout: left screen
|
||||
xmin *= (float)m_screenArea.width() / (float)fullRect.width();
|
||||
xmax *= (fullRect.width() - 0.5f * m_screenArea.width()) / (0.5f * fullRect.width());
|
||||
} else {
|
||||
// horizontal layout: right screen
|
||||
xmin *= (fullRect.width() - 0.5f * m_screenArea.width()) / (0.5f * fullRect.width());
|
||||
xmax *= (float)m_screenArea.width() / (float)fullRect.width();
|
||||
}
|
||||
}
|
||||
if (m_screenArea.height() != fullRect.height()) {
|
||||
if (m_screenArea.y() == 0) {
|
||||
// vertical layout: top screen
|
||||
ymin *= (fullRect.height() - 0.5f * m_screenArea.height()) / (0.5f * fullRect.height());
|
||||
ymax *= (float)m_screenArea.height() / (float)fullRect.height();
|
||||
} else {
|
||||
// vertical layout: bottom screen
|
||||
ymin *= (float)m_screenArea.height() / (float)fullRect.height();
|
||||
ymax *= (fullRect.height() - 0.5f * m_screenArea.height()) / (0.5f * fullRect.height());
|
||||
}
|
||||
}
|
||||
|
||||
m_projectionMatrix = QMatrix4x4();
|
||||
m_projectionMatrix.frustum(xmin, xmax, ymin, ymax, zNear, zFar);
|
||||
|
||||
const float scaleFactor = 1.1f / zNear;
|
||||
|
||||
// Create a second matrix that transforms screen coordinates
|
||||
// to world coordinates.
|
||||
QMatrix4x4 matrix;
|
||||
matrix.translate(xmin * scaleFactor, ymax * scaleFactor, -1.1);
|
||||
matrix.scale( (xmax - xmin) * scaleFactor / fullRect.width(),
|
||||
-(ymax - ymin) * scaleFactor / fullRect.height(),
|
||||
0.001);
|
||||
// Combine the matrices
|
||||
m_projectionMatrix *= matrix;
|
||||
|
||||
m_modelviewMatrix = QMatrix4x4();
|
||||
m_modelviewMatrix.translate(m_screenArea.x(), m_screenArea.y(), 0.0);
|
||||
}
|
||||
|
||||
if (m_stop) {
|
||||
// effect is still closing from last usage
|
||||
m_stop = false;
|
||||
|
|
|
@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define KWIN_FLIPSWITCH_H
|
||||
|
||||
#include <kwineffects.h>
|
||||
#include <QMatrix4x4>
|
||||
#include <QQueue>
|
||||
#include <QTimeLine>
|
||||
|
||||
|
@ -133,6 +134,8 @@ private:
|
|||
QFont m_captionFont;
|
||||
EffectWindowList m_flipOrderedWindows;
|
||||
QHash< const EffectWindow*, ItemInfo* > m_windows;
|
||||
QMatrix4x4 m_projectionMatrix;
|
||||
QMatrix4x4 m_modelviewMatrix;
|
||||
// options
|
||||
bool m_tabbox;
|
||||
bool m_tabboxAlternative;
|
||||
|
|
Loading…
Reference in a new issue