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
This commit is contained in:
Martin Gräßlin 2016-10-06 09:57:56 +02:00
parent 196ac5eb38
commit ff6e042c7f
3 changed files with 19 additions and 5 deletions

View file

@ -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 &region, 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 &region, 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);
}
}

View file

@ -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

View file

@ -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 &region, 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);