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
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
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)
61 , m_using_platform_display(false)
62{
63 qCDebug(lcQpaGl) << "Xcb EGL gl-integration created";
64}
65
67{
68 if (m_egl_display != EGL_NO_DISPLAY)
69 eglTerminate(m_egl_display);
70}
71
72bool QXcbEglIntegration::initialize(QXcbConnection *connection)
73{
74 m_connection = connection;
75
76 const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
77
78#if QT_CONFIG(xcb_xlib)
79 if (extensions && strstr(extensions, "EGL_EXT_platform_x11")) {
80 QEGLStreamConvenience streamFuncs;
81 m_egl_display = streamFuncs.get_platform_display(EGL_PLATFORM_X11_KHR,
82 m_connection->xlib_display(),
83 nullptr);
84 m_using_platform_display = true;
85 }
86
87#if QT_CONFIG(egl_x11)
88 if (!m_egl_display)
89 m_egl_display = eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(m_connection->xlib_display()));
90#endif
91#else
92 if (extensions && (strstr(extensions, "EGL_EXT_platform_xcb") || strstr(extensions, "EGL_MESA_platform_xcb"))) {
93 QEGLStreamConvenience streamFuncs;
94 m_egl_display = streamFuncs.get_platform_display(EGL_PLATFORM_XCB_KHR,
95 reinterpret_cast<void *>(connection->xcb_connection()),
96 nullptr);
97 m_using_platform_display = true;
98 }
99#endif
100
101 EGLint major, minor;
102 bool success = eglInitialize(m_egl_display, &major, &minor);
103#if QT_CONFIG(egl_x11)
104 if (!success) {
105 m_egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
106 qCDebug(lcQpaGl) << "Xcb EGL gl-integration retrying with display" << m_egl_display;
107 success = eglInitialize(m_egl_display, &major, &minor);
108 }
109#endif
110
111 m_native_interface_handler.reset(new QXcbEglNativeInterfaceHandler(connection->nativeInterface()));
112
113 if (success)
114 qCDebug(lcQpaGl) << "Xcb EGL gl-integration successfully initialized";
115 else
116 qCWarning(lcQpaGl) << "Xcb EGL gl-integration initialize failed";
117
118 return success;
119}
120
121QXcbWindow *QXcbEglIntegration::createWindow(QWindow *window) const
122{
123 return new QXcbEglWindow(window, const_cast<QXcbEglIntegration *>(this));
124}
125
127{
128 QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
129 QXcbEglContext *platformContext = new QXcbEglContext(screen->surfaceFormatFor(context->format()),
130 context->shareHandle(),
131 eglDisplay());
132 return platformContext;
133}
134
135QOpenGLContext *QXcbEglIntegration::createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const
136{
137 return QEGLPlatformContext::createFrom<QXcbEglContext>(context, display, eglDisplay(), shareContext);
138}
139
141{
142 QXcbScreen *screen = static_cast<QXcbScreen *>(surface->screen()->handle());
143 return new QEGLPbuffer(eglDisplay(), screen->surfaceFormatFor(surface->requestedFormat()), surface);
144}
145
146xcb_visualid_t QXcbEglIntegration::getCompatibleVisualId(xcb_screen_t *screen, EGLConfig config) const
147{
148 xcb_visualid_t visualId = 0;
149 EGLint eglValue = 0;
150
151 EGLint configRedSize = 0;
152 eglGetConfigAttrib(eglDisplay(), config, EGL_RED_SIZE, &configRedSize);
153
154 EGLint configGreenSize = 0;
155 eglGetConfigAttrib(eglDisplay(), config, EGL_GREEN_SIZE, &configGreenSize);
156
157 EGLint configBlueSize = 0;
158 eglGetConfigAttrib(eglDisplay(), config, EGL_BLUE_SIZE, &configBlueSize);
159
160 EGLint configAlphaSize = 0;
161 eglGetConfigAttrib(eglDisplay(), config, EGL_ALPHA_SIZE, &configAlphaSize);
162
163 eglGetConfigAttrib(eglDisplay(), config, EGL_CONFIG_ID, &eglValue);
164 int configId = eglValue;
165
166 // See if EGL provided a valid VisualID:
167 eglGetConfigAttrib(eglDisplay(), config, EGL_NATIVE_VISUAL_ID, &eglValue);
168 visualId = eglValue;
169 if (visualId) {
170 // EGL has suggested a visual id, so get the rest of the visual info for that id:
171 std::optional<VisualInfo> chosenVisualInfo = getVisualInfo(screen, visualId);
172 if (chosenVisualInfo) {
173 // Skip size checks if implementation supports non-matching visual
174 // and config (QTBUG-9444).
175 if (q_hasEglExtension(eglDisplay(), "EGL_NV_post_convert_rounding"))
176 return visualId;
177 // Skip also for i.MX6 where 565 visuals are suggested for the default 444 configs and it works just fine.
178 const char *vendor = eglQueryString(eglDisplay(), EGL_VENDOR);
179 if (vendor && strstr(vendor, "Vivante"))
180 return visualId;
181
182 int visualRedSize = qPopulationCount(chosenVisualInfo->visualType.red_mask);
183 int visualGreenSize = qPopulationCount(chosenVisualInfo->visualType.green_mask);
184 int visualBlueSize = qPopulationCount(chosenVisualInfo->visualType.blue_mask);
185 int visualAlphaSize = chosenVisualInfo->depth - visualRedSize - visualBlueSize - visualGreenSize;
186
187 const bool visualMatchesConfig = visualRedSize >= configRedSize
188 && visualGreenSize >= configGreenSize
189 && visualBlueSize >= configBlueSize
190 && visualAlphaSize >= configAlphaSize;
191
192 // In some cases EGL tends to suggest a 24-bit visual for 8888
193 // configs. In such a case we have to fall back to getVisualInfo.
194 if (!visualMatchesConfig) {
195 visualId = 0;
196 qCDebug(lcQpaGl,
197 "EGL suggested using X Visual ID %d (%d %d %d %d depth %d) for EGL config %d"
198 "(%d %d %d %d), but this is incompatible",
199 visualId, visualRedSize, visualGreenSize, visualBlueSize, visualAlphaSize, chosenVisualInfo->depth,
200 configId, configRedSize, configGreenSize, configBlueSize, configAlphaSize);
201 }
202 } else {
203 qCDebug(lcQpaGl, "EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
204 visualId, configId);
205 visualId = 0;
206 }
207 }
208 else
209 qCDebug(lcQpaGl, "EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId);
210
211 if (visualId) {
212 qCDebug(lcQpaGl, configAlphaSize > 0
213 ? "Using ARGB Visual ID %d provided by EGL for config %d"
214 : "Using Opaque Visual ID %d provided by EGL for config %d", visualId, configId);
215 return visualId;
216 }
217
218 // Finally, try to use getVisualInfo and only use the bit depths to match on:
219 if (!visualId) {
220 uint8_t depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize;
221 std::optional<VisualInfo> matchingVisual = getVisualInfo(screen, std::nullopt, depth);
222 if (!matchingVisual) {
223 // Try again without taking the alpha channel into account:
224 depth = configRedSize + configGreenSize + configBlueSize;
225 matchingVisual = getVisualInfo(screen, std::nullopt, depth);
226 }
227
228 if (matchingVisual)
229 visualId = matchingVisual->visualType.visual_id;
230 }
231
232 if (visualId) {
233 qCDebug(lcQpaGl, "Using Visual ID %d provided by getVisualInfo for EGL config %d", visualId, configId);
234 return visualId;
235 }
236
237 qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
238 return 0;
239}
240
241QT_END_NAMESPACE
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
QPlatformOpenGLContext * createPlatformOpenGLContext(QOpenGLContext *context) const override
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)