summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorUjinT34 <41110182+UjinT34@users.noreply.github.com>2026-02-07 15:38:01 +0300
committerGitHub <noreply@github.com>2026-02-07 12:38:01 +0000
commit9f9dbb0dc54e76ef7d9dd6da8961e9ca1d4ac0ec (patch)
tree3ca57255748bedc670c29fce08454af05cb965e1 /src
parentcfbbfb591ae5c7d11bae72effe6e08ef60ce7453 (diff)
renderer: allow tearing with DS with invisible cursors (#13155)
Diffstat (limited to 'src')
-rw-r--r--src/debug/HyprCtl.cpp17
-rw-r--r--src/helpers/Monitor.cpp12
-rw-r--r--src/helpers/Monitor.hpp8
-rw-r--r--src/managers/PointerManager.cpp11
-rw-r--r--src/managers/PointerManager.hpp1
5 files changed, 27 insertions, 22 deletions
diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp
index 8dbe3a1d..0c33c7a4 100644
--- a/src/debug/HyprCtl.cpp
+++ b/src/debug/HyprCtl.cpp
@@ -144,13 +144,13 @@ std::string CHyprCtl::getSolitaryBlockedReason(Hyprutils::Memory::CSharedPointer
}
const std::array<const char*, CMonitor::DS_CHECKS_COUNT> DS_REASONS_JSON = {
- "\"UNKNOWN\"", "\"USER\"", "\"WINDOWED\"", "\"CONTENT\"", "\"MIRROR\"", "\"RECORD\"", "\"SW\"",
- "\"CANDIDATE\"", "\"SURFACE\"", "\"TRANSFORM\"", "\"DMA\"", "\"TEARING\"", "\"FAILED\"", "\"CM\"",
+ "\"UNKNOWN\"", "\"USER\"", "\"WINDOWED\"", "\"CONTENT\"", "\"MIRROR\"", "\"RECORD\"", "\"SW\"",
+ "\"CANDIDATE\"", "\"SURFACE\"", "\"TRANSFORM\"", "\"DMA\"", "\"FAILED\"", "\"CM\"",
};
const std::array<const char*, CMonitor::DS_CHECKS_COUNT> DS_REASONS_TEXT = {
- "unknown reason", "user settings", "windowed mode", "content type", "monitor mirrors", "screen record/screenshot", "software renders/cursors",
- "missing candidate", "invalid surface", "surface transformations", "invalid buffer", "tearing", "activation failed", "color management",
+ "unknown reason", "user settings", "windowed mode", "content type", "monitor mirrors", "screen record/screenshot", "software renders/cursors",
+ "missing candidate", "invalid surface", "surface transformations", "invalid buffer", "activation failed", "color management",
};
std::string CHyprCtl::getDSBlockedReason(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format) {
@@ -173,14 +173,13 @@ std::string CHyprCtl::getDSBlockedReason(Hyprutils::Memory::CSharedPointer<CMoni
}
const std::array<const char*, CMonitor::TC_CHECKS_COUNT> TEARING_REASONS_JSON = {
- "\"UNKNOWN\"", "\"NOT_TORN\"", "\"USER\"", "\"ZOOM\"", "\"SUPPORT\"", "\"CANDIDATE\"", "\"WINDOW\"",
+ "\"UNKNOWN\"", "\"NOT_TORN\"", "\"USER\"", "\"ZOOM\"", "\"SUPPORT\"", "\"CANDIDATE\"", "\"WINDOW\"", "\"HW_CURSOR\"",
};
-const std::array<const char*, CMonitor::TC_CHECKS_COUNT> TEARING_REASONS_TEXT = {
- "unknown reason", "next frame is not torn", "user settings", "zoom", "not supported by monitor", "missing candidate", "window settings",
-};
+const std::array<const char*, CMonitor::TC_CHECKS_COUNT> TEARING_REASONS_TEXT = {"unknown reason", "next frame is not torn", "user settings", "zoom",
+ "not supported by monitor", "missing candidate", "window settings", "hw cursor"};
-std::string CHyprCtl::getTearingBlockedReason(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format) {
+std::string CHyprCtl::getTearingBlockedReason(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format) {
const auto reasons = m->isTearingBlocked(true);
if (!reasons || (reasons == CMonitor::TC_NOT_TORN && m->m_tearingState.activelyTearing))
return "null";
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp
index ab581394..f0077c63 100644
--- a/src/helpers/Monitor.cpp
+++ b/src/helpers/Monitor.cpp
@@ -1724,6 +1724,10 @@ uint8_t CMonitor::isTearingBlocked(bool full) {
}
}
+ // TODO: remove this when kernel allows tearing + hw cursor updated
+ if (g_pPointerManager->hasVisibleHWCursor(m_self.lock()))
+ reasons |= TC_HW_CURSOR;
+
if (m_solitaryClient.expired()) {
reasons |= TC_CANDIDATE;
return reasons;
@@ -1765,12 +1769,6 @@ uint16_t CMonitor::isDSBlocked(bool full) {
}
}
- if (m_tearingState.activelyTearing) {
- reasons |= DS_BLOCK_TEARING;
- if (!full)
- return reasons;
- }
-
if (!m_mirrors.empty() || isMirror()) {
reasons |= DS_BLOCK_MIRROR;
if (!full)
@@ -1862,7 +1860,7 @@ bool CMonitor::attemptDirectScanout() {
}
//#TODO this entire bit is bootleg deluxe, above bit is to not make vrr go down the drain, returning early here means fifo gets forever locked.
- if (PSURFACE->m_fifo && *PSAMEFIFO)
+ if (PSURFACE->m_fifo && !m_tearingState.activelyTearing && *PSAMEFIFO)
PSURFACE->m_stateQueue.unlockFirst(LOCK_REASON_FIFO);
return true;
diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp
index d1f9a556..3ce98d8c 100644
--- a/src/helpers/Monitor.hpp
+++ b/src/helpers/Monitor.hpp
@@ -233,9 +233,8 @@ class CMonitor {
DS_BLOCK_SURFACE = (1 << 8),
DS_BLOCK_TRANSFORM = (1 << 9),
DS_BLOCK_DMA = (1 << 10),
- DS_BLOCK_TEARING = (1 << 11),
- DS_BLOCK_FAILED = (1 << 12),
- DS_BLOCK_CM = (1 << 13),
+ DS_BLOCK_FAILED = (1 << 11),
+ DS_BLOCK_CM = (1 << 12),
DS_CHECKS_COUNT = 14,
};
@@ -276,8 +275,9 @@ class CMonitor {
TC_SUPPORT = (1 << 4),
TC_CANDIDATE = (1 << 5),
TC_WINDOW = (1 << 6),
+ TC_HW_CURSOR = (1 << 7),
- TC_CHECKS_COUNT = 7,
+ TC_CHECKS_COUNT = 8,
};
// methods
diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp
index 44084d2c..5db37cb0 100644
--- a/src/managers/PointerManager.cpp
+++ b/src/managers/PointerManager.cpp
@@ -72,8 +72,10 @@ void CPointerManager::lockSoftwareForMonitor(PHLMONITOR mon) {
void CPointerManager::unlockSoftwareForMonitor(PHLMONITOR mon) {
auto const state = stateFor(mon);
state->softwareLocks--;
- if (state->softwareLocks < 0)
+ if (state->softwareLocks < 0) {
state->softwareLocks = 0;
+ Log::logger->log(Log::WARN, "Unlocking SW for monitor while it's not locked");
+ }
if (state->softwareLocks == 0)
updateCursorBackend();
@@ -81,7 +83,12 @@ void CPointerManager::unlockSoftwareForMonitor(PHLMONITOR mon) {
bool CPointerManager::softwareLockedFor(PHLMONITOR mon) {
auto const state = stateFor(mon);
- return state->softwareLocks > 0 || state->hardwareFailed;
+ return state->softwareLocks > 0 || (state->hardwareFailed && hasCursor() && g_pHyprRenderer->shouldRenderCursor());
+}
+
+bool CPointerManager::hasVisibleHWCursor(PHLMONITOR pMonitor) {
+ auto const state = stateFor(pMonitor);
+ return state->softwareLocks == 0 && !state->hardwareFailed && hasCursor() && g_pHyprRenderer->shouldRenderCursor();
}
Vector2D CPointerManager::position() {
diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp
index d60903a6..29603513 100644
--- a/src/managers/PointerManager.hpp
+++ b/src/managers/PointerManager.hpp
@@ -48,6 +48,7 @@ class CPointerManager {
void lockSoftwareAll();
void unlockSoftwareAll();
bool softwareLockedFor(PHLMONITOR pMonitor);
+ bool hasVisibleHWCursor(PHLMONITOR pMonitor);
void renderSoftwareCursorsFor(PHLMONITOR pMonitor, const Time::steady_tp& now, CRegion& damage /* logical */, std::optional<Vector2D> overridePos = {} /* monitor-local */,
bool forceRender = false);