diff options
| author | UjinT34 <41110182+UjinT34@users.noreply.github.com> | 2026-03-07 13:27:47 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-07 10:27:47 +0000 |
| commit | 32e75e3e320fb66ab517a378df645f3d29b3a209 (patch) | |
| tree | 4212f4cf197fc961161de7a9e57b85735257184a /src/render | |
| parent | 36b19075f3a644a4095352d778e6d03e103bb334 (diff) | |
renderer: refactor render elements (#13438)
Part 2 of renderer refactors
Diffstat (limited to 'src/render')
24 files changed, 392 insertions, 312 deletions
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 165f580a..ad4409d5 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -49,6 +49,7 @@ #include "render/Framebuffer.hpp" #include "render/OpenGL.hpp" #include "render/Texture.hpp" +#include "render/decorations/CHyprDropShadowDecoration.hpp" #include "render/gl/GLFramebuffer.hpp" #include "render/gl/GLTexture.hpp" #include <hyprutils/math/Mat3x3.hpp> @@ -747,6 +748,309 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, const T g_pHyprOpenGL->m_renderData.currentWindow.reset(); } +void CHyprRenderer::draw(WP<IPassElement> element, const CRegion& damage) { + if (!element) + return; + + switch (element->type()) { + case EK_BORDER: draw(dc<CBorderPassElement*>(element.get()), damage); break; + case EK_CLEAR: draw(dc<CClearPassElement*>(element.get()), damage); break; + case EK_FRAMEBUFFER: draw(dc<CFramebufferElement*>(element.get()), damage); break; + case EK_PRE_BLUR: draw(dc<CPreBlurElement*>(element.get()), damage); break; + case EK_RECT: draw(dc<CRectPassElement*>(element.get()), damage); break; + case EK_HINTS: draw(dc<CRendererHintsPassElement*>(element.get()), damage); break; + case EK_SHADOW: draw(dc<CShadowPassElement*>(element.get()), damage); break; + case EK_SURFACE: draw(dc<CSurfacePassElement*>(element.get()), damage); break; + case EK_TEXTURE: draw(dc<CTexPassElement*>(element.get()), damage); break; + case EK_TEXTURE_MATTE: draw(dc<CTextureMatteElement*>(element.get()), damage); break; + default: Log::logger->log(Log::WARN, "Unimplimented draw for {}", element->passName()); + } +} + +void CHyprRenderer::draw(CBorderPassElement* element, const CRegion& damage) { + const auto& m_data = element->m_data; + if (m_data.hasGrad2) + g_pHyprOpenGL->renderBorder( + m_data.box, m_data.grad1, m_data.grad2, m_data.lerp, + {.round = m_data.round, .roundingPower = m_data.roundingPower, .borderSize = m_data.borderSize, .a = m_data.a, .outerRound = m_data.outerRound}); + else + g_pHyprOpenGL->renderBorder( + m_data.box, m_data.grad1, + {.round = m_data.round, .roundingPower = m_data.roundingPower, .borderSize = m_data.borderSize, .a = m_data.a, .outerRound = m_data.outerRound}); +} + +void CHyprRenderer::draw(CClearPassElement* element, const CRegion& damage) { + const auto& m_data = element->m_data; + g_pHyprOpenGL->clear(m_data.color); +}; + +void CHyprRenderer::draw(CFramebufferElement* element, const CRegion& damage) { + const auto& m_data = element->m_data; + SP<IFramebuffer> fb = nullptr; + + if (m_data.main) { + switch (m_data.framebufferID) { + case FB_MONITOR_RENDER_MAIN: fb = g_pHyprOpenGL->m_renderData.mainFB; break; + case FB_MONITOR_RENDER_CURRENT: fb = g_pHyprOpenGL->m_renderData.currentFB; break; + case FB_MONITOR_RENDER_OUT: fb = g_pHyprOpenGL->m_renderData.outFB; break; + } + + if (!fb) { + Log::logger->log(Log::ERR, "BUG THIS: CFramebufferElement::draw: main but null"); + return; + } + + } else { + switch (m_data.framebufferID) { + case FB_MONITOR_RENDER_EXTRA_OFFLOAD: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->offloadFB; break; + case FB_MONITOR_RENDER_EXTRA_MIRROR: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorFB; break; + case FB_MONITOR_RENDER_EXTRA_MIRROR_SWAP: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorSwapFB; break; + case FB_MONITOR_RENDER_EXTRA_OFF_MAIN: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->offMainFB; break; + case FB_MONITOR_RENDER_EXTRA_MONITOR_MIRROR: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->monitorMirrorFB; break; + case FB_MONITOR_RENDER_EXTRA_BLUR: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->blurFB; break; + } + + if (!fb) { + Log::logger->log(Log::ERR, "BUG THIS: CFramebufferElement::draw: not main but null"); + return; + } + } + + fb->bind(); +}; + +void CHyprRenderer::draw(CPreBlurElement* element, const CRegion& damage) { + g_pHyprOpenGL->preBlurForCurrentMonitor(); +}; + +void CHyprRenderer::draw(CRectPassElement* element, const CRegion& damage) { + const auto& m_data = element->m_data; + if (m_data.box.w <= 0 || m_data.box.h <= 0) + return; + + if (!m_data.clipBox.empty()) + g_pHyprOpenGL->m_renderData.clipBox = m_data.clipBox; + + if (m_data.color.a == 1.F || !m_data.blur) + g_pHyprOpenGL->renderRect(m_data.box, m_data.color, {.damage = &damage, .round = m_data.round, .roundingPower = m_data.roundingPower}); + else + g_pHyprOpenGL->renderRect(m_data.box, m_data.color, + {.round = m_data.round, .roundingPower = m_data.roundingPower, .blur = true, .blurA = m_data.blurA, .xray = m_data.xray}); + + g_pHyprOpenGL->m_renderData.clipBox = {}; +}; + +void CHyprRenderer::draw(CRendererHintsPassElement* element, const CRegion& damage) { + const auto& m_data = element->m_data; + if (m_data.renderModif.has_value()) + g_pHyprOpenGL->m_renderData.renderModif = *m_data.renderModif; +}; + +void CHyprRenderer::draw(CShadowPassElement* element, const CRegion& damage) { + const auto& m_data = element->m_data; + m_data.deco->render(g_pHyprOpenGL->m_renderData.pMonitor.lock(), m_data.a); +}; + +void CHyprRenderer::draw(CSurfacePassElement* element, const CRegion& damage) { + const auto& m_data = element->m_data; + + g_pHyprOpenGL->m_renderData.currentWindow = m_data.pWindow; + g_pHyprOpenGL->m_renderData.surface = m_data.surface; + g_pHyprOpenGL->m_renderData.currentLS = m_data.pLS; + g_pHyprOpenGL->m_renderData.clipBox = m_data.clipBox; + g_pHyprOpenGL->m_renderData.discardMode = m_data.discardMode; + g_pHyprOpenGL->m_renderData.discardOpacity = m_data.discardOpacity; + g_pHyprOpenGL->m_renderData.useNearestNeighbor = m_data.useNearestNeighbor; + g_pHyprOpenGL->pushMonitorTransformEnabled(m_data.flipEndFrame); + + CScopeGuard x = {[]() { + g_pHyprOpenGL->m_renderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); + g_pHyprOpenGL->m_renderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); + g_pHyprOpenGL->m_renderData.useNearestNeighbor = false; + g_pHyprOpenGL->m_renderData.clipBox = {}; + g_pHyprOpenGL->m_renderData.clipRegion = {}; + g_pHyprOpenGL->m_renderData.discardMode = 0; + g_pHyprOpenGL->m_renderData.discardOpacity = 0; + g_pHyprOpenGL->m_renderData.useNearestNeighbor = false; + g_pHyprOpenGL->popMonitorTransformEnabled(); + g_pHyprOpenGL->m_renderData.currentWindow.reset(); + g_pHyprOpenGL->m_renderData.surface.reset(); + g_pHyprOpenGL->m_renderData.currentLS.reset(); + }}; + + if (!m_data.texture) + return; + + const auto& TEXTURE = m_data.texture; + + // this is bad, probably has been logged elsewhere. Means the texture failed + // uploading to the GPU. + if (!TEXTURE->m_texID) + return; + + const auto INTERACTIVERESIZEINPROGRESS = m_data.pWindow && g_layoutManager->dragController()->target() && g_layoutManager->dragController()->mode() == MBIND_RESIZE; + TRACY_GPU_ZONE("RenderSurface"); + + auto PSURFACE = Desktop::View::CWLSurface::fromResource(m_data.surface); + + const float ALPHA = m_data.alpha * m_data.fadeAlpha * (PSURFACE ? PSURFACE->m_alphaModifier : 1.F); + const float OVERALL_ALPHA = PSURFACE ? PSURFACE->m_overallOpacity : 1.F; + const bool BLUR = m_data.blur && (!TEXTURE->m_opaque || ALPHA < 1.F || OVERALL_ALPHA < 1.F); + + auto windowBox = element->getTexBox(); + + const auto PROJSIZEUNSCALED = windowBox.size(); + + windowBox.scale(m_data.pMonitor->m_scale); + windowBox.round(); + + if (windowBox.width <= 1 || windowBox.height <= 1) { + element->discard(); + return; + } + + const bool MISALIGNEDFSV1 = std::floor(m_data.pMonitor->m_scale) != m_data.pMonitor->m_scale /* Fractional */ && m_data.surface->m_current.scale == 1 /* fs protocol */ && + windowBox.size() != m_data.surface->m_current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, m_data.surface->m_current.bufferSize.x, 3) && + DELTALESSTHAN(windowBox.height, m_data.surface->m_current.bufferSize.y, 3) /* off by one-or-two */ && + (!m_data.pWindow || (!m_data.pWindow->m_realSize->isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */ && + (!m_data.pLS || (!m_data.pLS->m_realSize->isBeingAnimated())); /* not LS or not animated */ + + g_pHyprRenderer->calculateUVForSurface(m_data.pWindow, m_data.surface, m_data.pMonitor->m_self.lock(), m_data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1); + + auto cancelRender = false; + g_pHyprOpenGL->m_renderData.clipRegion = element->visibleRegion(cancelRender); + if (cancelRender) + return; + + // check for fractional scale surfaces misaligning the buffer size + // in those cases it's better to just force nearest neighbor + // as long as the window is not animated. During those it'd look weird. + // UV will fixup it as well + if (MISALIGNEDFSV1) + g_pHyprOpenGL->m_renderData.useNearestNeighbor = true; + + float rounding = m_data.rounding; + float roundingPower = m_data.roundingPower; + + rounding -= 1; // to fix a border issue + + if (m_data.dontRound) { + rounding = 0; + roundingPower = 2.0f; + } + + const bool WINDOWOPAQUE = m_data.pWindow && m_data.pWindow->wlSurface()->resource() == m_data.surface ? m_data.pWindow->opaque() : false; + const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding <= 0 && WINDOWOPAQUE; + + if (CANDISABLEBLEND) + g_pHyprOpenGL->blend(false); + else + g_pHyprOpenGL->blend(true); + + // FIXME: This is wrong and will bug the blur out as shit if the first surface + // is a subsurface that does NOT cover the entire frame. In such cases, we probably should fall back + // to what we do for misaligned surfaces (blur the entire thing and then render shit without blur) + if (m_data.surfaceCounter == 0 && !m_data.popup) { + if (BLUR) + g_pHyprOpenGL->renderTexture(TEXTURE, windowBox, + { + .surface = m_data.surface, + .a = ALPHA, + .blur = true, + .blurA = m_data.fadeAlpha, + .overallA = OVERALL_ALPHA, + .round = rounding, + .roundingPower = roundingPower, + .allowCustomUV = true, + .blockBlurOptimization = m_data.blockBlurOptimization, + }); + else + g_pHyprOpenGL->renderTexture(TEXTURE, windowBox, + {.a = ALPHA * OVERALL_ALPHA, .round = rounding, .roundingPower = roundingPower, .discardActive = false, .allowCustomUV = true}); + } else { + if (BLUR && m_data.popup) + g_pHyprOpenGL->renderTexture(TEXTURE, windowBox, + { + .surface = m_data.surface, + .a = ALPHA, + .blur = true, + .blurA = m_data.fadeAlpha, + .overallA = OVERALL_ALPHA, + .round = rounding, + .roundingPower = roundingPower, + .allowCustomUV = true, + .blockBlurOptimization = true, + }); + else + g_pHyprOpenGL->renderTexture(TEXTURE, windowBox, + {.a = ALPHA * OVERALL_ALPHA, .round = rounding, .roundingPower = roundingPower, .discardActive = false, .allowCustomUV = true}); + } + + if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) + m_data.surface->presentFeedback(m_data.when, m_data.pMonitor->m_self.lock()); + + // add async (dmabuf) buffers to usedBuffers so we can handle release later + // sync (shm) buffers will be released in commitState, so no need to track them here + if (m_data.surface->m_current.buffer && !m_data.surface->m_current.buffer->isSynchronous()) + g_pHyprRenderer->m_usedAsyncBuffers.emplace_back(m_data.surface->m_current.buffer); + + g_pHyprOpenGL->blend(true); +}; + +void CHyprRenderer::draw(CTexPassElement* element, const CRegion& damage) { + const auto& m_data = element->m_data; + g_pHyprOpenGL->pushMonitorTransformEnabled(m_data.flipEndFrame); + + CScopeGuard x = {[&]() { + // + g_pHyprOpenGL->popMonitorTransformEnabled(); + g_pHyprOpenGL->m_renderData.clipBox = {}; + if (m_data.replaceProjection) + g_pHyprOpenGL->m_renderData.monitorProjection = g_pHyprOpenGL->m_renderData.pMonitor->m_projMatrix; + if (m_data.ignoreAlpha.has_value()) + g_pHyprOpenGL->m_renderData.discardMode = 0; + }}; + + if (!m_data.clipBox.empty()) + g_pHyprOpenGL->m_renderData.clipBox = m_data.clipBox; + + if (m_data.replaceProjection) + g_pHyprOpenGL->m_renderData.monitorProjection = *m_data.replaceProjection; + + if (m_data.ignoreAlpha.has_value()) { + g_pHyprOpenGL->m_renderData.discardMode = DISCARD_ALPHA; + g_pHyprOpenGL->m_renderData.discardOpacity = *m_data.ignoreAlpha; + } + + if (m_data.blur) { + g_pHyprOpenGL->renderTexture(m_data.tex, m_data.box, + { + .a = m_data.a, + .blur = true, + .blurA = m_data.blurA, + .overallA = 1.F, + .round = m_data.round, + .roundingPower = m_data.roundingPower, + .blockBlurOptimization = m_data.blockBlurOptimization.value_or(false), + }); + } else { + g_pHyprOpenGL->renderTexture(m_data.tex, m_data.box, + {.damage = m_data.damage.empty() ? &damage : &m_data.damage, .a = m_data.a, .round = m_data.round, .roundingPower = m_data.roundingPower}); + } +}; + +void CHyprRenderer::draw(CTextureMatteElement* element, const CRegion& damage) { + const auto& m_data = element->m_data; + if (m_data.disableTransformAndModify) { + g_pHyprOpenGL->pushMonitorTransformEnabled(true); + g_pHyprOpenGL->setRenderModifEnabled(false); + g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, m_data.fb); + g_pHyprOpenGL->setRenderModifEnabled(true); + g_pHyprOpenGL->popMonitorTransformEnabled(); + } else + g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, m_data.fb); +}; + SP<ITexture> CHyprRenderer::createTexture(const SP<Aquamarine::IBuffer> buffer, bool keepDataCopy) { if (!buffer) return createTexture(); diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index bd14c219..b854715d 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -7,20 +7,32 @@ #include <optional> #include "../helpers/Monitor.hpp" #include "../desktop/view/LayerSurface.hpp" -#include "OpenGL.hpp" +#include "./pass/Pass.hpp" #include "Renderbuffer.hpp" #include "../helpers/time/Timer.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/time/Time.hpp" #include "../../protocols/cursor-shape-v1.hpp" +#include "desktop/view/Popup.hpp" #include "render/Framebuffer.hpp" #include "render/Texture.hpp" +#include "render/pass/BorderPassElement.hpp" +#include "render/pass/ClearPassElement.hpp" +#include "render/pass/FramebufferElement.hpp" +#include "render/pass/PreBlurElement.hpp" +#include "render/pass/RectPassElement.hpp" +#include "render/pass/RendererHintsPassElement.hpp" +#include "render/pass/ShadowPassElement.hpp" +#include "render/pass/SurfacePassElement.hpp" +#include "render/pass/TexPassElement.hpp" +#include "render/pass/TextureMatteElement.hpp" struct SMonitorRule; class CWorkspace; class CInputPopup; class IHLBuffer; class CEventLoopTimer; +class CRenderPass; const std::vector<const char*> ASSET_PATHS = { #ifdef DATAROOTDIR @@ -174,6 +186,18 @@ class CHyprRenderer { SP<CWLSurfaceResource> surface = nullptr, bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1); bool reloadShaders(const std::string& path = ""); + void draw(CBorderPassElement* element, const CRegion& damage); + void draw(CClearPassElement* element, const CRegion& damage); + void draw(CFramebufferElement* element, const CRegion& damage); + void draw(CPreBlurElement* element, const CRegion& damage); + void draw(CRectPassElement* element, const CRegion& damage); + void draw(CRendererHintsPassElement* element, const CRegion& damage); + void draw(CShadowPassElement* element, const CRegion& damage); + void draw(CSurfacePassElement* element, const CRegion& damage); + void draw(CTexPassElement* element, const CRegion& damage); + void draw(CTextureMatteElement* element, const CRegion& damage); + void draw(WP<IPassElement> element, const CRegion& damage); + private: void arrangeLayerArray(PHLMONITOR, const std::vector<PHLLSREF>&, bool, CBox*); void renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const CBox& geometry); @@ -219,6 +243,7 @@ class CHyprRenderer { std::vector<PHLWINDOWREF> m_renderUnfocused; SP<CEventLoopTimer> m_renderUnfocusedTimer; + friend class CRenderPass; friend class CHyprOpenGLImpl; friend class CToplevelExportFrame; friend class Screenshare::CScreenshareFrame; diff --git a/src/render/pass/BorderPassElement.cpp b/src/render/pass/BorderPassElement.cpp index 13063290..ef24224b 100644 --- a/src/render/pass/BorderPassElement.cpp +++ b/src/render/pass/BorderPassElement.cpp @@ -1,21 +1,9 @@ #include "BorderPassElement.hpp" -#include "../OpenGL.hpp" CBorderPassElement::CBorderPassElement(const CBorderPassElement::SBorderData& data_) : m_data(data_) { ; } -void CBorderPassElement::draw(const CRegion& damage) { - if (m_data.hasGrad2) - g_pHyprOpenGL->renderBorder( - m_data.box, m_data.grad1, m_data.grad2, m_data.lerp, - {.round = m_data.round, .roundingPower = m_data.roundingPower, .borderSize = m_data.borderSize, .a = m_data.a, .outerRound = m_data.outerRound}); - else - g_pHyprOpenGL->renderBorder( - m_data.box, m_data.grad1, - {.round = m_data.round, .roundingPower = m_data.roundingPower, .borderSize = m_data.borderSize, .a = m_data.a, .outerRound = m_data.outerRound}); -} - bool CBorderPassElement::needsLiveBlur() { return false; } diff --git a/src/render/pass/BorderPassElement.hpp b/src/render/pass/BorderPassElement.hpp index 238b9ed5..1a458fd5 100644 --- a/src/render/pass/BorderPassElement.hpp +++ b/src/render/pass/BorderPassElement.hpp @@ -18,7 +18,6 @@ class CBorderPassElement : public IPassElement { CBorderPassElement(const SBorderData& data_); virtual ~CBorderPassElement() = default; - virtual void draw(const CRegion& damage); virtual bool needsLiveBlur(); virtual bool needsPrecomputeBlur(); @@ -26,6 +25,9 @@ class CBorderPassElement : public IPassElement { return "CBorderPassElement"; } - private: + virtual ePassElementType type() { + return EK_BORDER; + }; + SBorderData m_data; }; diff --git a/src/render/pass/ClearPassElement.cpp b/src/render/pass/ClearPassElement.cpp index 256b857f..85080723 100644 --- a/src/render/pass/ClearPassElement.cpp +++ b/src/render/pass/ClearPassElement.cpp @@ -1,14 +1,9 @@ #include "ClearPassElement.hpp" -#include "../OpenGL.hpp" CClearPassElement::CClearPassElement(const CClearPassElement::SClearData& data_) : m_data(data_) { ; } -void CClearPassElement::draw(const CRegion& damage) { - g_pHyprOpenGL->clear(m_data.color); -} - bool CClearPassElement::needsLiveBlur() { return false; } diff --git a/src/render/pass/ClearPassElement.hpp b/src/render/pass/ClearPassElement.hpp index 067b7094..112af442 100644 --- a/src/render/pass/ClearPassElement.hpp +++ b/src/render/pass/ClearPassElement.hpp @@ -10,7 +10,6 @@ class CClearPassElement : public IPassElement { CClearPassElement(const SClearData& data); virtual ~CClearPassElement() = default; - virtual void draw(const CRegion& damage); virtual bool needsLiveBlur(); virtual bool needsPrecomputeBlur(); virtual std::optional<CBox> boundingBox(); @@ -20,6 +19,9 @@ class CClearPassElement : public IPassElement { return "CClearPassElement"; } - private: + virtual ePassElementType type() { + return EK_CLEAR; + }; + SClearData m_data; }; diff --git a/src/render/pass/FramebufferElement.cpp b/src/render/pass/FramebufferElement.cpp index bc7c686a..047ce1e8 100644 --- a/src/render/pass/FramebufferElement.cpp +++ b/src/render/pass/FramebufferElement.cpp @@ -1,44 +1,9 @@ #include "FramebufferElement.hpp" -#include "../OpenGL.hpp" CFramebufferElement::CFramebufferElement(const CFramebufferElement::SFramebufferElementData& data_) : m_data(data_) { ; } -void CFramebufferElement::draw(const CRegion& damage) { - SP<IFramebuffer> fb = nullptr; - - if (m_data.main) { - switch (m_data.framebufferID) { - case FB_MONITOR_RENDER_MAIN: fb = g_pHyprOpenGL->m_renderData.mainFB; break; - case FB_MONITOR_RENDER_CURRENT: fb = g_pHyprOpenGL->m_renderData.currentFB; break; - case FB_MONITOR_RENDER_OUT: fb = g_pHyprOpenGL->m_renderData.outFB; break; - } - - if (!fb) { - Log::logger->log(Log::ERR, "BUG THIS: CFramebufferElement::draw: main but null"); - return; - } - - } else { - switch (m_data.framebufferID) { - case FB_MONITOR_RENDER_EXTRA_OFFLOAD: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->offloadFB; break; - case FB_MONITOR_RENDER_EXTRA_MIRROR: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorFB; break; - case FB_MONITOR_RENDER_EXTRA_MIRROR_SWAP: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorSwapFB; break; - case FB_MONITOR_RENDER_EXTRA_OFF_MAIN: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->offMainFB; break; - case FB_MONITOR_RENDER_EXTRA_MONITOR_MIRROR: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->monitorMirrorFB; break; - case FB_MONITOR_RENDER_EXTRA_BLUR: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->blurFB; break; - } - - if (!fb) { - Log::logger->log(Log::ERR, "BUG THIS: CFramebufferElement::draw: not main but null"); - return; - } - } - - fb->bind(); -} - bool CFramebufferElement::needsLiveBlur() { return false; } diff --git a/src/render/pass/FramebufferElement.hpp b/src/render/pass/FramebufferElement.hpp index 515c3380..f2e1cc74 100644 --- a/src/render/pass/FramebufferElement.hpp +++ b/src/render/pass/FramebufferElement.hpp @@ -11,7 +11,6 @@ class CFramebufferElement : public IPassElement { CFramebufferElement(const SFramebufferElementData& data_); virtual ~CFramebufferElement() = default; - virtual void draw(const CRegion& damage); virtual bool needsLiveBlur(); virtual bool needsPrecomputeBlur(); virtual bool undiscardable(); @@ -20,6 +19,9 @@ class CFramebufferElement : public IPassElement { return "CFramebufferElement"; } - private: + virtual ePassElementType type() { + return EK_FRAMEBUFFER; + }; + SFramebufferElementData m_data; };
\ No newline at end of file diff --git a/src/render/pass/Pass.cpp b/src/render/pass/Pass.cpp index a4436516..cfe8933a 100644 --- a/src/render/pass/Pass.cpp +++ b/src/render/pass/Pass.cpp @@ -190,7 +190,7 @@ CRegion CRenderPass::render(const CRegion& damage_) { } g_pHyprOpenGL->m_renderData.damage = el->elementDamage; - el->element->draw(el->elementDamage); + g_pHyprRenderer->draw(el->element, el->elementDamage); } if (*PDEBUGPASS) { diff --git a/src/render/pass/PassElement.hpp b/src/render/pass/PassElement.hpp index a006ce9e..0dc5f581 100644 --- a/src/render/pass/PassElement.hpp +++ b/src/render/pass/PassElement.hpp @@ -1,16 +1,29 @@ #pragma once #include "../../defines.hpp" -#include <optional> + +enum ePassElementType : uint8_t { + EK_UNKNOWN = 0, + EK_BORDER, + EK_CLEAR, + EK_FRAMEBUFFER, + EK_PRE_BLUR, + EK_RECT, + EK_HINTS, + EK_SHADOW, + EK_SURFACE, + EK_TEXTURE, + EK_TEXTURE_MATTE +}; class IPassElement { public: virtual ~IPassElement() = default; - virtual void draw(const CRegion& damage) = 0; - virtual bool needsLiveBlur() = 0; - virtual bool needsPrecomputeBlur() = 0; - virtual const char* passName() = 0; + virtual bool needsLiveBlur() = 0; + virtual bool needsPrecomputeBlur() = 0; + virtual const char* passName() = 0; + virtual ePassElementType type() = 0; virtual void discard(); virtual bool undiscardable(); virtual std::optional<CBox> boundingBox(); // in monitor-local logical coordinates diff --git a/src/render/pass/PreBlurElement.cpp b/src/render/pass/PreBlurElement.cpp index 6f282232..9c054b93 100644 --- a/src/render/pass/PreBlurElement.cpp +++ b/src/render/pass/PreBlurElement.cpp @@ -1,12 +1,7 @@ #include "PreBlurElement.hpp" -#include "../OpenGL.hpp" CPreBlurElement::CPreBlurElement() = default; -void CPreBlurElement::draw(const CRegion& damage) { - g_pHyprOpenGL->preBlurForCurrentMonitor(); -} - bool CPreBlurElement::needsLiveBlur() { return false; } diff --git a/src/render/pass/PreBlurElement.hpp b/src/render/pass/PreBlurElement.hpp index 80474a29..fa8a875c 100644 --- a/src/render/pass/PreBlurElement.hpp +++ b/src/render/pass/PreBlurElement.hpp @@ -6,7 +6,6 @@ class CPreBlurElement : public IPassElement { CPreBlurElement(); virtual ~CPreBlurElement() = default; - virtual void draw(const CRegion& damage); virtual bool needsLiveBlur(); virtual bool needsPrecomputeBlur(); virtual bool disableSimplification(); @@ -15,4 +14,8 @@ class CPreBlurElement : public IPassElement { virtual const char* passName() { return "CPreBlurElement"; } + + virtual ePassElementType type() { + return EK_PRE_BLUR; + }; };
\ No newline at end of file diff --git a/src/render/pass/RectPassElement.cpp b/src/render/pass/RectPassElement.cpp index 6c60741e..f6f88faa 100644 --- a/src/render/pass/RectPassElement.cpp +++ b/src/render/pass/RectPassElement.cpp @@ -1,26 +1,10 @@ #include "RectPassElement.hpp" -#include "../OpenGL.hpp" +#include "../Renderer.hpp" CRectPassElement::CRectPassElement(const CRectPassElement::SRectData& data_) : m_data(data_) { ; } -void CRectPassElement::draw(const CRegion& damage) { - if (m_data.box.w <= 0 || m_data.box.h <= 0) - return; - - if (!m_data.clipBox.empty()) - g_pHyprOpenGL->m_renderData.clipBox = m_data.clipBox; - - if (m_data.color.a == 1.F || !m_data.blur) - g_pHyprOpenGL->renderRect(m_data.box, m_data.color, {.damage = &damage, .round = m_data.round, .roundingPower = m_data.roundingPower}); - else - g_pHyprOpenGL->renderRect(m_data.box, m_data.color, - {.round = m_data.round, .roundingPower = m_data.roundingPower, .blur = true, .blurA = m_data.blurA, .xray = m_data.xray}); - - g_pHyprOpenGL->m_renderData.clipBox = {}; -} - bool CRectPassElement::needsLiveBlur() { return m_data.color.a < 1.F && !m_data.xray && m_data.blur; } diff --git a/src/render/pass/RectPassElement.hpp b/src/render/pass/RectPassElement.hpp index c83d52ec..b6d310ad 100644 --- a/src/render/pass/RectPassElement.hpp +++ b/src/render/pass/RectPassElement.hpp @@ -1,5 +1,6 @@ #pragma once #include "PassElement.hpp" +#include <hyprutils/math/Region.hpp> class CRectPassElement : public IPassElement { public: @@ -16,7 +17,6 @@ class CRectPassElement : public IPassElement { CRectPassElement(const SRectData& data); virtual ~CRectPassElement() = default; - virtual void draw(const CRegion& damage); virtual bool needsLiveBlur(); virtual bool needsPrecomputeBlur(); virtual std::optional<CBox> boundingBox(); @@ -26,6 +26,9 @@ class CRectPassElement : public IPassElement { return "CRectPassElement"; } - private: + virtual ePassElementType type() { + return EK_RECT; + }; + SRectData m_data; }; diff --git a/src/render/pass/RendererHintsPassElement.cpp b/src/render/pass/RendererHintsPassElement.cpp index 2ad68204..6e81d9c5 100644 --- a/src/render/pass/RendererHintsPassElement.cpp +++ b/src/render/pass/RendererHintsPassElement.cpp @@ -1,15 +1,9 @@ #include "RendererHintsPassElement.hpp" -#include "../OpenGL.hpp" CRendererHintsPassElement::CRendererHintsPassElement(const CRendererHintsPassElement::SData& data_) : m_data(data_) { ; } -void CRendererHintsPassElement::draw(const CRegion& damage) { - if (m_data.renderModif.has_value()) - g_pHyprOpenGL->m_renderData.renderModif = *m_data.renderModif; -} - bool CRendererHintsPassElement::needsLiveBlur() { return false; } diff --git a/src/render/pass/RendererHintsPassElement.hpp b/src/render/pass/RendererHintsPassElement.hpp index d56a0cd6..a5a429b5 100644 --- a/src/render/pass/RendererHintsPassElement.hpp +++ b/src/render/pass/RendererHintsPassElement.hpp @@ -12,7 +12,6 @@ class CRendererHintsPassElement : public IPassElement { CRendererHintsPassElement(const SData& data); virtual ~CRendererHintsPassElement() = default; - virtual void draw(const CRegion& damage); virtual bool needsLiveBlur(); virtual bool needsPrecomputeBlur(); virtual bool undiscardable(); @@ -21,6 +20,9 @@ class CRendererHintsPassElement : public IPassElement { return "CRendererHintsPassElement"; } - private: + virtual ePassElementType type() { + return EK_HINTS; + }; + SData m_data; };
\ No newline at end of file diff --git a/src/render/pass/ShadowPassElement.cpp b/src/render/pass/ShadowPassElement.cpp index 45ad18c8..da5601a3 100644 --- a/src/render/pass/ShadowPassElement.cpp +++ b/src/render/pass/ShadowPassElement.cpp @@ -1,15 +1,9 @@ #include "ShadowPassElement.hpp" -#include "../OpenGL.hpp" -#include "../decorations/CHyprDropShadowDecoration.hpp" CShadowPassElement::CShadowPassElement(const CShadowPassElement::SShadowData& data_) : m_data(data_) { ; } -void CShadowPassElement::draw(const CRegion& damage) { - m_data.deco->render(g_pHyprOpenGL->m_renderData.pMonitor.lock(), m_data.a); -} - bool CShadowPassElement::needsLiveBlur() { return false; } diff --git a/src/render/pass/ShadowPassElement.hpp b/src/render/pass/ShadowPassElement.hpp index 028ac88c..ee176102 100644 --- a/src/render/pass/ShadowPassElement.hpp +++ b/src/render/pass/ShadowPassElement.hpp @@ -13,7 +13,6 @@ class CShadowPassElement : public IPassElement { CShadowPassElement(const SShadowData& data_); virtual ~CShadowPassElement() = default; - virtual void draw(const CRegion& damage); virtual bool needsLiveBlur(); virtual bool needsPrecomputeBlur(); @@ -21,6 +20,9 @@ class CShadowPassElement : public IPassElement { return "CShadowPassElement"; } - private: + virtual ePassElementType type() { + return EK_SHADOW; + }; + SShadowData m_data; }; diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index c5feb8f7..89cd9d73 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -17,150 +17,6 @@ CSurfacePassElement::CSurfacePassElement(const CSurfacePassElement::SRenderData& ; } -void CSurfacePassElement::draw(const CRegion& damage) { - g_pHyprOpenGL->m_renderData.currentWindow = m_data.pWindow; - g_pHyprOpenGL->m_renderData.surface = m_data.surface; - g_pHyprOpenGL->m_renderData.currentLS = m_data.pLS; - g_pHyprOpenGL->m_renderData.clipBox = m_data.clipBox; - g_pHyprOpenGL->m_renderData.discardMode = m_data.discardMode; - g_pHyprOpenGL->m_renderData.discardOpacity = m_data.discardOpacity; - g_pHyprOpenGL->m_renderData.useNearestNeighbor = m_data.useNearestNeighbor; - g_pHyprOpenGL->pushMonitorTransformEnabled(m_data.flipEndFrame); - - CScopeGuard x = {[]() { - g_pHyprOpenGL->m_renderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); - g_pHyprOpenGL->m_renderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); - g_pHyprOpenGL->m_renderData.useNearestNeighbor = false; - g_pHyprOpenGL->m_renderData.clipBox = {}; - g_pHyprOpenGL->m_renderData.clipRegion = {}; - g_pHyprOpenGL->m_renderData.discardMode = 0; - g_pHyprOpenGL->m_renderData.discardOpacity = 0; - g_pHyprOpenGL->m_renderData.useNearestNeighbor = false; - g_pHyprOpenGL->popMonitorTransformEnabled(); - g_pHyprOpenGL->m_renderData.currentWindow.reset(); - g_pHyprOpenGL->m_renderData.surface.reset(); - g_pHyprOpenGL->m_renderData.currentLS.reset(); - }}; - - if (!m_data.texture) - return; - - const auto& TEXTURE = m_data.texture; - - // this is bad, probably has been logged elsewhere. Means the texture failed - // uploading to the GPU. - if (!TEXTURE->m_texID) - return; - - const auto INTERACTIVERESIZEINPROGRESS = m_data.pWindow && g_layoutManager->dragController()->target() && g_layoutManager->dragController()->mode() == MBIND_RESIZE; - TRACY_GPU_ZONE("RenderSurface"); - - auto PSURFACE = Desktop::View::CWLSurface::fromResource(m_data.surface); - - const float ALPHA = m_data.alpha * m_data.fadeAlpha * (PSURFACE ? PSURFACE->m_alphaModifier : 1.F); - const float OVERALL_ALPHA = PSURFACE ? PSURFACE->m_overallOpacity : 1.F; - const bool BLUR = m_data.blur && (!TEXTURE->m_opaque || ALPHA < 1.F || OVERALL_ALPHA < 1.F); - - auto windowBox = getTexBox(); - - const auto PROJSIZEUNSCALED = windowBox.size(); - - windowBox.scale(m_data.pMonitor->m_scale); - windowBox.round(); - - if (windowBox.width <= 1 || windowBox.height <= 1) { - discard(); - return; - } - - const bool MISALIGNEDFSV1 = std::floor(m_data.pMonitor->m_scale) != m_data.pMonitor->m_scale /* Fractional */ && m_data.surface->m_current.scale == 1 /* fs protocol */ && - windowBox.size() != m_data.surface->m_current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, m_data.surface->m_current.bufferSize.x, 3) && - DELTALESSTHAN(windowBox.height, m_data.surface->m_current.bufferSize.y, 3) /* off by one-or-two */ && - (!m_data.pWindow || (!m_data.pWindow->m_realSize->isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */ && - (!m_data.pLS || (!m_data.pLS->m_realSize->isBeingAnimated())); /* not LS or not animated */ - - g_pHyprRenderer->calculateUVForSurface(m_data.pWindow, m_data.surface, m_data.pMonitor->m_self.lock(), m_data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1); - - auto cancelRender = false; - g_pHyprOpenGL->m_renderData.clipRegion = visibleRegion(cancelRender); - if (cancelRender) - return; - - // check for fractional scale surfaces misaligning the buffer size - // in those cases it's better to just force nearest neighbor - // as long as the window is not animated. During those it'd look weird. - // UV will fixup it as well - if (MISALIGNEDFSV1) - g_pHyprOpenGL->m_renderData.useNearestNeighbor = true; - - float rounding = m_data.rounding; - float roundingPower = m_data.roundingPower; - - rounding -= 1; // to fix a border issue - - if (m_data.dontRound) { - rounding = 0; - roundingPower = 2.0f; - } - - const bool WINDOWOPAQUE = m_data.pWindow && m_data.pWindow->wlSurface()->resource() == m_data.surface ? m_data.pWindow->opaque() : false; - const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding <= 0 && WINDOWOPAQUE; - - if (CANDISABLEBLEND) - g_pHyprOpenGL->blend(false); - else - g_pHyprOpenGL->blend(true); - - // FIXME: This is wrong and will bug the blur out as shit if the first surface - // is a subsurface that does NOT cover the entire frame. In such cases, we probably should fall back - // to what we do for misaligned surfaces (blur the entire thing and then render shit without blur) - if (m_data.surfaceCounter == 0 && !m_data.popup) { - if (BLUR) - g_pHyprOpenGL->renderTexture(TEXTURE, windowBox, - { - .surface = m_data.surface, - .a = ALPHA, - .blur = true, - .blurA = m_data.fadeAlpha, - .overallA = OVERALL_ALPHA, - .round = rounding, - .roundingPower = roundingPower, - .allowCustomUV = true, - .blockBlurOptimization = m_data.blockBlurOptimization, - }); - else - g_pHyprOpenGL->renderTexture(TEXTURE, windowBox, - {.a = ALPHA * OVERALL_ALPHA, .round = rounding, .roundingPower = roundingPower, .discardActive = false, .allowCustomUV = true}); - } else { - if (BLUR && m_data.popup) - g_pHyprOpenGL->renderTexture(TEXTURE, windowBox, - { - .surface = m_data.surface, - .a = ALPHA, - .blur = true, - .blurA = m_data.fadeAlpha, - .overallA = OVERALL_ALPHA, - .round = rounding, - .roundingPower = roundingPower, - .allowCustomUV = true, - .blockBlurOptimization = true, - }); - else - g_pHyprOpenGL->renderTexture(TEXTURE, windowBox, - {.a = ALPHA * OVERALL_ALPHA, .round = rounding, .roundingPower = roundingPower, .discardActive = false, .allowCustomUV = true}); - } - - if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) - m_data.surface->presentFeedback(m_data.when, m_data.pMonitor->m_self.lock()); - - // add async (dmabuf) buffers to usedBuffers so we can handle release later - // sync (shm) buffers will be released in commitState, so no need to track them here - if (m_data.surface->m_current.buffer && !m_data.surface->m_current.buffer->isSynchronous()) - g_pHyprRenderer->m_usedAsyncBuffers.emplace_back(m_data.surface->m_current.buffer); - - g_pHyprOpenGL->blend(true); -} - CBox CSurfacePassElement::getTexBox() { const double outputX = -m_data.pMonitor->m_position.x, outputY = -m_data.pMonitor->m_position.y; diff --git a/src/render/pass/SurfacePassElement.hpp b/src/render/pass/SurfacePassElement.hpp index 058744de..bd02417d 100644 --- a/src/render/pass/SurfacePassElement.hpp +++ b/src/render/pass/SurfacePassElement.hpp @@ -52,7 +52,6 @@ class CSurfacePassElement : public IPassElement { CSurfacePassElement(const SRenderData& data); virtual ~CSurfacePassElement() = default; - virtual void draw(const CRegion& damage); virtual bool needsLiveBlur(); virtual bool needsPrecomputeBlur(); virtual std::optional<CBox> boundingBox(); @@ -64,7 +63,10 @@ class CSurfacePassElement : public IPassElement { return "CSurfacePassElement"; } - private: + virtual ePassElementType type() { + return EK_SURFACE; + }; + SRenderData m_data; CBox getTexBox(); diff --git a/src/render/pass/TexPassElement.cpp b/src/render/pass/TexPassElement.cpp index 39853a64..ad132226 100644 --- a/src/render/pass/TexPassElement.cpp +++ b/src/render/pass/TexPassElement.cpp @@ -1,8 +1,5 @@ #include "TexPassElement.hpp" -#include "../OpenGL.hpp" - -#include <hyprutils/utils/ScopeGuard.hpp> -using namespace Hyprutils::Utils; +#include "../Renderer.hpp" CTexPassElement::CTexPassElement(const SRenderData& data) : m_data(data) { ; @@ -12,47 +9,6 @@ CTexPassElement::CTexPassElement(CTexPassElement::SRenderData&& data) : m_data(s ; } -void CTexPassElement::draw(const CRegion& damage) { - g_pHyprOpenGL->pushMonitorTransformEnabled(m_data.flipEndFrame); - - CScopeGuard x = {[this]() { - // - g_pHyprOpenGL->popMonitorTransformEnabled(); - g_pHyprOpenGL->m_renderData.clipBox = {}; - if (m_data.replaceProjection) - g_pHyprOpenGL->m_renderData.monitorProjection = g_pHyprOpenGL->m_renderData.pMonitor->m_projMatrix; - if (m_data.ignoreAlpha.has_value()) - g_pHyprOpenGL->m_renderData.discardMode = 0; - }}; - - if (!m_data.clipBox.empty()) - g_pHyprOpenGL->m_renderData.clipBox = m_data.clipBox; - - if (m_data.replaceProjection) - g_pHyprOpenGL->m_renderData.monitorProjection = *m_data.replaceProjection; - - if (m_data.ignoreAlpha.has_value()) { - g_pHyprOpenGL->m_renderData.discardMode = DISCARD_ALPHA; - g_pHyprOpenGL->m_renderData.discardOpacity = *m_data.ignoreAlpha; - } - - if (m_data.blur) { - g_pHyprOpenGL->renderTexture(m_data.tex, m_data.box, - { - .a = m_data.a, - .blur = true, - .blurA = m_data.blurA, - .overallA = 1.F, - .round = m_data.round, - .roundingPower = m_data.roundingPower, - .blockBlurOptimization = m_data.blockBlurOptimization.value_or(false), - }); - } else { - g_pHyprOpenGL->renderTexture(m_data.tex, m_data.box, - {.damage = m_data.damage.empty() ? &damage : &m_data.damage, .a = m_data.a, .round = m_data.round, .roundingPower = m_data.roundingPower}); - } -} - bool CTexPassElement::needsLiveBlur() { return false; // TODO? } diff --git a/src/render/pass/TexPassElement.hpp b/src/render/pass/TexPassElement.hpp index 770e8b05..90f5f40e 100644 --- a/src/render/pass/TexPassElement.hpp +++ b/src/render/pass/TexPassElement.hpp @@ -28,7 +28,6 @@ class CTexPassElement : public IPassElement { CTexPassElement(SRenderData&& data); virtual ~CTexPassElement() = default; - virtual void draw(const CRegion& damage); virtual bool needsLiveBlur(); virtual bool needsPrecomputeBlur(); virtual std::optional<CBox> boundingBox(); @@ -39,6 +38,9 @@ class CTexPassElement : public IPassElement { return "CTexPassElement"; } - private: + virtual ePassElementType type() { + return EK_TEXTURE; + }; + SRenderData m_data; }; diff --git a/src/render/pass/TextureMatteElement.cpp b/src/render/pass/TextureMatteElement.cpp index 8023df8b..a99a9ef9 100644 --- a/src/render/pass/TextureMatteElement.cpp +++ b/src/render/pass/TextureMatteElement.cpp @@ -5,17 +5,6 @@ CTextureMatteElement::CTextureMatteElement(const CTextureMatteElement::STextureM ; } -void CTextureMatteElement::draw(const CRegion& damage) { - if (m_data.disableTransformAndModify) { - g_pHyprOpenGL->pushMonitorTransformEnabled(true); - g_pHyprOpenGL->setRenderModifEnabled(false); - g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, m_data.fb); - g_pHyprOpenGL->setRenderModifEnabled(true); - g_pHyprOpenGL->popMonitorTransformEnabled(); - } else - g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, m_data.fb); -} - bool CTextureMatteElement::needsLiveBlur() { return false; } diff --git a/src/render/pass/TextureMatteElement.hpp b/src/render/pass/TextureMatteElement.hpp index 273c6474..bf3bb4bf 100644 --- a/src/render/pass/TextureMatteElement.hpp +++ b/src/render/pass/TextureMatteElement.hpp @@ -16,7 +16,6 @@ class CTextureMatteElement : public IPassElement { CTextureMatteElement(const STextureMatteData& data_); virtual ~CTextureMatteElement() = default; - virtual void draw(const CRegion& damage); virtual bool needsLiveBlur(); virtual bool needsPrecomputeBlur(); @@ -24,6 +23,9 @@ class CTextureMatteElement : public IPassElement { return "CTextureMatteElement"; } - private: + virtual ePassElementType type() { + return EK_TEXTURE_MATTE; + }; + STextureMatteData m_data; };
\ No newline at end of file |
