From 37d2840246af43a7141e2a036820fc3dec468f01 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 22 Dec 2023 19:54:05 +0100 Subject: [PATCH] renderer: reject non-clean scales, find nearest clean --- src/helpers/Monitor.hpp | 3 ++- src/render/Renderer.cpp | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index f44e2c16..2b196c96 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -40,7 +40,8 @@ class CMonitor { uint64_t ID = -1; int activeWorkspace = -1; - float scale = 1; + float setScale = 1; // scale set by cfg + float scale = 1; // real scale std::string szName = ""; std::string szDescription = ""; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 2397849a..b56c275e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1704,7 +1704,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // Check if the rule isn't already applied // TODO: clean this up lol if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && - DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && + DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->setScale == pMonitorRule->scale && ((DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) || pMonitorRule->offset == Vector2D(-INT32_MAX, -INT32_MAX)) && pMonitor->transform == pMonitorRule->transform && pMonitorRule->enable10bit == pMonitor->enabled10bit && @@ -1726,6 +1726,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->scale = DEFAULTSCALE; } + pMonitor->setScale = pMonitor->scale; + wlr_output_set_transform(pMonitor->output, pMonitorRule->transform); pMonitor->transform = pMonitorRule->transform; @@ -1942,6 +1944,42 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->vecPixelSize = pMonitor->vecSize; + Vector2D logicalSize = pMonitor->vecPixelSize / pMonitor->scale; + if (logicalSize.x != std::round(logicalSize.x) || logicalSize.y != std::round(logicalSize.y)) { + // invalid scale, will produce fractional pixels. + // find the nearest valid. + + float searchScale = std::round(pMonitor->scale * 360.0); + bool found = false; + + for (size_t i = 0; i < 90; ++i) { + double scaleUp = (searchScale + i) / 360.0; + double scaleDown = (searchScale - i) / 360.0; + + Vector2D logicalUp = pMonitor->vecPixelSize / scaleUp; + Vector2D logicalDown = pMonitor->vecPixelSize / scaleDown; + + if (logicalUp == logicalUp.round()) { + found = true; + searchScale = scaleUp; + break; + } + if (logicalDown == logicalDown.round()) { + found = true; + searchScale = scaleDown; + break; + } + } + + if (!found) { + Debug::log(ERR, "Invalid scale passed to monitor, {} failed to find a clean divisor", pMonitor->scale); + g_pConfigManager->addParseError("Invalid scale passed to monitor " + pMonitor->szName + ", failed to find a clean divisor"); + } else { + Debug::log(WARN, "Invalid scale ({}) passed to monitor, adjusting to {}", pMonitor->scale, searchScale); + pMonitor->scale = searchScale; + } + } + // clang-format off static const std::array>, 2> formats{ std::vector>{ /* 10-bit */