diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index da146027..38672353 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -351,11 +351,27 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib); glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.texAttrib); - if (pixman_region32_not_empty(damage)) { - PIXMAN_DAMAGE_FOREACH(damage) { - const auto RECT = RECTSARR[i]; - scissor(&RECT); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { + pixman_region32_t damageClip; + pixman_region32_init(&damageClip); + pixman_region32_intersect_rect(&damageClip, damage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height); + + if (pixman_region32_not_empty(&damageClip)) { + PIXMAN_DAMAGE_FOREACH(&damageClip) { + const auto RECT = RECTSARR[i]; + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + + pixman_region32_fini(&damageClip); + } else { + if (pixman_region32_not_empty(damage)) { + PIXMAN_DAMAGE_FOREACH(damage) { + const auto RECT = RECTSARR[i]; + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } } } @@ -467,11 +483,27 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b glEnableVertexAttribArray(shader->posAttrib); glEnableVertexAttribArray(shader->texAttrib); - if (pixman_region32_not_empty(m_RenderData.pDamage)) { - PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) { - const auto RECT = RECTSARR[i]; - scissor(&RECT); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { + pixman_region32_t damageClip; + pixman_region32_init(&damageClip); + pixman_region32_intersect_rect(&damageClip, damage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height); + + if (pixman_region32_not_empty(&damageClip)) { + PIXMAN_DAMAGE_FOREACH(&damageClip) { + const auto RECT = RECTSARR[i]; + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + + pixman_region32_fini(&damageClip); + } else { + if (pixman_region32_not_empty(damage)) { + PIXMAN_DAMAGE_FOREACH(damage) { + const auto RECT = RECTSARR[i]; + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } } } @@ -832,11 +864,27 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) { glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib); glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib); - if (pixman_region32_not_empty(m_RenderData.pDamage)) { - PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) { - const auto RECT = RECTSARR[i]; - scissor(&RECT); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { + pixman_region32_t damageClip; + pixman_region32_init(&damageClip); + pixman_region32_intersect_rect(&damageClip, m_RenderData.pDamage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height); + + if (pixman_region32_not_empty(&damageClip)) { + PIXMAN_DAMAGE_FOREACH(&damageClip) { + const auto RECT = RECTSARR[i]; + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + + pixman_region32_fini(&damageClip); + } else { + if (pixman_region32_not_empty(m_RenderData.pDamage)) { + PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) { + const auto RECT = RECTSARR[i]; + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } } } @@ -1074,11 +1122,27 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib); glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib); - if (pixman_region32_not_empty(m_RenderData.pDamage)) { - PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) { - const auto RECT = RECTSARR[i]; - scissor(&RECT); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { + pixman_region32_t damageClip; + pixman_region32_init(&damageClip); + pixman_region32_intersect_rect(&damageClip, m_RenderData.pDamage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height); + + if (pixman_region32_not_empty(&damageClip)) { + PIXMAN_DAMAGE_FOREACH(&damageClip) { + const auto RECT = RECTSARR[i]; + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + + pixman_region32_fini(&damageClip); + } else { + if (pixman_region32_not_empty(m_RenderData.pDamage)) { + PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) { + const auto RECT = RECTSARR[i]; + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } } } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 30d66084..33ebb964 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -67,6 +67,8 @@ struct SCurrentRenderData { Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); + + wlr_box clipBox = {}; }; class CHyprOpenGLImpl { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index e36fc5e1..8a1f6f3c 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -248,6 +248,15 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* g_pHyprOpenGL->m_pCurrentWindow = pWindow; + // clip box for animated offsets + if (const auto OFFVEC = PWORKSPACE->m_vRenderOffset.vec(); OFFVEC != Vector2D()) { + g_pHyprOpenGL->m_RenderData.clipBox = {(int)OFFVEC.x, (int)OFFVEC.y, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y }; + + scaleBox(&g_pHyprOpenGL->m_RenderData.clipBox, pMonitor->scale); + } else { + g_pHyprOpenGL->m_RenderData.clipBox = {0, 0, 0, 0}; + } + // render window decorations first, if not fullscreen full if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_MAIN) { @@ -289,6 +298,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* } g_pHyprOpenGL->m_pCurrentWindow = nullptr; + g_pHyprOpenGL->m_RenderData.clipBox = { 0, 0, 0, 0 }; } void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, timespec* time) {