diff --git a/CMakeLists.txt b/CMakeLists.txt index b6dea4d96c..3efd773f89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,6 +157,13 @@ if (Libinput_FOUND AND UDEV_FOUND) set(HAVE_INPUT TRUE) endif() +find_package(Libdrm) +set_package_properties(Libdrm PROPERTIES TYPE OPTIONAL PURPOSE "Required for drm output on Wayland.") +set(HAVE_DRM FALSE) +if(Libdrm_FOUND AND UDEV_FOUND) + set(HAVE_DRM TRUE) +endif() + find_package(X11) set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries" URL "http://www.x.org" @@ -281,6 +288,7 @@ else() set(HAVE_WAYLAND_EGL FALSE) set(HAVE_WAYLAND_CURSOR FALSE) set(HAVE_X11_XCB FALSE) + set(HAVE_DRM FALSE) endif() if(XCB_CURSOR_FOUND) @@ -433,6 +441,13 @@ if(HAVE_WAYLAND) if(KWIN_HAVE_EGL AND Wayland_Egl_FOUND) set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} egl_wayland_backend.cpp) endif() + if(HAVE_DRM) + set(kwin_KDEINIT_SRCS + ${kwin_KDEINIT_SRCS} + drm_backend.cpp + screens_drm.cpp + ) + endif() endif() if(UDEV_FOUND) @@ -566,6 +581,10 @@ if(HAVE_INPUT) set(kwinLibs ${kwinLibs} Libinput::Libinput) endif() +if(HAVE_DRM) + set(kwinLibs ${kwinLibs} Libdrm::Libdrm) +endif() + add_library(kwin SHARED ${kwin_KDEINIT_SRCS}) set_target_properties(kwin PROPERTIES diff --git a/cmake/modules/FindLibdrm.cmake b/cmake/modules/FindLibdrm.cmake new file mode 100644 index 0000000000..ebaa87dc9a --- /dev/null +++ b/cmake/modules/FindLibdrm.cmake @@ -0,0 +1,126 @@ +#.rst: +# FindLibdrm +# ------- +# +# Try to find libdrm on a Unix system. +# +# This will define the following variables: +# +# ``Libdrm_FOUND`` +# True if (the requested version of) libdrm is available +# ``Libdrm_VERSION`` +# The version of libdrm +# ``Libdrm_LIBRARIES`` +# This can be passed to target_link_libraries() instead of the ``Libdrm::Libdrm`` +# target +# ``Libdrm_INCLUDE_DIRS`` +# This should be passed to target_include_directories() if the target is not +# used for linking +# ``Libdrm_DEFINITIONS`` +# This should be passed to target_compile_options() if the target is not +# used for linking +# +# If ``Libdrm_FOUND`` is TRUE, it will also define the following imported target: +# +# ``Libdrm::Libdrm`` +# The libdrm library +# +# In general we recommend using the imported target, as it is easier to use. +# Bear in mind, however, that if the target is in the link interface of an +# exported library, it must be made available by the package config file. + +#============================================================================= +# Copyright 2014 Alex Merry +# Copyright 2014 Martin Gräßlin +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +if(CMAKE_VERSION VERSION_LESS 2.8.12) + message(FATAL_ERROR "CMake 2.8.12 is required by FindLibdrm.cmake") +endif() +if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12) + message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use FindLibdrm.cmake") +endif() + +if(NOT WIN32) + # Use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig) + pkg_check_modules(PKG_Libdrm QUIET libdrm) + + set(Libdrm_DEFINITIONS ${PKG_Libdrm_CFLAGS_OTHER}) + set(Libdrm_VERSION ${PKG_Libdrm_VERSION}) + + find_path(Libdrm_INCLUDE_DIR + NAMES + xf86drm.h + HINTS + ${PKG_Libdrm_INCLUDE_DIRS} + ) + find_library(Libdrm_LIBRARY + NAMES + drm + HINTS + ${PKG_Libdrm_LIBRARY_DIRS} + ) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Libdrm + FOUND_VAR + Libdrm_FOUND + REQUIRED_VARS + Libdrm_LIBRARY + Libdrm_INCLUDE_DIR + VERSION_VAR + Libdrm_VERSION + ) + + if(Libdrm_FOUND AND NOT TARGET Libdrm::Libdrm) + add_library(Libdrm::Libdrm UNKNOWN IMPORTED) + set_target_properties(Libdrm::Libdrm PROPERTIES + IMPORTED_LOCATION "${Libdrm_LIBRARY}" + INTERFACE_COMPILE_OPTIONS "${Libdrm_DEFINITIONS}" + INTERFACE_INCLUDE_DIRECTORIES "${Libdrm_INCLUDE_DIR}" + INTERFACE_INCLUDE_DIRECTORIES "${Libdrm_INCLUDE_DIR}/libdrm" + ) + endif() + + mark_as_advanced(Libdrm_LIBRARY Libdrm_INCLUDE_DIR) + + # compatibility variables + set(Libdrm_LIBRARIES ${Libdrm_LIBRARY}) + set(Libdrm_INCLUDE_DIRS ${Libdrm_INCLUDE_DIR}) + set(Libdrm_VERSION_STRING ${Libdrm_VERSION}) + +else() + message(STATUS "FindLibdrm.cmake cannot find libdrm on Windows systems.") + set(Libdrm_FOUND FALSE) +endif() + +include(FeatureSummary) +set_package_properties(Libdrm PROPERTIES + URL "https://wiki.freedesktop.org/dri/" + DESCRIPTION "Userspace interface to kernel DRM services." +) diff --git a/config-kwin.h.cmake b/config-kwin.h.cmake index 181cfa4bc2..79052e25fe 100644 --- a/config-kwin.h.cmake +++ b/config-kwin.h.cmake @@ -15,6 +15,7 @@ #cmakedefine01 HAVE_XCB_CURSOR #cmakedefine01 HAVE_XCB_SYNC #cmakedefine01 HAVE_X11_XCB +#cmakedefine01 HAVE_DRM /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H 1 diff --git a/drm_backend.cpp b/drm_backend.cpp new file mode 100644 index 0000000000..51d02cad7e --- /dev/null +++ b/drm_backend.cpp @@ -0,0 +1,212 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2015 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "drm_backend.h" +#include "logind.h" +#include "scene_qpainter.h" +#include "screens_drm.h" +#include "udev.h" +#include "utils.h" +#include "virtual_terminal.h" +// system +#include +#include +// drm +#include +#include +#include + +#include + +namespace KWin +{ + +DrmBackend::DrmBackend(QObject *parent) + : AbstractBackend(parent) + , m_udev(new Udev) +{ +} + +DrmBackend::~DrmBackend() +{ + if (m_fd >= 0) { + close(m_fd); + } +} + +void DrmBackend::init() +{ + LogindIntegration *logind = LogindIntegration::self(); + auto takeControl = [logind, this]() { + if (logind->hasSessionControl()) { + openDrm(); + } else { + logind->takeControl(); + connect(logind, &LogindIntegration::hasSessionControlChanged, this, &DrmBackend::openDrm); + } + }; + if (logind->isConnected()) { + takeControl(); + } else { + connect(logind, &LogindIntegration::connectedChanged, this, takeControl); + } + VirtualTerminal::create(this); +} + +void DrmBackend::openDrm() +{ + VirtualTerminal::self()->init(); + UdevDevice::Ptr device = m_udev->primaryGpu(); + if (!device) { + qCWarning(KWIN_CORE) << "Did not find a GPU"; + return; + } + int fd = LogindIntegration::self()->takeDevice(device->devNode()); + if (fd < 0) { + qCWarning(KWIN_CORE) << "failed to open drm device at" << device->devNode(); + return; + } + m_fd = fd; + m_drmId = device->sysNum(); + queryResources(); + emit screensQueried(); +} + +template +struct DrmCleanup +{ + static inline void cleanup(Pointer *ptr) + { + cleanupFunc(ptr); + } +}; +template using ScopedDrmPointer = QScopedPointer>; + +void DrmBackend::queryResources() +{ + if (m_fd < 0) { + return; + } + ScopedDrmPointer<_drmModeRes, &drmModeFreeResources> resources(drmModeGetResources(m_fd)); + if (!resources) { + qCWarning(KWIN_CORE) << "drmModeGetResources failed"; + return; + } + for (int i = 0; i < resources->count_connectors; ++i) { + const auto id = resources->connectors[i]; + ScopedDrmPointer<_drmModeConnector, &drmModeFreeConnector> connector(drmModeGetConnector(m_fd, id)); + if (!connector) { + continue; + } + if (connector->connection != DRM_MODE_CONNECTED) { + continue; + } + ScopedDrmPointer<_drmModeEncoder, &drmModeFreeEncoder> encoder(drmModeGetEncoder(m_fd, connector->encoder_id)); + if (!encoder) { + continue; + } + ScopedDrmPointer<_drmModeCrtc, &drmModeFreeCrtc> crtc(drmModeGetCrtc(m_fd, encoder->crtc_id)); + if (!crtc) { + continue; + } + m_resolution = QSize(crtc->mode.hdisplay, crtc->mode.vdisplay); + m_crtcId = encoder->crtc_id; + m_connector = connector->connector_id; + m_mode = crtc->mode; + // for the moment only one crtc + break; + } +} + +void DrmBackend::present(DrmBuffer *buffer) +{ + drmModeSetCrtc(m_fd, m_crtcId, buffer->m_bufferId, 0, 0, &m_connector, 1, &m_mode); +} + +Screens *DrmBackend::createScreens(QObject *parent) +{ + return new DrmScreens(this, parent); +} + +QPainterBackend *DrmBackend::createQPainterBackend() +{ + return new DrmQPainterBackend(this); +} + +DrmBuffer *DrmBackend::createBuffer(const QSize &size) +{ + return new DrmBuffer(this, size); +} + +DrmBuffer::DrmBuffer(DrmBackend *backend, const QSize &size) + : m_backend(backend) + , m_size(size) +{ + drm_mode_create_dumb createArgs; + memset(&createArgs, 0, sizeof createArgs); + createArgs.bpp = 32; + createArgs.width = size.width(); + createArgs.height = size.height(); + if (drmIoctl(m_backend->fd(), DRM_IOCTL_MODE_CREATE_DUMB, &createArgs) != 0) { + return; + } + m_handle = createArgs.handle; + m_bufferSize = createArgs.size; + m_stride = createArgs.pitch; + drmModeAddFB(m_backend->fd(), size.width(), size.height(), 24, 32, + m_stride, createArgs.handle, &m_bufferId); +} + +DrmBuffer::~DrmBuffer() +{ + delete m_image; + if (m_memory) { + munmap(m_memory, m_bufferSize); + } + if (m_bufferId) { + drmModeRmFB(m_backend->fd(), m_bufferId); + } + if (m_handle) { + drm_mode_destroy_dumb destroyArgs; + destroyArgs.handle = m_handle; + drmIoctl(m_backend->fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs); + } +} + +bool DrmBuffer::map() +{ + if (!m_handle || !m_bufferId) { + return false; + } + drm_mode_map_dumb mapArgs; + memset(&mapArgs, 0, sizeof mapArgs); + mapArgs.handle = m_handle; + if (drmIoctl(m_backend->fd(), DRM_IOCTL_MODE_MAP_DUMB, &mapArgs) != 0) { + return false; + } + void *address = mmap(nullptr, m_bufferSize, PROT_WRITE, MAP_SHARED, m_backend->fd(), mapArgs.offset); + if (address == MAP_FAILED) { + return false; + } + m_memory = address; + m_image = new QImage((uchar*)m_memory, m_size.width(), m_size.height(), m_stride, QImage::Format_RGB32); + return !m_image->isNull(); +} + +} diff --git a/drm_backend.h b/drm_backend.h new file mode 100644 index 0000000000..cee2ca77d4 --- /dev/null +++ b/drm_backend.h @@ -0,0 +1,99 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2015 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#ifndef KWIN_DRM_BACKEND_H +#define KWIN_DRM_BACKEND_H +#include "abstract_backend.h" + +#include +#include +#include + +namespace KWin +{ + +class Udev; + +class DrmBuffer; + +class KWIN_EXPORT DrmBackend : public AbstractBackend +{ + Q_OBJECT +public: + explicit DrmBackend(QObject *parent = nullptr); + virtual ~DrmBackend(); + + Screens *createScreens(QObject *parent = nullptr) override; + QPainterBackend *createQPainterBackend() override; + + void init(); + DrmBuffer *createBuffer(const QSize &size); + void present(DrmBuffer *buffer); + + QSize size() const { + // TODO: this is wrong + return m_resolution; + } + int fd() const { + return m_fd; + } + +Q_SIGNALS: + void screensQueried(); + +private: + void openDrm(); + void queryResources(); + QScopedPointer m_udev; + int m_fd = -1; + int m_drmId = 0; + // TODO: this is wrong + QSize m_resolution; + quint32 m_crtcId = 0; + quint32 m_connector = 0; + drmModeModeInfo m_mode; +}; + +class DrmBuffer +{ +public: + ~DrmBuffer(); + + bool map(); + QImage *image() const { + return m_image; + } + +private: + friend class DrmBackend; + DrmBuffer(DrmBackend *backend, const QSize &size); + DrmBackend *m_backend; + QSize m_size; + quint32 m_handle = 0; + quint32 m_bufferId = 0; + quint32 m_stride = 0; + quint64 m_bufferSize = 0; + void *m_memory = nullptr; + QImage *m_image = nullptr; +}; + +} + +#endif + diff --git a/main_wayland.cpp b/main_wayland.cpp index 8757d7fb63..47f0e29788 100644 --- a/main_wayland.cpp +++ b/main_wayland.cpp @@ -22,6 +22,9 @@ along with this program. If not, see . #include // kwin #include "fb_backend.h" +#if HAVE_DRM +#include "drm_backend.h" +#endif #include "wayland_backend.h" #include "wayland_server.h" #include "xcbutils.h" @@ -122,6 +125,14 @@ void ApplicationWayland::createBackend() } } } +#if HAVE_DRM + if (m_drm) { + DrmBackend *b = new DrmBackend(this); + connect(b, &DrmBackend::screensQueried, this, &ApplicationWayland::continueStartupWithScreens); + b->init(); + backend = b; + } +#endif if (!m_framebuffer.isEmpty()) { FramebufferBackend *b = new FramebufferBackend(this); connect(b, &FramebufferBackend::screensQueried, this, &ApplicationWayland::continueStartupWithScreens); @@ -447,6 +458,10 @@ KWIN_EXPORT int kdemain(int argc, char * argv[]) QCommandLineOption libinputOption(QStringLiteral("libinput"), i18n("Enable libinput support for input events processing. Note: never use in a nested session.")); parser.addOption(libinputOption); +#endif +#if HAVE_DRM + QCommandLineOption drmOption(QStringLiteral("drm"), i18n("Render through drm node.")); + parser.addOption(drmOption); #endif parser.addPositionalArgument(QStringLiteral("applications"), i18n("Applications to start once Wayland and Xwayland server are started"), @@ -463,6 +478,13 @@ KWIN_EXPORT int kdemain(int argc, char * argv[]) std::cerr << "FATAL ERROR Cannot have both --windowed and --framebuffer" << std::endl; return 1; } +#if HAVE_DRM + if (parser.isSet(drmOption) && (parser.isSet(windowedOption) || parser.isSet(framebufferOption))) { + std::cerr << "FATAL ERROR Cannot have both --windowed/--framebuffer and --drm" << std::endl; + return 1; + } + a.setDrm(parser.isSet(drmOption)); +#endif a.setWindowed(parser.isSet(windowedOption)); if (parser.isSet(windowedOption)) { diff --git a/main_wayland.h b/main_wayland.h index e97c049930..b8d93178d6 100644 --- a/main_wayland.h +++ b/main_wayland.h @@ -49,6 +49,9 @@ public: void setFramebuffer(const QString &fbdev) { m_framebuffer = fbdev; } + void setDrm(bool set) { + m_drm = set; + } void setApplicationsToStart(const QStringList &applications) { m_applicationsToStart = applications; } @@ -69,6 +72,7 @@ private: QByteArray m_x11Display; QByteArray m_waylandDisplay; QString m_framebuffer; + bool m_drm = false; QStringList m_applicationsToStart; }; diff --git a/scene_qpainter.cpp b/scene_qpainter.cpp index 123b94d899..4590704a6e 100644 --- a/scene_qpainter.cpp +++ b/scene_qpainter.cpp @@ -27,6 +27,9 @@ along with this program. If not, see . #include "main.h" #include "toplevel.h" #if HAVE_WAYLAND +#if HAVE_DRM +#include "drm_backend.h" +#endif #include "fb_backend.h" #include "virtual_terminal.h" #include "wayland_backend.h" @@ -332,6 +335,72 @@ void FramebufferQPainterBackend::renderCursor(QPainter *painter) m_backend->markCursorAsRendered(); } +#if HAVE_DRM +//**************************************** +// DrmQPainterBackend +//**************************************** +DrmQPainterBackend::DrmQPainterBackend(DrmBackend *backend) + : QObject() + , QPainterBackend() + , m_backend(backend) +{ + + m_buffer[0] = m_backend->createBuffer(m_backend->size()); + m_buffer[0]->map(); + m_buffer[1] = m_backend->createBuffer(m_backend->size()); + m_buffer[1]->map(); + m_buffer[0]->image()->fill(Qt::black); + m_buffer[1]->image()->fill(Qt::black); + + connect(VirtualTerminal::self(), &VirtualTerminal::activeChanged, this, + [this] (bool active) { + if (active) { + Compositor::self()->bufferSwapComplete(); + Compositor::self()->addRepaintFull(); + } else { + Compositor::self()->aboutToSwapBuffers(); + } + } + ); +} + +DrmQPainterBackend::~DrmQPainterBackend() +{ + delete m_buffer[0]; + delete m_buffer[1]; +} + +QImage *DrmQPainterBackend::buffer() +{ + return m_buffer[m_bufferIndex]->image(); +} + +bool DrmQPainterBackend::needsFullRepaint() const +{ + return true; +} + +void DrmQPainterBackend::prepareRenderingFrame() +{ + m_bufferIndex = (m_bufferIndex + 1) % 2; +} + +void DrmQPainterBackend::present(int mask, const QRegion &damage) +{ + Q_UNUSED(mask) + Q_UNUSED(damage) + if (!VirtualTerminal::self()->isActive()) { + return; + } + m_backend->present(m_buffer[m_bufferIndex]); +} + +bool DrmQPainterBackend::usesOverlayWindow() const +{ + return false; +} +#endif + #endif //**************************************** diff --git a/scene_qpainter.h b/scene_qpainter.h index 21f653b6ff..170310c9c1 100644 --- a/scene_qpainter.h +++ b/scene_qpainter.h @@ -44,6 +44,8 @@ namespace Wayland { class WaylandBackend; } +class DrmBackend; +class DrmBuffer; class FramebufferBackend; class X11WindowedBackend; @@ -174,6 +176,28 @@ private: QImage m_backBuffer; FramebufferBackend *m_backend; }; + +#if HAVE_DRM +class DrmQPainterBackend : public QObject, public QPainterBackend +{ + Q_OBJECT +public: + DrmQPainterBackend(DrmBackend *backend); + virtual ~DrmQPainterBackend(); + + QImage *buffer() override; + bool needsFullRepaint() const override; + bool usesOverlayWindow() const override; + void prepareRenderingFrame() override; + void present(int mask, const QRegion &damage) override; + +private: + DrmBackend *m_backend; + DrmBuffer *m_buffer[2]; + int m_bufferIndex = 0; +}; +#endif + #endif class SceneQPainter : public Scene diff --git a/screens_drm.cpp b/screens_drm.cpp new file mode 100644 index 0000000000..b3ad8010f0 --- /dev/null +++ b/screens_drm.cpp @@ -0,0 +1,68 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2015 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "screens_drm.h" +#include "drm_backend.h" + +namespace KWin +{ + +DrmScreens::DrmScreens(DrmBackend *backend, QObject *parent) + : Screens(parent) + , m_backend(backend) +{ +} + +DrmScreens::~DrmScreens() = default; + +void DrmScreens::init() +{ + KWin::Screens::init(); + updateCount(); + emit changed(); +} + +QRect DrmScreens::geometry(int screen) const +{ + if (screen == 0) { + return QRect(QPoint(0, 0), size(screen)); + } + return QRect(); +} + +QSize DrmScreens::size(int screen) const +{ + if (screen == 0) { + return m_backend->size(); + } + return QSize(); +} + +void DrmScreens::updateCount() +{ + setCount(1); +} + +int DrmScreens::number(const QPoint &pos) const +{ + Q_UNUSED(pos) + return 0; +} + +} diff --git a/screens_drm.h b/screens_drm.h new file mode 100644 index 0000000000..d813a9928f --- /dev/null +++ b/screens_drm.h @@ -0,0 +1,46 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2015 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#ifndef KWIN_SCREENS_DRM_H +#define KWIN_SCREENS_DRM_H +#include "screens.h" + +namespace KWin +{ +class DrmBackend; + +class DrmScreens : public Screens +{ + Q_OBJECT +public: + DrmScreens(DrmBackend *backend, QObject *parent = nullptr); + virtual ~DrmScreens(); + void init() override; + QRect geometry(int screen) const override; + int number(const QPoint &pos) const override; + QSize size(int screen) const override; + void updateCount() override; + +private: + DrmBackend *m_backend; +}; + +} + +#endif diff --git a/udev.cpp b/udev.cpp index 4809f67362..bb4b20a0fc 100644 --- a/udev.cpp +++ b/udev.cpp @@ -181,4 +181,12 @@ const char *UdevDevice::devNode() return udev_device_get_devnode(m_device); } +int UdevDevice::sysNum() const +{ + if (!m_device) { + return 0; + } + return QByteArray(udev_device_get_sysnum(m_device)).toInt(); +} + } diff --git a/udev.h b/udev.h index a3833037b0..6960110ac1 100644 --- a/udev.h +++ b/udev.h @@ -36,6 +36,7 @@ public: udev_device *getParentWithSubsystemDevType(const char *subsystem, const char *devtype = nullptr) const; const char *devNode(); + int sysNum() const; operator udev_device*() const { return m_device; diff --git a/workspace.cpp b/workspace.cpp index 09ae9a2c11..4b81a83cee 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -1332,6 +1332,12 @@ QString Workspace::supportInformation() const support.append(yes); #else support.append(no); +#endif + support.append(QStringLiteral("HAVE_DRM: ")); +#if HAVE_DRM + support.append(yes); +#else + support.append(no); #endif support.append(QStringLiteral("HAVE_XCB_CURSOR: ")); #if HAVE_XCB_CURSOR