renderer/opengl: invalidate intermediate FBs post render, avoid stencil if possible (#12848)

This commit is contained in:
Vaxry 2026-01-05 22:37:54 +01:00 committed by GitHub
parent 107275238c
commit 6fce2d7288
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 45 additions and 56 deletions

View file

@ -123,3 +123,10 @@ GLuint CFramebuffer::getFBID() {
SP<CTexture> CFramebuffer::getStencilTex() { SP<CTexture> CFramebuffer::getStencilTex() {
return m_stencilTex; return m_stencilTex;
} }
void CFramebuffer::invalidate(const std::vector<GLenum>& attachments) {
if (!isAllocated())
return;
glInvalidateFramebuffer(GL_FRAMEBUFFER, attachments.size(), attachments.data());
}

View file

@ -19,6 +19,7 @@ class CFramebuffer {
SP<CTexture> getTexture(); SP<CTexture> getTexture();
SP<CTexture> getStencilTex(); SP<CTexture> getStencilTex();
GLuint getFBID(); GLuint getFBID();
void invalidate(const std::vector<GLenum>& attachments);
Vector2D m_size; Vector2D m_size;
DRMFormat m_drmFormat = 0 /* DRM_FORMAT_INVALID */; DRMFormat m_drmFormat = 0 /* DRM_FORMAT_INVALID */;

View file

@ -890,6 +890,16 @@ void CHyprOpenGLImpl::end() {
popMonitorTransformEnabled(); popMonitorTransformEnabled();
} }
// invalidate our render FBs to signal to the driver we don't need them anymore
m_renderData.pCurrentMonData->mirrorFB.bind();
m_renderData.pCurrentMonData->mirrorFB.invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
m_renderData.pCurrentMonData->mirrorSwapFB.bind();
m_renderData.pCurrentMonData->mirrorSwapFB.invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
m_renderData.pCurrentMonData->offloadFB.bind();
m_renderData.pCurrentMonData->offloadFB.invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
m_renderData.pCurrentMonData->offMainFB.bind();
m_renderData.pCurrentMonData->offMainFB.invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
// reset our data // reset our data
m_renderData.pMonitor.reset(); m_renderData.pMonitor.reset();
m_renderData.mouseZoomFactor = 1.f; m_renderData.mouseZoomFactor = 1.f;
@ -1351,8 +1361,6 @@ void CHyprOpenGLImpl::clear(const CHyprColor& color) {
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
}); });
} }
scissor(nullptr);
} }
void CHyprOpenGLImpl::blend(bool enabled) { void CHyprOpenGLImpl::blend(bool enabled) {
@ -1432,40 +1440,15 @@ void CHyprOpenGLImpl::renderRectWithBlurInternal(const CBox& box, const CHyprCol
m_renderData.currentFB->bind(); m_renderData.currentFB->bind();
// make a stencil for rounded corners to work with blur
scissor(nullptr); // allow the entire window and stencil to render
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
setCapStatus(GL_STENCIL_TEST, true);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
renderRect(box, CHyprColor(0, 0, 0, 0), SRectRenderData{.round = data.round, .roundingPower = data.roundingPower});
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
scissor(box);
CBox MONITORBOX = {0, 0, m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y}; CBox MONITORBOX = {0, 0, m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y};
pushMonitorTransformEnabled(true); pushMonitorTransformEnabled(true);
const auto SAVEDRENDERMODIF = m_renderData.renderModif; const auto SAVEDRENDERMODIF = m_renderData.renderModif;
m_renderData.renderModif = {}; // fix shit m_renderData.renderModif = {}; // fix shit
renderTexture(POUTFB->getTexture(), MONITORBOX, renderTexture(POUTFB->getTexture(), MONITORBOX,
STextureRenderData{.damage = &damage, .a = data.blurA, .round = 0, .roundingPower = 2.0f, .allowCustomUV = false, .allowDim = false, .noAA = false}); STextureRenderData{.damage = &damage, .a = data.blurA, .round = data.round, .roundingPower = 2.F, .allowCustomUV = false, .allowDim = false, .noAA = false});
popMonitorTransformEnabled(); popMonitorTransformEnabled();
m_renderData.renderModif = SAVEDRENDERMODIF; m_renderData.renderModif = SAVEDRENDERMODIF;
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
setCapStatus(GL_STENCIL_TEST, false);
glStencilMask(0xFF);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
scissor(nullptr);
renderRectWithDamageInternal(box, col, data); renderRectWithDamageInternal(box, col, data);
} }
@ -2386,32 +2369,35 @@ void CHyprOpenGLImpl::renderTextureWithBlurInternal(SP<CTexture> tex, const CBox
m_renderData.currentFB->bind(); m_renderData.currentFB->bind();
// make a stencil for rounded corners to work with blur const auto NEEDS_STENCIL = m_renderData.discardMode != 0;
scissor(nullptr); // allow the entire window and stencil to render
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
setCapStatus(GL_STENCIL_TEST, true); if (NEEDS_STENCIL) {
scissor(nullptr); // allow the entire window and stencil to render
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 1, 0xFF); setCapStatus(GL_STENCIL_TEST, true);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glStencilFunc(GL_ALWAYS, 1, 0xFF);
if (USENEWOPTIMIZE && !(m_renderData.discardMode & DISCARD_ALPHA)) glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
renderRect(box, CHyprColor(0, 0, 0, 0), SRectRenderData{.round = data.round, .roundingPower = data.roundingPower});
else
renderTexture(tex, box,
STextureRenderData{.a = data.a,
.round = data.round,
.roundingPower = data.roundingPower,
.discardActive = true,
.allowCustomUV = true,
.wrapX = data.wrapX,
.wrapY = data.wrapY}); // discard opaque
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 0xFF); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); if (USENEWOPTIMIZE && !(m_renderData.discardMode & DISCARD_ALPHA))
renderRect(box, CHyprColor(0, 0, 0, 0), SRectRenderData{.round = data.round, .roundingPower = data.roundingPower});
else
renderTexture(tex, box,
STextureRenderData{.a = data.a,
.round = data.round,
.roundingPower = data.roundingPower,
.discardActive = true,
.allowCustomUV = true,
.wrapX = data.wrapX,
.wrapY = data.wrapY}); // discard opaque
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
// stencil done. Render everything. // stencil done. Render everything.
const auto LASTTL = m_renderData.primarySurfaceUVTopLeft; const auto LASTTL = m_renderData.primarySurfaceUVTopLeft;
@ -2452,10 +2438,6 @@ void CHyprOpenGLImpl::renderTextureWithBlurInternal(SP<CTexture> tex, const CBox
m_renderData.primarySurfaceUVTopLeft = LASTTL; m_renderData.primarySurfaceUVTopLeft = LASTTL;
m_renderData.primarySurfaceUVBottomRight = LASTBR; m_renderData.primarySurfaceUVBottomRight = LASTBR;
// render the window, but clear stencil
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
// draw window // draw window
setCapStatus(GL_STENCIL_TEST, false); setCapStatus(GL_STENCIL_TEST, false);
renderTextureInternal(tex, box, renderTextureInternal(tex, box,
@ -2472,8 +2454,7 @@ void CHyprOpenGLImpl::renderTextureWithBlurInternal(SP<CTexture> tex, const CBox
.wrapY = data.wrapY, .wrapY = data.wrapY,
}); });
glStencilMask(0xFF); m_renderData.currentFB->invalidate({GL_STENCIL_ATTACHMENT});
glStencilFunc(GL_ALWAYS, 1, 0xFF);
scissor(nullptr); scissor(nullptr);
} }