summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Redondo <[email protected]>2025-02-28 12:14:06 +0100
committerDavid Redondo <[email protected]>2025-03-11 16:45:25 +0100
commit58e68f1981d0ba0a80e373dd5ca78a9260824c36 (patch)
tree76c4faafe64ae628f3b5ef75b4649bd4bed9599f
parentab73b6c286ca79c4ab353e72ce0279ee4f7f5713 (diff)
Move client hardware integration sources into the plugin folder
Change-Id: I49629ce1d55d8762ab30c33062fb78b05fdb05d4 Reviewed-by: Eskil Abrahamsen Blomfeldt <[email protected]>
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/CMakeLists.txt10
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglintegration.cpp121
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglintegration.h68
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglwindow.cpp230
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglwindow.h59
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmglcontext.cpp76
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmglcontext.h48
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/CMakeLists.txt4
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/dmabufserverbufferintegration.cpp152
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/dmabufserverbufferintegration.h111
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/CMakeLists.txt4
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drmeglserverbufferintegration.cpp155
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drmeglserverbufferintegration.h106
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/CMakeLists.txt6
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybriseglserverbufferintegration.cpp167
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybriseglserverbufferintegration.h133
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/CMakeLists.txt4
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/shmserverbufferintegration.cpp107
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/shmserverbufferintegration.h55
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/CMakeLists.txt4
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/vulkanserverbufferintegration.cpp177
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/vulkanserverbufferintegration.h66
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/CMakeLists.txt10
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/main.cpp2
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglclientbufferintegration.cpp166
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglclientbufferintegration_p.h60
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglinclude_p.h27
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglwindow.cpp201
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglwindow_p.h76
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandglcontext.cpp430
-rw-r--r--src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandglcontext_p.h74
31 files changed, 2885 insertions, 24 deletions
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/CMakeLists.txt b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/CMakeLists.txt
index f706632c0a6..ca6c0338614 100644
--- a/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/CMakeLists.txt
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/CMakeLists.txt
@@ -11,12 +11,10 @@ qt_internal_add_plugin(QWaylandBrcmEglClientBufferPlugin
OUTPUT_NAME brcm-egl
PLUGIN_TYPE wayland-graphics-integration-client
SOURCES
- ../../../../hardwareintegration/client/brcm-egl/qwaylandbrcmeglintegration.cpp ../../../../hardwareintegration/client/brcm-egl/qwaylandbrcmeglintegration.h
- ../../../../hardwareintegration/client/brcm-egl/qwaylandbrcmeglwindow.cpp ../../../../hardwareintegration/client/brcm-egl/qwaylandbrcmeglwindow.h
- ../../../../hardwareintegration/client/brcm-egl/qwaylandbrcmglcontext.cpp ../../../../hardwareintegration/client/brcm-egl/qwaylandbrcmglcontext.h
+ qwaylandbrcmeglintegration.cpp qwaylandbrcmeglintegration.h
+ qwaylandbrcmeglwindow.cpp qwaylandbrcmeglwindow.h
+ qwaylandbrcmglcontext.cpp qwaylandbrcmglcontext.h
main.cpp
- INCLUDE_DIRECTORIES
- ../../../../hardwareintegration/client/brcm-egl
PUBLIC_LIBRARIES
${CMAKE_DL_LIBS}
EGL::EGL
@@ -30,7 +28,7 @@ qt_internal_add_plugin(QWaylandBrcmEglClientBufferPlugin
qt6_generate_wayland_protocol_client_sources(QWaylandBrcmEglClientBufferPlugin
PRIVATE_CODE
FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../hardwareintegration/client/brcm-egl/../../../extensions/brcm.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../extensions/brcm.xml
)
#### Keys ignored in scope 1:.:.:brcm-egl.pro:<TRUE>:
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglintegration.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglintegration.cpp
new file mode 100644
index 00000000000..8f9047993ed
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglintegration.cpp
@@ -0,0 +1,121 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandbrcmeglintegration.h"
+
+#include <QtWaylandClient/private/qwaylandclientbufferintegration_p.h>
+
+#include "qwaylandbrcmeglwindow.h"
+#include "qwaylandbrcmglcontext.h"
+
+#include <QtCore/QDebug>
+
+#include "wayland-brcm-client-protocol.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandBrcmEglIntegration::QWaylandBrcmEglIntegration()
+{
+ qDebug() << "Using Brcm-EGL";
+}
+
+void QWaylandBrcmEglIntegration::wlDisplayHandleGlobal(void *data, struct ::wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
+{
+ Q_UNUSED(version);
+ if (interface == "qt_brcm") {
+ QWaylandBrcmEglIntegration *integration = static_cast<QWaylandBrcmEglIntegration *>(data);
+ integration->m_waylandBrcm = static_cast<struct qt_brcm *>(wl_registry_bind(registry, id, &qt_brcm_interface, 1));
+ }
+}
+
+qt_brcm *QWaylandBrcmEglIntegration::waylandBrcm() const
+{
+ return m_waylandBrcm;
+}
+
+QWaylandBrcmEglIntegration::~QWaylandBrcmEglIntegration()
+{
+ eglTerminate(m_eglDisplay);
+}
+
+void QWaylandBrcmEglIntegration::initialize(QWaylandDisplay *waylandDisplay)
+{
+ m_display = waylandDisplay;
+ m_waylandDisplay = waylandDisplay->wl_display();
+ waylandDisplay->addRegistryListener(wlDisplayHandleGlobal, this);
+ EGLint major,minor;
+ m_eglDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
+ if (m_eglDisplay == NULL) {
+ qWarning("EGL not available");
+ } else {
+ if (!eglInitialize(m_eglDisplay, &major, &minor)) {
+ qWarning("failed to initialize EGL display");
+ return;
+ }
+
+ eglFlushBRCM = (PFNEGLFLUSHBRCMPROC)eglGetProcAddress("eglFlushBRCM");
+ if (!eglFlushBRCM) {
+ qWarning("failed to resolve eglFlushBRCM, performance will suffer");
+ }
+
+ eglCreateGlobalImageBRCM = (PFNEGLCREATEGLOBALIMAGEBRCMPROC)eglGetProcAddress("eglCreateGlobalImageBRCM");
+ if (!eglCreateGlobalImageBRCM) {
+ qWarning("failed to resolve eglCreateGlobalImageBRCM");
+ return;
+ }
+
+ eglDestroyGlobalImageBRCM = (PFNEGLDESTROYGLOBALIMAGEBRCMPROC)eglGetProcAddress("eglDestroyGlobalImageBRCM");
+ if (!eglDestroyGlobalImageBRCM) {
+ qWarning("failed to resolve eglDestroyGlobalImageBRCM");
+ return;
+ }
+ }
+}
+
+QWaylandWindow *QWaylandBrcmEglIntegration::createEglWindow(QWindow *window)
+{
+ return new QWaylandBrcmEglWindow(window, m_display);
+}
+
+QPlatformOpenGLContext *QWaylandBrcmEglIntegration::createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const
+{
+ return new QWaylandBrcmGLContext(m_eglDisplay, glFormat, share);
+}
+
+EGLDisplay QWaylandBrcmEglIntegration::eglDisplay() const
+{
+ return m_eglDisplay;
+}
+
+void *QWaylandBrcmEglIntegration::nativeResource(NativeResource resource)
+{
+ switch (resource) {
+ case EglDisplay:
+ return m_eglDisplay;
+ default:
+ break;
+ }
+ return nullptr;
+}
+
+void *QWaylandBrcmEglIntegration::nativeResourceForContext(NativeResource resource, QPlatformOpenGLContext *context)
+{
+ Q_ASSERT(context);
+ switch (resource) {
+ case EglConfig:
+ return static_cast<QWaylandBrcmGLContext *>(context)->eglConfig();
+ case EglContext:
+ return static_cast<QWaylandBrcmGLContext *>(context)->eglContext();
+ case EglDisplay:
+ return m_eglDisplay;
+ default:
+ break;
+ }
+ return nullptr;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglintegration.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglintegration.h
new file mode 100644
index 00000000000..ac164ab9dac
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglintegration.h
@@ -0,0 +1,68 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDBRCMEGLINTEGRATION_H
+#define QWAYLANDBRCMEGLINTEGRATION_H
+
+#include <QtWaylandClient/private/qwaylandclientbufferintegration_p.h>
+#include <QtWaylandClient/private/wayland-wayland-client-protocol.h>
+#include <wayland-client-core.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <EGL/eglext_brcm.h>
+
+#include <QtCore/qglobal.h>
+
+struct qt_brcm;
+
+QT_BEGIN_NAMESPACE
+
+class QWindow;
+
+namespace QtWaylandClient {
+
+class QWaylandWindow;
+
+class QWaylandBrcmEglIntegration : public QWaylandClientBufferIntegration
+{
+public:
+ QWaylandBrcmEglIntegration();
+ ~QWaylandBrcmEglIntegration();
+
+ void initialize(QWaylandDisplay *waylandDisplay) override;
+
+ bool supportsThreadedOpenGL() const override { return true; }
+ bool supportsWindowDecoration() const override { return false; }
+
+ QWaylandWindow *createEglWindow(QWindow *window);
+ QPlatformOpenGLContext *createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const override;
+
+ EGLDisplay eglDisplay() const;
+
+ struct qt_brcm *waylandBrcm() const;
+
+ PFNEGLFLUSHBRCMPROC eglFlushBRCM;
+ PFNEGLCREATEGLOBALIMAGEBRCMPROC eglCreateGlobalImageBRCM;
+ PFNEGLDESTROYGLOBALIMAGEBRCMPROC eglDestroyGlobalImageBRCM;
+
+ void *nativeResource(NativeResource resource) override;
+ void *nativeResourceForContext(NativeResource resource, QPlatformOpenGLContext *context) override;
+
+private:
+ static void wlDisplayHandleGlobal(void *data, struct ::wl_registry *registry, uint32_t id, const QString &interface, uint32_t version);
+
+ struct wl_display *m_waylandDisplay = nullptr;
+ struct qt_brcm *m_waylandBrcm = nullptr;
+
+ EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
+
+ QWaylandDisplay *m_display = nullptr;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDBRCMEGLINTEGRATION_H
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglwindow.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglwindow.cpp
new file mode 100644
index 00000000000..117e57807f6
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglwindow.cpp
@@ -0,0 +1,230 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandbrcmeglwindow.h"
+
+#include <QtWaylandClient/private/qwaylandbuffer_p.h>
+#include <QtWaylandClient/private/qwaylandscreen_p.h>
+#include "qwaylandbrcmglcontext.h"
+
+#include <QtGui/private/qeglconvenience_p.h>
+
+#include <QtGui/QWindow>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <EGL/eglext_brcm.h>
+
+#include "wayland-brcm-client-protocol.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandBrcmBuffer : public QWaylandBuffer
+{
+public:
+ QWaylandBrcmBuffer(QWaylandDisplay *display,
+ struct qt_brcm *brcm,
+ const QSize &size,
+ EGLint *data,
+ int count,
+ struct wl_event_queue *eventQueue)
+ : m_size(size)
+ , m_display(display)
+ , m_eventQueue(eventQueue)
+ {
+ wl_array_init(&m_array);
+ m_data = static_cast<EGLint *>(wl_array_add(&m_array, count * sizeof(EGLint)));
+
+ for (int i = 0; i < count; ++i)
+ m_data[i] = data[i];
+
+ mBuffer = qt_brcm_create_buffer(brcm, size.width(), size.height(), &m_array);
+ wl_proxy_set_queue(reinterpret_cast<struct wl_proxy*>(mBuffer), m_eventQueue);
+
+ static const struct wl_buffer_listener buffer_listener = {
+ QWaylandBrcmBuffer::buffer_release
+ };
+
+ wl_buffer_add_listener(mBuffer, &buffer_listener, this);
+ }
+
+ ~QWaylandBrcmBuffer()
+ {
+ wl_array_release(&m_array);
+ wl_buffer_destroy(mBuffer);
+ mBuffer = nullptr;
+ }
+
+ QSize size() const { return m_size; }
+
+ void bind()
+ {
+ m_released = false;
+ }
+
+ void waitForRelease()
+ {
+ if (m_released)
+ return;
+ while (!m_released) {
+ wl_display_dispatch_queue(m_display->wl_display(), m_eventQueue);
+ }
+ }
+
+ static void buffer_release(void *data, wl_buffer *buffer)
+ {
+ Q_UNUSED(buffer);
+ static_cast<QWaylandBrcmBuffer *>(data)->m_released = true;
+ }
+
+private:
+
+ QSize m_size;
+ bool m_released = true;
+ wl_array m_array;
+ EGLint *m_data = nullptr;
+ QWaylandDisplay *m_display = nullptr;
+ struct wl_event_queue *m_eventQueue = nullptr;
+};
+
+QWaylandBrcmEglWindow::QWaylandBrcmEglWindow(QWindow *window, QWaylandDisplay *display)
+ : QWaylandWindow(window, display)
+ , m_eglIntegration(static_cast<QWaylandBrcmEglIntegration *>(mDisplay->clientBufferIntegration()))
+ , m_format(window->format())
+ , m_eventQueue(wl_display_create_queue(mDisplay->wl_display()))
+{
+}
+
+QWaylandBrcmEglWindow::~QWaylandBrcmEglWindow()
+{
+ destroyEglSurfaces();
+}
+
+QWaylandWindow::WindowType QWaylandBrcmEglWindow::windowType() const
+{
+ return QWaylandWindow::Egl;
+}
+
+void QWaylandBrcmEglWindow::setGeometry(const QRect &rect)
+{
+ destroyEglSurfaces();
+ QWaylandWindow::setGeometry(rect);
+}
+
+QSurfaceFormat QWaylandBrcmEglWindow::format() const
+{
+ return m_format;
+}
+
+void QWaylandBrcmEglWindow::destroyEglSurfaces()
+{
+ for (int i = 0; i < m_count; ++i) {
+ if (m_eglSurfaces[i]) {
+ eglDestroySurface(m_eglIntegration->eglDisplay(), m_eglSurfaces[i]);
+ m_eglSurfaces[i] = 0;
+ // the server does this
+ //m_eglIntegration->eglDestroyGlobalImageBRCM(&m_globalImages[5*i]);
+ delete m_buffers[i];
+ }
+ }
+
+ m_count = 0;
+ m_current = 0;
+}
+
+QSurfaceFormat brcmFixFormat(const QSurfaceFormat &f)
+{
+ QSurfaceFormat format = f;
+ format.setRedBufferSize(8);
+ format.setGreenBufferSize(8);
+ format.setBlueBufferSize(8);
+ format.setAlphaBufferSize(8);
+ return format;
+}
+
+void QWaylandBrcmEglWindow::createEglSurfaces()
+{
+ QSize size(geometry().size());
+
+ m_count = window()->format().swapBehavior() == QSurfaceFormat::TripleBuffer ? 3 : 2;
+
+ EGLConfig eglConfig = q_configFromGLFormat(m_eglIntegration->eglDisplay(), brcmFixFormat(window()->format()), true, EGL_PIXMAP_BIT);
+
+ m_format = q_glFormatFromConfig(m_eglIntegration->eglDisplay(), eglConfig);
+
+ EGLint pixel_format = EGL_PIXEL_FORMAT_ARGB_8888_BRCM;
+
+ EGLint rt;
+ eglGetConfigAttrib(m_eglIntegration->eglDisplay(), eglConfig, EGL_RENDERABLE_TYPE, &rt);
+
+ if (rt & EGL_OPENGL_ES_BIT) {
+ pixel_format |= EGL_PIXEL_FORMAT_RENDER_GLES_BRCM;
+ pixel_format |= EGL_PIXEL_FORMAT_GLES_TEXTURE_BRCM;
+ }
+
+ if (rt & EGL_OPENGL_ES2_BIT) {
+ pixel_format |= EGL_PIXEL_FORMAT_RENDER_GLES2_BRCM;
+ pixel_format |= EGL_PIXEL_FORMAT_GLES2_TEXTURE_BRCM;
+ }
+
+ if (rt & EGL_OPENVG_BIT) {
+ pixel_format |= EGL_PIXEL_FORMAT_RENDER_VG_BRCM;
+ pixel_format |= EGL_PIXEL_FORMAT_VG_IMAGE_BRCM;
+ }
+
+ if (rt & EGL_OPENGL_BIT) {
+ pixel_format |= EGL_PIXEL_FORMAT_RENDER_GL_BRCM;
+ }
+
+ memset(m_globalImages, 0, 5 * m_count * sizeof(EGLint));
+ for (int i = 0; i < m_count; ++i) {
+ m_eglIntegration->eglCreateGlobalImageBRCM(size.width(), size.height(), pixel_format,
+ 0, size.width() * 4, &m_globalImages[5*i]);
+
+ m_globalImages[5*i+2] = size.width();
+ m_globalImages[5*i+3] = size.height();
+ m_globalImages[5*i+4] = pixel_format;
+
+ EGLint attrs[] = {
+ EGL_VG_COLORSPACE, EGL_VG_COLORSPACE_sRGB,
+ EGL_VG_ALPHA_FORMAT, pixel_format & EGL_PIXEL_FORMAT_ARGB_8888_PRE_BRCM ? EGL_VG_ALPHA_FORMAT_PRE : EGL_VG_ALPHA_FORMAT_NONPRE,
+ EGL_NONE
+ };
+
+ m_eglSurfaces[i] = eglCreatePixmapSurface(m_eglIntegration->eglDisplay(), eglConfig, (EGLNativePixmapType)&m_globalImages[5*i], attrs);
+ if (m_eglSurfaces[i] == EGL_NO_SURFACE)
+ qFatal("eglCreatePixmapSurface failed: %x, global image id: %d %d\n", eglGetError(), m_globalImages[5*i], m_globalImages[5*i+1]);
+ m_buffers[i] = new QWaylandBrcmBuffer(mDisplay, m_eglIntegration->waylandBrcm(), size, &m_globalImages[5*i], 5, m_eventQueue);
+ }
+}
+
+void QWaylandBrcmEglWindow::swapBuffers()
+{
+ if (m_eglIntegration->eglFlushBRCM) {
+ m_eglIntegration->eglFlushBRCM();
+ } else {
+ glFlush();
+ glFinish();
+ }
+
+ if (!m_count)
+ return;
+
+ m_buffers[m_current]->bind();
+ commit(m_buffers[m_current], QRegion(0, 0, geometry().size().width(), geometry().size().height()));
+
+ m_current = (m_current + 1) % m_count;
+ m_buffers[m_current]->waitForRelease();
+}
+
+bool QWaylandBrcmEglWindow::makeCurrent(EGLContext context)
+{
+ if (!m_count)
+ const_cast<QWaylandBrcmEglWindow *>(this)->createEglSurfaces();
+ return eglMakeCurrent(m_eglIntegration->eglDisplay(), m_eglSurfaces[m_current], m_eglSurfaces[m_current], context);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglwindow.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglwindow.h
new file mode 100644
index 00000000000..3b9026f9c0a
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmeglwindow.h
@@ -0,0 +1,59 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDBRCMEGLWINDOW_H
+#define QWAYLANDBRCMEGLWINDOW_H
+
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
+#include "qwaylandbrcmeglintegration.h"
+
+#include <QMutex>
+
+#include <EGL/egl.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandBrcmBuffer;
+
+class QWaylandBrcmEglWindow : public QWaylandWindow
+{
+ Q_OBJECT
+public:
+ QWaylandBrcmEglWindow(QWindow *window, QWaylandDisplay *display);
+ ~QWaylandBrcmEglWindow();
+ WindowType windowType() const override;
+ void setGeometry(const QRect &rect) override;
+
+ QSurfaceFormat format() const override;
+
+ bool makeCurrent(EGLContext context);
+ void swapBuffers();
+
+private:
+ void createEglSurfaces();
+ void destroyEglSurfaces();
+
+ QWaylandBrcmEglIntegration *m_eglIntegration = nullptr;
+ struct wl_egl_window *m_waylandEglWindow = nullptr;
+
+ const QWaylandWindow *m_parentWindow = nullptr;
+
+ EGLint m_globalImages[3*5];
+ EGLSurface m_eglSurfaces[3];
+
+ QWaylandBrcmBuffer *m_buffers[3];
+ QSurfaceFormat m_format;
+
+ struct wl_event_queue *m_eventQueue = nullptr;
+
+ int m_current = 0;
+ int m_count = 0;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDBRCMEGLWINDOW_H
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmglcontext.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmglcontext.cpp
new file mode 100644
index 00000000000..66135a7cc43
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmglcontext.cpp
@@ -0,0 +1,76 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandbrcmglcontext.h"
+
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
+#include "qwaylandbrcmeglwindow.h"
+
+#include <QtGui/private/qeglconvenience_p.h>
+
+#include <qpa/qplatformopenglcontext.h>
+#include <QtGui/QSurfaceFormat>
+
+#include <dlfcn.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+extern QSurfaceFormat brcmFixFormat(const QSurfaceFormat &format);
+
+QWaylandBrcmGLContext::QWaylandBrcmGLContext(EGLDisplay eglDisplay, const QSurfaceFormat &format, QPlatformOpenGLContext *share)
+ : QPlatformOpenGLContext()
+ , m_eglDisplay(eglDisplay)
+ , m_config(q_configFromGLFormat(m_eglDisplay, brcmFixFormat(format), true))
+ , m_format(q_glFormatFromConfig(m_eglDisplay, m_config))
+{
+ EGLContext shareEGLContext = share ? static_cast<QWaylandBrcmGLContext *>(share)->eglContext() : EGL_NO_CONTEXT;
+
+ eglBindAPI(EGL_OPENGL_ES_API);
+
+ QList<EGLint> eglContextAttrs;
+ eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
+ eglContextAttrs.append(format.majorVersion() == 1 ? 1 : 2);
+ eglContextAttrs.append(EGL_NONE);
+
+ m_context = eglCreateContext(m_eglDisplay, m_config, shareEGLContext, eglContextAttrs.constData());
+}
+
+QWaylandBrcmGLContext::~QWaylandBrcmGLContext()
+{
+ eglDestroyContext(m_eglDisplay, m_context);
+}
+
+bool QWaylandBrcmGLContext::makeCurrent(QPlatformSurface *surface)
+{
+ return static_cast<QWaylandBrcmEglWindow *>(surface)->makeCurrent(m_context);
+}
+
+void QWaylandBrcmGLContext::doneCurrent()
+{
+ eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+}
+
+void QWaylandBrcmGLContext::swapBuffers(QPlatformSurface *surface)
+{
+ static_cast<QWaylandBrcmEglWindow *>(surface)->swapBuffers();
+}
+
+QFunctionPointer QWaylandBrcmGLContext::getProcAddress(const char *procName)
+{
+ QFunctionPointer proc = (QFunctionPointer) eglGetProcAddress(procName);
+ if (!proc)
+ proc = (QFunctionPointer) dlsym(RTLD_DEFAULT, procName);
+ return proc;
+}
+
+EGLConfig QWaylandBrcmGLContext::eglConfig() const
+{
+ return m_config;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmglcontext.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmglcontext.h
new file mode 100644
index 00000000000..e64a20d9b73
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/qwaylandbrcmglcontext.h
@@ -0,0 +1,48 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWAYLANDBRCMGLCONTEXT_H
+#define QWAYLANDBRCMGLCONTEXT_H
+
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+
+#include <qpa/qplatformopenglcontext.h>
+
+#include <EGL/egl.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class QWaylandWindow;
+
+class QWaylandBrcmGLContext : public QPlatformOpenGLContext {
+public:
+ QWaylandBrcmGLContext(EGLDisplay eglDisplay, const QSurfaceFormat &format, QPlatformOpenGLContext *share);
+ ~QWaylandBrcmGLContext();
+
+ void swapBuffers(QPlatformSurface *surface) override;
+
+ bool makeCurrent(QPlatformSurface *surface) override;
+ void doneCurrent() override;
+
+ QFunctionPointer getProcAddress(const char *procName) override;
+
+ QSurfaceFormat format() const override { return m_format; }
+
+ EGLConfig eglConfig() const;
+ EGLContext eglContext() const { return m_context; }
+
+private:
+ EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
+
+ EGLContext m_context;
+ EGLConfig m_config;
+ QSurfaceFormat m_format;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDBRCMGLCONTEXT_H
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/CMakeLists.txt b/src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/CMakeLists.txt
index 7329aebc323..68c09f76e30 100644
--- a/src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/CMakeLists.txt
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/CMakeLists.txt
@@ -11,10 +11,8 @@ qt_internal_add_plugin(DmaBufServerBufferPlugin
OUTPUT_NAME dmabuf-server
PLUGIN_TYPE wayland-graphics-integration-client
SOURCES
- ../../../../hardwareintegration/client/dmabuf-server/dmabufserverbufferintegration.cpp ../../../../hardwareintegration/client/dmabuf-server/dmabufserverbufferintegration.h
+ dmabufserverbufferintegration.cpp dmabufserverbufferintegration.h
main.cpp
- INCLUDE_DIRECTORIES
- ../../../../hardwareintegration/client/dmabuf-server
LIBRARIES
EGL::EGL
Qt::Core
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/dmabufserverbufferintegration.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/dmabufserverbufferintegration.cpp
new file mode 100644
index 00000000000..54df2badd2e
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/dmabufserverbufferintegration.cpp
@@ -0,0 +1,152 @@
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "dmabufserverbufferintegration.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QDebug>
+#include <QtOpenGL/QOpenGLTexture>
+#include <QtGui/QOpenGLContext>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+DmaBufServerBuffer::DmaBufServerBuffer(DmaBufServerBufferIntegration *integration
+ , struct ::qt_server_buffer *id
+ , int32_t fd
+ , int32_t width
+ , int32_t height
+ , int32_t stride
+ , int32_t offset
+ , int32_t fourcc_format)
+ : m_integration(integration)
+ , m_server_buffer(id)
+{
+ m_size = QSize(width, height);
+
+
+ EGLint import_attribs[] = {
+ EGL_WIDTH, width,
+ EGL_HEIGHT, height,
+ EGL_LINUX_DRM_FOURCC_EXT, fourcc_format,
+ EGL_DMA_BUF_PLANE0_FD_EXT, fd,
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset,
+ EGL_DMA_BUF_PLANE0_PITCH_EXT, stride,
+ EGL_NONE
+ };
+
+ m_image = integration->eglCreateImageKHR(
+ EGL_NO_CONTEXT,
+ EGL_LINUX_DMA_BUF_EXT,
+ (EGLClientBuffer)nullptr,
+ import_attribs);
+
+ int err = eglGetError();
+ qCDebug(lcQpaWayland) << "imported egl image" << m_image;
+ if (m_image == EGL_NO_IMAGE_KHR || err != EGL_SUCCESS)
+ qCWarning(lcQpaWayland) << "DmaBufServerBuffer error importing image. EGL error code" << Qt::hex << err;
+
+ qt_server_buffer_set_user_data(id, this);
+
+}
+
+DmaBufServerBuffer::~DmaBufServerBuffer()
+{
+ int err = m_integration->eglDestroyImageKHR(m_image);
+ if (err != EGL_SUCCESS)
+ qCWarning(lcQpaWayland) << "~DmaBufServerBuffer error destroying image" << m_image << "error code " << Qt::hex << err;
+ qt_server_buffer_release(m_server_buffer);
+ qt_server_buffer_destroy(m_server_buffer);
+}
+
+QOpenGLTexture *DmaBufServerBuffer::toOpenGlTexture()
+{
+ if (!QOpenGLContext::currentContext())
+ qCWarning(lcQpaWayland) <<"DmaBufServerBuffer: creating texture with no current context";
+
+ if (!m_texture) {
+ m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ m_texture->create();
+ }
+
+ m_texture->bind();
+ m_integration->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ m_texture->release();
+ m_texture->setSize(m_size.width(), m_size.height());
+ return m_texture;
+}
+
+void DmaBufServerBufferIntegration::initializeEgl()
+{
+ if (m_egl_initialized)
+ return;
+ m_egl_initialized = true;
+
+ m_egl_display = eglGetDisplay((EGLNativeDisplayType) m_display->wl_display());
+ if (m_egl_display == EGL_NO_DISPLAY) {
+ qCWarning(lcQpaWayland) << "Failed to initialize drm egl server buffer integration. Could not get egl display from wl_display.";
+ return;
+ }
+
+ const char *extensionString = eglQueryString(m_egl_display, EGL_EXTENSIONS);
+
+
+ if (!extensionString || !strstr(extensionString, "EGL_KHR_image")) {
+ qCWarning(lcQpaWayland) << "Failed to initialize dmabuf server buffer integration. There is no EGL_KHR_image extension.\n";
+ return;
+ }
+ m_egl_create_image = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
+ m_egl_destroy_image = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
+ if (!m_egl_create_image || !m_egl_destroy_image) {
+ qCWarning(lcQpaWayland) << "Failed to initialize dmabuf server buffer integration. Could not resolve eglCreateImageKHR or eglDestroyImageKHR";
+ return;
+ }
+
+ m_gl_egl_image_target_texture = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
+ if (!m_gl_egl_image_target_texture) {
+ qCWarning(lcQpaWayland) << "Failed to initialize dmabuf server buffer integration. Could not resolve glEGLImageTargetTexture2DOES";
+ return;
+ }
+}
+
+void DmaBufServerBufferIntegration::initialize(QWaylandDisplay *display)
+{
+ m_display = display;
+ display->addRegistryListener(&wlDisplayHandleGlobal, this);
+}
+
+QWaylandServerBuffer *DmaBufServerBufferIntegration::serverBuffer(struct qt_server_buffer *buffer)
+{
+ return static_cast<QWaylandServerBuffer *>(qt_server_buffer_get_user_data(buffer));
+}
+
+void DmaBufServerBufferIntegration::wlDisplayHandleGlobal(void *data, ::wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
+{
+ Q_UNUSED(version);
+ if (interface == QStringLiteral("qt_dmabuf_server_buffer")) {
+ auto *integration = static_cast<DmaBufServerBufferIntegration *>(data);
+ integration->QtWayland::qt_dmabuf_server_buffer::init(registry, id, 1);
+ }
+}
+
+void DmaBufServerBufferIntegration::dmabuf_server_buffer_server_buffer_created(struct ::qt_server_buffer *id
+ , int32_t name
+ , int32_t width
+ , int32_t height
+ , int32_t stride
+ , int32_t offset
+ , int32_t format)
+{
+ (void) new DmaBufServerBuffer(this, id, name, width, height, stride, offset, format);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/dmabufserverbufferintegration.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/dmabufserverbufferintegration.h
new file mode 100644
index 00000000000..13dbdfbfbab
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/dmabuf-server/dmabufserverbufferintegration.h
@@ -0,0 +1,111 @@
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef DMABUFSERVERBUFFERINTEGRATION_H
+#define DMABUFSERVERBUFFERINTEGRATION_H
+
+#include <QtCore/QVariant>
+#include <QtWaylandClient/private/qwayland-wayland.h>
+#include "qwayland-qt-dmabuf-server-buffer.h"
+#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h>
+
+#include "dmabufserverbufferintegration.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtCore/QTextStream>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#ifndef EGL_KHR_image
+typedef void *EGLImageKHR;
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+#endif
+
+#ifndef GL_OES_EGL_image
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class DmaBufServerBufferIntegration;
+
+class DmaBufServerBuffer : public QWaylandServerBuffer
+{
+public:
+ DmaBufServerBuffer(DmaBufServerBufferIntegration *integration, struct ::qt_server_buffer *id, int32_t fd,
+ int32_t width, int32_t height, int32_t stride, int32_t offset, int32_t fourcc_format);
+ ~DmaBufServerBuffer() override;
+ QOpenGLTexture* toOpenGlTexture() override;
+private:
+ DmaBufServerBufferIntegration *m_integration = nullptr;
+ EGLImageKHR m_image = EGL_NO_IMAGE_KHR;
+ QOpenGLTexture *m_texture = nullptr;
+ struct ::qt_server_buffer *m_server_buffer = nullptr;
+};
+
+class DmaBufServerBufferIntegration
+ : public QWaylandServerBufferIntegration
+ , public QtWayland::qt_dmabuf_server_buffer
+{
+public:
+ void initialize(QWaylandDisplay *display) override;
+
+ QWaylandServerBuffer *serverBuffer(struct qt_server_buffer *buffer) override;
+
+ inline EGLImageKHR eglCreateImageKHR(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+ inline EGLBoolean eglDestroyImageKHR(EGLImageKHR image);
+ inline void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
+protected:
+ void dmabuf_server_buffer_server_buffer_created(struct ::qt_server_buffer *id, int32_t fd,
+ int32_t width, int32_t height, int32_t stride,
+ int32_t offset, int32_t fourcc_format) override;
+
+private:
+ static void wlDisplayHandleGlobal(void *data, struct ::wl_registry *registry, uint32_t id,
+ const QString &interface, uint32_t version);
+ void initializeEgl();
+
+ PFNEGLCREATEIMAGEKHRPROC m_egl_create_image = nullptr;
+ PFNEGLDESTROYIMAGEKHRPROC m_egl_destroy_image = nullptr;
+ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_gl_egl_image_target_texture = nullptr;
+ QWaylandDisplay *m_display = nullptr;
+ EGLDisplay m_egl_display = EGL_NO_DISPLAY;
+ bool m_egl_initialized = false;
+};
+
+EGLImageKHR DmaBufServerBufferIntegration::eglCreateImageKHR(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+ if (!m_egl_initialized)
+ initializeEgl();
+ if (!m_egl_create_image) {
+ qCWarning(lcQpaWayland) << "DmaBufServerBufferIntegration: Trying to use unresolved function eglCreateImageKHR";
+ return EGL_NO_IMAGE_KHR;
+ }
+ return m_egl_create_image(m_egl_display, ctx, target, buffer, attrib_list);
+}
+
+EGLBoolean DmaBufServerBufferIntegration::eglDestroyImageKHR(EGLImageKHR image)
+{
+ if (!m_egl_destroy_image) {
+ qCWarning(lcQpaWayland) << "DmaBufServerBufferIntegration: Trying to use unresolved function eglDestroyImageKHR";
+ return false;
+ }
+ return m_egl_destroy_image(m_egl_display, image);
+}
+
+void DmaBufServerBufferIntegration::glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
+{
+ if (!m_gl_egl_image_target_texture) {
+ qCWarning(lcQpaWayland) << "DmaBufServerBufferIntegration: Trying to use unresolved function glEGLImageTargetTexture2DOES";
+ return;
+ }
+ m_gl_egl_image_target_texture(target, image);
+}
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/CMakeLists.txt b/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/CMakeLists.txt
index 535b1024f0f..c552a9b2878 100644
--- a/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/CMakeLists.txt
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/CMakeLists.txt
@@ -11,10 +11,8 @@ qt_internal_add_plugin(DrmEglServerBufferPlugin
OUTPUT_NAME drm-egl-server
PLUGIN_TYPE wayland-graphics-integration-client
SOURCES
- ../../../../hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.cpp ../../../../hardwareintegration/client/drm-egl-server/drmeglserverbufferintegration.h
+ drmeglserverbufferintegration.cpp drmeglserverbufferintegration.h
main.cpp
- INCLUDE_DIRECTORIES
- ../../../../hardwareintegration/client/drm-egl-server
LIBRARIES
EGL::EGL
Qt::Core
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drmeglserverbufferintegration.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drmeglserverbufferintegration.cpp
new file mode 100644
index 00000000000..16a3aa4cf51
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drmeglserverbufferintegration.cpp
@@ -0,0 +1,155 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "drmeglserverbufferintegration.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QDebug>
+#include <QtOpenGL/QOpenGLTexture>
+#include <QtGui/QOpenGLContext>
+
+#include <EGL/egl.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+DrmServerBuffer::DrmServerBuffer(DrmEglServerBufferIntegration *integration
+ , int32_t name
+ , int32_t width
+ , int32_t height
+ , int32_t stride
+ , int32_t format)
+ : m_integration(integration)
+{
+ m_size = QSize(width, height);
+ EGLint egl_format;
+ int32_t format_stride;
+ switch (format) {
+ case QtWayland::qt_drm_egl_server_buffer::format_RGBA32:
+ m_format = QWaylandServerBuffer::RGBA32;
+ egl_format = EGL_DRM_BUFFER_FORMAT_ARGB32_MESA;
+ format_stride = stride / 4;
+ break;
+#ifdef EGL_DRM_BUFFER_FORMAT_A8_MESA
+ case QtWayland::qt_drm_egl_server_buffer::format_A8:
+ m_format = QWaylandServerBuffer::A8;
+ egl_format = EGL_DRM_BUFFER_FORMAT_A8_MESA;
+ format_stride = stride;
+ break;
+#endif
+ default:
+ qWarning("DrmServerBuffer: unknown format");
+ m_format = QWaylandServerBuffer::RGBA32;
+ egl_format = EGL_DRM_BUFFER_FORMAT_ARGB32_MESA;
+ format_stride = stride / 4;
+ break;
+ }
+ EGLint attribs[] = {
+ EGL_WIDTH, width,
+ EGL_HEIGHT, height,
+ EGL_DRM_BUFFER_STRIDE_MESA, format_stride,
+ EGL_DRM_BUFFER_FORMAT_MESA, egl_format,
+ EGL_NONE
+ };
+
+ qintptr name_pointer = name;
+ m_image = integration->eglCreateImageKHR(EGL_NO_CONTEXT, EGL_DRM_BUFFER_MESA, (EGLClientBuffer) name_pointer, attribs);
+
+}
+
+DrmServerBuffer::~DrmServerBuffer()
+{
+ m_integration->eglDestroyImageKHR(m_image);
+}
+
+QOpenGLTexture *DrmServerBuffer::toOpenGlTexture()
+{
+ if (!QOpenGLContext::currentContext())
+ qWarning("DrmServerBuffer: creating texture with no current context");
+
+ if (!m_texture) {
+ m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ m_texture->create();
+ }
+
+ m_texture->bind();
+ m_integration->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ m_texture->release();
+ m_texture->setSize(m_size.width(), m_size.height());
+ return m_texture;
+}
+
+void DrmEglServerBufferIntegration::initializeEgl()
+{
+ if (m_egl_initialized)
+ return;
+ m_egl_initialized = true;
+
+#if QT_CONFIG(egl_extension_platform_wayland)
+ m_egl_display = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_EXT, m_display->wl_display(), nullptr);
+#else
+ m_egl_display = eglGetDisplay((EGLNativeDisplayType) m_display->wl_display());
+#endif
+ if (m_egl_display == EGL_NO_DISPLAY) {
+ qWarning("Failed to initialize drm egl server buffer integration. Could not get egl display from wl_display.");
+ return;
+ }
+
+ const char *extensionString = eglQueryString(m_egl_display, EGL_EXTENSIONS);
+ if (!extensionString || !strstr(extensionString, "EGL_KHR_image")) {
+ qWarning("Failed to initialize drm egl server buffer integration. There is no EGL_KHR_image extension.\n");
+ return;
+ }
+ m_egl_create_image = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
+ m_egl_destroy_image = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
+ if (!m_egl_create_image || !m_egl_destroy_image) {
+ qWarning("Failed to initialize drm egl server buffer integration. Could not resolve eglCreateImageKHR or eglDestroyImageKHR");
+ return;
+ }
+
+ m_gl_egl_image_target_texture = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
+ if (!m_gl_egl_image_target_texture) {
+ qWarning("Failed to initialize drm egl server buffer integration. Could not resolve glEGLImageTargetTexture2DOES");
+ return;
+ }
+ m_egl_initialized = true;
+}
+
+void DrmEglServerBufferIntegration::initialize(QWaylandDisplay *display)
+{
+ m_display = display;
+ display->addRegistryListener(&wlDisplayHandleGlobal, this);
+}
+
+QWaylandServerBuffer *DrmEglServerBufferIntegration::serverBuffer(struct qt_server_buffer *buffer)
+{
+ return static_cast<QWaylandServerBuffer *>(qt_server_buffer_get_user_data(buffer));
+}
+
+void DrmEglServerBufferIntegration::wlDisplayHandleGlobal(void *data, ::wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
+{
+ Q_UNUSED(version);
+ if (interface == QStringLiteral("qt_drm_egl_server_buffer")) {
+ auto *integration = static_cast<DrmEglServerBufferIntegration *>(data);
+ integration->QtWayland::qt_drm_egl_server_buffer::init(registry, id, 1);
+ }
+}
+
+void DrmEglServerBufferIntegration::drm_egl_server_buffer_server_buffer_created(struct ::qt_server_buffer *id
+ , int32_t name
+ , int32_t width
+ , int32_t height
+ , int32_t stride
+ , int32_t format)
+{
+ DrmServerBuffer *server_buffer = new DrmServerBuffer(this, name, width, height, stride, format);
+ qt_server_buffer_set_user_data(id, server_buffer);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drmeglserverbufferintegration.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drmeglserverbufferintegration.h
new file mode 100644
index 00000000000..a06bc96b87d
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drmeglserverbufferintegration.h
@@ -0,0 +1,106 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef DRMEGLSERVERBUFFERINTEGRATION_H
+#define DRMEGLSERVERBUFFERINTEGRATION_H
+
+#include <QtWaylandClient/private/qwayland-wayland.h>
+#include <QtCore/QVariant>
+#include "qwayland-drm-egl-server-buffer.h"
+#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h>
+
+#include "drmeglserverbufferintegration.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtCore/QTextStream>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#ifndef EGL_KHR_image
+typedef void *EGLImageKHR;
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+#endif
+
+#ifndef GL_OES_EGL_image
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class DrmEglServerBufferIntegration;
+
+class DrmServerBuffer : public QWaylandServerBuffer
+{
+public:
+ DrmServerBuffer(DrmEglServerBufferIntegration *integration, int32_t name, int32_t width, int32_t height, int32_t stride, int32_t format);
+ ~DrmServerBuffer() override;
+ QOpenGLTexture* toOpenGlTexture() override;
+private:
+ DrmEglServerBufferIntegration *m_integration = nullptr;
+ EGLImageKHR m_image;
+ QOpenGLTexture *m_texture = nullptr;
+};
+
+class DrmEglServerBufferIntegration
+ : public QWaylandServerBufferIntegration
+ , public QtWayland::qt_drm_egl_server_buffer
+{
+public:
+ void initialize(QWaylandDisplay *display) override;
+
+ QWaylandServerBuffer *serverBuffer(struct qt_server_buffer *buffer) override;
+
+ inline EGLImageKHR eglCreateImageKHR(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+ inline EGLBoolean eglDestroyImageKHR (EGLImageKHR image);
+ inline void glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+protected:
+ void drm_egl_server_buffer_server_buffer_created(struct ::qt_server_buffer *id, int32_t name, int32_t width, int32_t height, int32_t stride, int32_t format) override;
+private:
+ static void wlDisplayHandleGlobal(void *data, struct ::wl_registry *registry, uint32_t id,
+ const QString &interface, uint32_t version);
+ void initializeEgl();
+
+ PFNEGLCREATEIMAGEKHRPROC m_egl_create_image;
+ PFNEGLDESTROYIMAGEKHRPROC m_egl_destroy_image;
+ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_gl_egl_image_target_texture;
+ QWaylandDisplay *m_display = nullptr;
+ EGLDisplay m_egl_display = EGL_NO_DISPLAY;
+ bool m_egl_initialized = false;
+};
+
+EGLImageKHR DrmEglServerBufferIntegration::eglCreateImageKHR(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+ if (!m_egl_initialized)
+ initializeEgl();
+ if (!m_egl_create_image) {
+ qWarning("DrmEglServerBufferIntegration: Trying to used unresolved function eglCreateImageKHR");
+ return EGL_NO_IMAGE_KHR;
+ }
+ return m_egl_create_image(m_egl_display, ctx, target, buffer,attrib_list);
+}
+
+EGLBoolean DrmEglServerBufferIntegration::eglDestroyImageKHR (EGLImageKHR image)
+{
+ if (!m_egl_destroy_image) {
+ qWarning("DrmEglServerBufferIntegration: Trying to use unresolved function eglDestroyImageKHR");
+ return false;
+ }
+ return m_egl_destroy_image(m_egl_display, image);
+}
+
+void DrmEglServerBufferIntegration::glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
+{
+ if (!m_gl_egl_image_target_texture) {
+ qWarning("DrmEglServerBufferIntegration: Trying to use unresolved function glEGLImageTargetRenderbufferStorageOES");
+ return;
+ }
+ m_gl_egl_image_target_texture(target,image);
+}
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/CMakeLists.txt b/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/CMakeLists.txt
index 6b7cd897e19..351f8f6d3f4 100644
--- a/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/CMakeLists.txt
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/CMakeLists.txt
@@ -11,10 +11,8 @@ qt_internal_add_plugin(LibHybrisEglServerBufferPlugin
OUTPUT_NAME libhybris-egl-server
PLUGIN_TYPE wayland-graphics-integration-client
SOURCES
- ../../../../hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.cpp ../../../../hardwareintegration/client/libhybris-egl-server/libhybriseglserverbufferintegration.h
+ libhybriseglserverbufferintegration.cpp libhybriseglserverbufferintegration.h
main.cpp
- INCLUDE_DIRECTORIES
- ../../../../hardwareintegration/client/libhybris-egl-server
PUBLIC_LIBRARIES
EGL::EGL
Qt::Core
@@ -27,7 +25,7 @@ qt_internal_add_plugin(LibHybrisEglServerBufferPlugin
qt6_generate_wayland_protocol_client_sources(LibHybrisEglServerBufferPlugin
PRIVATE_CODE
FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../hardwareintegration/client/libhybris-egl-server/../../../extensions/libhybris-egl-server-buffer.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../extensions/libhybris-egl-server-buffer.xml
)
#### Keys ignored in scope 1:.:.:libhybris-egl-server.pro:<TRUE>:
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybriseglserverbufferintegration.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybriseglserverbufferintegration.cpp
new file mode 100644
index 00000000000..54081de97af
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybriseglserverbufferintegration.cpp
@@ -0,0 +1,167 @@
+// Copyright (C) 2016 Jolla Ltd, author: <[email protected]>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "libhybriseglserverbufferintegration.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QDebug>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLTexture>
+#include <hybris/eglplatformcommon/hybris_nativebufferext.h>
+
+#include <EGL/egl.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+LibHybrisServerBuffer::LibHybrisServerBuffer(LibHybrisEglServerBufferIntegration *integration
+ , int32_t numFds
+ , wl_array *ints
+ , int32_t name
+ , int32_t width
+ , int32_t height
+ , int32_t stride
+ , int32_t format)
+ : QWaylandServerBuffer()
+ , m_integration(integration)
+ , m_stride(stride)
+ , m_hybrisFormat(format)
+{
+ m_numFds = numFds;
+ m_fds.reserve(numFds);
+ m_ints.resize(ints->size / sizeof(int32_t));
+ memcpy(m_ints.data(), ints->data, ints->size);
+ m_image = 0;
+
+ m_size = QSize(width, height);
+}
+
+LibHybrisServerBuffer::~LibHybrisServerBuffer()
+{
+ m_integration->eglDestroyImageKHR(m_image);
+}
+
+QOpenGLTexture * LibHybrisServerBuffer::toOpenGlTexture()
+{
+ if (!QOpenGLContext::currentContext()) {
+ qWarning("LibHybrisServerBuffer: creating texture with no current context");
+ }
+
+ if (!m_texture) {
+ m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ m_texture->create();
+ }
+
+ m_texture->bind();
+ m_integration->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ m_texture->release();
+ m_texture->setSize(m_size.width(), m_size.height());
+
+ return m_texture;
+}
+
+void LibHybrisServerBuffer::libhybris_buffer_add_fd(int32_t fd)
+{
+ m_fds << fd;
+
+ if (m_fds.size() == m_numFds) {
+ EGLint egl_format;
+ switch (m_hybrisFormat) {
+ case QtWayland::qt_libhybris_egl_server_buffer::format_RGBA32:
+ m_format = QWaylandServerBuffer::RGBA32;
+ egl_format = HYBRIS_PIXEL_FORMAT_RGBA_8888;
+ break;
+ default:
+ qWarning("LibHybrisServerBuffer: unknown format");
+ m_format = QWaylandServerBuffer::RGBA32;
+ egl_format = HYBRIS_PIXEL_FORMAT_RGBA_8888;
+ break;
+ }
+
+ EGLClientBuffer buf;
+ m_integration->eglHybrisCreateRemoteBuffer(m_size.width(), m_size.height(), HYBRIS_USAGE_HW_TEXTURE, egl_format, m_stride, m_ints.size(), m_ints.data(), m_fds.size(), m_fds.data(), &buf);
+ m_image = m_integration->eglCreateImageKHR(EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, buf, 0);
+ }
+}
+
+void LibHybrisEglServerBufferIntegration::initializeEgl()
+{
+ if (m_egl_initialized)
+ return;
+ m_egl_initialized = true;
+
+ m_egl_display = eglGetDisplay((EGLNativeDisplayType) m_display->wl_display());
+ if (m_egl_display == EGL_NO_DISPLAY) {
+ qWarning("Failed to initialize libhybris egl server buffer integration. Could not get egl display from wl_display.");
+ return;
+ }
+
+ const char *extensionString = eglQueryString(m_egl_display, EGL_EXTENSIONS);
+ if (!extensionString || !strstr(extensionString, "EGL_KHR_image")) {
+ qWarning("Failed to initialize libhybris egl server buffer integration. There is no EGL_KHR_image extension.\n");
+ return;
+ }
+ m_egl_create_image = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
+ m_egl_destroy_image = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
+ if (!m_egl_create_image || !m_egl_destroy_image) {
+ qWarning("Failed to initialize libhybris egl server buffer integration. Could not resolve eglCreateImageKHR or eglDestroyImageKHR");
+ return;
+ }
+
+ m_gl_egl_image_target_texture = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
+ if (!m_gl_egl_image_target_texture) {
+ qWarning("Failed to initialize libhybris egl server buffer integration. Could not resolve glEGLImageTargetTexture2DOES");
+ return;
+ }
+
+ m_egl_create_buffer = reinterpret_cast<PFNEGLHYBRISCREATEREMOTEBUFFERPROC>(eglGetProcAddress("eglHybrisCreateRemoteBuffer"));
+ if (!m_egl_create_buffer) {
+ qWarning("Failed to initialize libhybris egl server buffer integration. Could not resolve eglHybrisCreateRemoteBuffer");
+ return;
+ }
+ m_egl_initialized = true;
+}
+
+void LibHybrisEglServerBufferIntegration::initialize(QWaylandDisplay *display)
+{
+ m_display = display;
+ display->addRegistryListener(&wlDisplayHandleGlobal, this);
+}
+
+QWaylandServerBuffer *LibHybrisEglServerBufferIntegration::serverBuffer(struct qt_server_buffer *buffer)
+{
+ return static_cast<QWaylandServerBuffer *>(qt_server_buffer_get_user_data(buffer));
+}
+
+void LibHybrisEglServerBufferIntegration::wlDisplayHandleGlobal(void *data, ::wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
+{
+ Q_UNUSED(version);
+ if (interface == QStringLiteral("qt_libhybris_egl_server_buffer")) {
+ auto *integration = static_cast<LibHybrisEglServerBufferIntegration *>(data);
+ integration->QtWayland::qt_libhybris_egl_server_buffer::init(registry, id, 1);
+ }
+}
+
+void LibHybrisEglServerBufferIntegration::libhybris_egl_server_buffer_server_buffer_created(struct ::qt_libhybris_buffer *id
+ , struct ::qt_server_buffer *qid
+ , int32_t numFds
+ , wl_array *ints
+ , int32_t name
+ , int32_t width
+ , int32_t height
+ , int32_t stride
+ , int32_t format)
+{
+ LibHybrisServerBuffer *server_buffer = new LibHybrisServerBuffer(this, numFds, ints, name, width, height, stride, format);
+ server_buffer->QtWayland::qt_libhybris_buffer::init(id);
+ qt_server_buffer_set_user_data(qid, server_buffer);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybriseglserverbufferintegration.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybriseglserverbufferintegration.h
new file mode 100644
index 00000000000..7fd4a2abbf8
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybriseglserverbufferintegration.h
@@ -0,0 +1,133 @@
+// Copyright (C) 2016 Jolla Ltd, author: <[email protected]>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef LIBHYBRISEGLSERVERBUFFERINTEGRATION_H
+#define LIBHYBRISEGLSERVERBUFFERINTEGRATION_H
+
+#include <QtWaylandClient/private/qwayland-wayland.h>
+#include "qwayland-libhybris-egl-server-buffer.h"
+#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h>
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtCore/QList>
+#include <QtCore/QTextStream>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#ifndef EGL_KHR_image
+typedef void *EGLImageKHR;
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+#endif
+
+#ifndef GL_OES_EGL_image
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+#ifndef EGL_HYBRIS_native_buffer
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLHYBRISCREATEREMOTEBUFFERPROC)(EGLint width, EGLint height, EGLint usage, EGLint format, EGLint stride,
+ int num_ints, int *ints, int num_fds, int *fds, EGLClientBuffer *buffer);
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class LibHybrisEglServerBufferIntegration;
+
+class LibHybrisServerBuffer : public QWaylandServerBuffer, public QtWayland::qt_libhybris_buffer
+{
+public:
+ LibHybrisServerBuffer(LibHybrisEglServerBufferIntegration *integration, int32_t numFds, wl_array *ints, int32_t name, int32_t width, int32_t height, int32_t stride, int32_t format);
+ ~LibHybrisServerBuffer();
+ QOpenGLTexture* toOpenGlTexture() override;
+
+protected:
+ void libhybris_buffer_add_fd(int32_t fd) override;
+
+private:
+ LibHybrisEglServerBufferIntegration *m_integration = nullptr;
+ EGLImageKHR m_image;
+ QOpenGLTexture *m_texture = nullptr;
+ int m_numFds;
+ QList<int32_t> m_ints;
+ QList<int32_t> m_fds;
+ int32_t m_stride;
+ int32_t m_hybrisFormat;
+};
+
+class LibHybrisEglServerBufferIntegration
+ : public QWaylandServerBufferIntegration
+ , public QtWayland::qt_libhybris_egl_server_buffer
+{
+public:
+ void initialize(QWaylandDisplay *display) override;
+
+ virtual QWaylandServerBuffer *serverBuffer(struct qt_server_buffer *buffer) override;
+
+ inline EGLImageKHR eglCreateImageKHR(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+ inline EGLBoolean eglDestroyImageKHR (EGLImageKHR image);
+ inline void glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+ inline EGLBoolean eglHybrisCreateRemoteBuffer(EGLint width, EGLint height, EGLint usage, EGLint format, EGLint stride, int num_ints, int *ints, int num_fds, int *fds, EGLClientBuffer *buffer);
+
+protected:
+ void libhybris_egl_server_buffer_server_buffer_created(struct ::qt_libhybris_buffer *id, struct ::qt_server_buffer *qid,
+ int32_t numFds, wl_array *ints, int32_t name, int32_t width, int32_t height, int32_t stride, int32_t format) override;
+private:
+ static void wlDisplayHandleGlobal(void *data, struct ::wl_registry *registry, uint32_t id,
+ const QString &interface, uint32_t version);
+ void initializeEgl();
+
+ PFNEGLCREATEIMAGEKHRPROC m_egl_create_image;
+ PFNEGLDESTROYIMAGEKHRPROC m_egl_destroy_image;
+ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_gl_egl_image_target_texture;
+ PFNEGLHYBRISCREATEREMOTEBUFFERPROC m_egl_create_buffer;
+ QWaylandDisplay *m_display = nullptr;
+ EGLDisplay m_egl_display = EGL_NO_DISPLAY;
+ bool m_egl_initialized = false;
+};
+
+EGLImageKHR LibHybrisEglServerBufferIntegration::eglCreateImageKHR(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+ if (!m_egl_initialized)
+ initializeEgl();
+
+ if (!m_egl_create_image) {
+ qWarning("LibHybrisEglServerBufferIntegration: Trying to used unresolved function eglCreateImageKHR");
+ return EGL_NO_IMAGE_KHR;
+ }
+ return m_egl_create_image(m_egl_display, ctx, target, buffer,attrib_list);
+}
+
+EGLBoolean LibHybrisEglServerBufferIntegration::eglDestroyImageKHR (EGLImageKHR image)
+{
+ if (!m_egl_destroy_image) {
+ qWarning("LibHybrisEglServerBufferIntegration: Trying to use unresolved function eglDestroyImageKHR");
+ return false;
+ }
+ return m_egl_destroy_image(m_egl_display, image);
+}
+
+void LibHybrisEglServerBufferIntegration::glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
+{
+ if (!m_gl_egl_image_target_texture) {
+ qWarning("LibHybrisEglServerBufferIntegration: Trying to use unresolved function glEGLImageTargetRenderbufferStorageOES");
+ return;
+ }
+ m_gl_egl_image_target_texture(target,image);
+}
+
+EGLBoolean LibHybrisEglServerBufferIntegration::eglHybrisCreateRemoteBuffer(EGLint width, EGLint height, EGLint usage, EGLint format, EGLint stride,
+ int num_ints, int *ints, int num_fds, int *fds, EGLClientBuffer *buffer)
+{
+ if (!m_egl_create_buffer) {
+ qWarning("LibHybrisEglServerBufferIntegration: Trying to use unresolved function eglHybrisCreateRemoteBuffer");
+ return false;
+ }
+ return m_egl_create_buffer(width, height, usage, format, stride, num_ints, ints, num_fds, fds, buffer);
+}
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/CMakeLists.txt b/src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/CMakeLists.txt
index b979086d2c7..8f20ada4cb4 100644
--- a/src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/CMakeLists.txt
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/CMakeLists.txt
@@ -11,10 +11,8 @@ qt_internal_add_plugin(ShmServerBufferPlugin
OUTPUT_NAME shm-emulation-server
PLUGIN_TYPE wayland-graphics-integration-client
SOURCES
- ../../../../hardwareintegration/client/shm-emulation-server/shmserverbufferintegration.cpp ../../../../hardwareintegration/client/shm-emulation-server/shmserverbufferintegration.h
+ shmserverbufferintegration.cpp shmserverbufferintegration.h
main.cpp
- INCLUDE_DIRECTORIES
- ../../../../hardwareintegration/client/shm-emulation-server
LIBRARIES
Qt::Core
Qt::Gui
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/shmserverbufferintegration.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/shmserverbufferintegration.cpp
new file mode 100644
index 00000000000..38065dbde16
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/shmserverbufferintegration.cpp
@@ -0,0 +1,107 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "shmserverbufferintegration.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QDebug>
+#include <QtOpenGL/QOpenGLTexture>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QImage>
+#include <QtCore/QSharedMemory>
+
+QT_BEGIN_NAMESPACE
+
+static QOpenGLTexture *createTextureFromShm(const QString &key, int w, int h, int bpl, int format)
+{
+ QT_IGNORE_DEPRECATIONS(QSharedMemory shm(key);)
+ bool ok;
+ ok = shm.attach(QSharedMemory::ReadOnly);
+ if (!ok) {
+ qWarning() << "Could not attach to" << key;
+ return nullptr;
+ }
+ ok = shm.lock();
+ if (!ok) {
+ qWarning() << "Could not lock" << key << "for reading";
+ return nullptr;
+ }
+
+ QImage::Format imageFormat;
+ switch (format) {
+ case QtWayland::qt_shm_emulation_server_buffer::format_RGBA32:
+ imageFormat = QImage::Format_RGBA8888;
+ break;
+ case QtWayland::qt_shm_emulation_server_buffer::format_A8:
+ imageFormat = QImage::Format_Alpha8;
+ break;
+ default:
+ qWarning() << "ShmServerBuffer: unknown format" << format;
+ imageFormat = QImage::Format_RGBA8888;
+ break;
+ }
+
+ QImage image(static_cast<const uchar*>(shm.constData()), w, h, bpl, imageFormat);
+
+ if (!QOpenGLContext::currentContext())
+ qWarning("ShmServerBuffer: creating texture with no current context");
+
+ auto *tex = new QOpenGLTexture(image, QOpenGLTexture::DontGenerateMipMaps);
+ shm.unlock();
+ return tex;
+}
+
+
+namespace QtWaylandClient {
+
+ShmServerBuffer::ShmServerBuffer(const QString &key, const QSize& size, int bytesPerLine, QWaylandServerBuffer::Format format)
+ : m_key(key)
+ , m_bpl(bytesPerLine)
+{
+ m_format = format;
+ m_size = size;
+}
+
+ShmServerBuffer::~ShmServerBuffer()
+{
+}
+
+QOpenGLTexture *ShmServerBuffer::toOpenGlTexture()
+{
+ if (!m_texture)
+ m_texture = createTextureFromShm(m_key, m_size.width(), m_size.height(), m_bpl, m_format);
+
+ return m_texture;
+}
+
+void ShmServerBufferIntegration::initialize(QWaylandDisplay *display)
+{
+ m_display = display;
+ display->addRegistryListener(&wlDisplayHandleGlobal, this);
+}
+
+QWaylandServerBuffer *ShmServerBufferIntegration::serverBuffer(struct qt_server_buffer *buffer)
+{
+ return static_cast<QWaylandServerBuffer *>(qt_server_buffer_get_user_data(buffer));
+}
+
+void ShmServerBufferIntegration::wlDisplayHandleGlobal(void *data, ::wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
+{
+ Q_UNUSED(version);
+ if (interface == "qt_shm_emulation_server_buffer") {
+ auto *integration = static_cast<ShmServerBufferIntegration *>(data);
+ integration->QtWayland::qt_shm_emulation_server_buffer::init(registry, id, 1);
+ }
+}
+
+
+void QtWaylandClient::ShmServerBufferIntegration::shm_emulation_server_buffer_server_buffer_created(qt_server_buffer *id, const QString &key, int32_t width, int32_t height, int32_t bytes_per_line, int32_t format)
+{
+ QSize size(width, height);
+ auto fmt = QWaylandServerBuffer::Format(format);
+ auto *server_buffer = new ShmServerBuffer(key, size, bytes_per_line, fmt);
+ qt_server_buffer_set_user_data(id, server_buffer);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/shmserverbufferintegration.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/shmserverbufferintegration.h
new file mode 100644
index 00000000000..344046ae182
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/shm-emulation-server/shmserverbufferintegration.h
@@ -0,0 +1,55 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef SHMSERVERBUFFERINTEGRATION_H
+#define SHMSERVERBUFFERINTEGRATION_H
+
+#include <QtWaylandClient/private/qwayland-wayland.h>
+#include "qwayland-shm-emulation-server-buffer.h"
+#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h>
+
+#include "shmserverbufferintegration.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtCore/QTextStream>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class ShmServerBufferIntegration;
+
+class ShmServerBuffer : public QWaylandServerBuffer
+{
+public:
+ ShmServerBuffer(const QString &key, const QSize &size, int bytesPerLine, QWaylandServerBuffer::Format format);
+ ~ShmServerBuffer() override;
+ QOpenGLTexture* toOpenGlTexture() override;
+private:
+ QOpenGLTexture *m_texture = nullptr;
+ QString m_key;
+ int m_bpl;
+};
+
+class ShmServerBufferIntegration
+ : public QWaylandServerBufferIntegration
+ , public QtWayland::qt_shm_emulation_server_buffer
+{
+public:
+ void initialize(QWaylandDisplay *display) override;
+
+ QWaylandServerBuffer *serverBuffer(struct qt_server_buffer *buffer) override;
+
+protected:
+ void shm_emulation_server_buffer_server_buffer_created(qt_server_buffer *id, const QString &key, int32_t width, int32_t height, int32_t bytes_per_line, int32_t format) override;
+
+private:
+ static void wlDisplayHandleGlobal(void *data, struct ::wl_registry *registry, uint32_t id,
+ const QString &interface, uint32_t version);
+ QWaylandDisplay *m_display = nullptr;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/CMakeLists.txt b/src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/CMakeLists.txt
index f0aeabf291a..34ce655330b 100644
--- a/src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/CMakeLists.txt
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/CMakeLists.txt
@@ -11,10 +11,8 @@ qt_internal_add_plugin(VulkanServerBufferPlugin
OUTPUT_NAME vulkan-server
PLUGIN_TYPE wayland-graphics-integration-client
SOURCES
- ../../../../hardwareintegration/client/vulkan-server/vulkanserverbufferintegration.cpp ../../../../hardwareintegration/client/vulkan-server/vulkanserverbufferintegration.h
+ vulkanserverbufferintegration.cpp vulkanserverbufferintegration.h
main.cpp
- INCLUDE_DIRECTORIES
- ../../../../hardwareintegration/client/vulkan-server
LIBRARIES
Qt::Core
Qt::Gui
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/vulkanserverbufferintegration.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/vulkanserverbufferintegration.cpp
new file mode 100644
index 00000000000..8f1ff9a46d3
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/vulkanserverbufferintegration.cpp
@@ -0,0 +1,177 @@
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "vulkanserverbufferintegration.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QDebug>
+#include <QtOpenGL/QOpenGLTexture>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/qopengl.h>
+#include <QtGui/QImage>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+static constexpr bool sbiExtraDebug =
+#ifdef VULKAN_SERVER_BUFFER_EXTRA_DEBUG
+ true;
+#else
+ false;
+#endif
+
+#define DECL_GL_FUNCTION(name, type) \
+ type name
+
+#define FIND_GL_FUNCTION(name, type) \
+ do { \
+ name = reinterpret_cast<type>(glContext->getProcAddress(#name)); \
+ if (!name) { \
+ qWarning() << "ERROR in GL proc lookup. Could not find " #name; \
+ return false; \
+ } \
+ } while (0)
+
+struct VulkanServerBufferGlFunctions
+{
+ DECL_GL_FUNCTION(glCreateMemoryObjectsEXT, PFNGLCREATEMEMORYOBJECTSEXTPROC);
+ DECL_GL_FUNCTION(glImportMemoryFdEXT, PFNGLIMPORTMEMORYFDEXTPROC);
+ DECL_GL_FUNCTION(glTextureStorageMem2DEXT, PFNGLTEXTURESTORAGEMEM2DEXTPROC);
+ DECL_GL_FUNCTION(glTexStorageMem2DEXT, PFNGLTEXSTORAGEMEM2DEXTPROC);
+ DECL_GL_FUNCTION(glDeleteMemoryObjectsEXT, PFNGLDELETEMEMORYOBJECTSEXTPROC);
+
+ bool init(QOpenGLContext *glContext)
+ {
+ FIND_GL_FUNCTION(glCreateMemoryObjectsEXT, PFNGLCREATEMEMORYOBJECTSEXTPROC);
+ FIND_GL_FUNCTION(glImportMemoryFdEXT, PFNGLIMPORTMEMORYFDEXTPROC);
+ FIND_GL_FUNCTION(glTextureStorageMem2DEXT, PFNGLTEXTURESTORAGEMEM2DEXTPROC);
+ FIND_GL_FUNCTION(glTexStorageMem2DEXT, PFNGLTEXSTORAGEMEM2DEXTPROC);
+ FIND_GL_FUNCTION(glDeleteMemoryObjectsEXT, PFNGLDELETEMEMORYOBJECTSEXTPROC);
+
+ return true;
+ }
+ static bool create(QOpenGLContext *glContext);
+};
+
+static VulkanServerBufferGlFunctions *funcs = nullptr;
+
+bool VulkanServerBufferGlFunctions::create(QOpenGLContext *glContext)
+{
+ if (funcs)
+ return true;
+ funcs = new VulkanServerBufferGlFunctions;
+ if (!funcs->init(glContext)) {
+ delete funcs;
+ funcs = nullptr;
+ return false;
+ }
+ return true;
+}
+
+VulkanServerBuffer::VulkanServerBuffer(VulkanServerBufferIntegration *integration, struct ::qt_server_buffer *id,
+ int32_t fd, uint32_t width, uint32_t height, uint32_t memory_size, uint32_t format)
+ : m_integration(integration)
+ , m_server_buffer(id)
+ , m_fd(fd)
+ , m_memorySize(memory_size)
+ , m_internalFormat(format)
+{
+ m_size = QSize(width, height);
+}
+
+VulkanServerBuffer::~VulkanServerBuffer()
+{
+ if (QCoreApplication::closingDown())
+ return; // can't trust anything at this point
+
+ if (m_texture) { //only do gl cleanup if import has been called
+ m_integration->deleteGLTextureWhenPossible(m_texture);
+
+ if (sbiExtraDebug) qDebug() << "glDeleteMemoryObjectsEXT" << m_memoryObject;
+ funcs->glDeleteMemoryObjectsEXT(1, &m_memoryObject);
+ }
+ qt_server_buffer_release(m_server_buffer);
+ qt_server_buffer_destroy(m_server_buffer);
+}
+
+void VulkanServerBuffer::import()
+{
+ if (m_texture)
+ return;
+
+ if (sbiExtraDebug) qDebug() << "importing" << m_fd << Qt::hex << glGetError();
+
+ auto *glContext = QOpenGLContext::currentContext();
+ if (!glContext)
+ return;
+
+ if (!funcs && !VulkanServerBufferGlFunctions::create(glContext))
+ return;
+
+ funcs->glCreateMemoryObjectsEXT(1, &m_memoryObject);
+ if (sbiExtraDebug) qDebug() << "glCreateMemoryObjectsEXT" << Qt::hex << glGetError();
+ funcs->glImportMemoryFdEXT(m_memoryObject, m_memorySize, GL_HANDLE_TYPE_OPAQUE_FD_EXT, m_fd);
+ if (sbiExtraDebug) qDebug() << "glImportMemoryFdEXT" << Qt::hex << glGetError();
+
+
+ m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ m_texture->create();
+
+ if (sbiExtraDebug) qDebug() << "created texture" << m_texture->textureId() << Qt::hex << glGetError();
+
+ m_texture->bind();
+ if (sbiExtraDebug) qDebug() << "bound texture" << Qt::hex << glGetError();
+ funcs->glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, m_internalFormat, m_size.width(), m_size.height(), m_memoryObject, 0 );
+ if (sbiExtraDebug) qDebug() << "glTexStorageMem2DEXT" << Qt::hex << glGetError();
+ if (sbiExtraDebug) qDebug() << "format" << Qt::hex << m_internalFormat << GL_RGBA8;
+}
+
+QOpenGLTexture *VulkanServerBuffer::toOpenGlTexture()
+{
+ m_integration->deleteOrphanedTextures();
+ if (!m_texture)
+ import();
+ return m_texture;
+}
+
+void VulkanServerBufferIntegration::initialize(QWaylandDisplay *display)
+{
+ m_display = display;
+ display->addRegistryListener(&wlDisplayHandleGlobal, this);
+}
+
+QWaylandServerBuffer *VulkanServerBufferIntegration::serverBuffer(struct qt_server_buffer *buffer)
+{
+ return static_cast<QWaylandServerBuffer *>(qt_server_buffer_get_user_data(buffer));
+}
+
+void VulkanServerBufferIntegration::wlDisplayHandleGlobal(void *data, ::wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
+{
+ Q_UNUSED(version);
+ if (interface == "zqt_vulkan_server_buffer_v1") {
+ auto *integration = static_cast<VulkanServerBufferIntegration *>(data);
+ integration->QtWayland::zqt_vulkan_server_buffer_v1::init(registry, id, 1);
+ }
+}
+
+void VulkanServerBufferIntegration::zqt_vulkan_server_buffer_v1_server_buffer_created(qt_server_buffer *id, int32_t fd, uint32_t width, uint32_t height, uint32_t memory_size, uint32_t format)
+{
+ if (sbiExtraDebug) qDebug() << "vulkan_server_buffer_server_buffer_created" << fd;
+ auto *server_buffer = new VulkanServerBuffer(this, id, fd, width, height, memory_size, format);
+ qt_server_buffer_set_user_data(id, server_buffer);
+}
+
+void VulkanServerBufferIntegration::deleteOrphanedTextures()
+{
+ if (!QOpenGLContext::currentContext()) {
+ qWarning("VulkanServerBufferIntegration::deleteOrphanedTextures with no current context!");
+ return;
+ }
+ qDeleteAll(orphanedTextures);
+ orphanedTextures.clear();
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/vulkanserverbufferintegration.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/vulkanserverbufferintegration.h
new file mode 100644
index 00000000000..2f0867a8197
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/vulkan-server/vulkanserverbufferintegration.h
@@ -0,0 +1,66 @@
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef VULKANSERVERBUFFERINTEGRATION_H
+#define VULKANSERVERBUFFERINTEGRATION_H
+
+#include <QtWaylandClient/private/qwayland-wayland.h>
+#include "qwayland-qt-vulkan-server-buffer-unstable-v1.h"
+#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h>
+
+#include "vulkanserverbufferintegration.h"
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtCore/QTextStream>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class VulkanServerBufferIntegration;
+
+class VulkanServerBuffer : public QWaylandServerBuffer
+{
+public:
+ VulkanServerBuffer(VulkanServerBufferIntegration *integration, struct ::qt_server_buffer *id, int32_t fd, uint32_t width, uint32_t height, uint32_t memory_size, uint32_t format);
+ ~VulkanServerBuffer() override;
+ QOpenGLTexture* toOpenGlTexture() override;
+
+private:
+ void import();
+
+ VulkanServerBufferIntegration *m_integration = nullptr;
+ struct ::qt_server_buffer *m_server_buffer = nullptr;
+ QOpenGLTexture *m_texture = nullptr;
+ int m_fd = -1;
+ uint m_memorySize = 0;
+ uint m_internalFormat = 0;
+ GLuint m_memoryObject = 0;
+};
+
+class VulkanServerBufferIntegration
+ : public QWaylandServerBufferIntegration
+ , public QtWayland::zqt_vulkan_server_buffer_v1
+{
+public:
+ void initialize(QWaylandDisplay *display) override;
+
+ QWaylandServerBuffer *serverBuffer(struct qt_server_buffer *buffer) override;
+
+ void deleteGLTextureWhenPossible(QOpenGLTexture *texture) { orphanedTextures << texture; }
+ void deleteOrphanedTextures();
+
+protected:
+ void zqt_vulkan_server_buffer_v1_server_buffer_created(qt_server_buffer *id, int32_t fd, uint32_t width, uint32_t height, uint32_t memory_size, uint32_t format) override;
+
+private:
+ static void wlDisplayHandleGlobal(void *data, struct ::wl_registry *registry, uint32_t id,
+ const QString &interface, uint32_t version);
+ QWaylandDisplay *m_display = nullptr;
+ QList<QOpenGLTexture *> orphanedTextures;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/CMakeLists.txt b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/CMakeLists.txt
index e75ce07e530..ef3df07a434 100644
--- a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/CMakeLists.txt
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/CMakeLists.txt
@@ -13,11 +13,19 @@ qt_internal_add_plugin(QWaylandEglClientBufferPlugin
PLUGIN_TYPE wayland-graphics-integration-client
SOURCES
main.cpp
+ qwaylandeglclientbufferintegration.cpp qwaylandeglclientbufferintegration_p.h
+ qwaylandeglinclude_p.h
+ qwaylandeglwindow.cpp qwaylandeglwindow_p.h
+ qwaylandglcontext.cpp qwaylandglcontext_p.h
LIBRARIES
+ ${CMAKE_DL_LIBS}
+ EGL::EGL
Qt::Core
Qt::Gui
+ Qt::OpenGLPrivate
Qt::WaylandClientPrivate
- Qt::WaylandEglClientHwIntegrationPrivate
+ Wayland::Client
+ Wayland::Egl
QT_LICENSE_ID QT_COMMERCIAL_OR_LGPL3
)
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/main.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/main.cpp
index 9d4fd95edd3..4cb5930bc3b 100644
--- a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/main.cpp
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/main.cpp
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtWaylandClient/private/qwaylandclientbufferintegrationplugin_p.h>
-#include <QtWaylandEglClientHwIntegration/private/qwaylandeglclientbufferintegration_p.h>
+#include "qwaylandeglclientbufferintegration_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglclientbufferintegration.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglclientbufferintegration.cpp
new file mode 100644
index 00000000000..3b97aef208b
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglclientbufferintegration.cpp
@@ -0,0 +1,166 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandeglclientbufferintegration_p.h"
+
+#include "qwaylandeglwindow_p.h"
+#include "qwaylandglcontext_p.h"
+
+#include <wayland-client-core.h>
+
+#include <QtCore/QDebug>
+#include <private/qeglconvenience_p.h>
+
+#ifndef EGL_EXT_platform_base
+typedef EGLDisplay (*PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
+#endif
+
+#ifndef EGL_PLATFORM_WAYLAND_KHR
+#define EGL_PLATFORM_WAYLAND_KHR 0x31D8
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+static const char *qwaylandegl_threadedgl_blacklist_vendor[] = {
+ 0
+};
+
+QWaylandEglClientBufferIntegration::QWaylandEglClientBufferIntegration()
+{
+ qCDebug(lcQpaWayland) << "Using Wayland-EGL";
+}
+
+
+QWaylandEglClientBufferIntegration::~QWaylandEglClientBufferIntegration()
+{
+ eglTerminate(m_eglDisplay);
+}
+
+void QWaylandEglClientBufferIntegration::initialize(QWaylandDisplay *display)
+{
+#if QT_CONFIG(egl_extension_platform_wayland)
+ m_eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_EXT, display->wl_display(), nullptr);
+#else
+ if (q_hasEglExtension(EGL_NO_DISPLAY, "EGL_EXT_platform_base")) {
+ if (q_hasEglExtension(EGL_NO_DISPLAY, "EGL_KHR_platform_wayland") ||
+ q_hasEglExtension(EGL_NO_DISPLAY, "EGL_EXT_platform_wayland") ||
+ q_hasEglExtension(EGL_NO_DISPLAY, "EGL_MESA_platform_wayland")) {
+
+ static PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplay = nullptr;
+ if (!eglGetPlatformDisplay)
+ eglGetPlatformDisplay = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
+
+ m_eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, display->wl_display(), nullptr);
+ } else {
+ qCWarning(lcQpaWayland) << "The EGL implementation does not support the Wayland platform";
+ return;
+ }
+ } else {
+ QByteArray eglPlatform = qgetenv("EGL_PLATFORM");
+ if (eglPlatform.isEmpty()) {
+ setenv("EGL_PLATFORM","wayland",true);
+ }
+
+ m_eglDisplay = eglGetDisplay((EGLNativeDisplayType) display->wl_display());
+ }
+#endif
+
+ m_display = display;
+
+ if (m_eglDisplay == EGL_NO_DISPLAY) {
+ qCWarning(lcQpaWayland) << "EGL not available";
+ return;
+ }
+
+ EGLint major,minor;
+ if (!eglInitialize(m_eglDisplay, &major, &minor)) {
+ qCWarning(lcQpaWayland) << "Failed to initialize EGL display" << Qt::hex << eglGetError();
+ m_eglDisplay = EGL_NO_DISPLAY;
+ return;
+ }
+
+ m_supportsThreading = true;
+ if (qEnvironmentVariableIsSet("QT_OPENGL_NO_SANITY_CHECK"))
+ return;
+
+ const char *vendor = eglQueryString(m_eglDisplay, EGL_VENDOR);
+ for (int i = 0; qwaylandegl_threadedgl_blacklist_vendor[i]; ++i) {
+ if (strstr(vendor, qwaylandegl_threadedgl_blacklist_vendor[i]) != 0) {
+ m_supportsThreading = false;
+ break;
+ }
+ }
+
+ // On desktop NVIDIA resizing QtQuick freezes them when using threaded rendering QTBUG-95817
+ // In order to support threaded rendering on embedded platforms where resizing is not needed
+ // we check if XDG_CURRENT_DESKTOP is set which desktop environments should set
+ if (qstrcmp(vendor, "NVIDIA") == 0 && qEnvironmentVariableIsSet("XDG_CURRENT_DESKTOP")) {
+ m_supportsThreading = false;
+ }
+}
+
+bool QWaylandEglClientBufferIntegration::isValid() const
+{
+ return m_eglDisplay != EGL_NO_DISPLAY;
+}
+
+bool QWaylandEglClientBufferIntegration::supportsThreadedOpenGL() const
+{
+ return m_supportsThreading;
+}
+
+bool QWaylandEglClientBufferIntegration::supportsWindowDecoration() const
+{
+ return true;
+}
+
+QWaylandWindow *QWaylandEglClientBufferIntegration::createEglWindow(QWindow *window)
+{
+ return new QWaylandEglWindow(window, m_display);
+}
+
+QPlatformOpenGLContext *QWaylandEglClientBufferIntegration::createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const
+{
+ QSurfaceFormat fmt = glFormat;
+ if (m_display->supportsWindowDecoration())
+ fmt.setAlphaBufferSize(8);
+ return new QWaylandGLContext(m_eglDisplay, m_display, fmt, share);
+}
+
+void *QWaylandEglClientBufferIntegration::nativeResource(NativeResource resource)
+{
+ switch (resource) {
+ case EglDisplay:
+ return m_eglDisplay;
+ default:
+ break;
+ }
+ return nullptr;
+}
+
+void *QWaylandEglClientBufferIntegration::nativeResourceForContext(NativeResource resource, QPlatformOpenGLContext *context)
+{
+ Q_ASSERT(context);
+ switch (resource) {
+ case EglConfig:
+ return static_cast<QWaylandGLContext *>(context)->eglConfig();
+ case EglContext:
+ return static_cast<QWaylandGLContext *>(context)->eglContext();
+ case EglDisplay:
+ return m_eglDisplay;
+ default:
+ break;
+ }
+ return nullptr;
+}
+
+EGLDisplay QWaylandEglClientBufferIntegration::eglDisplay() const
+{
+ return m_eglDisplay;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglclientbufferintegration_p.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglclientbufferintegration_p.h
new file mode 100644
index 00000000000..ed8fdec2d94
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglclientbufferintegration_p.h
@@ -0,0 +1,60 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QWAYLANDEGLINTEGRATION_H
+#define QWAYLANDEGLINTEGRATION_H
+
+#include <QtWaylandClient/private/qwaylandclientbufferintegration_p.h>
+
+#include "qwaylandeglinclude_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWindow;
+
+namespace QtWaylandClient {
+
+class QWaylandWindow;
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandEglClientBufferIntegration : public QWaylandClientBufferIntegration
+{
+public:
+ QWaylandEglClientBufferIntegration();
+ ~QWaylandEglClientBufferIntegration() override;
+
+ void initialize(QWaylandDisplay *display) override;
+ bool isValid() const override;
+ bool supportsThreadedOpenGL() const override;
+ bool supportsWindowDecoration() const override;
+
+ QWaylandWindow *createEglWindow(QWindow *window) override;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const override;
+
+ void *nativeResource(NativeResource resource) override;
+ void *nativeResourceForContext(NativeResource resource, QPlatformOpenGLContext *context) override;
+
+ EGLDisplay eglDisplay() const;
+
+private:
+ QWaylandDisplay *m_display = nullptr;
+
+ EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
+ bool m_supportsThreading = false;
+};
+
+QT_END_NAMESPACE
+
+}
+
+#endif // QWAYLANDEGLINTEGRATION_H
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglinclude_p.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglinclude_p.h
new file mode 100644
index 00000000000..eb52ce8eecd
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglinclude_p.h
@@ -0,0 +1,27 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QWAYLANDEGLINCLUDE_H
+#define QWAYLANDEGLINCLUDE_H
+
+#include <string.h>
+#include <wayland-client-core.h>
+
+#include <wayland-egl.h>
+
+#define EGL_EGLEXT_PROTOTYPES
+#include <QtGui/private/qt_egl_p.h>
+
+#endif // QWAYLANDEGLINCLUDE_H
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglwindow.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglwindow.cpp
new file mode 100644
index 00000000000..8375d0e196d
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglwindow.cpp
@@ -0,0 +1,201 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandeglwindow_p.h"
+
+#include <QtWaylandClient/private/qwaylandscreen_p.h>
+#include <QtWaylandClient/private/qwaylandsurface_p.h>
+#include "qwaylandglcontext_p.h"
+
+#include <QtGui/private/qeglconvenience_p.h>
+
+#include <QDebug>
+#include <QtGui/QWindow>
+#include <qpa/qwindowsysteminterface.h>
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLContext>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+QWaylandEglWindow::QWaylandEglWindow(QWindow *window, QWaylandDisplay *display)
+ : QWaylandWindow(window, display)
+ , m_clientBufferIntegration(static_cast<QWaylandEglClientBufferIntegration *>(mDisplay->clientBufferIntegration()))
+{
+ connect(display, &QWaylandDisplay::connected, this, [this] {
+ m_clientBufferIntegration = static_cast<QWaylandEglClientBufferIntegration *>(
+ mDisplay->clientBufferIntegration());
+ });
+ ensureSize();
+}
+
+QWaylandEglWindow::~QWaylandEglWindow()
+{
+ if (m_eglSurface) {
+ eglDestroySurface(m_clientBufferIntegration->eglDisplay(), m_eglSurface);
+ m_eglSurface = 0;
+ }
+
+ if (m_waylandEglWindow)
+ wl_egl_window_destroy(m_waylandEglWindow);
+
+ delete m_contentFBO;
+}
+
+QWaylandWindow::WindowType QWaylandEglWindow::windowType() const
+{
+ return QWaylandWindow::Egl;
+}
+
+void QWaylandEglWindow::ensureSize()
+{
+ // this is always called on the main thread
+ QRect rect = geometry();
+ QMargins margins = clientSideMargins();
+ QSize sizeWithMargins = (rect.size() + QSize(margins.left() + margins.right(), margins.top() + margins.bottom())) * scale();
+ {
+ QWriteLocker lock(&m_bufferSizeLock);
+ m_bufferSize = sizeWithMargins;
+ }
+
+ QMutexLocker lock (&m_eglSurfaceLock);
+ updateSurface(false);
+}
+
+void QWaylandEglWindow::updateSurface(bool create)
+{
+ // eglSurfaceLock should be locked before calling this method
+
+ QSize sizeWithMargins;
+ {
+ QReadLocker lock(&m_bufferSizeLock);
+ sizeWithMargins = m_bufferSize;
+ }
+
+ // wl_egl_windows must have both width and height > 0
+ // mesa's egl returns NULL if we try to create a, invalid wl_egl_window, however not all EGL
+ // implementations may do that, so check the size ourself. Besides, we must deal with resizing
+ // a valid window to 0x0, which would make it invalid. Hence, destroy it.
+ if (sizeWithMargins.isEmpty()) {
+ if (m_eglSurface) {
+ eglDestroySurface(m_clientBufferIntegration->eglDisplay(), m_eglSurface);
+ m_eglSurface = 0;
+ }
+ if (m_waylandEglWindow) {
+ wl_egl_window_destroy(m_waylandEglWindow);
+ m_waylandEglWindow = 0;
+ }
+ mOffset = QPoint();
+ } else {
+ QReadLocker locker(&mSurfaceLock);
+ if (m_waylandEglWindow) {
+ int current_width = 0;
+ int current_height = 0;
+ static bool disableResizeCheck = qgetenv("QT_WAYLAND_DISABLE_RESIZECHECK").toInt();
+
+ if (!disableResizeCheck) {
+ wl_egl_window_get_attached_size(m_waylandEglWindow, &current_width, &current_height);
+ }
+ if (disableResizeCheck || (current_width != sizeWithMargins.width() || current_height != sizeWithMargins.height()) || m_requestedSize != sizeWithMargins) {
+ wl_egl_window_resize(m_waylandEglWindow, sizeWithMargins.width(), sizeWithMargins.height(), mOffset.x(), mOffset.y());
+ m_requestedSize = sizeWithMargins;
+ mOffset = QPoint();
+
+ m_resize = true;
+ }
+ } else if (create && mSurface) {
+ wl_egl_window *eglWindow = wl_egl_window_create(mSurface->object(), sizeWithMargins.width(), sizeWithMargins.height());
+ if (Q_UNLIKELY(!eglWindow)) {
+ qCWarning(lcQpaWayland, "Could not create wl_egl_window with size %dx%d\n", sizeWithMargins.width(), sizeWithMargins.height());
+ return;
+ }
+
+ QSurfaceFormat fmt = window()->requestedFormat();
+ if (mDisplay->supportsWindowDecoration())
+ fmt.setAlphaBufferSize(8);
+ EGLConfig eglConfig = q_configFromGLFormat(m_clientBufferIntegration->eglDisplay(), fmt);
+ setFormat(q_glFormatFromConfig(m_clientBufferIntegration->eglDisplay(), eglConfig, fmt));
+
+ EGLSurface eglSurface = eglCreateWindowSurface(m_clientBufferIntegration->eglDisplay(), eglConfig, (EGLNativeWindowType) eglWindow, 0);
+ if (Q_UNLIKELY(eglSurface == EGL_NO_SURFACE)) {
+ qCWarning(lcQpaWayland, "Could not create EGL surface (EGL error 0x%x)\n", eglGetError());
+ wl_egl_window_destroy(eglWindow);
+ return;
+ }
+
+ m_waylandEglWindow = eglWindow;
+ m_eglSurface = eglSurface;
+ m_requestedSize = sizeWithMargins;
+ }
+ }
+}
+
+QRect QWaylandEglWindow::contentsRect() const
+{
+ QRect r = geometry();
+ QMargins m = clientSideMargins();
+ return QRect(m.left(), m.bottom(), r.width(), r.height());
+}
+
+void QWaylandEglWindow::invalidateSurface()
+{
+ QMutexLocker lock (&m_eglSurfaceLock);
+
+ if (m_eglSurface) {
+ eglDestroySurface(m_clientBufferIntegration->eglDisplay(), m_eglSurface);
+ m_eglSurface = 0;
+ }
+ if (m_waylandEglWindow) {
+ wl_egl_window_destroy(m_waylandEglWindow);
+ m_waylandEglWindow = nullptr;
+ }
+ delete m_contentFBO;
+ m_contentFBO = nullptr;
+}
+
+EGLSurface QWaylandEglWindow::eglSurface() const
+{
+ return m_eglSurface;
+}
+
+QMutex* QWaylandEglWindow::eglSurfaceLock()
+{
+ return &m_eglSurfaceLock;
+}
+
+GLuint QWaylandEglWindow::contentFBO() const
+{
+ if (!decoration())
+ return 0;
+
+ if (m_resize || !m_contentFBO) {
+ QOpenGLFramebufferObject *old = m_contentFBO;
+ QSize fboSize = geometry().size() * scale();
+ m_contentFBO = new QOpenGLFramebufferObject(fboSize.width(), fboSize.height(), QOpenGLFramebufferObject::CombinedDepthStencil);
+
+ delete old;
+ m_resize = false;
+ }
+
+ return m_contentFBO->handle();
+}
+
+GLuint QWaylandEglWindow::contentTexture() const
+{
+ return m_contentFBO->texture();
+}
+
+void QWaylandEglWindow::bindContentFBO()
+{
+ if (decoration()) {
+ contentFBO();
+ m_contentFBO->bind();
+ }
+}
+
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qwaylandeglwindow_p.cpp"
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglwindow_p.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglwindow_p.h
new file mode 100644
index 00000000000..dc2e0319519
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandeglwindow_p.h
@@ -0,0 +1,76 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QWAYLANDEGLWINDOW_H
+#define QWAYLANDEGLWINDOW_H
+
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
+#include "qwaylandeglinclude_p.h"
+#include "qwaylandeglclientbufferintegration_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLFramebufferObject;
+
+namespace QtWaylandClient {
+
+class QWaylandGLContext;
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandEglWindow : public QWaylandWindow
+{
+ Q_OBJECT
+public:
+ QWaylandEglWindow(QWindow *window, QWaylandDisplay *display);
+ ~QWaylandEglWindow();
+ WindowType windowType() const override;
+ void ensureSize() override;
+
+ void updateSurface(bool create);
+ QRect contentsRect() const;
+
+ EGLSurface eglSurface() const;
+ GLuint contentFBO() const;
+ GLuint contentTexture() const;
+ bool needToUpdateContentFBO() const { return decoration() && (m_resize || !m_contentFBO); }
+
+ void bindContentFBO();
+
+ void invalidateSurface() override;
+
+ QMutex* eglSurfaceLock();
+
+private:
+ QWaylandEglClientBufferIntegration *m_clientBufferIntegration = nullptr;
+ struct wl_egl_window *m_waylandEglWindow = nullptr;
+
+ // Locks any manipulation of the eglSurface size
+ QMutex m_eglSurfaceLock;
+ EGLSurface m_eglSurface = EGL_NO_SURFACE;
+ mutable bool m_resize = false;
+ mutable QOpenGLFramebufferObject *m_contentFBO = nullptr;
+
+ // Size used in the last call to wl_egl_window_resize
+ QSize m_requestedSize;
+
+ // Size of the buffer used by QWaylandWindow
+ // This is always written to from the main thread, potentially read from the rendering thread
+ QReadWriteLock m_bufferSizeLock;
+ QSize m_bufferSize;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDEGLWINDOW_H
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandglcontext.cpp b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandglcontext.cpp
new file mode 100644
index 00000000000..be5a36fa01a
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandglcontext.cpp
@@ -0,0 +1,430 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwaylandglcontext_p.h"
+
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
+#include <QtWaylandClient/private/qwaylandsubsurface_p.h>
+#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h>
+#include <QtWaylandClient/private/qwaylandintegration_p.h>
+#include "qwaylandeglwindow_p.h"
+
+#include <QDebug>
+#include <QtGui/private/qeglconvenience_p.h>
+#include <QtGui/private/qopenglcontext_p.h>
+#include <QtOpenGL/private/qopengltexturecache_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+
+#include <qpa/qplatformopenglcontext.h>
+#include <QtGui/QSurfaceFormat>
+#include <QtOpenGL/QOpenGLShaderProgram>
+#include <QtGui/QOpenGLFunctions>
+#include <QOpenGLBuffer>
+
+#include <QtCore/qmutex.h>
+
+#include <dlfcn.h>
+
+// Constants from EGL_KHR_create_context
+#ifndef EGL_CONTEXT_MINOR_VERSION_KHR
+#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
+#endif
+#ifndef EGL_CONTEXT_FLAGS_KHR
+#define EGL_CONTEXT_FLAGS_KHR 0x30FC
+#endif
+#ifndef EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
+#endif
+#ifndef EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
+#endif
+#ifndef EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
+#endif
+#ifndef EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
+#endif
+#ifndef EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
+#endif
+
+// Constants for OpenGL which are not available in the ES headers.
+#ifndef GL_CONTEXT_FLAGS
+#define GL_CONTEXT_FLAGS 0x821E
+#endif
+#ifndef GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
+#endif
+#ifndef GL_CONTEXT_FLAG_DEBUG_BIT
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#endif
+#ifndef GL_CONTEXT_PROFILE_MASK
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#endif
+#ifndef GL_CONTEXT_CORE_PROFILE_BIT
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#endif
+#ifndef GL_CONTEXT_COMPATIBILITY_PROFILE_BIT
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWaylandClient {
+
+class DecorationsBlitter : public QOpenGLFunctions
+{
+public:
+ DecorationsBlitter(QWaylandGLContext *context)
+ : m_context(context)
+ {
+ initializeOpenGLFunctions();
+ m_blitProgram = new QOpenGLShaderProgram();
+ m_blitProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, "attribute vec4 position;\n\
+ attribute vec4 texCoords;\n\
+ varying vec2 outTexCoords;\n\
+ void main()\n\
+ {\n\
+ gl_Position = position;\n\
+ outTexCoords = texCoords.xy;\n\
+ }");
+ m_blitProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, "varying highp vec2 outTexCoords;\n\
+ uniform sampler2D texture;\n\
+ void main()\n\
+ {\n\
+ gl_FragColor = texture2D(texture, outTexCoords);\n\
+ }");
+
+ m_blitProgram->bindAttributeLocation("position", 0);
+ m_blitProgram->bindAttributeLocation("texCoords", 1);
+
+ if (!m_blitProgram->link()) {
+ qDebug() << "Shader Program link failed.";
+ qDebug() << m_blitProgram->log();
+ }
+
+ m_blitProgram->bind();
+ m_blitProgram->enableAttributeArray(0);
+ m_blitProgram->enableAttributeArray(1);
+
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_SCISSOR_TEST);
+ glDepthMask(GL_FALSE);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ m_buffer.create();
+ m_buffer.bind();
+
+ static const GLfloat squareVertices[] = {
+ -1.f, -1.f,
+ 1.0f, -1.f,
+ -1.f, 1.0f,
+ 1.0f, 1.0f
+ };
+ static const GLfloat inverseSquareVertices[] = {
+ -1.f, 1.f,
+ 1.f, 1.f,
+ -1.f, -1.f,
+ 1.f, -1.f
+ };
+ static const GLfloat textureVertices[] = {
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ };
+
+ m_squareVerticesOffset = 0;
+ m_inverseSquareVerticesOffset = sizeof(squareVertices);
+ m_textureVerticesOffset = sizeof(squareVertices) + sizeof(textureVertices);
+
+ m_buffer.allocate(sizeof(squareVertices) + sizeof(inverseSquareVertices) + sizeof(textureVertices));
+ m_buffer.write(m_squareVerticesOffset, squareVertices, sizeof(squareVertices));
+ m_buffer.write(m_inverseSquareVerticesOffset, inverseSquareVertices, sizeof(inverseSquareVertices));
+ m_buffer.write(m_textureVerticesOffset, textureVertices, sizeof(textureVertices));
+
+ m_blitProgram->setAttributeBuffer(1, GL_FLOAT, m_textureVerticesOffset, 2);
+
+ m_textureWrap = m_context->context()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat) ? GL_REPEAT : GL_CLAMP_TO_EDGE;
+ }
+ ~DecorationsBlitter()
+ {
+ delete m_blitProgram;
+ }
+ void blit(QWaylandEglWindow *window)
+ {
+ QOpenGLTextureCache *cache = QOpenGLTextureCache::cacheForContext(m_context->context());
+
+ QSize surfaceSize = window->surfaceSize();
+ qreal scale = window->scale() ;
+ glViewport(0, 0, surfaceSize.width() * scale, surfaceSize.height() * scale);
+
+ //Draw Decoration
+ if (auto *decoration = window->decoration()) {
+ m_blitProgram->setAttributeBuffer(0, GL_FLOAT, m_inverseSquareVerticesOffset, 2);
+ QImage decorationImage = decoration->contentImage();
+ cache->bindTexture(m_context->context(), decorationImage);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_textureWrap);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_textureWrap);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+
+ //Draw Content
+ m_blitProgram->setAttributeBuffer(0, GL_FLOAT, m_squareVerticesOffset, 2);
+ glBindTexture(GL_TEXTURE_2D, window->contentTexture());
+ QRect r = window->contentsRect();
+ glViewport(r.x() * scale, r.y() * scale, r.width() * scale, r.height() * scale);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+
+ QOpenGLShaderProgram *m_blitProgram = nullptr;
+ QWaylandGLContext *m_context = nullptr;
+ QOpenGLBuffer m_buffer;
+ int m_squareVerticesOffset;
+ int m_inverseSquareVerticesOffset;
+ int m_textureVerticesOffset;
+ int m_textureWrap;
+};
+
+QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *display,
+ const QSurfaceFormat &fmt, QPlatformOpenGLContext *share)
+ : QEGLPlatformContext(fmt, share, eglDisplay)
+ , m_display(display)
+ , m_decorationsContext(EGL_NO_CONTEXT)
+{
+ m_reconnectionWatcher = QObject::connect(m_display, &QWaylandDisplay::connected,
+ m_display, [this] { invalidateContext(); });
+
+ switch (format().renderableType()) {
+ case QSurfaceFormat::OpenVG:
+ m_api = EGL_OPENVG_API;
+ break;
+#ifdef EGL_VERSION_1_4
+ case QSurfaceFormat::OpenGL:
+ m_api = EGL_OPENGL_API;
+ break;
+#endif // EGL_VERSION_1_4
+ default:
+ m_api = EGL_OPENGL_ES_API;
+ break;
+ }
+
+ if (m_display->supportsWindowDecoration()) {
+ // Create an EGL context for the decorations blitter. By using a dedicated context we are free to
+ // change its state and we also use OpenGL ES 2 API independently to what the app is using to draw.
+ QList<EGLint> eglDecorationsContextAttrs = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+ m_decorationsContext = eglCreateContext(eglDisplay, eglConfig(), eglContext(),
+ eglDecorationsContextAttrs.constData());
+ if (m_decorationsContext == EGL_NO_CONTEXT)
+ qWarning("QWaylandGLContext: Failed to create the decorations EGLContext. Decorations will not be drawn.");
+ }
+
+ EGLint a = EGL_MIN_SWAP_INTERVAL;
+ EGLint b = EGL_MAX_SWAP_INTERVAL;
+ if (!eglGetConfigAttrib(eglDisplay, eglConfig(), a, &a)
+ || !eglGetConfigAttrib(eglDisplay, eglConfig(), b, &b) || a > 0) {
+ m_supportNonBlockingSwap = false;
+ }
+ {
+ bool ok;
+ int supportNonBlockingSwap = qEnvironmentVariableIntValue("QT_WAYLAND_FORCE_NONBLOCKING_SWAP_SUPPORT", &ok);
+ if (ok)
+ m_supportNonBlockingSwap = supportNonBlockingSwap != 0;
+ }
+ if (!m_supportNonBlockingSwap) {
+ qCWarning(lcQpaWayland) << "Non-blocking swap buffers not supported."
+ << "Subsurface rendering can be affected."
+ << "It may also cause the event loop to freeze in some situations";
+ }
+}
+
+EGLSurface QWaylandGLContext::createTemporaryOffscreenSurface()
+{
+ m_wlSurface = m_display->createSurface(nullptr);
+ m_eglWindow = wl_egl_window_create(m_wlSurface, 1, 1);
+#if QT_CONFIG(egl_extension_platform_wayland)
+ EGLSurface eglSurface =
+ eglCreatePlatformWindowSurface(eglDisplay(), eglConfig(), m_eglWindow, nullptr);
+#else
+ EGLSurface eglSurface = eglCreateWindowSurface(eglDisplay(), eglConfig(), m_eglWindow, nullptr);
+#endif
+ return eglSurface;
+}
+
+void QWaylandGLContext::destroyTemporaryOffscreenSurface(EGLSurface eglSurface)
+{
+ eglDestroySurface(eglDisplay(), eglSurface);
+ wl_egl_window_destroy(m_eglWindow);
+ m_eglWindow = nullptr;
+ wl_surface_destroy(m_wlSurface);
+ m_wlSurface = nullptr;
+}
+
+void QWaylandGLContext::runGLChecks()
+{
+ bool ok;
+ const int doneCurrentWorkAround = qEnvironmentVariableIntValue("QT_WAYLAND_ENABLE_DONECURRENT_WORKAROUND", &ok);
+ if (ok) {
+ m_doneCurrentWorkAround = doneCurrentWorkAround != 0;
+ if (m_doneCurrentWorkAround)
+ qCDebug(lcQpaWayland) << "Enabling doneCurrent() workaround on request.";
+ else
+ qCDebug(lcQpaWayland) << "Disabling doneCurrent() workaround on request.";
+
+ } else {
+ // Note that even though there is an EGL context current here,
+ // QOpenGLContext and QOpenGLFunctions are not yet usable at this stage.
+ const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
+ if (renderer && strstr(renderer, "Mali")) {
+ qCDebug(lcQpaWayland) << "Enabling doneCurrent() workaround for Mali GPU."
+ << "Set QT_WAYLAND_ENABLE_DONECURRENT_WORKAROUND=0 to disable.";
+ m_doneCurrentWorkAround = true;
+ }
+ }
+
+ QEGLPlatformContext::runGLChecks();
+}
+
+QWaylandGLContext::~QWaylandGLContext()
+{
+ QObject::disconnect(m_reconnectionWatcher);
+ delete m_blitter;
+ m_blitter = nullptr;
+ if (m_decorationsContext != EGL_NO_CONTEXT)
+ eglDestroyContext(eglDisplay(), m_decorationsContext);
+}
+
+void QWaylandGLContext::beginFrame()
+{
+ Q_ASSERT(m_currentWindow != nullptr);
+ if (m_supportNonBlockingSwap)
+ m_currentWindow->beginFrame();
+}
+
+void QWaylandGLContext::endFrame()
+{
+ Q_ASSERT(m_currentWindow != nullptr);
+ if (m_doneCurrentWorkAround) {
+ doneCurrent();
+ QOpenGLContextPrivate::setCurrentContext(nullptr);
+ }
+
+ if (m_supportNonBlockingSwap)
+ m_currentWindow->endFrame();
+}
+
+bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface)
+{
+ if (!isValid()) {
+ return false;
+ }
+
+ // in QWaylandGLContext() we called eglBindAPI with the correct value. However,
+ // eglBindAPI's documentation says:
+ // "eglBindAPI defines the current rendering API for EGL in the thread it is called from"
+ // Since makeCurrent() can be called from a different thread than the one we created the
+ // context in make sure to call eglBindAPI in the correct thread.
+ if (eglQueryAPI() != m_api) {
+ eglBindAPI(m_api);
+ }
+
+ m_currentWindow = static_cast<QWaylandEglWindow *>(surface);
+
+ QMutexLocker lock(m_currentWindow->eglSurfaceLock());
+ EGLSurface eglSurface = m_currentWindow->eglSurface();
+
+ if (!m_currentWindow->needToUpdateContentFBO() && (eglSurface != EGL_NO_SURFACE)) {
+ if (!eglMakeCurrent(eglDisplay(), eglSurface, eglSurface, eglContext())) {
+ qWarning("QWaylandGLContext::makeCurrent: eglError: %#x, this: %p \n", eglGetError(), this);
+ return false;
+ }
+ return true;
+ }
+
+ if (eglSurface == EGL_NO_SURFACE) {
+ m_currentWindow->updateSurface(true);
+ eglSurface = m_currentWindow->eglSurface();
+ }
+
+ if (!eglMakeCurrent(eglDisplay(), eglSurface, eglSurface, eglContext())) {
+ qWarning("QWaylandGLContext::makeCurrent: eglError: %#x, this: %p \n", eglGetError(), this);
+ return false;
+ }
+
+ //### setCurrentContext will be called in QOpenGLContext::makeCurrent after this function
+ // returns, but that's too late, as we need a current context in order to bind the content FBO.
+ QOpenGLContextPrivate::setCurrentContext(context());
+ m_currentWindow->bindContentFBO();
+
+ return true;
+}
+
+void QWaylandGLContext::doneCurrent()
+{
+ eglMakeCurrent(eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+}
+
+void QWaylandGLContext::swapBuffers(QPlatformSurface *surface)
+{
+ QWaylandEglWindow *window = static_cast<QWaylandEglWindow *>(surface);
+
+ EGLSurface eglSurface = window->eglSurface();
+
+ if (window->decoration()) {
+ if (m_api != EGL_OPENGL_ES_API)
+ eglBindAPI(EGL_OPENGL_ES_API);
+
+ // save the current EGL content and surface to set it again after the blitter is done
+ EGLDisplay currentDisplay = eglGetCurrentDisplay();
+ EGLContext currentContext = eglGetCurrentContext();
+ EGLSurface currentSurfaceDraw = eglGetCurrentSurface(EGL_DRAW);
+ EGLSurface currentSurfaceRead = eglGetCurrentSurface(EGL_READ);
+ eglMakeCurrent(eglDisplay(), eglSurface, eglSurface, m_decorationsContext);
+
+ if (!m_blitter)
+ m_blitter = new DecorationsBlitter(this);
+ m_blitter->blit(window);
+
+ if (m_api != EGL_OPENGL_ES_API)
+ eglBindAPI(m_api);
+ eglMakeCurrent(currentDisplay, currentSurfaceDraw, currentSurfaceRead, currentContext);
+ }
+
+ int swapInterval = m_supportNonBlockingSwap ? 0 : format().swapInterval();
+ eglSwapInterval(eglDisplay(), swapInterval);
+ if (swapInterval == 0 && format().swapInterval() > 0) {
+ // Emulating a blocking swap
+ glFlush(); // Flush before waiting so we can swap more quickly when the frame event arrives
+ window->waitForFrameSync(100);
+ }
+ window->handleUpdate();
+ if (!eglSwapBuffers(eglDisplay(), eglSurface))
+ qCWarning(lcQpaWayland, "eglSwapBuffers failed with %#x, surface: %p", eglGetError(), eglSurface);
+}
+
+GLuint QWaylandGLContext::defaultFramebufferObject(QPlatformSurface *surface) const
+{
+ return static_cast<QWaylandEglWindow *>(surface)->contentFBO();
+}
+
+QFunctionPointer QWaylandGLContext::getProcAddress(const char *procName)
+{
+ QFunctionPointer proc = (QFunctionPointer) eglGetProcAddress(procName);
+ if (!proc)
+ proc = (QFunctionPointer) dlsym(RTLD_DEFAULT, procName);
+ return proc;
+}
+
+EGLSurface QWaylandGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
+{
+ return static_cast<QWaylandEglWindow *>(surface)->eglSurface();
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandglcontext_p.h b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandglcontext_p.h
new file mode 100644
index 00000000000..bd9eb53f85e
--- /dev/null
+++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/qwaylandglcontext_p.h
@@ -0,0 +1,74 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QWAYLANDGLCONTEXT_H
+#define QWAYLANDGLCONTEXT_H
+
+#include "qwaylandeglinclude_p.h" //must be first
+
+#include <QtWaylandClient/private/qwaylanddisplay_p.h>
+#include <QtGui/private/qeglplatformcontext_p.h>
+#include <qpa/qplatformopenglcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLShaderProgram;
+class QOpenGLTextureCache;
+
+namespace QtWaylandClient {
+
+class QWaylandEglWindow;
+class DecorationsBlitter;
+
+class Q_WAYLANDCLIENT_EXPORT QWaylandGLContext : public QEGLPlatformContext
+{
+public:
+ QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *display, const QSurfaceFormat &format, QPlatformOpenGLContext *share);
+ ~QWaylandGLContext();
+ void swapBuffers(QPlatformSurface *surface) override;
+
+ bool makeCurrent(QPlatformSurface *surface) override;
+ void doneCurrent() override;
+
+ void beginFrame() override;
+ void endFrame() override;
+
+ GLuint defaultFramebufferObject(QPlatformSurface *surface) const override;
+
+ QFunctionPointer getProcAddress(const char *procName) override;
+
+protected:
+ EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override;
+ EGLSurface createTemporaryOffscreenSurface() override;
+ void destroyTemporaryOffscreenSurface(EGLSurface surface) override;
+ void runGLChecks() override;
+
+private:
+ QWaylandDisplay *m_display = nullptr;
+ EGLContext m_decorationsContext;
+ DecorationsBlitter *m_blitter = nullptr;
+ bool m_supportNonBlockingSwap = true;
+ EGLenum m_api;
+ wl_surface *m_wlSurface = nullptr;
+ wl_egl_window *m_eglWindow = nullptr;
+ QWaylandEglWindow *m_currentWindow = nullptr;
+ QMetaObject::Connection m_reconnectionWatcher;
+ bool m_doneCurrentWorkAround = false;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDGLCONTEXT_H