KWin
Loading...
Searching...
No Matches
x11_standalone_omlsynccontrolvsyncmonitor.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
10
11#include <private/qtx11extras_p.h>
12
13namespace KWin
14{
15
16std::unique_ptr<OMLSyncControlVsyncMonitor> OMLSyncControlVsyncMonitor::create()
17{
18 const char *extensions = glXQueryExtensionsString(QX11Info::display(),
19 QX11Info::appScreen());
20 if (!strstr(extensions, "GLX_OML_sync_control")) {
21 return nullptr; // GLX_OML_sync_control is unsupported.
22 }
23
24 std::unique_ptr<OMLSyncControlVsyncMonitor> monitor{new OMLSyncControlVsyncMonitor()};
25 if (monitor->isValid()) {
26 return monitor;
27 } else {
28 return nullptr;
29 }
30}
31
33{
34 // Establish a new X11 connection to avoid locking up the main X11 connection.
35 m_display = XOpenDisplay(DisplayString(QX11Info::display()));
36 if (!m_display) {
37 qCDebug(KWIN_X11STANDALONE) << "Failed to establish vsync monitor X11 connection";
38 return;
39 }
40
41 ::Window rootWindow = DefaultRootWindow(m_display);
42
43 const int attribs[] = {
44 GLX_RENDER_TYPE, GLX_RGBA_BIT,
45 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
46 0};
47
48 GLXFBConfig config = chooseGlxFbConfig(m_display, attribs);
49 if (!config) {
50 qCDebug(KWIN_X11STANDALONE) << "Couldn't find any suitable FBConfig for vsync monitor";
51 return;
52 }
53
54 XVisualInfo *visualInfo = glXGetVisualFromFBConfig(m_display, config);
55 if (!visualInfo) {
56 return;
57 }
58
59 Visual *visual = visualInfo->visual;
60 const int depth = visualInfo->depth;
61 XFree(visualInfo);
62
63 Colormap colormap = XCreateColormap(m_display, rootWindow, visual, AllocNone);
64 XSetWindowAttributes attributes;
65 attributes.colormap = colormap;
66
67 m_dummyWindow = XCreateWindow(m_display, rootWindow, 0, 0, 1, 1, 0, depth,
68 InputOutput, visual, CWColormap, &attributes);
69 XFreeColormap(m_display, colormap);
70 if (!m_dummyWindow) {
71 qCDebug(KWIN_X11STANDALONE) << "Failed to create a dummy window for vsync monitor";
72 return;
73 }
74
75 m_drawable = glXCreateWindow(m_display, config, m_dummyWindow, nullptr);
76 if (!m_drawable) {
77 qCDebug(KWIN_X11STANDALONE) << "Failed to create GLXWindow for dummy window";
78 return;
79 }
80
81 m_localContext = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE, 0, true);
82 if (!m_localContext) {
83 qCDebug(KWIN_X11STANDALONE) << "Failed to create opengl context for vsync monitor";
84 return;
85 }
86}
87
89{
90 if (m_localContext) {
91 glXDestroyContext(m_display, m_localContext);
92 }
93 if (m_drawable) {
94 glXDestroyWindow(m_display, m_drawable);
95 }
96 if (m_dummyWindow) {
97 XDestroyWindow(m_display, m_dummyWindow);
98 }
99 if (m_display) {
100 XCloseDisplay(m_display);
101 }
102}
103
105{
106 return m_display && m_localContext && m_drawable;
107}
108
110{
111 if (!glXMakeCurrent(m_display, m_drawable, m_localContext)) {
112 qCDebug(KWIN_X11STANDALONE) << "Failed to make vsync monitor OpenGL context current";
113 return;
114 }
115
116 int64_t ust, msc, sbc;
117
118 glXGetSyncValuesOML(m_display, m_drawable, &ust, &msc, &sbc);
119 glXWaitForMscOML(m_display, m_drawable, 0, 2, (msc + 1) % 2, &ust, &msc, &sbc);
120
121 Q_EMIT vblankOccurred(std::chrono::microseconds(ust));
122}
123
124OMLSyncControlVsyncMonitor::OMLSyncControlVsyncMonitor()
125{
126 m_helper.moveToThread(&m_thread);
127
132
133 m_thread.setObjectName(QStringLiteral("vsync event monitor"));
134 m_thread.start();
135}
136
138{
139 m_thread.quit();
140 m_thread.wait();
141}
142
144{
145 return m_helper.isValid();
146}
147
149{
150 QMetaObject::invokeMethod(&m_helper, &OMLSyncControlVsyncMonitorHelper::poll);
151}
152
153} // namespace KWin
154
155#include "moc_x11_standalone_omlsynccontrolvsyncmonitor.cpp"
void vblankOccurred(std::chrono::nanoseconds timestamp)
static std::unique_ptr< OMLSyncControlVsyncMonitor > create()
void vblankOccurred(std::chrono::nanoseconds timestamp)
KWIN_EXPORT xcb_window_t rootWindow()
Definition xcb.h:24
GLXFBConfig chooseGlxFbConfig(::Display *display, const int attributes[])