platformsupport/scenes: move egldisplay code into a helper class

This commit is contained in:
Xaver Hugl 2023-03-17 01:08:24 +01:00
parent acf38d364b
commit 48fb07b367
38 changed files with 407 additions and 251 deletions

View file

@ -535,4 +535,9 @@ const std::vector<std::unique_ptr<DrmGpu>> &DrmBackend::gpus() const
{ {
return m_gpus; return m_gpus;
} }
EglDisplay *DrmBackend::sceneEglDisplayObject() const
{
return m_gpus.front()->eglDisplay();
}
} }

View file

@ -47,6 +47,7 @@ public:
std::unique_ptr<InputBackend> createInputBackend() override; std::unique_ptr<InputBackend> createInputBackend() override;
std::unique_ptr<QPainterBackend> createQPainterBackend() override; std::unique_ptr<QPainterBackend> createQPainterBackend() override;
std::unique_ptr<OpenGLBackend> createOpenGLBackend() override; std::unique_ptr<OpenGLBackend> createOpenGLBackend() override;
EglDisplay *sceneEglDisplayObject() const override;
std::optional<DmaBufParams> testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers) override; std::optional<DmaBufParams> testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers) override;
std::shared_ptr<DmaBufTexture> createDmaBufTexture(const QSize &size, quint32 format, const uint64_t modifier) override; std::shared_ptr<DmaBufTexture> createDmaBufTexture(const QSize &size, quint32 format, const uint64_t modifier) override;

View file

@ -60,11 +60,11 @@ EglGbmBackend::~EglGbmBackend()
bool EglGbmBackend::initializeEgl() bool EglGbmBackend::initializeEgl()
{ {
initClientExtensions(); initClientExtensions();
EGLDisplay display = m_backend->primaryGpu()->eglDisplay(); auto display = m_backend->primaryGpu()->eglDisplay();
// Use eglGetPlatformDisplayEXT() to get the display pointer // Use eglGetPlatformDisplayEXT() to get the display pointer
// if the implementation supports it. // if the implementation supports it.
if (display == EGL_NO_DISPLAY) { if (!display) {
const bool hasMesaGBM = hasClientExtension(QByteArrayLiteral("EGL_MESA_platform_gbm")); const bool hasMesaGBM = hasClientExtension(QByteArrayLiteral("EGL_MESA_platform_gbm"));
const bool hasKHRGBM = hasClientExtension(QByteArrayLiteral("EGL_KHR_platform_gbm")); const bool hasKHRGBM = hasClientExtension(QByteArrayLiteral("EGL_KHR_platform_gbm"));
const GLenum platform = hasMesaGBM ? EGL_PLATFORM_GBM_MESA : EGL_PLATFORM_GBM_KHR; const GLenum platform = hasMesaGBM ? EGL_PLATFORM_GBM_MESA : EGL_PLATFORM_GBM_KHR;
@ -80,15 +80,14 @@ bool EglGbmBackend::initializeEgl()
return false; return false;
} }
display = eglGetPlatformDisplayEXT(platform, m_backend->primaryGpu()->gbmDevice(), nullptr); m_backend->primaryGpu()->setEglDisplay(EglDisplay::create(eglGetPlatformDisplayEXT(platform, m_backend->primaryGpu()->gbmDevice(), nullptr)));
m_backend->primaryGpu()->setEglDisplay(display); display = m_backend->primaryGpu()->eglDisplay();
} if (!display) {
if (display == EGL_NO_DISPLAY) {
return false; return false;
} }
}
setEglDisplay(display); setEglDisplay(display);
return initEglAPI(); return true;
} }
void EglGbmBackend::init() void EglGbmBackend::init()
@ -102,7 +101,6 @@ void EglGbmBackend::init()
setFailed("Could not initialize rendering context"); setFailed("Could not initialize rendering context");
return; return;
} }
initBufferAge();
initKWinGL(); initKWinGL();
initWayland(); initWayland();
} }

View file

