diff options
-rw-r--r-- | unix/xserver/hw/vnc/XserverDesktop.cc | 66 |
1 files 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<RRCrtcPtr> 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; } |