Commit 42e543c5 authored by Aleix Pol Gonzalez's avatar Aleix Pol Gonzalez 🐧
Browse files

screencasting: implement intefraces to create dmabuf textures

parent 38eb72ef
......@@ -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()
......
......@@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#if HAVE_GBM
#include "egl_gbm_backend.h"
#include <gbm.h>
#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
}
}
......@@ -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;
......
/*
* Copyright © 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*
* Authors:
* Aleix Pol Gonzalez <aleixpol@kde.org>
*/
#include "gbm_dmabuf.h"
#include "kwineglimagetexture.h"
#include "platformsupport/scenes/opengl/drm_fourcc.h"
#include "main.h"
#include "platform.h"
#include <unistd.h>
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);
}
}
/*
* Copyright © 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*
* Authors:
* Aleix Pol Gonzalez <aleixpol@kde.org>
*/
#pragma once
#include "dmabuftexture.h"
#include <gbm.h>
#include <QSize>
#include <epoxy/egl.h>
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;
};
}
......@@ -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(
......
......@@ -35,6 +35,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "pointer_input.h"
#include "screens.h"
#include "wayland_server.h"
#include "../drm/gbm_dmabuf.h"
#include <config-kwin.h>
......@@ -64,6 +65,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <linux/input.h>
#include <wayland-cursor.h>
#include <unistd.h>
#include <gbm.h>
  • @apol @vladz The toplevel CMakeLists.txt says gbm is an optional dependency. This code uses it unconditionally.

    I tried fixing things a bit with http://www.davidfaure.fr/2020/kwin_gbm.diff (cmake and includes) but the actual C++ code is also unconditional.

    /d/kde/src/5/kde/workspace/kwin/plugins/platforms/wayland/wayland_backend.cpp: In constructor ‘KWin::Wayland::WaylandBackend::WaylandBackend(QObject*)’:
    /d/kde/src/5/kde/workspace/kwin/plugins/platforms/wayland/wayland_backend.cpp:459:19: error: ‘gbm_create_device’ was not declared in this scope
      459 |     m_gbmDevice = gbm_create_device(m_drmFileDescriptor);
          |                   ^~~~~~~~~~~~~~~~~
    /d/kde/src/5/kde/workspace/kwin/plugins/platforms/wayland/wayland_backend.cpp: In destructor ‘virtual KWin::Wayland::WaylandBackend::~WaylandBackend()’:
    /d/kde/src/5/kde/workspace/kwin/plugins/platforms/wayland/wayland_backend.cpp:484:5: error: ‘gbm_device_destroy’ was not declared in this scope
      484 |     gbm_device_destroy(m_gbmDevice);
          |     ^~~~~~~~~~~~~~~~~~
    /d/kde/src/5/kde/workspace/kwin/plugins/platforms/wayland/wayland_backend.cpp: In member function ‘virtual KWin::DmaBufTexture* KWin::Wayland::WaylandBackend::createDmaBufTexture(const QSize&)’:
    /d/kde/src/5/kde/workspace/kwin/plugins/platforms/wayland/wayland_backend.cpp:840:12: error: ‘GbmDmaBuf’ has not been declared
      840 |     return GbmDmaBuf::createBuffer(size, m_gbmDevice);
          |   

    Is it worth supporting this (new PC, I just didn't have gbm-devel installed) or should gbm be turned into a required dependency?

  • Good catch! !322 (merged)

Please register or sign in to reply
#include <fcntl.h>
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
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment