[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kwin] /: Add support for GLX_INTEL_swap_event
From:       Fredrik_Höglund <fredrik () kde ! org>
Date:       2014-09-18 18:26:33
Message-ID: E1XUgPZ-0006Cb-8I () scm ! kde ! org
[Download RAW message or body]

Git commit ad0abdc81286ce6db94f735935e304c65afdf17d by Fredrik Höglund.
Committed on 07/08/2014 at 12:16.
Pushed by fredrik into branch 'master'.

Add support for GLX_INTEL_swap_event

Enable swap events and use them to defer rendering of the next frame
until the last glXSwapBuffers() call has completed.

M  +57   -0    glxbackend.cpp
M  +20   -0    glxbackend.h

http://commits.kde.org/kwin/ad0abdc81286ce6db94f735935e304c65afdf17d

diff --git a/glxbackend.cpp b/glxbackend.cpp
index d2b5af0..def6e9f 100644
--- a/glxbackend.cpp
+++ b/glxbackend.cpp
@@ -30,6 +30,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "options.h"
 #include "utils.h"
 #include "overlaywindow.h"
+#include "composite.h"
+#include "xcbutils.h"
 // kwin libs
 #include <kwinglplatform.h>
 #include <kwinxrenderutils.h>
@@ -38,11 +40,48 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <QOpenGLContext>
 // system
 #include <unistd.h>
+#include <xcb/glx.h>
 
 #include <tuple>
 
+#if __cplusplus <= 201103L
+namespace std {
+    // C++-14
+    template<class T, class... Args>
+    unique_ptr<T> make_unique(Args&&... args) {
+        return unique_ptr<T>(new T(std::forward<Args>(args)...));
+    }
+}
+#endif
+
+
 namespace KWin
 {
+
+SwapEventFilter::SwapEventFilter(xcb_drawable_t drawable)
+    : X11EventFilter(Xcb::Extensions::self()->glxEventBase() + XCB_GLX_BUFFER_SWAP_COMPLETE),
+      m_drawable(drawable)
+{
+}
+
+bool SwapEventFilter::event(xcb_generic_event_t *event)
+{
+    xcb_glx_buffer_swap_complete_event_t *ev =
+            reinterpret_cast<xcb_glx_buffer_swap_complete_event_t *>(event);
+
+    if (ev->drawable == m_drawable) {
+        Compositor::self()->bufferSwapComplete();
+        return true;
+    }
+
+    return false;
+}
+
+
+// -----------------------------------------------------------------------
+
+
+
 GlxBackend::GlxBackend()
     : OpenGLBackend()
     , m_overlayWindow(new OverlayWindow())
@@ -116,6 +155,21 @@ void GlxBackend::init()
     m_haveMESASwapControl   = hasGLExtension(QByteArrayLiteral("GLX_MESA_swap_control"));
     m_haveEXTSwapControl    = hasGLExtension(QByteArrayLiteral("GLX_EXT_swap_control"));
     m_haveSGISwapControl    = hasGLExtension(QByteArrayLiteral("GLX_SGI_swap_control"));
+    m_haveINTELSwapEvent    = hasGLExtension(QByteArrayLiteral("GLX_INTEL_swap_event"));
+
+    if (m_haveINTELSwapEvent) {
+        const QList<QByteArray> tokens = QByteArray(qVersion()).split('.');
+        uint32_t version = tokens[0].toInt() << 16 | tokens[1].toInt() << 8 | tokens[2].toInt();
+
+        // Qt 5.3 doesn't forward swap events to the native event filter
+        if (version < 0x00050400)
+            m_haveINTELSwapEvent = false;
+    }
+
+    if (m_haveINTELSwapEvent) {
+        m_swapEventFilter = std::make_unique<SwapEventFilter>(window);
+        glXSelectEvent(display(), glxWindow, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK);
+    }
 
     haveSwapInterval = m_haveMESASwapControl || m_haveEXTSwapControl || m_haveSGISwapControl;
 
@@ -473,6 +527,9 @@ void GlxBackend::present()
     const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion);
 
     if (fullRepaint) {
+        if (m_haveINTELSwapEvent)
+            Compositor::self()->aboutToSwapBuffers();
+
         if (haveSwapInterval) {
             if (gs_tripleBufferNeedsDetection) {
                 glXWaitGL();
diff --git a/glxbackend.h b/glxbackend.h
index 4b49ae8..fba0a34 100644
--- a/glxbackend.h
+++ b/glxbackend.h
@@ -20,6 +20,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef KWIN_GLX_BACKEND_H
 #define KWIN_GLX_BACKEND_H
 #include "scene_opengl.h"
+#include "x11eventfilter.h"
+
+#include <memory>
 
 namespace KWin
 {
@@ -34,6 +37,21 @@ public:
     int mipmap;
 };
 
+
+// ------------------------------------------------------------------
+
+
+class SwapEventFilter : public X11EventFilter
+{
+public:
+    SwapEventFilter(xcb_drawable_t drawable);
+    bool event(xcb_generic_event_t *event) override;
+
+private:
+    xcb_drawable_t m_drawable;
+};
+
+
 /**
  * @brief OpenGL Backend using GLX over an X overlay window.
  **/
@@ -76,11 +94,13 @@ private:
     GLXContext ctx;
     QHash<xcb_visualid_t, FBConfigInfo *> m_fbconfigHash;
     QHash<xcb_visualid_t, int> m_visualDepthHash;
+    std::unique_ptr<SwapEventFilter> m_swapEventFilter;
     int m_bufferAge;
     bool m_haveMESACopySubBuffer;
     bool m_haveMESASwapControl;
     bool m_haveEXTSwapControl;
     bool m_haveSGISwapControl;
+    bool m_haveINTELSwapEvent;
     bool haveSwapInterval, haveWaitSync;
     friend class GlxTexture;
 };
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic