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
97bool QWaylandEglClientBufferIntegration::isValid() const
98{
99 return m_eglDisplay != EGL_NO_DISPLAY;
100}
101
102bool QWaylandEglClientBufferIntegration::supportsThreadedOpenGL() const
103{
104 return m_supportsThreading;
105}
106
107bool QWaylandEglClientBufferIntegration::supportsWindowDecoration() const
108{
109 return true;
110}
111
112QWaylandWindow *QWaylandEglClientBufferIntegration::createEglWindow(QWindow *window)
113{
114 return new QWaylandEglWindow(window, m_display);
115}
116
117QPlatformOpenGLContext *QWaylandEglClientBufferIntegration::createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const
118{
119 QSurfaceFormat fmt = glFormat;
120 if (m_display->supportsWindowDecoration())
121 fmt.setAlphaBufferSize(8);
122 return new QWaylandGLContext(m_eglDisplay, m_display, fmt, share);
123}
124
125void *QWaylandEglClientBufferIntegration::nativeResource(NativeResource resource)
126{
127 switch (resource) {
128 case EglDisplay:
129 return m_eglDisplay;
130 default:
131 break;
132 }
133 return nullptr;
134}
135
136void *QWaylandEglClientBufferIntegration::nativeResourceForContext(NativeResource resource, QPlatformOpenGLContext *context)
137{
138 Q_ASSERT(context);
139 switch (resource) {
140 case EglConfig:
141 return static_cast<QWaylandGLContext *>(context)->eglConfig();
142 case EglContext:
143 return static_cast<QWaylandGLContext *>(context)->eglContext();
144 case EglDisplay:
145 return m_eglDisplay;
146 default:
147 break;
148 }
149 return nullptr;
150}
151
152EGLDisplay QWaylandEglClientBufferIntegration::eglDisplay() const
153{
154 return m_eglDisplay;
155}
156
157}
158
159QT_END_NAMESPACE
160

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