diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Compositor.cpp | 36 | ||||
| -rw-r--r-- | src/Compositor.hpp | 17 | ||||
| -rw-r--r-- | src/managers/PointerManager.cpp | 2 | ||||
| -rw-r--r-- | src/protocols/DRMSyncobj.cpp | 14 | ||||
| -rw-r--r-- | src/protocols/LinuxDMABUF.cpp | 15 | ||||
| -rw-r--r-- | src/protocols/MesaDRM.cpp | 24 | ||||
| -rw-r--r-- | src/render/OpenGL.cpp | 2 | ||||
| -rw-r--r-- | src/render/Renderer.cpp | 14 | ||||
| -rw-r--r-- | src/render/Renderer.hpp | 2 |
9 files changed, 87 insertions, 39 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a2733042..cbb70e2b 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -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) { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 70b18691..eddbe677 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -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 = {}; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 318ec343..f5635810 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -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) diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp index bedec422..0896b904 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp @@ -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))); diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index 24cf2951..c7de03a2 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -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)}; diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index 45ee24c5..789f90b6 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -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); } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 27abe81f..f4599a84 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -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); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index beeb0f5a..cf8ed0ba 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -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; } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index a986b63b..b1e514f3 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -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 { |
