Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwaylandglcontext.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6
7#include <QtWaylandClient/private/qwaylanddisplay_p.h>
8#include <QtWaylandClient/private/qwaylandwindow_p.h>
9#include <QtWaylandClient/private/qwaylandsubsurface_p.h>
10#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h>
11#include <QtWaylandClient/private/qwaylandintegration_p.h>
13
14#include <QDebug>
15#include <QtGui/private/qeglconvenience_p.h>
16#include <QtGui/private/qopenglcontext_p.h>
17#include <QtOpenGL/private/qopengltexturecache_p.h>
18#include <QtGui/private/qguiapplication_p.h>
19#include <QtGui/private/qeglpbuffer_p.h>
20
21
22#include <qpa/qplatformopenglcontext.h>
23#include <QtGui/QSurfaceFormat>
24#include <QtOpenGL/QOpenGLShaderProgram>
25#include <QtGui/QOpenGLFunctions>
26#include <QOpenGLBuffer>
27
28#include <QtCore/qmutex.h>
29
30#include <dlfcn.h>
31
32// Constants from EGL_KHR_create_context
33#ifndef EGL_CONTEXT_MINOR_VERSION_KHR
34#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
35#endif
36#ifndef EGL_CONTEXT_FLAGS_KHR
37#define EGL_CONTEXT_FLAGS_KHR 0x30FC
38#endif
39#ifndef EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR
40#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
41#endif
42#ifndef EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
43#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
44#endif
45#ifndef EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
46#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
47#endif
48#ifndef EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
49#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
50#endif
51#ifndef EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR
52#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
53#endif
54#ifndef EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
55#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
56#endif
57#ifndef EGL_LOSE_CONTEXT_ON_RESET_KHR
58#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF
59#endif
60#ifndef EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
61#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
62#endif
63
64// Constants from EGL_EXT_create_context_robustness
65#ifndef EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT
66#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
67#endif
68#ifndef EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT
69#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
70#endif
71#ifndef EGL_LOSE_CONTEXT_ON_RESET_EXT
72#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
73#endif
74
75// Constants for OpenGL which are not available in the ES headers.
76#ifndef GL_CONTEXT_FLAGS
77#define GL_CONTEXT_FLAGS 0x821E
78#endif
79#ifndef GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
80#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
81#endif
82#ifndef GL_CONTEXT_FLAG_DEBUG_BIT
83#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
84#endif
85#ifndef GL_CONTEXT_PROFILE_MASK
86#define GL_CONTEXT_PROFILE_MASK 0x9126
87#endif
88#ifndef GL_CONTEXT_CORE_PROFILE_BIT
89#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
90#endif
91#ifndef GL_CONTEXT_COMPATIBILITY_PROFILE_BIT
92#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
93#endif
94
95// Constants from EGL_NV_robustness_video_memory_purge
96#ifndef EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV
97#define EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x334C
98#endif
99
100QT_BEGIN_NAMESPACE
101
102namespace QtWaylandClient {
103
109
114{
116 m_display, [this] { invalidateContext(); });
117
118 switch (format().renderableType()) {
121 break;
122#ifdef EGL_VERSION_1_4
125 break;
126#endif // EGL_VERSION_1_4
127 default:
129 break;
130 }
131
135 || !eglGetConfigAttrib(eglDisplay, eglConfig(), b, &b) || a > 0) {
137 }
138 {
139 bool ok;
140 int supportNonBlockingSwap = qEnvironmentVariableIntValue("QT_WAYLAND_FORCE_NONBLOCKING_SWAP_SUPPORT", &ok);
141 if (ok)
143 }
145 qCWarning(lcQpaWayland) << "Non-blocking swap buffers not supported."
146 << "Subsurface rendering can be affected."
147 << "It may also cause the event loop to freeze in some situations";
148 }
149}
150
163
172
174{
175 bool ok;
176 const int doneCurrentWorkAround = qEnvironmentVariableIntValue("QT_WAYLAND_ENABLE_DONECURRENT_WORKAROUND", &ok);
177 if (ok) {
180 qCDebug(lcQpaWayland) << "Enabling doneCurrent() workaround on request.";
181 else
182 qCDebug(lcQpaWayland) << "Disabling doneCurrent() workaround on request.";
183
184 } else {
185 // Note that even though there is an EGL context current here,
186 // QOpenGLContext and QOpenGLFunctions are not yet usable at this stage.
187 const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
188 if (renderer && strstr(renderer, "Mali")) {
189 qCDebug(lcQpaWayland) << "Enabling doneCurrent() workaround for Mali GPU."
190 << "Set QT_WAYLAND_ENABLE_DONECURRENT_WORKAROUND=0 to disable.";
192 }
193 }
194
196}
197
202
204{
205 if (!m_currentWindow)
206 return;
207
210}
211
227
229{
230 if (!isValid()) {
231 return false;
232 }
233
235 m_currentWindow = nullptr;
237 }
238
239 // in QWaylandGLContext() we called eglBindAPI with the correct value. However,
240 // eglBindAPI's documentation says:
241 // "eglBindAPI defines the current rendering API for EGL in the thread it is called from"
242 // Since makeCurrent() can be called from a different thread than the one we created the
243 // context in make sure to call eglBindAPI in the correct thread.
244 if (eglQueryAPI() != m_api) {
246 }
247
248 m_currentWindow = static_cast<QWaylandEglWindow *>(surface);
249
251
254
255 if (eglSurface == EGL_NO_SURFACE) {
258 }
259
261 qWarning("QWaylandGLContext::makeCurrent: eglError: %#x, this: %p \n", eglGetError(), this);
262 return false;
263 }
264 if (!checkGraphicsReset())
265 return false;
266
267 // Nvidia requires that the surface is current and on the render thread at the time of doing the actual resizing
269 return true;
270}
271
277
279{
282 }
283
285
287
290 if (swapInterval == 0 && format().swapInterval() > 0) {
291 // Emulating a blocking swap
292 glFlush(); // Flush before waiting so we can swap more quickly when the frame event arrives
294 }
297 qCWarning(lcQpaWayland, "eglSwapBuffers failed with %#x, surface: %p", eglGetError(), eglSurface);
298}
299
307
308}
309
310QT_END_NAMESPACE