diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index cfbd7ef9..1681dea1 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -539,6 +539,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("cursor:enable_hyprcursor", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1}); + m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0}); m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0}); diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 950032a4..cf10db71 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -6,6 +6,8 @@ #include "../protocols/core/Compositor.hpp" #include "eventLoop/EventLoopManager.hpp" #include "SeatManager.hpp" +#include +#include CPointerManager::CPointerManager() { hooks.monitorAdded = g_pHookSystem->hookDynamic("newMonitor", [this](void* self, SCallbackInfo& info, std::any data) { @@ -395,9 +397,35 @@ SP CPointerManager::renderHWCursorBuffer(SPmakeEGLCurrent(); g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); - const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); - if (!RBO) - return nullptr; + auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); + if (!RBO) { + Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier); + static auto PDUMB = CConfigValue("cursor:allow_dumb_copy"); + if (!*PDUMB) + return nullptr; + + auto bufData = buf->beginDataPtr(0); + auto bufPtr = std::get<0>(bufData); + + // clear buffer + memset(bufPtr, 0, std::get<2>(bufData)); + + auto texBuffer = currentCursorImage.pBuffer ? currentCursorImage.pBuffer : currentCursorImage.surface->resource()->current.buffer; + + if (texBuffer) { + auto textAttrs = texBuffer->shm(); + auto texData = texBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE); + auto texPtr = std::get<0>(texData); + Debug::log(TRACE, "cursor texture {}x{} {} {} {}", textAttrs.size.x, textAttrs.size.y, (void*)texPtr, textAttrs.format, textAttrs.stride); + // copy cursor texture + for (int i = 0; i < texBuffer->shm().size.y; i++) + memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * textAttrs.stride, textAttrs.stride); + } + + buf->endDataPtr(); + + return buf; + } RBO->bind(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 274813d6..61690479 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1092,10 +1092,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked) return false; // do not DS if this monitor is being mirrored. Will break the functionality. - if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock())) { - Debug::log(TRACE, "Direct scanout failed: soft locked / HW cursors failed"); + if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock())) return false; - } const auto PCANDIDATE = pMonitor->solitaryClient.lock();