From ff6e042c7f9617004fefe63dd657fc2abf374c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Thu, 6 Oct 2016 09:57:56 +0200 Subject: [PATCH] Fix scissoring of VBO rendering in multi-screen setup on Wayland Summary: On Wayland in multi-screen a "window" is used to render to per screen. In OpenGL every "window" is at 0/0 and scissoring is in respect to the window geometry. The rendering geometry passed to VBO rendering, which performs the scissoring, is in virtual combined screen geometry space. Thus the scissoring always removes any rendering on the second screen. This results in e.g. wobbly windows not working on any additional screen on Wayland. This change makes the VBO rendering multi-screen aware by passing the current virtual window geometry in each rendering pass. That replaces the so far used virtual screen size. For single screen rendering or multi-screen rendering on X11 this doesn't change anything as there is always only one OpenGL window and the screen geoemetry starts at 0/0. Thus the subtracting of x/y geometry do not affect the scissoring at all. Reviewers: #kwin, #plasma_on_wayland Subscribers: plasma-devel, kwin Tags: #plasma_on_wayland, #kwin Differential Revision: https://phabricator.kde.org/D2955 --- libkwineffects/kwinglutils.cpp | 5 +++-- libkwineffects/kwinglutils.h | 15 ++++++++++++++- scene_opengl.cpp | 4 ++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libkwineffects/kwinglutils.cpp b/libkwineffects/kwinglutils.cpp index bf73a4d8ec..271461c4c4 100644 --- a/libkwineffects/kwinglutils.cpp +++ b/libkwineffects/kwinglutils.cpp @@ -2022,6 +2022,7 @@ GLvoid *GLVertexBufferPrivate::mapNextFreeRange(size_t size) // GLVertexBuffer //********************************* QSize GLVertexBuffer::s_virtualScreenSize; +QRect GLVertexBuffer::s_virtualScreenGeometry; GLVertexBuffer::GLVertexBuffer(UsageHint hint) : d(new GLVertexBufferPrivate(hint)) @@ -2195,7 +2196,7 @@ void GLVertexBuffer::draw(const QRegion ®ion, GLenum primitiveMode, int first } else { // Clip using scissoring foreach (const QRect &r, region.rects()) { - glScissor(r.x(), s_virtualScreenSize.height() - r.y() - r.height(), r.width(), r.height()); + glScissor(r.x() - s_virtualScreenGeometry.x(), s_virtualScreenGeometry.height() - s_virtualScreenGeometry.y() - r.y() - r.height(), r.width(), r.height()); glDrawElementsBaseVertex(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, nullptr, first); } } @@ -2207,7 +2208,7 @@ void GLVertexBuffer::draw(const QRegion ®ion, GLenum primitiveMode, int first } else { // Clip using scissoring foreach (const QRect &r, region.rects()) { - glScissor(r.x(), s_virtualScreenSize.height() - r.y() - r.height(), r.width(), r.height()); + glScissor(r.x() - s_virtualScreenGeometry.x(), s_virtualScreenGeometry.height() - s_virtualScreenGeometry.y() - r.y() - r.height(), r.width(), r.height()); glDrawArrays(primitiveMode, first, count); } } diff --git a/libkwineffects/kwinglutils.h b/libkwineffects/kwinglutils.h index 5cb67b55bd..c3df01f17b 100644 --- a/libkwineffects/kwinglutils.h +++ b/libkwineffects/kwinglutils.h @@ -756,14 +756,27 @@ public: /** * Sets the virtual screen size to @p s. * @since 5.2 + * @deprecated since 5.9 use setVirtualScreenGeometry **/ - static void setVirtualScreenSize(const QSize &s) { + static void KWINGLUTILS_DEPRECATED setVirtualScreenSize(const QSize &s) { s_virtualScreenSize = s; } + /** + * Sets the virtual screen geometry to @p g. + * This is the geometry of the OpenGL window currently being rendered to + * in the virtual geometry space the rendering geometries use. + * @since 5.9 + **/ + static void setVirtualScreenGeometry(const QRect &g) { + s_virtualScreenGeometry = g; + } + private: GLVertexBufferPrivate* const d; + // TODO: remove with next ABI break static QSize s_virtualScreenSize; + static QRect s_virtualScreenGeometry; }; } // namespace diff --git a/scene_opengl.cpp b/scene_opengl.cpp index c8ce5db210..36c6fcfe27 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -699,6 +699,7 @@ qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels) QRegion valid; // prepare rendering makes context current on the output QRegion repaint = m_backend->prepareRenderingForScreen(i); + GLVertexBuffer::setVirtualScreenGeometry(geo); const GLenum status = glGetGraphicsResetStatus(); if (status != GL_NO_ERROR) { @@ -725,6 +726,7 @@ qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels) handleGraphicsReset(status); return 0; } + GLVertexBuffer::setVirtualScreenGeometry(screens()->geometry()); int mask = 0; updateProjectionMatrix(); @@ -919,7 +921,6 @@ void SceneOpenGL::screenGeometryChanged(const QSize &size) glViewport(0,0, size.width(), size.height()); m_backend->screenGeometryChanged(size); GLRenderTarget::setVirtualScreenSize(size); - GLVertexBuffer::setVirtualScreenSize(size); } void SceneOpenGL::paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data) @@ -1009,7 +1010,6 @@ SceneOpenGL2::SceneOpenGL2(OpenGLBackend *backend, QObject *parent) const QSize &s = screens()->size(); GLRenderTarget::setVirtualScreenSize(s); - GLVertexBuffer::setVirtualScreenSize(s); // push one shader on the stack so that one is always bound ShaderManager::instance()->pushShader(ShaderTrait::MapTexture);