From 81723f4ccac7ed0a1b77cc028e27af3eb8d4603b Mon Sep 17 00:00:00 2001 From: Matias Date: Sat, 12 Jul 2025 22:45:19 +0200 Subject: [PATCH] feat: switch to hooking renderWindow and inserting a pass beforehand --- src/main.cpp | 206 ++++++++++++++++++++------------------------------- 1 file changed, 79 insertions(+), 127 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5916494..3655bde 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,13 +3,17 @@ #include // version.hpp will be generated by meson +#include "src/plugins/PluginAPI.hpp" +#include "src/render/Framebuffer.hpp" #include "src/render/Shader.hpp" +#include "src/render/pass/PassElement.hpp" +#include "src/render/pass/RectPassElement.hpp" #include "version.hpp" #include #include #include -#include +#include #include // Do NOT change this function. @@ -17,140 +21,82 @@ APICALL EXPORT std::string PLUGIN_API_VERSION() { return HYPRLAND_API_VERSION; } -class CWindowTransformer: public IWindowTransformer { +class CBindOwnFramebuffer final: public IPassElement { public: - virtual CFramebuffer* transform(CFramebuffer* in); - virtual void preWindowRender(CSurfacePassElement::SRenderData* pRenderData); + explicit CBindOwnFramebuffer(CFramebuffer m_framebuffer) : + m_framebuffer(std::move(m_framebuffer)) {} + + void draw(const CRegion& damage); + + bool needsLiveBlur() { + return true; + } + + bool needsPrecomputeBlur() { + return false; + } + + const char* passName() { + return "BIND_OWN_FRAMEBUFFER"; + } private: - float m_rot = 0; - Vector2D m_prevPos; + CFramebuffer m_framebuffer; }; -std::vector ptrs; - -void renderTex(CBox monbox, CTexture& tex, float rot) { - if (g_pHyprOpenGL->m_renderData.damage.empty()) - return; - - CBox newBox = monbox.scale(g_pHyprOpenGL->m_renderData.renderModif.combinedScale()); - g_pHyprOpenGL->m_renderData.renderModif.applyToBox(newBox); - - Mat3x3 matrix = g_pHyprOpenGL->m_renderData.monitorProjection.projectBox( - monbox, - wlTransformToHyprutils(invertTransform(WL_OUTPUT_TRANSFORM_NORMAL)), - rot - ); - Mat3x3 glMatrix = g_pHyprOpenGL->m_renderData.projection.copy().multiply(matrix); - - SShader* shader = &g_pHyprOpenGL->m_shaders->m_shPASSTHRURGBA; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(tex.m_target, tex.m_texID); - - glUseProgram(shader->program); - - glUniformMatrix3fv( - shader->uniformLocations[SHADER_PROJ], - 1, - GL_TRUE, - glMatrix.getMatrix().data() - ); - glUniform1i(shader->uniformLocations[SHADER_TEX], 0); - - const auto TOPLEFT = Vector2D(newBox.x, newBox.y); - const auto FULLSIZE = Vector2D(newBox.width, newBox.height); - - glUniform2f(shader->uniformLocations[SHADER_TOP_LEFT], TOPLEFT.x, TOPLEFT.y); - glUniform2f(shader->uniformLocations[SHADER_FULL_SIZE], FULLSIZE.x, FULLSIZE.y); - glUniform1f(shader->uniformLocations[SHADER_RADIUS], 0); - - glUniform1i(shader->uniformLocations[SHADER_DISCARD_OPAQUE], 0); - glUniform1i(shader->uniformLocations[SHADER_DISCARD_ALPHA], 0); - - glUniform1f(shader->uniformLocations[SHADER_ALPHA], 1); - - glVertexAttribPointer( - shader->uniformLocations[SHADER_POS_ATTRIB], - 2, - GL_FLOAT, - GL_FALSE, - 0, - fullVerts - ); - glVertexAttribPointer( - shader->uniformLocations[SHADER_TEX_ATTRIB], - 2, - GL_FLOAT, - GL_FALSE, - 0, - fullVerts - ); - - glEnableVertexAttribArray(shader->uniformLocations[SHADER_POS_ATTRIB]); - glEnableVertexAttribArray(shader->uniformLocations[SHADER_TEX_ATTRIB]); - - for (auto& RECT : g_pHyprOpenGL->m_renderData.damage.getRects()) { - g_pHyprOpenGL->scissor(&RECT); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - } - - g_pHyprOpenGL->scissor(nullptr); - - glDisableVertexAttribArray(shader->uniformLocations[SHADER_POS_ATTRIB]); - glDisableVertexAttribArray(shader->uniformLocations[SHADER_TEX_ATTRIB]); - - glBindTexture(tex.m_target, 0); -} - -void CWindowTransformer::preWindowRender(CSurfacePassElement::SRenderData* pRenderData) { - auto&& newPos = pRenderData->pos; - - auto delta = newPos - m_prevPos; - - m_rot = delta.x * 0.01f; - std::println("delta.x: {}", delta.x); - - // pRenderData->pos.x += 50; - pRenderData->rounding = 5; - pRenderData->alpha = 0.9; - - m_prevPos = newPos; -} - -CFramebuffer* CWindowTransformer::transform(CFramebuffer* in) { - static CFramebuffer off; - - if (!off.isAllocated() || off.m_size != in->m_size) { - off.release(); - off.alloc(in->m_size.x, in->m_size.y); - } - - off.bind(); - g_pHyprOpenGL->clear(CHyprColor {0, 0, 0, 0}); - - CBox monbox = {// m_prevPos.x, - // m_prevPos.y, - 0, - 0, - g_pHyprOpenGL->m_renderData.pMonitor->m_transformedSize.x, - g_pHyprOpenGL->m_renderData.pMonitor->m_transformedSize.y - }; - - renderTex(monbox, *in->getTexture(), m_rot); - - return &off; -} - void onNewWindow(std::any data) { // data is guaranteed auto PWINDOW = std::any_cast(data); - ptrs.push_back(static_cast( - PWINDOW->m_transformers.emplace_back(new CWindowTransformer {}).get() - )); } -static SP g_p = nullptr; +static SP g_openWindow = nullptr; +inline CFunctionHook* g_pRenderWindowHook = nullptr; + +typedef void (*origRenderWindow)( + void*, + PHLWINDOW, + PHLMONITOR, + const Time::steady_tp&, + bool, + eRenderPassMode, + bool, + bool +); + +void hkRenderWindow( + void* thisptr, + PHLWINDOW pWindow, + PHLMONITOR pMonitor, + const Time::steady_tp& time, + bool decorate, + eRenderPassMode mode, + bool ignorePosition = false, + bool standalone = false +) { + std::println("renderWindow hooked!"); + CHyprRenderer* pRenderer = (CHyprRenderer*)thisptr; + + CBox monbox = + {pWindow->m_position.x, pWindow->m_position.y, pWindow->m_size.x, pWindow->m_size.y}; + + // test that it works + CRectPassElement::SRectData data; + data.color = CHyprColor(1, 0, 0, 0.2f); + data.box = monbox; + pRenderer->m_renderPass.add(makeUnique(data)); + + // then call the original... + (*(origRenderWindow)g_pRenderWindowHook->m_original)( + thisptr, + pWindow, + pMonitor, + time, + decorate, + mode, + ignorePosition, + standalone + ); +} APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { PHANDLE = handle; @@ -169,12 +115,17 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { throw std::runtime_error("[WiggleWobble] Version mismatch"); } - g_p = HyprlandAPI::registerCallbackDynamic( + g_openWindow = HyprlandAPI::registerCallbackDynamic( PHANDLE, "openWindow", [](void* self, SCallbackInfo& info, std::any data) { onNewWindow(data); } ); + static const auto METHODS = HyprlandAPI::findFunctionsByName(PHANDLE, "renderWindow"); + g_pRenderWindowHook = + HyprlandAPI::createFunctionHook(handle, METHODS[0].address, (void*)&hkRenderWindow); + g_pRenderWindowHook->hook(); + HyprlandAPI::reloadConfig(); HyprlandAPI::addNotification( @@ -188,5 +139,6 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { } APICALL EXPORT void PLUGIN_EXIT() { - g_p = nullptr; + g_pRenderWindowHook = nullptr; + g_openWindow = nullptr; }