diff --git a/src/Window.cpp b/src/Window.cpp index 63c5a79e3..1bd30f22d 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -548,6 +548,12 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { m_sAdditionalConfigData.dimAround = true; } else if (r.szRule == "keepaspectratio") { m_sAdditionalConfigData.keepAspectRatio = true; + } else if (r.szRule.find("xray") == 0) { + CVarList vars(r.szRule, 0, ' '); + + try { + m_sAdditionalConfigData.xray = configStringToInt(vars[1]); + } catch (...) {} } } @@ -569,6 +575,7 @@ void CWindow::updateDynamicRules() { m_sAdditionalConfigData.forceRGBX = false; m_sAdditionalConfigData.borderSize = -1; m_sAdditionalConfigData.keepAspectRatio = false; + m_sAdditionalConfigData.xray = -1; const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this); for (auto& r : WINDOWRULES) { diff --git a/src/Window.hpp b/src/Window.hpp index 3ff9f6f7b..3d1c69ac6 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -122,6 +122,7 @@ struct SWindowAdditionalConfigData { CWindowOverridableVar dimAround = false; CWindowOverridableVar forceRGBX = false; CWindowOverridableVar keepAspectRatio = false; + CWindowOverridableVar xray = -1; // -1 means unset, takes precedence over the renderdata one CWindowOverridableVar borderSize = -1; // -1 means unset, takes precedence over the renderdata one }; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 461956a20..0723ad242 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -889,11 +889,11 @@ bool windowRuleValid(const std::string& RULE) { RULE != "nofullscreenrequest" && RULE != "nomaximizerequest" && RULE != "fakefullscreen" && RULE != "nomaxsize" && RULE != "pin" && RULE != "noanim" && RULE != "dimaround" && RULE != "windowdance" && RULE != "maximize" && RULE != "keepaspectratio" && RULE.find("animation") != 0 && RULE.find("rounding") != 0 && RULE.find("workspace") != 0 && RULE.find("bordercolor") != 0 && RULE != "forcergbx" && RULE != "noinitialfocus" && RULE != "stayfocused" && - RULE.find("bordersize") != 0); + RULE.find("bordersize") != 0 && RULE.find("xray") != 0); } bool layerRuleValid(const std::string& RULE) { - return !(RULE != "noanim" && RULE != "blur" && RULE.find("ignorealpha") != 0 && RULE.find("ignorezero") != 0); + return !(RULE != "noanim" && RULE != "blur" && RULE.find("ignorealpha") != 0 && RULE.find("ignorezero") != 0 && RULE.find("xray") != 0); } void CConfigManager::handleWindowRule(const std::string& command, const std::string& value) { diff --git a/src/helpers/WLClasses.cpp b/src/helpers/WLClasses.cpp index 3a03afcda..c257b6b85 100644 --- a/src/helpers/WLClasses.cpp +++ b/src/helpers/WLClasses.cpp @@ -12,6 +12,7 @@ void SLayerSurface::applyRules() { forceBlur = false; ignoreAlpha = false; ignoreAlphaValue = 0.f; + xray = -1; for (auto& rule : g_pConfigManager->getMatchingRules(this)) { if (rule.rule == "noanim") @@ -29,6 +30,11 @@ void SLayerSurface::applyRules() { if (!alphaValue.empty()) ignoreAlphaValue = std::stof(alphaValue); } catch (...) { Debug::log(ERR, "Invalid value passed to ignoreAlpha"); } + } else if (rule.rule.find("xray") == 0) { + CVarList vars{rule.rule, 0, ' '}; + try { + xray = configStringToInt(vars[1]); + } catch (...) {} } } } \ No newline at end of file diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 18e223b69..e43a00fff 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -50,6 +50,7 @@ struct SLayerSurface { bool noAnimations = false; bool forceBlur = false; + int xray = -1; bool ignoreAlpha = false; float ignoreAlphaValue = 0.f; @@ -242,7 +243,7 @@ struct STablet { std::string name = ""; bool operator==(const STablet& b) const { - return wlrDevice == b.wlrDevice; + return wlrDevice == b.wlrDevice; } }; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index b56c876bb..f57907622 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1022,6 +1022,21 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { } } + for (auto& m : g_pCompositor->m_vMonitors) { + for (auto& lsl : m->m_aLayerSurfaceLayers) { + for (auto& ls : lsl) { + if (!ls->layerSurface || ls->xray != 1) + continue; + + if (ls->layerSurface->surface->opaque && ls->alpha.fl() >= 1.f) + continue; + + hasWindows = true; + break; + } + } + } + if (!hasWindows) return; @@ -1073,13 +1088,33 @@ bool CHyprOpenGLImpl::preBlurQueued() { return !(!m_RenderData.pCurrentMonData->blurFBDirty || !*PBLURNEWOPTIMIZE || !*PBLUR || !m_RenderData.pCurrentMonData->blurFBShouldRender); } +bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWindow* pWindow) { + static auto* const PBLURNEWOPTIMIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations")->intValue; + static auto* const PBLURXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur:xray")->intValue; + + if (!m_RenderData.pCurrentMonData->blurFB.m_cTex.m_iTexID) + return false; + + if (pWindow && pWindow->m_sAdditionalConfigData.xray.toUnderlying() == 0) + return false; + + if (pLayer && pLayer->xray == 0) + return false; + + if ((*PBLURNEWOPTIMIZE && pWindow && !pWindow->m_bIsFloating && !g_pCompositor->isWorkspaceSpecial(pWindow->m_iWorkspaceID)) || *PBLURXRAY) + return true; + + if ((pLayer && pLayer->xray == 1) || (pWindow && pWindow->m_sAdditionalConfigData.xray.toUnderlying() == 1)) + return true; + + return false; +} + void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round, bool blockBlurOptimization) { RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; static auto* const PNOBLUROVERSIZED = &g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized")->intValue; - static auto* const PBLURNEWOPTIMIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations")->intValue; - static auto* const PBLURXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur:xray")->intValue; TRACY_GPU_ZONE("RenderTextureWithBlur"); @@ -1113,10 +1148,8 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, wlr_region_scale(inverseOpaque.pixman(), inverseOpaque.pixman(), m_RenderData.pMonitor->scale); - // vvv TODO: layered blur fbs? - const bool USENEWOPTIMIZE = (*PBLURNEWOPTIMIZE && !blockBlurOptimization && - ((m_pCurrentWindow && !m_pCurrentWindow->m_bIsFloating && !g_pCompositor->isWorkspaceSpecial(m_pCurrentWindow->m_iWorkspaceID)) || *PBLURXRAY) && - m_RenderData.pCurrentMonData->blurFB.m_cTex.m_iTexID); + // vvv TODO: layered blur fbs? + const bool USENEWOPTIMIZE = shouldUseNewBlurOptimizations(m_pCurrentLayer, m_pCurrentWindow) && !blockBlurOptimization; CFramebuffer* POUTFB = nullptr; if (!USENEWOPTIMIZE) { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index d38f54aeb..1719102be 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -26,8 +26,7 @@ inline const float fullVerts[] = { }; inline const float fanVertsFull[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f}; -enum eDiscardMode -{ +enum eDiscardMode { DISCARD_OPAQUE = 1, DISCARD_ALPHA = 1 << 1 }; @@ -149,6 +148,7 @@ class CHyprOpenGLImpl { bool m_bReloadScreenShader = true; // at launch it can be set CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window + SLayerSurface* m_pCurrentLayer = nullptr; // hack to get the current rendered layer std::unordered_map m_mWindowFramebuffers; std::unordered_map m_mLayerFramebuffers; @@ -185,6 +185,8 @@ class CHyprOpenGLImpl { void preBlurForCurrentMonitor(); + bool shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWindow* pWindow); + friend class CHyprRenderer; }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index aaa15b86a..29bdb39d2 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -414,6 +414,8 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times renderdata.h = pLayer->geometry.height; renderdata.blockBlurOptimization = pLayer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM || pLayer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; + g_pHyprOpenGL->m_pCurrentLayer = pLayer; + if (pLayer->ignoreAlpha) { g_pHyprOpenGL->m_RenderData.discardMode |= DISCARD_ALPHA; g_pHyprOpenGL->m_RenderData.discardOpacity = pLayer->ignoreAlphaValue; @@ -424,6 +426,8 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times renderdata.squishOversized = false; // don't squish popups renderdata.dontRound = true; wlr_layer_surface_v1_for_each_popup_surface(pLayer->layerSurface, renderSurface, &renderdata); + + g_pHyprOpenGL->m_pCurrentLayer = nullptr; } void CHyprRenderer::renderIMEPopup(SIMEPopup* pPopup, CMonitor* pMonitor, timespec* time) {