diff --git a/include/aquamarine/backend/DRM.hpp b/include/aquamarine/backend/DRM.hpp index 88ec1d3..14f2444 100644 --- a/include/aquamarine/backend/DRM.hpp +++ b/include/aquamarine/backend/DRM.hpp @@ -287,6 +287,9 @@ namespace Aquamarine { SDRMPageFlip pendingPageFlip; bool frameEventScheduled = false; + // the current state is invalid and won't commit, don't try to modeset. + bool commitTainted = false; + Hyprutils::Memory::CSharedPointer fallbackMode; struct { diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index a3db54e..ae3cf79 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -1355,7 +1355,11 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) { mgpu.swapchain = CSwapchain::create(backend->mgpu.allocator, backend.lock()); } - auto OPTIONS = swapchain->currentOptions(); + auto OPTIONS = swapchain->currentOptions(); + auto bufDma = STATE.buffer->dmabuf(); + OPTIONS.size = STATE.buffer->size; + if (OPTIONS.format == DRM_FORMAT_INVALID) + OPTIONS.format = bufDma.format; OPTIONS.multigpu = false; // this is not a shared swapchain, and additionally, don't make it linear, nvidia would be mad OPTIONS.cursor = false; OPTIONS.scanout = true; @@ -1428,6 +1432,18 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) { bool ok = connector->commitState(data); + if (!ok && !data.modeset && !connector->commitTainted) { + // attempt to re-modeset, however, flip a tainted flag if the modesetting fails + // to avoid doing this over and over. + data.modeset = true; + data.blocking = true; + data.flags = DRM_MODE_PAGE_FLIP_EVENT; + ok = connector->commitState(data); + + if (!ok) + connector->commitTainted = true; + } + if (onlyTest || !ok) return ok; @@ -1437,6 +1453,9 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) { lastCommitNoBuffer = !data.mainFB; needsFrame = false; + if (ok) + connector->commitTainted = false; + return ok; }