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
4#include "qwaylandeglclientbufferintegration_p.h"
5
6#include "qwaylandeglwindow_p.h"
7#include "qwaylandglcontext_p.h"
8
9#include <wayland-client-core.h>
10
11#include <QtCore/QDebug>
12#include <private/qeglconvenience_p.h>
13
14#ifndef EGL_EXT_platform_base
15typedef EGLDisplay (*PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
16#endif
17
18#ifndef EGL_PLATFORM_WAYLAND_KHR
19#define EGL_PLATFORM_WAYLAND_KHR 0x31D8
20#endif
21
22QT_BEGIN_NAMESPACE
23
24namespace QtWaylandClient {
25
26static const char *qwaylandegl_threadedgl_blacklist_vendor[] = {
27 0
28};
29
30QWaylandEglClientBufferIntegration::QWaylandEglClientBufferIntegration()
31{
32 qCDebug(lcQpaWayland) << "Using Wayland-EGL";
33}
34
35
36QWaylandEglClientBufferIntegration::~QWaylandEglClientBufferIntegration()
37{
38 eglTerminate(dpy: m_eglDisplay);
39}
40
41void QWaylandEglClientBufferIntegration::initialize(QWaylandDisplay *display)
42{
43#if QT_CONFIG(egl_extension_platform_wayland)
44 m_eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_EXT, native_display: display->wl_display(), attrib_list: nullptr);
45#else
46 if (q_hasEglExtension(EGL_NO_DISPLAY, "EGL_EXT_platform_base")) {
47 if (q_hasEglExtension(EGL_NO_DISPLAY, "EGL_KHR_platform_wayland") ||
48 q_hasEglExtension(EGL_NO_DISPLAY, "EGL_EXT_platform_wayland") ||
49 q_hasEglExtension(EGL_NO_DISPLAY, "EGL_MESA_platform_wayland")) {
50
51 static PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplay = nullptr;
52 if (!eglGetPlatformDisplay)
53 eglGetPlatformDisplay = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
54
55 m_eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, display->wl_display(), nullptr);
56 } else {
57 qCWarning(lcQpaWayland) << "The EGL implementation does not support the Wayland platform";
58 return;
59 }
60 } else {
61 QByteArray eglPlatform = qgetenv("EGL_PLATFORM");
62 if (eglPlatform.isEmpty()) {
63 setenv("EGL_PLATFORM","wayland",true);
64 }
65
66 m_eglDisplay = eglGetDisplay((EGLNativeDisplayType) display->wl_display());
67 }
68#endif
69
70 m_display = display;
71
72 if (m_eglDisplay == EGL_NO_DISPLAY) {
73 qCWarning(lcQpaWayland) << "EGL not available";
74 return;
75 }
76
77 EGLint major,minor;
78 if (!eglInitialize(dpy: m_eglDisplay, major: &major, minor: &minor)) {
79 qCWarning(lcQpaWayland) << "Failed to initialize EGL display" << Qt::hex << eglGetError();
80 m_eglDisplay = EGL_NO_DISPLAY;
81 return;
82 }
83
84 m_supportsThreading = true;
85 if (qEnvironmentVariableIsSet(varName: "QT_OPENGL_NO_SANITY_CHECK"))
86 return;
87
88 const char *vendor = eglQueryString(dpy: m_eglDisplay, EGL_VENDOR);
89 for (int i = 0; qwaylandegl_threadedgl_blacklist_vendor[i]; ++i) {
90 if (strstr(haystack: vendor, needle: qwaylandegl_threadedgl_blacklist_vendor[i]) != 0) {
91 m_supportsThreading = false;
92 break;
93 }
94 }
95
96 // On desktop NVIDIA resizing QtQuick freezes them when using threaded rendering QTBUG-95817
97 // In order to support threaded rendering on embedded platforms where resizing is not needed
98 // we check if XDG_CURRENT_DESKTOP is set which desktop environments should set
99 if (qstrcmp(str1: vendor, str2: "NVIDIA") == 0 && qEnvironmentVariableIsSet(varName: "XDG_CURRENT_DESKTOP")) {
100 m_supportsThreading = false;
101 }
102}
103
104bool QWaylandEglClientBufferIntegration::isValid() const
105{
106 return m_eglDisplay != EGL_NO_DISPLAY;
107}
108
109bool QWaylandEglClientBufferIntegration::supportsThreadedOpenGL() const
110{
111 return m_supportsThreading;
112}
113
114bool QWaylandEglClientBufferIntegration::supportsWindowDecoration() const
115{
116 return true;
117}
118
119QWaylandWindow *QWaylandEglClientBufferIntegration::createEglWindow(QWindow *window)
120{
121 return new QWaylandEglWindow(window, m_display);
122}
123
124QPlatformOpenGLContext *QWaylandEglClientBufferIntegration::createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const
125{
126 QSurfaceFormat fmt = glFormat;
127 if (m_display->supportsWindowDecoration())
128 fmt.setAlphaBufferSize(8);
129 return new QWaylandGLContext(m_eglDisplay, m_display, fmt, share);
130}
131
132void *QWaylandEglClientBufferIntegration::nativeResource(NativeResource resource)
133{
134 switch (resource) {
135 case EglDisplay:
136 return m_eglDisplay;
137 default:
138 break;
139 }
140 return nullptr;
141}
142
143void *QWaylandEglClientBufferIntegration::nativeResourceForContext(NativeResource resource, QPlatformOpenGLContext *context)
144{
145 Q_ASSERT(context);
146 switch (resource) {
147 case EglConfig:
148 return static_cast<QWaylandGLContext *>(context)->eglConfig();
149 case EglContext:
150 return static_cast<QWaylandGLContext *>(context)->eglContext();
151 case EglDisplay:
152 return m_eglDisplay;
153 default:
154 break;
155 }
156 return nullptr;
157}
158
159EGLDisplay QWaylandEglClientBufferIntegration::eglDisplay() const
160{
161 return m_eglDisplay;
162}
163
164}
165
166QT_END_NAMESPACE
167

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp