From 40081cb330fa838ad9c0a7b87c20b2300ea7fb38 Mon Sep 17 00:00:00 2001
From: Vaxry <vaxry@vaxry.net>
Date: Sat, 2 Nov 2024 15:26:25 +0000
Subject: [PATCH] renderer: improve api around new framebuffer changes

ref #8325
---
 src/protocols/Screencopy.cpp                  |  2 +-
 src/protocols/ToplevelExport.cpp              |  2 +-
 src/render/Framebuffer.cpp                    | 19 ++++-
 src/render/Framebuffer.hpp                    | 12 ++-
 src/render/OpenGL.cpp                         | 75 ++++++++++---------
 .../decorations/CHyprDropShadowDecoration.cpp |  2 +-
 6 files changed, 68 insertions(+), 44 deletions(-)

diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp
index 780c081dd..1fcaff058 100644
--- a/src/protocols/Screencopy.cpp
+++ b/src/protocols/Screencopy.cpp
@@ -253,7 +253,7 @@ bool CScreencopyFrame::copyShm() {
     g_pHyprOpenGL->setMonitorTransformEnabled(false);
 
 #ifndef GLES2
-    glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.getFBID());
 #else
     glBindFramebuffer(GL_FRAMEBUFFER, fb.m_iFb);
 #endif
diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp
index f2af89db4..04c089d79 100644
--- a/src/protocols/ToplevelExport.cpp
+++ b/src/protocols/ToplevelExport.cpp
@@ -279,7 +279,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) {
     outFB.bind();
 
 #ifndef GLES2
-    glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.m_iFb);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.getFBID());
 #endif
 
     glPixelStorei(GL_PACK_ALIGNMENT, 1);
diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp
index 7e086778d..814a3339d 100644
--- a/src/render/Framebuffer.cpp
+++ b/src/render/Framebuffer.cpp
@@ -65,9 +65,10 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
     return true;
 }
 
-void CFramebuffer::addStencil() {
+void CFramebuffer::addStencil(SP<CTexture> tex) {
     // TODO: Allow this with gles2
 #ifndef GLES2
+    m_pStencilTex = tex;
     glBindTexture(GL_TEXTURE_2D, m_pStencilTex->m_iTexID);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_vSize.x, m_vSize.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
 
@@ -109,5 +110,17 @@ CFramebuffer::~CFramebuffer() {
 }
 
 bool CFramebuffer::isAllocated() {
-    return m_iFbAllocated;
-}
\ No newline at end of file
+    return m_iFbAllocated && m_cTex;
+}
+
+SP<CTexture> CFramebuffer::getTexture() {
+    return m_cTex;
+}
+
+GLuint CFramebuffer::getFBID() {
+    return m_iFbAllocated ? m_iFb : 0;
+}
+
+SP<CTexture> CFramebuffer::getStencilTex() {
+    return m_pStencilTex;
+}
diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp
index ca7f9e8a9..84dfeef12 100644
--- a/src/render/Framebuffer.hpp
+++ b/src/render/Framebuffer.hpp
@@ -9,17 +9,23 @@ class CFramebuffer {
     ~CFramebuffer();
 
     bool         alloc(int w, int h, uint32_t format = GL_RGBA);
-    void         addStencil();
+    void         addStencil(SP<CTexture> tex);
     void         bind();
     void         release();
     void         reset();
     bool         isAllocated();
+    SP<CTexture> getTexture();
+    SP<CTexture> getStencilTex();
+    GLuint       getFBID();
 
     Vector2D     m_vSize;
 
+  private:
     SP<CTexture> m_cTex;
-    GLuint       m_iFb;
-    bool         m_iFbAllocated{false};
+    GLuint       m_iFb          = -1;
+    bool         m_iFbAllocated = false;
 
     SP<CTexture> m_pStencilTex;
+
+    friend class CRenderbuffer;
 };
\ No newline at end of file
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index 209637076..415bb920c 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -830,15 +830,15 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb
     if (m_RenderData.pCurrentMonData->offloadFB.m_vSize != pMonitor->vecPixelSize) {
         m_RenderData.pCurrentMonData->stencilTex->allocate();
 
-        m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex    = m_RenderData.pCurrentMonData->stencilTex;
-        m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex     = m_RenderData.pCurrentMonData->stencilTex;
-        m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
-        m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex    = m_RenderData.pCurrentMonData->stencilTex;
-
         m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat);
         m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat);
         m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat);
         m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat);
