Only create the viewport as needed

So far, we were creating a model view with the complete scene rendered
(even if we didn't render the windows themselves). This required us to
have a big glPerspective spanning the entire scene and we were just
cropping it as we rendered it into a smaller texture.

This changes our scenes so we have the correct matrix set up at all
times.

Specifically in the case of the Pinephone, this solves the following
issue where we were unable to connect external displays because it
exceeded GL_MAX_VIEWPORT_DIMS:
https://invent.kde.org/teams/plasma-mobile/issues/-/issues/11
This commit is contained in:
Aleix Pol 2021-06-08 22:25:40 +02:00
parent bec50eaec0
commit fffd41b32e
6 changed files with 23 additions and 51 deletions

View file

@ -684,12 +684,8 @@ PlatformSurfaceTexture *EglGbmBackend::createPlatformSurfaceTextureWayland(Surfa
void EglGbmBackend::setViewport(const Output &output) const
{
const QSize &overall = screens()->size();
const QRect &v = output.output->geometry();
qreal scale = output.output->scale();
glViewport(-v.x() * scale, (v.height() - overall.height() + v.y()) * scale,
overall.width() * scale, overall.height() * scale);
const QSize size = output.output->pixelSize();
glViewport(0, 0, size.width(), size.height());
}
QRegion EglGbmBackend::beginFrame(int screenId)

View file

@ -436,11 +436,8 @@ bool EglStreamBackend::makeContextCurrent(const Output &output)
return false;
}
const QSize &overall = screens()->size();
const QRect &v = output.output->geometry();
qreal scale = output.output->scale();
glViewport(-v.x() * scale, (v.height() - overall.height() + v.y()) * scale,
overall.width() * scale, overall.height() * scale);
const QSize size = output.output->pixelSize();
glViewport(0, 0, size.width(), size.height());
return true;
}

View file

@ -239,12 +239,8 @@ bool EglWaylandBackend::makeContextCurrent(EglWaylandOutput *output)
return false;
}
const QRect &v = output->m_waylandOutput->geometry();
const qreal scale = output->m_waylandOutput->scale();
const QSize overall = screens()->size();
glViewport(-v.x() * scale, (v.height() - overall.height() + v.y()) * scale,
overall.width() * scale, overall.height() * scale);
const QSize size = output->m_waylandOutput->pixelSize();
glViewport(0, 0, size.width(), size.height());
return true;
}

View file

@ -70,13 +70,9 @@ QRegion EglX11Backend::beginFrame(int screenId)
void EglX11Backend::setupViewport(int screenId)
{
// TODO: ensure the viewport is set correctly each time
const QSize &overall = screens()->size();
const QRect &v = screens()->geometry(screenId);
// TODO: are the values correct?
qreal scale = screens()->scale(screenId);
glViewport(-v.x(), v.height() - overall.height() + v.y(), overall.width() * scale, overall.height() * scale);
const QSize size = screens()->geometry(screenId).size() * scale;
glViewport(0, 0, size.width(), size.height());
}
void EglX11Backend::endFrame(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion)

View file

@ -64,6 +64,7 @@
#include <KLocalizedString>
#include <KNotification>
#include <KProcess>
#include <QtMath>
// HACK: workaround for libepoxy < 1.3
#ifndef GL_GUILTY_CONTEXT_RESET
@ -691,7 +692,7 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Topleve
GLRenderTarget::setVirtualScreenScale(scaling);
int mask = 0;
updateProjectionMatrix();
updateProjectionMatrix(geo);
paintScreen(&mask, damage.intersected(geo), repaint, &update, &valid,
renderLoop, projectionMatrix()); // call generic implementation
@ -1012,41 +1013,29 @@ SceneOpenGL2::~SceneOpenGL2()
}
}
QMatrix4x4 SceneOpenGL2::createProjectionMatrix() const
void SceneOpenGL2::updateProjectionMatrix(const QRect &rect)
{
// Create a perspective projection with a 60° field-of-view,
// and an aspect ratio of 1.0.
const float fovY = 60.0f;
m_projectionMatrix.setToIdentity();
const float fovY = std::tan(qDegreesToRadians(60.0f) / 2);
const float aspect = 1.0f;
const float zNear = 0.1f;
const float zFar = 100.0f;
const float yMax = zNear * std::tan(fovY * M_PI / 360.0f);
const float yMax = zNear * fovY;
const float yMin = -yMax;
const float xMin = yMin * aspect;
const float xMax = yMax * aspect;
QMatrix4x4 projection;
projection.frustum(xMin, xMax, yMin, yMax, zNear, zFar);
m_projectionMatrix.frustum(xMin, xMax, yMin, yMax, zNear, zFar);
// Create a second matrix that transforms screen coordinates
// to world coordinates.
const float scaleFactor = 1.1 * std::tan(fovY * M_PI / 360.0f) / yMax;
const QSize size = screens()->size();
QMatrix4x4 matrix;
matrix.translate(xMin * scaleFactor, yMax * scaleFactor, -1.1);
matrix.scale( (xMax - xMin) * scaleFactor / size.width(),
-(yMax - yMin) * scaleFactor / size.height(),
0.001);
// Combine the matrices
return projection * matrix;
}
void SceneOpenGL2::updateProjectionMatrix()
{
m_projectionMatrix = createProjectionMatrix();
const float scaleFactor = 1.1 * fovY / yMax;
m_projectionMatrix.translate(xMin * scaleFactor, yMax * scaleFactor, -1.1);
m_projectionMatrix.scale( (xMax - xMin) * scaleFactor / rect.width(),
-(yMax - yMin) * scaleFactor / rect.height(),
0.001);
m_projectionMatrix.translate(-rect.x(), -rect.y());
}
void SceneOpenGL2::paintSimpleScreen(int mask, const QRegion &region)

View file

@ -78,7 +78,7 @@ protected:
void handleGraphicsReset(GLenum status);
virtual void doPaintBackground(const QVector<float> &vertices) = 0;
virtual void updateProjectionMatrix() = 0;
virtual void updateProjectionMatrix(const QRect &geometry) = 0;
protected:
bool init_ok;
@ -114,14 +114,12 @@ protected:
void doPaintBackground(const QVector< float >& vertices) override;
Scene::Window *createWindow(Toplevel *t) override;
void finalDrawWindow(EffectWindowImpl* w, int mask, const QRegion &region, WindowPaintData& data) override;
void updateProjectionMatrix() override;
void updateProjectionMatrix(const QRect &geometry) override;
void paintCursor(const QRegion &region) override;
private:
void performPaintWindow(EffectWindowImpl* w, int mask, const QRegion &region, WindowPaintData& data);
QMatrix4x4 createProjectionMatrix() const;
private:
LanczosFilter *m_lanczosFilter;
QScopedPointer<GLTexture> m_cursorTexture;
QMatrix4x4 m_projectionMatrix;