From f84403833857fe4acc027eb29c128feda6c3dc96 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 18 Jul 2012 14:28:58 +0000 Subject: [PATCH] We need to be able to handle outputs without any CRTC connected as well. This is generally the state disabled outputs are in. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4939 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- unix/xserver/hw/vnc/XserverDesktop.cc | 66 +++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc index 8606dcce..99fca44d 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.cc +++ b/unix/xserver/hw/vnc/XserverDesktop.cc @@ -842,11 +842,35 @@ unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height, } } - /* Next count how many useful outputs we have... */ + /* + * Next count how many useful outputs we have... + * + * This gets slightly complicated because we might need to hook a CRTC + * up to the output, but also check that we don't try to use the same + * CRTC for multiple outputs. + */ + std::set usedCrtcs; availableOutputs = 0; for (int i = 0;i < rp->numOutputs;i++) { - if (rp->outputs[i]->crtc != NULL) + RROutputPtr output; + + output = rp->outputs[i]; + + if (output->crtc != NULL) availableOutputs++; + else { + for (int j = 0;j < output->numCrtcs;j++) { + if (output->crtcs[j]->numOutputs != 0) + continue; + if (usedCrtcs.count(output->crtcs[j]) != 0) + continue; + + availableOutputs++; + usedCrtcs.insert(output->crtcs[j]); + + break; + } + } } /* Try to create more outputs if needed... (only works on Xvnc) */ @@ -884,14 +908,17 @@ unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height, output = rp->outputs[i]; crtc = output->crtc; - /* Useful output? */ - if (crtc == NULL) - continue; - /* Known? */ if (outputIdMap.count(output) == 0) continue; + /* A known output should have a CRTC, but double check... */ + if (crtc == NULL) { + vlog.error("Existing output '%s' has unexpectedly been disabled", + output->name); + continue; + } + /* Find the corresponding screen... */ for (iter = layout.begin();iter != layout.end();++iter) { if (iter->id == outputIdMap[output]) @@ -964,14 +991,33 @@ unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height, output = rp->outputs[i]; crtc = output->crtc; - /* Useful output? */ - if (crtc == NULL) - continue; - /* In use? */ if (outputIdMap.count(output) == 1) continue; + /* Need a CRTC? */ + if (crtc == NULL) { + for (int j = 0;j < output->numCrtcs;j++) { + if (output->crtcs[j]->numOutputs != 0) + continue; + + crtc = output->crtcs[j]; + break; + } + + /* Couldn't find one... */ + if (crtc == NULL) + continue; + + ret = RRCrtcSet(crtc, NULL, 0, 0, RR_Rotate_0, + 1, &output); + if (!ret) { + vlog.error("Failed to associate a CRTC with output '%s'", + output->name); + return rfb::resultInvalid; + } + } + break; } -- 2.39.5