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