diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index c79fab70..8f25c686 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -153,7 +153,7 @@ void CHyprOpenGLImpl::end() { m_RenderData.damage = m_RenderData.pMonitor->lastFrameDamage; if (!m_RenderData.pMonitor->mirrors.empty()) - g_pHyprOpenGL->saveBufferForMirror(); // save with original damage region + saveBufferForMirror(); // save with original damage region glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb); wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; @@ -178,15 +178,17 @@ void CHyprOpenGLImpl::end() { monbox.y = m_RenderData.pMonitor->vecTransformedSize.y - monbox.height; } - clear(CColor(11.0 / 255.0, 11.0 / 255.0, 11.0 / 255.0, 1.0)); - m_bEndFrame = true; m_bApplyFinalShader = true; if (m_RenderData.mouseZoomUseMouse) m_RenderData.useNearestNeighbor = true; + blend(false); + renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f, 0); + blend(true); + m_RenderData.useNearestNeighbor = false; m_bApplyFinalShader = false; m_bEndFrame = false; @@ -389,6 +391,15 @@ void CHyprOpenGLImpl::clear(const CColor& color) { scissor((wlr_box*)nullptr); } +void CHyprOpenGLImpl::blend(bool enabled) { + if (enabled) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + + m_bBlend = enabled; +} + void CHyprOpenGLImpl::scissor(const wlr_box* pBox, bool transform) { RASSERT(m_RenderData.pMonitor, "Tried to scissor without begin()!"); @@ -452,7 +463,6 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CReg float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); - glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glUseProgram(m_RenderData.pCurrentMonData->m_shQUAD.program); @@ -547,7 +557,6 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b CShader* shader = nullptr; - glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); bool usingFinalShader = false; @@ -697,7 +706,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b // Dual (or more) kawase blur CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* pBox, CRegion* originalDamage) { - glDisable(GL_BLEND); + const auto BLENDBEFORE = m_bBlend; + blend(false); glDisable(GL_STENCIL_TEST); // get transforms for the full monitor @@ -806,6 +816,8 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p glBindTexture(PMIRRORFB->m_cTex.m_iTarget, 0); + blend(BLENDBEFORE); + return currentRenderToFB; } @@ -1455,8 +1467,12 @@ void CHyprOpenGLImpl::saveBufferForMirror() { wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y}; + blend(false); + renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f, 0, false, false); + blend(true); + m_RenderData.pCurrentMonData->primaryFB.bind(); } @@ -1589,19 +1605,16 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { void CHyprOpenGLImpl::clearWithTex() { RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!"); - static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue; - if (!*PRENDERTEX) { - auto TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor); + auto TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor); - if (TEXIT == m_mMonitorBGTextures.end()) { - createBGTextureForMonitor(m_RenderData.pMonitor); - TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor); - } - - if (TEXIT != m_mMonitorBGTextures.end()) - renderTexture(TEXIT->second, &m_mMonitorRenderResources[m_RenderData.pMonitor].backgroundTexBox, 1.0, 0); + if (TEXIT == m_mMonitorBGTextures.end()) { + createBGTextureForMonitor(m_RenderData.pMonitor); + TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor); } + + if (TEXIT != m_mMonitorBGTextures.end()) + renderTexture(TEXIT->second, &m_mMonitorRenderResources[m_RenderData.pMonitor].backgroundTexBox, 1.0, 0); } void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index ac5c3e6b..db8b37d1 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -111,6 +111,8 @@ class CHyprOpenGLImpl { void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); void restoreMatrix(); + void blend(bool enabled); + void makeWindowSnapshot(CWindow*); void makeRawWindowSnapshot(CWindow*, CFramebuffer*); void makeLayerSnapshot(SLayerSurface*); @@ -159,6 +161,7 @@ class CHyprOpenGLImpl { bool m_bFakeFrame = false; bool m_bEndFrame = false; bool m_bApplyFinalShader = false; + bool m_bBlend = false; CShader m_sFinalScreenShader; CTimer m_tGlobalTimer; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index acc5955e..f3656fc7 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -40,6 +40,13 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { rounding -= 1; // to fix a border issue + const bool CANDISABLEBLEND = RDATA->alpha >= 1.f && rounding == 0 && surface->opaque; + + if (CANDISABLEBLEND) + g_pHyprOpenGL->blend(false); + else + g_pHyprOpenGL->blend(true); + if (RDATA->surface && surface == RDATA->surface) { if (wlr_xwayland_surface_try_from_wlr_surface(surface) && !wlr_xwayland_surface_try_from_wlr_surface(surface)->has_alpha && RDATA->fadeAlpha * RDATA->alpha == 1.f) { g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true); @@ -58,6 +65,8 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { wlr_presentation_surface_textured_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->pMonitor->output); } + g_pHyprOpenGL->blend(true); + // reset the UV, we might've set it above g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); @@ -806,6 +815,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { static auto* const PNODIRECTSCANOUT = &g_pConfigManager->getConfigValuePtr("misc:no_direct_scanout")->intValue; static auto* const PVFR = &g_pConfigManager->getConfigValuePtr("misc:vfr")->intValue; static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue; + static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue; static int damageBlinkCleanup = 0; // because double-buffered @@ -979,11 +989,17 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { EMIT_HOOK_EVENT("render", RENDER_BEGIN); if (pMonitor->isMirror()) { + g_pHyprOpenGL->blend(false); g_pHyprOpenGL->renderMirrored(); + g_pHyprOpenGL->blend(true); EMIT_HOOK_EVENT("render", RENDER_POST_MIRROR); } else { - g_pHyprOpenGL->clear(CColor(17.0 / 255.0, 17.0 / 255.0, 17.0 / 255.0, 1.0)); - g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper" + g_pHyprOpenGL->blend(false); + if (*PRENDERTEX /* inverted cfg flag */) + g_pHyprOpenGL->clear(CColor(17.0 / 255.0, 17.0 / 255.0, 17.0 / 255.0, 1.0)); + else + g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper" + g_pHyprOpenGL->blend(true); wlr_box renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y}; renderWorkspace(pMonitor, g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace), &now, renderBox);