@ -94,9 +94,7 @@ DrmGpu::DrmGpu(DrmBackend *backend, const QString &devNode, int fd, dev_t device
DrmGpu::~DrmGpu() DrmGpu::~DrmGpu()
{ {
removeOutputs(); removeOutputs();
if (m_eglDisplay != EGL_NO_DISPLAY) { m_eglDisplay.reset();
eglTerminate(m_eglDisplay);
}
m_crtcs.clear(); m_crtcs.clear();
m_connectors.clear(); m_connectors.clear();
m_planes.clear(); m_planes.clear();
@ -671,14 +669,14 @@ gbm_device *DrmGpu::gbmDevice() const
return m_gbmDevice; 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<EglDisplay> &&display)
{ {
m_eglDisplay = display; m_eglDisplay = std::move(display);
} }
bool DrmGpu::addFB2ModifiersSupported() const bool DrmGpu::addFB2ModifiersSupported() const

View file

@ -35,6 +35,7 @@ class EglGbmBackend;
class DrmAbstractOutput; class DrmAbstractOutput;
class DrmRenderBackend; class DrmRenderBackend;
class DrmVirtualOutput; class DrmVirtualOutput;
class EglDisplay;
class DrmLease : public QObject class DrmLease : public QObject
{ {
@ -75,7 +76,7 @@ public:
bool asyncPageflipSupported() const; bool asyncPageflipSupported() const;
bool isNVidia() const; bool isNVidia() const;
gbm_device *gbmDevice() const; gbm_device *gbmDevice() const;
EGLDisplay eglDisplay() const; EglDisplay *eglDisplay() const;
DrmBackend *platform() const; DrmBackend *platform() const;
/** /**
* Returns the clock from which presentation timestamps are sourced. The returned value * Returns the clock from which presentation timestamps are sourced. The returned value
@ -88,7 +89,7 @@ public:
QVector<DrmOutput *> drmOutputs() const; QVector<DrmOutput *> drmOutputs() const;
const QVector<DrmPipeline *> pipelines() const; const QVector<DrmPipeline *> pipelines() const;
void setEglDisplay(EGLDisplay display); void setEglDisplay(std::unique_ptr<EglDisplay> &&display);
bool updateOutputs(); bool updateOutputs();
void removeOutputs(); void removeOutputs();
@ -134,7 +135,7 @@ private:
bool m_isRemoved = false; bool m_isRemoved = false;
clockid_t m_presentationClock; clockid_t m_presentationClock;
gbm_device *m_gbmDevice; gbm_device *m_gbmDevice;
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; std::unique_ptr<EglDisplay> m_eglDisplay;
DrmBackend *const m_platform; DrmBackend *const m_platform;
std::vector<std::unique_ptr<DrmPlane>> m_planes; std::vector<std::unique_ptr<DrmPlane>> m_planes;

View file

@ -20,12 +20,7 @@ VirtualBackend::VirtualBackend(QObject *parent)
{ {
} }
VirtualBackend::~VirtualBackend() VirtualBackend::~VirtualBackend() = default;
{
if (sceneEglDisplay() != EGL_NO_DISPLAY) {
eglTerminate(sceneEglDisplay());
}
}
bool VirtualBackend::initialize() bool VirtualBackend::initialize()
{ {
@ -84,4 +79,14 @@ void VirtualBackend::setVirtualOutputs(const QVector<QRect> &geometries, QVector
Q_EMIT outputsQueried(); Q_EMIT outputsQueried();
} }
void VirtualBackend::setEglDisplay(std::unique_ptr<EglDisplay> &&display)
{
m_display = std::move(display);
}
EglDisplay *VirtualBackend::sceneEglDisplayObject() const
{
return m_display.get();
}
} // namespace KWin } // namespace KWin

View file

@ -44,6 +44,9 @@ public:
return QVector<CompositingType>{OpenGLCompositing, QPainterCompositing}; return QVector<CompositingType>{OpenGLCompositing, QPainterCompositing};
} }
void setEglDisplay(std::unique_ptr<EglDisplay> &&display);
EglDisplay *sceneEglDisplayObject() const override;
Q_SIGNALS: Q_SIGNALS:
void virtualOutputsSet(bool countChanged); void virtualOutputsSet(bool countChanged);
@ -51,6 +54,7 @@ private:
VirtualOutput *createOutput(const QPoint &position, const QSize &size, qreal scale); VirtualOutput *createOutput(const QPoint &position, const QSize &size, qreal scale);
QVector<VirtualOutput *> m_outputs; QVector<VirtualOutput *> m_outputs;
std::unique_ptr<EglDisplay> m_display;
}; };
} // namespace KWin } // namespace KWin

View file

@ -86,24 +86,24 @@ VirtualEglBackend::~VirtualEglBackend()
bool VirtualEglBackend::initializeEgl() bool VirtualEglBackend::initializeEgl()
{ {
initClientExtensions(); initClientExtensions();
EGLDisplay display = m_backend->sceneEglDisplay(); auto display = m_backend->sceneEglDisplayObject();
// Use eglGetPlatformDisplayEXT() to get the display pointer // Use eglGetPlatformDisplayEXT() to get the display pointer
// if the implementation supports it. // if the implementation supports it.
if (display == EGL_NO_DISPLAY) { if (!display) {
// first try surfaceless // first try surfaceless
if (hasClientExtension(QByteArrayLiteral("EGL_MESA_platform_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 { } else {
qCWarning(KWIN_VIRTUAL) << "Extension EGL_MESA_platform_surfaceless not available"; qCWarning(KWIN_VIRTUAL) << "Extension EGL_MESA_platform_surfaceless not available";
} }
} if (!display) {
if (display == EGL_NO_DISPLAY) {
return false; return false;
} }
}
setEglDisplay(display); setEglDisplay(display);
return initEglAPI(); return true;
} }
void VirtualEglBackend::init() void VirtualEglBackend::init()

View file

@ -422,10 +422,7 @@ WaylandBackend::WaylandBackend(const WaylandBackendOptions &options, QObject *pa
WaylandBackend::~WaylandBackend() WaylandBackend::~WaylandBackend()
{ {
if (sceneEglDisplay() != EGL_NO_DISPLAY) { m_eglDisplay.reset();
eglTerminate(sceneEglDisplay());
}
destroyOutputs(); destroyOutputs();
m_seat.reset(); m_seat.reset();
@ -624,6 +621,15 @@ std::shared_ptr<DmaBufTexture> WaylandBackend::createDmaBufTexture(const QSize &
return std::make_shared<DmaBufTexture>(m_eglBackend->importDmaBufAsTexture(attributes), std::move(attributes)); return std::make_shared<DmaBufTexture>(m_eglBackend->importDmaBufAsTexture(attributes), std::move(attributes));
} }
void WaylandBackend::setEglDisplay(std::unique_ptr<EglDisplay> &&display)
{
m_eglDisplay = std::move(display);
}
EglDisplay *WaylandBackend::sceneEglDisplayObject() const
{
return m_eglDisplay.get();
}
} }
} // KWin } // KWin

View file

@ -229,6 +229,8 @@ public:
{ {
m_eglBackend = eglBackend; m_eglBackend = eglBackend;
} }
void setEglDisplay(std::unique_ptr<EglDisplay> &&display);
EglDisplay *sceneEglDisplayObject() const override;
Q_SIGNALS: Q_SIGNALS:
void pointerLockChanged(bool locked); void pointerLockChanged(bool locked);
@ -247,6 +249,7 @@ private:
bool m_pointerLockRequested = false; bool m_pointerLockRequested = false;
FileDescriptor m_drmFileDescriptor; FileDescriptor m_drmFileDescriptor;
gbm_device *m_gbmDevice; gbm_device *m_gbmDevice;
std::unique_ptr<EglDisplay> m_eglDisplay;
}; };
} // namespace Wayland } // namespace Wayland

View file

@ -340,11 +340,11 @@ bool WaylandEglBackend::createEglWaylandOutput(Output *waylandOutput)
bool WaylandEglBackend::initializeEgl() bool WaylandEglBackend::initializeEgl()
{ {
initClientExtensions(); initClientExtensions();
EGLDisplay display = m_backend->sceneEglDisplay(); auto display = m_backend->sceneEglDisplayObject();
// Use eglGetPlatformDisplayEXT() to get the display pointer // Use eglGetPlatformDisplayEXT() to get the display pointer
// if the implementation supports it. // if the implementation supports it.
if (display == EGL_NO_DISPLAY) { if (!display) {
m_havePlatformBase = hasClientExtension(QByteArrayLiteral("EGL_EXT_platform_base")); m_havePlatformBase = hasClientExtension(QByteArrayLiteral("EGL_EXT_platform_base"));
if (m_havePlatformBase) { if (m_havePlatformBase) {
// Make sure that the wayland platform is supported // Make sure that the wayland platform is supported
@ -352,17 +352,17 @@ bool WaylandEglBackend::initializeEgl()
return false; 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 { } else {
display = eglGetDisplay(m_backend->display()->nativeDisplay()); m_backend->setEglDisplay(EglDisplay::create(eglGetDisplay(m_backend->display()->nativeDisplay())));
} }
} display = m_backend->sceneEglDisplayObject();
if (!display) {
if (display == EGL_NO_DISPLAY) {
return false; return false;
} }
}
setEglDisplay(display); setEglDisplay(display);
return initEglAPI(); return true;
} }
void WaylandEglBackend::init() void WaylandEglBackend::init()
@ -377,7 +377,6 @@ void WaylandEglBackend::init()
} }
initKWinGL(); initKWinGL();
initBufferAge();
initWayland(); initWayland();
} }

View file

@ -119,9 +119,7 @@ X11StandaloneBackend::X11StandaloneBackend(QObject *parent)
X11StandaloneBackend::~X11StandaloneBackend() X11StandaloneBackend::~X11StandaloneBackend()
{ {
if (sceneEglDisplay() != EGL_NO_DISPLAY) { m_eglDisplay.reset();
eglTerminate(sceneEglDisplay());
}
XRenderUtils::cleanup(); XRenderUtils::cleanup();
} }
@ -511,4 +509,13 @@ void X11StandaloneBackend::updateRefreshRate()
m_renderLoop->setRefreshRate(refreshRate); m_renderLoop->setRefreshRate(refreshRate);
} }
void X11StandaloneBackend::setEglDisplay(std::unique_ptr<EglDisplay> &&display)
{
m_eglDisplay = std::move(display);
}
EglDisplay *X11StandaloneBackend::sceneEglDisplayObject() const
{
return m_eglDisplay.get();
}
} }

View file

@ -69,6 +69,9 @@ public:
RenderLoop *renderLoop() const; RenderLoop *renderLoop() const;
Outputs outputs() const override; Outputs outputs() const override;
void setEglDisplay(std::unique_ptr<EglDisplay> &&display);
EglDisplay *sceneEglDisplayObject() const override;
private: private:
/** /**
* Tests whether GLX is supported and returns @c true * Tests whether GLX is supported and returns @c true
@ -98,6 +101,7 @@ private:
std::unique_ptr<X11Keyboard> m_keyboard; std::unique_ptr<X11Keyboard> m_keyboard;
std::unique_ptr<RenderLoop> m_renderLoop; std::unique_ptr<RenderLoop> m_renderLoop;
QVector<Output *> m_outputs; QVector<Output *> m_outputs;
std::unique_ptr<EglDisplay> m_eglDisplay;
}; };
} }

View file

@ -92,7 +92,7 @@ std::unique_ptr<SurfaceTexture> EglBackend::createSurfaceTextureX11(SurfacePixma
void EglBackend::init() void EglBackend::init()
{ {
QOpenGLContext *qtShareContext = QOpenGLContext::globalShareContext(); QOpenGLContext *qtShareContext = QOpenGLContext::globalShareContext();
EGLDisplay shareDisplay = EGL_NO_DISPLAY; ::EGLDisplay shareDisplay = EGL_NO_DISPLAY;
EGLContext shareContext = EGL_NO_CONTEXT; EGLContext shareContext = EGL_NO_CONTEXT;
if (qtShareContext) { if (qtShareContext) {
qDebug(KWIN_X11STANDALONE) << "Global share context format:" << qtShareContext->format(); qDebug(KWIN_X11STANDALONE) << "Global share context format:" << qtShareContext->format();
@ -112,7 +112,7 @@ void EglBackend::init()
m_fbo = std::make_unique<GLFramebuffer>(0, workspace()->geometry().size()); m_fbo = std::make_unique<GLFramebuffer>(0, workspace()->geometry().size());
kwinApp()->outputBackend()->setSceneEglDisplay(shareDisplay); m_backend->setEglDisplay(EglDisplay::create(shareDisplay, false));
kwinApp()->outputBackend()->setSceneEglGlobalShareContext(shareContext); kwinApp()->outputBackend()->setSceneEglGlobalShareContext(shareContext);
qputenv("EGL_PLATFORM", "x11"); qputenv("EGL_PLATFORM", "x11");
@ -172,11 +172,11 @@ void EglBackend::init()
bool EglBackend::initRenderingContext() bool EglBackend::initRenderingContext()
{ {
initClientExtensions(); initClientExtensions();
EGLDisplay dpy = kwinApp()->outputBackend()->sceneEglDisplay(); auto display = kwinApp()->outputBackend()->sceneEglDisplayObject();
// Use eglGetPlatformDisplayEXT() to get the display pointer // Use eglGetPlatformDisplayEXT() to get the display pointer
// if the implementation supports it. // if the implementation supports it.
if (dpy == EGL_NO_DISPLAY) { if (!display) {
m_havePlatformBase = hasClientExtension(QByteArrayLiteral("EGL_EXT_platform_base")); m_havePlatformBase = hasClientExtension(QByteArrayLiteral("EGL_EXT_platform_base"));
if (m_havePlatformBase) { if (m_havePlatformBase) {
// Make sure that the X11 platform is supported // Make sure that the X11 platform is supported
@ -186,19 +186,18 @@ bool EglBackend::initRenderingContext()
return false; 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 { } else {
dpy = eglGetDisplay(m_backend->display()); m_backend->setEglDisplay(EglDisplay::create(eglGetDisplay(m_backend->display())));
} }
} display = m_backend->sceneEglDisplayObject();
if (!display) {
if (dpy == EGL_NO_DISPLAY) {
qCWarning(KWIN_CORE) << "Failed to get the EGLDisplay"; qCWarning(KWIN_CORE) << "Failed to get the EGLDisplay";
return false; return false;
} }
setEglDisplay(dpy); }
initEglAPI();
setEglDisplay(display);
initBufferConfigs(); initBufferConfigs();
if (!m_overlayWindow->create()) { if (!m_overlayWindow->create()) {
@ -260,7 +259,6 @@ EGLSurface EglBackend::createSurface(xcb_window_t window)
bool EglBackend::initBufferConfigs() bool EglBackend::initBufferConfigs()
{ {
initBufferAge();
const EGLint config_attribs[] = { const EGLint config_attribs[] = {
EGL_SURFACE_TYPE, EGL_SURFACE_TYPE,
EGL_WINDOW_BIT | (supportsBufferAge() ? 0 : EGL_SWAP_BEHAVIOR_PRESERVED_BIT), EGL_WINDOW_BIT | (supportsBufferAge() ? 0 : EGL_SWAP_BEHAVIOR_PRESERVED_BIT),

View file

@ -169,10 +169,7 @@ X11WindowedBackend::~X11WindowedBackend()
m_pointerDevice.reset(); m_pointerDevice.reset();
m_keyboardDevice.reset(); m_keyboardDevice.reset();
m_touchDevice.reset(); m_touchDevice.reset();
m_eglDisplay.reset();
if (sceneEglDisplay() != EGL_NO_DISPLAY) {
eglTerminate(sceneEglDisplay());
}
if (m_gbmDevice) { if (m_gbmDevice) {
gbm_device_destroy(m_gbmDevice); gbm_device_destroy(m_gbmDevice);
@ -801,4 +798,14 @@ void X11WindowedBackend::destroyOutputs()
} }
} }
void X11WindowedBackend::setEglDisplay(std::unique_ptr<EglDisplay> &&display)
{
m_eglDisplay = std::move(display);
}
EglDisplay *X11WindowedBackend::sceneEglDisplayObject() const
{
return m_eglDisplay.get();
}
} // namespace KWin } // namespace KWin

View file

@ -124,6 +124,9 @@ public:
X11WindowedInputDevice *keyboardDevice() const; X11WindowedInputDevice *keyboardDevice() const;
X11WindowedInputDevice *touchDevice() const; X11WindowedInputDevice *touchDevice() const;
void setEglDisplay(std::unique_ptr<EglDisplay> &&display);
EglDisplay *sceneEglDisplayObject() const override;
private: private:
void createOutputs(); void createOutputs();
void grabKeyboard(xcb_timestamp_t time); void grabKeyboard(xcb_timestamp_t time);
@ -174,6 +177,7 @@ private:
FileDescriptor m_drmFileDescriptor; FileDescriptor m_drmFileDescriptor;
gbm_device *m_gbmDevice = nullptr; gbm_device *m_gbmDevice = nullptr;
std::unique_ptr<EglDisplay> m_eglDisplay;
QVector<X11WindowedOutput *> m_outputs; QVector<X11WindowedOutput *> m_outputs;
}; };

View file

@ -276,11 +276,11 @@ X11WindowedBackend *X11WindowedEglBackend::backend() const
bool X11WindowedEglBackend::initializeEgl() bool X11WindowedEglBackend::initializeEgl()
{ {
initClientExtensions(); initClientExtensions();
EGLDisplay dpy = kwinApp()->outputBackend()->sceneEglDisplay(); auto display = kwinApp()->outputBackend()->sceneEglDisplayObject();
// Use eglGetPlatformDisplayEXT() to get the display pointer // Use eglGetPlatformDisplayEXT() to get the display pointer
// if the implementation supports it. // if the implementation supports it.
if (dpy == EGL_NO_DISPLAY) { if (!display) {
const bool havePlatformBase = hasClientExtension(QByteArrayLiteral("EGL_EXT_platform_base")); const bool havePlatformBase = hasClientExtension(QByteArrayLiteral("EGL_EXT_platform_base"));
if (havePlatformBase) { if (havePlatformBase) {
// Make sure that the X11 platform is supported // Make sure that the X11 platform is supported
@ -290,17 +290,17 @@ bool X11WindowedEglBackend::initializeEgl()
return false; 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 { } else {
dpy = eglGetDisplay(m_backend->display()); m_backend->setEglDisplay(EglDisplay::create(eglGetDisplay(m_backend->display())));
} }
} display = m_backend->sceneEglDisplayObject();
if (!display) {
if (dpy == EGL_NO_DISPLAY) {
return false; return false;
} }
setEglDisplay(dpy); }
return initEglAPI(); setEglDisplay(display);
return true;
} }
bool X11WindowedEglBackend::initRenderingContext() bool X11WindowedEglBackend::initRenderingContext()
@ -328,7 +328,6 @@ void X11WindowedEglBackend::init()
} }
initKWinGL(); initKWinGL();
initBufferAge();
initWayland(); initWayland();
const auto &outputs = m_backend->outputs(); const auto &outputs = m_backend->outputs();

View file

@ -13,6 +13,7 @@
#include "inputbackend.h" #include "inputbackend.h"
#include "output.h" #include "output.h"
#include "outputconfiguration.h" #include "outputconfiguration.h"
#include "platformsupport/scenes/opengl/egldisplay.h"
#include "platformsupport/scenes/opengl/openglbackend.h" #include "platformsupport/scenes/opengl/openglbackend.h"
#include "platformsupport/scenes/qpainter/qpainterbackend.h" #include "platformsupport/scenes/qpainter/qpainterbackend.h"
@ -21,7 +22,6 @@ namespace KWin
OutputBackend::OutputBackend(QObject *parent) OutputBackend::OutputBackend(QObject *parent)
: QObject(parent) : QObject(parent)
, m_eglDisplay(EGL_NO_DISPLAY)
{ {
} }
@ -103,14 +103,13 @@ void OutputBackend::removeVirtualOutput(Output *output)
Q_ASSERT(!output); Q_ASSERT(!output);
} }
EGLDisplay KWin::OutputBackend::sceneEglDisplay() const ::EGLDisplay KWin::OutputBackend::sceneEglDisplay() const
{ {
return m_eglDisplay; if (auto display = sceneEglDisplayObject()) {
return display->handle();
} else {
return EGL_NO_DISPLAY;
} }
void OutputBackend::setSceneEglDisplay(EGLDisplay display)
{
m_eglDisplay = display;
} }
QString OutputBackend::supportInformation() const QString OutputBackend::supportInformation() const

View file

@ -28,6 +28,7 @@ class OpenGLBackend;
class QPainterBackend; class QPainterBackend;
class OutputConfiguration; class OutputConfiguration;
struct DmaBufParams; struct DmaBufParams;
class EglDisplay;
class KWIN_EXPORT Outputs : public QVector<Output *> class KWIN_EXPORT Outputs : public QVector<Output *>
{ {
@ -58,8 +59,8 @@ public:
/** /**
* The EGLDisplay used by the compositing scene. * The EGLDisplay used by the compositing scene.
*/ */
EGLDisplay sceneEglDisplay() const; ::EGLDisplay sceneEglDisplay() const;
void setSceneEglDisplay(EGLDisplay display); virtual EglDisplay *sceneEglDisplayObject() const = 0;
/** /**
* Returns the compositor-wide shared EGL context. This function may return EGL_NO_CONTEXT * Returns the compositor-wide shared EGL context. This function may return EGL_NO_CONTEXT
* if the underlying rendering backend does not use EGL. * if the underlying rendering backend does not use EGL.
@ -119,8 +120,6 @@ Q_SIGNALS:
protected: protected:
explicit OutputBackend(QObject *parent = nullptr); explicit OutputBackend(QObject *parent = nullptr);
private:
EGLDisplay m_eglDisplay;
EGLContext m_globalShareContext = EGL_NO_CONTEXT; EGLContext m_globalShareContext = EGL_NO_CONTEXT;
}; };

View file

@ -15,7 +15,7 @@
namespace KWin 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) : GLTexture(internalFormat, size, 1, true)
, m_image(image) , m_image(image)
, m_display(display) , m_display(display)

View file

@ -22,12 +22,12 @@ namespace KWin
class KWINGLUTILS_EXPORT EGLImageTexture : public GLTexture class KWINGLUTILS_EXPORT EGLImageTexture : public GLTexture
{ {
public: public:
EGLImageTexture(EGLDisplay display, EGLImageKHR image, int internalFormat, const QSize &size); EGLImageTexture(::EGLDisplay display, EGLImageKHR image, int internalFormat, const QSize &size);
~EGLImageTexture() override; ~EGLImageTexture() override;
private: private:
EGLImageKHR m_image; EGLImageKHR m_image;
EGLDisplay m_display; ::EGLDisplay m_display;
}; };
} }

View file

@ -2,6 +2,7 @@ target_sources(kwin PRIVATE
abstract_egl_backend.cpp abstract_egl_backend.cpp
basiceglsurfacetexture_internal.cpp basiceglsurfacetexture_internal.cpp
basiceglsurfacetexture_wayland.cpp basiceglsurfacetexture_wayland.cpp
egldisplay.cpp
openglbackend.cpp openglbackend.cpp
openglsurfacetexture.cpp openglsurfacetexture.cpp
openglsurfacetexture_internal.cpp openglsurfacetexture_internal.cpp

View file

@ -67,7 +67,7 @@ EGLContext AbstractEglBackend::ensureGlobalShareContext()
void AbstractEglBackend::destroyGlobalShareContext() 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) { if (eglDisplay == EGL_NO_DISPLAY || s_globalShareContext == EGL_NO_CONTEXT) {
return; return;
} }
@ -78,8 +78,8 @@ void AbstractEglBackend::destroyGlobalShareContext()
void AbstractEglBackend::teardown() void AbstractEglBackend::teardown()
{ {
if (m_functions.eglUnbindWaylandDisplayWL && m_display != EGL_NO_DISPLAY) { if (m_functions.eglUnbindWaylandDisplayWL && m_display) {
m_functions.eglUnbindWaylandDisplayWL(m_display, *(WaylandServer::self()->display())); m_functions.eglUnbindWaylandDisplayWL(m_display->handle(), *(WaylandServer::self()->display()));
} }
destroyGlobalShareContext(); destroyGlobalShareContext();
} }
@ -93,56 +93,22 @@ void AbstractEglBackend::cleanup()
cleanupSurfaces(); cleanupSurfaces();
cleanupGL(); cleanupGL();
doneCurrent(); doneCurrent();
eglDestroyContext(m_display, m_context); eglDestroyContext(m_display->handle(), m_context);
eglReleaseThread();
} }
void AbstractEglBackend::cleanupSurfaces() void AbstractEglBackend::cleanupSurfaces()
{ {
if (m_surface != EGL_NO_SURFACE) { 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; m_display = display;
if (eglInitialize(m_display, &major, &minor) == EGL_FALSE) { setExtensions(m_display->extensions());
qCWarning(KWIN_OPENGL) << "eglInitialize failed"; setSupportsNativeFence(m_display->supportsNativeFence());
EGLint error = eglGetError(); setSupportsBufferAge(m_display->supportsBufferAge());
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;
} }
typedef void (*eglFuncPtr)(); typedef void (*eglFuncPtr)();
@ -163,19 +129,6 @@ void AbstractEglBackend::initKWinGL()
initGL(&getProcAddress); 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) static int bpcForFormat(uint32_t format)
{ {
switch (format) { switch (format) {
@ -323,13 +276,13 @@ bool AbstractEglBackend::makeCurrent()
// Workaround to tell Qt that no QOpenGLContext is current // Workaround to tell Qt that no QOpenGLContext is current
context->doneCurrent(); 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; return current;
} }
void AbstractEglBackend::doneCurrent() 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 bool AbstractEglBackend::isOpenGLES() const
@ -440,7 +393,7 @@ EGLContext AbstractEglBackend::createContextInternal(EGLContext sharedContext)
EGLContext ctx = EGL_NO_CONTEXT; EGLContext ctx = EGL_NO_CONTEXT;
for (auto it = candidates.begin(); it != candidates.end(); it++) { for (auto it = candidates.begin(); it != candidates.end(); it++) {
const auto attribs = (*it)->build(); 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) { if (ctx != EGL_NO_CONTEXT) {
qCDebug(KWIN_OPENGL) << "Created EGL context with attributes:" << (*it).get(); qCDebug(KWIN_OPENGL) << "Created EGL context with attributes:" << (*it).get();
break; break;
@ -453,12 +406,6 @@ EGLContext AbstractEglBackend::createContextInternal(EGLContext sharedContext)
return ctx; return ctx;
} }
void AbstractEglBackend::setEglDisplay(const EGLDisplay &display)
{
m_display = display;
kwinApp()->outputBackend()->setSceneEglDisplay(display);
}
void AbstractEglBackend::setConfig(const EGLConfig &config) void AbstractEglBackend::setConfig(const EGLConfig &config)
{ {
m_config = config; m_config = config;
@ -504,71 +451,14 @@ EGLImageKHR AbstractEglBackend::importBufferAsImage(KWaylandServer::LinuxDmaBufV
EGLImageKHR AbstractEglBackend::importDmaBufAsImage(const DmaBufAttributes &dmabuf) const EGLImageKHR AbstractEglBackend::importDmaBufAsImage(const DmaBufAttributes &dmabuf) const
{ {
QVector<EGLint> attribs; return m_display->importDmaBufAsImage(dmabuf);
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());
} }
std::shared_ptr<GLTexture> AbstractEglBackend::importDmaBufAsTexture(const DmaBufAttributes &attributes) const std::shared_ptr<GLTexture> AbstractEglBackend::importDmaBufAsTexture(const DmaBufAttributes &attributes) const
{ {
EGLImageKHR image = importDmaBufAsImage(attributes); EGLImageKHR image = importDmaBufAsImage(attributes);
if (image != EGL_NO_IMAGE_KHR) { if (image != EGL_NO_IMAGE_KHR) {
return std::make_shared<EGLImageTexture>(eglDisplay(), image, GL_RGBA8, QSize(attributes.width, attributes.height)); return std::make_shared<EGLImageTexture>(m_display->handle(), image, GL_RGBA8, QSize(attributes.width, attributes.height));
} else { } else {
qCWarning(KWIN_OPENGL) << "Failed to record frame: Error creating EGLImageKHR - " << getEglErrorString(); qCWarning(KWIN_OPENGL) << "Failed to record frame: Error creating EGLImageKHR - " << getEglErrorString();
return nullptr; return nullptr;
@ -619,4 +509,14 @@ bool AbstractEglBackend::initBufferConfigs()
return true; return true;
} }
::EGLDisplay AbstractEglBackend::eglDisplay() const
{
return m_display->handle();
}
EglDisplay *AbstractEglBackend::eglDisplayObject() const
{
return m_display;
}
} }

View file

@ -7,6 +7,7 @@
SPDX-License-Identifier: GPL-2.0-or-later SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#pragma once #pragma once
#include "platformsupport/scenes/opengl/egldisplay.h"
#include "platformsupport/scenes/opengl/openglbackend.h" #include "platformsupport/scenes/opengl/openglbackend.h"
#include "wayland/linuxdmabufv1clientbuffer.h" #include "wayland/linuxdmabufv1clientbuffer.h"
@ -19,9 +20,9 @@ struct wl_resource;
namespace KWin namespace KWin
{ {
typedef GLboolean (*eglBindWaylandDisplayWL_func)(EGLDisplay dpy, wl_display *display); typedef GLboolean (*eglBindWaylandDisplayWL_func)(::EGLDisplay dpy, wl_display *display);
typedef GLboolean (*eglUnbindWaylandDisplayWL_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 (*eglQueryWaylandBufferWL_func)(::EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
struct AbstractEglBackendFunctions struct AbstractEglBackendFunctions
{ {
@ -45,10 +46,7 @@ public:
{ {
return &m_functions; return &m_functions;
} }
EGLDisplay eglDisplay() const ::EGLDisplay eglDisplay() const;
{
return m_display;
}
EGLContext context() const EGLContext context() const
{ {
return m_context; return m_context;
@ -61,6 +59,7 @@ public:
{ {
return m_config; return m_config;
} }
EglDisplay *eglDisplayObject() const;
bool testImportBuffer(KWaylandServer::LinuxDmaBufV1ClientBuffer *buffer) override; bool testImportBuffer(KWaylandServer::LinuxDmaBufV1ClientBuffer *buffer) override;
QHash<uint32_t, QVector<uint64_t>> supportedFormats() const override; QHash<uint32_t, QVector<uint64_t>> supportedFormats() const override;
@ -75,14 +74,12 @@ public:
protected: protected:
AbstractEglBackend(dev_t deviceId = 0); AbstractEglBackend(dev_t deviceId = 0);
void setEglDisplay(const EGLDisplay &display);
void setSurface(const EGLSurface &surface); void setSurface(const EGLSurface &surface);
void setConfig(const EGLConfig &config); void setConfig(const EGLConfig &config);
void cleanup(); void cleanup();
virtual void cleanupSurfaces(); virtual void cleanupSurfaces();
bool initEglAPI(); void setEglDisplay(EglDisplay *display);
void initKWinGL(); void initKWinGL();
void initBufferAge();
void initClientExtensions(); void initClientExtensions();
void initWayland(); void initWayland();
bool hasClientExtension(const QByteArray &ext) const; bool hasClientExtension(const QByteArray &ext) const;
@ -98,7 +95,7 @@ private:
void teardown(); void teardown();
AbstractEglBackendFunctions m_functions; AbstractEglBackendFunctions m_functions;
EGLDisplay m_display = EGL_NO_DISPLAY; EglDisplay *m_display = nullptr;
EGLSurface m_surface = EGL_NO_SURFACE; EGLSurface m_surface = EGL_NO_SURFACE;
EGLContext m_context = EGL_NO_CONTEXT; EGLContext m_context = EGL_NO_CONTEXT;
EGLConfig m_config = nullptr; EGLConfig m_config = nullptr;

View file

@ -0,0 +1,170 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2023 Xaver Hugl <xaver.hugl@gmail.com>
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 <QOpenGLContext>
#include <drm_fourcc.h>
namespace KWin
{
static bool isOpenGLES()
{
if (qstrcmp(qgetenv("KWIN_COMPOSE"), "O2ES") == 0) {
return true;
}
return QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES;
}
std::unique_ptr<EglDisplay> 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<EglDisplay>(display, extensions, owning);
}
EglDisplay::EglDisplay(::EGLDisplay display, const QList<QByteArray> &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<QByteArray> 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<EGLint> 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());
}
}

View file

@ -0,0 +1,51 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2023 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "kwin_export.h"
#include <QByteArray>
#include <QList>
#include <epoxy/egl.h>
namespace KWin
{
struct DmaBufAttributes;
class GLTexture;
class KWIN_EXPORT EglDisplay
{
public:
EglDisplay(::EGLDisplay display, const QList<QByteArray> &extensions, bool owning = true);
~EglDisplay();
QList<QByteArray> 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<EglDisplay> create(::EGLDisplay display, bool owning = true);
private:
const ::EGLDisplay m_handle;
const QList<QByteArray> m_extensions;
const bool m_owning;
const bool m_supportsBufferAge;
const bool m_supportsSwapBuffersWithDamage;
const bool m_supportsNativeFence;
};
}

View file

@ -28,7 +28,7 @@ bool isOpenGLES()
return QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES; 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. // std::max as these values are initialized to -1 by default.
const EGLint redSize = std::max(surfaceFormat.redBufferSize(), 0); const EGLint redSize = std::max(surfaceFormat.redBufferSize(), 0);
@ -88,7 +88,7 @@ EGLConfig configFromFormat(EGLDisplay display, const QSurfaceFormat &surfaceForm
return configs[0]; return configs[0];
} }
QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config) QSurfaceFormat formatFromConfig(::EGLDisplay display, EGLConfig config)
{ {
int redSize = 0; int redSize = 0;
int blueSize = 0; int blueSize = 0;

View file

@ -20,8 +20,8 @@ namespace QPA
bool isOpenGLES(); bool isOpenGLES();
EGLConfig configFromFormat(EGLDisplay display, const QSurfaceFormat &surfaceFormat, EGLint surfaceType = 0); EGLConfig configFromFormat(::EGLDisplay display, const QSurfaceFormat &surfaceFormat, EGLint surfaceType = 0);
QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config); QSurfaceFormat formatFromConfig(::EGLDisplay display, EGLConfig config);
} // namespace QPA } // namespace QPA
} // namespace KWin } // namespace KWin

View file

@ -30,7 +30,7 @@ namespace KWin
namespace QPA namespace QPA
{ {
EGLPlatformContext::EGLPlatformContext(QOpenGLContext *context, EGLDisplay display) EGLPlatformContext::EGLPlatformContext(QOpenGLContext *context, ::EGLDisplay display)
: m_eglDisplay(display) : m_eglDisplay(display)
{ {
create(context->format(), kwinApp()->outputBackend()->sceneEglGlobalShareContext()); create(context->format(), kwinApp()->outputBackend()->sceneEglGlobalShareContext());
@ -43,7 +43,7 @@ EGLPlatformContext::~EGLPlatformContext()
} }
} }
EGLDisplay EGLPlatformContext::eglDisplay() const ::EGLDisplay EGLPlatformContext::eglDisplay() const
{ {
return m_eglDisplay; return m_eglDisplay;
} }

View file

@ -22,7 +22,7 @@ namespace QPA
class EGLPlatformContext : public QPlatformOpenGLContext class EGLPlatformContext : public QPlatformOpenGLContext
{ {
public: public:
EGLPlatformContext(QOpenGLContext *context, EGLDisplay display); EGLPlatformContext(QOpenGLContext *context, ::EGLDisplay display);
~EGLPlatformContext() override; ~EGLPlatformContext() override;
bool makeCurrent(QPlatformSurface *surface) override; bool makeCurrent(QPlatformSurface *surface) override;
@ -34,14 +34,14 @@ public:
QFunctionPointer getProcAddress(const char *procName) override; QFunctionPointer getProcAddress(const char *procName) override;
void swapBuffers(QPlatformSurface *surface) override; void swapBuffers(QPlatformSurface *surface) override;
EGLDisplay eglDisplay() const; ::EGLDisplay eglDisplay() const;
EGLContext eglContext() const; EGLContext eglContext() const;
private: private:
void create(const QSurfaceFormat &format, EGLContext shareContext); void create(const QSurfaceFormat &format, EGLContext shareContext);
void updateFormatFromContext(); void updateFormatFromContext();
EGLDisplay m_eglDisplay; ::EGLDisplay m_eglDisplay;
EGLConfig m_config = EGL_NO_CONFIG_KHR; EGLConfig m_config = EGL_NO_CONFIG_KHR;
EGLContext m_context = EGL_NO_CONTEXT; EGLContext m_context = EGL_NO_CONTEXT;
QSurfaceFormat m_format; QSurfaceFormat m_format;

View file

@ -146,7 +146,7 @@ QPlatformOpenGLContext *Integration::createPlatformOpenGLContext(QOpenGLContext
qCWarning(KWIN_QPA) << "Attempting to create a QOpenGLContext before the scene is initialized"; qCWarning(KWIN_QPA) << "Attempting to create a QOpenGLContext before the scene is initialized";
return nullptr; return nullptr;
} }
const EGLDisplay eglDisplay = kwinApp()->outputBackend()->sceneEglDisplay(); const ::EGLDisplay eglDisplay = kwinApp()->outputBackend()->sceneEglDisplay();
if (eglDisplay != EGL_NO_DISPLAY) { if (eglDisplay != EGL_NO_DISPLAY) {
EGLPlatformContext *platformContext = new EGLPlatformContext(context, eglDisplay); EGLPlatformContext *platformContext = new EGLPlatformContext(context, eglDisplay);
return platformContext; return platformContext;

View file

@ -32,7 +32,7 @@ public:
private: private:
QSurfaceFormat m_format; QSurfaceFormat m_format;
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; ::EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
EGLSurface m_surface = EGL_NO_SURFACE; EGLSurface m_surface = EGL_NO_SURFACE;
}; };

View file

@ -52,7 +52,7 @@ private:
QSurfaceFormat m_format; QSurfaceFormat m_format;
QPointer<InternalWindow> m_handle; QPointer<InternalWindow> m_handle;
std::shared_ptr<QOpenGLFramebufferObject> m_contentFBO; std::shared_ptr<QOpenGLFramebufferObject> m_contentFBO;
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; ::EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
quint32 m_windowId; quint32 m_windowId;
bool m_resized = false; bool m_resized = false;
qreal m_scale = 1; qreal m_scale = 1;

View file

@ -16,7 +16,7 @@ namespace KWin
#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1 #define EGL_NO_NATIVE_FENCE_FD_ANDROID -1
#endif // EGL_ANDROID_native_fence_sync #endif // EGL_ANDROID_native_fence_sync
EGLNativeFence::EGLNativeFence(EGLDisplay display) EGLNativeFence::EGLNativeFence(::EGLDisplay display)
: m_display(display) : m_display(display)
{ {
m_sync = eglCreateSyncKHR(m_display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr); m_sync = eglCreateSyncKHR(m_display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);

View file

@ -16,7 +16,7 @@ namespace KWin
class EGLNativeFence class EGLNativeFence
{ {
public: public:
explicit EGLNativeFence(EGLDisplay display); explicit EGLNativeFence(::EGLDisplay display);
~EGLNativeFence(); ~EGLNativeFence();
bool isValid() const; bool isValid() const;
@ -24,7 +24,7 @@ public:
private: private:
EGLSyncKHR m_sync = EGL_NO_SYNC_KHR; EGLSyncKHR m_sync = EGL_NO_SYNC_KHR;
EGLDisplay m_display = EGL_NO_DISPLAY; ::EGLDisplay m_display = EGL_NO_DISPLAY;
int m_fileDescriptor = -1; int m_fileDescriptor = -1;
Q_DISABLE_COPY(EGLNativeFence) Q_DISABLE_COPY(EGLNativeFence)

View file

@ -223,7 +223,7 @@ void Display::setEglDisplay(void *display)
qCWarning(KWIN_CORE) << "EGLDisplay cannot be changed"; qCWarning(KWIN_CORE) << "EGLDisplay cannot be changed";
return; return;
} }
d->eglDisplay = (EGLDisplay)display; d->eglDisplay = (::EGLDisplay)display;
new DrmClientBufferIntegration(this); new DrmClientBufferIntegration(this);
} }

View file

@ -51,7 +51,7 @@ public:
QVector<SeatInterface *> seats; QVector<SeatInterface *> seats;
QVector<ClientConnection *> clients; QVector<ClientConnection *> clients;
QStringList socketNames; QStringList socketNames;
EGLDisplay eglDisplay = EGL_NO_DISPLAY; ::EGLDisplay eglDisplay = EGL_NO_DISPLAY;
QHash<::wl_resource *, ClientBuffer *> resourceToBuffer; QHash<::wl_resource *, ClientBuffer *> resourceToBuffer;
QHash<ClientBuffer *, ClientBufferDestroyListener *> bufferToListener; QHash<ClientBuffer *, ClientBufferDestroyListener *> bufferToListener;
QList<ClientBufferIntegration *> bufferIntegrations; QList<ClientBufferIntegration *> bufferIntegrations;

View file

@ -17,7 +17,7 @@
namespace KWaylandServer 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; static eglQueryWaylandBufferWL_func eglQueryWaylandBufferWL = nullptr;
class DrmClientBufferPrivate : public ClientBufferPrivate class DrmClientBufferPrivate : public ClientBufferPrivate
@ -35,7 +35,7 @@ DrmClientBuffer::DrmClientBuffer(wl_resource *resource, DrmClientBufferIntegrati
{ {
Q_D(DrmClientBuffer); 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_TEXTURE_FORMAT, &d->textureFormat);
eglQueryWaylandBufferWL(eglDisplay, resource, EGL_WIDTH, &d->width); eglQueryWaylandBufferWL(eglDisplay, resource, EGL_WIDTH, &d->width);
eglQueryWaylandBufferWL(eglDisplay, resource, EGL_HEIGHT, &d->height); eglQueryWaylandBufferWL(eglDisplay, resource, EGL_HEIGHT, &d->height);
@ -77,7 +77,7 @@ DrmClientBufferIntegration::DrmClientBufferIntegration(Display *display)
ClientBuffer *DrmClientBufferIntegration::createBuffer(::wl_resource *resource) ClientBuffer *DrmClientBufferIntegration::createBuffer(::wl_resource *resource)
{ {
EGLDisplay eglDisplay = display()->eglDisplay(); ::EGLDisplay eglDisplay = display()->eglDisplay();
static bool resolved = false; static bool resolved = false;
if (!resolved && eglDisplay != EGL_NO_DISPLAY) { if (!resolved && eglDisplay != EGL_NO_DISPLAY) {
eglQueryWaylandBufferWL = (eglQueryWaylandBufferWL_func)eglGetProcAddress("eglQueryWaylandBufferWL"); eglQueryWaylandBufferWL = (eglQueryWaylandBufferWL_func)eglGetProcAddress("eglQueryWaylandBufferWL");