platformsupport/scenes: move egldisplay code into a helper class
This commit is contained in:
parent
acf38d364b
commit
48fb07b367
38 changed files with 407 additions and 251 deletions
|
@ -535,4 +535,9 @@ const std::vector<std::unique_ptr<DrmGpu>> &DrmBackend::gpus() const
|
|||
{
|
||||
return m_gpus;
|
||||
}
|
||||
|
||||
EglDisplay *DrmBackend::sceneEglDisplayObject() const
|
||||
{
|
||||
return m_gpus.front()->eglDisplay();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public:
|
|||
std::unique_ptr<InputBackend> createInputBackend() override;
|
||||
std::unique_ptr<QPainterBackend> createQPainterBackend() 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::shared_ptr<DmaBufTexture> createDmaBufTexture(const QSize &size, quint32 format, const uint64_t modifier) override;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<EglDisplay> &&display)
|
||||
{
|
||||
m_eglDisplay = display;
|
||||
m_eglDisplay = std::move(display);
|
||||
}
|
||||
|
||||
bool DrmGpu::addFB2ModifiersSupported() const
|
||||
|
|
|
@ -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<DrmOutput *> drmOutputs() const;
|
||||
const QVector<DrmPipeline *> pipelines() const;
|
||||
|
||||
void setEglDisplay(EGLDisplay display);
|
||||
void setEglDisplay(std::unique_ptr<EglDisplay> &&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<EglDisplay> m_eglDisplay;
|
||||
DrmBackend *const m_platform;
|
||||
|
||||
std::vector<std::unique_ptr<DrmPlane>> m_planes;
|
||||
|
|
|
@ -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<QRect> &geometries, QVector
|
|||
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
|
||||
|
|
|
@ -44,6 +44,9 @@ public:
|
|||
return QVector<CompositingType>{OpenGLCompositing, QPainterCompositing};
|
||||
}
|
||||
|
||||
void setEglDisplay(std::unique_ptr<EglDisplay> &&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<VirtualOutput *> m_outputs;
|
||||
std::unique_ptr<EglDisplay> m_display;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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<DmaBufTexture> WaylandBackend::createDmaBufTexture(const QSize &
|
|||
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
|
||||
|
|
|
@ -229,6 +229,8 @@ public:
|
|||
{
|
||||
m_eglBackend = eglBackend;
|
||||
}
|
||||
void setEglDisplay(std::unique_ptr<EglDisplay> &&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<EglDisplay> m_eglDisplay;
|
||||
};
|
||||
|
||||
} // namespace Wayland
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<EglDisplay> &&display)
|
||||
{
|
||||
m_eglDisplay = std::move(display);
|
||||
}
|
||||
|
||||
EglDisplay *X11StandaloneBackend::sceneEglDisplayObject() const
|
||||
{
|
||||
return m_eglDisplay.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,9 @@ public:
|
|||
RenderLoop *renderLoop() const;
|
||||
Outputs outputs() const override;
|
||||
|
||||
void setEglDisplay(std::unique_ptr<EglDisplay> &&display);
|
||||
EglDisplay *sceneEglDisplayObject() const override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Tests whether GLX is supported and returns @c true
|
||||
|
@ -98,6 +101,7 @@ private:
|
|||
std::unique_ptr<X11Keyboard> m_keyboard;
|
||||
std::unique_ptr<RenderLoop> m_renderLoop;
|
||||
QVector<Output *> m_outputs;
|
||||
std::unique_ptr<EglDisplay> m_eglDisplay;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ std::unique_ptr<SurfaceTexture> 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<GLFramebuffer>(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),
|
||||
|
|
|
@ -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<EglDisplay> &&display)
|
||||
{
|
||||
m_eglDisplay = std::move(display);
|
||||
}
|
||||
|
||||
EglDisplay *X11WindowedBackend::sceneEglDisplayObject() const
|
||||
{
|
||||
return m_eglDisplay.get();
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -124,6 +124,9 @@ public:
|
|||
X11WindowedInputDevice *keyboardDevice() const;
|
||||
X11WindowedInputDevice *touchDevice() const;
|
||||
|
||||
void setEglDisplay(std::unique_ptr<EglDisplay> &&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<EglDisplay> m_eglDisplay;
|
||||
|
||||
QVector<X11WindowedOutput *> m_outputs;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -28,6 +28,7 @@ class OpenGLBackend;
|
|||
class QPainterBackend;
|
||||
class OutputConfiguration;
|
||||
struct DmaBufParams;
|
||||
class EglDisplay;
|
||||
|
||||
class KWIN_EXPORT Outputs : public QVector<Output *>
|
||||
{
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<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
|
||||
<< 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<GLTexture> AbstractEglBackend::importDmaBufAsTexture(const DmaBufAttributes &attributes) const
|
||||
{
|
||||
EGLImageKHR image = importDmaBufAsImage(attributes);
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<uint32_t, QVector<uint64_t>> 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;
|
||||
|
|
170
src/platformsupport/scenes/opengl/egldisplay.cpp
Normal file
170
src/platformsupport/scenes/opengl/egldisplay.cpp
Normal 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());
|
||||
}
|
||||
}
|
51
src/platformsupport/scenes/opengl/egldisplay.h
Normal file
51
src/platformsupport/scenes/opengl/egldisplay.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ private:
|
|||
QSurfaceFormat m_format;
|
||||
QPointer<InternalWindow> m_handle;
|
||||
std::shared_ptr<QOpenGLFramebufferObject> 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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
QVector<SeatInterface *> seats;
|
||||
QVector<ClientConnection *> clients;
|
||||
QStringList socketNames;
|
||||
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
|
||||
::EGLDisplay eglDisplay = EGL_NO_DISPLAY;
|
||||
QHash<::wl_resource *, ClientBuffer *> resourceToBuffer;
|
||||
QHash<ClientBuffer *, ClientBufferDestroyListener *> bufferToListener;
|
||||
QList<ClientBufferIntegration *> bufferIntegrations;
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in a new issue