Skip to content
Merged
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
36 changes: 18 additions & 18 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
36 changes: 23 additions & 13 deletions src/Compositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ void CCompositor::restoreNofile() {
}

bool CCompositor::supportsDrmSyncobjTimeline() const {
return m_bDrmSyncobjTimelineSupported;
return m_drm.syncobjSupport || m_drmRenderNode.syncObjSupport;
}

void CCompositor::setMallocThreshold() {
Expand Down Expand Up @@ -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) {
Expand Down
17 changes: 12 additions & 5 deletions src/Compositor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 = {};
Expand Down
2 changes: 1 addition & 1 deletion src/managers/PointerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 12 additions & 2 deletions src/protocols/DRMSyncobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
Expand Down
15 changes: 14 additions & 1 deletion src/protocols/LinuxDMABUF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down Expand Up @@ -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)};
Expand Down
24 changes: 11 additions & 13 deletions src/protocols/MesaDRM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion src/render/OpenGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
14 changes: 11 additions & 3 deletions src/render/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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});
Expand All @@ -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};
Expand All @@ -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});
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -2295,6 +2299,10 @@ bool CHyprRenderer::isIntel() {
return m_intel;
}

bool CHyprRenderer::isSoftware() {
return m_software;
}

bool CHyprRenderer::isMgpu() {
return m_mgpu;
}
Expand Down
2 changes: 2 additions & 0 deletions src/render/Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class CHyprRenderer {
SP<CRenderbuffer> getCurrentRBO();
bool isNvidia();
bool isIntel();
bool isSoftware();
bool isMgpu();
void makeEGLCurrent();
void unsetEGL();
Expand Down Expand Up @@ -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 {
Expand Down
Loading