mirror of
https://github.com/hyprwm/aquamarine.git
synced 2025-12-20 04:40:12 +01:00
core: introduce drmRenderNodeFD() (#193)
make a getter for drmRenderNodeFD() so we can create sync timelines on the rendernode on devices not supporting fences on the card* device directly.
This commit is contained in:
parent
141a991678
commit
f0db9b7eed
10 changed files with 120 additions and 2 deletions
|
|
@ -88,8 +88,9 @@ namespace Aquamarine {
|
|||
virtual bool createOutput(const std::string& name = "") = 0; // "" means auto
|
||||
virtual Hyprutils::Memory::CSharedPointer<IAllocator> preferredAllocator() = 0;
|
||||
virtual std::vector<SDRMFormat> getRenderableFormats(); // empty = use getRenderFormats
|
||||
virtual std::vector<Hyprutils::Memory::CSharedPointer<IAllocator>> getAllocators() = 0;
|
||||
virtual Hyprutils::Memory::CWeakPointer<IBackendImplementation> getPrimary() = 0;
|
||||
virtual std::vector<Hyprutils::Memory::CSharedPointer<IAllocator>> getAllocators() = 0;
|
||||
virtual Hyprutils::Memory::CWeakPointer<IBackendImplementation> getPrimary() = 0;
|
||||
virtual int drmRenderNodeFD() = 0;
|
||||
};
|
||||
|
||||
class CBackend {
|
||||
|
|
@ -148,6 +149,9 @@ namespace Aquamarine {
|
|||
bool ready = false;
|
||||
Hyprutils::Memory::CSharedPointer<CSession> session;
|
||||
|
||||
/* Get the primary DRM RenderNode */
|
||||
int drmRenderNodeFD();
|
||||
|
||||
private:
|
||||
CBackend();
|
||||
|
||||
|
|
|
|||
|
|
@ -379,6 +379,7 @@ namespace Aquamarine {
|
|||
|
||||
std::vector<FIdleCallback> idleCallbacks;
|
||||
std::string gpuName;
|
||||
virtual int drmRenderNodeFD();
|
||||
|
||||
private:
|
||||
CDRMBackend(Hyprutils::Memory::CSharedPointer<CBackend> backend);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ namespace Aquamarine {
|
|||
virtual Hyprutils::Memory::CWeakPointer<IBackendImplementation> getPrimary();
|
||||
|
||||
Hyprutils::Memory::CWeakPointer<CHeadlessBackend> self;
|
||||
virtual int drmRenderNodeFD();
|
||||
|
||||
private:
|
||||
CHeadlessBackend(Hyprutils::Memory::CSharedPointer<CBackend> backend_);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ namespace Aquamarine {
|
|||
static Hyprutils::Memory::CSharedPointer<CSessionDevice> openIfKMS(Hyprutils::Memory::CSharedPointer<CSession> session_, const std::string& path_);
|
||||
|
||||
bool supportsKMS();
|
||||
void resolveMatchingRenderNode(udev_device* cardDevice);
|
||||
|
||||
int fd = -1;
|
||||
int deviceID = -1;
|
||||
|
|
@ -53,6 +54,8 @@ namespace Aquamarine {
|
|||
Hyprutils::Signal::CSignalT<> remove;
|
||||
} events;
|
||||
|
||||
int renderNodeFd = -1;
|
||||
|
||||
private:
|
||||
Hyprutils::Memory::CWeakPointer<CSession> session;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ namespace Aquamarine {
|
|||
virtual Hyprutils::Memory::CWeakPointer<IBackendImplementation> getPrimary();
|
||||
|
||||
Hyprutils::Memory::CWeakPointer<CWaylandBackend> self;
|
||||
virtual int drmRenderNodeFD();
|
||||
|
||||
private:
|
||||
CWaylandBackend(Hyprutils::Memory::CSharedPointer<CBackend> backend);
|
||||
|
|
|
|||
|
|
@ -210,6 +210,17 @@ int Aquamarine::CBackend::drmFD() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int Aquamarine::CBackend::drmRenderNodeFD() {
|
||||
for (auto const& i : implementations) {
|
||||
int fd = i->drmRenderNodeFD();
|
||||
if (fd < 0)
|
||||
continue;
|
||||
|
||||
return fd;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Aquamarine::CBackend::hasSession() {
|
||||
return session;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,10 @@ int Aquamarine::CHeadlessBackend::drmFD() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int Aquamarine::CHeadlessBackend::drmRenderNodeFD() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Aquamarine::CHeadlessBackend::dispatchEvents() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <aquamarine/backend/Backend.hpp>
|
||||
#include <fcntl.h>
|
||||
|
||||
extern "C" {
|
||||
#include <libseat.h>
|
||||
|
|
@ -141,6 +142,9 @@ Aquamarine::CSessionDevice::~CSessionDevice() {
|
|||
session->backend->log(AQ_LOG_ERROR, std::format("libseat: Couldn't close device at {}", path));
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
|
||||
if (renderNodeFd)
|
||||
close(renderNodeFd);
|
||||
}
|
||||
|
||||
bool Aquamarine::CSessionDevice::supportsKMS() {
|
||||
|
|
@ -157,6 +161,84 @@ bool Aquamarine::CSessionDevice::supportsKMS() {
|
|||
return kms;
|
||||
}
|
||||
|
||||
void Aquamarine::CSessionDevice::resolveMatchingRenderNode(udev_device* cardDevice) {
|
||||
if (!cardDevice)
|
||||
return;
|
||||
|
||||
auto pciParent = udev_device_get_parent_with_subsystem_devtype(cardDevice, "pci", nullptr);
|
||||
const auto* pciSyspath = pciParent ? udev_device_get_syspath(pciParent) : nullptr;
|
||||
|
||||
auto* enumerate = udev_enumerate_new(session->udevHandle);
|
||||
if (!enumerate)
|
||||
return;
|
||||
|
||||
udev_enumerate_add_match_subsystem(enumerate, "drm");
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
|
||||
auto* devices = udev_enumerate_get_list_entry(enumerate);
|
||||
udev_list_entry* entry = nullptr;
|
||||
|
||||
bool matched = false;
|
||||
|
||||
udev_list_entry_foreach(entry, devices) {
|
||||
const auto* path = udev_list_entry_get_name(entry);
|
||||
auto dev = udev_device_new_from_syspath(session->udevHandle, path);
|
||||
if (!dev)
|
||||
continue;
|
||||
|
||||
const auto* devnode = udev_device_get_devnode(dev);
|
||||
const auto* devtype = udev_device_get_devtype(dev);
|
||||
|
||||
if (!devnode || !devtype || strcmp(devtype, "drm_minor") != 0 || !strstr(devnode, "renderD")) {
|
||||
udev_device_unref(dev);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto devParent = udev_device_get_parent_with_subsystem_devtype(dev, "pci", nullptr);
|
||||
if (devParent && pciSyspath && strcmp(udev_device_get_syspath(devParent), pciSyspath) == 0) {
|
||||
renderNodeFd = open(devnode, O_RDWR | O_CLOEXEC);
|
||||
if (renderNodeFd < 0)
|
||||
session->backend->log(AQ_LOG_WARNING, std::format("drm: Failed to open matching render node {}", devnode));
|
||||
else
|
||||
matched = true;
|
||||
|
||||
udev_device_unref(dev);
|
||||
break;
|
||||
}
|
||||
|
||||
udev_device_unref(dev);
|
||||
}
|
||||
|
||||
if (!matched) {
|
||||
// fallback to the first render node
|
||||
udev_list_entry_foreach(entry, devices) {
|
||||
const auto* path = udev_list_entry_get_name(entry);
|
||||
auto dev = udev_device_new_from_syspath(session->udevHandle, path);
|
||||
if (!dev)
|
||||
continue;
|
||||
|
||||
const auto* devnode = udev_device_get_devnode(dev);
|
||||
const auto* devtype = udev_device_get_devtype(dev);
|
||||
|
||||
if (!devnode || !devtype || strcmp(devtype, "drm_minor") != 0 || !strstr(devnode, "renderD")) {
|
||||
udev_device_unref(dev);
|
||||
continue;
|
||||
}
|
||||
|
||||
renderNodeFd = open(devnode, O_RDWR | O_CLOEXEC);
|
||||
if (renderNodeFd >= 0) {
|
||||
session->backend->log(AQ_LOG_WARNING, std::format("drm: No matching render node for {}, falling back to {}", path, devnode));
|
||||
udev_device_unref(dev);
|
||||
break;
|
||||
}
|
||||
|
||||
udev_device_unref(dev);
|
||||
}
|
||||
}
|
||||
|
||||
udev_enumerate_unref(enumerate);
|
||||
}
|
||||
|
||||
SP<CSessionDevice> Aquamarine::CSessionDevice::openIfKMS(SP<CSession> session_, const std::string& path_) {
|
||||
auto dev = makeShared<CSessionDevice>(session_, path_);
|
||||
if (!dev->supportsKMS())
|
||||
|
|
|
|||
|
|
@ -139,6 +139,11 @@ int Aquamarine::CWaylandBackend::drmFD() {
|
|||
return drmState.fd;
|
||||
}
|
||||
|
||||
int Aquamarine::CWaylandBackend::drmRenderNodeFD() {
|
||||
// creation already attempts to use the rendernode, so just return same fd as drmFD().
|
||||
return drmState.fd;
|
||||
}
|
||||
|
||||
bool Aquamarine::CWaylandBackend::createOutput(const std::string& szName) {
|
||||
auto o = outputs.emplace_back(SP<CWaylandOutput>(new CWaylandOutput(szName.empty() ? std::format("WAYLAND-{}", ++lastOutputID) : szName, self)));
|
||||
o->self = o;
|
||||
|
|
|
|||
|
|
@ -150,6 +150,8 @@ static std::vector<SP<CSessionDevice>> scanGPUs(SP<CBackend> backend) {
|
|||
continue;
|
||||
}
|
||||
|
||||
sessionDevice->resolveMatchingRenderNode(device);
|
||||
|
||||
udev_device_unref(device);
|
||||
|
||||
if (isBootVGA)
|
||||
|
|
@ -906,6 +908,10 @@ int Aquamarine::CDRMBackend::drmFD() {
|
|||
return gpu->fd;
|
||||
}
|
||||
|
||||
int Aquamarine::CDRMBackend::drmRenderNodeFD() {
|
||||
return gpu->renderNodeFd;
|
||||
}
|
||||
|
||||
static void handlePF(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, unsigned crtc_id, void* data) {
|
||||
auto pageFlip = (SDRMPageFlip*)data;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue