From 6b92144f15117f9f7d93fe9867d6ec849d9abce1 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 11 Jan 2024 13:15:20 +0100 Subject: [PATCH] surface: avoid spam of window surfaces with scale and transform events fixes #4408 --- src/Compositor.cpp | 17 +++++++++++++++++ src/Window.cpp | 7 ++++++- src/events/Windows.cpp | 2 -- src/helpers/WLSurface.hpp | 8 +++++++- src/render/OpenGL.cpp | 4 +++- src/render/Renderer.cpp | 9 +++++++-- 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 62903cf9..cbdcd6b8 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2797,10 +2797,27 @@ void CCompositor::leaveUnsafeState() { void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) { g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale); wlr_surface_set_preferred_buffer_scale(pSurface, static_cast(std::ceil(scale))); + + const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface); + if (!PSURFACE) { + Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredScaleForSurface", (uintptr_t)pSurface); + return; + } + + PSURFACE->m_fLastScale = scale; + PSURFACE->m_iLastScale = static_cast(std::ceil(scale)); } void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) { wlr_surface_set_preferred_buffer_transform(pSurface, transform); + + const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface); + if (!PSURFACE) { + Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredTransformForSurface", (uintptr_t)pSurface); + return; + } + + PSURFACE->m_eLastTransform = transform; } void CCompositor::updateSuspendedStates() { diff --git a/src/Window.cpp b/src/Window.cpp index 73835ccd..818b4089 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -366,7 +366,12 @@ void CWindow::updateSurfaceScaleTransformDetails() { m_pWLSurface.wlr(), [](wlr_surface* surf, int x, int y, void* data) { const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID); - g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f); + + const auto PSURFACE = CWLSurface::surfaceFromWlr(surf); + if (PSURFACE && PSURFACE->m_fLastScale == PMONITOR->scale) + return; + + g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR->scale); g_pCompositor->setPreferredTransformForSurface(surf, PMONITOR->transform); }, this); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index b3c811c1..cb7a6aaf 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -803,8 +803,6 @@ void Events::listener_commitWindow(void* owner, void* data) { PWINDOW->m_pPendingSizeAck.reset(); } - PWINDOW->updateSurfaceScaleTransformDetails(); - g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); diff --git a/src/helpers/WLSurface.hpp b/src/helpers/WLSurface.hpp index faef4353..03714bbf 100644 --- a/src/helpers/WLSurface.hpp +++ b/src/helpers/WLSurface.hpp @@ -28,8 +28,14 @@ class CWLSurface { bool m_bFillIgnoreSmall = false; // if present, means this is a base surface of a window. Cleaned on unassign() - CWindow* m_pOwner = nullptr; + CWindow* m_pOwner = nullptr; + // track surface data and avoid dupes + float m_fLastScale = 0; + int m_iLastScale = 0; + wl_output_transform m_eLastTransform = (wl_output_transform)-1; + + // CWLSurface& operator=(wlr_surface* pSurface) { destroy(); m_pWLRSurface = pSurface; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 2dd4ca0e..55a48a46 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2019,8 +2019,10 @@ void CHyprOpenGLImpl::clearWithTex() { TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor); } + CBox box = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y}; + if (TEXIT != m_mMonitorBGTextures.end()) - renderTexturePrimitive(TEXIT->second, &m_mMonitorRenderResources[m_RenderData.pMonitor].backgroundTexBox); + renderTexture(TEXIT->second, &box, 1); } void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b7776ee6..6d5af8d9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1997,6 +1997,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR Vector2D logicalZero = pMonitor->vecPixelSize / scaleZero; if (logicalZero == logicalZero.round()) { pMonitor->scale = scaleZero; + wlr_output_set_scale(pMonitor->output, pMonitor->scale); } else { for (size_t i = 1; i < 90; ++i) { double scaleUp = (searchScale + i) / 120.0; @@ -2034,11 +2035,15 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } else pMonitor->scale = searchScale; } + + // for wlroots, that likes flooring, we have to do this. + double logicalX = std::round(pMonitor->vecPixelSize.x / pMonitor->scale); + logicalX += 0.1; + + wlr_output_set_scale(pMonitor->output, pMonitor->vecPixelSize.x / logicalX); } } - wlr_output_set_scale(pMonitor->output, pMonitor->scale); - // clang-format off static const std::array>, 2> formats{ std::vector>{ /* 10-bit */