From 2419c949bfc4673157555f191f417cafb1bb04a0 Mon Sep 17 00:00:00 2001 From: Alex Nemeth Date: Tue, 29 May 2018 15:28:27 +0200 Subject: [PATCH 1/4] Fix multimonitor blur Summary: On wayland blur on secondary monitor would not render correctly. BUG: 393723 Depends on D12452 Test Plan: - use more than one output - log in in a wayland session - open a transparent window (for example: Konsole with transparent and blur enabled profile) - drag the window to another screen - blurs the content under the window corretly Reviewers: #kwin, graesslin, davidedmundson Reviewed By: #kwin, davidedmundson Subscribers: apol, zzag, davidedmundson, kwin, #kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D12678 --- effects/blur/blur.cpp | 45 ++++++++++++++++++------------------- effects/blur/blur.h | 2 +- effects/blur/blurshader.cpp | 11 ++++----- effects/blur/blurshader.h | 1 - 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/effects/blur/blur.cpp b/effects/blur/blur.cpp index 7a90c92d78..1678b531dd 100644 --- a/effects/blur/blur.cpp +++ b/effects/blur/blur.cpp @@ -610,13 +610,25 @@ void BlurEffect::generateNoiseTexture() void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float opacity, const QMatrix4x4 &screenProjection, bool isDock, QRect windowRect) { - QRegion expandedBlurRegion = expand(shape) & expand(screen); + // Blur would not render correctly on a secondary monitor because of wrong coordinates + // BUG: 393723 + const int xTranslate = -screen.x(); + const int yTranslate = effects->virtualScreenSize().height() - screen.height() - screen.y(); + + const QRegion expandedBlurRegion = expand(shape) & expand(screen); // Upload geometry for the down and upsample iterations GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); - uploadGeometry(vbo, expandedBlurRegion, shape); + + uploadGeometry(vbo, expandedBlurRegion.translated(xTranslate, yTranslate), shape); vbo->bindArrays(); + const QRect sourceRect = expandedBlurRegion.boundingRect() & screen; + const QRect destRect = sourceRect.translated(xTranslate, yTranslate); + + GLRenderTarget::pushRenderTargets(m_renderTargetStack); + int blurRectCount = expandedBlurRegion.rectCount() * 6; + /* * If the window is a dock or panel we avoid the "extended blur" effect. * Extended blur is when windows that are not under the blurred area affect @@ -624,26 +636,12 @@ void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float o * We want to avoid this on panels, because it looks really weird and ugly * when maximized windows or windows near the panel affect the dock blur. */ - isDock ? m_renderTextures.last().bind() : m_renderTextures[0].bind(); - - QRect copyRect = expandedBlurRegion.boundingRect() & screen; - glCopyTexSubImage2D( - GL_TEXTURE_2D, - 0, - copyRect.x(), - effects->virtualScreenSize().height() - copyRect.y() - copyRect.height(), - copyRect.x(), - effects->virtualScreenSize().height() - copyRect.y() - copyRect.height(), - copyRect.width(), - copyRect.height() - ); - - GLRenderTarget::pushRenderTargets(m_renderTargetStack); - int blurRectCount = expandedBlurRegion.rectCount() * 6; - if (isDock) { - copyScreenSampleTexture(vbo, blurRectCount, shape, screen.size(), screenProjection); + m_renderTargets.last()->blitFromFramebuffer(sourceRect, destRect); + copyScreenSampleTexture(vbo, blurRectCount, shape.translated(xTranslate, yTranslate), screenProjection); } else { + m_renderTargets.first()->blitFromFramebuffer(sourceRect, destRect); + // Remove the m_renderTargets[0] from the top of the stack that we will not use GLRenderTarget::popRenderTarget(); } @@ -750,18 +748,19 @@ void BlurEffect::upSampleTexture(GLVertexBuffer *vbo, int blurRectCount) m_shader->unbind(); } -void BlurEffect::copyScreenSampleTexture(GLVertexBuffer *vbo, int blurRectCount, QRegion blurShape, QSize screenSize, QMatrix4x4 screenProjection) +void BlurEffect::copyScreenSampleTexture(GLVertexBuffer *vbo, int blurRectCount, QRegion blurShape, QMatrix4x4 screenProjection) { m_shader->bind(BlurShader::CopySampleType); m_shader->setModelViewProjectionMatrix(screenProjection); - m_shader->setTargetTextureSize(screenSize); + m_shader->setTargetTextureSize(effects->virtualScreenSize()); /* * This '1' sized adjustment is necessary do avoid windows affecting the blur that are * right next to this window. */ - m_shader->setBlurRect(blurShape.boundingRect().adjusted(1, 1, -1, -1), screenSize); + m_shader->setBlurRect(blurShape.boundingRect().adjusted(1, 1, -1, -1), effects->virtualScreenSize()); + m_renderTextures.last().bind(); vbo->draw(GL_TRIANGLES, 0, blurRectCount); GLRenderTarget::popRenderTarget(); diff --git a/effects/blur/blur.h b/effects/blur/blur.h index 7deefff4d1..ec1d845c3a 100644 --- a/effects/blur/blur.h +++ b/effects/blur/blur.h @@ -91,7 +91,7 @@ private: void upscaleRenderToScreen(GLVertexBuffer *vbo, int vboStart, int blurRectCount, QMatrix4x4 screenProjection, QPoint windowPosition); void downSampleTexture(GLVertexBuffer *vbo, int blurRectCount); void upSampleTexture(GLVertexBuffer *vbo, int blurRectCount); - void copyScreenSampleTexture(GLVertexBuffer *vbo, int blurRectCount, QRegion blurShape, QSize screenSize, QMatrix4x4 screenProjection); + void copyScreenSampleTexture(GLVertexBuffer *vbo, int blurRectCount, QRegion blurShape, QMatrix4x4 screenProjection); private: BlurShader *m_shader; diff --git a/effects/blur/blurshader.cpp b/effects/blur/blurshader.cpp index d16600ef1f..c07974dd3f 100644 --- a/effects/blur/blurshader.cpp +++ b/effects/blur/blurshader.cpp @@ -197,16 +197,14 @@ void GLSLBlurShader::setTexturePosition(QPoint texPos) void GLSLBlurShader::setBlurRect(QRect blurRect, QSize screenSize) { - if (!isValid() || blurRect == m_blurRectCopysample) + if (!isValid()) return; - m_blurRectCopysample = blurRect; - QVector4D rect = QVector4D( blurRect.bottomLeft().x() / float(screenSize.width()), - 1.0 - blurRect.bottomLeft().y() / float(screenSize.height()), - blurRect.topRight().x() / float(screenSize.width()), - 1.0 - blurRect.topRight().y() / float(screenSize.height()) + 1.0 - blurRect.bottomLeft().y() / float(screenSize.height()), + blurRect.topRight().x() / float(screenSize.width()), + 1.0 - blurRect.topRight().y() / float(screenSize.height()) ); m_shaderCopysample->setUniform(m_blurRectLocationCopysample, rect); @@ -474,7 +472,6 @@ void GLSLBlurShader::init() m_matrixUpsample = QMatrix4x4(); m_matrixCopysample = QMatrix4x4(); - m_blurRectCopysample = QRect(); m_offsetNoisesample = 0.0; m_noiseTextureSizeNoisesample = QVector2D(); diff --git a/effects/blur/blurshader.h b/effects/blur/blurshader.h index 81f4ddee9b..440f526f4e 100644 --- a/effects/blur/blurshader.h +++ b/effects/blur/blurshader.h @@ -133,7 +133,6 @@ private: QMatrix4x4 m_matrixUpsample; QMatrix4x4 m_matrixCopysample; - QRect m_blurRectCopysample; float m_offsetNoisesample; QVector2D m_noiseTextureSizeNoisesample; From 982316072d5f83783042b7c83ebf52e7a56a650c Mon Sep 17 00:00:00 2001 From: Alex Nemeth Date: Tue, 29 May 2018 15:21:59 +0200 Subject: [PATCH 2/4] [libkwineffects/kwinglutils] Calculate correct srcY0 and srcY1 in GLRenderTarget::blitFromFramebuffer Summary: There are several spaces that have to be considered in `GLRenderTarget::blitFromFramebuffer`: * KWin logical space: the origin is located at the global top-left corner * display space: the origin is located at the top-left corner of monitor/display * OpenGL screen space: the origin is located at the bottom-left corner of monitor/display Given `s`, which is in the KWin logical space, we have to transform it to the display space, then to the OpenGL screen space: * KWin logical space -> display space: `y' = s.y() - s_virtualScreenGeometry.y()` * display space -> OpenGL screen space: `y'' = s_virtualScreenGeometry.height() - y'` Overall, `srcY0` and `srcY1` should be written as follows: ``` srcY0 = s_virtualScreenGeometry.height() - (s.y() - s_virtualScreenGeometry.y() + s.height()) srcY1 = s_virtualScreenGeometry.height() - (s.y() - s_virtualScreenGeometry.y()) ``` Test Plan: Tweak background contrast effect to use GLRenderTarget::blitFromFramebuffer ``` diff --git a/effects/backgroundcontrast/contrast.cpp b/effects/backgroundcontrast/contrast.cpp index f920fcd88..5247d83b8 100644 --- a/effects/backgroundcontrast/contrast.cpp +++ b/effects/backgroundcontrast/contrast.cpp @@ -447,11 +447,10 @@ void ContrastEffect::doContrast(EffectWindow *w, const QRegion& shape, const QRe GLTexture scratch(GL_RGBA8, r.width() * scale, r.height() * scale); scratch.setFilter(GL_LINEAR); scratch.setWrapMode(GL_CLAMP_TO_EDGE); - scratch.bind(); - const QRect sg = GLRenderTarget::virtualScreenGeometry(); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (r.x() - sg.x()) * scale, (sg.height() - sg.y() - r.y() - r.height()) * scale, - scratch.width(), scratch.height()); + GLRenderTarget scratchTarget(scratch); + scratchTarget.blitFromFramebuffer(r); + scratch.bind(); // Draw the texture on the offscreen framebuffer object, while blurring it horizontally ``` GLRenderTarget::blitFromFramebuffer without this change: {F5817883, layout=center, size=full} Reviewers: #kwin, fredrik, davidedmundson Reviewed By: #kwin, davidedmundson Subscribers: kpiwowarski, davidedmundson, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D12452 --- libkwineffects/kwinglutils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libkwineffects/kwinglutils.cpp b/libkwineffects/kwinglutils.cpp index 24a14de094..84bb73bebc 100644 --- a/libkwineffects/kwinglutils.cpp +++ b/libkwineffects/kwinglutils.cpp @@ -1301,9 +1301,9 @@ void GLRenderTarget::blitFromFramebuffer(const QRect &source, const QRect &desti const QRect d = destination.isNull() ? QRect(0, 0, mTexture.width(), mTexture.height()) : destination; glBlitFramebuffer((s.x() - s_virtualScreenGeometry.x()) * s_virtualScreenScale, - (s_virtualScreenGeometry.height() - s_virtualScreenGeometry.y() + s.y() - s.height()) * s_virtualScreenScale, + (s_virtualScreenGeometry.height() - (s.y() - s_virtualScreenGeometry.y() + s.height())) * s_virtualScreenScale, (s.x() - s_virtualScreenGeometry.x() + s.width()) * s_virtualScreenScale, - (s_virtualScreenGeometry.height() - s_virtualScreenGeometry.y() + s.y()) * s_virtualScreenScale, + (s_virtualScreenGeometry.height() - (s.y() - s_virtualScreenGeometry.y())) * s_virtualScreenScale, d.x(), mTexture.height() - d.y() - d.height(), d.x() + d.width(), mTexture.height() - d.y(), GL_COLOR_BUFFER_BIT, filter); GLRenderTarget::popRenderTarget(); From e92b9a65d897092b17554c933e3a4b5e354e0dc9 Mon Sep 17 00:00:00 2001 From: Jonathan Riddell Date: Tue, 19 Jun 2018 11:12:41 +0100 Subject: [PATCH 3/4] Update version number for 5.13.1 GIT_SILENT --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a843f2ffbc..bc35d88cb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) project(KWIN) -set(PROJECT_VERSION "5.13.0") +set(PROJECT_VERSION "5.13.1") set(PROJECT_VERSION_MAJOR 5) set(QT_MIN_VERSION "5.9.0") From 275b7ee0f456328de870dcdc297871d4eb8cfff2 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Wed, 20 Jun 2018 09:37:55 +0100 Subject: [PATCH 4/4] Workaround crash in Aurorae destruction Summary: Workaround QtBug-68997 Deleting of a RenderControl/render controlled window triggers deletion of other queued deleted items, putting KWin in a corrupt state. See Qt bug report. Deleting this queued means we know we don't have anything else going on in the stack which should make this somewhat safe. BUG: 395346 Test Plan: Couldn't reproduce original crash. Based purely on the incomplete backtrace and code reading Set an Aurorae theme. Closed some windows. Things still worked as before Reviewers: #kwin, #plasma, mart Reviewed By: #kwin, #plasma, mart Subscribers: kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D13614 --- plugins/kdecorations/aurorae/src/aurorae.cpp | 10 ++++------ plugins/kdecorations/aurorae/src/aurorae.h | 6 +++++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/plugins/kdecorations/aurorae/src/aurorae.cpp b/plugins/kdecorations/aurorae/src/aurorae.cpp index 4c5879be2e..15266b7987 100644 --- a/plugins/kdecorations/aurorae/src/aurorae.cpp +++ b/plugins/kdecorations/aurorae/src/aurorae.cpp @@ -270,8 +270,6 @@ Decoration::~Decoration() if (m_context) { m_context->makeCurrent(m_offscreenSurface.data()); - delete m_renderControl; - delete m_view.data(); m_fbo.reset(); delete m_item; @@ -324,8 +322,8 @@ void Decoration::init() m_item->setParentItem(visualParent.value()); visualParent.value()->setProperty("drawBackground", false); } else { - m_renderControl = new QQuickRenderControl(this); - m_view = new QQuickWindow(m_renderControl); + m_renderControl.reset(new QQuickRenderControl); + m_view = new QQuickWindow(m_renderControl.data()); bool usingGL = m_view->rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL; m_view->setColor(Qt::transparent); m_view->setFlags(Qt::FramelessWindowHint); @@ -392,8 +390,8 @@ void Decoration::init() } m_updateTimer->start(); }; - connect(m_renderControl, &QQuickRenderControl::renderRequested, this, requestUpdate); - connect(m_renderControl, &QQuickRenderControl::sceneChanged, this, requestUpdate); + connect(m_renderControl.data(), &QQuickRenderControl::renderRequested, this, requestUpdate); + connect(m_renderControl.data(), &QQuickRenderControl::sceneChanged, this, requestUpdate); m_item->setParentItem(m_view->contentItem()); diff --git a/plugins/kdecorations/aurorae/src/aurorae.h b/plugins/kdecorations/aurorae/src/aurorae.h index 3b280990e6..80e477ba04 100644 --- a/plugins/kdecorations/aurorae/src/aurorae.h +++ b/plugins/kdecorations/aurorae/src/aurorae.h @@ -87,7 +87,11 @@ private: KWin::Borders *m_extendedBorders; KWin::Borders *m_padding; QString m_themeName; - QQuickRenderControl *m_renderControl = nullptr; + + //workaround QtBug-68997 + //deleting of a RenderControl/controlled window triggers deletion of other queued deleted items + //deleting this queued means we know we're not processing anything else at the same time and should minimise the damage + QScopedPointer m_renderControl; QScopedPointer m_updateTimer; QScopedPointer m_context; QScopedPointer m_offscreenSurface;