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.
This commit is contained in:
parent
29795f49e8
commit
ad0abdc812
2 changed files with 77 additions and 0 deletions
|
@ -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();
|
||||
|
|
20
glxbackend.h
20
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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue