MythTV  master
mythdisplay.cpp
Go to the documentation of this file.
1 //Qt
2 #include <QTimer>
3 #include <QThread>
4 #include <QApplication>
5 #include <QElapsedTimer>
6 #include <QWindow>
7 
8 // MythTV
9 #include "mythlogging.h"
10 #include "compat.h"
11 #include "mythcorecontext.h"
12 #include "mythuihelper.h"
13 #include "mythdisplay.h"
14 #include "mythegl.h"
15 #include "mythmainwindow.h"
16 
17 #ifdef USING_DBUS
19 #endif
20 #ifdef USING_WAYLANDEXTRAS
22 #endif
23 #ifdef Q_OS_ANDROID
25 #endif
26 #if defined(Q_OS_MAC)
28 #endif
29 #ifdef USING_X11
32 #endif
33 #ifdef USING_DRM
36 #endif
37 #if defined(Q_OS_WIN)
39 #endif
40 #ifdef USING_MMAL
42 #endif
43 
44 #define LOC QString("Display: ")
45 
81 {
82  MythDisplay* result = nullptr;
83 #ifdef USING_X11
85  result = new MythDisplayX11();
86 #endif
87 #ifdef USING_DBUS
88  // Disabled for now as org.gnome.Mutter.DisplayConfig.ApplyConfiguration does
89  // not seem to be actually implemented by anyone.
90 #ifdef USING_WAYLANDEXTRAS
91  //if (MythWaylandDevice::IsAvailable())
92 #endif
93  //{
94  // if (!result)
95  // result = MythDisplayMutter::Create();
96  //}
97 #endif
98 #ifdef USING_DRM
99  if (!result)
100  {
101  result = new MythDisplayDRM(MainWindow);
102  // On the Pi, use MythDisplayRPI if mode switching is not available via DRM
103 #ifdef USING_MMAL
104  if (!result->VideoModesAvailable())
105  {
106  delete result;
107  result = nullptr;
108  }
109 #endif
110  }
111 #else
112  (void)MainWindow;
113 #endif
114 #ifdef USING_MMAL
115  if (!result)
116  result = new MythDisplayRPI();
117 #endif
118 #if defined(Q_OS_MAC)
119  if (!result)
120  result = new MythDisplayOSX();
121 #endif
122 #ifdef Q_OS_ANDROID
123  if (!result)
124  result = new MythDisplayAndroid();
125 #endif
126 #if defined(Q_OS_WIN)
127  if (!result)
128  result = new MythDisplayWindows();
129 #endif
130  if (!result)
131  result = new MythDisplay();
132  return result;
133 }
134 
136 {
137  QStringList result;
138  bool spanall = false;
139  int screencount = MythDisplay::GetScreenCount();
140  if (MythDisplay::SpanAllScreens() && screencount > 1)
141  {
142  spanall = true;
143  result.append(tr("Spanning %1 screens").arg(screencount));
144  result.append(tr("Total bounds") + QString("\t: %1x%2")
145  .arg(GetScreenBounds().width()).arg(GetScreenBounds().height()));
146  result.append("");
147  }
148 
149  if (m_hdrState)
150  {
151  auto types = m_hdrState->m_supportedTypes;
152  auto hdr = m_hdrState->TypesToString();
153  result.append(tr("Supported HDR formats\t: %1").arg(hdr.join(",")));
154  if (types && !m_hdrState->IsControllable())
155  result.append(tr("HDR mode switching is not available"));
156  if (auto brightness = m_hdrState->GetMaxLuminance(); brightness > 1.0)
157  result.append(tr("Max display brightness\t: %1 nits").arg(static_cast<int>(brightness)));
158  }
159 
160  if (m_vrrState)
161  {
162  result.append(tr("Variable refresh rate '%1': %2 %3")
163  .arg(m_vrrState->TypeToString(),
164  m_vrrState->Enabled() ? tr("Enabled") : tr("Disabled"),
165  m_vrrState->RangeDescription()));
166  }
167 
168  auto * current = GetCurrentScreen();
169  const auto screens = QGuiApplication::screens();
170  bool first = true;
171  for (auto *screen : qAsConst(screens))
172  {
173  if (!first)
174  result.append("");
175  first = false;
176  auto id = QString("(%1)").arg(screen->manufacturer());
177  if (screen == current && !spanall)
178  result.append(tr("Current screen %1 %2:").arg(screen->name(), id));
179  else
180  result.append(tr("Screen %1 %2:").arg(screen->name(), id));
181  result.append(tr("Size") + QString("\t\t: %1mmx%2mm")
182  .arg(screen->physicalSize().width()).arg(screen->physicalSize().height()));
183  if (screen == current)
184  {
185  QString source;
186  auto aspect = GetAspectRatio(source);
187  result.append(tr("Aspect ratio") + QString("\t: %1 (%2)")
188  .arg(aspect, 0, 'f', 3).arg(source));
189  if (!spanall)
190  {
191  result.append(tr("Current mode") + QString("\t: %1x%2@%3Hz")
192  .arg(GetResolution().width()).arg(GetResolution().height())
193  .arg(GetRefreshRate(), 0, 'f', 2));
194  const auto & modes = GetVideoModes();
195  if (!modes.empty())
196  {
197  result.append(tr("Available modes:"));
198  for (auto it = modes.crbegin(); it != modes.crend(); ++it)
199  result.append(" " + it->ToString());
200  }
201  }
202  }
203  }
204 
205  return result;
206 }
207 
209 {
211  DebugScreen(m_screen, "Using");
212  if (m_screen)
213  {
214  connect(m_screen, &QScreen::geometryChanged, this, &MythDisplay::GeometryChanged);
215  connect(m_screen, &QScreen::physicalDotsPerInchChanged, this, &MythDisplay::PhysicalDPIChanged);
216  }
217 
218  auto *guiapp = qobject_cast<QGuiApplication *>(QCoreApplication::instance());
219  if (guiapp == nullptr)
220  return;
221 
222  connect(guiapp, &QGuiApplication::screenRemoved, this, &MythDisplay::ScreenRemoved);
223  connect(guiapp, &QGuiApplication::screenAdded, this, &MythDisplay::ScreenAdded);
224  connect(guiapp, &QGuiApplication::primaryScreenChanged, this, &MythDisplay::PrimaryScreenChanged);
225 }
226 
228 {
229  LOG(VB_GENERAL, LOG_INFO, LOC + "Deleting");
230 }
231 
245 void MythDisplay::SetWidget(QWidget *MainWindow)
246 {
247  QWidget* oldwidget = m_widget;
248  m_widget = MainWindow;
249  if (!m_modeComplete)
251 
252  QWindow* oldwindow = m_window;
253  if (m_widget)
254  m_window = m_widget->windowHandle();
255  else
256  m_window = nullptr;
257 
258  if (m_widget && (m_widget != oldwidget))
259  LOG(VB_GENERAL, LOG_INFO, LOC + "Have main widget");
260 
261  if (m_window && (m_window != oldwindow))
262  {
263  LOG(VB_GENERAL, LOG_INFO, LOC + "Have main window");
264 
265  connect(m_window, &QWindow::screenChanged, this, &MythDisplay::ScreenChanged, Qt::UniqueConnection);
266  QScreen *desired = GetDesiredScreen();
267  // If we have changed the video mode for the old screen then reset
268  // it to the default/desktop mode
269  if (oldwindow)
270  SwitchToDesktop();
271  // Ensure we completely re-initialise when the new screen is set
272  m_initialised = false;
273  if (desired != m_screen)
274  DebugScreen(desired, "Moving to");
275  m_window->setScreen(desired);
276  // WaitForNewScreen doesn't work as intended. It successfully filters
277  // out unwanted screenChanged signals after moving screens - but always
278  //times out. This just delays startup by 500ms - so ignore on startup as it isn't needed.
279  if (!m_firstScreenChange)
281  m_firstScreenChange = false;
283  return;
284  }
285 }
286 
288 {
289  return QGuiApplication::screens().size();
290 }
291 
293 {
294  if (m_physicalSize.isEmpty() || m_resolution.isEmpty())
295  return 1.0;
296 
297  return (m_physicalSize.width() / static_cast<double>(m_resolution.width())) /
298  (m_physicalSize.height() / static_cast<double>(m_resolution.height()));
299 }
300 
302 {
303  return m_guiMode.Resolution();
304 }
305 
307 {
308  return m_screenBounds;
309 }
310 
324 {
325  return m_screen;
326 }
327 
329 {
330  QScreen* newscreen = nullptr;
331 
332  // If geometry is overriden at the command line level, try and determine
333  // which screen that applies to (if any).
334  // N.B. So many potential issues here e.g. should the geometry override be
335  // ignored after first use? (as it will continue to override the screen
336  // regardless of changes to screen preference).
338  {
339  // this matches the check in MythMainWindow
340  bool windowed = GetMythDB()->GetBoolSetting("RunFrontendInWindow", false) &&
342  QRect override = MythMainWindow::GetGeometryOverride();
343  // When windowed, we use topleft as a best guess as to which screen we belong in.
344  // When fullscreen, Qt appears to use the reverse - though this may be
345  // the window manager rather than Qt. So could be wrong.
346  QPoint point = windowed ? override.topLeft() : override.bottomRight();
347  QList screens = QGuiApplication::screens();
348  for (QScreen *screen : qAsConst(screens))
349  {
350  if (screen->geometry().contains(point))
351  {
352  newscreen = screen;
353  LOG(VB_GENERAL, LOG_INFO, LOC + QString(
354  "Geometry override places window in screen '%1'").arg(newscreen->name()));
355  break;
356  }
357  }
358  }
359 
360  // If spanning all screens, then always use the primary display
361  if (!newscreen && MythDisplay::SpanAllScreens())
362  {
363  LOG(VB_GENERAL, LOG_INFO, LOC + "Using primary screen for multiscreen");
364  newscreen = QGuiApplication::primaryScreen();
365  }
366 
367  QString name = gCoreContext->GetSetting("XineramaScreen", nullptr);
368  // Lookup by name
369  if (!newscreen)
370  {
371  QList screens = QGuiApplication::screens();
372  for (QScreen *screen : qAsConst(screens))
373  {
374  if (!name.isEmpty() && name == screen->name())
375  {
376  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Found screen '%1'").arg(name));
377  newscreen = screen;
378  }
379  }
380  }
381 
382  // No name match. These were previously numbers.
383  if (!newscreen)
384  {
385  bool ok = false;
386  int screen_num = name.toInt(&ok);
387  QList<QScreen *>screens = QGuiApplication::screens();
388  if (ok && (screen_num >= 0) && (screen_num < screens.size()))
389  {
390  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Found screen number %1 (%2)")
391  .arg(name, screens[screen_num]->name()));
392  newscreen = screens[screen_num];
393  }
394  }
395 
396  // For anything else, return the primary screen.
397  if (!newscreen)
398  {
399  QScreen *primary = QGuiApplication::primaryScreen();
400  if (name.isEmpty() && primary)
401  {
402  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Defaulting to primary screen (%1)")
403  .arg(primary->name()));
404  }
405  else if (name != "-1" && primary)
406  {
407  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Screen '%1' not found, defaulting to primary screen (%2)")
408  .arg(name, primary->name()));
409  }
410  newscreen = primary;
411  }
412 
413  return newscreen;
414 }
415 
418 void MythDisplay::ScreenChanged(QScreen *qScreen)
419 {
420  if (qScreen == m_screen)
421  return;
422  if (m_screen)
423  disconnect(m_screen, nullptr, this, nullptr);
424  DebugScreen(qScreen, "Changed to");
425  m_screen = qScreen;
426  connect(m_screen, &QScreen::geometryChanged, this, &MythDisplay::GeometryChanged);
427  connect(m_screen, &QScreen::physicalDotsPerInchChanged, this, &MythDisplay::PhysicalDPIChanged);
428  Initialise();
429  emit CurrentScreenChanged(qScreen);
430 }
431 
433 {
434  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Qt screen pixel ratio changed to %1")
435  .arg(DPI, 2, 'f', 2, '0'));
436  emit CurrentDPIChanged(DPI);
437 }
438 
439 void MythDisplay::PrimaryScreenChanged(QScreen* qScreen)
440 {
441  DebugScreen(qScreen, "New primary");
442 }
443 
444 void MythDisplay::ScreenAdded(QScreen* qScreen)
445 {
446  DebugScreen(qScreen, "New");
447  emit ScreenCountChanged(QGuiApplication::screens().size());
448 }
449 
450 void MythDisplay::ScreenRemoved(QScreen* qScreen)
451 {
452  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Screen '%1' removed").arg(qScreen->name()));
453  emit ScreenCountChanged(QGuiApplication::screens().size());
454 }
455 
456 void MythDisplay::GeometryChanged(const QRect Geo)
457 {
458  LOG(VB_GENERAL, LOG_INFO, LOC + QString("New screen geometry: %1x%2+%3+%4")
459  .arg(Geo.width()).arg(Geo.height()).arg(Geo.left()).arg(Geo.top()));
460 }
461 
469 {
470  // Certain platform implementations do not have a window to access at startup
471  // and hence use this implementation. Flag the status as incomplete to ensure
472  // we try to retrieve the full details at the first opportunity.
473  m_modeComplete = false;
474  m_edid = MythEDID();
475  QScreen *screen = GetCurrentScreen();
476  if (!screen)
477  {
478  m_refreshRate = 60.0;
479  m_physicalSize = QSize(0, 0);
480  m_resolution = QSize(1920, 1080);
481  return;
482  }
483  m_refreshRate = screen->refreshRate();
484  m_resolution = screen->size();
485  m_physicalSize = QSize(static_cast<int>(screen->physicalSize().width()),
486  static_cast<int>(screen->physicalSize().height()));
487 }
488 
491 {
492  return gCoreContext->GetSetting("XineramaScreen", nullptr) == "-1";
493 }
494 
495 QString MythDisplay::GetExtraScreenInfo(QScreen *qScreen)
496 {
497  QString mfg = qScreen->manufacturer();
498  if (mfg.isEmpty())
499  mfg = "Unknown";
500  QString model = qScreen->model();
501  if (model.isEmpty())
502  model = "Unknown";
503  return QString("(Make: %1 Model: %2)").arg(mfg, model);
504 }
505 
506 void MythDisplay::DebugScreen(QScreen *qScreen, const QString &Message)
507 {
508  if (!qScreen)
509  return;
510 
511  auto geom = qScreen->geometry();
512  LOG(VB_GENERAL, LOG_INFO, LOC + QString("%1 screen '%2' %3")
513  .arg(Message, qScreen->name(), GetExtraScreenInfo(qScreen)));
514  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Qt screen pixel ratio: %1")
515  .arg(qScreen->devicePixelRatio(), 2, 'f', 2, '0'));
516  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Geometry: %1x%2+%3+%4 Size(Qt): %5mmx%6mm")
517  .arg(geom.width()).arg(geom.height()).arg(geom.left()).arg(geom.top())
518  .arg(qScreen->physicalSize().width()).arg(qScreen->physicalSize().height()));
519 
520  if (qScreen->virtualGeometry() != geom)
521  {
522  geom = qScreen->virtualGeometry();
523  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Total virtual geometry: %1x%2+%3+%4")
524  .arg(geom.width()).arg(geom.height()).arg(geom.left()).arg(geom.top()));
525  }
526 }
527 
529 {
530  m_videoModes.clear();
531  m_overrideVideoModes.clear();
533  // Note: The EDID is retrieved in UpdateCurrentMode and we need the EDID to
534  // check for refresh rate range support.
535  m_vrrState = MythVRR::Create(this);
537 
538  // Set the desktop mode - which is the mode at startup. We must always return
539  // the screen to this mode.
540  if (!m_initialised)
541  {
542  // Only ever set this once or after a screen change
543  m_initialised = true;
545  LOG(VB_GENERAL, LOG_NOTICE, LOC + QString("Desktop video mode: %1x%2 %3Hz")
546  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate, 0, 'f', 3));
547  if (m_edid.Valid())
548  {
549  if (m_edid.IsSRGB())
550  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Display is using sRGB colourspace");
551  else
552  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Display has custom colourspace");
553 
554  InitHDR();
555  }
556  }
557 
558  // Set the gui mode from database settings
559  int pixelwidth = m_resolution.width();
560  int pixelheight = m_resolution.height();
561  int mmwidth = m_physicalSize.width();
562  int mmheight = m_physicalSize.height();
563  double refreshrate = m_refreshRate;
564  double aspectratio = 0.0;
565  GetMythDB()->GetResolutionSetting("GuiVidMode", pixelwidth, pixelheight, aspectratio, refreshrate);
566  GetMythDB()->GetResolutionSetting("DisplaySize", mmwidth, mmheight);
567  m_guiMode = MythDisplayMode(pixelwidth, pixelheight, mmwidth, mmheight, -1.0, refreshrate);
568 
569  // Set default video mode
570  pixelwidth = pixelheight = 0;
571  GetMythDB()->GetResolutionSetting("TVVidMode", pixelwidth, pixelheight, aspectratio, refreshrate);
572  m_videoMode = MythDisplayMode(pixelwidth, pixelheight, mmwidth, mmheight, aspectratio, refreshrate);
573 
574  // Initialise video override modes
575  for (int i = 0; true; ++i)
576  {
577  int iw = 0;
578  int ih = 0;
579  int ow = 0;
580  int oh = 0;
581  double iaspect = 0.0;
582  double oaspect = 0.0;
583  double irate = 0.0;
584  double orate = 0.0;
585 
586  GetMythDB()->GetResolutionSetting("VidMode", iw, ih, iaspect, irate, i);
587  GetMythDB()->GetResolutionSetting("TVVidMode", ow, oh, oaspect, orate, i);
588 
589  if (!(iw || ih || !qFuzzyIsNull(irate)) || !(ih && ow && oh))
590  break;
591 
592  uint64_t key = MythDisplayMode::CalcKey(QSize(iw, ih), irate);
593  MythDisplayMode scr(QSize(ow, oh), QSize(mmwidth, mmheight), oaspect, orate);
594  m_overrideVideoModes[key] = scr;
595  }
596 }
597 
598 
607 {
608  const auto screens = QGuiApplication::screens();
609  for (auto * screen : qAsConst(screens))
610  {
611  auto dim = screen->geometry();
612  auto extra = MythDisplay::GetExtraScreenInfo(screen);
613  LOG(VB_GUI, LOG_INFO, LOC + QString("Screen %1: %2x%3 %4")
614  .arg(screen->name()).arg(dim.width()).arg(dim.height()).arg(extra));
615  }
616 
617  const auto * primary = QGuiApplication::primaryScreen();
618  if (!primary)
619  {
620  if (!screens.empty())
621  primary = screens.front();
622  if (!primary)
623  {
624  LOG(VB_GENERAL, LOG_ERR, LOC + "Qt has no screens!");
625  return;
626  }
627  }
628 
629  LOG(VB_GUI, LOG_INFO, LOC +QString("Primary screen: %1.").arg(primary->name()));
630 
631  auto numScreens = MythDisplay::GetScreenCount();
632  auto dim = primary->virtualSize();
633  LOG(VB_GUI, LOG_INFO, LOC + QString("Total desktop dim: %1x%2, over %3 screen[s].")
634  .arg(dim.width()).arg(dim.height()).arg(numScreens));
635 
637  {
638  LOG(VB_GUI, LOG_INFO, LOC + QString("Using entire desktop."));
639  m_screenBounds = primary->virtualGeometry();
640  return;
641  }
642 
643  if (GetMythDB()->GetBoolSetting("RunFrontendInWindow", false))
644  {
645  LOG(VB_GUI, LOG_INFO, LOC + "Running in a window");
646  // This doesn't include the area occupied by the
647  // Windows taskbar, or the Mac OS X menu bar and Dock
648  m_screenBounds = m_screen->availableGeometry();
649  }
650  else
651  {
652  m_screenBounds = m_screen->geometry();
653  }
654 
655  LOG(VB_GUI, LOG_INFO, LOC + QString("Using screen %1: %2x%3 at %4+%5")
656  .arg(m_screen->name()).arg(m_screenBounds.width()).arg(m_screenBounds.height())
657  .arg(m_screenBounds.left()).arg(m_screenBounds.top()));
658 }
659 
667 {
668  return Size.width() > m_resolution.width() || Size.height() > m_resolution.height();
669 }
670 
676 {
678  if (current == m_desktopMode)
679  return;
681 }
682 
686 bool MythDisplay::SwitchToVideo(QSize Size, double Rate)
687 {
688  if (!m_modeComplete)
690 
693  double targetrate = 0.0;
694  double aspectoverride = 0.0;
695 
696  // try to find video override mode
698  Size.width(), Size.height(), Rate);
699 
700  if (key != 0)
701  {
702  next = m_overrideVideoModes[key];
703  if (next.AspectRatio() > 0.0)
704  aspectoverride = next.AspectRatio();
705  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Found custom screen override %1x%2 Aspect %3")
706  .arg(next.Width()).arg(next.Height()).arg(aspectoverride));
707  }
708 
709  // If requested refresh rate is 0, attempt to match video fps
710  if (qFuzzyIsNull(next.RefreshRate()))
711  {
712  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Trying to match best refresh rate %1Hz")
713  .arg(Rate, 0, 'f', 3));
714  next.SetRefreshRate(Rate);
715  }
716 
717  // need to change video mode?
718  (void)MythDisplayMode::FindBestMatch(GetVideoModes(), next, targetrate);
719 
720  // If GSync or FreeSync are enabled, ignore refresh rate only changes.
721  // N.B. This check is not used when switching to GUI (which already ignores
722  // rate only changes) or switching back to the desktop (where we must reset
723  // the display to the original state).
724  if (m_vrrState && m_vrrState->Enabled())
725  {
726  if (next.Resolution() == current.Resolution())
727  {
728  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Ignoring mode switch to %1Hz - VRR enabled")
729  .arg(Rate, 0, 'f', 3));
730  return true;
731  }
732  LOG(VB_GENERAL, LOG_INFO, LOC + "Allowing mode switch with VRR enabled for new resolution");
733  }
734 
735  // No need for change
736  if ((next == current) && (MythDisplayMode::CompareRates(current.RefreshRate(), targetrate)))
737  {
738  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Using current mode %1x%2@%3Hz")
739  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate));
740  return true;
741  }
742 
743  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Trying mode %1x%2@%3Hz")
744  .arg(next.Width()).arg(next.Height()).arg(next.RefreshRate(), 0, 'f', 3));
745 
746  if (!SwitchToVideoMode(next.Resolution(), targetrate))
747  {
748  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to change mode to %1x%2@%3Hz")
749  .arg(next.Width()).arg(next.Height()).arg(next.RefreshRate(), 0, 'f', 3));
750  return false;
751  }
752 
753  if (next.Resolution() != m_resolution)
755 
756  // N.B. We used a computed aspect ratio unless overridden
757  m_aspectRatioOverride = aspectoverride > 0.0 ? aspectoverride : 0.0;
759  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Switched to %1x%2@%3Hz for video %4x%5")
760  .arg(m_resolution.width()).arg(m_resolution.height())
761  .arg(m_refreshRate, 0, 'f', 3).arg(Size.width()).arg(Size.height()));
763  return true;
764 }
765 
769 {
770  if (!m_modeComplete)
772 
773  // If the current resolution is the same as the GUI resolution then do nothing
774  // as refresh rate should not be critical for the GUI.
776  {
777  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Using %1x%2@%3Hz for GUI")
778  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate));
779  return true;
780  }
781 
783  {
784  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to change mode to %1x%2@%3Hz")
785  .arg(m_guiMode.Width()).arg(m_guiMode.Height()).arg(m_guiMode.RefreshRate(), 0, 'f', 3));
786  return false;
787  }
788 
789  if (Wait && (m_resolution != m_guiMode.Resolution()))
791 
793  m_aspectRatioOverride = 0.0;
794  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Switched to %1x%2@%3Hz")
795  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate, 0, 'f', 3));
796  return true;
797 }
798 
800 {
801  return m_refreshRate;
802 }
803 
804 std::chrono::microseconds MythDisplay::GetRefreshInterval(std::chrono::microseconds Fallback) const
805 {
806  // If FreeSync or GSync are enabled, return the maximum refresh rate.
807  // N.B. This may need more work as the max may not be well defined - especially
808  // if the resolution is changing. Displays should however support at least 60Hz
809  // at all resolutions which should be fine in the vast majority of cases (as the
810  // only place the refresh interval is functionally important is in checking
811  // for double rate deinterlacing support).
812  if (m_vrrState && m_vrrState->Enabled())
813  {
814  const auto range = m_vrrState->GetRange();
815  auto max = std::get<1>(range) > 60 ? std::get<1>(range) : 60;
816  return microsecondsFromFloat(1000000.0 / max);
817  }
818 
819  if (m_refreshRate > 20.0 && m_refreshRate < 200.0)
820  return microsecondsFromFloat(1000000.0 / m_refreshRate);
821  if (Fallback > 33ms) // ~30Hz
822  Fallback /= 2;
823  return Fallback;
824 }
825 
827 {
828  auto targetrate = static_cast<double>(NAN);
829  const MythDisplayMode mode(Size, QSize(0, 0), -1.0, 0.0);
830  const auto & modes = GetVideoModes();
831  int match = MythDisplayMode::FindBestMatch(modes, mode, targetrate);
832  if (match < 0)
833  return {};
834  return modes[static_cast<size_t>(match)].RefreshRates();
835 }
836 
837 bool MythDisplay::SwitchToVideoMode(QSize /*Size*/, double /*Framerate*/)
838 {
839  return false;
840 }
841 
843 {
844  return m_videoModes;
845 }
846 
865 double MythDisplay::GetAspectRatio(QString &Source, bool IgnoreModeOverride)
866 {
867  auto valid = [](double Aspect) { return (Aspect > 0.1 && Aspect < 10.0); };
868 
869  // Override for this video mode
870  // Is this behaviour still needed?
871  if (!IgnoreModeOverride && valid(m_aspectRatioOverride))
872  {
873  Source = tr("Video mode override");
874  return m_aspectRatioOverride;
875  }
876 
877  // General override for invalid/misleading EDIDs or multiscreen setups
878  // New default of -1.0 equates to square pixels for modern displays
879  bool multiscreen = MythDisplay::SpanAllScreens() && GetScreenCount() > 1;
880  double override = gCoreContext->GetFloatSettingOnHost("XineramaMonitorAspectRatio",
881  gCoreContext->GetHostName(), -1.0);
882 
883  // Zero (not valid) indicates auto
884  if (valid(override))
885  {
886  Source = tr("Override");
887  return override;
888  }
889 
890  // Auto for multiscreen is a best guess
891  if (multiscreen)
892  {
893  double aspect = EstimateVirtualAspectRatio();
894  if (valid(aspect))
895  {
896  Source = tr("Multiscreen estimate");
897  return aspect;
898  }
899  }
900 
901  double calculated = m_resolution.isEmpty() ? 0.0 :
902  static_cast<double>(m_resolution.width()) / m_resolution.height();
903  double detected = m_physicalSize.isEmpty() ? 0.0 :
904  static_cast<double>(m_physicalSize.width()) / m_physicalSize.height();
905 
906  // Assume pixel aspect ratio is 1 (square pixels)
907  if (valid(calculated))
908  {
909  if ((override < 0.0) || !valid(detected))
910  {
911  Source = tr("Square pixels");
912  return calculated;
913  }
914  }
915 
916  // Based on actual physical size if available
917  if (valid(detected))
918  {
919  Source = tr("Detected");
920  return detected;
921  }
922 
923  // the aspect ratio of last resort
924  Source = tr("Guessed");
925  return 16.0 / 9.0;
926 }
927 
929 {
930  return m_edid;
931 }
932 
934 {
935  return m_hdrState;
936 }
937 
939 {
940  if (m_edid.Valid())
941  {
942  auto hdrdesc = m_edid.GetHDRSupport();
943  m_hdrState = MythHDR::Create(this, hdrdesc);
944  LOG(VB_GENERAL, LOG_NOTICE, LOC + QString("Supported HDR formats: %1")
945  .arg(m_hdrState->TypesToString().join(",")));
946  if (auto brightness = m_hdrState->GetMaxLuminance(); brightness > 1.0)
947  {
948  LOG(VB_GENERAL, LOG_NOTICE, LOC + QString("Display reports max brightness of %1 nits")
949  .arg(static_cast<int>(brightness)));
950  }
951  }
952 }
953 
964 {
965  auto sortscreens = [](const QScreen* First, const QScreen* Second)
966  {
967  if (First->geometry().left() < Second->geometry().left())
968  return true;
969  if (First->geometry().top() < Second->geometry().top())
970  return true;
971  return false;
972  };
973 
974  // default
975  double result = 16.0 / 9.0;
976 
977  QList<QScreen*> screens;
978  if (m_screen)
979  screens = m_screen->virtualSiblings();
980  if (screens.empty())
981  return result;
982 
983  // N.B. This sorting may not be needed
984  std::sort(screens.begin(), screens.end(), sortscreens);
985  QList<double> aspectratios;
986  QSize totalresolution;
987  int lasttop = 0;
988  int lastleft = 0;
989  int rows = 1;
990  int columns = 1;
991  for (auto it = screens.constBegin() ; it != screens.constEnd(); ++it)
992  {
993  QRect geom = (*it)->geometry();
994  totalresolution += geom.size();
995  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("%1x%2+%3+%4 %5")
996  .arg(geom.width()).arg(geom.height()).arg(geom.left()).arg(geom.top())
997  .arg((*it)->physicalSize().width() / (*it)->physicalSize().height()));
998  if (lastleft < geom.left())
999  {
1000  columns++;
1001  lastleft = geom.left();
1002  }
1003  if (lasttop < geom.top())
1004  {
1005  rows++;
1006  lasttop = geom.top();
1007  lastleft = 0;
1008  }
1009  aspectratios << (*it)->physicalSize().width() / (*it)->physicalSize().height();
1010  }
1011 
1012  // If all else fails, use the total resolution and assume pixel aspect ratio
1013  // equals display aspect ratio
1014  if (!totalresolution.isEmpty())
1015  result = static_cast<double>(totalresolution.width()) / totalresolution.height();
1016 
1017  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Screen layout: %1x%2").arg(rows).arg(columns));
1018  if (rows == columns)
1019  {
1020  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Grid layout");
1021  }
1022  else if (rows == 1 && columns > 1)
1023  {
1024  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Horizontal layout");
1025  }
1026  else if (columns == 1 && rows > 1)
1027  {
1028  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Vertical layout");
1029  }
1030  else
1031  {
1032  LOG(VB_GENERAL, LOG_INFO,
1033  LOC + QString("Unsupported layout - defaulting to %1 (%2/%3)")
1034  .arg(result).arg(totalresolution.width()).arg(totalresolution.height()));
1035  return result;
1036  }
1037 
1038  // validate aspect ratios - with a little fuzzyness
1039  double aspectratio = 0.0;
1040  double average = 0.0;
1041  int count = 1;
1042  for (auto it2 = aspectratios.constBegin() ; it2 != aspectratios.constEnd(); ++it2, ++count)
1043  {
1044  aspectratio += *it2;
1045  average = aspectratio / count;
1046  if (qAbs(*it2 - average) > 0.1)
1047  {
1048  LOG(VB_GENERAL, LOG_INFO, LOC +
1049  QString("Inconsistent aspect ratios - defaulting to %1 (%2/%3)")
1050  .arg(result).arg(totalresolution.width()).arg(totalresolution.height()));
1051  return result;
1052  }
1053  }
1054 
1055  aspectratio = (average * columns) / rows;
1056  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Estimated aspect ratio: %1")
1057  .arg(aspectratio));
1058  return aspectratio;
1059 }
1060 
1062 {
1063  return m_resolution;
1064 }
1065 
1067 {
1068  return m_physicalSize;
1069 }
1070 
1072 {
1073  // Some implementations may have their own mechanism for ensuring the mode
1074  // is updated before continuing
1075  if (!m_waitForModeChanges)
1076  return;
1077 
1078  LOG(VB_GENERAL, LOG_INFO, LOC + "Waiting for resolution change");
1079  QEventLoop loop;
1080  QTimer timer;
1081  timer.setSingleShot(true);
1082  connect(&timer, &QTimer::timeout, [](){ LOG(VB_GENERAL, LOG_WARNING, LOC + "Timed out wating for screen change"); });
1083  QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
1084  QObject::connect(m_screen, &QScreen::geometryChanged, &loop, &QEventLoop::quit);
1085  // 500ms maximum wait
1086  timer.start(500ms);
1087  loop.exec();
1088 }
1089 
1091 {
1092  // N.B. This isn't working as intended as it always times out rather than
1093  // exiting deliberately. It does however somehow filter out unwanted screenChanged
1094  // events that otherwise often put the widget in the wrong screen.
1095  // Needs more investigation - but for now it works:)
1096  if (!m_widget || !m_widget->windowHandle())
1097  return;
1098  LOG(VB_GENERAL, LOG_INFO, LOC + "Waiting for new screen");
1099  QEventLoop loop;
1100  QTimer timer;
1101  timer.setSingleShot(true);
1102  connect(&timer, &QTimer::timeout, [](){ LOG(VB_GENERAL, LOG_WARNING, LOC + "Timed out waiting for new screen"); });
1103  QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
1104  QObject::connect(m_widget->windowHandle(), &QWindow::screenChanged, &loop, &QEventLoop::quit);
1105  // 500ms maximum wait
1106  timer.start(500ms);
1107  loop.exec();
1108 }
1109 
1111 {
1112  int pauselengthinms = gCoreContext->GetNumSetting("VideoModeChangePauseMS", 0);
1113  if (pauselengthinms)
1114  {
1115  LOG(VB_GENERAL, LOG_INFO, LOC +
1116  QString("Pausing %1ms for video mode switch").arg(pauselengthinms));
1117  QEventLoop loop;
1118  QTimer timer;
1119  timer.setSingleShot(true);
1120  QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
1121  // 500ms maximum wait
1122  timer.start(pauselengthinms);
1123  loop.exec();
1124  }
1125 }
1126 
1128 {
1129  // This is intentionally formatted to match the output of xrandr for comparison
1130  if (VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_INFO))
1131  {
1132  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Available modes:");
1133  for (auto it = m_videoModes.crbegin(); it != m_videoModes.crend(); ++it)
1134  {
1135  auto rates = (*it).RefreshRates();
1136  QStringList rateslist;
1137  for (auto it2 = rates.crbegin(); it2 != rates.crend(); ++it2)
1138  rateslist.append(QString("%1").arg(*it2, 2, 'f', 2, '0'));
1139  if (rateslist.empty())
1140  rateslist.append("Variable rate?");
1141  LOG(VB_PLAYBACK, LOG_INFO, QString("%1x%2\t%3")
1142  .arg((*it).Width()).arg((*it).Height()).arg(rateslist.join("\t")));
1143  }
1144  }
1145 }
1146 
1152 void MythDisplay::ConfigureQtGUI(int SwapInterval, const MythCommandLineParser& CmdLine)
1153 {
1154  auto forcevrr = CmdLine.toBool("vrr");
1155  bool gsyncchanged = false;
1156  bool freesyncchanged = false;
1157 
1158 #ifdef USING_QTWEBENGINE
1159  QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
1160 #endif
1161 
1162  // Set the default surface format. Explicitly required on some platforms.
1163  QSurfaceFormat format;
1164  // Allow overriding the default depth - use with caution as Qt will likely
1165  // crash if it cannot find a matching visual.
1166  if (qEnvironmentVariableIsSet("MYTHTV_DEPTH"))
1167  {
1168  // Note: Don't set depth and stencil to give Qt as much flexibility as possible
1169  int depth = qBound(6, qEnvironmentVariableIntValue("MYTHTV_DEPTH"), 16);
1170  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Trying to force depth to '%1'").arg(depth));
1171  format.setRedBufferSize(depth);
1172  }
1173  else
1174  {
1175  format.setDepthBufferSize(0);
1176  format.setStencilBufferSize(0);
1177  }
1178  format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
1179  format.setProfile(QSurfaceFormat::CompatibilityProfile);
1180  format.setSwapInterval(SwapInterval);
1181  QSurfaceFormat::setDefaultFormat(format);
1182 
1183 #ifdef Q_OS_MAC
1184  // Without this, we can't set focus to any of the CheckBoxSetting, and most
1185  // of the MythPushButton widgets, and they don't use the themed background.
1186  QApplication::setDesktopSettingsAware(false);
1187 #endif
1188 
1189 #if defined (USING_DRM) && defined (USING_QTPRIVATEHEADERS)
1190  // Avoid trying to setup DRM if we are definitely not going to use it.
1191 #ifdef USING_X11
1193 #endif
1194  {
1195 #ifdef USING_WAYLANDEXTRAS
1196  // When vt switching this still detects wayland servers, so disabled for now
1197  //if (!MythWaylandDevice::IsAvailable())
1198 #endif
1199  {
1200  MythDRMDevice::SetupDRM(CmdLine);
1201  freesyncchanged = MythDRMVRR::s_freeSyncResetOnExit;
1202  }
1203  }
1204 #endif
1205 
1206 #if defined (Q_OS_LINUX) && defined (USING_EGL) && defined (USING_X11)
1207  // We want to use EGL for VAAPI/MMAL/DRMPRIME rendering to ensure we
1208  // can use zero copy video buffers for the best performance.
1209  // To force Qt to use EGL we must set 'QT_XCB_GL_INTEGRATION' to 'xcb_egl'
1210  // and this must be done before any GUI is created. If the platform plugin is
1211  // not xcb then this should have no effect.
1212  // This does however break when using NVIDIA drivers - which do not support
1213  // EGL like other drivers so we try to check the EGL vendor - and we currently
1214  // have no need for EGL with NVIDIA (that may change however).
1215  // NOTE force using EGL by setting MYTHTV_FORCE_EGL
1216  // NOTE disable using EGL by setting MYTHTV_NO_EGL
1217  // NOTE We have no Qt platform information, window/surface or logging when this is called.
1218  QString soft = qgetenv("LIBGL_ALWAYS_SOFTWARE");
1219  bool ignore = soft == "1" || soft.compare("true", Qt::CaseInsensitive) == 0;
1220  bool allow = qEnvironmentVariableIsEmpty("MYTHTV_NO_EGL") && !ignore;
1221  bool force = !qEnvironmentVariableIsEmpty("MYTHTV_FORCE_EGL");
1222  if ((force || allow) && MythDisplayX11::IsAvailable())
1223  {
1224  // N.B. By default, ignore EGL if vendor string is not returned
1225  QString vendor = MythEGL::GetEGLVendor();
1226  if (vendor.contains("nvidia", Qt::CaseInsensitive) && !force)
1227  {
1228  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Not requesting EGL for vendor '%1'").arg(vendor));
1229  }
1230  else if (!vendor.isEmpty() || force)
1231  {
1232  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Requesting EGL for vendor '%1'").arg(vendor));
1233  setenv("QT_XCB_GL_INTEGRATION", "xcb_egl", 0);
1234  }
1235  }
1236 #endif
1237 
1238 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1239  // Ignore desktop scaling
1240  QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
1241 #endif
1242 
1243 #ifdef USING_X11
1244  if (auto display = CmdLine.toString("display"); !display.isEmpty())
1246  // GSync support via libXNVCtrl
1247  // Note: FreeSync support is checked in MythDRMDevice::SetupDRM
1248  if (forcevrr)
1249  {
1250  MythGSync::ForceGSync(CmdLine.toUInt("vrr") > 0);
1251  gsyncchanged = MythGSync::s_gsyncResetOnExit;
1252  }
1253 #endif
1254 
1255  if (forcevrr && !(gsyncchanged || freesyncchanged))
1256  LOG(VB_GENERAL, LOG_INFO, LOC + "Variable refresh rate not adjusted");
1257 }
force
bool force
Definition: mythtv/programs/mythcommflag/main.cpp:72
MythDisplay::m_physicalSize
QSize m_physicalSize
Definition: mythdisplay.h:93
mythwaylandextras.h
mythdisplaymutter.h
MythHDRPtr
std::shared_ptr< class MythHDR > MythHDRPtr
Definition: mythhdr.h:30
MythDisplayMode::AspectRatio
double AspectRatio() const
Definition: mythdisplaymode.cpp:84
MythDisplay::GetRefreshRate
double GetRefreshRate() const
Definition: mythdisplay.cpp:799
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
MythDisplay::GetScreenBounds
QRect GetScreenBounds()
Definition: mythdisplay.cpp:306
MythVRR::Create
static MythVRRPtr Create(class MythDisplay *_Display)
Create a concrete implementation of MythVRR suitable for the given Display.
Definition: mythvrr.cpp:54
MythDisplay::GetEDID
MythEDID & GetEDID()
Definition: mythdisplay.cpp:928
MythCommandLineParser
Parent class for defining application command line parsers.
Definition: mythcommandlineparser.h:116
MythDisplay::SwitchToDesktop
void SwitchToDesktop()
Return the screen to the original desktop video mode.
Definition: mythdisplay.cpp:675
MythDisplay::m_screenBounds
QRect m_screenBounds
Definition: mythdisplay.h:108
MythDisplay::m_hdrState
MythHDRPtr m_hdrState
Definition: mythdisplay.h:99
MythDisplayMode::FindBestScreen
static uint64_t FindBestScreen(const DisplayModeMap &Map, int Width, int Height, double Rate)
Definition: mythdisplaymode.cpp:223
MythDisplay::DebugScreen
static void DebugScreen(QScreen *qScreen, const QString &Message)
Definition: mythdisplay.cpp:506
MythDisplay::GeometryChanged
static void GeometryChanged(QRect Geometry)
Definition: mythdisplay.cpp:456
mythdisplaywindows.h
MythDisplay::m_resolution
QSize m_resolution
Definition: mythdisplay.h:92
MythDisplay::ScreenChanged
virtual void ScreenChanged(QScreen *qScreen)
The actual screen in use has changed. We must use it.
Definition: mythdisplay.cpp:418
MythDisplayDRM
Definition: mythdisplaydrm.h:11
MythDisplayModes
std::vector< MythDisplayMode > MythDisplayModes
Definition: mythdisplaymode.h:18
MythDisplay::m_videoMode
MythDisplayMode m_videoMode
Definition: mythdisplay.h:111
MythDisplayMode::CalcKey
static uint64_t CalcKey(QSize Size, double Rate)
Definition: mythdisplaymode.cpp:127
microsecondsFromFloat
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::microseconds > microsecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:102
setenv
#define setenv(x, y, z)
Definition: compat.h:157
MythDisplayX11::IsAvailable
static bool IsAvailable()
Definition: mythdisplayx11.cpp:17
types
static const struct wl_interface * types[]
Definition: idle_inhibit_unstable_v1.c:39
MythDisplay::GetAspectRatio
double GetAspectRatio(QString &Source, bool IgnoreModeOverride=false)
Returns current screen aspect ratio.
Definition: mythdisplay.cpp:865
LOC
#define LOC
Definition: mythdisplay.cpp:44
MythDisplay::SpanAllScreens
static bool SpanAllScreens()
Return true if the MythTV windows should span all screens.
Definition: mythdisplay.cpp:490
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythDisplayRPI
Definition: mythdisplayrpi.h:16
MythDisplay::GetCurrentScreen
QScreen * GetCurrentScreen()
Return a pointer to the screen to use.
Definition: mythdisplay.cpp:323
GetMythDB
MythDB * GetMythDB(void)
Definition: mythdb.cpp:46
MythDisplay::ScreenRemoved
void ScreenRemoved(QScreen *qScreen)
Definition: mythdisplay.cpp:450
MythDisplay::GetPixelAspectRatio
double GetPixelAspectRatio()
Definition: mythdisplay.cpp:292
MythDisplay::PhysicalDPIChanged
void PhysicalDPIChanged(qreal DPI)
Definition: mythdisplay.cpp:432
MythDisplay::UpdateCurrentMode
virtual void UpdateCurrentMode()
Retrieve screen details.
Definition: mythdisplay.cpp:468
MythDisplay::InitScreenBounds
void InitScreenBounds()
Get screen size from Qt while respecting the user's multiscreen settings.
Definition: mythdisplay.cpp:606
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
MythDisplay::m_modeComplete
bool m_modeComplete
Definition: mythdisplay.h:89
MythDisplay::CurrentScreenChanged
void CurrentScreenChanged(QScreen *qScreen)
MythDisplay::GetHDRState
MythHDRPtr GetHDRState()
Definition: mythdisplay.cpp:933
MythDisplay::ConfigureQtGUI
static void ConfigureQtGUI(int SwapInterval, const MythCommandLineParser &CmdLine)
Shared static initialistaion code for all MythTV GUI applications.
Definition: mythdisplay.cpp:1152
MythDisplay::m_guiMode
MythDisplayMode m_guiMode
Definition: mythdisplay.h:110
mythdisplayosx.h
MythDisplay::DebugModes
void DebugModes() const
Definition: mythdisplay.cpp:1127
MythDisplay::GetGUIResolution
QSize GetGUIResolution()
Definition: mythdisplay.cpp:301
quit
@ quit
Definition: lirc_client.h:30
MythDisplayAndroid
Definition: mythdisplayandroid.h:7
MythEGL::GetEGLVendor
static QString GetEGLVendor(void)
Definition: mythegl.cpp:85
MythDisplay::PauseForModeSwitch
static void PauseForModeSwitch()
Definition: mythdisplay.cpp:1110
MythDisplay::m_aspectRatioOverride
double m_aspectRatioOverride
Definition: mythdisplay.h:91
mythdisplay.h
MythDisplay::GetResolution
QSize GetResolution()
Definition: mythdisplay.cpp:1061
MythDisplay::EstimateVirtualAspectRatio
double EstimateVirtualAspectRatio()
Estimate the overall display aspect ratio for multi screen setups.
Definition: mythdisplay.cpp:963
mythlogging.h
mythdisplayrpi.h
MythDisplay::WaitForNewScreen
void WaitForNewScreen()
Definition: mythdisplay.cpp:1090
Source
Definition: channelsettings.cpp:68
MythDisplay::~MythDisplay
~MythDisplay() override
Definition: mythdisplay.cpp:227
MythDRMVRR::s_freeSyncResetOnExit
static bool s_freeSyncResetOnExit
Definition: mythdrmvrr.h:11
MythDisplay::m_overrideVideoModes
DisplayModeMap m_overrideVideoModes
Definition: mythdisplay.h:112
mythdisplaydrm.h
MythDisplay::GetScreenCount
static int GetScreenCount()
Definition: mythdisplay.cpp:287
MythDisplay::GetExtraScreenInfo
static QString GetExtraScreenInfo(QScreen *qScreen)
Definition: mythdisplay.cpp:495
MythDisplayWindows
Definition: mythdisplaywindows.h:7
compat.h
MythDisplay::m_edid
MythEDID m_edid
Definition: mythdisplay.h:94
MythDisplay::m_window
QWindow * m_window
Definition: mythdisplay.h:96
MythEDID::GetHDRSupport
MythHDRDesc GetHDRSupport() const
Definition: mythedid.cpp:99
MythEDID::Valid
bool Valid() const
Definition: mythedid.cpp:39
MythDisplay::SetWidget
void SetWidget(QWidget *MainWindow)
Set the QWidget and QWindow in use.
Definition: mythdisplay.cpp:245
MythDisplay::SwitchToVideoMode
virtual bool SwitchToVideoMode(QSize Size, double Framerate)
Definition: mythdisplay.cpp:837
MythDisplayX11
Definition: mythdisplayx11.h:16
MythDisplay::SwitchToVideo
bool SwitchToVideo(QSize Size, double Rate=0.0)
Switches to the resolution and refresh rate defined in the database for the specified video resolutio...
Definition: mythdisplay.cpp:686
MythDisplay::GetPhysicalSize
QSize GetPhysicalSize()
Definition: mythdisplay.cpp:1066
MythCommandLineParser::toUInt
uint toUInt(const QString &key) const
Returns stored QVariant as an unsigned integer, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2144
MythDisplay::GetRefreshInterval
std::chrono::microseconds GetRefreshInterval(std::chrono::microseconds Fallback) const
Definition: mythdisplay.cpp:804
MythDisplay::m_waitForModeChanges
bool m_waitForModeChanges
Definition: mythdisplay.h:88
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
MythDisplay::m_videoModes
MythDisplayModes m_videoModes
Definition: mythdisplay.h:98
MythDisplay::GetRefreshRates
MythDisplayRates GetRefreshRates(QSize Size)
Definition: mythdisplay.cpp:826
MythDisplay
Definition: mythdisplay.h:22
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:936
MythEDID::IsSRGB
bool IsSRGB() const
Definition: mythedid.cpp:74
MythXDisplay::SetQtX11Display
static void SetQtX11Display(const QString &DisplayStr)
Definition: mythxdisplay.cpp:37
MythDisplayMode
Definition: mythdisplaymode.h:22
MythDisplay::ScreenAdded
void ScreenAdded(QScreen *qScreen)
Definition: mythdisplay.cpp:444
mythuihelper.h
MythDisplayMode::Height
int Height() const
Definition: mythdisplaymode.cpp:64
MythDisplayRates
std::vector< double > MythDisplayRates
Definition: mythdisplaymode.h:20
MythDisplay::GetVideoModes
virtual const MythDisplayModes & GetVideoModes()
Definition: mythdisplay.cpp:842
MythDisplay::m_refreshRate
double m_refreshRate
Definition: mythdisplay.h:90
VERBOSE_LEVEL_CHECK
#define VERBOSE_LEVEL_CHECK(_MASK_, _LEVEL_)
Definition: mythlogging.h:14
MythDisplay::Initialise
void Initialise()
Definition: mythdisplay.cpp:528
MythDisplay::NextModeIsLarger
bool NextModeIsLarger(QSize Size)
Check whether the next mode is larger in size than the current mode.
Definition: mythdisplay.cpp:666
MythUIScreenBounds::WindowIsAlwaysFullscreen
static bool WindowIsAlwaysFullscreen()
Return true if the current platform only supports fullscreen windows.
Definition: mythuiscreenbounds.cpp:114
MythDisplay::m_widget
QWidget * m_widget
Definition: mythdisplay.h:95
MythCommandLineParser::toString
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2252
MythHDR::Create
static MythHDRPtr Create(class MythDisplay *_Display, const MythHDRDesc &Desc)
Definition: mythhdr.cpp:29
mythcorecontext.h
MythCommandLineParser::toBool
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
Definition: mythcommandlineparser.cpp:2095
MythDisplay::SwitchToGUI
bool SwitchToGUI(bool Wait=false)
Switches to the GUI resolution.
Definition: mythdisplay.cpp:768
MythDisplay::ScreenCountChanged
void ScreenCountChanged(int Screens)
MythDisplayOSX
Definition: mythdisplayosx.h:10
MythDisplayMode::SetRefreshRate
void SetRefreshRate(double Rate)
Definition: mythdisplaymode.cpp:121
MythUIScreenBounds::GetGeometryOverride
static QRect GetGeometryOverride()
Definition: mythuiscreenbounds.cpp:24
MythDisplay::WaitForScreenChange
void WaitForScreenChange()
Definition: mythdisplay.cpp:1071
MythDisplayMode::RefreshRate
double RefreshRate() const
Definition: mythdisplaymode.cpp:95
mythdrmvrr.h
MythDisplayMode::CompareRates
static bool CompareRates(double First, double Second, double Precision=0.01)
Determine whether two rates are considered equal with the given precision.
Definition: mythdisplaymode.cpp:135
MythDisplay::m_initialised
bool m_initialised
Definition: mythdisplay.h:106
MythDisplay::m_screen
QScreen * m_screen
Definition: mythdisplay.h:97
mythegl.h
MythDisplay::m_desktopMode
MythDisplayMode m_desktopMode
Definition: mythdisplay.h:109
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:862
mythdisplayandroid.h
MythDisplayMode::Resolution
QSize Resolution() const
Definition: mythdisplaymode.cpp:54
mythnvcontrol.h
MythDisplay::GetDescription
QStringList GetDescription()
Definition: mythdisplay.cpp:135
MythDisplay::GetDesiredScreen
static QScreen * GetDesiredScreen()
Definition: mythdisplay.cpp:328
MythDisplayMode::FindBestMatch
static int FindBestMatch(const MythDisplayModes &Modes, const MythDisplayMode &Mode, double &TargetRate)
Definition: mythdisplaymode.cpp:140
MythDisplay::PrimaryScreenChanged
static void PrimaryScreenChanged(QScreen *qScreen)
Definition: mythdisplay.cpp:439
MythDisplayMode::Width
int Width() const
Definition: mythdisplaymode.cpp:59
MythDisplay::m_vrrState
MythVRRPtr m_vrrState
Definition: mythdisplay.h:100
mythdisplayx11.h
MythDisplay::VideoModesAvailable
virtual bool VideoModesAvailable()
Definition: mythdisplay.h:29
MythGSync::s_gsyncResetOnExit
static bool s_gsyncResetOnExit
Definition: mythnvcontrol.h:26
mythmainwindow.h
MythDisplay::MythDisplay
MythDisplay()
Definition: mythdisplay.cpp:208
MythDisplay::Create
static MythDisplay * Create(MythMainWindow *MainWindow)
Create a MythDisplay object appropriate for the current platform.
Definition: mythdisplay.cpp:80
MythMainWindow
Definition: mythmainwindow.h:35
MythCoreContext::GetFloatSettingOnHost
double GetFloatSettingOnHost(const QString &key, const QString &host, double defaultval=0.0)
Definition: mythcorecontext.cpp:976
MythDisplay::InitHDR
void InitHDR()
Definition: mythdisplay.cpp:938
MythUIScreenBounds::GeometryIsOverridden
static bool GeometryIsOverridden()
Definition: mythuiscreenbounds.cpp:19
MythGSync::ForceGSync
static void ForceGSync(bool Enable)
Enable or disable GSync before the main window is created.
Definition: mythnvcontrol.cpp:25
MythEDID
Definition: mythedid.h:21
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:922
MythDisplay::CurrentDPIChanged
void CurrentDPIChanged(qreal DPI)
MythDisplay::m_firstScreenChange
bool m_firstScreenChange
Definition: mythdisplay.h:107