Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qxcbeglintegration.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
5
6#include "qxcbeglcontext.h"
7
8#include <QtGui/QOffscreenSurface>
9#include <QtGui/private/qeglconvenience_p.h>
10#include <QtGui/private/qeglstreamconvenience_p.h>
11#include <optional>
12
14
16
17namespace {
18
20{
21 xcb_visualtype_t visualType;
22 uint8_t depth;
23};
24
25std::optional<VisualInfo> getVisualInfo(xcb_screen_t *screen,
26 std::optional<xcb_visualid_t> requestedVisualId,
27 std::optional<uint8_t> requestedDepth = std::nullopt)
28{
29 xcb_depth_iterator_t depthIterator = xcb_screen_allowed_depths_iterator(screen);
30
31 while (depthIterator.rem) {
32 xcb_depth_t *depth = depthIterator.data;
33 xcb_visualtype_iterator_t visualTypeIterator = xcb_depth_visuals_iterator(depth);
34
35 while (visualTypeIterator.rem) {
36 xcb_visualtype_t *visualType = visualTypeIterator.data;
37 if (requestedVisualId && visualType->visual_id != *requestedVisualId) {
38 xcb_visualtype_next(&visualTypeIterator);
39 continue;
40 }
41
42 if (requestedDepth && depth->depth != *requestedDepth) {
43 xcb_visualtype_next(&visualTypeIterator);
44 continue;
45 }
46
47 return VisualInfo{ *visualType, depth->depth };
48 }
49
50 xcb_depth_next(&depthIterator);
51 }
52
53 return std::nullopt;
54}
55
56} // namespace
57
59 : m_connection(nullptr)
60 , m_egl_display(EGL_NO_DISPLAY)
61{
62 qCDebug(lcQpaGl) << "Xcb EGL gl-integration created";
63}
64
66{
67 if (m_egl_display != EGL_NO_DISPLAY)
68 eglTerminate(m_egl_display);
69}
70
72{
73 m_connection = connection;
74
75 const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
76
77#if QT_CONFIG(xcb_xlib)
78 if (extensions && strstr(extensions, "EGL_EXT_platform_x11")) {
79 QEGLStreamConvenience streamFuncs;
80 m_egl_display = streamFuncs.get_platform_display(EGL_PLATFORM_X11_KHR,
81 m_connection->xlib_display(),
82 nullptr);
83 }
84
85#if QT_CONFIG(egl_x11)
86 if (!m_egl_display)
87 m_egl_display = eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(m_connection->xlib_display()));
88#endif
89#else
90 if (extensions && (strstr(extensions, "EGL_EXT_platform_xcb") || strstr(extensions, "EGL_MESA_platform_xcb"))) {
91 QEGLStreamConvenience streamFuncs;
92 m_egl_display = streamFuncs.get_platform_display(EGL_PLATFORM_XCB_KHR,
93 reinterpret_cast<void *>(connection->xcb_connection()),
94 nullptr);
95 }
96#endif
97
98 EGLint major, minor;
99 bool success = eglInitialize(m_egl_display, &major, &minor);
100#if QT_CONFIG(egl_x11)
101 if (!success) {
102 m_egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
103 qCDebug(lcQpaGl) << "Xcb EGL gl-integration retrying with display" << m_egl_display;
104 success = eglInitialize(m_egl_display, &major, &minor);
105 }
106#endif
107
108 m_native_interface_handler.reset(new QXcbEglNativeInterfaceHandler(connection->nativeInterface()));
109
110 if (success)
111 qCDebug(lcQpaGl) << "Xcb EGL gl-integration successfully initialized";
112 else
113 qCWarning(lcQpaGl) << "Xcb EGL gl-integration initialize failed";
114
115 return success;
116}
117
119{
120 return new QXcbEglWindow(window, const_cast<QXcbEglIntegration *>(this));
121}
122
124{
125 QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
126 QXcbEglContext *platformContext = new QXcbEglContext(screen->surfaceFormatFor(context->format()),
127 context->shareHandle(),
128 eglDisplay());
129 return platformContext;
130}
131
133{
134 return QEGLPlatformContext::createFrom<QXcbEglContext>(context, display, eglDisplay(), shareContext);
135}
136
138{
139 QXcbScreen *screen = static_cast<QXcbScreen *>(surface->screen()->handle());
140 return new QEGLPbuffer(eglDisplay(), screen->surfaceFormatFor(surface->requestedFormat()), surface);
141}
142
143xcb_visualid_t QXcbEglIntegration::getCompatibleVisualId(xcb_screen_t *screen, EGLConfig config) const
144{
145 xcb_visualid_t visualId = 0;
146 EGLint eglValue = 0;
147
148 EGLint configRedSize = 0;
149 eglGetConfigAttrib(eglDisplay(), config, EGL_RED_SIZE, &configRedSize);
150
151 EGLint configGreenSize = 0;
152 eglGetConfigAttrib(eglDisplay(), config, EGL_GREEN_SIZE, &configGreenSize);
153
154 EGLint configBlueSize = 0;
155 eglGetConfigAttrib(eglDisplay(), config, EGL_BLUE_SIZE, &configBlueSize);
156
157 EGLint configAlphaSize = 0;
158 eglGetConfigAttrib(eglDisplay(), config, EGL_ALPHA_SIZE, &configAlphaSize);
159
160 eglGetConfigAttrib(eglDisplay(), config, EGL_CONFIG_ID, &eglValue);
161 int configId = eglValue;
162
163 // See if EGL provided a valid VisualID:
164 eglGetConfigAttrib(eglDisplay(), config, EGL_NATIVE_VISUAL_ID, &eglValue);
165 visualId = eglValue;
166 if (visualId) {
167 // EGL has suggested a visual id, so get the rest of the visual info for that id:
168 std::optional<VisualInfo> chosenVisualInfo = getVisualInfo(screen, visualId);
169 if (chosenVisualInfo) {
170 // Skip size checks if implementation supports non-matching visual
171 // and config (QTBUG-9444).
172 if (q_hasEglExtension(eglDisplay(), "EGL_NV_post_convert_rounding"))
173 return visualId;
174 // Skip also for i.MX6 where 565 visuals are suggested for the default 444 configs and it works just fine.
175 const char *vendor = eglQueryString(eglDisplay(), EGL_VENDOR);
176 if (vendor && strstr(vendor, "Vivante"))
177 return visualId;
178
179 int visualRedSize = qPopulationCount(chosenVisualInfo->visualType.red_mask);
180 int visualGreenSize = qPopulationCount(chosenVisualInfo->visualType.green_mask);
181 int visualBlueSize = qPopulationCount(chosenVisualInfo->visualType.blue_mask);
182 int visualAlphaSize = chosenVisualInfo->depth - visualRedSize - visualBlueSize - visualGreenSize;
183
184 const bool visualMatchesConfig = visualRedSize >= configRedSize
185 && visualGreenSize >= configGreenSize
186 && visualBlueSize >= configBlueSize
187 && visualAlphaSize >= configAlphaSize;
188
189 // In some cases EGL tends to suggest a 24-bit visual for 8888
190 // configs. In such a case we have to fall back to getVisualInfo.
191 if (!visualMatchesConfig) {
192 visualId = 0;
193 qCDebug(lcQpaGl,
194 "EGL suggested using X Visual ID %d (%d %d %d %d depth %d) for EGL config %d"
195 "(%d %d %d %d), but this is incompatible",
196 visualId, visualRedSize, visualGreenSize, visualBlueSize, visualAlphaSize, chosenVisualInfo->depth,
197 configId, configRedSize, configGreenSize, configBlueSize, configAlphaSize);
198 }
199 } else {
200 qCDebug(lcQpaGl, "EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
201 visualId, configId);
202 visualId = 0;
203 }
204 }
205 else
206 qCDebug(lcQpaGl, "EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId);
207
208 if (visualId) {
209 qCDebug(lcQpaGl, configAlphaSize > 0
210 ? "Using ARGB Visual ID %d provided by EGL for config %d"
211 : "Using Opaque Visual ID %d provided by EGL for config %d", visualId, configId);
212 return visualId;
213 }
214
215 // Finally, try to use getVisualInfo and only use the bit depths to match on:
216 if (!visualId) {
217 uint8_t depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize;
218 std::optional<VisualInfo> matchingVisual = getVisualInfo(screen, std::nullopt, depth);
219 if (!matchingVisual) {
220 // Try again without taking the alpha channel into account:
221 depth = configRedSize + configGreenSize + configBlueSize;
222 matchingVisual = getVisualInfo(screen, std::nullopt, depth);
223 }
224
225 if (matchingVisual)
226 visualId = matchingVisual->visualType.visual_id;
227 }
228
229 if (visualId) {
230 qCDebug(lcQpaGl, "Using Visual ID %d provided by getVisualInfo for EGL config %d", visualId, configId);
231 return visualId;
232 }
233
234 qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
235 return 0;
236}
237
A pbuffer-based implementation of QPlatformOffscreenSurface for EGL.
PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display
\inmodule QtGui
QScreen * screen() const
Returns the screen to which the offscreen surface is connected.
QSurfaceFormat requestedFormat() const
Returns the requested surfaceformat of this offscreen surface.
\inmodule QtGui
The QPlatformOpenGLContext class provides an abstraction for native GL contexts.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
QPlatformScreen * handle() const
Get the platform screen handle.
Definition qscreen.cpp:83
\inmodule QtGui
Definition qwindow.h:63
QOpenGLContext * createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const override
QPlatformOffscreenSurface * createPlatformOffscreenSurface(QOffscreenSurface *surface) const override
QXcbWindow * createWindow(QWindow *window) const override
bool initialize(QXcbConnection *connection) override
xcb_visualid_t getCompatibleVisualId(xcb_screen_t *screen, EGLConfig config) const
EGLDisplay eglDisplay() const
QPlatformOpenGLContext * createPlatformOpenGLContext(QOpenGLContext *context) const override
struct wl_display * display
Definition linuxdmabuf.h:41
Combined button and popup list for selecting options.
std::optional< VisualInfo > getVisualInfo(xcb_screen_t *screen, std::optional< xcb_visualid_t > requestedVisualId, std::optional< uint8_t > requestedDepth=std::nullopt)
Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR uint qPopulationCount(quint32 v) noexcept
static void * context
DBusConnection * connection
bool q_hasEglExtension(EGLDisplay display, const char *extensionName)
EGLConfig config
typedef EGLDisplay(EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum platform
#define EGL_PLATFORM_XCB_KHR
#define EGL_PLATFORM_X11_KHR
#define qWarning
Definition qlogging.h:162
#define qCWarning(category,...)
#define qCDebug(category,...)
GLint GLenum GLsizei GLsizei GLsizei depth
QScreen * screen
[1]
Definition main.cpp:29
QObject::connect nullptr
aWidget window() -> setWindowTitle("New Window Title")
[2]