+
+        m_RenderData.pCurrentMonData->offloadFB.addStencil(m_RenderData.pCurrentMonData->stencilTex);
+        m_RenderData.pCurrentMonData->mirrorFB.addStencil(m_RenderData.pCurrentMonData->stencilTex);
+        m_RenderData.pCurrentMonData->mirrorSwapFB.addStencil(m_RenderData.pCurrentMonData->stencilTex);
+        m_RenderData.pCurrentMonData->offMainFB.addStencil(m_RenderData.pCurrentMonData->stencilTex);
     }
 
     if (m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_RenderData.pMonitor->mirrors.empty())
@@ -870,10 +870,9 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb
         // we can render to the rbo / fbo (fake) directly
         const auto PFBO        = fb ? fb : PRBO->getFB();
         m_RenderData.currentFB = PFBO;
-        if (PFBO->m_pStencilTex != m_RenderData.pCurrentMonData->stencilTex) {
-            PFBO->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
-            PFBO->addStencil();
-        }
+        if (PFBO->getStencilTex() != m_RenderData.pCurrentMonData->stencilTex)
+            PFBO->addStencil(m_RenderData.pCurrentMonData->stencilTex);
+
         PFBO->bind();
         m_bOffloadedFramebuffer = false;
     }
@@ -924,9 +923,9 @@ void CHyprOpenGLImpl::end() {
         blend(false);
 
         if (m_sFinalScreenShader.program < 1 && !g_pHyprRenderer->m_bCrashingInProgress)
-            renderTexturePrimitive(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox);
+            renderTexturePrimitive(m_RenderData.pCurrentMonData->offloadFB.getTexture(), &monbox);
         else
-            renderTexture(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox, 1.f);
+            renderTexture(m_RenderData.pCurrentMonData->offloadFB.getTexture(), &monbox, 1.f);
 
         blend(true);
 
@@ -1269,7 +1268,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round
     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);
+    renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, &damage, 0, false, false, false);
     m_bEndFrame              = false;
     m_RenderData.renderModif = SAVEDRENDERMODIF;
 
@@ -1629,7 +1628,8 @@ void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, CBox* pBox, CFramebuf
     glBindTexture(tex->m_iTarget, tex->m_iTexID);
 
     glActiveTexture(GL_TEXTURE0 + 1);
-    glBindTexture(matte.m_cTex->m_iTarget, matte.m_cTex->m_iTexID);
+    auto matteTex = matte.getTexture();
+    glBindTexture(matteTex->m_iTarget, matteTex->m_iTexID);
 
     glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
     glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -1696,9 +1696,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
 
         glActiveTexture(GL_TEXTURE0);
 
-        glBindTexture(m_RenderData.currentFB->m_cTex->m_iTarget, m_RenderData.currentFB->m_cTex->m_iTexID);
+        auto currentTex = m_RenderData.currentFB->getTexture();
 
