diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2e7c802578..7e9b5e0c8e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -423,7 +423,6 @@ set(kwin_KDEINIT_SRCS
toplevel.cpp
unmanaged.cpp
scene.cpp
- scene_opengl.cpp
screenlockerwatcher.cpp
thumbnailitem.cpp
lanczosfilter.cpp
@@ -453,7 +452,6 @@ set(kwin_KDEINIT_SRCS
decorations/settings.cpp
decorations/decorationrenderer.cpp
decorations/decorations_logging.cpp
- abstract_egl_backend.cpp
platform.cpp
shell_client.cpp
wayland_server.cpp
diff --git a/composite.cpp b/composite.cpp
index ca984004ac..7ffb1fdf03 100644
--- a/composite.cpp
+++ b/composite.cpp
@@ -29,7 +29,6 @@ along with this program. If not, see .
#include "effects.h"
#include "overlaywindow.h"
#include "scene.h"
-#include "scene_opengl.h"
#include "screens.h"
#include "shadow.h"
#include "useractions.h"
@@ -39,6 +38,8 @@ along with this program. If not, see .
#include "wayland_server.h"
#include "decorations/decoratedclient.h"
+#include
+
#include
#include
@@ -220,47 +221,6 @@ void Compositor::slotCompositingOptionsInitialized()
}
}
- if (!m_scene) {
- switch(options->compositingMode()) {
- case OpenGLCompositing: {
- qCDebug(KWIN_CORE) << "Initializing OpenGL compositing";
-
- // Some broken drivers crash on glXQuery() so to prevent constant KWin crashes:
- if (kwinApp()->platform()->openGLCompositingIsBroken())
- qCWarning(KWIN_CORE) << "KWin has detected that your OpenGL library is unsafe to use";
- else {
- kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PreInit);
-
- m_scene = SceneOpenGL::createScene(this);
-
- kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PostInit);
-
- if (m_scene && !m_scene->initFailed()) {
- connect(static_cast(m_scene), &SceneOpenGL::resetCompositing, this, &Compositor::restart);
- break; // -->
- }
- delete m_scene;
- m_scene = NULL;
- }
-
- // Do not Fall back to XRender - it causes problems when selfcheck fails during startup, but works later on
- break;
- }
- default:
- qCDebug(KWIN_CORE) << "No compositing enabled";
- m_starting = false;
- if (cm_selection) {
- cm_selection->owning = false;
- cm_selection->release();
- }
- if (kwinApp()->platform()->requiresCompositing()) {
- qCCritical(KWIN_CORE) << "The used windowing system requires compositing";
- qCCritical(KWIN_CORE) << "We are going to quit KWin now as it is broken";
- qApp->quit();
- }
- return;
- }
- }
if (m_scene == NULL || m_scene->initFailed()) {
qCCritical(KWIN_CORE) << "Failed to initialize compositing, compositing disabled";
delete m_scene;
@@ -277,6 +237,7 @@ void Compositor::slotCompositingOptionsInitialized()
}
return;
}
+ connect(m_scene, &Scene::resetCompositing, this, &Compositor::restart);
emit sceneCreated();
if (Workspace::self()) {
diff --git a/data/org_kde_kwin.categories b/data/org_kde_kwin.categories
index e73674fc17..a256fa2c5a 100644
--- a/data/org_kde_kwin.categories
+++ b/data/org_kde_kwin.categories
@@ -18,3 +18,4 @@ kwin_xkbcommon KWin xkbcommon integration
kwin_qpa_plugin KWin QtPlatformAbstraction plugin
kwin_scene_xrender KWin XRender based compositor scene plugin
kwin_scene_qpainter KWin QPainter based compositor scene plugin
+kwin_scene_opengl KWin OpenGL based compositor scene plugins
diff --git a/lanczosfilter.h b/lanczosfilter.h
index fff5cf28eb..90dff420c2 100644
--- a/lanczosfilter.h
+++ b/lanczosfilter.h
@@ -29,6 +29,7 @@ along with this program. If not, see .
#include
#include
+#include
namespace KWin
{
@@ -40,7 +41,7 @@ class GLTexture;
class GLRenderTarget;
class GLShader;
-class LanczosFilter
+class KWIN_EXPORT LanczosFilter
: public QObject
{
Q_OBJECT
diff --git a/libkwineffects/kwingltexture_p.h b/libkwineffects/kwingltexture_p.h
index 440d2ce942..cec4c6c1f7 100644
--- a/libkwineffects/kwingltexture_p.h
+++ b/libkwineffects/kwingltexture_p.h
@@ -29,6 +29,8 @@ along with this program. If not, see .
#include
#include
#include
+#include
+#include
namespace KWin
{
diff --git a/platformsupport/scenes/CMakeLists.txt b/platformsupport/scenes/CMakeLists.txt
index 2e1df35485..6e560cbcda 100644
--- a/platformsupport/scenes/CMakeLists.txt
+++ b/platformsupport/scenes/CMakeLists.txt
@@ -1 +1,2 @@
add_subdirectory(qpainter)
+add_subdirectory(opengl)
diff --git a/platformsupport/scenes/opengl/CMakeLists.txt b/platformsupport/scenes/opengl/CMakeLists.txt
new file mode 100644
index 0000000000..26123568df
--- /dev/null
+++ b/platformsupport/scenes/opengl/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(SCENE_OPENGL_BACKEND_SRCS
+ abstract_egl_backend.cpp
+ backend.cpp
+ swap_profiler.cpp
+ texture.cpp
+)
+
+include_directories(${CMAKE_SOURCE_DIR})
+
+include(ECMQtDeclareLoggingCategory)
+ecm_qt_declare_logging_category(SCENE_OPENGL_BACKEND_SRCS
+ HEADER
+ logging.h
+ IDENTIFIER
+ KWIN_OPENGL
+ CATEGORY_NAME
+ kwin_scene_opengl
+ DEFAULT_SEVERITY
+ Critical
+)
+
+add_library(SceneOpenGLBackend STATIC ${SCENE_OPENGL_BACKEND_SRCS})
+target_link_libraries(SceneOpenGLBackend Qt5::Core Qt5::Widgets KF5::CoreAddons KF5::ConfigCore KF5::WindowSystem)
diff --git a/abstract_egl_backend.cpp b/platformsupport/scenes/opengl/abstract_egl_backend.cpp
similarity index 94%
rename from abstract_egl_backend.cpp
rename to platformsupport/scenes/opengl/abstract_egl_backend.cpp
index 209d372614..91729b4804 100644
--- a/abstract_egl_backend.cpp
+++ b/platformsupport/scenes/opengl/abstract_egl_backend.cpp
@@ -18,16 +18,20 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*********************************************************************/
#include "abstract_egl_backend.h"
+#include "texture.h"
#include "composite.h"
#include "egl_context_attribute_builder.h"
#include "options.h"
#include "platform.h"
+#include "scene.h"
#include "wayland_server.h"
#include
#include
#include
// kwin libs
+#include
#include
+#include
// Qt
#include
#include
@@ -93,25 +97,25 @@ bool AbstractEglBackend::initEglAPI()
{
EGLint major, minor;
if (eglInitialize(m_display, &major, &minor) == EGL_FALSE) {
- qCWarning(KWIN_CORE) << "eglInitialize failed";
+ qCWarning(KWIN_OPENGL) << "eglInitialize failed";
EGLint error = eglGetError();
if (error != EGL_SUCCESS) {
- qCWarning(KWIN_CORE) << "Error during eglInitialize " << error;
+ qCWarning(KWIN_OPENGL) << "Error during eglInitialize " << error;
}
return false;
}
EGLint error = eglGetError();
if (error != EGL_SUCCESS) {
- qCWarning(KWIN_CORE) << "Error during eglInitialize " << error;
+ qCWarning(KWIN_OPENGL) << "Error during eglInitialize " << error;
return false;
}
- qCDebug(KWIN_CORE) << "Egl Initialize succeeded";
+ qCDebug(KWIN_OPENGL) << "Egl Initialize succeeded";
if (eglBindAPI(isOpenGLES() ? EGL_OPENGL_ES_API : EGL_OPENGL_API) == EGL_FALSE) {
- qCCritical(KWIN_CORE) << "bind OpenGL API failed";
+ qCCritical(KWIN_OPENGL) << "bind OpenGL API failed";
return false;
}
- qCDebug(KWIN_CORE) << "EGL version: " << major << "." << minor;
+ qCDebug(KWIN_OPENGL) << "EGL version: " << major << "." << minor;
const QByteArray eglExtensions = eglQueryString(m_display, EGL_EXTENSIONS);
setExtensions(eglExtensions.split(' '));
return true;
@@ -250,13 +254,13 @@ bool AbstractEglBackend::createContext()
const auto attribs = (*it)->build();
ctx = eglCreateContext(m_display, config(), EGL_NO_CONTEXT, attribs.data());
if (ctx != EGL_NO_CONTEXT) {
- qCDebug(KWIN_CORE) << "Created EGL context with attributes:" << (*it).get();
+ qCDebug(KWIN_OPENGL) << "Created EGL context with attributes:" << (*it).get();
break;
}
}
if (ctx == EGL_NO_CONTEXT) {
- qCCritical(KWIN_CORE) << "Create Context failed";
+ qCCritical(KWIN_OPENGL) << "Create Context failed";
return false;
}
m_context = ctx;
@@ -281,8 +285,8 @@ void AbstractEglBackend::setSurface(const EGLSurface &surface)
kwinApp()->platform()->setSceneEglSurface(surface);
}
-AbstractEglTexture::AbstractEglTexture(SceneOpenGL::Texture *texture, AbstractEglBackend *backend)
- : SceneOpenGL::TexturePrivate()
+AbstractEglTexture::AbstractEglTexture(SceneOpenGLTexture *texture, AbstractEglBackend *backend)
+ : SceneOpenGLTexturePrivate()
, q(texture)
, m_backend(backend)
, m_image(EGL_NO_IMAGE_KHR)
@@ -453,7 +457,7 @@ bool AbstractEglTexture::loadEglTexture(const QPointer< KWayland::Server::Buffer
q->unbind();
if (EGL_NO_IMAGE_KHR == m_image) {
- qCDebug(KWIN_CORE) << "failed to create egl image";
+ qCDebug(KWIN_OPENGL) << "failed to create egl image";
q->discard();
return false;
}
@@ -466,7 +470,7 @@ EGLImageKHR AbstractEglTexture::attach(const QPointer< KWayland::Server::BufferI
EGLint format, yInverted;
eglQueryWaylandBufferWL(m_backend->eglDisplay(), buffer->resource(), EGL_TEXTURE_FORMAT, &format);
if (format != EGL_TEXTURE_RGB && format != EGL_TEXTURE_RGBA) {
- qCDebug(KWIN_CORE) << "Unsupported texture format: " << format;
+ qCDebug(KWIN_OPENGL) << "Unsupported texture format: " << format;
return EGL_NO_IMAGE_KHR;
}
if (!eglQueryWaylandBufferWL(m_backend->eglDisplay(), buffer->resource(), EGL_WAYLAND_Y_INVERTED_WL, &yInverted)) {
diff --git a/abstract_egl_backend.h b/platformsupport/scenes/opengl/abstract_egl_backend.h
similarity index 89%
rename from abstract_egl_backend.h
rename to platformsupport/scenes/opengl/abstract_egl_backend.h
index 35b4f3bb90..50d1a8282b 100644
--- a/abstract_egl_backend.h
+++ b/platformsupport/scenes/opengl/abstract_egl_backend.h
@@ -19,13 +19,23 @@ along with this program. If not, see .
*********************************************************************/
#ifndef KWIN_ABSTRACT_EGL_BACKEND_H
#define KWIN_ABSTRACT_EGL_BACKEND_H
-#include "scene_opengl.h"
+#include "backend.h"
+#include "texture.h"
+#include
#include
#include
class QOpenGLFramebufferObject;
+namespace KWayland
+{
+namespace Server
+{
+class BufferInterface;
+}
+}
+
namespace KWin
{
@@ -77,7 +87,7 @@ private:
QList m_clientExtensions;
};
-class KWIN_EXPORT AbstractEglTexture : public SceneOpenGL::TexturePrivate
+class KWIN_EXPORT AbstractEglTexture : public SceneOpenGLTexturePrivate
{
public:
virtual ~AbstractEglTexture();
@@ -86,14 +96,14 @@ public:
OpenGLBackend *backend() override;
protected:
- AbstractEglTexture(SceneOpenGL::Texture *texture, AbstractEglBackend *backend);
+ AbstractEglTexture(SceneOpenGLTexture *texture, AbstractEglBackend *backend);
EGLImageKHR image() const {
return m_image;
}
void setImage(const EGLImageKHR &img) {
m_image = img;
}
- SceneOpenGL::Texture *texture() const {
+ SceneOpenGLTexture *texture() const {
return q;
}
@@ -102,7 +112,7 @@ private:
bool loadEglTexture(const QPointer &buffer);
EGLImageKHR attach(const QPointer &buffer);
bool updateFromFBO(const QSharedPointer &fbo);
- SceneOpenGL::Texture *q;
+ SceneOpenGLTexture *q;
AbstractEglBackend *m_backend;
EGLImageKHR m_image;
};
diff --git a/platformsupport/scenes/opengl/backend.cpp b/platformsupport/scenes/opengl/backend.cpp
new file mode 100644
index 0000000000..cb0a23d532
--- /dev/null
+++ b/platformsupport/scenes/opengl/backend.cpp
@@ -0,0 +1,119 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2006 Lubos Lunak
+Copyright (C) 2009, 2010, 2011 Martin Gräßlin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#include "backend.h"
+#include
+#include
+
+#include "screens.h"
+
+#include
+
+namespace KWin
+{
+
+OpenGLBackend::OpenGLBackend()
+ : m_syncsToVBlank(false)
+ , m_blocksForRetrace(false)
+ , m_directRendering(false)
+ , m_haveBufferAge(false)
+ , m_failed(false)
+{
+}
+
+OpenGLBackend::~OpenGLBackend()
+{
+}
+
+void OpenGLBackend::setFailed(const QString &reason)
+{
+ qCWarning(KWIN_OPENGL) << "Creating the OpenGL rendering failed: " << reason;
+ m_failed = true;
+}
+
+void OpenGLBackend::idle()
+{
+ if (hasPendingFlush()) {
+ effects->makeOpenGLContextCurrent();
+ present();
+ }
+}
+
+void OpenGLBackend::addToDamageHistory(const QRegion ®ion)
+{
+ if (m_damageHistory.count() > 10)
+ m_damageHistory.removeLast();
+
+ m_damageHistory.prepend(region);
+}
+
+QRegion OpenGLBackend::accumulatedDamageHistory(int bufferAge) const
+{
+ QRegion region;
+
+ // Note: An age of zero means the buffer contents are undefined
+ if (bufferAge > 0 && bufferAge <= m_damageHistory.count()) {
+ for (int i = 0; i < bufferAge - 1; i++)
+ region |= m_damageHistory[i];
+ } else {
+ const QSize &s = screens()->size();
+ region = QRegion(0, 0, s.width(), s.height());
+ }
+
+ return region;
+}
+
+OverlayWindow* OpenGLBackend::overlayWindow()
+{
+ return NULL;
+}
+
+QRegion OpenGLBackend::prepareRenderingForScreen(int screenId)
+{
+ // fallback to repaint complete screen
+ return screens()->geometry(screenId);
+}
+
+void OpenGLBackend::endRenderingFrameForScreen(int screenId, const QRegion &damage, const QRegion &damagedRegion)
+{
+ Q_UNUSED(screenId)
+ Q_UNUSED(damage)
+ Q_UNUSED(damagedRegion)
+}
+
+bool OpenGLBackend::perScreenRendering() const
+{
+ return false;
+}
+
+void OpenGLBackend::copyPixels(const QRegion ®ion)
+{
+ const int height = screens()->size().height();
+ foreach (const QRect &r, region.rects()) {
+ const int x0 = r.x();
+ const int y0 = height - r.y() - r.height();
+ const int x1 = r.x() + r.width();
+ const int y1 = height - r.y();
+
+ glBlitFramebuffer(x0, y0, x1, y1, x0, y0, x1, y1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ }
+}
+
+}
diff --git a/platformsupport/scenes/opengl/backend.h b/platformsupport/scenes/opengl/backend.h
new file mode 100644
index 0000000000..483c71186b
--- /dev/null
+++ b/platformsupport/scenes/opengl/backend.h
@@ -0,0 +1,325 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2006 Lubos Lunak
+Copyright (C) 2009, 2010, 2011 Martin Gräßlin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#ifndef KWIN_SCENE_OPENGL_BACKEND_H
+#define KWIN_SCENE_OPENGL_BACKEND_H
+
+#include
+#include
+
+#include
+
+namespace KWin
+{
+class OpenGLBackend;
+class OverlayWindow;
+class SceneOpenGL;
+class SceneOpenGLTexture;
+class SceneOpenGLTexturePrivate;
+class WindowPixmap;
+
+/**
+ * @brief The OpenGLBackend creates and holds the OpenGL context and is responsible for Texture from Pixmap.
+ *
+ * The OpenGLBackend is an abstract base class used by the SceneOpenGL to abstract away the differences
+ * between various OpenGL windowing systems such as GLX and EGL.
+ *
+ * A concrete implementation has to create and release the OpenGL context in a way so that the
+ * SceneOpenGL does not have to care about it.
+ *
+ * In addition a major task for this class is to generate the SceneOpenGLTexturePrivate which is
+ * able to perform the texture from pixmap operation in the given backend.
+ *
+ * @author Martin Gräßlin
+ **/
+class KWIN_EXPORT OpenGLBackend
+{
+public:
+ OpenGLBackend();
+ virtual ~OpenGLBackend();
+
+ virtual void init() = 0;
+ /**
+ * @return Time passes since start of rendering current frame.
+ * @see startRenderTimer
+ **/
+ qint64 renderTime() {
+ return m_renderTimer.nsecsElapsed();
+ }
+ virtual void screenGeometryChanged(const QSize &size) = 0;
+ virtual SceneOpenGLTexturePrivate *createBackendTexture(SceneOpenGLTexture *texture) = 0;
+
+ /**
+ * @brief Backend specific code to prepare the rendering of a frame including flushing the
+ * previously rendered frame to the screen if the backend works this way.
+ *
+ * @return A region that if not empty will be repainted in addition to the damaged region
+ **/
+ virtual QRegion prepareRenderingFrame() = 0;
+
+ /**
+ * @brief Backend specific code to handle the end of rendering a frame.
+ *
+ * @param renderedRegion The possibly larger region that has been rendered
+ * @param damagedRegion The damaged region that should be posted
+ **/
+ virtual void endRenderingFrame(const QRegion &damage, const QRegion &damagedRegion) = 0;
+ virtual void endRenderingFrameForScreen(int screenId, const QRegion &damage, const QRegion &damagedRegion);
+ virtual bool makeCurrent() = 0;
+ virtual void doneCurrent() = 0;
+ virtual bool usesOverlayWindow() const = 0;
+ /**
+ * Whether the rendering needs to be split per screen.
+ * Default implementation returns @c false.
+ **/
+ virtual bool perScreenRendering() const;
+ virtual QRegion prepareRenderingForScreen(int screenId);
+ /**
+ * @brief Compositor is going into idle mode, flushes any pending paints.
+ **/
+ void idle();
+
+ /**
+ * @return bool Whether the scene needs to flush a frame.
+ **/
+ bool hasPendingFlush() const {
+ return !m_lastDamage.isEmpty();
+ }
+
+ /**
+ * @brief Returns the OverlayWindow used by the backend.
+ *
+ * A backend does not have to use an OverlayWindow, this is mostly for the X world.
+ * In case the backend does not use an OverlayWindow it is allowed to return @c null.
+ * It's the task of the caller to check whether it is @c null.
+ *
+ * @return :OverlayWindow*
+ **/
+ virtual OverlayWindow *overlayWindow();
+ /**
+ * @brief Whether the creation of the Backend failed.
+ *
+ * The SceneOpenGL should test whether the Backend got constructed correctly. If this method
+ * returns @c true, the SceneOpenGL should not try to start the rendering.
+ *
+ * @return bool @c true if the creation of the Backend failed, @c false otherwise.
+ **/
+ bool isFailed() const {
+ return m_failed;
+ }
+ /**
+ * @brief Whether the Backend provides VSync.
+ *
+ * Currently only the GLX backend can provide VSync.
+ *
+ * @return bool @c true if VSync support is available, @c false otherwise
+ **/
+ bool syncsToVBlank() const {
+ return m_syncsToVBlank;
+ }
+ /**
+ * @brief Whether VSync blocks execution until the screen is in the retrace
+ *
+ * Case for waitVideoSync and non triple buffering buffer swaps
+ *
+ **/
+ bool blocksForRetrace() const {
+ return m_blocksForRetrace;
+ }
+ /**
+ * @brief Whether the backend uses direct rendering.
+ *
+ * Some OpenGLScene modes require direct rendering. E.g. the OpenGL 2 should not be used
+ * if direct rendering is not supported by the Scene.
+ *
+ * @return bool @c true if the GL context is direct, @c false if indirect
+ **/
+ bool isDirectRendering() const {
+ return m_directRendering;
+ }
+
+ bool supportsBufferAge() const {
+ return m_haveBufferAge;
+ }
+
+ /**
+ * @returns whether the context is surfaceless
+ **/
+ bool isSurfaceLessContext() const {
+ return m_surfaceLessContext;
+ }
+
+ /**
+ * Returns the damage that has accumulated since a buffer of the given age was presented.
+ */
+ QRegion accumulatedDamageHistory(int bufferAge) const;
+
+ /**
+ * Saves the given region to damage history.
+ */
+ void addToDamageHistory(const QRegion ®ion);
+
+ /**
+ * The backend specific extensions (e.g. EGL/GLX extensions).
+ *
+ * Not the OpenGL (ES) extension!
+ **/
+ QList extensions() const {
+ return m_extensions;
+ }
+
+ /**
+ * @returns whether the backend specific extensions contains @p extension.
+ **/
+ bool hasExtension(const QByteArray &extension) const {
+ return m_extensions.contains(extension);
+ }
+
+ /**
+ * Copy a region of pixels from the current read to the current draw buffer
+ */
+ void copyPixels(const QRegion ®ion);
+
+protected:
+ /**
+ * @brief Backend specific flushing of frame to screen.
+ **/
+ virtual void present() = 0;
+ /**
+ * @brief Sets the backend initialization to failed.
+ *
+ * This method should be called by the concrete subclass in case the initialization failed.
+ * The given @p reason is logged as a warning.
+ *
+ * @param reason The reason why the initialization failed.
+ **/
+ void setFailed(const QString &reason);
+ /**
+ * @brief Sets whether the backend provides VSync.
+ *
+ * Should be called by the concrete subclass once it is determined whether VSync is supported.
+ * If the subclass does not call this method, the backend defaults to @c false.
+ * @param enabled @c true if VSync support available, @c false otherwise.
+ **/
+ void setSyncsToVBlank(bool enabled) {
+ m_syncsToVBlank = enabled;
+ }
+ /**
+ * @brief Sets whether the VSync iplementation blocks
+ *
+ * Should be called by the concrete subclass once it is determined how VSync works.
+ * If the subclass does not call this method, the backend defaults to @c false.
+ * @param enabled @c true if VSync blocks, @c false otherwise.
+ **/
+ void setBlocksForRetrace(bool enabled) {
+ m_blocksForRetrace = enabled;
+ }
+ /**
+ * @brief Sets whether the OpenGL context is direct.
+ *
+ * Should be called by the concrete subclass once it is determined whether the OpenGL context is
+ * direct or indirect.
+ * If the subclass does not call this method, the backend defaults to @c false.
+ *
+ * @param direct @c true if the OpenGL context is direct, @c false if indirect
+ **/
+ void setIsDirectRendering(bool direct) {
+ m_directRendering = direct;
+ }
+
+ void setSupportsBufferAge(bool value) {
+ m_haveBufferAge = value;
+ }
+
+ /**
+ * @return const QRegion& Damage of previously rendered frame
+ **/
+ const QRegion &lastDamage() const {
+ return m_lastDamage;
+ }
+ void setLastDamage(const QRegion &damage) {
+ m_lastDamage = damage;
+ }
+ /**
+ * @brief Starts the timer for how long it takes to render the frame.
+ *
+ * @see renderTime
+ **/
+ void startRenderTimer() {
+ m_renderTimer.start();
+ }
+
+ /**
+ * @param set whether the context is surface less
+ **/
+ void setSurfaceLessContext(bool set) {
+ m_surfaceLessContext = set;
+ }
+
+ /**
+ * Sets the platform-specific @p extensions.
+ *
+ * These are the EGL/GLX extensions, not the OpenGL extensions
+ **/
+ void setExtensions(const QList &extensions) {
+ m_extensions = extensions;
+ }
+
+private:
+ /**
+ * @brief Whether VSync is available and used, defaults to @c false.
+ **/
+ bool m_syncsToVBlank;
+ /**
+ * @brief Whether present() will block execution until the next vertical retrace @c false.
+ **/
+ bool m_blocksForRetrace;
+ /**
+ * @brief Whether direct rendering is used, defaults to @c false.
+ **/
+ bool m_directRendering;
+ /**
+ * @brief Whether the backend supports GLX_EXT_buffer_age / EGL_EXT_buffer_age.
+ */
+ bool m_haveBufferAge;
+ /**
+ * @brief Whether the initialization failed, of course default to @c false.
+ **/
+ bool m_failed;
+ /**
+ * @brief Damaged region of previously rendered frame.
+ **/
+ QRegion m_lastDamage;
+ /**
+ * @brief The damage history for the past 10 frames.
+ */
+ QList m_damageHistory;
+ /**
+ * @brief Timer to measure how long a frame renders.
+ **/
+ QElapsedTimer m_renderTimer;
+ bool m_surfaceLessContext = false;
+
+ QList m_extensions;
+};
+
+}
+
+#endif
diff --git a/platformsupport/scenes/opengl/swap_profiler.cpp b/platformsupport/scenes/opengl/swap_profiler.cpp
new file mode 100644
index 0000000000..619a2ae656
--- /dev/null
+++ b/platformsupport/scenes/opengl/swap_profiler.cpp
@@ -0,0 +1,57 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2006 Lubos Lunak
+Copyright (C) 2009, 2010, 2011 Martin Gräßlin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#include "swap_profiler.h"
+#include
+
+namespace KWin
+{
+
+SwapProfiler::SwapProfiler()
+{
+ init();
+}
+
+void SwapProfiler::init()
+{
+ m_time = 2 * 1000*1000; // we start with a long time mean of 2ms ...
+ m_counter = 0;
+}
+
+void SwapProfiler::begin()
+{
+ m_timer.start();
+}
+
+char SwapProfiler::end()
+{
+ // .. and blend in actual values.
+ // this way we prevent extremes from killing our long time mean
+ m_time = (10*m_time + m_timer.nsecsElapsed())/11;
+ if (++m_counter > 500) {
+ const bool blocks = m_time > 1000 * 1000; // 1ms, i get ~250µs and ~7ms w/o triple buffering...
+ qCDebug(KWIN_OPENGL) << "Triple buffering detection:" << QString(blocks ? QStringLiteral("NOT available") : QStringLiteral("Available")) <<
+ " - Mean block time:" << m_time/(1000.0*1000.0) << "ms";
+ return blocks ? 'd' : 't';
+ }
+ return 0;
+}
+
+}
diff --git a/platformsupport/scenes/opengl/swap_profiler.h b/platformsupport/scenes/opengl/swap_profiler.h
new file mode 100644
index 0000000000..8415b0a8d1
--- /dev/null
+++ b/platformsupport/scenes/opengl/swap_profiler.h
@@ -0,0 +1,53 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2006 Lubos Lunak
+Copyright (C) 2009, 2010, 2011 Martin Gräßlin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#ifndef KWIN_SCENE_OPENGL_SWAP_PROFILER_H
+#define KWIN_SCENE_OPENGL_SWAP_PROFILER_H
+
+#include
+#include
+
+namespace KWin
+{
+
+/**
+ * @short Profiler to detect whether we have triple buffering
+ * The strategy is to start setBlocksForRetrace(false) but assume blocking and have the system prove that assumption wrong
+ **/
+class KWIN_EXPORT SwapProfiler
+{
+public:
+ SwapProfiler();
+ void init();
+ void begin();
+ /**
+ * @return char being 'd' for double, 't' for triple (or more - but non-blocking) buffering and
+ * 0 (NOT '0') otherwise, so you can act on "if (char result = SwapProfiler::end()) { fooBar(); }
+ **/
+ char end();
+private:
+ QElapsedTimer m_timer;
+ qint64 m_time;
+ int m_counter;
+};
+
+}
+
+#endif
diff --git a/platformsupport/scenes/opengl/texture.cpp b/platformsupport/scenes/opengl/texture.cpp
new file mode 100644
index 0000000000..936272002e
--- /dev/null
+++ b/platformsupport/scenes/opengl/texture.cpp
@@ -0,0 +1,80 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2006 Lubos Lunak
+Copyright (C) 2009, 2010, 2011 Martin Gräßlin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#include "texture.h"
+#include "backend.h"
+#include "scene.h"
+
+namespace KWin
+{
+
+SceneOpenGLTexture::SceneOpenGLTexture(OpenGLBackend *backend)
+ : GLTexture(*backend->createBackendTexture(this))
+{
+}
+
+SceneOpenGLTexture::~SceneOpenGLTexture()
+{
+}
+
+SceneOpenGLTexture& SceneOpenGLTexture::operator = (const SceneOpenGLTexture& tex)
+{
+ d_ptr = tex.d_ptr;
+ return *this;
+}
+
+void SceneOpenGLTexture::discard()
+{
+ d_ptr = d_func()->backend()->createBackendTexture(this);
+}
+
+bool SceneOpenGLTexture::load(WindowPixmap *pixmap)
+{
+ if (!pixmap->isValid()) {
+ return false;
+ }
+
+ // decrease the reference counter for the old texture
+ d_ptr = d_func()->backend()->createBackendTexture(this); //new TexturePrivate();
+
+ Q_D(SceneOpenGLTexture);
+ return d->loadTexture(pixmap);
+}
+
+void SceneOpenGLTexture::updateFromPixmap(WindowPixmap *pixmap)
+{
+ Q_D(SceneOpenGLTexture);
+ d->updateTexture(pixmap);
+}
+
+SceneOpenGLTexturePrivate::SceneOpenGLTexturePrivate()
+{
+}
+
+SceneOpenGLTexturePrivate::~SceneOpenGLTexturePrivate()
+{
+}
+
+void SceneOpenGLTexturePrivate::updateTexture(WindowPixmap *pixmap)
+{
+ Q_UNUSED(pixmap)
+}
+
+}
diff --git a/platformsupport/scenes/opengl/texture.h b/platformsupport/scenes/opengl/texture.h
new file mode 100644
index 0000000000..d574b0cb55
--- /dev/null
+++ b/platformsupport/scenes/opengl/texture.h
@@ -0,0 +1,76 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2006 Lubos Lunak
+Copyright (C) 2009, 2010, 2011 Martin Gräßlin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#ifndef KWIN_SCENE_OPENGL_TEXTURE_H
+#define KWIN_SCENE_OPENGL_TEXTURE_H
+
+#include
+#include
+
+namespace KWin
+{
+
+class OpenGLBackend;
+class WindowPixmap;
+class SceneOpenGLTexturePrivate;
+
+class SceneOpenGLTexture
+ : public GLTexture
+{
+public:
+ SceneOpenGLTexture(OpenGLBackend *backend);
+ virtual ~SceneOpenGLTexture();
+
+ SceneOpenGLTexture & operator = (const SceneOpenGLTexture& tex);
+
+ void discard() override final;
+
+protected:
+ bool load(WindowPixmap *pixmap);
+ void updateFromPixmap(WindowPixmap *pixmap);
+
+ SceneOpenGLTexture(SceneOpenGLTexturePrivate& dd);
+
+private:
+ Q_DECLARE_PRIVATE(SceneOpenGLTexture)
+
+ friend class OpenGLWindowPixmap;
+};
+
+class SceneOpenGLTexturePrivate
+ : public GLTexturePrivate
+{
+public:
+ virtual ~SceneOpenGLTexturePrivate();
+
+ virtual bool loadTexture(WindowPixmap *pixmap) = 0;
+ virtual void updateTexture(WindowPixmap *pixmap);
+ virtual OpenGLBackend *backend() = 0;
+
+protected:
+ SceneOpenGLTexturePrivate();
+
+private:
+ Q_DISABLE_COPY(SceneOpenGLTexturePrivate)
+};
+
+}
+
+#endif
diff --git a/plugins/platforms/drm/CMakeLists.txt b/plugins/platforms/drm/CMakeLists.txt
index 8db5207a7d..f3b7e7c3fe 100644
--- a/plugins/platforms/drm/CMakeLists.txt
+++ b/plugins/platforms/drm/CMakeLists.txt
@@ -16,8 +16,10 @@ if(HAVE_GBM)
set(DRM_SOURCES ${DRM_SOURCES} egl_gbm_backend.cpp drm_buffer_gbm.cpp)
endif()
+include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/opengl)
+
add_library(KWinWaylandDrmBackend MODULE ${DRM_SOURCES})
-target_link_libraries(KWinWaylandDrmBackend kwin Libdrm::Libdrm SceneQPainterBackend)
+target_link_libraries(KWinWaylandDrmBackend kwin Libdrm::Libdrm SceneQPainterBackend SceneOpenGLBackend)
if(HAVE_GBM)
target_link_libraries(KWinWaylandDrmBackend gbm::gbm)
diff --git a/plugins/platforms/drm/egl_gbm_backend.cpp b/plugins/platforms/drm/egl_gbm_backend.cpp
index 646e775666..685bf065df 100644
--- a/plugins/platforms/drm/egl_gbm_backend.cpp
+++ b/plugins/platforms/drm/egl_gbm_backend.cpp
@@ -253,7 +253,7 @@ void EglGbmBackend::screenGeometryChanged(const QSize &size)
// TODO, create new buffer?
}
-SceneOpenGL::TexturePrivate *EglGbmBackend::createBackendTexture(SceneOpenGL::Texture *texture)
+SceneOpenGLTexturePrivate *EglGbmBackend::createBackendTexture(SceneOpenGLTexture *texture)
{
return new EglGbmTexture(texture, this);
}
@@ -343,7 +343,7 @@ bool EglGbmBackend::perScreenRendering() const
* EglTexture
************************************************/
-EglGbmTexture::EglGbmTexture(KWin::SceneOpenGL::Texture *texture, EglGbmBackend *backend)
+EglGbmTexture::EglGbmTexture(KWin::SceneOpenGLTexture *texture, EglGbmBackend *backend)
: AbstractEglTexture(texture, backend)
{
}
diff --git a/plugins/platforms/drm/egl_gbm_backend.h b/plugins/platforms/drm/egl_gbm_backend.h
index 30e17e6824..490ee14f04 100644
--- a/plugins/platforms/drm/egl_gbm_backend.h
+++ b/plugins/platforms/drm/egl_gbm_backend.h
@@ -20,7 +20,6 @@ along with this program. If not, see .
#ifndef KWIN_EGL_GBM_BACKEND_H
#define KWIN_EGL_GBM_BACKEND_H
#include "abstract_egl_backend.h"
-#include "scene_opengl.h"
struct gbm_surface;
@@ -40,7 +39,7 @@ public:
EglGbmBackend(DrmBackend *b);
virtual ~EglGbmBackend();
void screenGeometryChanged(const QSize &size) override;
- SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture) override;
+ SceneOpenGLTexturePrivate *createBackendTexture(SceneOpenGLTexture *texture) override;
QRegion prepareRenderingFrame() override;
void endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
void endRenderingFrameForScreen(int screenId, const QRegion &damage, const QRegion &damagedRegion) override;
@@ -87,7 +86,7 @@ public:
private:
friend class EglGbmBackend;
- EglGbmTexture(SceneOpenGL::Texture *texture, EglGbmBackend *backend);
+ EglGbmTexture(SceneOpenGLTexture *texture, EglGbmBackend *backend);
};
} // namespace
diff --git a/plugins/platforms/hwcomposer/CMakeLists.txt b/plugins/platforms/hwcomposer/CMakeLists.txt
index 9b24055878..85d7c04bad 100644
--- a/plugins/platforms/hwcomposer/CMakeLists.txt
+++ b/plugins/platforms/hwcomposer/CMakeLists.txt
@@ -5,12 +5,14 @@ set(HWCOMPOSER_SOURCES
screens_hwcomposer.cpp
)
+include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/opengl)
add_library(KWinWaylandHwcomposerBackend MODULE ${HWCOMPOSER_SOURCES})
target_link_libraries(KWinWaylandHwcomposerBackend
kwin
libhybris::libhardware
libhybris::hwcomposer
libhybris::hybriseglplatform
+ SceneOpenGLBackend
)
install(
diff --git a/plugins/platforms/hwcomposer/egl_hwcomposer_backend.cpp b/plugins/platforms/hwcomposer/egl_hwcomposer_backend.cpp
index 7b649bf8ee..3c96db1185 100644
--- a/plugins/platforms/hwcomposer/egl_hwcomposer_backend.cpp
+++ b/plugins/platforms/hwcomposer/egl_hwcomposer_backend.cpp
@@ -164,7 +164,7 @@ void EglHwcomposerBackend::endRenderingFrame(const QRegion &renderedRegion, cons
setLastDamage(renderedRegion);
}
-SceneOpenGL::TexturePrivate *EglHwcomposerBackend::createBackendTexture(SceneOpenGL::Texture *texture)
+SceneOpenGLTexturePrivate *EglHwcomposerBackend::createBackendTexture(SceneOpenGLTexture *texture)
{
return new EglHwcomposerTexture(texture, this);
}
@@ -174,7 +174,7 @@ bool EglHwcomposerBackend::usesOverlayWindow() const
return false;
}
-EglHwcomposerTexture::EglHwcomposerTexture(SceneOpenGL::Texture *texture, EglHwcomposerBackend *backend)
+EglHwcomposerTexture::EglHwcomposerTexture(SceneOpenGLTexture *texture, EglHwcomposerBackend *backend)
: AbstractEglTexture(texture, backend)
{
}
diff --git a/plugins/platforms/hwcomposer/egl_hwcomposer_backend.h b/plugins/platforms/hwcomposer/egl_hwcomposer_backend.h
index 1fbbaabfa1..3270104d6d 100644
--- a/plugins/platforms/hwcomposer/egl_hwcomposer_backend.h
+++ b/plugins/platforms/hwcomposer/egl_hwcomposer_backend.h
@@ -33,7 +33,7 @@ public:
EglHwcomposerBackend(HwcomposerBackend *backend);
virtual ~EglHwcomposerBackend();
bool usesOverlayWindow() const override;
- SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture) override;
+ SceneOpenGLTexturePrivate *createBackendTexture(SceneOpenGLTexture *texture) override;
void screenGeometryChanged(const QSize &size) override;
QRegion prepareRenderingFrame() override;
void endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
@@ -58,7 +58,7 @@ public:
private:
friend class EglHwcomposerBackend;
- EglHwcomposerTexture(SceneOpenGL::Texture *texture, EglHwcomposerBackend *backend);
+ EglHwcomposerTexture(SceneOpenGLTexture *texture, EglHwcomposerBackend *backend);
};
}
diff --git a/plugins/platforms/virtual/CMakeLists.txt b/plugins/platforms/virtual/CMakeLists.txt
index 24923620bc..6654633766 100644
--- a/plugins/platforms/virtual/CMakeLists.txt
+++ b/plugins/platforms/virtual/CMakeLists.txt
@@ -5,6 +5,7 @@ set(VIRTUAL_SOURCES
screens_virtual.cpp
)
+include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/opengl)
include(ECMQtDeclareLoggingCategory)
ecm_qt_declare_logging_category(VIRTUAL_SOURCES HEADER logging.h IDENTIFIER KWIN_VIRTUAL CATEGORY_NAME kwin_platform_virtual DEFAULT_SEVERITY Critical)
@@ -12,7 +13,7 @@ add_library(KWinWaylandVirtualBackend MODULE ${VIRTUAL_SOURCES})
target_link_libraries(KWinWaylandVirtualBackend kwin SceneQPainterBackend)
if(HAVE_GBM)
- target_link_libraries(KWinWaylandVirtualBackend gbm::gbm)
+ target_link_libraries(KWinWaylandVirtualBackend SceneOpenGLBackend gbm::gbm)
endif()
install(
diff --git a/plugins/platforms/virtual/egl_gbm_backend.cpp b/plugins/platforms/virtual/egl_gbm_backend.cpp
index 87a064db83..b4698a23f2 100644
--- a/plugins/platforms/virtual/egl_gbm_backend.cpp
+++ b/plugins/platforms/virtual/egl_gbm_backend.cpp
@@ -29,6 +29,7 @@ along with this program. If not, see .
#include
// kwin libs
#include
+#include
// Qt
#include
// system
@@ -214,7 +215,7 @@ void EglGbmBackend::screenGeometryChanged(const QSize &size)
// TODO, create new buffer?
}
-SceneOpenGL::TexturePrivate *EglGbmBackend::createBackendTexture(SceneOpenGL::Texture *texture)
+SceneOpenGLTexturePrivate *EglGbmBackend::createBackendTexture(SceneOpenGLTexture *texture)
{
return new EglGbmTexture(texture, this);
}
@@ -282,7 +283,7 @@ bool EglGbmBackend::usesOverlayWindow() const
* EglTexture
************************************************/
-EglGbmTexture::EglGbmTexture(KWin::SceneOpenGL::Texture *texture, EglGbmBackend *backend)
+EglGbmTexture::EglGbmTexture(KWin::SceneOpenGLTexture *texture, EglGbmBackend *backend)
: AbstractEglTexture(texture, backend)
{
}
diff --git a/plugins/platforms/virtual/egl_gbm_backend.h b/plugins/platforms/virtual/egl_gbm_backend.h
index b4560ed259..3940e9e246 100644
--- a/plugins/platforms/virtual/egl_gbm_backend.h
+++ b/plugins/platforms/virtual/egl_gbm_backend.h
@@ -20,7 +20,6 @@ along with this program. If not, see .
#ifndef KWIN_EGL_GBM_BACKEND_H
#define KWIN_EGL_GBM_BACKEND_H
#include "abstract_egl_backend.h"
-#include "scene_opengl.h"
namespace KWin
{
@@ -37,7 +36,7 @@ public:
EglGbmBackend(VirtualBackend *b);
virtual ~EglGbmBackend();
void screenGeometryChanged(const QSize &size) override;
- SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture) override;
+ SceneOpenGLTexturePrivate *createBackendTexture(SceneOpenGLTexture *texture) override;
QRegion prepareRenderingFrame() override;
void endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
bool usesOverlayWindow() const override;
@@ -68,7 +67,7 @@ public:
private:
friend class EglGbmBackend;
- EglGbmTexture(SceneOpenGL::Texture *texture, EglGbmBackend *backend);
+ EglGbmTexture(SceneOpenGLTexture *texture, EglGbmBackend *backend);
};
} // namespace
diff --git a/plugins/platforms/virtual/virtual_backend.cpp b/plugins/platforms/virtual/virtual_backend.cpp
index c8b20d6d56..1f2c384ae4 100644
--- a/plugins/platforms/virtual/virtual_backend.cpp
+++ b/plugins/platforms/virtual/virtual_backend.cpp
@@ -29,6 +29,7 @@ along with this program. If not, see .
// system
#include
#include
+#include
#if HAVE_GBM
#include
#endif
diff --git a/plugins/platforms/wayland/CMakeLists.txt b/plugins/platforms/wayland/CMakeLists.txt
index bdef9cff2a..1fc8e36398 100644
--- a/plugins/platforms/wayland/CMakeLists.txt
+++ b/plugins/platforms/wayland/CMakeLists.txt
@@ -8,11 +8,12 @@ if(HAVE_WAYLAND_EGL)
set(WAYLAND_BACKEND_SOURCES egl_wayland_backend.cpp ${WAYLAND_BACKEND_SOURCES})
endif()
+include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/opengl)
add_library(KWinWaylandWaylandBackend MODULE ${WAYLAND_BACKEND_SOURCES})
target_link_libraries(KWinWaylandWaylandBackend kwin KF5::WaylandClient SceneQPainterBackend)
if(HAVE_WAYLAND_EGL)
- target_link_libraries(KWinWaylandWaylandBackend Wayland::Egl)
+ target_link_libraries(KWinWaylandWaylandBackend SceneOpenGLBackend Wayland::Egl)
endif()
install(
diff --git a/plugins/platforms/wayland/egl_wayland_backend.cpp b/plugins/platforms/wayland/egl_wayland_backend.cpp
index 3107780f3e..16f64888b0 100644
--- a/plugins/platforms/wayland/egl_wayland_backend.cpp
+++ b/plugins/platforms/wayland/egl_wayland_backend.cpp
@@ -213,7 +213,7 @@ void EglWaylandBackend::screenGeometryChanged(const QSize &size)
m_bufferAge = 0;
}
-SceneOpenGL::TexturePrivate *EglWaylandBackend::createBackendTexture(SceneOpenGL::Texture *texture)
+SceneOpenGLTexturePrivate *EglWaylandBackend::createBackendTexture(SceneOpenGLTexture *texture)
{
return new EglWaylandTexture(texture, this);
}
@@ -280,7 +280,7 @@ bool EglWaylandBackend::usesOverlayWindow() const
* EglTexture
************************************************/
-EglWaylandTexture::EglWaylandTexture(KWin::SceneOpenGL::Texture *texture, KWin::EglWaylandBackend *backend)
+EglWaylandTexture::EglWaylandTexture(KWin::SceneOpenGLTexture *texture, KWin::EglWaylandBackend *backend)
: AbstractEglTexture(texture, backend)
{
}
diff --git a/plugins/platforms/wayland/egl_wayland_backend.h b/plugins/platforms/wayland/egl_wayland_backend.h
index 0b2893d86f..e42da7df34 100644
--- a/plugins/platforms/wayland/egl_wayland_backend.h
+++ b/plugins/platforms/wayland/egl_wayland_backend.h
@@ -20,7 +20,6 @@ along with this program. If not, see .
#ifndef KWIN_EGL_WAYLAND_BACKEND_H
#define KWIN_EGL_WAYLAND_BACKEND_H
#include "abstract_egl_backend.h"
-#include "scene_opengl.h"
// wayland
#include
@@ -54,7 +53,7 @@ public:
EglWaylandBackend(Wayland::WaylandBackend *b);
virtual ~EglWaylandBackend();
virtual void screenGeometryChanged(const QSize &size);
- virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture);
+ virtual SceneOpenGLTexturePrivate *createBackendTexture(SceneOpenGLTexture *texture) override;
virtual QRegion prepareRenderingFrame();
virtual void endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion);
virtual bool usesOverlayWindow() const override;
@@ -88,7 +87,7 @@ public:
private:
friend class EglWaylandBackend;
- EglWaylandTexture(SceneOpenGL::Texture *texture, EglWaylandBackend *backend);
+ EglWaylandTexture(SceneOpenGLTexture *texture, EglWaylandBackend *backend);
};
} // namespace
diff --git a/plugins/platforms/x11/common/CMakeLists.txt b/plugins/platforms/x11/common/CMakeLists.txt
index 5a1ab6d0ae..677f9f6c9f 100644
--- a/plugins/platforms/x11/common/CMakeLists.txt
+++ b/plugins/platforms/x11/common/CMakeLists.txt
@@ -4,5 +4,6 @@ endif()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-int-to-void-pointer-cast")
endif()
+include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/opengl)
add_library(eglx11common STATIC eglonxbackend.cpp)
target_link_libraries(eglx11common kwin)
diff --git a/plugins/platforms/x11/common/eglonxbackend.cpp b/plugins/platforms/x11/common/eglonxbackend.cpp
index 6eaf518a37..1990fc49bb 100644
--- a/plugins/platforms/x11/common/eglonxbackend.cpp
+++ b/plugins/platforms/x11/common/eglonxbackend.cpp
@@ -23,11 +23,15 @@ along with this program. If not, see .
#include "options.h"
#include "overlaywindow.h"
#include "platform.h"
+#include "scene.h"
#include "screens.h"
#include "xcbutils.h"
+#include "texture.h"
// kwin libs
#include
+#include
// Qt
+#include
#include
#include
// system
@@ -386,7 +390,7 @@ void EglOnXBackend::screenGeometryChanged(const QSize &size)
m_bufferAge = 0;
}
-SceneOpenGL::TexturePrivate *EglOnXBackend::createBackendTexture(SceneOpenGL::Texture *texture)
+SceneOpenGLTexturePrivate *EglOnXBackend::createBackendTexture(SceneOpenGLTexture *texture)
{
return new EglTexture(texture, this);
}
@@ -473,7 +477,7 @@ bool EglOnXBackend::makeContextCurrent(const EGLSurface &surface)
* EglTexture
************************************************/
-EglTexture::EglTexture(KWin::SceneOpenGL::Texture *texture, KWin::EglOnXBackend *backend)
+EglTexture::EglTexture(KWin::SceneOpenGLTexture *texture, KWin::EglOnXBackend *backend)
: AbstractEglTexture(texture, backend)
, m_backend(backend)
{
diff --git a/plugins/platforms/x11/common/eglonxbackend.h b/plugins/platforms/x11/common/eglonxbackend.h
index 941f660d60..0063971bf8 100644
--- a/plugins/platforms/x11/common/eglonxbackend.h
+++ b/plugins/platforms/x11/common/eglonxbackend.h
@@ -20,7 +20,9 @@ along with this program. If not, see .
#ifndef KWIN_EGL_ON_X_BACKEND_H
#define KWIN_EGL_ON_X_BACKEND_H
#include "abstract_egl_backend.h"
-#include "scene_opengl.h"
+#include "swap_profiler.h"
+
+#include
namespace KWin
{
@@ -35,7 +37,7 @@ public:
explicit EglOnXBackend(xcb_connection_t *connection, Display *display, xcb_window_t rootWindow, int screenNumber, xcb_window_t renderingWindow);
virtual ~EglOnXBackend();
virtual void screenGeometryChanged(const QSize &size);
- virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture);
+ virtual SceneOpenGLTexturePrivate *createBackendTexture(SceneOpenGLTexture *texture) override;
virtual QRegion prepareRenderingFrame();
virtual void endRenderingFrame(const QRegion &damage, const QRegion &damagedRegion);
virtual OverlayWindow* overlayWindow() override;
@@ -80,6 +82,7 @@ private:
xcb_window_t m_renderingWindow = XCB_WINDOW_NONE;
bool m_havePlatformBase = false;
bool m_x11TextureFromPixmapSupported = true;
+ SwapProfiler m_swapProfiler;
friend class EglTexture;
};
@@ -96,7 +99,7 @@ public:
private:
bool loadTexture(xcb_pixmap_t pix, const QSize &size);
friend class EglOnXBackend;
- EglTexture(SceneOpenGL::Texture *texture, EglOnXBackend *backend);
+ EglTexture(SceneOpenGLTexture *texture, EglOnXBackend *backend);
EglOnXBackend *m_backend;
};
diff --git a/plugins/platforms/x11/standalone/CMakeLists.txt b/plugins/platforms/x11/standalone/CMakeLists.txt
index 260987019e..66e878cfc1 100644
--- a/plugins/platforms/x11/standalone/CMakeLists.txt
+++ b/plugins/platforms/x11/standalone/CMakeLists.txt
@@ -20,8 +20,10 @@ if(HAVE_EPOXY_GLX)
set(X11PLATFORM_SOURCES ${X11PLATFORM_SOURCES} glxbackend.cpp glx_context_attribute_builder.cpp)
endif()
+include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/opengl)
+
add_library(KWinX11Platform MODULE ${X11PLATFORM_SOURCES})
-target_link_libraries(KWinX11Platform eglx11common kwin kwinxrenderutils Qt5::X11Extras XCB::CURSOR)
+target_link_libraries(KWinX11Platform eglx11common kwin kwinxrenderutils SceneOpenGLBackend Qt5::X11Extras XCB::CURSOR)
if(X11_Xinput_FOUND)
target_link_libraries(KWinX11Platform ${X11_Xinput_LIB})
endif()
diff --git a/plugins/platforms/x11/standalone/glxbackend.cpp b/plugins/platforms/x11/standalone/glxbackend.cpp
index f61bb68013..ff22ec7192 100644
--- a/plugins/platforms/x11/standalone/glxbackend.cpp
+++ b/plugins/platforms/x11/standalone/glxbackend.cpp
@@ -31,10 +31,13 @@ along with this program. If not, see .
#include "overlaywindow.h"
#include "composite.h"
#include "platform.h"
+#include "scene.h"
#include "screens.h"
#include "xcbutils.h"
+#include "texture.h"
// kwin libs
#include
+#include
#include
// Qt
#include
@@ -48,6 +51,7 @@ along with this program. If not, see .
#if HAVE_DL_LIBRARY
#include
#endif
+#include
#ifndef XCB_GLX_BUFFER_SWAP_COMPLETE
#define XCB_GLX_BUFFER_SWAP_COMPLETE 1
@@ -722,7 +726,7 @@ void GlxBackend::present()
}
} else { // Copy Pixels (horribly slow on Mesa)
glDrawBuffer(GL_FRONT);
- SceneOpenGL::copyPixels(lastDamage());
+ copyPixels(lastDamage());
glDrawBuffer(GL_BACK);
}
@@ -748,7 +752,7 @@ void GlxBackend::screenGeometryChanged(const QSize &size)
m_bufferAge = 0;
}
-SceneOpenGL::TexturePrivate *GlxBackend::createBackendTexture(SceneOpenGL::Texture *texture)
+SceneOpenGLTexturePrivate *GlxBackend::createBackendTexture(SceneOpenGLTexture *texture)
{
return new GlxTexture(texture, this);
}
@@ -844,8 +848,8 @@ bool GlxBackend::usesOverlayWindow() const
/********************************************************
* GlxTexture
*******************************************************/
-GlxTexture::GlxTexture(SceneOpenGL::Texture *texture, GlxBackend *backend)
- : SceneOpenGL::TexturePrivate()
+GlxTexture::GlxTexture(SceneOpenGLTexture *texture, GlxBackend *backend)
+ : SceneOpenGLTexturePrivate()
, q(texture)
, m_backend(backend)
, m_glxpixmap(None)
diff --git a/plugins/platforms/x11/standalone/glxbackend.h b/plugins/platforms/x11/standalone/glxbackend.h
index 59787419e0..ff3a0d8f2f 100644
--- a/plugins/platforms/x11/standalone/glxbackend.h
+++ b/plugins/platforms/x11/standalone/glxbackend.h
@@ -19,11 +19,14 @@ along with this program. If not, see .
*********************************************************************/
#ifndef KWIN_GLX_BACKEND_H
#define KWIN_GLX_BACKEND_H
-#include "scene_opengl.h"
+#include "backend.h"
+#include "texture.h"
+#include "swap_profiler.h"
#include "x11eventfilter.h"
#include
#include
+#include
#include
namespace KWin
@@ -68,7 +71,7 @@ public:
GlxBackend(Display *display);
virtual ~GlxBackend();
virtual void screenGeometryChanged(const QSize &size);
- virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture);
+ virtual SceneOpenGLTexturePrivate *createBackendTexture(SceneOpenGLTexture *texture) override;
virtual QRegion prepareRenderingFrame();
virtual void endRenderingFrame(const QRegion &damage, const QRegion &damagedRegion);
virtual bool makeCurrent() override;
@@ -116,13 +119,14 @@ private:
bool haveSwapInterval = false;
bool haveWaitSync = false;
Display *m_x11Display;
+ SwapProfiler m_swapProfiler;
friend class GlxTexture;
};
/**
* @brief Texture using an GLXPixmap.
**/
-class GlxTexture : public SceneOpenGL::TexturePrivate
+class GlxTexture : public SceneOpenGLTexturePrivate
{
public:
virtual ~GlxTexture();
@@ -132,12 +136,12 @@ public:
private:
friend class GlxBackend;
- GlxTexture(SceneOpenGL::Texture *texture, GlxBackend *backend);
+ GlxTexture(SceneOpenGLTexture *texture, GlxBackend *backend);
bool loadTexture(xcb_pixmap_t pix, const QSize &size, xcb_visualid_t visual);
Display *display() const {
return m_backend->m_x11Display;
}
- SceneOpenGL::Texture *q;
+ SceneOpenGLTexture *q;
GlxBackend *m_backend;
GLXPixmap m_glxpixmap; // the glx pixmap the texture is bound to
};
diff --git a/plugins/platforms/x11/windowed/CMakeLists.txt b/plugins/platforms/x11/windowed/CMakeLists.txt
index 1c445c5b5f..8236c6b480 100644
--- a/plugins/platforms/x11/windowed/CMakeLists.txt
+++ b/plugins/platforms/x11/windowed/CMakeLists.txt
@@ -5,8 +5,9 @@ set(X11BACKEND_SOURCES
x11windowed_backend.cpp
)
+include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/opengl)
add_library(KWinWaylandX11Backend MODULE ${X11BACKEND_SOURCES})
-target_link_libraries(KWinWaylandX11Backend eglx11common kwin kwinxrenderutils X11::XCB SceneQPainterBackend)
+target_link_libraries(KWinWaylandX11Backend eglx11common kwin kwinxrenderutils X11::XCB SceneQPainterBackend SceneOpenGLBackend)
install(
TARGETS
diff --git a/plugins/platforms/x11/windowed/x11windowed_backend.cpp b/plugins/platforms/x11/windowed/x11windowed_backend.cpp
index 302bac7f4c..95306b027c 100644
--- a/plugins/platforms/x11/windowed/x11windowed_backend.cpp
+++ b/plugins/platforms/x11/windowed/x11windowed_backend.cpp
@@ -27,8 +27,10 @@ along with this program. If not, see .
#include
// KDE
#include
+#include
#include
#include
+#include
#include
// kwayland
#include
diff --git a/plugins/scenes/CMakeLists.txt b/plugins/scenes/CMakeLists.txt
index 8ef7930be4..eb84a43ce8 100644
--- a/plugins/scenes/CMakeLists.txt
+++ b/plugins/scenes/CMakeLists.txt
@@ -1,3 +1,4 @@
+add_subdirectory(opengl)
add_subdirectory(qpainter)
if( KWIN_BUILD_XRENDER_COMPOSITING )
add_subdirectory(xrender)
diff --git a/plugins/scenes/opengl/CMakeLists.txt b/plugins/scenes/opengl/CMakeLists.txt
new file mode 100644
index 0000000000..47684dfe07
--- /dev/null
+++ b/plugins/scenes/opengl/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(SCENE_OPENGL_SRCS scene_opengl.cpp)
+
+include(ECMQtDeclareLoggingCategory)
+ecm_qt_declare_logging_category(
+ SCENE_OPENGL_SRCS HEADER
+ logging.h
+ IDENTIFIER
+ KWIN_OPENGL
+ CATEGORY_NAME
+ kwin_scene_opengl
+ DEFAULT_SEVERITY
+ Critical
+)
+
+add_library(KWinSceneOpenGL MODULE scene_opengl.cpp)
+target_link_libraries(KWinSceneOpenGL
+ kwin
+ SceneOpenGLBackend
+)
+
+install(
+ TARGETS
+ KWinSceneOpenGL
+ DESTINATION
+ ${PLUGIN_INSTALL_DIR}/org.kde.kwin.scenes/
+)
diff --git a/plugins/scenes/opengl/opengl.json b/plugins/scenes/opengl/opengl.json
new file mode 100644
index 0000000000..e31a6d8e0a
--- /dev/null
+++ b/plugins/scenes/opengl/opengl.json
@@ -0,0 +1,9 @@
+{
+ "CompositingType": 1,
+ "KPlugin": {
+ "Description": "KWin Compositor plugin rendering through OpenGL",
+ "Id": "KWinSceneOpenGL",
+ "Name": "SceneOpenGL"
+ }
+}
+
diff --git a/scene_opengl.cpp b/plugins/scenes/opengl/scene_opengl.cpp
similarity index 92%
rename from scene_opengl.cpp
rename to plugins/scenes/opengl/scene_opengl.cpp
index 66a39274f2..59a385de84 100644
--- a/scene_opengl.cpp
+++ b/plugins/scenes/opengl/scene_opengl.cpp
@@ -30,6 +30,7 @@ along with this program. If not, see .
#include "platform.h"
#include "wayland_server.h"
+#include "platformsupport/scenes/opengl/texture.h"
#include
@@ -44,6 +45,7 @@ along with this program. If not, see .
#include "screens.h"
#include "cursor.h"
#include "decorations/decoratedclient.h"
+#include
#include
#include
@@ -180,18 +182,18 @@ bool SyncObject::finish()
glGetSynciv(m_sync, GL_SYNC_STATUS, 1, nullptr, &value);
if (value != GL_SIGNALED) {
- qCDebug(KWIN_CORE) << "Waiting for X fence to finish";
+ qCDebug(KWIN_OPENGL) << "Waiting for X fence to finish";
// Wait for the fence to become signaled with a one second timeout
const GLenum result = glClientWaitSync(m_sync, 0, 1000000000);
switch (result) {
case GL_TIMEOUT_EXPIRED:
- qCWarning(KWIN_CORE) << "Timeout while waiting for X fence";
+ qCWarning(KWIN_OPENGL) << "Timeout while waiting for X fence";
return false;
case GL_WAIT_FAILED:
- qCWarning(KWIN_CORE) << "glClientWaitSync() failed";
+ qCWarning(KWIN_OPENGL) << "glClientWaitSync() failed";
return false;
}
}
@@ -302,85 +304,6 @@ bool SyncManager::updateFences()
// -----------------------------------------------------------------------
-
-
-//****************************************
-// SceneOpenGL
-//****************************************
-OpenGLBackend::OpenGLBackend()
- : m_syncsToVBlank(false)
- , m_blocksForRetrace(false)
- , m_directRendering(false)
- , m_haveBufferAge(false)
- , m_failed(false)
-{
-}
-
-OpenGLBackend::~OpenGLBackend()
-{
-}
-
-void OpenGLBackend::setFailed(const QString &reason)
-{
- qCWarning(KWIN_CORE) << "Creating the OpenGL rendering failed: " << reason;
- m_failed = true;
-}
-
-void OpenGLBackend::idle()
-{
- if (hasPendingFlush()) {
- effects->makeOpenGLContextCurrent();
- present();
- }
-}
-
-void OpenGLBackend::addToDamageHistory(const QRegion ®ion)
-{
- if (m_damageHistory.count() > 10)
- m_damageHistory.removeLast();
-
- m_damageHistory.prepend(region);
-}
-
-QRegion OpenGLBackend::accumulatedDamageHistory(int bufferAge) const
-{
- QRegion region;
-
- // Note: An age of zero means the buffer contents are undefined
- if (bufferAge > 0 && bufferAge <= m_damageHistory.count()) {
- for (int i = 0; i < bufferAge - 1; i++)
- region |= m_damageHistory[i];
- } else {
- const QSize &s = screens()->size();
- region = QRegion(0, 0, s.width(), s.height());
- }
-
- return region;
-}
-
-OverlayWindow* OpenGLBackend::overlayWindow()
-{
- return NULL;
-}
-
-QRegion OpenGLBackend::prepareRenderingForScreen(int screenId)
-{
- // fallback to repaint complete screen
- return screens()->geometry(screenId);
-}
-
-void OpenGLBackend::endRenderingFrameForScreen(int screenId, const QRegion &damage, const QRegion &damagedRegion)
-{
- Q_UNUSED(screenId)
- Q_UNUSED(damage)
- Q_UNUSED(damagedRegion)
-}
-
-bool OpenGLBackend::perScreenRendering() const
-{
- return false;
-}
-
/************************************************
* SceneOpenGL
***********************************************/
@@ -403,12 +326,12 @@ SceneOpenGL::SceneOpenGL(OpenGLBackend *backend, QObject *parent)
GLPlatform *glPlatform = GLPlatform::instance();
if (!glPlatform->isGLES() && !hasGLExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two"))
&& !hasGLExtension(QByteArrayLiteral("GL_ARB_texture_rectangle"))) {
- qCCritical(KWIN_CORE) << "GL_ARB_texture_non_power_of_two and GL_ARB_texture_rectangle missing";
+ qCCritical(KWIN_OPENGL) << "GL_ARB_texture_non_power_of_two and GL_ARB_texture_rectangle missing";
init_ok = false;
return; // error
}
if (glPlatform->isMesaDriver() && glPlatform->mesaVersion() < kVersionNumber(10, 0)) {
- qCCritical(KWIN_CORE) << "KWin requires at least Mesa 10.0 for OpenGL compositing.";
+ qCCritical(KWIN_OPENGL) << "KWin requires at least Mesa 10.0 for OpenGL compositing.";
init_ok = false;
return;
}
@@ -432,10 +355,10 @@ SceneOpenGL::SceneOpenGL(OpenGLBackend *backend, QObject *parent)
const QByteArray useExplicitSync = qgetenv("KWIN_EXPLICIT_SYNC");
if (useExplicitSync != "0") {
- qCDebug(KWIN_CORE) << "Initializing fences for synchronization with the X command stream";
+ qCDebug(KWIN_OPENGL) << "Initializing fences for synchronization with the X command stream";
m_syncManager = new SyncManager;
} else {
- qCDebug(KWIN_CORE) << "Explicit synchronization with the X command stream disabled by environment variable";
+ qCDebug(KWIN_OPENGL) << "Explicit synchronization with the X command stream disabled by environment variable";
}
}
}
@@ -514,7 +437,7 @@ void SceneOpenGL::initDebugOutput()
switch (type) {
case GL_DEBUG_TYPE_ERROR:
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
- qCWarning(KWIN_CORE, "%#x: %.*s", id, length, message);
+ qCWarning(KWIN_OPENGL, "%#x: %.*s", id, length, message);
break;
case GL_DEBUG_TYPE_OTHER:
@@ -532,7 +455,7 @@ void SceneOpenGL::initDebugOutput()
case GL_DEBUG_TYPE_PORTABILITY:
case GL_DEBUG_TYPE_PERFORMANCE:
default:
- qCDebug(KWIN_CORE, "%#x: %.*s", id, length, message);
+ qCDebug(KWIN_OPENGL, "%#x: %.*s", id, length, message);
break;
}
};
@@ -584,9 +507,9 @@ SceneOpenGL *SceneOpenGL::createScene(QObject *parent)
}
if (!scene) {
if (GLPlatform::instance()->recommendedCompositor() == XRenderCompositing) {
- qCCritical(KWIN_CORE) << "OpenGL driver recommends XRender based compositing. Falling back to XRender.";
- qCCritical(KWIN_CORE) << "To overwrite the detection use the environment variable KWIN_COMPOSE";
- qCCritical(KWIN_CORE) << "For more information see http://community.kde.org/KWin/Environment_Variables#KWIN_COMPOSE";
+ qCCritical(KWIN_OPENGL) << "OpenGL driver recommends XRender based compositing. Falling back to XRender.";
+ qCCritical(KWIN_OPENGL) << "To overwrite the detection use the environment variable KWIN_COMPOSE";
+ qCCritical(KWIN_OPENGL) << "For more information see http://community.kde.org/KWin/Environment_Variables#KWIN_COMPOSE";
QTimer::singleShot(0, Compositor::self(), SLOT(fallbackToXRenderCompositing()));
}
delete backend;
@@ -621,32 +544,19 @@ bool SceneOpenGL::initFailed() const
return !init_ok;
}
-void SceneOpenGL::copyPixels(const QRegion ®ion)
-{
- const int height = screens()->size().height();
- foreach (const QRect &r, region.rects()) {
- const int x0 = r.x();
- const int y0 = height - r.y() - r.height();
- const int x1 = r.x() + r.width();
- const int y1 = height - r.y();
-
- glBlitFramebuffer(x0, y0, x1, y1, x0, y0, x1, y1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- }
-}
-
void SceneOpenGL::handleGraphicsReset(GLenum status)
{
switch (status) {
case GL_GUILTY_CONTEXT_RESET:
- qCDebug(KWIN_CORE) << "A graphics reset attributable to the current GL context occurred.";
+ qCDebug(KWIN_OPENGL) << "A graphics reset attributable to the current GL context occurred.";
break;
case GL_INNOCENT_CONTEXT_RESET:
- qCDebug(KWIN_CORE) << "A graphics reset not attributable to the current GL context occurred.";
+ qCDebug(KWIN_OPENGL) << "A graphics reset not attributable to the current GL context occurred.";
break;
case GL_UNKNOWN_CONTEXT_RESET:
- qCDebug(KWIN_CORE) << "A graphics reset of an unknown cause occurred.";
+ qCDebug(KWIN_OPENGL) << "A graphics reset of an unknown cause occurred.";
break;
default:
@@ -660,7 +570,7 @@ void SceneOpenGL::handleGraphicsReset(GLenum status)
while (timer.elapsed() < 10000 && glGetGraphicsResetStatus() != GL_NO_ERROR)
usleep(50);
- qCDebug(KWIN_CORE) << "Attempting to reset compositing.";
+ qCDebug(KWIN_OPENGL) << "Attempting to reset compositing.";
QMetaObject::invokeMethod(this, "resetCompositing", Qt::QueuedConnection);
KNotification::event(QStringLiteral("graphicsreset"), i18n("Desktop effects were restarted due to a graphics reset"));
@@ -800,7 +710,7 @@ qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
options->glPreferBufferSwap() == Options::CopyFrontBuffer &&
validRegion != displayRegion) {
glReadBuffer(GL_FRONT);
- copyPixels(displayRegion - validRegion);
+ m_backend->copyPixels(displayRegion - validRegion);
glReadBuffer(GL_BACK);
validRegion = displayRegion;
}
@@ -815,8 +725,8 @@ qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
if (m_currentFence) {
if (!m_syncManager->updateFences()) {
- qCDebug(KWIN_CORE) << "Aborting explicit synchronization with the X command stream.";
- qCDebug(KWIN_CORE) << "Future frames will be rendered unsynchronized.";
+ qCDebug(KWIN_OPENGL) << "Aborting explicit synchronization with the X command stream.";
+ qCDebug(KWIN_OPENGL) << "Future frames will be rendered unsynchronized.";
delete m_syncManager;
m_syncManager = nullptr;
}
@@ -902,9 +812,9 @@ void SceneOpenGL::extendPaintRegion(QRegion ®ion, bool opaqueFullscreen)
}
}
-SceneOpenGL::Texture *SceneOpenGL::createTexture()
+SceneOpenGLTexture *SceneOpenGL::createTexture()
{
- return new Texture(m_backend);
+ return new SceneOpenGLTexture(m_backend);
}
bool SceneOpenGL::viewportLimitsMatched(const QSize &size) const {
@@ -1034,7 +944,7 @@ bool SceneOpenGL2::supported(OpenGLBackend *backend)
const QByteArray forceEnv = qgetenv("KWIN_COMPOSE");
if (!forceEnv.isEmpty()) {
if (qstrcmp(forceEnv, "O2") == 0 || qstrcmp(forceEnv, "O2ES") == 0) {
- qCDebug(KWIN_CORE) << "OpenGL 2 compositing enforced by environment variable";
+ qCDebug(KWIN_OPENGL) << "OpenGL 2 compositing enforced by environment variable";
return true;
} else {
// OpenGL 2 disabled by environment variable
@@ -1045,7 +955,7 @@ bool SceneOpenGL2::supported(OpenGLBackend *backend)
return false;
}
if (GLPlatform::instance()->recommendedCompositor() < OpenGL2Compositing) {
- qCDebug(KWIN_CORE) << "Driver does not recommend OpenGL 2 compositing";
+ qCDebug(KWIN_OPENGL) << "Driver does not recommend OpenGL 2 compositing";
return false;
}
return true;
@@ -1062,7 +972,7 @@ SceneOpenGL2::SceneOpenGL2(OpenGLBackend *backend, QObject *parent)
// We only support the OpenGL 2+ shader API, not GL_ARB_shader_objects
if (!hasGLVersion(2, 0)) {
- qCDebug(KWIN_CORE) << "OpenGL 2.0 is not supported";
+ qCDebug(KWIN_OPENGL) << "OpenGL 2.0 is not supported";
init_ok = false;
return;
}
@@ -1074,7 +984,7 @@ SceneOpenGL2::SceneOpenGL2(OpenGLBackend *backend, QObject *parent)
// push one shader on the stack so that one is always bound
ShaderManager::instance()->pushShader(ShaderTrait::MapTexture);
if (checkGLError("Init")) {
- qCCritical(KWIN_CORE) << "OpenGL 2 compositing setup failed";
+ qCCritical(KWIN_OPENGL) << "OpenGL 2 compositing setup failed";
init_ok = false;
return; // error
}
@@ -1086,12 +996,12 @@ SceneOpenGL2::SceneOpenGL2(OpenGLBackend *backend, QObject *parent)
}
if (!ShaderManager::instance()->selfTest()) {
- qCCritical(KWIN_CORE) << "ShaderManager self test failed";
+ qCCritical(KWIN_OPENGL) << "ShaderManager self test failed";
init_ok = false;
return;
}
- qCDebug(KWIN_CORE) << "OpenGL 2 compositing successfully initialized";
+ qCDebug(KWIN_OPENGL) << "OpenGL 2 compositing successfully initialized";
init_ok = true;
}
@@ -1198,65 +1108,6 @@ void SceneOpenGL2::performPaintWindow(EffectWindowImpl* w, int mask, QRegion reg
w->sceneWindow()->performPaint(mask, region, data);
}
-//****************************************
-// SceneOpenGL::Texture
-//****************************************
-
-SceneOpenGL::Texture::Texture(OpenGLBackend *backend)
- : GLTexture(*backend->createBackendTexture(this))
-{
-}
-
-SceneOpenGL::Texture::~Texture()
-{
-}
-
-SceneOpenGL::Texture& SceneOpenGL::Texture::operator = (const SceneOpenGL::Texture& tex)
-{
- d_ptr = tex.d_ptr;
- return *this;
-}
-
-void SceneOpenGL::Texture::discard()
-{
- d_ptr = d_func()->backend()->createBackendTexture(this);
-}
-
-bool SceneOpenGL::Texture::load(WindowPixmap *pixmap)
-{
- if (!pixmap->isValid()) {
- return false;
- }
-
- // decrease the reference counter for the old texture
- d_ptr = d_func()->backend()->createBackendTexture(this); //new TexturePrivate();
-
- Q_D(Texture);
- return d->loadTexture(pixmap);
-}
-
-void SceneOpenGL::Texture::updateFromPixmap(WindowPixmap *pixmap)
-{
- Q_D(Texture);
- d->updateTexture(pixmap);
-}
-
-//****************************************
-// SceneOpenGL::Texture
-//****************************************
-SceneOpenGL::TexturePrivate::TexturePrivate()
-{
-}
-
-SceneOpenGL::TexturePrivate::~TexturePrivate()
-{
-}
-
-void SceneOpenGL::TexturePrivate::updateTexture(WindowPixmap *pixmap)
-{
- Q_UNUSED(pixmap)
-}
-
//****************************************
// SceneOpenGL::Window
//****************************************
@@ -1271,7 +1122,7 @@ SceneOpenGL::Window::~Window()
{
}
-static SceneOpenGL::Texture *s_frameTexture = NULL;
+static SceneOpenGLTexture *s_frameTexture = NULL;
// Bind the window pixmap to an OpenGL texture.
bool SceneOpenGL::Window::bindTexture()
{
@@ -1748,7 +1599,7 @@ bool OpenGLWindowPixmap::bind()
toplevel()->resetDamage();
}
} else
- qCDebug(KWIN_CORE) << "Failed to bind window";
+ qCDebug(KWIN_OPENGL) << "Failed to bind window";
return success;
}
@@ -2473,36 +2324,6 @@ bool SceneOpenGLShadow::prepareBackend()
return true;
}
-SwapProfiler::SwapProfiler()
-{
- init();
-}
-
-void SwapProfiler::init()
-{
- m_time = 2 * 1000*1000; // we start with a long time mean of 2ms ...
- m_counter = 0;
-}
-
-void SwapProfiler::begin()
-{
- m_timer.start();
-}
-
-char SwapProfiler::end()
-{
- // .. and blend in actual values.
- // this way we prevent extremes from killing our long time mean
- m_time = (10*m_time + m_timer.nsecsElapsed())/11;
- if (++m_counter > 500) {
- const bool blocks = m_time > 1000 * 1000; // 1ms, i get ~250µs and ~7ms w/o triple buffering...
- qCDebug(KWIN_CORE) << "Triple buffering detection:" << QString(blocks ? QStringLiteral("NOT available") : QStringLiteral("Available")) <<
- " - Mean block time:" << m_time/(1000.0*1000.0) << "ms";
- return blocks ? 'd' : 't';
- }
- return 0;
-}
-
SceneOpenGLDecorationRenderer::SceneOpenGLDecorationRenderer(Decoration::DecoratedClientImpl *client)
: Renderer(client)
, m_texture()
@@ -2610,4 +2431,31 @@ void SceneOpenGLDecorationRenderer::reparent(Deleted *deleted)
Renderer::reparent(deleted);
}
+
+OpenGLFactory::OpenGLFactory(QObject *parent)
+ : SceneFactory(parent)
+{
+}
+
+OpenGLFactory::~OpenGLFactory() = default;
+
+Scene *OpenGLFactory::create(QObject *parent) const
+{
+ qCDebug(KWIN_OPENGL) << "Initializing OpenGL compositing";
+
+ // Some broken drivers crash on glXQuery() so to prevent constant KWin crashes:
+ if (kwinApp()->platform()->openGLCompositingIsBroken()) {
+ qCWarning(KWIN_OPENGL) << "KWin has detected that your OpenGL library is unsafe to use";
+ return nullptr;
+ }
+ kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PreInit);
+ auto s = SceneOpenGL::createScene(parent);
+ kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PostInit);
+ if (s && s->initFailed()) {
+ delete s;
+ return nullptr;
+ }
+ return s;
+}
+
} // namespace
diff --git a/plugins/scenes/opengl/scene_opengl.h b/plugins/scenes/opengl/scene_opengl.h
new file mode 100644
index 0000000000..6643dc3537
--- /dev/null
+++ b/plugins/scenes/opengl/scene_opengl.h
@@ -0,0 +1,354 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2006 Lubos Lunak
+Copyright (C) 2009, 2010, 2011 Martin Gräßlin
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+
+#ifndef KWIN_SCENE_OPENGL_H
+#define KWIN_SCENE_OPENGL_H
+
+#include "scene.h"
+#include "shadow.h"
+
+#include "kwinglutils.h"
+
+#include "decorations/decorationrenderer.h"
+#include "platformsupport/scenes/opengl/backend.h"
+
+namespace KWin
+{
+class LanczosFilter;
+class OpenGLBackend;
+class SyncManager;
+class SyncObject;
+
+class KWIN_EXPORT SceneOpenGL
+ : public Scene
+{
+ Q_OBJECT
+public:
+ class EffectFrame;
+ class Window;
+ virtual ~SceneOpenGL();
+ virtual bool initFailed() const;
+ virtual bool hasPendingFlush() const;
+ virtual qint64 paint(QRegion damage, ToplevelList windows);
+ virtual Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame);
+ virtual Shadow *createShadow(Toplevel *toplevel);
+ virtual void screenGeometryChanged(const QSize &size);
+ virtual OverlayWindow *overlayWindow();
+ virtual bool usesOverlayWindow() const;
+ virtual bool blocksForRetrace() const;
+ virtual bool syncsToVBlank() const;
+ virtual bool makeOpenGLContextCurrent() override;
+ virtual void doneOpenGLContextCurrent() override;
+ Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
+ virtual void triggerFence() override;
+ virtual QMatrix4x4 projectionMatrix() const = 0;
+ bool animationsSupported() const override;
+
+ void insertWait();
+
+ void idle();
+
+ bool debug() const { return m_debug; }
+ void initDebugOutput();
+
+ /**
+ * @brief Factory method to create a backend specific texture.
+ *
+ * @return :SceneOpenGL::Texture*
+ **/
+ SceneOpenGLTexture *createTexture();
+
+ OpenGLBackend *backend() const {
+ return m_backend;
+ }
+
+ QVector openGLPlatformInterfaceExtensions() const override;
+
+ static SceneOpenGL *createScene(QObject *parent);
+
+protected:
+ SceneOpenGL(OpenGLBackend *backend, QObject *parent = nullptr);
+ virtual void paintBackground(QRegion region);
+ virtual void extendPaintRegion(QRegion ®ion, bool opaqueFullscreen);
+ QMatrix4x4 transformation(int mask, const ScreenPaintData &data) const;
+ virtual void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data);
+
+ void handleGraphicsReset(GLenum status);
+
+ virtual void doPaintBackground(const QVector &vertices) = 0;
+ virtual void updateProjectionMatrix() = 0;
+
+protected:
+ bool init_ok;
+private:
+ bool viewportLimitsMatched(const QSize &size) const;
+private:
+ bool m_debug;
+ OpenGLBackend *m_backend;
+ SyncManager *m_syncManager;
+ SyncObject *m_currentFence;
+};
+
+class SceneOpenGL2 : public SceneOpenGL
+{
+ Q_OBJECT
+public:
+ explicit SceneOpenGL2(OpenGLBackend *backend, QObject *parent = nullptr);
+ virtual ~SceneOpenGL2();
+ virtual CompositingType compositingType() const {
+ return OpenGL2Compositing;
+ }
+
+ static bool supported(OpenGLBackend *backend);
+
+ QMatrix4x4 projectionMatrix() const override { return m_projectionMatrix; }
+ QMatrix4x4 screenProjectionMatrix() const override { return m_screenProjectionMatrix; }
+
+protected:
+ virtual void paintSimpleScreen(int mask, QRegion region);
+ virtual void paintGenericScreen(int mask, ScreenPaintData data);
+ virtual void doPaintBackground(const QVector< float >& vertices);
+ virtual Scene::Window *createWindow(Toplevel *t);
+ virtual void finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data);
+ virtual void updateProjectionMatrix() override;
+ void paintCursor() override;
+
+private:
+ void performPaintWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data);
+ QMatrix4x4 createProjectionMatrix() const;
+
+private:
+ LanczosFilter *m_lanczosFilter;
+ QScopedPointer m_cursorTexture;
+ QMatrix4x4 m_projectionMatrix;
+ QMatrix4x4 m_screenProjectionMatrix;
+ GLuint vao;
+};
+
+class SceneOpenGL::Window
+ : public Scene::Window
+{
+public:
+ virtual ~Window();
+ bool beginRenderWindow(int mask, const QRegion ®ion, WindowPaintData &data);
+ virtual void performPaint(int mask, QRegion region, WindowPaintData data) = 0;
+ void endRenderWindow();
+ bool bindTexture();
+ void setScene(SceneOpenGL *scene) {
+ m_scene = scene;
+ }
+
+protected:
+ virtual WindowPixmap* createWindowPixmap();
+ Window(Toplevel* c);
+ enum TextureType {
+ Content,
+ Decoration,
+ Shadow
+ };
+
+ QMatrix4x4 transformation(int mask, const WindowPaintData &data) const;
+ GLTexture *getDecorationTexture() const;
+
+protected:
+ SceneOpenGL *m_scene;
+ bool m_hardwareClipping;
+};
+
+class SceneOpenGL2Window : public SceneOpenGL::Window
+{
+public:
+ enum Leaf { ShadowLeaf = 0, DecorationLeaf, ContentLeaf, PreviousContentLeaf, LeafCount };
+
+ struct LeafNode
+ {
+ LeafNode()
+ : texture(0),
+ firstVertex(0),
+ vertexCount(0),
+ opacity(1.0),
+ hasAlpha(false),
+ coordinateType(UnnormalizedCoordinates)
+ {
+ }
+
+ GLTexture *texture;
+ int firstVertex;
+ int vertexCount;
+ float opacity;
+ bool hasAlpha;
+ TextureCoordinateType coordinateType;
+ };
+
+ explicit SceneOpenGL2Window(Toplevel *c);
+ virtual ~SceneOpenGL2Window();
+
+protected:
+ QMatrix4x4 modelViewProjectionMatrix(int mask, const WindowPaintData &data) const;
+ QVector4D modulate(float opacity, float brightness) const;
+ void setBlendEnabled(bool enabled);
+ void setupLeafNodes(LeafNode *nodes, const WindowQuadList *quads, const WindowPaintData &data);
+ virtual void performPaint(int mask, QRegion region, WindowPaintData data);
+
+private:
+ /**
+ * Whether prepareStates enabled blending and restore states should disable again.
+ **/
+ bool m_blendingEnabled;
+};
+
+class OpenGLWindowPixmap : public WindowPixmap
+{
+public:
+ explicit OpenGLWindowPixmap(Scene::Window *window, SceneOpenGL *scene);
+ virtual ~OpenGLWindowPixmap();
+ SceneOpenGLTexture *texture() const;
+ bool bind();
+ bool isValid() const override;
+protected:
+ WindowPixmap *createChild(const QPointer &subSurface) override;
+private:
+ explicit OpenGLWindowPixmap(const QPointer &subSurface, WindowPixmap *parent, SceneOpenGL *scene);
+ QScopedPointer m_texture;
+ SceneOpenGL *m_scene;
+};
+
+class SceneOpenGL::EffectFrame
+ : public Scene::EffectFrame
+{
+public:
+ EffectFrame(EffectFrameImpl* frame, SceneOpenGL *scene);
+ virtual ~EffectFrame();
+
+ virtual void free();
+ virtual void freeIconFrame();
+ virtual void freeTextFrame();
+ virtual void freeSelection();
+
+ virtual void render(QRegion region, double opacity, double frameOpacity);
+
+ virtual void crossFadeIcon();
+ virtual void crossFadeText();
+
+ static void cleanup();
+
+private:
+ void updateTexture();
+ void updateTextTexture();
+
+ GLTexture *m_texture;
+ GLTexture *m_textTexture;
+ GLTexture *m_oldTextTexture;
+ QPixmap *m_textPixmap; // need to keep the pixmap around to workaround some driver problems
+ GLTexture *m_iconTexture;
+ GLTexture *m_oldIconTexture;
+ GLTexture *m_selectionTexture;
+ GLVertexBuffer *m_unstyledVBO;
+ SceneOpenGL *m_scene;
+
+ static GLTexture* m_unstyledTexture;
+ static QPixmap* m_unstyledPixmap; // need to keep the pixmap around to workaround some driver problems
+ static void updateUnstyledTexture(); // Update OpenGL unstyled frame texture
+};
+
+/**
+ * @short OpenGL implementation of Shadow.
+ *
+ * This class extends Shadow by the Elements required for OpenGL rendering.
+ * @author Martin Gräßlin
+ **/
+class SceneOpenGLShadow
+ : public Shadow
+{
+public:
+ explicit SceneOpenGLShadow(Toplevel *toplevel);
+ virtual ~SceneOpenGLShadow();
+
+ GLTexture *shadowTexture() {
+ return m_texture.data();
+ }
+protected:
+ virtual void buildQuads();
+ virtual bool prepareBackend();
+private:
+ QSharedPointer m_texture;
+};
+
+class SceneOpenGLDecorationRenderer : public Decoration::Renderer
+{
+ Q_OBJECT
+public:
+ enum class DecorationPart : int {
+ Left,
+ Top,
+ Right,
+ Bottom,
+ Count
+ };
+ explicit SceneOpenGLDecorationRenderer(Decoration::DecoratedClientImpl *client);
+ virtual ~SceneOpenGLDecorationRenderer();
+
+ void render() override;
+ void reparent(Deleted *deleted) override;
+
+ GLTexture *texture() {
+ return m_texture.data();
+ }
+ GLTexture *texture() const {
+ return m_texture.data();
+ }
+
+private:
+ void resizeTexture();
+ QScopedPointer m_texture;
+};
+
+inline bool SceneOpenGL::hasPendingFlush() const
+{
+ return m_backend->hasPendingFlush();
+}
+
+inline bool SceneOpenGL::usesOverlayWindow() const
+{
+ return m_backend->usesOverlayWindow();
+}
+
+inline SceneOpenGLTexture* OpenGLWindowPixmap::texture() const
+{
+ return m_texture.data();
+}
+
+class KWIN_EXPORT OpenGLFactory : public SceneFactory
+{
+ Q_OBJECT
+ Q_INTERFACES(KWin::SceneFactory)
+ Q_PLUGIN_METADATA(IID "org.kde.kwin.Scene" FILE "opengl.json")
+
+public:
+ explicit OpenGLFactory(QObject *parent = nullptr);
+ ~OpenGLFactory() override;
+
+ Scene *create(QObject *parent = nullptr) const override;
+};
+
+} // namespace
+
+#endif
diff --git a/scene.h b/scene.h
index d80217b95f..8f3b9615f8 100644
--- a/scene.h
+++ b/scene.h
@@ -186,6 +186,7 @@ public:
Q_SIGNALS:
void frameRendered();
+ void resetCompositing();
public Q_SLOTS:
// a window has been destroyed
diff --git a/scene_opengl.h b/scene_opengl.h
deleted file mode 100644
index be09697f5d..0000000000
--- a/scene_opengl.h
+++ /dev/null
@@ -1,694 +0,0 @@
-/********************************************************************
- KWin - the KDE window manager
- This file is part of the KDE project.
-
-Copyright (C) 2006 Lubos Lunak
-Copyright (C) 2009, 2010, 2011 Martin Gräßlin
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*********************************************************************/
-
-#ifndef KWIN_SCENE_OPENGL_H
-#define KWIN_SCENE_OPENGL_H
-
-#include "scene.h"
-#include "shadow.h"
-
-#include "kwinglutils.h"
-#include "kwingltexture_p.h"
-
-#include "decorations/decorationrenderer.h"
-
-namespace KWin
-{
-class LanczosFilter;
-class OpenGLBackend;
-class SyncManager;
-class SyncObject;
-
-class KWIN_EXPORT SceneOpenGL
- : public Scene
-{
- Q_OBJECT
-public:
- class EffectFrame;
- class Texture;
- class TexturePrivate;
- class Window;
- virtual ~SceneOpenGL();
- virtual bool initFailed() const;
- virtual bool hasPendingFlush() const;
- virtual qint64 paint(QRegion damage, ToplevelList windows);
- virtual Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame);
- virtual Shadow *createShadow(Toplevel *toplevel);
- virtual void screenGeometryChanged(const QSize &size);
- virtual OverlayWindow *overlayWindow();
- virtual bool usesOverlayWindow() const;
- virtual bool blocksForRetrace() const;
- virtual bool syncsToVBlank() const;
- virtual bool makeOpenGLContextCurrent() override;
- virtual void doneOpenGLContextCurrent() override;
- Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
- virtual void triggerFence() override;
- virtual QMatrix4x4 projectionMatrix() const = 0;
- bool animationsSupported() const override;
-
- void insertWait();
-
- void idle();
-
- bool debug() const { return m_debug; }
- void initDebugOutput();
-
- /**
- * @brief Factory method to create a backend specific texture.
- *
- * @return :SceneOpenGL::Texture*
- **/
- Texture *createTexture();
-
- OpenGLBackend *backend() const {
- return m_backend;
- }
-
- QVector openGLPlatformInterfaceExtensions() const override;
-
- /**
- * Copy a region of pixels from the current read to the current draw buffer
- */
- static void copyPixels(const QRegion ®ion);
-
- static SceneOpenGL *createScene(QObject *parent);
-
-protected:
- SceneOpenGL(OpenGLBackend *backend, QObject *parent = nullptr);
- virtual void paintBackground(QRegion region);
- virtual void extendPaintRegion(QRegion ®ion, bool opaqueFullscreen);
- QMatrix4x4 transformation(int mask, const ScreenPaintData &data) const;
- virtual void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data);
-
- void handleGraphicsReset(GLenum status);
-
- virtual void doPaintBackground(const QVector &vertices) = 0;
- virtual void updateProjectionMatrix() = 0;
-
-Q_SIGNALS:
- void resetCompositing();
-
-protected:
- bool init_ok;
-private:
- bool viewportLimitsMatched(const QSize &size) const;
-private:
- bool m_debug;
- OpenGLBackend *m_backend;
- SyncManager *m_syncManager;
- SyncObject *m_currentFence;
-};
-
-class SceneOpenGL2 : public SceneOpenGL
-{
- Q_OBJECT
-public:
- explicit SceneOpenGL2(OpenGLBackend *backend, QObject *parent = nullptr);
- virtual ~SceneOpenGL2();
- virtual CompositingType compositingType() const {
- return OpenGL2Compositing;
- }
-
- static bool supported(OpenGLBackend *backend);
-
- QMatrix4x4 projectionMatrix() const override { return m_projectionMatrix; }
- QMatrix4x4 screenProjectionMatrix() const override { return m_screenProjectionMatrix; }
-
-protected:
- virtual void paintSimpleScreen(int mask, QRegion region);
- virtual void paintGenericScreen(int mask, ScreenPaintData data);
- virtual void doPaintBackground(const QVector< float >& vertices);
- virtual Scene::Window *createWindow(Toplevel *t);
- virtual void finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data);
- virtual void updateProjectionMatrix() override;
- void paintCursor() override;
-
-private:
- void performPaintWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data);
- QMatrix4x4 createProjectionMatrix() const;
-
-private:
- LanczosFilter *m_lanczosFilter;
- QScopedPointer m_cursorTexture;
- QMatrix4x4 m_projectionMatrix;
- QMatrix4x4 m_screenProjectionMatrix;
- GLuint vao;
-};
-
-class SceneOpenGL::TexturePrivate
- : public GLTexturePrivate
-{
-public:
- virtual ~TexturePrivate();
-
- virtual bool loadTexture(WindowPixmap *pixmap) = 0;
- virtual void updateTexture(WindowPixmap *pixmap);
- virtual OpenGLBackend *backend() = 0;
-
-protected:
- TexturePrivate();
-
-private:
- Q_DISABLE_COPY(TexturePrivate)
-};
-
-class SceneOpenGL::Texture
- : public GLTexture
-{
-public:
- Texture(OpenGLBackend *backend);
- virtual ~Texture();
-
- Texture & operator = (const Texture& tex);
-
- void discard() override final;
-
-protected:
- bool load(WindowPixmap *pixmap);
- void updateFromPixmap(WindowPixmap *pixmap);
-
- Texture(TexturePrivate& dd);
-
-private:
- Q_DECLARE_PRIVATE(Texture)
-
- friend class OpenGLWindowPixmap;
-};
-
-class SceneOpenGL::Window
- : public Scene::Window
-{
-public:
- virtual ~Window();
- bool beginRenderWindow(int mask, const QRegion ®ion, WindowPaintData &data);
- virtual void performPaint(int mask, QRegion region, WindowPaintData data) = 0;
- void endRenderWindow();
- bool bindTexture();
- void setScene(SceneOpenGL *scene) {
- m_scene = scene;
- }
-
-protected:
- virtual WindowPixmap* createWindowPixmap();
- Window(Toplevel* c);
- enum TextureType {
- Content,
- Decoration,
- Shadow
- };
-
- QMatrix4x4 transformation(int mask, const WindowPaintData &data) const;
- GLTexture *getDecorationTexture() const;
-
-protected:
- SceneOpenGL *m_scene;
- bool m_hardwareClipping;
-};
-
-class SceneOpenGL2Window : public SceneOpenGL::Window
-{
-public:
- enum Leaf { ShadowLeaf = 0, DecorationLeaf, ContentLeaf, PreviousContentLeaf, LeafCount };
-
- struct LeafNode
- {
- LeafNode()
- : texture(0),
- firstVertex(0),
- vertexCount(0),
- opacity(1.0),
- hasAlpha(false),
- coordinateType(UnnormalizedCoordinates)
- {
- }
-
- GLTexture *texture;
- int firstVertex;
- int vertexCount;
- float opacity;
- bool hasAlpha;
- TextureCoordinateType coordinateType;
- };
-
- explicit SceneOpenGL2Window(Toplevel *c);
- virtual ~SceneOpenGL2Window();
-
-protected:
- QMatrix4x4 modelViewProjectionMatrix(int mask, const WindowPaintData &data) const;
- QVector4D modulate(float opacity, float brightness) const;
- void setBlendEnabled(bool enabled);
- void setupLeafNodes(LeafNode *nodes, const WindowQuadList *quads, const WindowPaintData &data);
- virtual void performPaint(int mask, QRegion region, WindowPaintData data);
-
-private:
- /**
- * Whether prepareStates enabled blending and restore states should disable again.
- **/
- bool m_blendingEnabled;
-};
-
-class OpenGLWindowPixmap : public WindowPixmap
-{
-public:
- explicit OpenGLWindowPixmap(Scene::Window *window, SceneOpenGL *scene);
- virtual ~OpenGLWindowPixmap();
- SceneOpenGL::Texture *texture() const;
- bool bind();
- bool isValid() const override;
-protected:
- WindowPixmap *createChild(const QPointer &subSurface) override;
-private:
- explicit OpenGLWindowPixmap(const QPointer &subSurface, WindowPixmap *parent, SceneOpenGL *scene);
- QScopedPointer m_texture;
- SceneOpenGL *m_scene;
-};
-
-class SceneOpenGL::EffectFrame
- : public Scene::EffectFrame
-{
-public:
- EffectFrame(EffectFrameImpl* frame, SceneOpenGL *scene);
- virtual ~EffectFrame();
-
- virtual void free();
- virtual void freeIconFrame();
- virtual void freeTextFrame();
- virtual void freeSelection();
-
- virtual void render(QRegion region, double opacity, double frameOpacity);
-
- virtual void crossFadeIcon();
- virtual void crossFadeText();
-
- static void cleanup();
-
-private:
- void updateTexture();
- void updateTextTexture();
-
- GLTexture *m_texture;
- GLTexture *m_textTexture;
- GLTexture *m_oldTextTexture;
- QPixmap *m_textPixmap; // need to keep the pixmap around to workaround some driver problems
- GLTexture *m_iconTexture;
- GLTexture *m_oldIconTexture;
- GLTexture *m_selectionTexture;
- GLVertexBuffer *m_unstyledVBO;
- SceneOpenGL *m_scene;
-
- static GLTexture* m_unstyledTexture;
- static QPixmap* m_unstyledPixmap; // need to keep the pixmap around to workaround some driver problems
- static void updateUnstyledTexture(); // Update OpenGL unstyled frame texture
-};
-
-/**
- * @short OpenGL implementation of Shadow.
- *
- * This class extends Shadow by the Elements required for OpenGL rendering.
- * @author Martin Gräßlin
- **/
-class SceneOpenGLShadow
- : public Shadow
-{
-public:
- explicit SceneOpenGLShadow(Toplevel *toplevel);
- virtual ~SceneOpenGLShadow();
-
- GLTexture *shadowTexture() {
- return m_texture.data();
- }
-protected:
- virtual void buildQuads();
- virtual bool prepareBackend();
-private:
- QSharedPointer m_texture;
-};
-
-/**
- * @short Profiler to detect whether we have triple buffering
- * The strategy is to start setBlocksForRetrace(false) but assume blocking and have the system prove that assumption wrong
- **/
-class KWIN_EXPORT SwapProfiler
-{
-public:
- SwapProfiler();
- void init();
- void begin();
- /**
- * @return char being 'd' for double, 't' for triple (or more - but non-blocking) buffering and
- * 0 (NOT '0') otherwise, so you can act on "if (char result = SwapProfiler::end()) { fooBar(); }
- **/
- char end();
-private:
- QElapsedTimer m_timer;
- qint64 m_time;
- int m_counter;
-};
-
-/**
- * @brief The OpenGLBackend creates and holds the OpenGL context and is responsible for Texture from Pixmap.
- *
- * The OpenGLBackend is an abstract base class used by the SceneOpenGL to abstract away the differences
- * between various OpenGL windowing systems such as GLX and EGL.
- *
- * A concrete implementation has to create and release the OpenGL context in a way so that the
- * SceneOpenGL does not have to care about it.
- *
- * In addition a major task for this class is to generate the SceneOpenGL::TexturePrivate which is
- * able to perform the texture from pixmap operation in the given backend.
- *
- * @author Martin Gräßlin
- **/
-class KWIN_EXPORT OpenGLBackend
-{
-public:
- OpenGLBackend();
- virtual ~OpenGLBackend();
-
- virtual void init() = 0;
- /**
- * @return Time passes since start of rendering current frame.
- * @see startRenderTimer
- **/
- qint64 renderTime() {
- return m_renderTimer.nsecsElapsed();
- }
- virtual void screenGeometryChanged(const QSize &size) = 0;
- virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture) = 0;
-
- /**
- * @brief Backend specific code to prepare the rendering of a frame including flushing the
- * previously rendered frame to the screen if the backend works this way.
- *
- * @return A region that if not empty will be repainted in addition to the damaged region
- **/
- virtual QRegion prepareRenderingFrame() = 0;
-
- /**
- * @brief Backend specific code to handle the end of rendering a frame.
- *
- * @param renderedRegion The possibly larger region that has been rendered
- * @param damagedRegion The damaged region that should be posted
- **/
- virtual void endRenderingFrame(const QRegion &damage, const QRegion &damagedRegion) = 0;
- virtual void endRenderingFrameForScreen(int screenId, const QRegion &damage, const QRegion &damagedRegion);
- virtual bool makeCurrent() = 0;
- virtual void doneCurrent() = 0;
- virtual bool usesOverlayWindow() const = 0;
- /**
- * Whether the rendering needs to be split per screen.
- * Default implementation returns @c false.
- **/
- virtual bool perScreenRendering() const;
- virtual QRegion prepareRenderingForScreen(int screenId);
- /**
- * @brief Compositor is going into idle mode, flushes any pending paints.
- **/
- void idle();
-
- /**
- * @return bool Whether the scene needs to flush a frame.
- **/
- bool hasPendingFlush() const {
- return !m_lastDamage.isEmpty();
- }
-
- /**
- * @brief Returns the OverlayWindow used by the backend.
- *
- * A backend does not have to use an OverlayWindow, this is mostly for the X world.
- * In case the backend does not use an OverlayWindow it is allowed to return @c null.
- * It's the task of the caller to check whether it is @c null.
- *
- * @return :OverlayWindow*
- **/
- virtual OverlayWindow *overlayWindow();
- /**
- * @brief Whether the creation of the Backend failed.
- *
- * The SceneOpenGL should test whether the Backend got constructed correctly. If this method
- * returns @c true, the SceneOpenGL should not try to start the rendering.
- *
- * @return bool @c true if the creation of the Backend failed, @c false otherwise.
- **/
- bool isFailed() const {
- return m_failed;
- }
- /**
- * @brief Whether the Backend provides VSync.
- *
- * Currently only the GLX backend can provide VSync.
- *
- * @return bool @c true if VSync support is available, @c false otherwise
- **/
- bool syncsToVBlank() const {
- return m_syncsToVBlank;
- }
- /**
- * @brief Whether VSync blocks execution until the screen is in the retrace
- *
- * Case for waitVideoSync and non triple buffering buffer swaps
- *
- **/
- bool blocksForRetrace() const {
- return m_blocksForRetrace;
- }
- /**
- * @brief Whether the backend uses direct rendering.
- *
- * Some OpenGLScene modes require direct rendering. E.g. the OpenGL 2 should not be used
- * if direct rendering is not supported by the Scene.
- *
- * @return bool @c true if the GL context is direct, @c false if indirect
- **/
- bool isDirectRendering() const {
- return m_directRendering;
- }
-
- bool supportsBufferAge() const {
- return m_haveBufferAge;
- }
-
- /**
- * @returns whether the context is surfaceless
- **/
- bool isSurfaceLessContext() const {
- return m_surfaceLessContext;
- }
-
- /**
- * Returns the damage that has accumulated since a buffer of the given age was presented.
- */
- QRegion accumulatedDamageHistory(int bufferAge) const;
-
- /**
- * Saves the given region to damage history.
- */
- void addToDamageHistory(const QRegion ®ion);
-
- /**
- * The backend specific extensions (e.g. EGL/GLX extensions).
- *
- * Not the OpenGL (ES) extension!
- **/
- QList extensions() const {
- return m_extensions;
- }
-
- /**
- * @returns whether the backend specific extensions contains @p extension.
- **/
- bool hasExtension(const QByteArray &extension) const {
- return m_extensions.contains(extension);
- }
-
-protected:
- /**
- * @brief Backend specific flushing of frame to screen.
- **/
- virtual void present() = 0;
- /**
- * @brief Sets the backend initialization to failed.
- *
- * This method should be called by the concrete subclass in case the initialization failed.
- * The given @p reason is logged as a warning.
- *
- * @param reason The reason why the initialization failed.
- **/
- void setFailed(const QString &reason);
- /**
- * @brief Sets whether the backend provides VSync.
- *
- * Should be called by the concrete subclass once it is determined whether VSync is supported.
- * If the subclass does not call this method, the backend defaults to @c false.
- * @param enabled @c true if VSync support available, @c false otherwise.
- **/
- void setSyncsToVBlank(bool enabled) {
- m_syncsToVBlank = enabled;
- }
- /**
- * @brief Sets whether the VSync iplementation blocks
- *
- * Should be called by the concrete subclass once it is determined how VSync works.
- * If the subclass does not call this method, the backend defaults to @c false.
- * @param enabled @c true if VSync blocks, @c false otherwise.
- **/
- void setBlocksForRetrace(bool enabled) {
- m_blocksForRetrace = enabled;
- }
- /**
- * @brief Sets whether the OpenGL context is direct.
- *
- * Should be called by the concrete subclass once it is determined whether the OpenGL context is
- * direct or indirect.
- * If the subclass does not call this method, the backend defaults to @c false.
- *
- * @param direct @c true if the OpenGL context is direct, @c false if indirect
- **/
- void setIsDirectRendering(bool direct) {
- m_directRendering = direct;
- }
-
- void setSupportsBufferAge(bool value) {
- m_haveBufferAge = value;
- }
-
- /**
- * @return const QRegion& Damage of previously rendered frame
- **/
- const QRegion &lastDamage() const {
- return m_lastDamage;
- }
- void setLastDamage(const QRegion &damage) {
- m_lastDamage = damage;
- }
- /**
- * @brief Starts the timer for how long it takes to render the frame.
- *
- * @see renderTime
- **/
- void startRenderTimer() {
- m_renderTimer.start();
- }
-
- /**
- * @param set whether the context is surface less
- **/
- void setSurfaceLessContext(bool set) {
- m_surfaceLessContext = set;
- }
-
- /**
- * Sets the platform-specific @p extensions.
- *
- * These are the EGL/GLX extensions, not the OpenGL extensions
- **/
- void setExtensions(const QList &extensions) {
- m_extensions = extensions;
- }
-
- SwapProfiler m_swapProfiler;
-
-private:
- /**
- * @brief Whether VSync is available and used, defaults to @c false.
- **/
- bool m_syncsToVBlank;
- /**
- * @brief Whether present() will block execution until the next vertical retrace @c false.
- **/
- bool m_blocksForRetrace;
- /**
- * @brief Whether direct rendering is used, defaults to @c false.
- **/
- bool m_directRendering;
- /**
- * @brief Whether the backend supports GLX_EXT_buffer_age / EGL_EXT_buffer_age.
- */
- bool m_haveBufferAge;
- /**
- * @brief Whether the initialization failed, of course default to @c false.
- **/
- bool m_failed;
- /**
- * @brief Damaged region of previously rendered frame.
- **/
- QRegion m_lastDamage;
- /**
- * @brief The damage history for the past 10 frames.
- */
- QList m_damageHistory;
- /**
- * @brief Timer to measure how long a frame renders.
- **/
- QElapsedTimer m_renderTimer;
- bool m_surfaceLessContext = false;
-
- QList m_extensions;
-};
-
-class SceneOpenGLDecorationRenderer : public Decoration::Renderer
-{
- Q_OBJECT
-public:
- enum class DecorationPart : int {
- Left,
- Top,
- Right,
- Bottom,
- Count
- };
- explicit SceneOpenGLDecorationRenderer(Decoration::DecoratedClientImpl *client);
- virtual ~SceneOpenGLDecorationRenderer();
-
- void render() override;
- void reparent(Deleted *deleted) override;
-
- GLTexture *texture() {
- return m_texture.data();
- }
- GLTexture *texture() const {
- return m_texture.data();
- }
-
-private:
- void resizeTexture();
- QScopedPointer m_texture;
-};
-
-inline bool SceneOpenGL::hasPendingFlush() const
-{
- return m_backend->hasPendingFlush();
-}
-
-inline bool SceneOpenGL::usesOverlayWindow() const
-{
- return m_backend->usesOverlayWindow();
-}
-
-inline SceneOpenGL::Texture* OpenGLWindowPixmap::texture() const
-{
- return m_texture.data();
-}
-
-} // namespace
-
-#endif