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