From 0a9544013112ae486705bf915adfa34933cfe6be Mon Sep 17 00:00:00 2001 From: UjinT34 Date: Thu, 25 Jul 2024 02:55:34 +0300 Subject: [PATCH] first attempt --- src/helpers/Monitor.cpp | 8 ++- src/managers/PointerManager.cpp | 100 +++++++++++++++++++++++++------- 2 files changed, 86 insertions(+), 22 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index b0ac1a1b..812662e9 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -399,8 +399,10 @@ int CMonitor::findAvailableDefaultWS() { SP CMonitor::resizeSwapchain(SP swapchain, Vector2D size, bool isCursor) { if (!swapchain || size != swapchain->currentOptions().size) { - if (!swapchain) + if (!swapchain) { + Debug::log(TRACE, "creating new cursor {} swapchain", isCursor); swapchain = Aquamarine::CSwapchain::create(output->getBackend()->preferredAllocator(), output->getBackend()); + } auto options = swapchain->currentOptions(); options.size = size; @@ -408,6 +410,8 @@ SP CMonitor::resizeSwapchain(SP options.scanout = true; options.cursor = isCursor; options.multigpu = 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. @@ -860,6 +864,7 @@ bool CMonitor::attemptDirectScanout() { } bool CMonitor::resizeCursorSwapchain(Vector2D size) { + Debug::log(TRACE, "resizeCursorSwapchain"); auto swapchain = resizeSwapchain(cursorSwapchain, size, true); if (!cursorSwapchain) cursorSwapchain = swapchain; @@ -868,6 +873,7 @@ bool CMonitor::resizeCursorSwapchain(Vector2D size) { } bool CMonitor::resizeCursorFallbackSwapchain(Vector2D size) { + Debug::log(TRACE, "resizeCursorFallbackSwapchain"); auto swapchain = resizeSwapchain(cursorFallbackSwapchain, size, false); if (!cursorFallbackSwapchain) cursorFallbackSwapchain = swapchain; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 323a354a..f5903eb3 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -6,6 +6,10 @@ #include "../protocols/core/Compositor.hpp" #include "eventLoop/EventLoopManager.hpp" #include "SeatManager.hpp" +#include "render/OpenGL.hpp" +#include +#include +#include #include #include @@ -396,35 +400,34 @@ SP CPointerManager::renderHWCursorBuffer(SPmakeEGLCurrent(); g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); - auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format); + bool needsFallback = false; + SP fallback; + + 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); + needsFallback = true; - // clear buffer - memset(bufPtr, 0, std::get<2>(bufData)); + if (!state->monitor->resizeCursorFallbackSwapchain(maxSize)) + return nullptr; - 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); + fallback = state->monitor->cursorFallbackSwapchain->next(nullptr); + if (!fallback) { + Debug::log(TRACE, "Failed to acquire a buffer from the cursor fallback swapchain"); + return nullptr; } - - buf->endDataPtr(); - - return buf; - } + RBO = g_pHyprRenderer->getOrCreateRenderbuffer(fallback, state->monitor->cursorFallbackSwapchain->currentOptions().format); + if (!RBO) { + Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", fallback->dmabuf().format, fallback->dmabuf().modifier); + return nullptr; + } else + Debug::log(TRACE, "Created cursor RB with format {}, mod {}", fallback->dmabuf().format, fallback->dmabuf().modifier); + } else + Debug::log(TRACE, "Created cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier); RBO->bind(); @@ -438,11 +441,66 @@ SP CPointerManager::renderHWCursorBuffer(SPrenderTexture(texture, &xbox, 1.F); g_pHyprOpenGL->end(); - glFlush(); + if (needsFallback) + glFinish(); + else + glFlush(); g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; g_pHyprRenderer->onRenderbufferDestroy(RBO.get()); + if (needsFallback) { + // wlroots tries to blit here but it'll fail the same way we've got here in the first place + auto bufAttrs = buf->dmabuf(); + Debug::log(TRACE, "mapping cursor buffer for writing"); + auto bufData = buf->beginDataPtr(GBM_BO_TRANSFER_WRITE); + auto bufPtr = std::get<0>(bufData); + + auto textAttrs = fallback->dmabuf(); + Debug::log(TRACE, "mapping cursor fallback buffer for reading"); + auto texData = fallback->beginDataPtr(GBM_BO_TRANSFER_WRITE); + auto texPtr = std::get<0>(texData); + Debug::log(TRACE, "cursor buffer {}x{} {} format={}({}) stride={}({})", bufAttrs.size.x, bufAttrs.size.y, (void*)bufPtr, bufAttrs.format, std::get<1>(bufData), + bufAttrs.strides[0], std::get<2>(bufData)); + Debug::log(TRACE, "cursor fallback buffer {}x{} {} format={}({}) stride={}({})", textAttrs.size.x, textAttrs.size.y, (void*)texPtr, textAttrs.format, std::get<1>(texData), + textAttrs.strides[0], std::get<2>(texData)); + + const auto dma = fallback->dmabuf(); + + auto image = g_pHyprOpenGL->createEGLImage(dma); + if (image == EGL_NO_IMAGE_KHR) { + Debug::log(TRACE, "texture fallback failed"); + return nullptr; + } + + GLuint id; + + GLCALL(glGenTextures(1, &id)); + + GLCALL(glBindTexture(GL_TEXTURE_2D, id)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GLCALL(g_pHyprOpenGL->m_sProc.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image)); + GLCALL(glBindTexture(GL_TEXTURE_2D, 0)); + + Debug::log(TRACE, "texture fallback got {}", image); + if (!texPtr) + texPtr = (uint8_t*)image; + + if (!bufPtr || !texPtr) + return nullptr; + + // copy rendered cursor + for (int i = 0; i < textAttrs.size.y; i++) { + Debug::log(TRACE, "copying {}/{} dst start={}, src start={}, length={}", i + 1, textAttrs.size.y, (void*)(bufPtr + i * bufAttrs.strides[0]), + (void*)(texPtr + i * textAttrs.strides[0]), textAttrs.strides[0]); + memcpy(bufPtr + i * bufAttrs.strides[0], texPtr + i * textAttrs.strides[0], textAttrs.strides[0]); + } + + buf->endDataPtr(); + fallback->endDataPtr(); + } + return buf; }