diff --git a/plugins/platforms/drm/CMakeLists.txt b/plugins/platforms/drm/CMakeLists.txt index eff0f8e938..9a4fd4d2dc 100644 --- a/plugins/platforms/drm/CMakeLists.txt +++ b/plugins/platforms/drm/CMakeLists.txt @@ -18,6 +18,7 @@ if (HAVE_GBM) egl_gbm_backend.cpp drm_buffer_gbm.cpp gbm_surface.cpp + gbm_dmabuf.cpp remoteaccess_manager.cpp ) endif() diff --git a/plugins/platforms/drm/drm_backend.cpp b/plugins/platforms/drm/drm_backend.cpp index 97f1b3f653..3e444ed36d 100644 --- a/plugins/platforms/drm/drm_backend.cpp +++ b/plugins/platforms/drm/drm_backend.cpp @@ -34,6 +34,7 @@ along with this program. If not, see . #if HAVE_GBM #include "egl_gbm_backend.h" #include +#include "gbm_dmabuf.h" #endif #if HAVE_EGL_STREAMS #include "egl_stream_backend.h" @@ -818,4 +819,13 @@ QString DrmBackend::supportInformation() const return supportInfo; } +DmaBufTexture *DrmBackend::createDmaBufTexture(const QSize &size) +{ +#if HAVE_GBM + return GbmDmaBuf::createBuffer(size, m_gbmDevice); +#else + return nullptr; +#endif +} + } diff --git a/plugins/platforms/drm/drm_backend.h b/plugins/platforms/drm/drm_backend.h index 93333279a6..63ddecdf72 100644 --- a/plugins/platforms/drm/drm_backend.h +++ b/plugins/platforms/drm/drm_backend.h @@ -55,7 +55,6 @@ class DrmConnector; class GbmSurface; class Cursor; - class KWIN_EXPORT DrmBackend : public Platform { Q_OBJECT @@ -68,6 +67,7 @@ public: Screens *createScreens(QObject *parent = nullptr) override; QPainterBackend *createQPainterBackend() override; OpenGLBackend* createOpenGLBackend() override; + DmaBufTexture *createDmaBufTexture(const QSize &size) override; void init() override; void prepareShutdown() override; diff --git a/plugins/platforms/drm/gbm_dmabuf.cpp b/plugins/platforms/drm/gbm_dmabuf.cpp new file mode 100644 index 0000000000..535eb21845 --- /dev/null +++ b/plugins/platforms/drm/gbm_dmabuf.cpp @@ -0,0 +1,81 @@ +/* + * Copyright © 2020 Aleix Pol Gonzalez + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Aleix Pol Gonzalez + */ + +#include "gbm_dmabuf.h" +#include "kwineglimagetexture.h" +#include "platformsupport/scenes/opengl/drm_fourcc.h" +#include "main.h" +#include "platform.h" +#include + +namespace KWin +{ + +GbmDmaBuf::GbmDmaBuf(GLTexture *texture, gbm_bo *bo, int fd) + : DmaBufTexture(texture) + , m_bo(bo) + , m_fd(fd) +{} + +GbmDmaBuf::~GbmDmaBuf() +{ + m_texture.reset(nullptr); + + close(m_fd); + gbm_bo_destroy(m_bo); +} + + +KWin::GbmDmaBuf *GbmDmaBuf::createBuffer(const QSize &size, gbm_device *device) +{ + auto bo = gbm_bo_create(device, size.width(), size.height(), GBM_BO_FORMAT_ARGB8888, GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR); + + if (!bo) { + gbm_bo_destroy(bo); + return nullptr; + } + + const int fd = gbm_bo_get_fd(bo); + if (fd < 0) { + gbm_bo_destroy(bo); + return nullptr; + } + + EGLint importAttributes[] = { + EGL_WIDTH, EGLint(gbm_bo_get_width(bo)), + EGL_HEIGHT, EGLint(gbm_bo_get_height(bo)), + EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, + EGL_DMA_BUF_PLANE0_FD_EXT, fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGLint(gbm_bo_get_offset(bo, 0)), + EGL_DMA_BUF_PLANE0_PITCH_EXT, EGLint(gbm_bo_get_stride(bo)), + EGL_NONE + }; + + EGLDisplay display = kwinApp()->platform()->sceneEglDisplay(); + EGLImageKHR destinationImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, importAttributes); + if (destinationImage == EGL_NO_IMAGE_KHR) { + return nullptr; + } + + return new GbmDmaBuf(new KWin::EGLImageTexture(display, destinationImage, GL_RGBA8, size), bo, fd); +} + +} + diff --git a/plugins/platforms/drm/gbm_dmabuf.h b/plugins/platforms/drm/gbm_dmabuf.h new file mode 100644 index 0000000000..a22f2aeeeb --- /dev/null +++ b/plugins/platforms/drm/gbm_dmabuf.h @@ -0,0 +1,52 @@ +/* + * Copyright © 2020 Aleix Pol Gonzalez + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Aleix Pol Gonzalez + */ + +#pragma once + +#include "dmabuftexture.h" +#include +#include +#include + +namespace KWin +{ + +class GbmDmaBuf : public DmaBufTexture +{ +public: + ~GbmDmaBuf(); + + int fd() const override + { + return m_fd; + } + quint32 stride() const override { + return gbm_bo_get_stride(m_bo); + } + + static GbmDmaBuf *createBuffer(const QSize &size, gbm_device *device); + +private: + GbmDmaBuf(GLTexture *texture, gbm_bo *bo, int fd); + struct gbm_bo *const m_bo; + const int m_fd; +}; + +} diff --git a/plugins/platforms/wayland/CMakeLists.txt b/plugins/platforms/wayland/CMakeLists.txt index 13320b4dc4..700b5514c2 100644 --- a/plugins/platforms/wayland/CMakeLists.txt +++ b/plugins/platforms/wayland/CMakeLists.txt @@ -3,6 +3,7 @@ set(WAYLAND_BACKEND_SOURCES scene_qpainter_wayland_backend.cpp wayland_backend.cpp wayland_output.cpp + ../drm/gbm_dmabuf.cpp ) if (HAVE_WAYLAND_EGL) @@ -15,7 +16,7 @@ set_target_properties(KWinWaylandWaylandBackend PROPERTIES LIBRARY_OUTPUT_DIRECT target_link_libraries(KWinWaylandWaylandBackend kwin KF5::WaylandClient SceneQPainterBackend) if (HAVE_WAYLAND_EGL) - target_link_libraries(KWinWaylandWaylandBackend SceneOpenGLBackend Wayland::Egl) + target_link_libraries(KWinWaylandWaylandBackend SceneOpenGLBackend Wayland::Egl gbm::gbm) endif() install( diff --git a/plugins/platforms/wayland/wayland_backend.cpp b/plugins/platforms/wayland/wayland_backend.cpp index 804dc8c9d4..bd8bffd7fd 100644 --- a/plugins/platforms/wayland/wayland_backend.cpp +++ b/plugins/platforms/wayland/wayland_backend.cpp @@ -35,6 +35,7 @@ along with this program. If not, see . #include "pointer_input.h" #include "screens.h" #include "wayland_server.h" +#include "../drm/gbm_dmabuf.h" #include @@ -64,6 +65,9 @@ along with this program. If not, see . #include #include +#include +#include +#include namespace KWin { @@ -451,8 +455,18 @@ WaylandBackend::WaylandBackend(QObject *parent) , m_connectionThreadObject(new ConnectionThread(nullptr)) , m_connectionThread(nullptr) { - connect(this, &WaylandBackend::connectionFailed, this, &WaylandBackend::initFailed); supportsOutputChanges(); + connect(this, &WaylandBackend::connectionFailed, this, &WaylandBackend::initFailed); + + + char const *drm_render_node = "/dev/dri/renderD128"; + m_drm_fd = open(drm_render_node, O_RDWR); + if (m_drm_fd < 0) { + qCWarning(KWIN_WAYLAND_BACKEND) << "Failed to open drm render node" << drm_render_node; + m_gbmDevice = nullptr; + return; + } + m_gbmDevice = gbm_create_device(m_drm_fd); } WaylandBackend::~WaylandBackend() @@ -477,6 +491,8 @@ WaylandBackend::~WaylandBackend() m_connectionThread->quit(); m_connectionThread->wait(); m_connectionThreadObject->deleteLater(); + gbm_device_destroy(m_gbmDevice); + close(m_drm_fd); qCDebug(KWIN_WAYLAND_BACKEND) << "Destroyed Wayland display"; } @@ -835,6 +851,11 @@ Outputs WaylandBackend::enabledOutputs() const return m_outputs; } +DmaBufTexture *WaylandBackend::createDmaBufTexture(const QSize& size) +{ + return GbmDmaBuf::createBuffer(size, m_gbmDevice); +} + } } // KWin diff --git a/plugins/platforms/wayland/wayland_backend.h b/plugins/platforms/wayland/wayland_backend.h index e9cda4b139..dfdec642d0 100644 --- a/plugins/platforms/wayland/wayland_backend.h +++ b/plugins/platforms/wayland/wayland_backend.h @@ -36,6 +36,7 @@ struct wl_buffer; struct wl_display; struct wl_event_queue; struct wl_seat; +struct gbm_device; namespace KWayland { @@ -184,6 +185,7 @@ public: Screens *createScreens(QObject *parent = nullptr) override; OpenGLBackend *createOpenGLBackend() override; QPainterBackend *createQPainterBackend() override; + DmaBufTexture *createDmaBufTexture(const QSize &size) override; void flush(); @@ -248,6 +250,8 @@ private: WaylandCursor *m_waylandCursor = nullptr; bool m_pointerLockRequested = false; + int m_drmFileDescriptor = 0; + gbm_device *m_gbmDevice; }; inline