-        glTexParameteri(m_RenderData.currentFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glBindTexture(currentTex->m_iTarget, currentTex->m_iTexID);
+
+        glTexParameteri(currentTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
         glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program);
 
@@ -1740,9 +1742,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
 
         glActiveTexture(GL_TEXTURE0);
 
-        glBindTexture(currentRenderToFB->m_cTex->m_iTarget, currentRenderToFB->m_cTex->m_iTexID);
+        auto currentTex = currentRenderToFB->getTexture();
 
-        glTexParameteri(currentRenderToFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glBindTexture(currentTex->m_iTarget, currentTex->m_iTexID);
+
+        glTexParameteri(currentTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
         glUseProgram(pShader->program);
 
@@ -1790,7 +1794,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
     // draw the things.
     // first draw is swap -> mirr
     PMIRRORFB->bind();
-    glBindTexture(PMIRRORSWAPFB->m_cTex->m_iTarget, PMIRRORSWAPFB->m_cTex->m_iTexID);
+    glBindTexture(PMIRRORSWAPFB->getTexture()->m_iTarget, PMIRRORSWAPFB->getTexture()->m_iTexID);
 
     // damage region will be scaled, make a temp
     CRegion tempDamage{damage};
@@ -1818,9 +1822,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
 
         glActiveTexture(GL_TEXTURE0);
 
-        glBindTexture(currentRenderToFB->m_cTex->m_iTarget, currentRenderToFB->m_cTex->m_iTexID);
+        auto currentTex = currentRenderToFB->getTexture();
 
-        glTexParameteri(currentRenderToFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glBindTexture(currentTex->m_iTarget, currentTex->m_iTexID);
+
+        glTexParameteri(currentTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
         glUseProgram(m_RenderData.pCurrentMonData->m_shBLURFINISH.program);
 
@@ -1858,7 +1864,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
     }
 
     // finish
-    glBindTexture(PMIRRORFB->m_cTex->m_iTarget, 0);
+    glBindTexture(PMIRRORFB->getTexture()->m_iTarget, 0);
 
     blend(BLENDBEFORE);
 
@@ -1972,7 +1978,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
     clear(CColor(0, 0, 0, 0));
 
     m_bEndFrame = true; // fix transformed
-    renderTextureInternalWithDamage(POUTFB->m_cTex, &wholeMonitor, 1, &fakeDamage, 0, false, true, false);
+    renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, &fakeDamage, 0, false, true, false);
     m_bEndFrame = false;
 
     m_RenderData.currentFB->bind();
@@ -2003,7 +2009,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin
     static auto PBLURNEWOPTIMIZE = CConfigValue<Hyprlang::INT>("decoration:blur:new_optimizations");
     static auto PBLURXRAY        = CConfigValue<Hyprlang::INT>("decoration:blur:xray");
 
-    if (!m_RenderData.pCurrentMonData->blurFB.m_cTex->m_iTexID)
+    if (!m_RenderData.pCurrentMonData->blurFB.getTexture())
         return false;
 
     if (pWindow && pWindow->m_sWindowData.xray.hasValue() && !pWindow->m_sWindowData.xray.valueOrDefault())
@@ -2105,7 +2111,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
     setMonitorTransformEnabled(true);
     if (!USENEWOPTIMIZE)
         setRenderModifEnabled(false);
-    renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? blurA : a * blurA, &texDamage, 0, false, false, false);
+    renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, *PBLURIGNOREOPACITY ? blurA : a * blurA, &texDamage, 0, false, false, false);
     if (!USENEWOPTIMIZE)
         setRenderModifEnabled(true);
     setMonitorTransformEnabled(false);
@@ -2238,9 +2244,8 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr
 
     g_pHyprRenderer->makeEGLCurrent();
 
-    pFramebuffer->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
-
     pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat);
+    pFramebuffer->addStencil(m_RenderData.pCurrentMonData->stencilTex);
 
     g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer);
 
@@ -2376,7 +2381,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) {
 
     const auto FBDATA = &m_mWindowFramebuffers.at(ref);
 
-    if (!FBDATA->m_cTex->m_iTexID)
+    if (!FBDATA->getTexture())
         return;
 
     const auto PMONITOR = pWindow->m_pMonitor.lock();
@@ -2402,7 +2407,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) {
 
     m_bEndFrame = true;
 
-    renderTextureInternalWithDamage(FBDATA->m_cTex, &windowBox, pWindow->m_fAlpha.value(), &fakeDamage, 0);
+    renderTextureInternalWithDamage(FBDATA->getTexture(), &windowBox, pWindow->m_fAlpha.value(), &fakeDamage, 0);
 
     m_bEndFrame = false;
 }
