diff options
author | Simon Rettberg | 2020-09-17 15:17:01 +0200 |
---|---|---|
committer | Simon Rettberg | 2020-09-17 15:17:01 +0200 |
commit | 2901482b60f53ba9846db779601297838ad9f622 (patch) | |
tree | ce76febf8c2cf3b229a9fc3280cc0f0605d63cb4 /src | |
parent | Add more debug info (diff) | |
download | beamergui-2901482b60f53ba9846db779601297838ad9f622.tar.gz beamergui-2901482b60f53ba9846db779601297838ad9f622.tar.xz beamergui-2901482b60f53ba9846db779601297838ad9f622.zip |
Force-Add resolutions when using --resolutions option
If the user explicitly passes desired resolutions on the command line,
assume they know what they're doing, and go ahead and force things the
way they were requested.
Also add more debug spam to relevant code, so we can track down
where/why things fail.
Diffstat (limited to 'src')
-rw-r--r-- | src/xprivate.cpp | 60 | ||||
-rw-r--r-- | src/xprivate.h | 1 | ||||
-rw-r--r-- | src/xx.cpp | 43 |
3 files changed, 96 insertions, 8 deletions
diff --git a/src/xprivate.cpp b/src/xprivate.cpp index 7cb0949..53059e4 100644 --- a/src/xprivate.cpp +++ b/src/xprivate.cpp @@ -1,4 +1,5 @@ #include "xprivate.h" +#include "cvt.h" #include <QDebug> #include <QRegularExpression> @@ -658,3 +659,62 @@ XRRModeInfo* XPrivate::setOutputResolution(QStringList &args, OutputInfo *oi, in } return best; } + +/** + * !! oi pointer might be invalid after calling this !! + * @return true if updateScreenResources() should be called later + */ +bool XPrivate::addResolutionToOutput(OutputInfo *oi, const QSize &res) +{ + if (!getOutputModeForResolution(oi->output, res).empty()) + return false; // Nothing to do + XRRModeInfo *bestMode = nullptr; + for (auto *mode : _modeMap) { + if (int(mode->width) != res.width() || int(mode->height) != res.height()) + continue; + if (toVertRefresh(mode) < 59 || toVertRefresh(mode) > 70) + continue; // Play it safe + if (bestMode == nullptr || abs(toVertRefresh(bestMode) - 60) > abs(toVertRefresh(mode) - 60)) { + bestMode = mode; // As close to 60 as possible + } + } + if (bestMode != nullptr) { + qDebug() << "Adding existing mode" << res.width() << 'x' << res.height() << "to" << oi->outputName; + XRRAddOutputMode(_display, oi->id, bestMode->id); + return true; + } else { + // From scratch + qDebug() << "Creating requested mode" << res.width() << 'x' << res.height() << "from scratch"; + QByteArray ba = QString::asprintf("%dx%d_BG", res.width(), res.height()).toLocal8Bit(); + mode *mode = vert_refresh(res.width(), res.height(), 60, 0, 0, 0); + if (mode == nullptr) + return false; // Failed + XRRModeInfo m; + memset(&m, 0, sizeof(m)); + m.width = static_cast<unsigned int>(mode->hr); + m.height = static_cast<unsigned int>(mode->vr); + m.dotClock = static_cast<unsigned long>(mode->pclk) * 1000ul * 1000ul; + m.hSyncStart= static_cast<unsigned int>(mode->hss); + m.hSyncEnd = static_cast<unsigned int>(mode->hse); + m.hTotal = static_cast<unsigned int>(mode->hfl); + m.hSkew = 0; + m.vSyncStart= static_cast<unsigned int>(mode->vss); + m.vSyncEnd = static_cast<unsigned int>(mode->vse); + m.vTotal = static_cast<unsigned int>(mode->vfl); + m.id = 0; + m.name = ba.data(); + m.nameLength= static_cast<unsigned int>(ba.length()); + m.modeFlags = RR_VSyncPositive | RR_HSyncNegative; + free(mode); + RRMode xid = XRRCreateMode(_display, DefaultRootWindow(_display), &m); + if (xid <= 0) { + qDebug() << "Creating mode failed"; + return false; + } + qDebug() << "Adding created mode to" << oi->outputName; + XRRAddOutputMode(_display, oi->id, xid); + // Stuff changed, update now in case other screens want the same resolution + updateScreenResources(); + return false; // We just updated ourselves, don't signal "update required" + } +} diff --git a/src/xprivate.h b/src/xprivate.h index 0152fb1..bc8791e 100644 --- a/src/xprivate.h +++ b/src/xprivate.h @@ -56,6 +56,7 @@ public: XRRModeInfo* setOutputResolution(QStringList &args, OutputInfo *oi, int x, int y, const QSize &size); QList<QSize> getTotalSize(const QList<OutputInfo*> &projectors, const QList<OutputInfo*> &screens) const; void copyModesToAll(RROutput id, int num); + bool addResolutionToOutput(OutputInfo *oi, const QSize &res); Display* _display; Atom _EDID_ATOM; @@ -267,6 +267,7 @@ void ScreenSetup::initModes() if (!a->getOutputModeForResolution(info->output, mode->width, mode->height).isEmpty()) continue; XRRAddOutputMode(a->_display, info->id, mode->id); + qDebug() << "Adding mode" << mode->width << 'x' << mode->height << "to" << info->outputName; } } #undef RES @@ -274,6 +275,7 @@ void ScreenSetup::initModes() for (auto res : wanted) { unsigned int x = res & 0xffff; unsigned int y = res >> 16; + qDebug() << "Creating missing wanted resolution of" << x << "x" << y; createMode(x, y, 60, QString::asprintf("%ux%u", x, y)); } if (!wanted.isEmpty()) { // Modes were added, update for final loop below @@ -282,7 +284,8 @@ void ScreenSetup::initModes() // Finally copy all those the projector supports to other outputs for (auto key : a->_outputMap.keys()) { OutputInfo *oi = a->_outputMap[key]; - if (oi->outputType == Projector::Yes) { + if (oi->outputType == Projector::Yes && oi->output->npreferred > 0) { // Only if has edid + qDebug() << "Copying" << oi->output->nmode << "modes to all from" << oi->outputName; a->copyModesToAll(key, oi->output->nmode); } } @@ -497,7 +500,10 @@ bool ScreenSetup::createMode(unsigned int resX, unsigned int resY, float refresh } RRMode xid = XRRCreateMode(a->_display, DefaultRootWindow(a->_display), &m); - qDebug() << "Return value of create was" << xid; + if (xid <= 0) { + qDebug() << "Return value of create mode was" << xid << "(" << resX << 'x' << resY << ")"; + return false; + } // Immediately add to all screens for (OutputInfo *info : a->_outputMap) { XRRAddOutputMode(a->_display, info->id, xid); @@ -591,21 +597,42 @@ ConfigBackup ScreenSetup::setCustom(const QList<QPair<QSize, QList<QString>>> &l retval = createCrtcBackup(); auto screenSize = getTotalSizeHorz(sizes); if (screenSize.isEmpty()) - return retval; - int x = 0; + return retval; + // Make sure desired resolutions exist on outputs + bool reload = false; + for (auto e : list) { + if (e.second.isEmpty()) + continue; + const QSize &res = e.first; + for (auto outputName : e.second) { + for (auto oi : a->_outputMap) { + if (oi->outputName != outputName) + continue; + // Now add resolution if not found + if (a->addResolutionToOutput(oi, res)) { + reload = true; + } + } + } + } + if (reload) { + updateScreenResources(); + } + int x = 0; for (auto e : list) { if (e.second.isEmpty()) continue; const QSize &res = e.first; unsigned int w = 0; + // Find according output, apply resolution for (auto outputName : e.second) { for (auto oi : a->_outputMap) { if (oi->outputName != outputName) continue; - auto *mode = a->setOutputResolution(cmd, oi, x, 0, res); - if (mode != nullptr && mode->width > w) { - w = mode->width; - } + auto *mode = a->setOutputResolution(cmd, oi, x, 0, res); + if (mode != nullptr && mode->width > w) { + w = mode->width; + } } } x += w; |