From b9937484f4deefbc07c5fc3483d15885068e975d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 30 Nov 2023 10:14:35 +0000 Subject: [PATCH] screencopy: fix broken shm copying fixes #4001 --- src/protocols/Screencopy.cpp | 60 +++++++++++++++++++++++--------- src/protocols/ToplevelExport.cpp | 7 +++- src/render/Renderer.cpp | 16 +++++---- src/render/Renderer.hpp | 7 ++-- 4 files changed, 64 insertions(+), 26 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index fdd89d30..2e00a509 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -424,26 +424,54 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) { } bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) { - // void* data; - // uint32_t format; - // size_t stride; - // if (!wlr_buffer_begin_data_ptr_access(frame->buffer, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride)) - // return false; + wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer); + if (!sourceTex) + return false; - // if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer)) { - // Debug::log(ERR, "[sc] shm: Client requested a copy to a buffer that failed to pass wlr_renderer_begin_with_buffer"); - // wlr_buffer_end_data_ptr_access(frame->buffer); - // return false; - // } + void* data; + uint32_t format; + size_t stride; + if (!wlr_buffer_begin_data_ptr_access(frame->buffer, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride)) { + wlr_texture_destroy(sourceTex); + return false; + } - // bool success = wlr_renderer_read_pixels(g_pCompositor->m_sWLRRenderer, format, stride, frame->box.width, frame->box.height, frame->box.x, frame->box.y, 0, 0, data); - // wlr_renderer_end(g_pCompositor->m_sWLRRenderer); - // wlr_buffer_end_data_ptr_access(frame->buffer); + CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; - // return success; + g_pHyprRenderer->makeEGLCurrent(); - return false; // TODO: maybe fix this with the new rendering pipeline? - // though who tf isnt using dmabuf? + CFramebuffer fb; + fb.alloc(frame->box.w, frame->box.h); // 8bit only + + if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb)) { + wlr_texture_destroy(sourceTex); + wlr_buffer_end_data_ptr_access(frame->buffer); + return false; + } + + CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}.translate({-frame->box.x, -frame->box.y}); + g_pHyprOpenGL->setMonitorTransformEnabled(false); + g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1); + g_pHyprOpenGL->setMonitorTransformEnabled(true); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb); + + const auto PFORMAT = gles2FromDRM(format); + if (!PFORMAT) { + Debug::log(ERR, "[sc] Cannot read pixels, unsupported format {:x}", (uintptr_t)PFORMAT); + wlr_texture_destroy(sourceTex); + wlr_buffer_end_data_ptr_access(frame->buffer); + return false; + } + + glReadPixels(0, 0, frame->box.w, frame->box.h, PFORMAT->gl_format, PFORMAT->gl_type, data); + + g_pHyprRenderer->endRender(); + + wlr_buffer_end_data_ptr_access(frame->buffer); + wlr_texture_destroy(sourceTex); + + return true; } bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 6c626e87..ef9906d9 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -363,7 +363,12 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID); CRegion fakeDamage{0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10}; - if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE)) { + g_pHyprRenderer->makeEGLCurrent(); + + CFramebuffer outFB; + outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); + + if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &outFB)) { wlr_buffer_end_data_ptr_access(frame->buffer); return false; } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 20bcdcd2..b7b6ae96 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2312,7 +2312,7 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode if (!m_pCurrentWlrBuffer) return false; } else { - m_pCurrentWlrBuffer = buffer; + m_pCurrentWlrBuffer = wlr_buffer_lock(buffer); } try { @@ -2331,13 +2331,17 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode void CHyprRenderer::endRender() { const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; - g_pHyprOpenGL->end(); - - if (m_eRenderMode == RENDER_MODE_FULL_FAKE) { - wlr_output_rollback(PMONITOR->output); - return; + if (m_eRenderMode != RENDER_MODE_TO_BUFFER_READ_ONLY) + g_pHyprOpenGL->end(); + else { + g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; + g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f; + g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = true; } + if (m_eRenderMode == RENDER_MODE_FULL_FAKE) + return; + if (isNvidia()) glFinish(); else diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 3c21a84e..aaafa257 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -30,9 +30,10 @@ enum eRenderPassMode enum eRenderMode { - RENDER_MODE_NORMAL = 0, - RENDER_MODE_FULL_FAKE = 1, - RENDER_MODE_TO_BUFFER = 2 + RENDER_MODE_NORMAL = 0, + RENDER_MODE_FULL_FAKE = 1, + RENDER_MODE_TO_BUFFER = 2, + RENDER_MODE_TO_BUFFER_READ_ONLY = 3, }; class CToplevelExportProtocolManager;