diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index b9f3bf37..4b835621 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -396,25 +396,27 @@ int CMonitor::findAvailableDefaultWS() { return INT32_MAX; // shouldn't be reachable } -SP CMonitor::resizeSwapchain(SP swapchain, Vector2D size, bool isCursor) { +SP CMonitor::resizeSwapchain(SP swapchain, Vector2D size, bool isCursor, bool isDumb) { if (!swapchain || size != swapchain->currentOptions().size) { - if (!swapchain) - swapchain = Aquamarine::CSwapchain::create(output->getBackend()->preferredAllocator(), output->getBackend()); + if (!swapchain) { + auto allocator = isDumb && output->getBackend()->fallbackAllocator() ? output->getBackend()->fallbackAllocator() : output->getBackend()->preferredAllocator(); + swapchain = Aquamarine::CSwapchain::create(allocator, output->getBackend()); + } auto options = swapchain->currentOptions(); options.size = size; options.length = 2; options.scanout = true; options.cursor = isCursor; - options.multigpu = output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD; + options.multigpu = !isDumb && output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD; if (!isCursor && cursorSwapchain) options.format = cursorSwapchain->currentOptions().format; // We do not set the format. 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 (!swapchain->reconfigure(options)) { - Debug::log(TRACE, "Failed to reconfigure {} swapchain", isCursor ? "cursor" : "cursor fallback"); + Debug::log(TRACE, "Failed to reconfigure{} {} swapchain", isCursor ? "cursor" : "cursor fallback", isDumb ? " dumb" : ""); return nullptr; } } @@ -862,13 +864,21 @@ bool CMonitor::attemptDirectScanout() { } bool CMonitor::resizeCursorSwapchain(Vector2D size) { - auto swapchain = resizeSwapchain(cursorSwapchain, size, true); + auto swapchain = resizeSwapchain(cursorSwapchain, size, true, useDumbCursorBuffer); if (!cursorSwapchain) cursorSwapchain = swapchain; return !!swapchain; } +bool CMonitor::resizeCursorSwapchain(Vector2D size, bool useDumb) { + if (useDumbCursorBuffer != useDumb && cursorSwapchain) { + useDumbCursorBuffer = useDumb; + cursorSwapchain = nullptr; // recreate swapchain with a different allocator + } + return resizeCursorSwapchain(size); +} + bool CMonitor::resizeCursorFallbackSwapchain(Vector2D size) { auto swapchain = resizeSwapchain(cursorFallbackSwapchain, size, false); if (!cursorFallbackSwapchain) diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 2898d0a8..0d891a65 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -180,6 +180,7 @@ class CMonitor { void scheduleDone(); bool attemptDirectScanout(); bool resizeCursorSwapchain(Vector2D size); + bool resizeCursorSwapchain(Vector2D size, bool useDumb); bool resizeCursorFallbackSwapchain(Vector2D size); bool m_bEnabled = false; @@ -194,9 +195,10 @@ class CMonitor { private: void setupDefaultWS(const SMonitorRule&); int findAvailableDefaultWS(); - SP resizeSwapchain(SP swapchain, Vector2D size, bool isCursor); + SP resizeSwapchain(SP swapchain, Vector2D size, bool isCursor, bool isDumb = false); - wl_event_source* doneSource = nullptr; + wl_event_source* doneSource = nullptr; + bool useDumbCursorBuffer = false; struct { CHyprSignalListener frame; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index ae946813..d52c0237 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -411,10 +411,25 @@ SP CPointerManager::renderHWCursorBuffer(SP("cursor:allow_dumb_copy"); static auto PSLOW = CConfigValue("cursor:allow_slow_copy"); + auto isDumb = buf->type() == Aquamarine::BUFFER_TYPE_DMABUF_DUMB; + if (isDumb != *PDUMB) { + Debug::log(TRACE, "[pointer] switching swapchain to {}", *PDUMB ? "dumb" : "gbm"); + if (!state->monitor->resizeCursorSwapchain(maxSize, *PDUMB)) + return nullptr; + + buf = state->monitor->cursorSwapchain->next(nullptr); + if (!buf) { + Debug::log(TRACE, "Failed to acquire a buffer from the cursor swapchain"); + return nullptr; + } + isDumb = buf->type() == Aquamarine::BUFFER_TYPE_DMABUF_DUMB; + } + if (!*PDUMB && !*PSLOW) return nullptr; - if (*PSLOW) { + // slow copy will fail with dumb buffer + if (*PSLOW && !*PDUMB) { Debug::log(TRACE, "[pointer] performing slow copy"); needsFallback = true; @@ -437,8 +452,11 @@ SP CPointerManager::renderHWCursorBuffer(SPbeginDataPtr(0); auto bufPtr = std::get<0>(bufData); + auto bufSize = isDumb ? buf->shm().size : buf->dmabuf().size; + auto bufStride = isDumb ? buf->shm().stride : buf->dmabuf().strides[0]; + // clear buffer - memset(bufPtr, 0, buf->type() == Aquamarine::BUFFER_TYPE_DMABUF_DUMB ? std::get<2>(bufData) * buf->dmabuf().size.y : std::get<2>(bufData)); + memset(bufPtr, 0, bufStride * bufSize.y); auto texBuffer = currentCursorImage.pBuffer ? currentCursorImage.pBuffer : currentCursorImage.surface->resource()->current.buffer; if (texBuffer) { @@ -448,11 +466,11 @@ SP CPointerManager::renderHWCursorBuffer(SPdmabuf().strides[0] == textAttrs.stride && buf->dmabuf().size == textAttrs.size) + if (bufStride == textAttrs.stride && bufSize == textAttrs.size) memcpy(bufPtr, texPtr, textAttrs.stride * textAttrs.size.y); else for (int i = 0; i < texBuffer->shm().size.y; i++) - memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * textAttrs.stride, textAttrs.stride); + memcpy(bufPtr + i * bufStride, texPtr + i * textAttrs.stride, textAttrs.stride); } buf->endDataPtr();