@@ -2415,7 +2420,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) {
 
     const auto FBDATA = &m_mLayerFramebuffers.at(pLayer);
 
-    if (!FBDATA->m_cTex->m_iTexID)
+    if (!FBDATA->getTexture())
         return;
 
     const auto PMONITOR = pLayer->monitor.lock();
@@ -2435,7 +2440,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) {
 
     m_bEndFrame = true;
 
-    renderTextureInternalWithDamage(FBDATA->m_cTex, &layerBox, pLayer->alpha.value(), &fakeDamage, 0);
+    renderTextureInternalWithDamage(FBDATA->getTexture(), &layerBox, pLayer->alpha.value(), &fakeDamage, 0);
 
     m_bEndFrame = false;
 }
@@ -2526,7 +2531,7 @@ void CHyprOpenGLImpl::saveBufferForMirror(CBox* box) {
 
     blend(false);
 
-    renderTexture(m_RenderData.currentFB->m_cTex, box, 1.f, 0, false, false);
+    renderTexture(m_RenderData.currentFB->getTexture(), box, 1.f, 0, false, false);
 
     blend(true);
 
@@ -2548,7 +2553,7 @@ void CHyprOpenGLImpl::renderMirrored() {
     monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2;
 
     const auto PFB = &m_mMonitorRenderResources[mirrored].monitorMirrorFB;
-    if (!PFB->isAllocated() || PFB->m_cTex->m_iTexID <= 0)
+    if (!PFB->isAllocated() || !PFB->getTexture())
         return;
 
     // replace monitor projection to undo the mirrored monitor's projection
@@ -2561,7 +2566,7 @@ void CHyprOpenGLImpl::renderMirrored() {
     // clear stuff outside of mirrored area (e.g. when changing to mirrored)
     clear(CColor(0, 0, 0, 0));
 
-    renderTexture(PFB->m_cTex, &monbox, 1.f, 0, false, false);
+    renderTexture(PFB->getTexture(), &monbox, 1.f, 0, false, false);
 
     // reset matrix for further drawing
     m_RenderData.monitorProjection = monitor->projMatrix;
@@ -2926,7 +2931,7 @@ void CHyprOpenGLImpl::clearWithTex() {
     if (TEXIT != m_mMonitorBGFBs.end()) {
         CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
         m_bEndFrame = true;
-        renderTexture(TEXIT->second.m_cTex, &monbox, 1);
+        renderTexture(TEXIT->second.getTexture(), &monbox, 1);
         m_bEndFrame = false;
     }
 }
@@ -2978,7 +2983,7 @@ void CHyprOpenGLImpl::bindOffMain() {
 
 void CHyprOpenGLImpl::renderOffToMain(CFramebuffer* off) {
     CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
-    renderTexturePrimitive(off->m_cTex, &monbox);
+    renderTexturePrimitive(off->getTexture(), &monbox);
 }
 
 void CHyprOpenGLImpl::bindBackOnMain() {
diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp
index 79d5940ba..f146776f6 100644
--- a/src/render/decorations/CHyprDropShadowDecoration.cpp
+++ b/src/render/decorations/CHyprDropShadowDecoration.cpp
@@ -199,7 +199,7 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) {
         CBox monbox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
         g_pHyprOpenGL->setMonitorTransformEnabled(true);
         g_pHyprOpenGL->setRenderModifEnabled(false);
-        g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.m_cTex, &monbox, alphaFB);
+        g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.getTexture(), &monbox, alphaFB);
         g_pHyprOpenGL->setRenderModifEnabled(true);
         g_pHyprOpenGL->setMonitorTransformEnabled(false);