Skip to content

view: do not render monitor for tearing if it's blocked - #15500

Merged
vaxerski merged 1 commit into
hyprwm:mainfrom
vaxerski:fix-tearing-stuff
Jul 20, 2026
Merged

view: do not render monitor for tearing if it's blocked#15500
vaxerski merged 1 commit into
hyprwm:mainfrom
vaxerski:fix-tearing-stuff

Conversation

@vaxerski

Copy link
Copy Markdown
Member

If tearing is blocked, we cannot start rendering. We'll start fucking the log and wasting resources

@vaxerski
vaxerski merged commit 2174f26 into hyprwm:main Jul 20, 2026
11 checks passed
ksc98 pushed a commit to ksc98/Hyprland that referenced this pull request Jul 28, 2026
@epsilonshmepsilon

Copy link
Copy Markdown
Contributor

This breaks tearing for me.
First of all in CMonitor::isTearingBlocked I'm not sure if

if (!m_tearingState.nextRenderTorn) {
  reasons |= TC_NOT_TORN;
  if (!full)
    return reasons;
}

is useful. It's not really a reason for blocking tearing. I think the problem now is that to render a torn frame m_tearingState.nextRenderTorn needs to be true, or else isTearingBlocked is always true and

    if (PMONITOR && PMONITOR->m_solitaryClient.lock() == m_self.lock() && canBeTorn() && PMONITOR->m_tearingState.canTear && wlSurface()->resource()->m_current.texture &&
        !PMONITOR->isTearingBlocked()) {

will never be true in CWindow::commitWindow(), so no torn frame can be rendered.
But to get m_tearingState.nextRenderTorn to be true the only place to get it is in CMonitorFrameScheduler::onFrame().

 if (PMONITOR->m_tearingState.activelyTearing && ...) {
...
        PMONITOR->m_tearingState.nextRenderTorn          = true;

But m_tearingState.activelyTearing is only set here (if I'm correct):

bool CMonitor::updateTearing() {
    m_tearingState.activelyTearing = !isTearingBlocked();
    m_tearingState.nextRenderTorn  = false;
    return m_tearingState.activelyTearing;
}

But this uses isTearingBlocked() again which might be always true again because of

    if (!m_tearingState.nextRenderTorn) {
        reasons |= TC_NOT_TORN;
        if (!full)
            return reasons;
    }

So, also activelyTearing is always false.

So getting rid of

    if (!m_tearingState.nextRenderTorn) {
        reasons |= TC_NOT_TORN;
        if (!full)
            return reasons;
    }

in CMonitor::isTearingBlocked might be something to consider.

Also

    if (!m_tearingState.canTear) {
        reasons |= TC_SUPPORT;
        if (!full) {
            Log::logger->log(Log::WARN, "Tearing commit requested but monitor doesn't support it, ignoring");
            return reasons;
        }
    }

is in CMonitor::isTearingBlocked. So is canBeTorn() in

    if (PMONITOR && PMONITOR->m_solitaryClient.lock() == m_self.lock() && canBeTorn() && PMONITOR->m_tearingState.canTear && wlSurface()->resource()->m_current.texture &&
        !PMONITOR->isTearingBlocked()) {

still needed?

@gulafaran

Copy link
Copy Markdown
Contributor

This breaks tearing for me. First of all in CMonitor::isTearingBlocked I'm not sure if

if (!m_tearingState.nextRenderTorn) {
  reasons |= TC_NOT_TORN;
  if (!full)
    return reasons;
}

is useful. It's not really a reason for blocking tearing. I think the problem now is that to render a torn frame m_tearingState.nextRenderTorn needs to be true, or else isTearingBlocked is always true and

    if (PMONITOR && PMONITOR->m_solitaryClient.lock() == m_self.lock() && canBeTorn() && PMONITOR->m_tearingState.canTear && wlSurface()->resource()->m_current.texture &&
        !PMONITOR->isTearingBlocked()) {

will never be true in CWindow::commitWindow(), so no torn frame can be rendered. But to get m_tearingState.nextRenderTorn to be true the only place to get it is in CMonitorFrameScheduler::onFrame().

 if (PMONITOR->m_tearingState.activelyTearing && ...) {
...
        PMONITOR->m_tearingState.nextRenderTorn          = true;

But m_tearingState.activelyTearing is only set here (if I'm correct):

bool CMonitor::updateTearing() {
    m_tearingState.activelyTearing = !isTearingBlocked();
    m_tearingState.nextRenderTorn  = false;
    return m_tearingState.activelyTearing;
}

But this uses isTearingBlocked() again which might be always true again because of

    if (!m_tearingState.nextRenderTorn) {
        reasons |= TC_NOT_TORN;
        if (!full)
            return reasons;
    }

So, also activelyTearing is always false.

So getting rid of

    if (!m_tearingState.nextRenderTorn) {
        reasons |= TC_NOT_TORN;
        if (!full)
            return reasons;
    }

in CMonitor::isTearingBlocked might be something to consider.

Also

    if (!m_tearingState.canTear) {
        reasons |= TC_SUPPORT;
        if (!full) {
            Log::logger->log(Log::WARN, "Tearing commit requested but monitor doesn't support it, ignoring");
            return reasons;
        }
    }

is in CMonitor::isTearingBlocked. So is canBeTorn() in

    if (PMONITOR && PMONITOR->m_solitaryClient.lock() == m_self.lock() && canBeTorn() && PMONITOR->m_tearingState.canTear && wlSurface()->resource()->m_current.texture &&
        !PMONITOR->isTearingBlocked()) {

still needed?

will be reverted in #15580 but requires that AQ pr to not reintroduce the artifacts that caused this commit.

@realm2100

Copy link
Copy Markdown

this PR seems to have broken tearing for me as well, downgrading to 0.56.0 fixed the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants