summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Golubev <fatzer2@gmail.com>2023-12-24 11:09:32 +0300
committerAlexander Golubev <fatzer2@gmail.com>2023-12-24 12:57:08 +0300
commitd32b076ae65478e6ce78ac3cc1db6957cf1ebb25 (patch)
treee9567d4bc475e6ffe85c89cb4433ed794250962f
parentac6c53f3fa24444a902adaf7f904b320ef327ec5 (diff)
downloadtdelibs-d32b076ae65478e6ce78ac3cc1db6957cf1ebb25.tar.gz
tdelibs-d32b076ae65478e6ce78ac3cc1db6957cf1ebb25.zip
tderandr: workaround for tde/75fix/tde-75
Some videocards' drivers (most notably propryetary nvidia) report incorrect screen refresh rate via XRRRates(). Use XRRGetScreenResources() + some math borrowed from xrandr instead. Bug: https://mirror.git.trinitydesktop.org/gitea/TDE/tde/issues/75 Signed-off-by: Alexander Golubev <fatzer2@gmail.com>
-rw-r--r--tderandr/randr.cpp155
-rw-r--r--tderandr/randr.h2
2 files changed, 121 insertions, 36 deletions
diff --git a/tderandr/randr.cpp b/tderandr/randr.cpp
index 6a3d0381e..e050852df 100644
--- a/tderandr/randr.cpp
+++ b/tderandr/randr.cpp
@@ -40,6 +40,10 @@
#undef INT32
#include <X11/extensions/Xrandr.h>
+static int refreshRateForModeInfo (const XRRModeInfo *mode_info);
+static int refreshRateIndexToXRR(int screen, int size, int index);
+static int refreshRateXRRToIndex(int screen, int size, int hz);
+
HotPlugRule::HotPlugRule()
{
//
@@ -169,7 +173,8 @@ KDE_EXPORT void RandRScreen::loadSettings()
}
if (d->config) {
- m_currentRefreshRate = m_proposedRefreshRate = refreshRateHzToIndex(m_currentSize, XRRConfigCurrentRate(d->config));
+ m_currentRefreshRate = m_proposedRefreshRate =
+ refreshRateXRRToIndex(m_screen, m_currentSize, XRRConfigCurrentRate(d->config));
}
else {
m_currentRefreshRate = m_proposedRefreshRate = 0;
@@ -185,8 +190,12 @@ KDE_EXPORT void RandRScreen::setOriginal()
KDE_EXPORT bool RandRScreen::applyProposed()
{
- //kdDebug() << k_funcinfo << " size " << (SizeID)proposedSize() << ", rotation " << proposedRotation() << ", refresh " << refreshRateIndexToHz(proposedSize(), proposedRefreshRate()) << endl;
-
+#if 0
+ kdDebug() << k_funcinfo << " size " << (SizeID)proposedSize() <<
+ ", rotation " << proposedRotation() <<
+ ", refresh " << refreshRateIndexToHz(proposedSize(), proposedRefreshRate())
+ << " (" << refreshRateIndexToXRR(m_screen, proposedSize(), proposedRefreshRate()) << ")" << endl;
+#endif
Status status;
if (!d->config) {
@@ -198,10 +207,11 @@ KDE_EXPORT bool RandRScreen::applyProposed()
if (proposedRefreshRate() < 0)
status = XRRSetScreenConfig(tqt_xdisplay(), d->config, DefaultRootWindow(tqt_xdisplay()), (SizeID)proposedSize(), (Rotation)proposedRotation(), CurrentTime);
else {
- if( refreshRateIndexToHz(proposedSize(), proposedRefreshRate()) <= 0 ) {
+ int hz = refreshRateIndexToXRR(m_screen, proposedSize(), proposedRefreshRate());
+ if( hz <= 0 ) {
m_proposedRefreshRate = 0;
}
- status = XRRSetScreenConfigAndRate(tqt_xdisplay(), d->config, DefaultRootWindow(tqt_xdisplay()), (SizeID)proposedSize(), (Rotation)proposedRotation(), refreshRateIndexToHz(proposedSize(), proposedRefreshRate()), CurrentTime);
+ status = XRRSetScreenConfigAndRate(tqt_xdisplay(), d->config, DefaultRootWindow(tqt_xdisplay()), (SizeID)proposedSize(), (Rotation)proposedRotation(), hz, CurrentTime);
}
}
else {
@@ -487,26 +497,22 @@ KDE_EXPORT int RandRScreen::currentMMHeight() const
return m_pixelSizes[m_currentSize].height();
}
-KDE_EXPORT TQStringList RandRScreen::refreshRates(int size) const
+KDE_EXPORT TQValueVector<int> RandRScreen::refreshRatesValues(int size) const
{
- int nrates;
- TQStringList ret;
+ ScreenInfo *screeninfo = internal_read_screen_info(tqt_xdisplay());
+ int numSizes = screeninfo->res->nmode;
+ TQValueVector<int> ret;
- if (d->config) {
- short* rates = XRRRates(tqt_xdisplay(), m_screen, (SizeID)size, &nrates);
-
- for (int i = 0; i < nrates; i++)
- ret << refreshRateDirectDescription(rates[i]);
+ if (size > numSizes-1) { // out of range
+ return ret;
}
- else {
- // Great, now we have to go after the information manually. Ughh.
- ScreenInfo *screeninfo = internal_read_screen_info(tqt_xdisplay());
- int numSizes = screeninfo->res->nmode;
- for (int i = 0; i < numSizes; i++) {
- int refresh_rate = ((screeninfo->res->modes[i].dotClock*1.0)/((screeninfo->res->modes[i].hTotal)*(screeninfo->res->modes[i].vTotal)*1.0));
- TQString newRate = refreshRateDirectDescription(refresh_rate);
- if (!ret.contains(newRate)) {
- ret.append(newRate);
+
+ char * currentModeName = screeninfo->res->modes[size].name;
+ for (int i = 0; i < numSizes; i++) {
+ if (strcmp(currentModeName, screeninfo->res->modes[i].name) == 0) {
+ int rate = refreshRateForModeInfo(&screeninfo->res->modes[i]);
+ if (rate!=0) {
+ ret.append(rate);
}
}
}
@@ -514,6 +520,17 @@ KDE_EXPORT TQStringList RandRScreen::refreshRates(int size) const
return ret;
}
+KDE_EXPORT TQStringList RandRScreen::refreshRates(int size) const
+{
+ TQStringList ret;
+
+ for (int rate: refreshRatesValues(size)) {
+ ret.append(refreshRateDirectDescription(rate));
+ }
+
+ return ret;
+}
+
KDE_EXPORT TQString RandRScreen::refreshRateDirectDescription(int rate) const
{
return i18n("Refresh rate in Hertz (Hz)", "%1 Hz").arg(rate);
@@ -521,7 +538,7 @@ KDE_EXPORT TQString RandRScreen::refreshRateDirectDescription(int rate) const
KDE_EXPORT TQString RandRScreen::refreshRateIndirectDescription(int size, int index) const
{
- return i18n("Refresh rate in Hertz (Hz)", "%1 Hz").arg(refreshRateIndexToHz(size, index));
+ return refreshRateDirectDescription(refreshRateIndexToHz(size, index));
}
KDE_EXPORT TQString RandRScreen::refreshRateDescription(int size, int index) const
@@ -556,30 +573,28 @@ KDE_EXPORT int RandRScreen::proposedRefreshRate() const
KDE_EXPORT int RandRScreen::refreshRateHzToIndex(int size, int hz) const
{
- int nrates;
- short* rates = XRRRates(tqt_xdisplay(), m_screen, (SizeID)size, &nrates);
-
- for (int i = 0; i < nrates; i++)
- if (hz == rates[i])
+ TQValueVector<int> rates = refreshRatesValues(size);
+ for (size_t i=0; i<rates.size(); i++) {
+ if ( (int) (rates[i] + 0.5) == hz) {
return i;
+ }
+ }
- if (nrates != 0)
+ if (rates.size() != 0)
// Wrong input Hz!
Q_ASSERT(false);
return -1;
}
-KDE_EXPORT int RandRScreen::refreshRateIndexToHz(int size, int index) const
-{
- int nrates;
- short* rates = XRRRates(tqt_xdisplay(), m_screen, (SizeID)size, &nrates);
+KDE_EXPORT int RandRScreen::refreshRateIndexToHz(int size, int index) const {
+ TQValueVector<int> rates = refreshRatesValues(size);
- if (nrates == 0 || index < 0)
+ if (rates.size() == 0 || index < 0)
return 0;
- // Wrong input Hz!
- if(index >= nrates)
+ // Wrong input index!
+ if(index >= (ssize_t)rates.size())
return 0;
return rates[index];
@@ -880,4 +895,72 @@ KDE_EXPORT int RandRScreen::pixelCount( int index ) const
return sz.width() * sz.height();
}
+// Calculates refresh rate for modeinfo
+// snatch from xrandr-1.5
+static int refreshRateForModeInfo(const XRRModeInfo *mode_info)
+{
+ double rate;
+ double vTotal = mode_info->vTotal;
+
+ if (mode_info->modeFlags & RR_DoubleScan) {
+ /* doublescan doubles the number of lines */
+ vTotal *= 2;
+ }
+
+ if (mode_info->modeFlags & RR_Interlace) {
+ /* interlace splits the frame into two fields */
+ /* the field rate is what is typically reported by monitors */
+ vTotal /= 2;
+ }
+
+ if (mode_info->hTotal && vTotal)
+ rate = ((double) mode_info->dotClock /
+ ((double) mode_info->hTotal * (double) vTotal));
+ else
+ rate = 0;
+ return (int) (rate+0.5);
+}
+
+// On some video drivers (e.g. proprietary nvidia) XRandR returns incorrect
+// readings for refresh rate[1], when read via XRRRates(), so for display
+// purposes we will use data from XRRGetScreenResources() and some fancy
+// calculations (see internal_read_screen_info() and refreshRateForModeInfo()).
+// Unfortunately, other XRandR functions (like XRRConfigCurrentRate() and
+// XRRSetScreenConfigAndRate()) expect the data reported by XRRRates(). So,
+// in order to be able to correctly set a refresh rate we have to request
+// it via XRRRates() anyway.
+//
+// [1]: see https://mirror.git.trinitydesktop.org/gitea/TDE/tde/issues/75
+
+static int refreshRateXRRToIndex(int screen, int size, int hz)
+{
+ int nrates;
+ short* rates = XRRRates(tqt_xdisplay(), screen, (SizeID)size, &nrates);
+
+ for (int i = 0; i < nrates; i++)
+ if (hz == rates[i])
+ return i;
+
+ if (nrates != 0)
+ // Wrong input Hz!
+ Q_ASSERT(false);
+
+ return -1;
+}
+
+static int refreshRateIndexToXRR(int screen, int size, int index)
+{
+ int nrates;
+ short* rates = XRRRates(tqt_xdisplay(), screen, (SizeID)size, &nrates);
+
+ if (nrates == 0 || index < 0)
+ return 0;
+
+ // Wrong input Hz!
+ if(index >= nrates)
+ return 0;
+
+ return rates[index];
+}
+
#include "randr.moc"
diff --git a/tderandr/randr.h b/tderandr/randr.h
index 36e87badd..36cdd0088 100644
--- a/tderandr/randr.h
+++ b/tderandr/randr.h
@@ -21,6 +21,7 @@
#include <tqobject.h>
#include <tqstringlist.h>
+#include <tqvaluevector.h>
#include <tqptrlist.h>
#include <tdecmodule.h>
@@ -152,6 +153,7 @@ public:
/**
* Refresh rate functions.
*/
+ TQValueVector<int> refreshRatesValues(int size) const;
TQStringList refreshRates(int size) const;
TQString refreshRateDirectDescription(int rate) const;