From 48fb07b367d1a52975d138d9e4bddf1ba224cf4a Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Fri, 17 Mar 2023 01:08:24 +0100 Subject: [PATCH] platformsupport/scenes: move egldisplay code into a helper class --- src/backends/drm/drm_backend.cpp | 5 + src/backends/drm/drm_backend.h | 1 + src/backends/drm/drm_egl_backend.cpp | 18 +- src/backends/drm/drm_gpu.cpp | 12 +- src/backends/drm/drm_gpu.h | 7 +- src/backends/virtual/virtual_backend.cpp | 17 +- src/backends/virtual/virtual_backend.h | 4 + src/backends/virtual/virtual_egl_backend.cpp | 16 +- src/backends/wayland/wayland_backend.cpp | 14 +- src/backends/wayland/wayland_backend.h | 3 + src/backends/wayland/wayland_egl_backend.cpp | 19 +- .../x11/standalone/x11_standalone_backend.cpp | 13 +- .../x11/standalone/x11_standalone_backend.h | 4 + .../standalone/x11_standalone_egl_backend.cpp | 26 ++- .../x11/windowed/x11_windowed_backend.cpp | 15 +- .../x11/windowed/x11_windowed_backend.h | 4 + .../x11/windowed/x11_windowed_egl_backend.cpp | 21 ++- src/core/outputbackend.cpp | 15 +- src/core/outputbackend.h | 7 +- src/libkwineffects/kwineglimagetexture.cpp | 2 +- src/libkwineffects/kwineglimagetexture.h | 4 +- .../scenes/opengl/CMakeLists.txt | 1 + .../scenes/opengl/abstract_egl_backend.cpp | 150 +++------------- .../scenes/opengl/abstract_egl_backend.h | 19 +- .../scenes/opengl/egldisplay.cpp | 170 ++++++++++++++++++ .../scenes/opengl/egldisplay.h | 51 ++++++ src/plugins/qpa/eglhelpers.cpp | 4 +- src/plugins/qpa/eglhelpers.h | 4 +- src/plugins/qpa/eglplatformcontext.cpp | 4 +- src/plugins/qpa/eglplatformcontext.h | 6 +- src/plugins/qpa/integration.cpp | 2 +- src/plugins/qpa/offscreensurface.h | 2 +- src/plugins/qpa/window.h | 2 +- src/plugins/screencast/eglnativefence.cpp | 2 +- src/plugins/screencast/eglnativefence.h | 4 +- src/wayland/display.cpp | 2 +- src/wayland/display_p.h | 2 +- src/wayland/drmclientbuffer.cpp | 6 +- 38 files changed, 407 insertions(+), 251 deletions(-) create mode 100644 src/platformsupport/scenes/opengl/egldisplay.cpp create mode 100644 src/platformsupport/scenes/opengl/egldisplay.h diff --git a/src/backends/drm/drm_backend.cpp b/src/backends/drm/drm_backend.cpp index b88edf7096..b45ee9b3ee 100644 --- a/src/backends/drm/drm_backend.cpp +++ b/src/backends/drm/drm_backend.cpp @@ -535,4 +535,9 @@ const std::vector> &DrmBackend::gpus() const { return m_gpus; } + +EglDisplay *DrmBackend::sceneEglDisplayObject() const +{ + return m_gpus.front()->eglDisplay(); +} } diff --git a/src/backends/drm/drm_backend.h b/src/backends/drm/drm_backend.h index 2dd688bb70..984351a653 100644 --- a/src/backends/drm/drm_backend.h +++ b/src/backends/drm/drm_backend.h @@ -47,6 +47,7 @@ public: std::unique_ptr createInputBackend() override; std::unique_ptr createQPainterBackend() override; std::unique_ptr createOpenGLBackend() override; + EglDisplay *sceneEglDisplayObject() const override; std::optional testCreateDmaBuf(const QSize &size, quint32 format, const QVector &modifiers) override; std::shared_ptr createDmaBufTexture(const QSize &size, quint32 format, const uint64_t modifier) override; diff --git a/src/backends/drm/drm_egl_backend.cpp b/src/backends/drm/drm_egl_backend.cpp index 891e26f52e..52cc9a8ed0 100644 --- a/src/backends/drm/drm_egl_backend.cpp +++ b/src/backends/drm/drm_egl_backend.cpp @@ -60,11 +60,11 @@ EglGbmBackend::~EglGbmBackend() bool EglGbmBackend::initializeEgl() { initClientExtensions(); - EGLDisplay display = m_backend->primaryGpu()->eglDisplay(); + auto display = m_backend->primaryGpu()->eglDisplay(); // Use eglGetPlatformDisplayEXT() to get the display pointer // if the implementation supports it. - if (display == EGL_NO_DISPLAY) { + if (!display) { const bool hasMesaGBM = hasClientExtension(QByteArrayLiteral("EGL_MESA_platform_gbm")); const bool hasKHRGBM = hasClientExtension(QByteArrayLiteral("EGL_KHR_platform_gbm")); const GLenum platform = hasMesaGBM ? EGL_PLATFORM_GBM_MESA : EGL_PLATFORM_GBM_KHR; @@ -80,15 +80,14 @@ bool EglGbmBackend::initializeEgl() return false; } - display = eglGetPlatformDisplayEXT(platform, m_backend->primaryGpu()->gbmDevice(), nullptr); - m_backend->primaryGpu()->setEglDisplay(display); - } - - if (display == EGL_NO_DISPLAY) { - return false; + m_backend->primaryGpu()->setEglDisplay(EglDisplay::create(eglGetPlatformDisplayEXT(platform, m_backend->primaryGpu()->gbmDevice(), nullptr))); + display = m_backend->primaryGpu()->eglDisplay(); + if (!display) { + return false; + } } setEglDisplay(display); - return initEglAPI(); + return true; } void EglGbmBackend::init() @@ -102,7 +101,6 @@ void EglGbmBackend::init() setFailed("Could not initialize rendering context"); return; } - initBufferAge(); initKWinGL(); initWayland(); } diff --git a/src/backends/drm/drm_gpu.cpp b/src/backends/drm/drm_gpu.cpp index 0f8399c5a0..4590fa18c4 100644 --- a/src/backends/drm/drm_gpu.cpp +++ b/src/backends/drm/drm_gpu.cpp @@ -94,9 +94,7 @@ DrmGpu::DrmGpu(DrmBackend *backend, const QString &devNode, int fd, dev_t device DrmGpu::~DrmGpu() { removeOutputs(); - if (m_eglDisplay != EGL_NO_DISPLAY) { - eglTerminate(m_eglDisplay); - } + m_eglDisplay.reset(); m_crtcs.clear(); m_connectors.clear(); m_planes.clear(); @@ -671,14 +669,14 @@ gbm_device *DrmGpu::gbmDevice() const return m_gbmDevice; } -EGLDisplay DrmGpu::eglDisplay() const +EglDisplay *DrmGpu::eglDisplay() const { - return m_eglDisplay; + return m_eglDisplay.get(); } -void DrmGpu::setEglDisplay(EGLDisplay display) +void DrmGpu::setEglDisplay(std::unique_ptr &&display) { - m_eglDisplay = display; + m_eglDisplay = std::move(display); } bool DrmGpu::addFB2ModifiersSupported() const diff --git a/src/backends/drm/drm_gpu.h b/src/backends/drm/drm_gpu.h index 566e3fa947..7737d36b1f 100644 --- a/src/backends/drm/drm_gpu.h +++ b/src/backends/drm/drm_gpu.h @@ -35,6 +35,7 @@ class EglGbmBackend; class DrmAbstractOutput; class DrmRenderBackend; class DrmVirtualOutput; +class EglDisplay; class DrmLease : public QObject { @@ -75,7 +76,7 @@ public: bool asyncPageflipSupported() const; bool isNVidia() const; gbm_device *gbmDevice() const; - EGLDisplay eglDisplay() const; + EglDisplay *eglDisplay() const; DrmBackend *platform() const; /** * Returns the clock from which presentation timestamps are sourced. The returned value @@ -88,7 +89,7 @@ public: QVector drmOutputs() const; const QVector pipelines() const; - void setEglDisplay(EGLDisplay display); + void setEglDisplay(std::unique_ptr &&display); bool updateOutputs(); void removeOutputs(); @@ -134,7 +135,7 @@ private: bool m_isRemoved = false; clockid_t m_presentationClock; gbm_device *m_gbmDevice; - EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; + std::unique_ptr m_eglDisplay; DrmBackend *const m_platform; std::vector> m_planes; diff --git a/src/backends/virtual/virtual_backend.cpp b/src/backends/virtual/virtual_backend.cpp index 7dd4332438..74de726c6f 100644 --- a/src/backends/virtual/virtual_backend.cpp +++ b/src/backends/virtual/virtual_backend.cpp @@ -20,12 +20,7 @@ VirtualBackend::VirtualBackend(QObject *parent) { } -VirtualBackend::~VirtualBackend() -{ - if (sceneEglDisplay() != EGL_NO_DISPLAY) { - eglTerminate(sceneEglDisplay()); - } -} +VirtualBackend::~VirtualBackend() = default; bool VirtualBackend::initialize() { @@ -84,4 +79,14 @@ void VirtualBackend::setVirtualOutputs(const QVector &geometries, QVector Q_EMIT outputsQueried(); } +void VirtualBackend::setEglDisplay(std::unique_ptr &&display) +{ + m_display = std::move(display); +} + +EglDisplay *VirtualBackend::sceneEglDisplayObject() const +{ + return m_display.get(); +} + } // namespace KWin diff --git a/src/backends/virtual/virtual_backend.h b/src/backends/virtual/virtual_backend.h index 4feb6555b1..4474dc6035 100644 --- a/src/backends/virtual/virtual_backend.h +++ b/src/backends/virtual/virtual_backend.h @@ -44,6 +44,9 @@ public: return QVector{OpenGLCompositing, QPainterCompositing}; } + void setEglDisplay(std::unique_ptr &&display); + EglDisplay *sceneEglDisplayObject() const override; + Q_SIGNALS: void virtualOutputsSet(bool countChanged); @@ -51,6 +54,7 @@ private: VirtualOutput *createOutput(const QPoint &position, const QSize &size, qreal scale); QVector m_outputs; + std::unique_ptr m_display; }; } // namespace KWin diff --git a/src/backends/virtual/virtual_egl_backend.cpp b/src/backends/virtual/virtual_egl_backend.cpp index 4719418aae..cba24e12d1 100644 --- a/src/backends/virtual/virtual_egl_backend.cpp +++ b/src/backends/virtual/virtual_egl_backend.cpp @@ -86,24 +86,24 @@ VirtualEglBackend::~VirtualEglBackend() bool VirtualEglBackend::initializeEgl() { initClientExtensions(); - EGLDisplay display = m_backend->sceneEglDisplay(); + auto display = m_backend->sceneEglDisplayObject(); // Use eglGetPlatformDisplayEXT() to get the display pointer // if the implementation supports it. - if (display == EGL_NO_DISPLAY) { + if (!display) { // first try surfaceless if (hasClientExtension(QByteArrayLiteral("EGL_MESA_platform_surfaceless"))) { - display = eglGetPlatformDisplayEXT(EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, nullptr); + m_backend->setEglDisplay(EglDisplay::create(eglGetPlatformDisplayEXT(EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, nullptr))); + display = m_backend->sceneEglDisplayObject(); } else { qCWarning(KWIN_VIRTUAL) << "Extension EGL_MESA_platform_surfaceless not available"; } - } - - if (display == EGL_NO_DISPLAY) { - return false; + if (!display) { + return false; + } } setEglDisplay(display); - return initEglAPI(); + return true; } void VirtualEglBackend::init() diff --git a/src/backends/wayland/wayland_backend.cpp b/src/backends/wayland/wayland_backend.cpp index 831cde547f..4d824b8822 100644 --- a/src/backends/wayland/wayland_backend.cpp +++ b/src/backends/wayland/wayland_backend.cpp @@ -422,10 +422,7 @@ WaylandBackend::WaylandBackend(const WaylandBackendOptions &options, QObject *pa WaylandBackend::~WaylandBackend() { - if (sceneEglDisplay() != EGL_NO_DISPLAY) { - eglTerminate(sceneEglDisplay()); - } - + m_eglDisplay.reset(); destroyOutputs(); m_seat.reset(); @@ -624,6 +621,15 @@ std::shared_ptr WaylandBackend::createDmaBufTexture(const QSize & return std::make_shared(m_eglBackend->importDmaBufAsTexture(attributes), std::move(attributes)); } +void WaylandBackend::setEglDisplay(std::unique_ptr &&display) +{ + m_eglDisplay = std::move(display); +} + +EglDisplay *WaylandBackend::sceneEglDisplayObject() const +{ + return m_eglDisplay.get(); +} } } // KWin diff --git a/src/backends/wayland/wayland_backend.h b/src/backends/wayland/wayland_backend.h index 3ceaef0ca7..f385496155 100644 --- a/src/backends/wayland/wayland_backend.h +++ b/src/backends/wayland/wayland_backend.h @@ -229,6 +229,8 @@ public: { m_eglBackend = eglBackend; } + void setEglDisplay(std::unique_ptr &&display); + EglDisplay *sceneEglDisplayObject() const override; Q_SIGNALS: void pointerLockChanged(bool locked); @@ -247,6 +249,7 @@ private: bool m_pointerLockRequested = false; FileDescriptor m_drmFileDescriptor; gbm_device *m_gbmDevice; + std::unique_ptr m_eglDisplay; }; } // namespace Wayland diff --git a/src/backends/wayland/wayland_egl_backend.cpp b/src/backends/wayland/wayland_egl_backend.cpp index a224cc7514..f9d3aeec0a 100644 --- a/src/backends/wayland/wayland_egl_backend.cpp +++ b/src/backends/wayland/wayland_egl_backend.cpp @@ -340,11 +340,11 @@ bool WaylandEglBackend::createEglWaylandOutput(Output *waylandOutput) bool WaylandEglBackend::initializeEgl() { initClientExtensions(); - EGLDisplay display = m_backend->sceneEglDisplay(); + auto display = m_backend->sceneEglDisplayObject(); // Use eglGetPlatformDisplayEXT() to get the display pointer // if the implementation supports it. - if (display == EGL_NO_DISPLAY) { + if (!display) { m_havePlatformBase = hasClientExtension(QByteArrayLiteral("EGL_EXT_platform_base")); if (m_havePlatformBase) { // Make sure that the wayland platform is supported @@ -352,17 +352,17 @@ bool WaylandEglBackend::initializeEgl() return false; } - display = eglGetPlatformDisplayEXT(EGL_PLATFORM_WAYLAND_EXT, m_backend->display()->nativeDisplay(), nullptr); + m_backend->setEglDisplay(EglDisplay::create(eglGetPlatformDisplayEXT(EGL_PLATFORM_WAYLAND_EXT, m_backend->display()->nativeDisplay(), nullptr))); } else { - display = eglGetDisplay(m_backend->display()->nativeDisplay()); + m_backend->setEglDisplay(EglDisplay::create(eglGetDisplay(m_backend->display()->nativeDisplay()))); + } + display = m_backend->sceneEglDisplayObject(); + if (!display) { + return false; } } - - if (display == EGL_NO_DISPLAY) { - return false; - } setEglDisplay(display); - return initEglAPI(); + return true; } void WaylandEglBackend::init() @@ -377,7 +377,6 @@ void WaylandEglBackend::init() } initKWinGL(); - initBufferAge(); initWayland(); } diff --git a/src/backends/x11/standalone/x11_standalone_backend.cpp b/src/backends/x11/standalone/x11_standalone_backend.cpp index 69c19373fc..2dd778f024 100644 --- a/src/backends/x11/standalone/x11_standalone_backend.cpp +++ b/src/backends/x11/standalone/x11_standalone_backend.cpp @@ -119,9 +119,7 @@ X11StandaloneBackend::X11StandaloneBackend(QObject *parent) X11StandaloneBackend::~X11StandaloneBackend() { - if (sceneEglDisplay() != EGL_NO_DISPLAY) { - eglTerminate(sceneEglDisplay()); - } + m_eglDisplay.reset(); XRenderUtils::cleanup(); } @@ -511,4 +509,13 @@ void X11StandaloneBackend::updateRefreshRate() m_renderLoop->setRefreshRate(refreshRate); } +void X11StandaloneBackend::setEglDisplay(std::unique_ptr &&display) +{ + m_eglDisplay = std::move(display); +} + +EglDisplay *X11StandaloneBackend::sceneEglDisplayObject() const +{ + return m_eglDisplay.get(); +} } diff --git a/src/backends/x11/standalone/x11_standalone_backend.h b/src/backends/x11/standalone/x11_standalone_backend.h index c06256d299..c8ccdcf16d 100644 --- a/src/backends/x11/standalone/x11_standalone_backend.h +++ b/src/backends/x11/standalone/x11_standalone_backend.h @@ -69,6 +69,9 @@ public: RenderLoop *renderLoop() const; Outputs outputs() const override; + void setEglDisplay(std::unique_ptr &&display); + EglDisplay *sceneEglDisplayObject() const override; + private: /** * Tests whether GLX is supported and returns @c true @@ -98,6 +101,7 @@ private: std::unique_ptr m_keyboard; std::unique_ptr m_renderLoop; QVector m_outputs; + std::unique_ptr m_eglDisplay; }; } diff --git a/src/backends/x11/standalone/x11_standalone_egl_backend.cpp b/src/backends/x11/standalone/x11_standalone_egl_backend.cpp index 69bf430a33..d0d286f6ac 100644 --- a/src/backends/x11/standalone/x11_standalone_egl_backend.cpp +++ b/src/backends/x11/standalone/x11_standalone_egl_backend.cpp @@ -92,7 +92,7 @@ std::unique_ptr EglBackend::createSurfaceTextureX11(SurfacePixma void EglBackend::init() { QOpenGLContext *qtShareContext = QOpenGLContext::globalShareContext(); - EGLDisplay shareDisplay = EGL_NO_DISPLAY; + ::EGLDisplay shareDisplay = EGL_NO_DISPLAY; EGLContext shareContext = EGL_NO_CONTEXT; if (qtShareContext) { qDebug(KWIN_X11STANDALONE) << "Global share context format:" << qtShareContext->format(); @@ -112,7 +112,7 @@ void EglBackend::init() m_fbo = std::make_unique(0, workspace()->geometry().size()); - kwinApp()->outputBackend()->setSceneEglDisplay(shareDisplay); + m_backend->setEglDisplay(EglDisplay::create(shareDisplay, false)); kwinApp()->outputBackend()->setSceneEglGlobalShareContext(shareContext); qputenv("EGL_PLATFORM", "x11"); @@ -172,11 +172,11 @@ void EglBackend::init() bool EglBackend::initRenderingContext() { initClientExtensions(); - EGLDisplay dpy = kwinApp()->outputBackend()->sceneEglDisplay(); + auto display = kwinApp()->outputBackend()->sceneEglDisplayObject(); // Use eglGetPlatformDisplayEXT() to get the display pointer // if the implementation supports it. - if (dpy == EGL_NO_DISPLAY) { + if (!display) { m_havePlatformBase = hasClientExtension(QByteArrayLiteral("EGL_EXT_platform_base")); if (m_havePlatformBase) { // Make sure that the X11 platform is supported @@ -186,19 +186,18 @@ bool EglBackend::initRenderingContext() return false; } - dpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, m_backend->display(), nullptr); + m_backend->setEglDisplay(EglDisplay::create(eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, m_backend->display(), nullptr))); } else { - dpy = eglGetDisplay(m_backend->display()); + m_backend->setEglDisplay(EglDisplay::create(eglGetDisplay(m_backend->display()))); + } + display = m_backend->sceneEglDisplayObject(); + if (!display) { + qCWarning(KWIN_CORE) << "Failed to get the EGLDisplay"; + return false; } } - if (dpy == EGL_NO_DISPLAY) { - qCWarning(KWIN_CORE) << "Failed to get the EGLDisplay"; - return false; - } - setEglDisplay(dpy); - initEglAPI(); - + setEglDisplay(display); initBufferConfigs(); if (!m_overlayWindow->create()) { @@ -260,7 +259,6 @@ EGLSurface EglBackend::createSurface(xcb_window_t window) bool EglBackend::initBufferConfigs() { - initBufferAge(); const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT | (supportsBufferAge() ? 0 : EGL_SWAP_BEHAVIOR_PRESERVED_BIT), diff --git a/src/backends/x11/windowed/x11_windowed_backend.cpp b/src/backends/x11/windowed/x11_windowed_backend.cpp index abcec6f27c..8a3b5595da 100644 --- a/src/backends/x11/windowed/x11_windowed_backend.cpp +++ b/src/backends/x11/windowed/x11_windowed_backend.cpp @@ -169,10 +169,7 @@ X11WindowedBackend::~X11WindowedBackend() m_pointerDevice.reset(); m_keyboardDevice.reset(); m_touchDevice.reset(); - - if (sceneEglDisplay() != EGL_NO_DISPLAY) { - eglTerminate(sceneEglDisplay()); - } + m_eglDisplay.reset(); if (m_gbmDevice) { gbm_device_destroy(m_gbmDevice); @@ -801,4 +798,14 @@ void X11WindowedBackend::destroyOutputs() } } +void X11WindowedBackend::setEglDisplay(std::unique_ptr &&display) +{ + m_eglDisplay = std::move(display); +} + +EglDisplay *X11WindowedBackend::sceneEglDisplayObject() const +{ + return m_eglDisplay.get(); +} + } // namespace KWin diff --git a/src/backends/x11/windowed/x11_windowed_backend.h b/src/backends/x11/windowed/x11_windowed_backend.h index db24f8aa1b..ecc8d17df6 100644 --- a/src/backends/x11/windowed/x11_windowed_backend.h +++ b/src/backends/x11/windowed/x11_windowed_backend.h @@ -124,6 +124,9 @@ public: X11WindowedInputDevice *keyboardDevice() const; X11WindowedInputDevice *touchDevice() const; + void setEglDisplay(std::unique_ptr &&display); + EglDisplay *sceneEglDisplayObject() const override; + private: void createOutputs(); void grabKeyboard(xcb_timestamp_t time); @@ -174,6 +177,7 @@ private: FileDescriptor m_drmFileDescriptor; gbm_device *m_gbmDevice = nullptr; + std::unique_ptr m_eglDisplay; QVector m_outputs; }; diff --git a/src/backends/x11/windowed/x11_windowed_egl_backend.cpp b/src/backends/x11/windowed/x11_windowed_egl_backend.cpp index 9047b7f783..cfa461ffca 100644 --- a/src/backends/x11/windowed/x11_windowed_egl_backend.cpp +++ b/src/backends/x11/windowed/x11_windowed_egl_backend.cpp @@ -276,11 +276,11 @@ X11WindowedBackend *X11WindowedEglBackend::backend() const bool X11WindowedEglBackend::initializeEgl() { initClientExtensions(); - EGLDisplay dpy = kwinApp()->outputBackend()->sceneEglDisplay(); + auto display = kwinApp()->outputBackend()->sceneEglDisplayObject(); // Use eglGetPlatformDisplayEXT() to get the display pointer // if the implementation supports it. - if (dpy == EGL_NO_DISPLAY) { + if (!display) { const bool havePlatformBase = hasClientExtension(QByteArrayLiteral("EGL_EXT_platform_base")); if (havePlatformBase) { // Make sure that the X11 platform is supported @@ -290,17 +290,17 @@ bool X11WindowedEglBackend::initializeEgl() return false; } - dpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, m_backend->display(), nullptr); + m_backend->setEglDisplay(EglDisplay::create(eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, m_backend->display(), nullptr))); } else { - dpy = eglGetDisplay(m_backend->display()); + m_backend->setEglDisplay(EglDisplay::create(eglGetDisplay(m_backend->display()))); + } + display = m_backend->sceneEglDisplayObject(); + if (!display) { + return false; } } - - if (dpy == EGL_NO_DISPLAY) { - return false; - } - setEglDisplay(dpy); - return initEglAPI(); + setEglDisplay(display); + return true; } bool X11WindowedEglBackend::initRenderingContext() @@ -328,7 +328,6 @@ void X11WindowedEglBackend::init() } initKWinGL(); - initBufferAge(); initWayland(); const auto &outputs = m_backend->outputs(); diff --git a/src/core/outputbackend.cpp b/src/core/outputbackend.cpp index 6e43c2b2ad..0e36e1342e 100644 --- a/src/core/outputbackend.cpp +++ b/src/core/outputbackend.cpp @@ -13,6 +13,7 @@ #include "inputbackend.h" #include "output.h" #include "outputconfiguration.h" +#include "platformsupport/scenes/opengl/egldisplay.h" #include "platformsupport/scenes/opengl/openglbackend.h" #include "platformsupport/scenes/qpainter/qpainterbackend.h" @@ -21,7 +22,6 @@ namespace KWin OutputBackend::OutputBackend(QObject *parent) : QObject(parent) - , m_eglDisplay(EGL_NO_DISPLAY) { } @@ -103,14 +103,13 @@ void OutputBackend::removeVirtualOutput(Output *output) Q_ASSERT(!output); } -EGLDisplay KWin::OutputBackend::sceneEglDisplay() const +::EGLDisplay KWin::OutputBackend::sceneEglDisplay() const { - return m_eglDisplay; -} - -void OutputBackend::setSceneEglDisplay(EGLDisplay display) -{ - m_eglDisplay = display; + if (auto display = sceneEglDisplayObject()) { + return display->handle(); + } else { + return EGL_NO_DISPLAY; + } } QString OutputBackend::supportInformation() const diff --git a/src/core/outputbackend.h b/src/core/outputbackend.h index eb52e8176a..d73c9bafaa 100644 --- a/src/core/outputbackend.h +++ b/src/core/outputbackend.h @@ -28,6 +28,7 @@ class OpenGLBackend; class QPainterBackend; class OutputConfiguration; struct DmaBufParams; +class EglDisplay; class KWIN_EXPORT Outputs : public QVector { @@ -58,8 +59,8 @@ public: /** * The EGLDisplay used by the compositing scene. */ - EGLDisplay sceneEglDisplay() const; - void setSceneEglDisplay(EGLDisplay display); + ::EGLDisplay sceneEglDisplay() const; + virtual EglDisplay *sceneEglDisplayObject() const = 0; /** * Returns the compositor-wide shared EGL context. This function may return EGL_NO_CONTEXT * if the underlying rendering backend does not use EGL. @@ -119,8 +120,6 @@ Q_SIGNALS: protected: explicit OutputBackend(QObject *parent = nullptr); -private: - EGLDisplay m_eglDisplay; EGLContext m_globalShareContext = EGL_NO_CONTEXT; }; diff --git a/src/libkwineffects/kwineglimagetexture.cpp b/src/libkwineffects/kwineglimagetexture.cpp index bf4c8c42fa..841f98e8e8 100644 --- a/src/libkwineffects/kwineglimagetexture.cpp +++ b/src/libkwineffects/kwineglimagetexture.cpp @@ -15,7 +15,7 @@ namespace KWin { -EGLImageTexture::EGLImageTexture(EGLDisplay display, EGLImage image, int internalFormat, const QSize &size) +EGLImageTexture::EGLImageTexture(::EGLDisplay display, EGLImage image, int internalFormat, const QSize &size) : GLTexture(internalFormat, size, 1, true) , m_image(image) , m_display(display) diff --git a/src/libkwineffects/kwineglimagetexture.h b/src/libkwineffects/kwineglimagetexture.h index f984661651..db825571df 100644 --- a/src/libkwineffects/kwineglimagetexture.h +++ b/src/libkwineffects/kwineglimagetexture.h @@ -22,12 +22,12 @@ namespace KWin class KWINGLUTILS_EXPORT EGLImageTexture : public GLTexture { public: - EGLImageTexture(EGLDisplay display, EGLImageKHR image, int internalFormat, const QSize &size); + EGLImageTexture(::EGLDisplay display, EGLImageKHR image, int internalFormat, const QSize &size); ~EGLImageTexture() override; private: EGLImageKHR m_image; - EGLDisplay m_display; + ::EGLDisplay m_display; }; } diff --git a/src/platformsupport/scenes/opengl/CMakeLists.txt b/src/platformsupport/scenes/opengl/CMakeLists.txt index 7317b5a5c2..f76c61eb60 100644 --- a/src/platformsupport/scenes/opengl/CMakeLists.txt +++ b/src/platformsupport/scenes/opengl/CMakeLists.txt @@ -2,6 +2,7 @@ target_sources(kwin PRIVATE abstract_egl_backend.cpp basiceglsurfacetexture_internal.cpp basiceglsurfacetexture_wayland.cpp + egldisplay.cpp openglbackend.cpp openglsurfacetexture.cpp openglsurfacetexture_internal.cpp diff --git a/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp b/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp index abc748fab1..cc73c325f7 100644 --- a/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp +++ b/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp @@ -67,7 +67,7 @@ EGLContext AbstractEglBackend::ensureGlobalShareContext() void AbstractEglBackend::destroyGlobalShareContext() { - const EGLDisplay eglDisplay = kwinApp()->outputBackend()->sceneEglDisplay(); + const ::EGLDisplay eglDisplay = kwinApp()->outputBackend()->sceneEglDisplay(); if (eglDisplay == EGL_NO_DISPLAY || s_globalShareContext == EGL_NO_CONTEXT) { return; } @@ -78,8 +78,8 @@ void AbstractEglBackend::destroyGlobalShareContext() void AbstractEglBackend::teardown() { - if (m_functions.eglUnbindWaylandDisplayWL && m_display != EGL_NO_DISPLAY) { - m_functions.eglUnbindWaylandDisplayWL(m_display, *(WaylandServer::self()->display())); + if (m_functions.eglUnbindWaylandDisplayWL && m_display) { + m_functions.eglUnbindWaylandDisplayWL(m_display->handle(), *(WaylandServer::self()->display())); } destroyGlobalShareContext(); } @@ -93,56 +93,22 @@ void AbstractEglBackend::cleanup() cleanupSurfaces(); cleanupGL(); doneCurrent(); - eglDestroyContext(m_display, m_context); - eglReleaseThread(); + eglDestroyContext(m_display->handle(), m_context); } void AbstractEglBackend::cleanupSurfaces() { if (m_surface != EGL_NO_SURFACE) { - eglDestroySurface(m_display, m_surface); + eglDestroySurface(m_display->handle(), m_surface); } } -bool AbstractEglBackend::initEglAPI() +void AbstractEglBackend::setEglDisplay(EglDisplay *display) { - EGLint major, minor; - if (eglInitialize(m_display, &major, &minor) == EGL_FALSE) { - qCWarning(KWIN_OPENGL) << "eglInitialize failed"; - EGLint error = eglGetError(); - if (error != EGL_SUCCESS) { - qCWarning(KWIN_OPENGL) << "Error during eglInitialize " << error; - } - return false; - } - EGLint error = eglGetError(); - if (error != EGL_SUCCESS) { - qCWarning(KWIN_OPENGL) << "Error during eglInitialize " << error; - return false; - } - qCDebug(KWIN_OPENGL) << "Egl Initialize succeeded"; - - if (eglBindAPI(isOpenGLES() ? EGL_OPENGL_ES_API : EGL_OPENGL_API) == EGL_FALSE) { - qCCritical(KWIN_OPENGL) << "bind OpenGL API failed"; - return false; - } - qCDebug(KWIN_OPENGL) << "EGL version: " << major << "." << minor; - const QByteArray eglExtensions = eglQueryString(m_display, EGL_EXTENSIONS); - setExtensions(eglExtensions.split(' ')); - - const QByteArray requiredExtensions[] = { - QByteArrayLiteral("EGL_KHR_no_config_context"), - QByteArrayLiteral("EGL_KHR_surfaceless_context"), - }; - for (const QByteArray &extensionName : requiredExtensions) { - if (!hasExtension(extensionName)) { - qCWarning(KWIN_OPENGL) << extensionName << "extension is unsupported"; - return false; - } - } - - setSupportsNativeFence(hasExtension(QByteArrayLiteral("EGL_ANDROID_native_fence_sync"))); - return true; + m_display = display; + setExtensions(m_display->extensions()); + setSupportsNativeFence(m_display->supportsNativeFence()); + setSupportsBufferAge(m_display->supportsBufferAge()); } typedef void (*eglFuncPtr)(); @@ -163,19 +129,6 @@ void AbstractEglBackend::initKWinGL() initGL(&getProcAddress); } -void AbstractEglBackend::initBufferAge() -{ - setSupportsBufferAge(false); - - if (hasExtension(QByteArrayLiteral("EGL_EXT_buffer_age"))) { - const QByteArray useBufferAge = qgetenv("KWIN_USE_BUFFER_AGE"); - - if (useBufferAge != "0") { - setSupportsBufferAge(true); - } - } -} - static int bpcForFormat(uint32_t format) { switch (format) { @@ -323,13 +276,13 @@ bool AbstractEglBackend::makeCurrent() // Workaround to tell Qt that no QOpenGLContext is current context->doneCurrent(); } - const bool current = eglMakeCurrent(m_display, m_surface, m_surface, m_context); + const bool current = eglMakeCurrent(m_display->handle(), m_surface, m_surface, m_context); return current; } void AbstractEglBackend::doneCurrent() { - eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglMakeCurrent(m_display->handle(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } bool AbstractEglBackend::isOpenGLES() const @@ -440,7 +393,7 @@ EGLContext AbstractEglBackend::createContextInternal(EGLContext sharedContext) EGLContext ctx = EGL_NO_CONTEXT; for (auto it = candidates.begin(); it != candidates.end(); it++) { const auto attribs = (*it)->build(); - ctx = eglCreateContext(m_display, config(), sharedContext, attribs.data()); + ctx = eglCreateContext(m_display->handle(), config(), sharedContext, attribs.data()); if (ctx != EGL_NO_CONTEXT) { qCDebug(KWIN_OPENGL) << "Created EGL context with attributes:" << (*it).get(); break; @@ -453,12 +406,6 @@ EGLContext AbstractEglBackend::createContextInternal(EGLContext sharedContext) return ctx; } -void AbstractEglBackend::setEglDisplay(const EGLDisplay &display) -{ - m_display = display; - kwinApp()->outputBackend()->setSceneEglDisplay(display); -} - void AbstractEglBackend::setConfig(const EGLConfig &config) { m_config = config; @@ -504,71 +451,14 @@ EGLImageKHR AbstractEglBackend::importBufferAsImage(KWaylandServer::LinuxDmaBufV EGLImageKHR AbstractEglBackend::importDmaBufAsImage(const DmaBufAttributes &dmabuf) const { - QVector attribs; - attribs.reserve(6 + dmabuf.planeCount * 10 + 1); - - attribs - << EGL_WIDTH << dmabuf.width - << EGL_HEIGHT << dmabuf.height - << EGL_LINUX_DRM_FOURCC_EXT << dmabuf.format - << EGL_IMAGE_PRESERVED_KHR << EGL_TRUE; - - attribs - << EGL_DMA_BUF_PLANE0_FD_EXT << dmabuf.fd[0].get() - << EGL_DMA_BUF_PLANE0_OFFSET_EXT << dmabuf.offset[0] - << EGL_DMA_BUF_PLANE0_PITCH_EXT << dmabuf.pitch[0]; - if (dmabuf.modifier != DRM_FORMAT_MOD_INVALID) { - attribs - << EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT << EGLint(dmabuf.modifier & 0xffffffff) - << EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT << EGLint(dmabuf.modifier >> 32); - } - - if (dmabuf.planeCount > 1) { - attribs - << EGL_DMA_BUF_PLANE1_FD_EXT << dmabuf.fd[1].get() - << EGL_DMA_BUF_PLANE1_OFFSET_EXT << dmabuf.offset[1] - << EGL_DMA_BUF_PLANE1_PITCH_EXT << dmabuf.pitch[1]; - if (dmabuf.modifier != DRM_FORMAT_MOD_INVALID) { - attribs - << EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT << EGLint(dmabuf.modifier & 0xffffffff) - << EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT << EGLint(dmabuf.modifier >> 32); - } - } - - if (dmabuf.planeCount > 2) { - attribs - << EGL_DMA_BUF_PLANE2_FD_EXT << dmabuf.fd[2].get() - << EGL_DMA_BUF_PLANE2_OFFSET_EXT << dmabuf.offset[2] - << EGL_DMA_BUF_PLANE2_PITCH_EXT << dmabuf.pitch[2]; - if (dmabuf.modifier != DRM_FORMAT_MOD_INVALID) { - attribs - << EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT << EGLint(dmabuf.modifier & 0xffffffff) - << EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT << EGLint(dmabuf.modifier >> 32); - } - } - - if (dmabuf.planeCount > 3) { - attribs - << EGL_DMA_BUF_PLANE3_FD_EXT << dmabuf.fd[3].get() - << EGL_DMA_BUF_PLANE3_OFFSET_EXT << dmabuf.offset[3] - << EGL_DMA_BUF_PLANE3_PITCH_EXT << dmabuf.pitch[3]; - if (dmabuf.modifier != DRM_FORMAT_MOD_INVALID) { - attribs - << EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT << EGLint(dmabuf.modifier & 0xffffffff) - << EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT << EGLint(dmabuf.modifier >> 32); - } - } - - attribs << EGL_NONE; - - return eglCreateImageKHR(m_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data()); + return m_display->importDmaBufAsImage(dmabuf); } std::shared_ptr AbstractEglBackend::importDmaBufAsTexture(const DmaBufAttributes &attributes) const { EGLImageKHR image = importDmaBufAsImage(attributes); if (image != EGL_NO_IMAGE_KHR) { - return std::make_shared(eglDisplay(), image, GL_RGBA8, QSize(attributes.width, attributes.height)); + return std::make_shared(m_display->handle(), image, GL_RGBA8, QSize(attributes.width, attributes.height)); } else { qCWarning(KWIN_OPENGL) << "Failed to record frame: Error creating EGLImageKHR - " << getEglErrorString(); return nullptr; @@ -619,4 +509,14 @@ bool AbstractEglBackend::initBufferConfigs() return true; } + +::EGLDisplay AbstractEglBackend::eglDisplay() const +{ + return m_display->handle(); +} + +EglDisplay *AbstractEglBackend::eglDisplayObject() const +{ + return m_display; +} } diff --git a/src/platformsupport/scenes/opengl/abstract_egl_backend.h b/src/platformsupport/scenes/opengl/abstract_egl_backend.h index e4bfdf3321..50956cd198 100644 --- a/src/platformsupport/scenes/opengl/abstract_egl_backend.h +++ b/src/platformsupport/scenes/opengl/abstract_egl_backend.h @@ -7,6 +7,7 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once +#include "platformsupport/scenes/opengl/egldisplay.h" #include "platformsupport/scenes/opengl/openglbackend.h" #include "wayland/linuxdmabufv1clientbuffer.h" @@ -19,9 +20,9 @@ struct wl_resource; namespace KWin { -typedef GLboolean (*eglBindWaylandDisplayWL_func)(EGLDisplay dpy, wl_display *display); -typedef GLboolean (*eglUnbindWaylandDisplayWL_func)(EGLDisplay dpy, wl_display *display); -typedef GLboolean (*eglQueryWaylandBufferWL_func)(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); +typedef GLboolean (*eglBindWaylandDisplayWL_func)(::EGLDisplay dpy, wl_display *display); +typedef GLboolean (*eglUnbindWaylandDisplayWL_func)(::EGLDisplay dpy, wl_display *display); +typedef GLboolean (*eglQueryWaylandBufferWL_func)(::EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); struct AbstractEglBackendFunctions { @@ -45,10 +46,7 @@ public: { return &m_functions; } - EGLDisplay eglDisplay() const - { - return m_display; - } + ::EGLDisplay eglDisplay() const; EGLContext context() const { return m_context; @@ -61,6 +59,7 @@ public: { return m_config; } + EglDisplay *eglDisplayObject() const; bool testImportBuffer(KWaylandServer::LinuxDmaBufV1ClientBuffer *buffer) override; QHash> supportedFormats() const override; @@ -75,14 +74,12 @@ public: protected: AbstractEglBackend(dev_t deviceId = 0); - void setEglDisplay(const EGLDisplay &display); void setSurface(const EGLSurface &surface); void setConfig(const EGLConfig &config); void cleanup(); virtual void cleanupSurfaces(); - bool initEglAPI(); + void setEglDisplay(EglDisplay *display); void initKWinGL(); - void initBufferAge(); void initClientExtensions(); void initWayland(); bool hasClientExtension(const QByteArray &ext) const; @@ -98,7 +95,7 @@ private: void teardown(); AbstractEglBackendFunctions m_functions; - EGLDisplay m_display = EGL_NO_DISPLAY; + EglDisplay *m_display = nullptr; EGLSurface m_surface = EGL_NO_SURFACE; EGLContext m_context = EGL_NO_CONTEXT; EGLConfig m_config = nullptr; diff --git a/src/platformsupport/scenes/opengl/egldisplay.cpp b/src/platformsupport/scenes/opengl/egldisplay.cpp new file mode 100644 index 0000000000..257abe7961 --- /dev/null +++ b/src/platformsupport/scenes/opengl/egldisplay.cpp @@ -0,0 +1,170 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2023 Xaver Hugl + + SPDX-License-Identifier: GPL-2.0-or-later +*/ +#include "egldisplay.h" +#include "core/dmabufattributes.h" +#include "kwineglimagetexture.h" +#include "kwineglutils_p.h" +#include "libkwineffects/kwinglutils.h" +#include "utils/common.h" + +#include +#include + +namespace KWin +{ + +static bool isOpenGLES() +{ + if (qstrcmp(qgetenv("KWIN_COMPOSE"), "O2ES") == 0) { + return true; + } + return QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES; +} + +std::unique_ptr EglDisplay::create(::EGLDisplay display, bool owning) +{ + if (!display) { + return nullptr; + } + EGLint major, minor; + if (eglInitialize(display, &major, &minor) == EGL_FALSE) { + qCWarning(KWIN_OPENGL) << "eglInitialize failed"; + EGLint error = eglGetError(); + if (error != EGL_SUCCESS) { + qCWarning(KWIN_OPENGL) << "Error during eglInitialize " << error; + } + return nullptr; + } + EGLint error = eglGetError(); + if (error != EGL_SUCCESS) { + qCWarning(KWIN_OPENGL) << "Error during eglInitialize " << error; + return nullptr; + } + qCDebug(KWIN_OPENGL) << "Egl Initialize succeeded"; + if (eglBindAPI(isOpenGLES() ? EGL_OPENGL_ES_API : EGL_OPENGL_API) == EGL_FALSE) { + qCCritical(KWIN_OPENGL) << "bind OpenGL API failed"; + return nullptr; + } + qCDebug(KWIN_OPENGL) << "EGL version: " << major << "." << minor; + + const auto extensions = QByteArray(eglQueryString(display, EGL_EXTENSIONS)).split(' '); + + const QByteArray requiredExtensions[] = { + QByteArrayLiteral("EGL_KHR_no_config_context"), + QByteArrayLiteral("EGL_KHR_surfaceless_context"), + }; + for (const QByteArray &extensionName : requiredExtensions) { + if (!extensions.contains(extensionName)) { + qCWarning(KWIN_OPENGL) << extensionName << "extension is unsupported"; + return nullptr; + } + } + + return std::make_unique(display, extensions, owning); +} + +EglDisplay::EglDisplay(::EGLDisplay display, const QList &extensions, bool owning) + : m_handle(display) + , m_extensions(extensions) + , m_owning(owning) + , m_supportsBufferAge(extensions.contains(QByteArrayLiteral("EGL_EXT_buffer_age")) && qgetenv("KWIN_USE_BUFFER_AGE") != "0") + , m_supportsSwapBuffersWithDamage(extensions.contains(QByteArrayLiteral("EGL_EXT_swap_buffers_with_damage"))) + , m_supportsNativeFence(extensions.contains(QByteArrayLiteral("EGL_ANDROID_native_fence_sync"))) +{ +} + +EglDisplay::~EglDisplay() +{ + if (m_owning) { + eglTerminate(m_handle); + } +} + +QList EglDisplay::extensions() const +{ + return m_extensions; +} + +::EGLDisplay EglDisplay::handle() const +{ + return m_handle; +} + +bool EglDisplay::hasExtension(const QByteArray &name) const +{ + return m_extensions.contains(name); +} + +bool EglDisplay::supportsBufferAge() const +{ + return m_supportsBufferAge; +} + +bool EglDisplay::supportsSwapBuffersWithDamage() const +{ + return m_supportsSwapBuffersWithDamage; +} + +bool EglDisplay::supportsNativeFence() const +{ + return m_supportsNativeFence; +} + +EGLImageKHR EglDisplay::importDmaBufAsImage(const DmaBufAttributes &dmabuf) const +{ + QVector attribs; + attribs.reserve(6 + dmabuf.planeCount * 10 + 1); + + attribs << EGL_WIDTH << dmabuf.width + << EGL_HEIGHT << dmabuf.height + << EGL_LINUX_DRM_FOURCC_EXT << dmabuf.format; + + attribs << EGL_DMA_BUF_PLANE0_FD_EXT << dmabuf.fd[0].get() + << EGL_DMA_BUF_PLANE0_OFFSET_EXT << dmabuf.offset[0] + << EGL_DMA_BUF_PLANE0_PITCH_EXT << dmabuf.pitch[0]; + if (dmabuf.modifier != DRM_FORMAT_MOD_INVALID) { + attribs << EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT << EGLint(dmabuf.modifier & 0xffffffff) + << EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT << EGLint(dmabuf.modifier >> 32); + } + + if (dmabuf.planeCount > 1) { + attribs << EGL_DMA_BUF_PLANE1_FD_EXT << dmabuf.fd[1].get() + << EGL_DMA_BUF_PLANE1_OFFSET_EXT << dmabuf.offset[1] + << EGL_DMA_BUF_PLANE1_PITCH_EXT << dmabuf.pitch[1]; + if (dmabuf.modifier != DRM_FORMAT_MOD_INVALID) { + attribs << EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT << EGLint(dmabuf.modifier & 0xffffffff) + << EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT << EGLint(dmabuf.modifier >> 32); + } + } + + if (dmabuf.planeCount > 2) { + attribs << EGL_DMA_BUF_PLANE2_FD_EXT << dmabuf.fd[2].get() + << EGL_DMA_BUF_PLANE2_OFFSET_EXT << dmabuf.offset[2] + << EGL_DMA_BUF_PLANE2_PITCH_EXT << dmabuf.pitch[2]; + if (dmabuf.modifier != DRM_FORMAT_MOD_INVALID) { + attribs << EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT << EGLint(dmabuf.modifier & 0xffffffff) + << EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT << EGLint(dmabuf.modifier >> 32); + } + } + + if (dmabuf.planeCount > 3) { + attribs << EGL_DMA_BUF_PLANE3_FD_EXT << dmabuf.fd[3].get() + << EGL_DMA_BUF_PLANE3_OFFSET_EXT << dmabuf.offset[3] + << EGL_DMA_BUF_PLANE3_PITCH_EXT << dmabuf.pitch[3]; + if (dmabuf.modifier != DRM_FORMAT_MOD_INVALID) { + attribs << EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT << EGLint(dmabuf.modifier & 0xffffffff) + << EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT << EGLint(dmabuf.modifier >> 32); + } + } + + attribs << EGL_NONE; + + return eglCreateImageKHR(m_handle, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data()); +} +} diff --git a/src/platformsupport/scenes/opengl/egldisplay.h b/src/platformsupport/scenes/opengl/egldisplay.h new file mode 100644 index 0000000000..b9f291eafc --- /dev/null +++ b/src/platformsupport/scenes/opengl/egldisplay.h @@ -0,0 +1,51 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2023 Xaver Hugl + + SPDX-License-Identifier: GPL-2.0-or-later +*/ +#pragma once + +#include "kwin_export.h" + +#include +#include +#include + +namespace KWin +{ + +struct DmaBufAttributes; +class GLTexture; + +class KWIN_EXPORT EglDisplay +{ +public: + EglDisplay(::EGLDisplay display, const QList &extensions, bool owning = true); + ~EglDisplay(); + + QList extensions() const; + ::EGLDisplay handle() const; + bool hasExtension(const QByteArray &name) const; + + bool supportsBufferAge() const; + bool supportsSwapBuffersWithDamage() const; + bool supportsNativeFence() const; + + EGLImageKHR importDmaBufAsImage(const DmaBufAttributes &dmabuf) const; + + static std::unique_ptr create(::EGLDisplay display, bool owning = true); + +private: + const ::EGLDisplay m_handle; + const QList m_extensions; + const bool m_owning; + + const bool m_supportsBufferAge; + const bool m_supportsSwapBuffersWithDamage; + const bool m_supportsNativeFence; +}; + +} diff --git a/src/plugins/qpa/eglhelpers.cpp b/src/plugins/qpa/eglhelpers.cpp index f37af18e31..4350a49b9b 100644 --- a/src/plugins/qpa/eglhelpers.cpp +++ b/src/plugins/qpa/eglhelpers.cpp @@ -28,7 +28,7 @@ bool isOpenGLES() return QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES; } -EGLConfig configFromFormat(EGLDisplay display, const QSurfaceFormat &surfaceFormat, EGLint surfaceType) +EGLConfig configFromFormat(::EGLDisplay display, const QSurfaceFormat &surfaceFormat, EGLint surfaceType) { // std::max as these values are initialized to -1 by default. const EGLint redSize = std::max(surfaceFormat.redBufferSize(), 0); @@ -88,7 +88,7 @@ EGLConfig configFromFormat(EGLDisplay display, const QSurfaceFormat &surfaceForm return configs[0]; } -QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config) +QSurfaceFormat formatFromConfig(::EGLDisplay display, EGLConfig config) { int redSize = 0; int blueSize = 0; diff --git a/src/plugins/qpa/eglhelpers.h b/src/plugins/qpa/eglhelpers.h index 9a23a4002b..edf6f8ee48 100644 --- a/src/plugins/qpa/eglhelpers.h +++ b/src/plugins/qpa/eglhelpers.h @@ -20,8 +20,8 @@ namespace QPA bool isOpenGLES(); -EGLConfig configFromFormat(EGLDisplay display, const QSurfaceFormat &surfaceFormat, EGLint surfaceType = 0); -QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config); +EGLConfig configFromFormat(::EGLDisplay display, const QSurfaceFormat &surfaceFormat, EGLint surfaceType = 0); +QSurfaceFormat formatFromConfig(::EGLDisplay display, EGLConfig config); } // namespace QPA } // namespace KWin diff --git a/src/plugins/qpa/eglplatformcontext.cpp b/src/plugins/qpa/eglplatformcontext.cpp index ca510a3e19..485a6b9303 100644 --- a/src/plugins/qpa/eglplatformcontext.cpp +++ b/src/plugins/qpa/eglplatformcontext.cpp @@ -30,7 +30,7 @@ namespace KWin namespace QPA { -EGLPlatformContext::EGLPlatformContext(QOpenGLContext *context, EGLDisplay display) +EGLPlatformContext::EGLPlatformContext(QOpenGLContext *context, ::EGLDisplay display) : m_eglDisplay(display) { create(context->format(), kwinApp()->outputBackend()->sceneEglGlobalShareContext()); @@ -43,7 +43,7 @@ EGLPlatformContext::~EGLPlatformContext() } } -EGLDisplay EGLPlatformContext::eglDisplay() const +::EGLDisplay EGLPlatformContext::eglDisplay() const { return m_eglDisplay; } diff --git a/src/plugins/qpa/eglplatformcontext.h b/src/plugins/qpa/eglplatformcontext.h index 271fa3729b..bea05d2a50 100644 --- a/src/plugins/qpa/eglplatformcontext.h +++ b/src/plugins/qpa/eglplatformcontext.h @@ -22,7 +22,7 @@ namespace QPA class EGLPlatformContext : public QPlatformOpenGLContext { public: - EGLPlatformContext(QOpenGLContext *context, EGLDisplay display); + EGLPlatformContext(QOpenGLContext *context, ::EGLDisplay display); ~EGLPlatformContext() override; bool makeCurrent(QPlatformSurface *surface) override; @@ -34,14 +34,14 @@ public: QFunctionPointer getProcAddress(const char *procName) override; void swapBuffers(QPlatformSurface *surface) override; - EGLDisplay eglDisplay() const; + ::EGLDisplay eglDisplay() const; EGLContext eglContext() const; private: void create(const QSurfaceFormat &format, EGLContext shareContext); void updateFormatFromContext(); - EGLDisplay m_eglDisplay; + ::EGLDisplay m_eglDisplay; EGLConfig m_config = EGL_NO_CONFIG_KHR; EGLContext m_context = EGL_NO_CONTEXT; QSurfaceFormat m_format; diff --git a/src/plugins/qpa/integration.cpp b/src/plugins/qpa/integration.cpp index 76db7e5838..526d939144 100644 --- a/src/plugins/qpa/integration.cpp +++ b/src/plugins/qpa/integration.cpp @@ -146,7 +146,7 @@ QPlatformOpenGLContext *Integration::createPlatformOpenGLContext(QOpenGLContext qCWarning(KWIN_QPA) << "Attempting to create a QOpenGLContext before the scene is initialized"; return nullptr; } - const EGLDisplay eglDisplay = kwinApp()->outputBackend()->sceneEglDisplay(); + const ::EGLDisplay eglDisplay = kwinApp()->outputBackend()->sceneEglDisplay(); if (eglDisplay != EGL_NO_DISPLAY) { EGLPlatformContext *platformContext = new EGLPlatformContext(context, eglDisplay); return platformContext; diff --git a/src/plugins/qpa/offscreensurface.h b/src/plugins/qpa/offscreensurface.h index f09fc746b7..6b9de8555a 100644 --- a/src/plugins/qpa/offscreensurface.h +++ b/src/plugins/qpa/offscreensurface.h @@ -32,7 +32,7 @@ public: private: QSurfaceFormat m_format; - EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; + ::EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; EGLSurface m_surface = EGL_NO_SURFACE; }; diff --git a/src/plugins/qpa/window.h b/src/plugins/qpa/window.h index bd84558c0f..598c285382 100644 --- a/src/plugins/qpa/window.h +++ b/src/plugins/qpa/window.h @@ -52,7 +52,7 @@ private: QSurfaceFormat m_format; QPointer m_handle; std::shared_ptr m_contentFBO; - EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; + ::EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; quint32 m_windowId; bool m_resized = false; qreal m_scale = 1; diff --git a/src/plugins/screencast/eglnativefence.cpp b/src/plugins/screencast/eglnativefence.cpp index a2e096511e..058e1a86c1 100644 --- a/src/plugins/screencast/eglnativefence.cpp +++ b/src/plugins/screencast/eglnativefence.cpp @@ -16,7 +16,7 @@ namespace KWin #define EGL_NO_NATIVE_FENCE_FD_ANDROID -1 #endif // EGL_ANDROID_native_fence_sync -EGLNativeFence::EGLNativeFence(EGLDisplay display) +EGLNativeFence::EGLNativeFence(::EGLDisplay display) : m_display(display) { m_sync = eglCreateSyncKHR(m_display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr); diff --git a/src/plugins/screencast/eglnativefence.h b/src/plugins/screencast/eglnativefence.h index 15886eae39..b570ef7d63 100644 --- a/src/plugins/screencast/eglnativefence.h +++ b/src/plugins/screencast/eglnativefence.h @@ -16,7 +16,7 @@ namespace KWin class EGLNativeFence { public: - explicit EGLNativeFence(EGLDisplay display); + explicit EGLNativeFence(::EGLDisplay display); ~EGLNativeFence(); bool isValid() const; @@ -24,7 +24,7 @@ public: private: EGLSyncKHR m_sync = EGL_NO_SYNC_KHR; - EGLDisplay m_display = EGL_NO_DISPLAY; + ::EGLDisplay m_display = EGL_NO_DISPLAY; int m_fileDescriptor = -1; Q_DISABLE_COPY(EGLNativeFence) diff --git a/src/wayland/display.cpp b/src/wayland/display.cpp index b1ddbf1d2b..9f8a559fef 100644 --- a/src/wayland/display.cpp +++ b/src/wayland/display.cpp @@ -223,7 +223,7 @@ void Display::setEglDisplay(void *display) qCWarning(KWIN_CORE) << "EGLDisplay cannot be changed"; return; } - d->eglDisplay = (EGLDisplay)display; + d->eglDisplay = (::EGLDisplay)display; new DrmClientBufferIntegration(this); } diff --git a/src/wayland/display_p.h b/src/wayland/display_p.h index d07556a697..a28d77229f 100644 --- a/src/wayland/display_p.h +++ b/src/wayland/display_p.h @@ -51,7 +51,7 @@ public: QVector seats; QVector clients; QStringList socketNames; - EGLDisplay eglDisplay = EGL_NO_DISPLAY; + ::EGLDisplay eglDisplay = EGL_NO_DISPLAY; QHash<::wl_resource *, ClientBuffer *> resourceToBuffer; QHash bufferToListener; QList bufferIntegrations; diff --git a/src/wayland/drmclientbuffer.cpp b/src/wayland/drmclientbuffer.cpp index 530f178d9b..24ef8ccd23 100644 --- a/src/wayland/drmclientbuffer.cpp +++ b/src/wayland/drmclientbuffer.cpp @@ -17,7 +17,7 @@ namespace KWaylandServer { -typedef EGLBoolean (*eglQueryWaylandBufferWL_func)(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); +typedef EGLBoolean (*eglQueryWaylandBufferWL_func)(::EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); static eglQueryWaylandBufferWL_func eglQueryWaylandBufferWL = nullptr; class DrmClientBufferPrivate : public ClientBufferPrivate @@ -35,7 +35,7 @@ DrmClientBuffer::DrmClientBuffer(wl_resource *resource, DrmClientBufferIntegrati { Q_D(DrmClientBuffer); - EGLDisplay eglDisplay = integration->display()->eglDisplay(); + ::EGLDisplay eglDisplay = integration->display()->eglDisplay(); eglQueryWaylandBufferWL(eglDisplay, resource, EGL_TEXTURE_FORMAT, &d->textureFormat); eglQueryWaylandBufferWL(eglDisplay, resource, EGL_WIDTH, &d->width); eglQueryWaylandBufferWL(eglDisplay, resource, EGL_HEIGHT, &d->height); @@ -77,7 +77,7 @@ DrmClientBufferIntegration::DrmClientBufferIntegration(Display *display) ClientBuffer *DrmClientBufferIntegration::createBuffer(::wl_resource *resource) { - EGLDisplay eglDisplay = display()->eglDisplay(); + ::EGLDisplay eglDisplay = display()->eglDisplay(); static bool resolved = false; if (!resolved && eglDisplay != EGL_NO_DISPLAY) { eglQueryWaylandBufferWL = (eglQueryWaylandBufferWL_func)eglGetProcAddress("eglQueryWaylandBufferWL");