From 84690a0de659cf638155e6219823879cd9302da5 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Mon, 20 Dec 2021 16:15:25 +0200 Subject: [PATCH] scenes/opengl: Move copying front buffer to back buffer to X11 specific code On X11, if buffer age is unsupported, kwin can do some quirks like copying parts of the front buffer to back buffer to avoid repainting the whole screen. Currently, the copying is performed in the opengl scene, which is not perfect because it makes the scene responsible not only for painting the scene but also some low level platform specific shenanigans. This change moves the copying step to the glx and egl backends. It simplifies the opengl scene, makes it less overloaded and more open to changes, but it also duplicates code, which is not ideal. However, given the de-facto deprecated state of the X11 platform, it's sort of acceptable as the main focus is now on wayland session and the things that are needed to make it fly as expected. --- src/backends/x11/standalone/eglbackend.cpp | 14 +++++++++++++- src/backends/x11/standalone/glxbackend.cpp | 12 +++++++++++- src/scenes/opengl/scene_opengl.cpp | 14 -------------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/backends/x11/standalone/eglbackend.cpp b/src/backends/x11/standalone/eglbackend.cpp index d508a24cb7..161f64d7f0 100644 --- a/src/backends/x11/standalone/eglbackend.cpp +++ b/src/backends/x11/standalone/eglbackend.cpp @@ -6,6 +6,7 @@ */ #include "eglbackend.h" +#include "kwinglplatform.h" #include "logging.h" #include "options.h" #include "overlaywindow.h" @@ -114,7 +115,18 @@ void EglBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, // eglSwapBuffers() or eglSwapBuffersWithDamageEXT() completes. m_vsyncMonitor->arm(); - presentSurface(surface(), renderedRegion, screens()->geometry()); + QRegion effectiveRenderedRegion = renderedRegion; + if (!GLPlatform::instance()->isGLES()) { + const QRegion displayRegion(screens()->geometry()); + if (!supportsBufferAge() && options->glPreferBufferSwap() == Options::CopyFrontBuffer && renderedRegion != displayRegion) { + glReadBuffer(GL_FRONT); + copyPixels(displayRegion - renderedRegion); + glReadBuffer(GL_BACK); + effectiveRenderedRegion = displayRegion; + } + } + + presentSurface(surface(), effectiveRenderedRegion, screens()->geometry()); if (overlayWindow() && overlayWindow()->window()) { // show the window only after the first pass, overlayWindow()->show(); // since that pass may take long diff --git a/src/backends/x11/standalone/glxbackend.cpp b/src/backends/x11/standalone/glxbackend.cpp index 68fd1bd580..71e92229c3 100644 --- a/src/backends/x11/standalone/glxbackend.cpp +++ b/src/backends/x11/standalone/glxbackend.cpp @@ -767,7 +767,17 @@ void GlxBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, m_vsyncMonitor->arm(); } - present(renderedRegion); + const QRegion displayRegion(screens()->geometry()); + + QRegion effectiveRenderedRegion = renderedRegion; + if (!supportsBufferAge() && options->glPreferBufferSwap() == Options::CopyFrontBuffer && renderedRegion != displayRegion) { + glReadBuffer(GL_FRONT); + copyPixels(displayRegion - renderedRegion); + glReadBuffer(GL_BACK); + effectiveRenderedRegion = displayRegion; + } + + present(effectiveRenderedRegion); if (overlayWindow()->window()) // show the window only after the first pass, overlayWindow()->show(); // since that pass may take long diff --git a/src/scenes/opengl/scene_opengl.cpp b/src/scenes/opengl/scene_opengl.cpp index 6c57d93a64..764778b352 100644 --- a/src/scenes/opengl/scene_opengl.cpp +++ b/src/scenes/opengl/scene_opengl.cpp @@ -318,20 +318,6 @@ void SceneOpenGL::paint(AbstractOutput *output, const QRegion &damage, const QLi renderLoop, projectionMatrix()); // call generic implementation paintCursor(output, valid); - if (!GLPlatform::instance()->isGLES() && !output) { - const QRegion displayRegion(geometry()); - - // copy dirty parts from front to backbuffer - if (!m_backend->supportsBufferAge() && - options->glPreferBufferSwap() == Options::CopyFrontBuffer && - valid != displayRegion) { - glReadBuffer(GL_FRONT); - m_backend->copyPixels(displayRegion - valid); - glReadBuffer(GL_BACK); - valid = displayRegion; - } - } - renderLoop->endFrame(); GLVertexBuffer::streamingBuffer()->endOfFrame();