diff --git a/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp b/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp index 83b8d37752..c06cb83aa0 100644 --- a/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp +++ b/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp @@ -12,7 +12,7 @@ #include "options.h" #include "utils/common.h" #include "utils/egl_context_attribute_builder.h" -#include "wayland/display.h" +#include "wayland/drmclientbuffer.h" #include "wayland_server.h" // kwin libs #include "libkwineffects/kwineglimagetexture.h" @@ -25,6 +25,7 @@ #include #include +#include namespace KWin { @@ -79,9 +80,6 @@ void AbstractEglBackend::destroyGlobalShareContext() void AbstractEglBackend::teardown() { - if (m_functions.eglUnbindWaylandDisplayWL && m_display) { - m_functions.eglUnbindWaylandDisplayWL(m_display->handle(), *(WaylandServer::self()->display())); - } destroyGlobalShareContext(); } @@ -162,19 +160,29 @@ void AbstractEglBackend::initWayland() if (!WaylandServer::self()) { return; } - if (hasExtension(QByteArrayLiteral("EGL_WL_bind_wayland_display"))) { - m_functions.eglBindWaylandDisplayWL = (eglBindWaylandDisplayWL_func)eglGetProcAddress("eglBindWaylandDisplayWL"); - m_functions.eglUnbindWaylandDisplayWL = (eglUnbindWaylandDisplayWL_func)eglGetProcAddress("eglUnbindWaylandDisplayWL"); - m_functions.eglQueryWaylandBufferWL = (eglQueryWaylandBufferWL_func)eglGetProcAddress("eglQueryWaylandBufferWL"); - // only bind if not already done - if (waylandServer()->display()->eglDisplay() != eglDisplay()) { - if (!m_functions.eglBindWaylandDisplayWL(eglDisplay(), *(WaylandServer::self()->display()))) { - m_functions.eglUnbindWaylandDisplayWL = nullptr; - m_functions.eglQueryWaylandBufferWL = nullptr; + + if (m_deviceId) { + QString renderNode = m_display->renderNode(); + if (renderNode.isEmpty()) { + drmDevice *device = nullptr; + if (drmGetDeviceFromDevId(deviceId(), 0, &device) != 0) { + qCWarning(KWIN_OPENGL) << "drmGetDeviceFromDevId() failed:" << strerror(errno); } else { - waylandServer()->display()->setEglDisplay(eglDisplay()); + if (device->available_nodes & (1 << DRM_NODE_RENDER)) { + renderNode = QString::fromLocal8Bit(device->nodes[DRM_NODE_RENDER]); + } else if (device->available_nodes & (1 << DRM_NODE_PRIMARY)) { + qCWarning(KWIN_OPENGL) << "No render nodes have been found, falling back to primary node"; + renderNode = QString::fromLocal8Bit(device->nodes[DRM_NODE_PRIMARY]); + } + drmFreeDevice(&device); } } + + if (!renderNode.isEmpty()) { + waylandServer()->drm()->setDevice(renderNode); + } else { + qCWarning(KWIN_OPENGL) << "No render node have been found, not initializing wl-drm"; + } } auto filterFormats = [this](int bpc) { diff --git a/src/platformsupport/scenes/opengl/abstract_egl_backend.h b/src/platformsupport/scenes/opengl/abstract_egl_backend.h index 967135e282..a3fe8dbb57 100644 --- a/src/platformsupport/scenes/opengl/abstract_egl_backend.h +++ b/src/platformsupport/scenes/opengl/abstract_egl_backend.h @@ -21,17 +21,6 @@ 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); - -struct AbstractEglBackendFunctions -{ - eglBindWaylandDisplayWL_func eglBindWaylandDisplayWL = nullptr; - eglUnbindWaylandDisplayWL_func eglUnbindWaylandDisplayWL = nullptr; - eglQueryWaylandBufferWL_func eglQueryWaylandBufferWL = nullptr; -}; - struct DmaBufAttributes; class Output; @@ -43,10 +32,6 @@ public: bool makeCurrent() override; void doneCurrent() override; - const AbstractEglBackendFunctions *functions() const - { - return &m_functions; - } ::EGLDisplay eglDisplay() const; ::EGLContext context() const; EGLSurface surface() const; @@ -85,7 +70,6 @@ private: void teardown(); - AbstractEglBackendFunctions m_functions; EglDisplay *m_display = nullptr; EGLSurface m_surface = EGL_NO_SURFACE; std::unique_ptr m_context; diff --git a/src/platformsupport/scenes/opengl/basiceglsurfacetexture_wayland.cpp b/src/platformsupport/scenes/opengl/basiceglsurfacetexture_wayland.cpp index f0e7c0ad48..4d725518b0 100644 --- a/src/platformsupport/scenes/opengl/basiceglsurfacetexture_wayland.cpp +++ b/src/platformsupport/scenes/opengl/basiceglsurfacetexture_wayland.cpp @@ -9,19 +9,10 @@ #include "platformsupport/scenes/opengl/abstract_egl_backend.h" #include "scene/surfaceitem_wayland.h" #include "utils/common.h" -#include "wayland/drmclientbuffer.h" #include "wayland/linuxdmabufv1clientbuffer.h" #include "wayland/shmclientbuffer.h" -#ifndef EGL_WL_bind_wayland_display -#define EGL_WAYLAND_BUFFER_WL 0x31D5 -#define EGL_WAYLAND_PLANE_WL 0x31D6 -#define EGL_TEXTURE_Y_U_V_WL 0x31D7 -#define EGL_TEXTURE_Y_UV_WL 0x31D8 -#define EGL_TEXTURE_Y_XUXV_WL 0x31D9 -#define EGL_TEXTURE_EXTERNAL_WL 0x31DA -#define EGL_WAYLAND_Y_INVERTED_WL 0x31DB -#endif // EGL_WL_bind_wayland_display +#include namespace KWin { @@ -48,8 +39,6 @@ bool BasicEGLSurfaceTextureWayland::create() return loadDmabufTexture(buffer); } else if (auto buffer = qobject_cast(m_pixmap->buffer())) { return loadShmTexture(buffer); - } else if (auto buffer = qobject_cast(m_pixmap->buffer())) { - return loadEglTexture(buffer); } else { return false; } @@ -57,10 +46,6 @@ bool BasicEGLSurfaceTextureWayland::create() void BasicEGLSurfaceTextureWayland::destroy() { - if (m_image != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(backend()->eglDisplay(), m_image); - m_image = EGL_NO_IMAGE_KHR; - } m_texture.reset(); m_bufferType = BufferType::None; } @@ -71,8 +56,6 @@ void BasicEGLSurfaceTextureWayland::update(const QRegion ®ion) updateDmabufTexture(buffer); } else if (auto buffer = qobject_cast(m_pixmap->buffer())) { updateShmTexture(buffer, region); - } else if (auto buffer = qobject_cast(m_pixmap->buffer())) { - updateEglTexture(buffer); } } @@ -111,57 +94,6 @@ void BasicEGLSurfaceTextureWayland::updateShmTexture(KWaylandServer::ShmClientBu } } -bool BasicEGLSurfaceTextureWayland::loadEglTexture(KWaylandServer::DrmClientBuffer *buffer) -{ - const AbstractEglBackendFunctions *funcs = backend()->functions(); - if (Q_UNLIKELY(!funcs->eglQueryWaylandBufferWL)) { - return false; - } - if (Q_UNLIKELY(!buffer->resource())) { - return false; - } - - m_texture.reset(new GLTexture(GL_TEXTURE_2D)); - m_texture->setSize(buffer->size()); - m_texture->create(); - m_texture->setWrapMode(GL_CLAMP_TO_EDGE); - m_texture->setFilter(GL_LINEAR); - m_texture->bind(); - m_image = attach(buffer); - m_texture->unbind(); - m_bufferType = BufferType::Egl; - - if (EGL_NO_IMAGE_KHR == m_image) { - qCDebug(KWIN_OPENGL) << "failed to create egl image"; - m_texture.reset(); - return false; - } - - return true; -} - -void BasicEGLSurfaceTextureWayland::updateEglTexture(KWaylandServer::DrmClientBuffer *buffer) -{ - if (Q_UNLIKELY(m_bufferType != BufferType::Egl)) { - destroy(); - create(); - return; - } - if (Q_UNLIKELY(!buffer->resource())) { - return; - } - - m_texture->bind(); - EGLImageKHR image = attach(buffer); - m_texture->unbind(); - if (image != EGL_NO_IMAGE_KHR) { - if (m_image != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(backend()->eglDisplay(), m_image); - } - m_image = image; - } -} - bool BasicEGLSurfaceTextureWayland::loadDmabufTexture(KWaylandServer::LinuxDmaBufV1ClientBuffer *buffer) { EGLImageKHR image = backend()->importBufferAsImage(buffer); @@ -200,24 +132,4 @@ void BasicEGLSurfaceTextureWayland::updateDmabufTexture(KWaylandServer::LinuxDma m_texture->setContentTransform(buffer->origin() == KWaylandServer::ClientBuffer::Origin::TopLeft ? TextureTransform::MirrorY : TextureTransforms()); } -EGLImageKHR BasicEGLSurfaceTextureWayland::attach(KWaylandServer::DrmClientBuffer *buffer) -{ - if (buffer->textureFormat() != EGL_TEXTURE_RGB && buffer->textureFormat() != EGL_TEXTURE_RGBA) { - qCDebug(KWIN_OPENGL) << "Unsupported texture format: " << buffer->textureFormat(); - return EGL_NO_IMAGE_KHR; - } - - const EGLint attribs[] = { - EGL_WAYLAND_PLANE_WL, 0, - EGL_NONE}; - EGLImageKHR image = eglCreateImageKHR(backend()->eglDisplay(), EGL_NO_CONTEXT, - EGL_WAYLAND_BUFFER_WL, - static_cast(buffer->resource()), attribs); - if (image != EGL_NO_IMAGE_KHR) { - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, static_cast(image)); - m_texture->setContentTransform(buffer->origin() == KWaylandServer::ClientBuffer::Origin::TopLeft ? TextureTransform::MirrorY : TextureTransforms()); - } - return image; -} - } // namespace KWin diff --git a/src/platformsupport/scenes/opengl/basiceglsurfacetexture_wayland.h b/src/platformsupport/scenes/opengl/basiceglsurfacetexture_wayland.h index c02af3eb90..779b154916 100644 --- a/src/platformsupport/scenes/opengl/basiceglsurfacetexture_wayland.h +++ b/src/platformsupport/scenes/opengl/basiceglsurfacetexture_wayland.h @@ -8,11 +8,8 @@ #include "openglsurfacetexture_wayland.h" -#include - namespace KWaylandServer { -class DrmClientBuffer; class ShmClientBuffer; class LinuxDmaBufV1ClientBuffer; } @@ -36,21 +33,16 @@ public: private: bool loadShmTexture(KWaylandServer::ShmClientBuffer *buffer); void updateShmTexture(KWaylandServer::ShmClientBuffer *buffer, const QRegion ®ion); - bool loadEglTexture(KWaylandServer::DrmClientBuffer *buffer); - void updateEglTexture(KWaylandServer::DrmClientBuffer *buffer); bool loadDmabufTexture(KWaylandServer::LinuxDmaBufV1ClientBuffer *buffer); void updateDmabufTexture(KWaylandServer::LinuxDmaBufV1ClientBuffer *buffer); - EGLImageKHR attach(KWaylandServer::DrmClientBuffer *buffer); void destroy(); enum class BufferType { None, Shm, DmaBuf, - Egl, }; - EGLImageKHR m_image = EGL_NO_IMAGE_KHR; BufferType m_bufferType = BufferType::None; }; diff --git a/src/platformsupport/scenes/opengl/egldisplay.cpp b/src/platformsupport/scenes/opengl/egldisplay.cpp index 50c8264462..ff58687db6 100644 --- a/src/platformsupport/scenes/opengl/egldisplay.cpp +++ b/src/platformsupport/scenes/opengl/egldisplay.cpp @@ -16,6 +16,10 @@ #include #include +#ifndef EGL_DRM_RENDER_NODE_FILE_EXT +#define EGL_DRM_RENDER_NODE_FILE_EXT 0x3377 +#endif + namespace KWin { @@ -102,6 +106,54 @@ bool EglDisplay::hasExtension(const QByteArray &name) const return m_extensions.contains(name); } +static bool checkExtension(const QByteArrayView extensions, const QByteArrayView extension) +{ + for (int i = 0; i < extensions.size();) { + if (extensions[i] == ' ') { + i++; + continue; + } + int next = extensions.indexOf(' ', i); + if (next == -1) { + next = extensions.size(); + } + + const int size = next - i; + if (extension.size() == size && extensions.sliced(i, size) == extension) { + return true; + } + + i = next; + } + + return false; +} + +QString EglDisplay::renderNode() const +{ + const char *clientExtensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + if (checkExtension(clientExtensions, "EGL_EXT_device_query")) { + EGLAttrib eglDeviceAttrib; + if (eglQueryDisplayAttribEXT(m_handle, EGL_DEVICE_EXT, &eglDeviceAttrib)) { + EGLDeviceEXT eglDevice = reinterpret_cast(eglDeviceAttrib); + + const char *deviceExtensions = eglQueryDeviceStringEXT(eglDevice, EGL_EXTENSIONS); + if (checkExtension(deviceExtensions, "EGL_EXT_device_drm_render_node")) { + if (const char *node = eglQueryDeviceStringEXT(eglDevice, EGL_DRM_RENDER_NODE_FILE_EXT)) { + return QString::fromLocal8Bit(node); + } + } + if (checkExtension(deviceExtensions, "EGL_EXT_device_drm")) { + // Fallback to display device. + if (const char *node = eglQueryDeviceStringEXT(eglDevice, EGL_DRM_DEVICE_FILE_EXT)) { + return QString::fromLocal8Bit(node); + } + } + } + } + return QString(); +} + bool EglDisplay::supportsBufferAge() const { return m_supportsBufferAge; diff --git a/src/platformsupport/scenes/opengl/egldisplay.h b/src/platformsupport/scenes/opengl/egldisplay.h index 183a6a3324..a1e3d8a677 100644 --- a/src/platformsupport/scenes/opengl/egldisplay.h +++ b/src/platformsupport/scenes/opengl/egldisplay.h @@ -31,6 +31,8 @@ public: ::EGLDisplay handle() const; bool hasExtension(const QByteArray &name) const; + QString renderNode() const; + bool supportsBufferAge() const; bool supportsSwapBuffersWithDamage() const; bool supportsNativeFence() const; diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt index de786fa3a6..d466149f7c 100644 --- a/src/wayland/CMakeLists.txt +++ b/src/wayland/CMakeLists.txt @@ -200,11 +200,14 @@ ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/kde-output-order-v1.xml BASENAME kde-output-order-v1 ) - ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml PROTOCOL ${WaylandProtocols_DATADIR}/staging/fractional-scale/fractional-scale-v1.xml BASENAME fractional-scale-v1 ) +ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml + PROTOCOL ${PROJECT_SOURCE_DIR}/src/wayland/protocols/wayland-drm.xml + BASENAME drm +) target_sources(kwin PRIVATE abstract_data_source.cpp diff --git a/src/wayland/display.cpp b/src/wayland/display.cpp index 9f8a559fef..f383315024 100644 --- a/src/wayland/display.cpp +++ b/src/wayland/display.cpp @@ -7,7 +7,6 @@ #include "display.h" #include "clientbufferintegration.h" #include "display_p.h" -#include "drmclientbuffer.h" #include "output_interface.h" #include "shmclientbuffer.h" #include "utils/common.h" @@ -217,21 +216,6 @@ ClientConnection *Display::createClient(int fd) return getConnection(c); } -void Display::setEglDisplay(void *display) -{ - if (d->eglDisplay != EGL_NO_DISPLAY) { - qCWarning(KWIN_CORE) << "EGLDisplay cannot be changed"; - return; - } - d->eglDisplay = (::EGLDisplay)display; - new DrmClientBufferIntegration(this); -} - -void *Display::eglDisplay() const -{ - return d->eglDisplay; -} - struct ClientBufferDestroyListener : wl_listener { ClientBufferDestroyListener(Display *display, ClientBuffer *buffer); diff --git a/src/wayland/display.h b/src/wayland/display.h index 5e26b7b039..7a3f9a341e 100644 --- a/src/wayland/display.h +++ b/src/wayland/display.h @@ -125,21 +125,6 @@ public: ClientConnection *getConnection(wl_client *client); QVector connections() const; - /** - * Set the EGL @p display for this Wayland display. - * The EGLDisplay can only be set once and must be alive as long as the Wayland display - * is alive. The user should have set up the binding between the EGLDisplay and the - * Wayland display prior to calling this method. - * - * @see eglDisplay - */ - void setEglDisplay(void *display); - /** - * @returns the EGLDisplay used for this Wayland display or EGL_NO_DISPLAY if not set. - * @see setEglDisplay - */ - void *eglDisplay() const; - /** * Returns the client buffer with the specified @a resource. Returns @c null if there's * no such a buffer. diff --git a/src/wayland/display_p.h b/src/wayland/display_p.h index a28d77229f..efdf9ab631 100644 --- a/src/wayland/display_p.h +++ b/src/wayland/display_p.h @@ -15,8 +15,6 @@ #include #include -#include - struct wl_resource; namespace KWaylandServer @@ -51,7 +49,6 @@ public: QVector seats; QVector clients; QStringList socketNames; - ::EGLDisplay eglDisplay = EGL_NO_DISPLAY; QHash<::wl_resource *, ClientBuffer *> resourceToBuffer; QHash bufferToListener; QList bufferIntegrations; diff --git a/src/wayland/drmclientbuffer.cpp b/src/wayland/drmclientbuffer.cpp index 24ef8ccd23..f7d67a3ff2 100644 --- a/src/wayland/drmclientbuffer.cpp +++ b/src/wayland/drmclientbuffer.cpp @@ -5,90 +5,132 @@ */ #include "drmclientbuffer.h" -#include "clientbuffer_p.h" #include "display.h" +#include "utils/common.h" -#include -#include - -#ifndef EGL_WL_bind_wayland_display -#define EGL_WAYLAND_Y_INVERTED_WL 0x31DB -#endif +#include "qwayland-server-drm.h" namespace KWaylandServer { -typedef EGLBoolean (*eglQueryWaylandBufferWL_func)(::EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); -static eglQueryWaylandBufferWL_func eglQueryWaylandBufferWL = nullptr; -class DrmClientBufferPrivate : public ClientBufferPrivate +static constexpr int s_version = 2; + +class DrmClientBufferIntegrationPrivate : public QtWaylandServer::wl_drm { public: - int textureFormat = 0; - int width = 0; - int height = 0; - int yInverted = 0; - bool hasAlphaChannel = false; + explicit DrmClientBufferIntegrationPrivate(Display *display); + + QString nodeName; + +protected: + void drm_bind_resource(Resource *resource) override; + void drm_authenticate(Resource *resource, uint32_t id) override; + void drm_create_buffer(Resource *resource, + uint32_t id, + uint32_t name, + int32_t width, + int32_t height, + uint32_t stride, + uint32_t format) override; + void drm_create_planar_buffer(Resource *resource, + uint32_t id, + uint32_t name, + int32_t width, + int32_t height, + uint32_t format, + int32_t offset0, + int32_t stride0, + int32_t offset1, + int32_t stride1, + int32_t offset2, + int32_t stride2) override; + void drm_create_prime_buffer(Resource *resource, + uint32_t id, + int32_t name, + int32_t width, + int32_t height, + uint32_t format, + int32_t offset0, + int32_t stride0, + int32_t offset1, + int32_t stride1, + int32_t offset2, + int32_t stride2) override; }; -DrmClientBuffer::DrmClientBuffer(wl_resource *resource, DrmClientBufferIntegration *integration) - : ClientBuffer(resource, *new DrmClientBufferPrivate) +DrmClientBufferIntegrationPrivate::DrmClientBufferIntegrationPrivate(Display *display) + : QtWaylandServer::wl_drm(*display, s_version) { - Q_D(DrmClientBuffer); - - ::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); - - if (!eglQueryWaylandBufferWL(eglDisplay, resource, EGL_WAYLAND_Y_INVERTED_WL, &d->yInverted)) { - // If EGL_WAYLAND_Y_INVERTED_WL is unsupported, we must assume that the buffer is inverted. - d->yInverted = true; - } } -int DrmClientBuffer::textureFormat() const +void DrmClientBufferIntegrationPrivate::drm_bind_resource(Resource *resource) { - Q_D(const DrmClientBuffer); - return d->textureFormat; + send_device(resource->handle, nodeName); + send_capabilities(resource->handle, capability_prime); } -QSize DrmClientBuffer::size() const +void DrmClientBufferIntegrationPrivate::drm_authenticate(Resource *resource, uint32_t id) { - Q_D(const DrmClientBuffer); - return QSize(d->width, d->height); + send_authenticated(resource->handle); } -bool DrmClientBuffer::hasAlphaChannel() const +void DrmClientBufferIntegrationPrivate::drm_create_buffer(Resource *resource, + uint32_t id, + uint32_t name, + int32_t width, + int32_t height, + uint32_t stride, + uint32_t format) { - Q_D(const DrmClientBuffer); - return d->textureFormat == EGL_TEXTURE_RGBA; + wl_resource_post_error(resource->handle, 0, "wl_drm.create_buffer is not implemented"); } -ClientBuffer::Origin DrmClientBuffer::origin() const +void DrmClientBufferIntegrationPrivate::drm_create_planar_buffer(Resource *resource, + uint32_t id, + uint32_t name, + int32_t width, + int32_t height, + uint32_t format, + int32_t offset0, + int32_t stride0, + int32_t offset1, + int32_t stride1, + int32_t offset2, + int32_t stride2) { - Q_D(const DrmClientBuffer); - return d->yInverted ? Origin::TopLeft : Origin::BottomLeft; + wl_resource_post_error(resource->handle, 0, "wl_drm.create_planar_buffer is not implemented"); +} + +void DrmClientBufferIntegrationPrivate::drm_create_prime_buffer(Resource *resource, + uint32_t id, + int32_t name, + int32_t width, + int32_t height, + uint32_t format, + int32_t offset0, + int32_t stride0, + int32_t offset1, + int32_t stride1, + int32_t offset2, + int32_t stride2) +{ + close(name); + wl_resource_post_error(resource->handle, 0, "wl_drm.create_prime_buffer is not implemented"); } DrmClientBufferIntegration::DrmClientBufferIntegration(Display *display) : ClientBufferIntegration(display) + , d(std::make_unique(display)) { } -ClientBuffer *DrmClientBufferIntegration::createBuffer(::wl_resource *resource) +DrmClientBufferIntegration::~DrmClientBufferIntegration() { - ::EGLDisplay eglDisplay = display()->eglDisplay(); - static bool resolved = false; - if (!resolved && eglDisplay != EGL_NO_DISPLAY) { - eglQueryWaylandBufferWL = (eglQueryWaylandBufferWL_func)eglGetProcAddress("eglQueryWaylandBufferWL"); - resolved = true; - } +} - EGLint format; - if (eglQueryWaylandBufferWL(eglDisplay, resource, EGL_TEXTURE_FORMAT, &format)) { - return new DrmClientBuffer(resource, this); - } - return nullptr; +void DrmClientBufferIntegration::setDevice(const QString &node) +{ + d->nodeName = node; } } // namespace KWaylandServer diff --git a/src/wayland/drmclientbuffer.h b/src/wayland/drmclientbuffer.h index 31eb3c2fa0..8fd877f203 100644 --- a/src/wayland/drmclientbuffer.h +++ b/src/wayland/drmclientbuffer.h @@ -6,15 +6,22 @@ #pragma once -#include "clientbuffer.h" #include "clientbufferintegration.h" namespace KWaylandServer { -class DrmClientBufferPrivate; +class DrmClientBufferIntegrationPrivate; /** - * The DrmClientBufferIntegration class provides support for wl_drm client buffers. + * The DrmClientBufferIntegration provides a stub implementation for the wl_drm + * protocol. + * + * It provides the minimum amount of information to Xwayland so it can run. No + * ClientBuffers are provided by the DrmClientBufferIntegration. Xwayland is + * expected to provide us linux dmabuf client buffers instead. + * + * Once the wl_drm protocol is no longer mandatory in Xwayland, this stub can be + * dropped. */ class KWIN_EXPORT DrmClientBufferIntegration : public ClientBufferIntegration { @@ -22,30 +29,12 @@ class KWIN_EXPORT DrmClientBufferIntegration : public ClientBufferIntegration public: explicit DrmClientBufferIntegration(Display *display); + ~DrmClientBufferIntegration() override; - ClientBuffer *createBuffer(::wl_resource *resource) override; -}; + void setDevice(const QString &node); -/** - * The DrmClientBuffer class represents a wl_drm client buffer. - * - * Nowadays, the wl_drm protocol is de-facto deprecated with the introduction of the - * linux-dmabuf-v1 protocol. Note that Vulkan WSI in Mesa still prefers wl_drm, but - * that's about to change, https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4942/ - */ -class KWIN_EXPORT DrmClientBuffer : public ClientBuffer -{ - Q_OBJECT - Q_DECLARE_PRIVATE(DrmClientBuffer) - -public: - explicit DrmClientBuffer(wl_resource *resource, DrmClientBufferIntegration *integration); - - int textureFormat() const; - - QSize size() const override; - bool hasAlphaChannel() const override; - Origin origin() const override; +private: + std::unique_ptr d; }; } // namespace KWaylandServer diff --git a/src/wayland/protocols/wayland-drm.xml b/src/wayland/protocols/wayland-drm.xml new file mode 100644 index 0000000000..eaf2654ab2 --- /dev/null +++ b/src/wayland/protocols/wayland-drm.xml @@ -0,0 +1,189 @@ + + + + + Copyright © 2008-2011 Kristian Høgsberg + Copyright © 2010-2011 Intel Corporation + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that\n the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bitmask of capabilities. + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wayland_server.cpp b/src/wayland_server.cpp index 01a441ad62..5f2cbfdb9f 100644 --- a/src/wayland_server.cpp +++ b/src/wayland_server.cpp @@ -26,6 +26,7 @@ #include "wayland/datadevicemanager_interface.h" #include "wayland/display.h" #include "wayland/dpms_interface.h" +#include "wayland/drmclientbuffer.h" #include "wayland/drmlease_v1_interface.h" #include "wayland/filtered_display.h" #include "wayland/fractionalscale_v1_interface.h" @@ -512,6 +513,14 @@ bool WaylandServer::init(InitializationFlags flags) return true; } +KWaylandServer::DrmClientBufferIntegration *WaylandServer::drm() +{ + if (!m_drm) { + m_drm = new DrmClientBufferIntegration(m_display); + } + return m_drm; +} + KWaylandServer::LinuxDmaBufV1ClientBufferIntegration *WaylandServer::linuxDmabuf() { if (!m_linuxDmabuf) { diff --git a/src/wayland_server.h b/src/wayland_server.h index f7bb1ace20..1cda45bec5 100644 --- a/src/wayland_server.h +++ b/src/wayland_server.h @@ -37,6 +37,7 @@ class OutputDeviceV2Interface; class OutputManagementV2Interface; class XdgForeignV2Interface; class XdgOutputManagerV1Interface; +class DrmClientBufferIntegration; class LinuxDmaBufV1ClientBufferIntegration; class TabletManagerV2Interface; class KeyboardShortcutsInhibitManagerV1Interface; @@ -130,6 +131,7 @@ public: bool isKeyboardShortcutsInhibited() const; + KWaylandServer::DrmClientBufferIntegration *drm(); KWaylandServer::LinuxDmaBufV1ClientBufferIntegration *linuxDmabuf(); KWaylandServer::InputMethodV1Interface *inputMethod() const @@ -264,6 +266,7 @@ private: KWaylandServer::IdleInterface *m_idle = nullptr; KWaylandServer::XdgOutputManagerV1Interface *m_xdgOutputManagerV1 = nullptr; KWaylandServer::XdgDecorationManagerV1Interface *m_xdgDecorationManagerV1 = nullptr; + KWaylandServer::DrmClientBufferIntegration *m_drm = nullptr; KWaylandServer::LinuxDmaBufV1ClientBufferIntegration *m_linuxDmabuf = nullptr; KWaylandServer::KeyboardShortcutsInhibitManagerV1Interface *m_keyboardShortcutsInhibitManager = nullptr; QPointer m_xwaylandConnection;