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:
parent
bec50eaec0
commit
fffd41b32e
6 changed files with 23 additions and 51 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ®ion)
|
||||
|
|
|
@ -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 ®ion, WindowPaintData& data) override;
|
||||
void updateProjectionMatrix() override;
|
||||
void updateProjectionMatrix(const QRect &geometry) override;
|
||||
void paintCursor(const QRegion ®ion) override;
|
||||
|
||||
private:
|
||||
void performPaintWindow(EffectWindowImpl* w, int mask, const QRegion ®ion, WindowPaintData& data);
|
||||
QMatrix4x4 createProjectionMatrix() const;
|
||||
|
||||
private:
|
||||
LanczosFilter *m_lanczosFilter;
|
||||
QScopedPointer<GLTexture> m_cursorTexture;
|
||||
QMatrix4x4 m_projectionMatrix;
|
||||
|
|
Loading…
Reference in a new issue