@@ -699,6 +699,12 @@ void Aquamarine::CDRMBackend::recheckCRTCs() {
699699 continue ;
700700 }
701701
702+ // disabled outputs release their CRTCs so active outputs get priority
703+ if (c->crtc && c->status == DRM_MODE_CONNECTED && c->output && !c->output ->enabledState ) {
704+ backend->log (AQ_LOG_DEBUG, std::format (" drm: {} is disabled, releasing crtc {}" , c->szName , c->crtc ->id ));
705+ c->crtc .reset ();
706+ }
707+
702708 if (c->crtc && c->status == DRM_MODE_CONNECTED) {
703709 backend->log (AQ_LOG_DEBUG, std::format (" drm: Skipping connector {}, has crtc {} and is connected" , c->szName , c->crtc ->id ));
704710 continue ;
@@ -727,14 +733,18 @@ void Aquamarine::CDRMBackend::recheckCRTCs() {
727733
728734 bool assigned = false ;
729735
730- // try to use a connected connector
736+ // try to use a connected, enabled connector
731737 for (auto const & c : recheck) {
732738 if (!(c->possibleCrtcs & (1 << i)))
733739 continue ;
734740
735741 if (c->status != DRM_MODE_CONNECTED)
736742 continue ;
737743
744+ // Pass 1 only assigns to enabled connectors
745+ if (c->output && !c->output ->enabledState )
746+ continue ;
747+
738748 // deactivate old output
739749 if (c->output && c->output ->state && c->output ->state ->state ().enabled ) {
740750 c->output ->state ->setEnabled (false );
@@ -754,11 +764,38 @@ void Aquamarine::CDRMBackend::recheckCRTCs() {
754764 backend->log (AQ_LOG_DEBUG, std::format (" drm: slot {} crtc {} unassigned" , i, crtcs.at (i)->id ));
755765 }
756766
767+ // Pass 2: assign remaining CRTCs to disabled connectors as backup slots
768+ for (size_t i = 0 ; i < crtcs.size (); ++i) {
769+ bool taken = false ;
770+ for (auto const & c : connectors) {
771+ if (c->crtc == crtcs.at (i)) {
772+ taken = true ;
773+ break ;
774+ }
775+ }
776+ if (taken)
777+ continue ;
778+
779+ for (auto const & c : recheck) {
780+ if (!(c->possibleCrtcs & (1 << i)))
781+ continue ;
782+ if (c->status != DRM_MODE_CONNECTED)
783+ continue ;
784+
785+ backend->log (AQ_LOG_DEBUG, std::format (" drm: backup slot {} crtc {} assigned to disabled {}" , i, crtcs.at (i)->id , c->szName ));
786+ c->crtc = crtcs.at (i);
787+ std::erase (recheck, c);
788+ break ;
789+ }
790+ }
791+
757792 for (auto const & c : connectors) {
758793 if (c->status == DRM_MODE_CONNECTED)
759794 continue ;
760795
761- backend->log (AQ_LOG_DEBUG, std::format (" drm: Connector {} is not connected{}" , c->szName , c->crtc ? std::format (" , removing old crtc {}" , c->crtc ->id ) : " " ));
796+ if (c->crtc )
797+ backend->log (AQ_LOG_DEBUG, std::format (" drm: {} is not connected, clearing stale crtc {}" , c->szName , c->crtc ->id ));
798+ c->crtc .reset ();
762799 }
763800
764801 // tell the user to re-assign a valid mode etc, if needed
@@ -884,6 +921,11 @@ void Aquamarine::CDRMBackend::recheckOutputs() {
884921 // now that crtcs are assigned, connect outputs
885922 for (const auto & conn : connectors) {
886923 if (conn->status == DRM_MODE_CONNECTED && !conn->output && !conn->tilingRedundant ) {
924+ if (!conn->crtc ) {
925+ backend->log (AQ_LOG_DEBUG, std::format (" drm: {} has no CRTC, deferring connection" , conn->szName ));
926+ continue ;
927+ }
928+
887929 backend->log (AQ_LOG_DEBUG, std::format (" drm: Connector {} connected" , conn->szName ));
888930
889931 auto drmConn = drmModeGetConnector (gpu->fd , conn->id );
@@ -1726,13 +1768,27 @@ void Aquamarine::SDRMConnector::applyCommit(const SDRMConnectorCommitData& data)
17261768 if (output->state ->state ().committed & COutputState::AQ_OUTPUT_STATE_MODE)
17271769 refresh = calculateRefresh (data.modeInfo );
17281770
1729- output->enabledState = output->state ->state ().enabled ;
1771+ const bool wasEnabled = output->enabledState ;
1772+ output->enabledState = output->state ->state ().enabled ;
17301773
17311774 if (!output->enabledState )
17321775 releaseFBReferences ();
17331776
17341777 if (!backend->updateSecondaryRendererState ())
17351778 backend->backend ->log (AQ_LOG_ERROR, std::format (" drm: Failed to update renderer state for {} on applyCommit" , szName));
1779+
1780+ if (wasEnabled != output->enabledState ) {
1781+ auto bk = backend.lock ();
1782+ if (bk) {
1783+ bk->backend ->log (AQ_LOG_DEBUG, std::format (" drm: Connector {} enabledState changed {} -> {}" , szName, wasEnabled, output->enabledState ));
1784+ auto weak = bk->self ;
1785+ bk->backend ->addIdleEvent (makeShared<std::function<void (void )>>([weak] {
1786+ auto b = weak.lock ();
1787+ if (b)
1788+ b->recheckOutputs ();
1789+ }));
1790+ }
1791+ }
17361792}
17371793
17381794void Aquamarine::SDRMConnector::rollbackCommit (const SDRMConnectorCommitData& data) {
0 commit comments