diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 2c77694f..7c626002 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -97,6 +97,7 @@ void CConfigManager::setDefaultVars() { configValues["debug:disable_time"].intValue = 1; configValues["debug:enable_stdout_logs"].intValue = 0; configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL; + configValues["debug:manual_crash"].intValue = 0; configValues["decoration:rounding"].intValue = 0; configValues["decoration:blur"].intValue = 1; @@ -1397,6 +1398,15 @@ void CConfigManager::loadConfigLoadVars() { // update layout g_pLayoutManager->switchToLayout(configValues["general:layout"].strValue); + // manual crash + if (configValues["debug:manual_crash"].intValue && !m_bManualCrashInitiated) { + m_bManualCrashInitiated = true; + g_pHyprNotificationOverlay->addNotification("Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor.", CColor(0), 5000, ICON_INFO); + } else if (m_bManualCrashInitiated && !configValues["debug:manual_crash"].intValue) { + // cowabunga it is + g_pHyprRenderer->initiateManualCrash(); + } + Debug::disableStdout = !configValues["debug:enable_stdout_logs"].intValue; for (auto& m : g_pCompositor->m_vMonitors) { diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index eb8998e1..cee6075e 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -213,7 +213,8 @@ class CConfigManager { std::deque m_dLayerRules; std::deque m_dBlurLSNamespaces; - bool firstExecDispatched = false; + bool firstExecDispatched = false; + bool m_bManualCrashInitiated = false; std::deque firstExecRequests; std::vector> environmentVariables; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 8b5fb2ef..57fae086 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -205,6 +205,16 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shPASSTHRURGBA.texAttrib = glGetAttribLocation(prog, "texcoord"); m_RenderData.pCurrentMonData->m_shPASSTHRURGBA.posAttrib = glGetAttribLocation(prog, "pos"); + prog = createProgram(TEXVERTSRC, FRAGGLITCH); + m_RenderData.pCurrentMonData->m_shGLITCH.program = prog; + m_RenderData.pCurrentMonData->m_shGLITCH.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shGLITCH.tex = glGetUniformLocation(prog, "tex"); + m_RenderData.pCurrentMonData->m_shGLITCH.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shGLITCH.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shGLITCH.distort = glGetUniformLocation(prog, "distort"); + m_RenderData.pCurrentMonData->m_shGLITCH.time = glGetUniformLocation(prog, "time"); + m_RenderData.pCurrentMonData->m_shGLITCH.fullSize = glGetUniformLocation(prog, "screenSize"); + prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBX); m_RenderData.pCurrentMonData->m_shRGBX.program = prog; m_RenderData.pCurrentMonData->m_shRGBX.tex = glGetUniformLocation(prog, "tex"); @@ -318,7 +328,7 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) { m_sFinalScreenShader.proj = glGetUniformLocation(m_sFinalScreenShader.program, "proj"); m_sFinalScreenShader.tex = glGetUniformLocation(m_sFinalScreenShader.program, "tex"); m_sFinalScreenShader.time = glGetUniformLocation(m_sFinalScreenShader.program, "time"); - if (m_sFinalScreenShader.time != -1 && g_pConfigManager->getInt("debug:damage_tracking") != 0) { + if (m_sFinalScreenShader.time != -1 && g_pConfigManager->getInt("debug:damage_tracking") != 0 && !g_pHyprRenderer->m_bCrashingInProgress) { // The screen shader uses the "time" uniform // Since the screen shader could change every frame, damage tracking *needs* to be disabled g_pConfigManager->addParseError("Screen shader: Screen shader uses uniform 'time', which requires debug:damage_tracking to be switched off.\n" @@ -502,9 +512,14 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - bool usingFinalShader = false; + bool usingFinalShader = false; - if (m_bApplyFinalShader && m_sFinalScreenShader.program) { + const bool CRASHING = m_bApplyFinalShader && g_pHyprRenderer->m_bCrashingInProgress; + + if (CRASHING) { + shader = &m_RenderData.pCurrentMonData->m_shGLITCH; + usingFinalShader = true; + } else if (m_bApplyFinalShader && m_sFinalScreenShader.program) { shader = &m_sFinalScreenShader; usingFinalShader = true; } else { @@ -539,13 +554,18 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b #endif glUniform1i(shader->tex, 0); - if (usingFinalShader && g_pConfigManager->getInt("debug:damage_tracking") == 0) { + if ((usingFinalShader && g_pConfigManager->getInt("debug:damage_tracking") == 0) || CRASHING) { glUniform1f(shader->time, m_tGlobalTimer.getSeconds()); } else if (usingFinalShader && shader->time > 0) { // Don't let time be unitialised glUniform1f(shader->time, 0.f); } + if (CRASHING) { + glUniform1f(shader->distort, g_pHyprRenderer->m_fCrashingDistort); + glUniform2f(shader->fullSize, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y); + } + if (!usingFinalShader) { glUniform1f(shader->alpha, alpha); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 028be4df..3c563946 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -23,8 +23,7 @@ inline const float fullVerts[] = { }; inline const float fanVertsFull[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f}; -enum eDiscardMode -{ +enum eDiscardMode { DISCARD_OPAQUE = 1, DISCARD_ALPHAZERO = 1 << 1 }; @@ -55,6 +54,7 @@ struct SMonitorRenderData { CShader m_shBLUR2; CShader m_shSHADOW; CShader m_shBORDER1; + CShader m_shGLITCH; // }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f1fdd636..94a71f74 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1791,3 +1791,30 @@ std::tuple CHyprRenderer::getRenderTimes(CMonitor* pMonitor return std::make_tuple<>(avgRenderTime, maxRenderTime, minRenderTime); } + +static int handleCrashLoop(void* data) { + + g_pHyprNotificationOverlay->addNotification("Hyprland will crash in " + std::to_string(10 - (int)(g_pHyprRenderer->m_fCrashingDistort * 2.f)) + "s.", CColor(0), 5000, + ICON_INFO); + + g_pHyprRenderer->m_fCrashingDistort += 0.5f; + + if (g_pHyprRenderer->m_fCrashingDistort >= 5.5f) + *((int*)nullptr) = 1337; + + wl_event_source_timer_update(g_pHyprRenderer->m_pCrashingLoop, 1000); + + return 1; +} + +void CHyprRenderer::initiateManualCrash() { + g_pHyprNotificationOverlay->addNotification("Manual crash initiated. Farewell...", CColor(0), 5000, ICON_INFO); + + m_pCrashingLoop = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleCrashLoop, nullptr); + wl_event_source_timer_update(m_pCrashingLoop, 1000); + + m_bCrashingInProgress = true; + m_fCrashingDistort = 0.5; + + g_pConfigManager->setInt("debug:damage_tracking", 0); +} \ No newline at end of file diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 82da4b69..7b0f47fd 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -10,16 +10,14 @@ struct SMonitorRule; // TODO: add fuller damage tracking for updating only parts of a window -enum DAMAGETRACKINGMODES -{ +enum DAMAGETRACKINGMODES { DAMAGE_TRACKING_INVALID = -1, DAMAGE_TRACKING_NONE = 0, DAMAGE_TRACKING_MONITOR, DAMAGE_TRACKING_FULL }; -enum eRenderPassMode -{ +enum eRenderPassMode { RENDER_PASS_ALL = 0, RENDER_PASS_MAIN, RENDER_PASS_POPUP @@ -62,6 +60,11 @@ class CHyprRenderer { bool attemptDirectScanout(CMonitor*); void setWindowScanoutMode(CWindow*); + void initiateManualCrash(); + + bool m_bCrashingInProgress = false; + float m_fCrashingDistort = 0.5f; + wl_event_source* m_pCrashingLoop = nullptr; private: void arrangeLayerArray(CMonitor*, const std::vector>&, bool, wlr_box*); diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index 33bcdca3..04bf9259 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -39,6 +39,7 @@ class CShader { GLint angle; GLint time; + GLint distort; GLint getUniformLocation(const std::string&); diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index 52e77fae..097c30a8 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -258,3 +258,36 @@ void main() { gl_FragColor = pixColor * alpha; } )#"; + +static const std::string FRAGGLITCH = R"#( +precision mediump float; +varying vec2 v_texcoord; +uniform sampler2D tex; +uniform float time; +uniform float distort; +uniform vec2 screenSize; + +float rand(float co){ + return fract(sin(dot(vec2(co, co), vec2(12.9898, 78.233))) * 43758.5453); +} + +void main() { + float ABERR_OFFSET = 4.0 * (distort / 5.5); + float TEAR_AMOUNT = 9000.0 * (1.0 - (distort / 5.5)); + float TEAR_BANDS = 108.0 / 2.0 * (distort / 5.5) * 2.0; + + float offset = (mod(rand(floor(v_texcoord.y * TEAR_BANDS)) * 318.772 * time, 20.0) - 10.0) / TEAR_AMOUNT; + + vec2 pixCoord = vec2(v_texcoord.x + offset, v_texcoord.y); + vec4 pixColor = texture2D(tex, pixCoord); + vec4 pixColorLeft = texture2D(tex, pixCoord + vec2(ABERR_OFFSET / screenSize.x, 0)); + vec4 pixColorRight = texture2D(tex, pixCoord + vec2(-ABERR_OFFSET / screenSize.x, 0)); + + pixColor[0] = pixColorLeft[0]; + pixColor[2] = pixColorRight[2]; + + pixColor[0] += distort / 90.0; + + gl_FragColor = pixColor; +} +)#"; \ No newline at end of file