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.
This commit is contained in:
Vlad Zahorodnii 2021-12-20 16:15:25 +02:00
parent 13b85d77fc
commit 84690a0de6
3 changed files with 24 additions and 16 deletions

View file

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

View file

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

View file

@ -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();