diff options
| author | outfoxxed <outfoxxed@outfoxxed.me> | 2025-01-23 13:57:33 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-23 22:57:33 +0100 |
| commit | 465cf66df14c28427ba30580253be6e3908bd28c (patch) | |
| tree | 93bc76546ffa329972863fd2716e8856debaeef8 /src/render/pass/SurfacePassElement.cpp | |
| parent | 1a0a22ad038bbd51c4e1514868d6dcd505af0242 (diff) | |
protocols: add hyprland_surface_v1.set_visible_region implementation (#9120)
Diffstat (limited to 'src/render/pass/SurfacePassElement.cpp')
| -rw-r--r-- | src/render/pass/SurfacePassElement.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index d720081f..b79407c8 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -7,6 +7,8 @@ #include "../../managers/input/InputManager.hpp" #include "../Renderer.hpp" +#include <hyprutils/math/Box.hpp> +#include <hyprutils/math/Vector2D.hpp> #include <hyprutils/utils/ScopeGuard.hpp> using namespace Hyprutils::Utils; @@ -28,6 +30,7 @@ void CSurfacePassElement::draw(const CRegion& damage) { g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; g_pHyprOpenGL->m_RenderData.clipBox = {}; + g_pHyprOpenGL->m_RenderData.clipRegion = {}; g_pHyprOpenGL->m_RenderData.discardMode = 0; g_pHyprOpenGL->m_RenderData.discardOpacity = 0; g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; @@ -84,6 +87,11 @@ void CSurfacePassElement::draw(const CRegion& damage) { Debug::log(TRACE, "FIXME: rendering surface with color management enabled, should apply necessary transformations"); g_pHyprRenderer->calculateUVForSurface(data.pWindow, data.surface, data.pMonitor->self.lock(), data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1); + auto cancelRender = false; + g_pHyprOpenGL->m_RenderData.clipRegion = visibleRegion(cancelRender); + if (cancelRender) + return; + // check for fractional scale surfaces misaligning the buffer size // in those cases it's better to just force nearest neighbor // as long as the window is not animated. During those it'd look weird. @@ -229,6 +237,48 @@ CRegion CSurfacePassElement::opaqueRegion() { return data.texture && data.texture->m_bOpaque ? boundingBox()->expand(-data.rounding) : CRegion{}; } +CRegion CSurfacePassElement::visibleRegion(bool& cancel) { + auto PSURFACE = CWLSurface::fromResource(data.surface); + if (!PSURFACE) + return {}; + + const auto& bufferSize = data.surface->current.bufferSize; + + auto visibleRegion = PSURFACE->m_visibleRegion.copy(); + if (visibleRegion.empty()) + return {}; + + visibleRegion.intersect(CBox(Vector2D(), bufferSize)); + + if (visibleRegion.empty()) { + cancel = true; + return visibleRegion; + } + + // deal with any rounding errors that might come from scaling + visibleRegion.expand(1); + + auto uvTL = g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft; + auto uvBR = g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight; + + if (uvTL == Vector2D(-1, -1)) + uvTL = Vector2D(0, 0); + + if (uvBR == Vector2D(-1, -1)) + uvBR = Vector2D(1, 1); + + visibleRegion.translate(-uvTL * bufferSize); + + auto texBox = getTexBox(); + texBox.scale(data.pMonitor->scale); + texBox.round(); + + visibleRegion.scale((Vector2D(1, 1) / (uvBR - uvTL)) * (texBox.size() / bufferSize)); + visibleRegion.translate((data.pos + data.localPos) * data.pMonitor->scale - data.pMonitor->vecPosition); + + return visibleRegion; +} + void CSurfacePassElement::discard() { if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { Debug::log(TRACE, "discard for invisible surface"); |
