diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index a289be1a..defa1a11 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -137,6 +137,7 @@ void CConfigManager::setDefaultVars() { configValues["decoration:blur:noise"].floatValue = 0.0117; configValues["decoration:blur:contrast"].floatValue = 0.8916; configValues["decoration:blur:brightness"].floatValue = 0.8172; + configValues["decoration:blur:special"].intValue = 1; configValues["decoration:active_opacity"].floatValue = 1; configValues["decoration:inactive_opacity"].floatValue = 1; configValues["decoration:fullscreen_opacity"].floatValue = 1; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 9cd5ced8..11c92525 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -473,6 +473,54 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) { renderRectWithDamage(box, col, &m_RenderData.damage, round); } +void CHyprOpenGLImpl::renderRectWithBlur(wlr_box* box, const CColor& col, int round, float blurA) { + if (m_RenderData.damage.empty()) + return; + + CRegion damage{m_RenderData.damage}; + damage.intersect(box); + + CFramebuffer* POUTFB = blurMainFramebufferWithDamage(blurA, &damage); + + // bind primary + m_RenderData.pCurrentMonData->primaryFB.bind(); + + // make a stencil for rounded corners to work with blur + scissor((wlr_box*)nullptr); // allow the entire window and stencil to render + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + + glEnable(GL_STENCIL_TEST); + + glStencilFunc(GL_ALWAYS, 1, -1); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + renderRect(box, CColor(0, 0, 0, 0), round); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glStencilFunc(GL_EQUAL, 1, -1); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + scissor(box); + wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; + m_bEndFrame = true; // fix transformed + const auto SAVEDRENDERMODIF = m_RenderData.renderModif; + m_RenderData.renderModif = {}; // fix shit + renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, blurA, &damage, 0, false, false, false); + m_bEndFrame = false; + m_RenderData.renderModif = SAVEDRENDERMODIF; + + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + glDisable(GL_STENCIL_TEST); + glStencilMask(-1); + glStencilFunc(GL_ALWAYS, 1, 0xFF); + scissor((wlr_box*)nullptr); + + renderRectWithDamage(box, col, &m_RenderData.damage, round); +} + void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CRegion* damage, int round) { RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); @@ -788,7 +836,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, wlr_box* pBox) // but it works... well, I guess? // // Dual (or more) kawase blur -CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* pBox, CRegion* originalDamage) { +CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* originalDamage) { TRACY_GPU_ZONE("RenderBlurMainFramebufferWithDamage"); @@ -1054,7 +1102,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { // make the fake dmg CRegion fakeDamage{0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; wlr_box wholeMonitor = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - const auto POUTFB = blurMainFramebufferWithDamage(1, &wholeMonitor, &fakeDamage); + const auto POUTFB = blurMainFramebufferWithDamage(1, &fakeDamage); // render onto blurFB m_RenderData.pCurrentMonData->blurFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y); @@ -1155,7 +1203,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, if (!USENEWOPTIMIZE) { inverseOpaque.translate({pBox->x, pBox->y}).intersect(texDamage); - POUTFB = blurMainFramebufferWithDamage(a, pBox, &inverseOpaque); + POUTFB = blurMainFramebufferWithDamage(a, &inverseOpaque); } else { POUTFB = &m_RenderData.pCurrentMonData->blurFB; } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 23b78d6a..c04e8c65 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -103,6 +103,7 @@ class CHyprOpenGLImpl { void bindWlrOutputFb(); void renderRect(wlr_box*, const CColor&, int round = 0); + void renderRectWithBlur(wlr_box*, const CColor&, int round = 0, float blurA = 1.f); void renderRectWithDamage(wlr_box*, const CColor&, CRegion* damage, int round = 0); void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0, bool allowCustomUV = false); void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); @@ -177,7 +178,7 @@ class CHyprOpenGLImpl { void initShaders(); // returns the out FB, can be either Mirror or MirrorSwap - CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, CRegion* damage); + CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false, bool allowDim = false); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6a9df66e..0105780d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -453,7 +453,8 @@ void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMon } void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time, const Vector2D& translate, const float& scale) { - static auto* const PDIMSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:dim_special")->floatValue; + static auto* const PDIMSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:dim_special")->floatValue; + static auto* const PBLURSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:blur:special")->intValue; const SRenderModifData RENDERMODIFDATA = {translate, scale}; @@ -605,18 +606,21 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* continue; if (!renderedSpecialBG) { + const auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID); + const auto SPECIALANIMPROGRS = + PSPECIALWORKSPACE->m_vRenderOffset.isBeingAnimated() ? PSPECIALWORKSPACE->m_vRenderOffset.getCurveValue() : PSPECIALWORKSPACE->m_fAlpha.getCurveValue(); + const bool ANIMOUT = !pMonitor->specialWorkspaceID; + if (*PDIMSPECIAL != 0.f) { - const auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID); - - const auto SPECIALANIMPROGRS = - PSPECIALWORKSPACE->m_vRenderOffset.isBeingAnimated() ? PSPECIALWORKSPACE->m_vRenderOffset.getCurveValue() : PSPECIALWORKSPACE->m_fAlpha.getCurveValue(); - - const bool ANIMOUT = !pMonitor->specialWorkspaceID; - - wlr_box monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; + wlr_box monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS))); } + if (*PBLURSPECIAL) { + wlr_box monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; + g_pHyprOpenGL->renderRectWithBlur(&monbox, CColor(0, 0, 0, 0), 0, (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)); + } + renderedSpecialBG = true; }