mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-10-29 19:34:47 +00:00
syncobj: use rendernode for timelines (#11087)
* syncobj: use rendernode for timelines use rendernode for timelines instead of the drmfd, some devices dont support to use the drmfd for this. * opengl: use rendernode if available use rendernode if available for CHyprOpenglImpl * MesaDRM: use the m_drmRenderNodeFD if it exist try use the rendernode we got from AQ if it exist. * linuxdmabuf: use rendernode if available use the rendernode if available already from AQ * syncobj: prefer rendernode over displaynode prefer the rendernode over the displaynode, and log a error if attempting to use the protocol without explicit sync support on any of the nodes. * syncobj: check support on both nodes always check support on both nodes always so it can be used later for preferring rendernode if possible in syncobj protocol. * syncobj: remove old var in non linux if else case remove old m_bDrmSyncobjTimelineSupported from non linux if else case that will fail to compile on non linux. the nodes sets support by default to false, and if non linux it wont check for support and set it to true. * build: bump aq requirement bump to 0.9.3 where rendernode support got added. * flake.lock: update * renderer: glfinish on software renderer software renderers apparently bug out on implicit sync, use glfinish as with nvidia case on implicit paths. * flake.lock: update --------- Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
This commit is contained in:
parent
ced38b1b0f
commit
b329ea8e96
@ -105,7 +105,7 @@ find_package(Threads REQUIRED)
|
||||
set(GLES_VERSION "GLES3")
|
||||
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
||||
|
||||
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.9.0)
|
||||
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.9.3)
|
||||
pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2)
|
||||
pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7)
|
||||
pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.8.2)
|
||||
|
||||
36
flake.lock
generated
36
flake.lock
generated
@ -16,11 +16,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1753216019,
|
||||
"narHash": "sha256-zik7WISrR1ks2l6T1MZqZHb/OqroHdJnSnAehkE0kCk=",
|
||||
"lastModified": 1755632680,
|
||||
"narHash": "sha256-EjaD8+d7AiAV2fGRN4NTMboWDwk8szDfwbzZ8DL1PhQ=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "be166e11d86ba4186db93e10c54a141058bdce49",
|
||||
"rev": "50637ed23e962f0db294d6b0ef534f37b144644b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -238,11 +238,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1754481650,
|
||||
"narHash": "sha256-6u6HdEFJh5gY6VfyMQbhP7zDdVcqOrCDTkbiHJmAtMI=",
|
||||
"lastModified": 1755416120,
|
||||
"narHash": "sha256-PosTxeL39YrLvCX5MqqPA6NNWQ4T5ea5K55nmN7ju9Q=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "df6b8820c4a0835d83d0c7c7be86fbc555f1f7fd",
|
||||
"rev": "e631ea36ddba721eceda69bfee6dd01068416489",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -261,11 +261,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1751897909,
|
||||
"narHash": "sha256-FnhBENxihITZldThvbO7883PdXC/2dzW4eiNvtoV5Ao=",
|
||||
"lastModified": 1755184602,
|
||||
"narHash": "sha256-RCBQN8xuADB0LEgaKbfRqwm6CdyopE1xIEhNc67FAbw=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"rev": "fcca0c61f988a9d092cbb33e906775014c61579d",
|
||||
"rev": "b3b0f1f40ae09d4447c20608e5a4faf8bf3c492d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -276,11 +276,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1754725699,
|
||||
"narHash": "sha256-iAcj9T/Y+3DBy2J0N+yF9XQQQ8IEb5swLFzs23CdP88=",
|
||||
"lastModified": 1755186698,
|
||||
"narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "85dbfc7aaf52ecb755f87e577ddbe6dbbdbc1054",
|
||||
"rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -299,11 +299,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1754416808,
|
||||
"narHash": "sha256-c6yg0EQ9xVESx6HGDOCMcyRSjaTpNJP10ef+6fRcofA=",
|
||||
"lastModified": 1755446520,
|
||||
"narHash": "sha256-I0Ok1OGDwc1jPd8cs2VvAYZsHriUVFGIUqW+7uSsOUM=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "9c52372878df6911f9afc1e2a1391f55e4dfc864",
|
||||
"rev": "4b04db83821b819bbbe32ed0a025b31e7971f22e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -365,11 +365,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1753633878,
|
||||
"narHash": "sha256-js2sLRtsOUA/aT10OCDaTjO80yplqwOIaLUqEe0nMx0=",
|
||||
"lastModified": 1755354946,
|
||||
"narHash": "sha256-zdov5f/GcoLQc9qYIS1dUTqtJMeDqmBmo59PAxze6e4=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "371b96bd11ad2006ed4f21229dbd1be69bed3e8a",
|
||||
"rev": "a10726d6a8d0ef1a0c645378f983b6278c42eaa0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@ -31,7 +31,7 @@ if cpp_compiler.check_header('execinfo.h')
|
||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||
endif
|
||||
|
||||
aquamarine = dependency('aquamarine', version: '>=0.9.0')
|
||||
aquamarine = dependency('aquamarine', version: '>=0.9.3')
|
||||
hyprcursor = dependency('hyprcursor', version: '>=0.1.7')
|
||||
hyprgraphics = dependency('hyprgraphics', version: '>= 0.1.3')
|
||||
hyprlang = dependency('hyprlang', version: '>= 0.3.2')
|
||||
|
||||
@ -169,7 +169,7 @@ void CCompositor::restoreNofile() {
|
||||
}
|
||||
|
||||
bool CCompositor::supportsDrmSyncobjTimeline() const {
|
||||
return m_bDrmSyncobjTimelineSupported;
|
||||
return m_drm.syncobjSupport || m_drmRenderNode.syncObjSupport;
|
||||
}
|
||||
|
||||
void CCompositor::setMallocThreshold() {
|
||||
@ -356,22 +356,32 @@ void CCompositor::initServer(std::string socketName, int socketFd) {
|
||||
|
||||
m_initialized = true;
|
||||
|
||||
m_drmFD = m_aqBackend->drmFD();
|
||||
Debug::log(LOG, "Running on DRMFD: {}", m_drmFD);
|
||||
m_drm.fd = m_aqBackend->drmFD();
|
||||
Debug::log(LOG, "Running on DRMFD: {}", m_drm.fd);
|
||||
|
||||
m_drmRenderNode.fd = m_aqBackend->drmRenderNodeFD();
|
||||
Debug::log(LOG, "Using RENDERNODEFD: {}", m_drmRenderNode.fd);
|
||||
|
||||
#if defined(__linux__)
|
||||
if (m_drmFD >= 0) {
|
||||
uint64_t cap = 0;
|
||||
int ret = drmGetCap(m_drmFD, DRM_CAP_SYNCOBJ_TIMELINE, &cap);
|
||||
m_bDrmSyncobjTimelineSupported = (ret == 0 && cap != 0);
|
||||
Debug::log(LOG, "DRM syncobj timeline support: {}", m_bDrmSyncobjTimelineSupported ? "yes" : "no");
|
||||
} else {
|
||||
m_bDrmSyncobjTimelineSupported = false;
|
||||
Debug::log(LOG, "DRM syncobj timeline support: no (no DRM FD)");
|
||||
}
|
||||
auto syncObjSupport = [](auto fd) {
|
||||
if (fd < 0)
|
||||
return false;
|
||||
|
||||
uint64_t cap = 0;
|
||||
int ret = drmGetCap(fd, DRM_CAP_SYNCOBJ_TIMELINE, &cap);
|
||||
return ret == 0 && cap != 0;
|
||||
};
|
||||
|
||||
if ((m_drm.syncobjSupport = syncObjSupport(m_drm.fd)))
|
||||
Debug::log(LOG, "DRM DisplayNode syncobj timeline support: {}", m_drm.syncobjSupport ? "yes" : "no");
|
||||
|
||||
if ((m_drmRenderNode.syncObjSupport = syncObjSupport(m_drmRenderNode.fd)))
|
||||
Debug::log(LOG, "DRM RenderNode syncobj timeline support: {}", m_drmRenderNode.syncObjSupport ? "yes" : "no");
|
||||
|
||||
if (!m_drm.syncobjSupport && !m_drmRenderNode.syncObjSupport)
|
||||
Debug::log(LOG, "DRM no syncobj support, disabling explicit sync");
|
||||
#else
|
||||
Debug::log(LOG, "DRM syncobj timeline support: no (not linux)");
|
||||
m_bDrmSyncobjTimelineSupported = false;
|
||||
#endif
|
||||
|
||||
if (!socketName.empty() && socketFd != -1) {
|
||||
|
||||
@ -27,9 +27,18 @@ class CCompositor {
|
||||
CCompositor(bool onlyConfig = false);
|
||||
~CCompositor();
|
||||
|
||||
wl_display* m_wlDisplay = nullptr;
|
||||
wl_event_loop* m_wlEventLoop = nullptr;
|
||||
int m_drmFD = -1;
|
||||
wl_display* m_wlDisplay = nullptr;
|
||||
wl_event_loop* m_wlEventLoop = nullptr;
|
||||
struct {
|
||||
int fd = -1;
|
||||
bool syncobjSupport = false;
|
||||
} m_drm;
|
||||
|
||||
struct {
|
||||
int fd = -1;
|
||||
bool syncObjSupport = false;
|
||||
} m_drmRenderNode;
|
||||
|
||||
bool m_initialized = false;
|
||||
SP<Aquamarine::CBackend> m_aqBackend;
|
||||
|
||||
@ -175,8 +184,6 @@ class CCompositor {
|
||||
void removeLockFile();
|
||||
void setMallocThreshold();
|
||||
|
||||
bool m_bDrmSyncobjTimelineSupported = false;
|
||||
|
||||
uint64_t m_hyprlandPID = 0;
|
||||
wl_event_source* m_critSigSource = nullptr;
|
||||
rlimit m_originalNofile = {};
|
||||
|
||||
@ -432,7 +432,7 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
||||
options.length = 2;
|
||||
options.scanout = true;
|
||||
options.cursor = true;
|
||||
options.multigpu = state->monitor->m_output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_drmFD;
|
||||
options.multigpu = state->monitor->m_output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_drm.fd;
|
||||
// We do not set the format (unless shm). If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us,
|
||||
// but if it's set, we don't wanna change it.
|
||||
if (shouldUseCpuBuffer)
|
||||
|
||||
@ -199,8 +199,18 @@ bool CDRMSyncobjManagerResource::good() {
|
||||
return m_resource->resource();
|
||||
}
|
||||
|
||||
CDRMSyncobjProtocol::CDRMSyncobjProtocol(const wl_interface* iface, const int& ver, const std::string& name) :
|
||||
IWaylandProtocol(iface, ver, name), m_drmFD(g_pCompositor->m_drmFD) {}
|
||||
CDRMSyncobjProtocol::CDRMSyncobjProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
if (g_pCompositor->m_drmRenderNode.syncObjSupport)
|
||||
m_drmFD = g_pCompositor->m_drmRenderNode.fd;
|
||||
else if (g_pCompositor->m_drm.syncobjSupport)
|
||||
m_drmFD = g_pCompositor->m_drm.fd;
|
||||
else {
|
||||
LOGM(ERR, "CDRMSyncobjProtocol: no nodes support explicit sync?");
|
||||
return;
|
||||
}
|
||||
|
||||
LOGM(LOG, "CDRMSyncobjProtocol: using fd {}", m_drmFD);
|
||||
}
|
||||
|
||||
void CDRMSyncobjProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
const auto& RESOURCE = m_managers.emplace_back(makeUnique<CDRMSyncobjManagerResource>(makeUnique<CWpLinuxDrmSyncobjManagerV1>(client, ver, id)));
|
||||
|
||||
@ -408,7 +408,7 @@ void CLinuxDMABUFResource::sendMods() {
|
||||
|
||||
CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
static auto P = g_pHookSystem->hookDynamic("ready", [this](void* self, SCallbackInfo& info, std::any d) {
|
||||
int rendererFD = g_pCompositor->m_drmFD;
|
||||
int rendererFD = g_pCompositor->m_drmRenderNode.fd >= 0 ? g_pCompositor->m_drmRenderNode.fd : g_pCompositor->m_drm.fd;
|
||||
auto dev = devIDFromFD(rendererFD);
|
||||
|
||||
if (!dev.has_value()) {
|
||||
@ -467,6 +467,19 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_pCompositor->m_drmRenderNode.fd >= 0 && rendererFD == g_pCompositor->m_drmRenderNode.fd) {
|
||||
// Already using the compositor's render node, reuse it.
|
||||
m_mainDeviceFD = CFileDescriptor{fcntl(g_pCompositor->m_drmRenderNode.fd, F_DUPFD_CLOEXEC, 0)};
|
||||
drmFreeDevice(&device);
|
||||
if (!m_mainDeviceFD.isValid()) {
|
||||
LOGM(ERR, "failed to open rendernode, disabling linux dmabuf");
|
||||
removeGlobal();
|
||||
return;
|
||||
}
|
||||
|
||||
return; // already using rendernode.
|
||||
}
|
||||
|
||||
if (device->available_nodes & (1 << DRM_NODE_RENDER)) {
|
||||
const char* name = device->nodes[DRM_NODE_RENDER];
|
||||
m_mainDeviceFD = CFileDescriptor{open(name, O_RDWR | O_CLOEXEC)};
|
||||
|
||||
@ -113,28 +113,26 @@ bool CMesaDRMResource::good() {
|
||||
|
||||
CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
drmDevice* dev = nullptr;
|
||||
int drmFD = g_pCompositor->m_drmFD;
|
||||
int drmFD = g_pCompositor->m_drmRenderNode.fd >= 0 ? g_pCompositor->m_drmRenderNode.fd : g_pCompositor->m_drm.fd;
|
||||
|
||||
if (drmGetDevice2(drmFD, 0, &dev) != 0) {
|
||||
LOGM(ERR, "Failed to get device, disabling MesaDRM");
|
||||
LOGM(ERR, "Failed to get device from fd {}, disabling MesaDRM", drmFD);
|
||||
removeGlobal();
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->available_nodes & (1 << DRM_NODE_RENDER)) {
|
||||
if (dev->available_nodes & (1 << DRM_NODE_RENDER) && dev->nodes[DRM_NODE_RENDER]) {
|
||||
m_nodeName = dev->nodes[DRM_NODE_RENDER];
|
||||
} else {
|
||||
ASSERT(dev->available_nodes & (1 << DRM_NODE_PRIMARY));
|
||||
|
||||
if (!dev->nodes[DRM_NODE_PRIMARY]) {
|
||||
LOGM(ERR, "No DRM render node available, both render and primary are null, disabling MesaDRM");
|
||||
drmFreeDevice(&dev);
|
||||
removeGlobal();
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (dev->available_nodes & (1 << DRM_NODE_PRIMARY) && dev->nodes[DRM_NODE_PRIMARY]) {
|
||||
LOGM(WARN, "No DRM render node, falling back to primary {}", dev->nodes[DRM_NODE_PRIMARY]);
|
||||
m_nodeName = dev->nodes[DRM_NODE_PRIMARY];
|
||||
} else {
|
||||
LOGM(ERR, "No usable DRM node (render or primary) found, disabling MesaDRM");
|
||||
drmFreeDevice(&dev);
|
||||
removeGlobal();
|
||||
return;
|
||||
}
|
||||
|
||||
drmFreeDevice(&dev);
|
||||
}
|
||||
|
||||
|
||||
@ -254,7 +254,7 @@ EGLDeviceEXT CHyprOpenGLImpl::eglDeviceFromDRMFD(int drmFD) {
|
||||
return EGL_NO_DEVICE_EXT;
|
||||
}
|
||||
|
||||
CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmFD) {
|
||||
CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmRenderNode.fd >= 0 ? g_pCompositor->m_drmRenderNode.fd : g_pCompositor->m_drm.fd) {
|
||||
const std::string EGLEXTENSIONS = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
||||
|
||||
Debug::log(LOG, "Supported EGL global extensions: ({}) {}", std::ranges::count(EGLEXTENSIONS, ' '), EGLEXTENSIONS);
|
||||
|
||||
@ -69,6 +69,8 @@ CHyprRenderer::CHyprRenderer() {
|
||||
m_nvidia = true;
|
||||
else if (name.contains("i915"))
|
||||
m_intel = true;
|
||||
else if (name.contains("softpipe") || name.contains("Software Rasterizer") || name.contains("llvmpipe"))
|
||||
m_software = true;
|
||||
|
||||
Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel,
|
||||
std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len});
|
||||
@ -79,7 +81,7 @@ CHyprRenderer::CHyprRenderer() {
|
||||
} else {
|
||||
Debug::log(LOG, "Aq backend has no session, omitting full DRM node checks");
|
||||
|
||||
const auto DRMV = drmGetVersion(g_pCompositor->m_drmFD);
|
||||
const auto DRMV = drmGetVersion(g_pCompositor->m_drm.fd);
|
||||
|
||||
if (DRMV) {
|
||||
std::string name = std::string{DRMV->name, DRMV->name_len};
|
||||
@ -89,6 +91,8 @@ CHyprRenderer::CHyprRenderer() {
|
||||
m_nvidia = true;
|
||||
else if (name.contains("i915"))
|
||||
m_intel = true;
|
||||
else if (name.contains("softpipe") || name.contains("Software Rasterizer") || name.contains("llvmpipe"))
|
||||
m_software = true;
|
||||
|
||||
Debug::log(LOG, "Primary DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel,
|
||||
std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len});
|
||||
@ -2234,8 +2238,8 @@ void CHyprRenderer::endRender(const std::function<void()>& renderingDoneCallback
|
||||
if (!g_pHyprOpenGL->explicitSyncSupported()) {
|
||||
Debug::log(TRACE, "renderer: Explicit sync unsupported, falling back to implicit in endRender");
|
||||
|
||||
// nvidia doesn't have implicit sync, so we have to explicitly wait here
|
||||
if (isNvidia() && *PNVIDIAANTIFLICKER)
|
||||
// nvidia doesn't have implicit sync, so we have to explicitly wait here, llvmpipe and other software renderer seems to bug out aswell.
|
||||
if ((isNvidia() && *PNVIDIAANTIFLICKER) || isSoftware())
|
||||
glFinish();
|
||||
else
|
||||
glFlush(); // mark an implicit sync point
|
||||
@ -2295,6 +2299,10 @@ bool CHyprRenderer::isIntel() {
|
||||
return m_intel;
|
||||
}
|
||||
|
||||
bool CHyprRenderer::isSoftware() {
|
||||
return m_software;
|
||||
}
|
||||
|
||||
bool CHyprRenderer::isMgpu() {
|
||||
return m_mgpu;
|
||||
}
|
||||
|
||||
@ -75,6 +75,7 @@ class CHyprRenderer {
|
||||
SP<CRenderbuffer> getCurrentRBO();
|
||||
bool isNvidia();
|
||||
bool isIntel();
|
||||
bool isSoftware();
|
||||
bool isMgpu();
|
||||
void makeEGLCurrent();
|
||||
void unsetEGL();
|
||||
@ -143,6 +144,7 @@ class CHyprRenderer {
|
||||
eRenderMode m_renderMode = RENDER_MODE_NORMAL;
|
||||
bool m_nvidia = false;
|
||||
bool m_intel = false;
|
||||
bool m_software = false;
|
||||
bool m_mgpu = false;
|
||||
|
||||
struct {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user