-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Closes: #43
- Loading branch information
Showing
29 changed files
with
2,713 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
include(ECMQtDeclareLoggingCategory) | ||
ecm_qt_declare_logging_category( | ||
AuroraDeviceIntegrationDrm_SOURCES | ||
HEADER "drmloggingcategories.h" | ||
IDENTIFIER "Aurora::Platform::gLcDrm" | ||
CATEGORY_NAME "aurora.platform.drm" | ||
DEFAULT_SEVERITY "Info" | ||
DESCRIPTION "Aurora device integration for DRM/KMS" | ||
) | ||
|
||
qt6_add_plugin(AuroraDeviceIntegrationDrm | ||
SHARED | ||
CLASS_NAME DrmIntegrationPlugin | ||
MANUAL_FINALIZATION | ||
drm.json | ||
drmbackend.cpp drmbackend.h | ||
drmblob.cpp drmblob.h | ||
drmcrtc.cpp drmcrtc.h | ||
drmcursor.cpp drmcursor.h | ||
drmgpu.cpp drmgpu.h | ||
drmintegration.cpp drmintegration.h | ||
drmintegrationplugin.cpp drmintegrationplugin.h | ||
drmobject.cpp drmobject.h | ||
drmoutput.cpp drmoutput.h | ||
drmplane.cpp drmplane.h | ||
drmpointer.h | ||
drmproperty.cpp drmproperty.h | ||
drmwindow.cpp drmwindow.h | ||
${AuroraDeviceIntegrationDrm_SOURCES} | ||
) | ||
|
||
set_target_properties(AuroraDeviceIntegrationDrm | ||
PROPERTIES OUTPUT_NAME drm | ||
) | ||
|
||
target_link_libraries(AuroraDeviceIntegrationDrm | ||
PUBLIC | ||
Qt6::Core | ||
Qt6::Gui | ||
Liri::AuroraCore | ||
Liri::AuroraPlatform | ||
EGL::EGL | ||
PkgConfig::Libdrm | ||
PkgConfig::Gbm | ||
PRIVATE | ||
Liri::AuroraPlatformPrivate | ||
) | ||
|
||
qt6_finalize_target(AuroraDeviceIntegrationDrm) | ||
|
||
install( | ||
TARGETS AuroraDeviceIntegrationDrm | ||
DESTINATION ${KDE_INSTALL_PLUGINDIR}/aurora/deviceintegration | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"Keys": [ "drm" ] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini <[email protected]> | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
#include <LiriAuroraUdev/UdevEnumerate> | ||
|
||
#include "drmbackend.h" | ||
#include "drmgpu.h" | ||
#include "drmloggingcategories.h" | ||
#include "drmoutput.h" | ||
|
||
#include <sys/stat.h> | ||
|
||
#include <gbm.h> | ||
#include <libdrm/drm_mode.h> | ||
#include <xf86drm.h> | ||
#include <xf86drmMode.h> | ||
|
||
#ifndef EGL_EXT_platform_base | ||
typedef EGLDisplay(EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum platform, | ||
void *native_display, | ||
const EGLint *attrib_list); | ||
#endif | ||
|
||
#ifndef EGL_PLATFORM_GBM_KHR | ||
# define EGL_PLATFORM_GBM_KHR 0x31D7 | ||
#endif | ||
|
||
namespace Aurora { | ||
|
||
namespace Platform { | ||
|
||
Q_GLOBAL_STATIC(DrmBackend, gDrmBackend) | ||
|
||
DrmBackend::DrmBackend(QObject *parent) | ||
: QObject(parent) | ||
, m_session(Session::create(Session::Type::Logind, this)) | ||
, m_udev(new Aurora::PlatformSupport::Udev()) | ||
{ | ||
} | ||
|
||
DrmBackend::~DrmBackend() | ||
{ | ||
if (m_udev) { | ||
delete m_udev; | ||
m_udev = nullptr; | ||
} | ||
} | ||
|
||
Session *DrmBackend::session() const | ||
{ | ||
return m_session; | ||
} | ||
|
||
EGLDisplay DrmBackend::eglDisplay() const | ||
{ | ||
return m_eglDisplay; | ||
} | ||
|
||
EGLNativeDisplayType DrmBackend::platformDisplay() const | ||
{ | ||
if (m_gpu) | ||
return reinterpret_cast<EGLNativeDisplayType>(m_gpu->gbmDevice()); | ||
return EGL_CAST(EGLNativeDisplayType, 0); | ||
} | ||
|
||
bool DrmBackend::isAtomicEnabled() const | ||
{ | ||
return m_enableAtomic; | ||
} | ||
|
||
DrmGpu *DrmBackend::primaryGpu() const | ||
{ | ||
return m_gpu; | ||
} | ||
|
||
void DrmBackend::initialize() | ||
{ | ||
if (m_initialized) | ||
return; | ||
|
||
m_initialized = true; | ||
|
||
// Session | ||
connect(m_session, &Session::devicePaused, this, [this](dev_t deviceId) { | ||
if (auto *gpu = findGpu(deviceId)) | ||
gpu->setActive(false); | ||
}); | ||
connect(m_session, &Session::deviceResumed, this, [this](dev_t deviceId) { | ||
if (auto *gpu = findGpu(deviceId)) | ||
gpu->setActive(true); | ||
}); | ||
|
||
// Find all GPUs | ||
Aurora::PlatformSupport::UdevEnumerate enumerate( | ||
Aurora::PlatformSupport::UdevDevice::PrimaryVideoDevice | ||
| Aurora::PlatformSupport::UdevDevice::GenericVideoDevice, | ||
m_udev); | ||
auto udevDevices = enumerate.scan(); | ||
if (Q_UNLIKELY(udevDevices.isEmpty())) | ||
qFatal("Could not find DRM device!"); | ||
|
||
// Create GPUs | ||
if (!udevDevices.isEmpty()) { | ||
qCDebug(gLcDrm, "Found the following video devices for the \"%s\" seat:", | ||
qPrintable(m_session->seat())); | ||
for (auto *udevDevice : qAsConst(udevDevices)) { | ||
if (udevDevice->seat() == m_session->seat()) { | ||
const auto path = udevDevice->deviceNode(); | ||
qCDebug(gLcDrm) << '\t' << path.toLocal8Bit().constData(); | ||
addGpu(path); | ||
} | ||
} | ||
} | ||
if (Q_UNLIKELY(m_gpus.isEmpty())) | ||
qFatal("No suitable DRM device have been found"); | ||
|
||
// Select the first one | ||
m_gpu = m_gpus.first(); | ||
|
||
// Create EGL display | ||
createDisplay(); | ||
} | ||
|
||
void DrmBackend::destroy() | ||
{ | ||
} | ||
|
||
DrmBackend *DrmBackend::instance() | ||
{ | ||
return gDrmBackend(); | ||
} | ||
|
||
DrmGpu *DrmBackend::addGpu(const QString &path) | ||
{ | ||
// Open the DRM device | ||
int fd = m_session->openRestricted(path); | ||
if (fd < 0) { | ||
qCWarning(gLcDrm) << "Failed to open DRM device" << path; | ||
return nullptr; | ||
} | ||
|
||
// Make a simpel DRM call to check if the device is usable | ||
drmModeResPtr resources = drmModeGetResources(fd); | ||
if (!resources) { | ||
qCDebug(gLcDrm) << "Skipping KMS incapable DRM device" << path; | ||
m_session->closeRestricted(fd); | ||
return nullptr; | ||
} | ||
drmModeFreeResources(resources); | ||
|
||
struct stat sbuf; | ||
if (fstat(fd, &sbuf) < 0) { | ||
qCDebug(gLcDrm, "Failed to fstat \"%s\": %s", qPrintable(path), strerror(errno)); | ||
m_session->closeRestricted(fd); | ||
return nullptr; | ||
} | ||
|
||
qCInfo(gLcDrm) << "Adding DRM device:" << path; | ||
|
||
auto *gpu = new DrmGpu(path, fd, sbuf.st_rdev); | ||
m_gpus.append(gpu); | ||
emit gpuAdded(gpu); | ||
return gpu; | ||
} | ||
|
||
DrmGpu *DrmBackend::findGpu(dev_t deviceId) const | ||
{ | ||
auto it = std::find_if(m_gpus.begin(), m_gpus.end(), | ||
[deviceId](const auto *gpu) { return gpu->deviceId() == deviceId; }); | ||
return it == m_gpus.end() ? nullptr : *it; | ||
} | ||
|
||
void DrmBackend::createDisplay() | ||
{ | ||
EGLNativeDisplayType nativeDisplay = platformDisplay(); | ||
|
||
PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = nullptr; | ||
const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); | ||
if (extensions | ||
&& (strstr(extensions, "EGL_KHR_platform_gbm") | ||
|| strstr(extensions, "EGL_MESA_platform_gbm"))) { | ||
getPlatformDisplay = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>( | ||
eglGetProcAddress("eglGetPlatformDisplayEXT")); | ||
} | ||
|
||
if (getPlatformDisplay) { | ||
m_eglDisplay = getPlatformDisplay(EGL_PLATFORM_GBM_KHR, nativeDisplay, nullptr); | ||
} else { | ||
qCDebug(gLcDrm, "No eglGetPlatformDisplay for GBM, falling back to eglGetDisplay"); | ||
m_eglDisplay = eglGetDisplay(nativeDisplay); | ||
} | ||
} | ||
|
||
void DrmBackend::updateOutputs() | ||
{ | ||
for (auto it = m_gpus.begin(); it != m_gpus.end(); ++it) { | ||
auto *gpu = (*it); | ||
if (gpu->isRemoved()) | ||
gpu->removeOutputs(); | ||
else | ||
gpu->updateOutputs(); | ||
} | ||
|
||
for (auto it = m_gpus.begin(); it != m_gpus.end();) { | ||
auto *gpu = (*it); | ||
|
||
if (gpu->isRemoved() || (gpu != m_gpu && gpu->hasDrmOutputs())) { | ||
qCDebug(gLcDrm, "Removing GPU \"%s\"", qPrintable(gpu->deviceNode())); | ||
it = m_gpus.erase(it); | ||
emit gpuRemoved(gpu); | ||
} else { | ||
it++; | ||
} | ||
} | ||
} | ||
|
||
void DrmBackend::addOutput(DrmOutput *output) | ||
{ | ||
} | ||
|
||
void DrmBackend::removeOutput(DrmOutput *output) | ||
{ | ||
} | ||
|
||
} // namespace Platform | ||
|
||
} // namespace Aurora |
Oops, something went wrong.