Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 , 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
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
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
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
A pbuffer-based implementation of QPlatformOffscreenSurface for EGL.
\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:166
#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]