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 Q_OS_ANDROID
18 #include "mythdisplayandroid.h"
19 #endif
20 #if defined(Q_OS_MAC)
21 #include "mythdisplayosx.h"
22 #endif
23 #ifdef USING_X11
24 #include "mythdisplayx11.h"
25 #endif
26 #ifdef USING_DRM
27 #include "mythdisplaydrm.h"
28 #endif
29 #if defined(Q_OS_WIN)
30 #include "mythdisplaywindows.h"
31 #endif
32 #ifdef USING_MMAL
33 #include "mythdisplayrpi.h"
34 #endif
35 
36 #define LOC QString("Display: ")
37 
71 {
72  static QMutex s_lock(QMutex::Recursive);
73  static MythDisplay* s_display = nullptr;
74 
75  QMutexLocker locker(&s_lock);
76 
77  if (Acquire)
78  {
79  if (s_display)
80  {
81  s_display->IncrRef();
82  }
83  else
84  {
85 #ifdef USING_X11
87  s_display = new MythDisplayX11();
88 #endif
89 #ifdef USING_MMAL
90  if (!s_display)
91  s_display = new MythDisplayRPI();
92 #endif
93 #ifdef USING_DRM
94  // this will only work by validating the screen's serial number
95  if (!s_display)
96  s_display = new MythDisplayDRM();
97 #endif
98 #if defined(Q_OS_MAC)
99  if (!s_display)
100  s_display = new MythDisplayOSX();
101 #endif
102 #ifdef Q_OS_ANDROID
103  if (!s_display)
104  s_display = new MythDisplayAndroid();
105 #endif
106 #if defined(Q_OS_WIN)
107  if (!s_display)
108  s_display = new MythDisplayWindows();
109 #endif
110  if (!s_display)
111  s_display = new MythDisplay();
112  }
113  }
114  else
115  {
116  if (s_display)
117  if (s_display->DecrRef() == 0)
118  s_display = nullptr;
119  }
120  return s_display;
121 }
122 
124 {
125  QStringList result;
126  bool spanall = false;
127  int screencount = MythDisplay::GetScreenCount();
129 
130  if (MythDisplay::SpanAllScreens() && screencount > 1)
131  {
132  spanall = true;
133  result.append(tr("Spanning %1 screens").arg(screencount));
134  result.append(tr("Total bounds") + QString("\t: %1x%2")
135  .arg(display->GetScreenBounds().width())
136  .arg(display->GetScreenBounds().height()));
137  result.append("");
138  }
139 
140  QScreen *current = display->GetCurrentScreen();
141  QList<QScreen*> screens = QGuiApplication::screens();
142  bool first = true;
143  for (auto *screen : qAsConst(screens))
144  {
145  if (!first)
146  result.append("");
147  first = false;
148  QString id = QString("(%1)").arg(screen->manufacturer());
149  if (screen == current && !spanall)
150  result.append(tr("Current screen %1 %2:").arg(screen->name()).arg(id));
151  else
152  result.append(tr("Screen %1 %2:").arg(screen->name()).arg(id));
153  result.append(tr("Size") + QString("\t\t: %1mmx%2mm")
154  .arg(screen->physicalSize().width()).arg(screen->physicalSize().height()));
155  if (screen == current)
156  {
157  QString source;
158  double aspect = display->GetAspectRatio(source);
159  result.append(tr("Aspect ratio") + QString("\t: %1 (%2)")
160  .arg(aspect, 0, 'f', 3).arg(source));
161  if (!spanall)
162  {
163  result.append(tr("Current mode") + QString("\t: %1x%2@%3Hz")
164  .arg(display->GetResolution().width()).arg(display->GetResolution().height())
165  .arg(display->GetRefreshRate(), 0, 'f', 2));
166  }
167  }
168  }
170  return result;
171 }
172 
174  : ReferenceCounter("Display")
175 {
177  DebugScreen(m_screen, "Using");
178  if (m_screen)
179  {
180  connect(m_screen, &QScreen::geometryChanged, this, &MythDisplay::GeometryChanged);
181  connect(m_screen, &QScreen::physicalDotsPerInchChanged, this, &MythDisplay::PhysicalDPIChanged);
182  }
183 
184  auto *guiapp = qobject_cast<QGuiApplication *>(QCoreApplication::instance());
185  if (guiapp == nullptr)
186  return;
187 
188  connect(guiapp, &QGuiApplication::screenRemoved, this, &MythDisplay::ScreenRemoved);
189  connect(guiapp, &QGuiApplication::screenAdded, this, &MythDisplay::ScreenAdded);
190  connect(guiapp, &QGuiApplication::primaryScreenChanged, this, &MythDisplay::PrimaryScreenChanged);
191 }
192 
194 {
195  LOG(VB_GENERAL, LOG_INFO, LOC + "Deleting");
196 }
197 
211 void MythDisplay::SetWidget(QWidget *MainWindow)
212 {
213  QWidget* oldwidget = m_widget;
214  m_widget = MainWindow;
215  if (!m_modeComplete)
217 
218  QWindow* oldwindow = m_window;
219  if (m_widget)
220  m_window = m_widget->windowHandle();
221  else
222  m_window = nullptr;
223 
224  if (m_widget && (m_widget != oldwidget))
225  LOG(VB_GENERAL, LOG_INFO, LOC + "Have main widget");
226 
227  if (m_window && (m_window != oldwindow))
228  {
229  LOG(VB_GENERAL, LOG_INFO, LOC + "Have main window");
230 
231  connect(m_window, &QWindow::screenChanged, this, &MythDisplay::ScreenChanged, Qt::UniqueConnection);
232  QScreen *desired = GetDesiredScreen();
233  // If we have changed the video mode for the old screen then reset
234  // it to the default/desktop mode
235  SwitchToDesktop();
236  // Ensure we completely re-initialise when the new screen is set
237  m_initialised = false;
238  if (desired != m_screen)
239  DebugScreen(desired, "Moving to");
240  m_window->setScreen(desired);
241  // WaitForNewScreen doesn't work as intended. It successfully filters
242  // out unwanted screenChanged signals after moving screens - but always
243  //times out. This just delays startup by 500ms - so ignore on startup as it isn't needed.
244  if (!m_firstScreenChange)
246  m_firstScreenChange = false;
248  return;
249  }
250 }
251 
253 {
254  return QGuiApplication::screens().size();
255 }
256 
258 {
259  if (m_physicalSize.isEmpty() || m_resolution.isEmpty())
260  return 1.0;
261 
262  return (m_physicalSize.width() / static_cast<double>(m_resolution.width())) /
263  (m_physicalSize.height() / static_cast<double>(m_resolution.height()));
264 }
265 
267 {
268  return m_guiMode.Resolution();
269 }
270 
272 {
273  return m_screenBounds;
274 }
275 
289 {
290  return m_screen;
291 }
292 
294 {
295  QScreen* newscreen = nullptr;
296 
297  // If geometry is overriden at the command line level, try and determine
298  // which screen that applies to (if any).
299  // N.B. So many potential issues here e.g. should the geometry override be
300  // ignored after first use? (as it will continue to override the screen
301  // regardless of changes to screen preference).
303  {
304  // this matches the check in MythMainWindow
305  bool windowed = GetMythDB()->GetBoolSetting("RunFrontendInWindow", false) &&
307  QRect override = MythUIHelper::GetGeometryOverride();
308  // When windowed, we use topleft as a best guess as to which screen we belong in.
309  // When fullscreen, Qt appears to use the reverse - though this may be
310  // the window manager rather than Qt. So could be wrong.
311  QPoint point = windowed ? override.topLeft() : override.bottomRight();
312  for (QScreen *screen : QGuiApplication::screens())
313  {
314  if (screen->geometry().contains(point))
315  {
316  newscreen = screen;
317  LOG(VB_GENERAL, LOG_INFO, LOC + QString(
318  "Geometry override places window in screen '%1'").arg(newscreen->name()));
319  break;
320  }
321  }
322  }
323 
324  // If spanning all screens, then always use the primary display
325  if (!newscreen && MythDisplay::SpanAllScreens())
326  {
327  LOG(VB_GENERAL, LOG_INFO, LOC + "Using primary screen for multiscreen");
328  newscreen = QGuiApplication::primaryScreen();
329  }
330 
331  QString name = gCoreContext->GetSetting("XineramaScreen", nullptr);
332  // Lookup by name
333  if (!newscreen)
334  {
335  for (QScreen *screen : QGuiApplication::screens())
336  {
337  if (!name.isEmpty() && name == screen->name())
338  {
339  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Found screen '%1'").arg(name));
340  newscreen = screen;
341  }
342  }
343  }
344 
345  // No name match. These were previously numbers.
346  if (!newscreen)
347  {
348  bool ok = false;
349  int screen_num = name.toInt(&ok);
350  QList<QScreen *>screens = QGuiApplication::screens();
351  if (ok && (screen_num >= 0) && (screen_num < screens.size()))
352  {
353  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Found screen number %1 (%2)")
354  .arg(name).arg(screens[screen_num]->name()));
355  newscreen = screens[screen_num];
356  }
357  }
358 
359  // For anything else, return the primary screen.
360  if (!newscreen)
361  {
362  QScreen *primary = QGuiApplication::primaryScreen();
363  if (name.isEmpty() && primary)
364  {
365  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Defaulting to primary screen (%1)")
366  .arg(primary->name()));
367  }
368  else if (name != "-1" && primary)
369  {
370  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Screen '%1' not found, defaulting to primary screen (%2)")
371  .arg(name).arg(primary->name()));
372  }
373  newscreen = primary;
374  }
375 
376  return newscreen;
377 }
378 
381 void MythDisplay::ScreenChanged(QScreen *qScreen)
382 {
383  if (qScreen == m_screen)
384  return;
385  if (m_screen)
386  disconnect(m_screen, nullptr, this, nullptr);
387  DebugScreen(qScreen, "Changed to");
388  m_screen = qScreen;
389  connect(m_screen, &QScreen::geometryChanged, this, &MythDisplay::GeometryChanged);
390  connect(m_screen, &QScreen::physicalDotsPerInchChanged, this, &MythDisplay::PhysicalDPIChanged);
391  Initialise();
392  emit CurrentScreenChanged(qScreen);
393 }
394 
396 {
397  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Qt screen pixel ratio changed to %1")
398  .arg(DPI, 2, 'f', 2, '0'));
399  emit CurrentDPIChanged(DPI);
400 }
401 
402 void MythDisplay::PrimaryScreenChanged(QScreen* qScreen)
403 {
404  DebugScreen(qScreen, "New primary");
405 }
406 
407 void MythDisplay::ScreenAdded(QScreen* qScreen)
408 {
409  DebugScreen(qScreen, "New");
410  emit ScreenCountChanged(QGuiApplication::screens().size());
411 }
412 
413 void MythDisplay::ScreenRemoved(QScreen* qScreen)
414 {
415  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Screen '%1' removed").arg(qScreen->name()));
416  emit ScreenCountChanged(QGuiApplication::screens().size());
417 }
418 
419 void MythDisplay::GeometryChanged(const QRect &Geo)
420 {
421  LOG(VB_GENERAL, LOG_INFO, LOC + QString("New screen geometry: %1x%2+%3+%4")
422  .arg(Geo.width()).arg(Geo.height()).arg(Geo.left()).arg(Geo.top()));
423 }
424 
432 {
433  // Certain platform implementations do not have a window to access at startup
434  // and hence use this implementation. Flag the status as incomplete to ensure
435  // we try to retrieve the full details at the first opportunity.
436  m_modeComplete = false;
437  m_edid = MythEDID();
438  QScreen *screen = GetCurrentScreen();
439  if (!screen)
440  {
441  m_refreshRate = 60.0;
442  m_physicalSize = QSize(0, 0);
443  m_resolution = QSize(1920, 1080);
444  return;
445  }
446  m_refreshRate = screen->refreshRate();
447  m_resolution = screen->size();
448  m_physicalSize = QSize(static_cast<int>(screen->physicalSize().width()),
449  static_cast<int>(screen->physicalSize().height()));
450 }
451 
454 {
455  return gCoreContext->GetSetting("XineramaScreen", nullptr) == "-1";
456 }
457 
458 QString MythDisplay::GetExtraScreenInfo(QScreen *qScreen)
459 {
460  QString mfg = qScreen->manufacturer();
461  if (mfg.isEmpty())
462  mfg = "Unknown";
463  QString model = qScreen->model();
464  if (model.isEmpty())
465  model = "Unknown";
466  return QString("(Make: %1 Model: %2)").arg(mfg).arg(model);
467 }
468 
469 void MythDisplay::DebugScreen(QScreen *qScreen, const QString &Message)
470 {
471  if (!qScreen)
472  return;
473 
474  QRect geom = qScreen->geometry();
475  QString extra = GetExtraScreenInfo(qScreen);
476 
477  LOG(VB_GENERAL, LOG_INFO, LOC + QString("%1 screen '%2' %3")
478  .arg(Message).arg(qScreen->name()).arg(extra));
479  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Qt screen pixel ratio: %1")
480  .arg(qScreen->devicePixelRatio(), 2, 'f', 2, '0'));
481  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Geometry: %1x%2+%3+%4 Size(Qt): %5mmx%6mm")
482  .arg(geom.width()).arg(geom.height()).arg(geom.left()).arg(geom.top())
483  .arg(qScreen->physicalSize().width()).arg(qScreen->physicalSize().height()));
484 
485  if (qScreen->virtualGeometry() != geom)
486  {
487  geom = qScreen->virtualGeometry();
488  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Total virtual geometry: %1x%2+%3+%4")
489  .arg(geom.width()).arg(geom.height()).arg(geom.left()).arg(geom.top()));
490  }
491 }
492 
494 {
495  m_videoModes.clear();
496  m_overrideVideoModes.clear();
499 
500  // Set the desktop mode - which is the mode at startup. We must always return
501  // the screen to this mode.
502  if (!m_initialised)
503  {
504  // Only ever set this once or after a screen change
505  m_initialised = true;
507  LOG(VB_GENERAL, LOG_NOTICE, LOC + QString("Desktop video mode: %1x%2 %3Hz")
508  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate, 0, 'f', 3));
509  if (m_edid.Valid())
510  {
511  if (m_edid.IsSRGB())
512  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Display is using sRGB colourspace");
513  else
514  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Display has custom colourspace");
515  }
516  }
517 
518  // Set the gui mode from database settings
519  int pixelwidth = m_resolution.width();
520  int pixelheight = m_resolution.height();
521  int mmwidth = m_physicalSize.width();
522  int mmheight = m_physicalSize.height();
523  double refreshrate = m_refreshRate;
524  double aspectratio = 0.0;
525  GetMythDB()->GetResolutionSetting("GuiVidMode", pixelwidth, pixelheight, aspectratio, refreshrate);
526  GetMythDB()->GetResolutionSetting("DisplaySize", mmwidth, mmheight);
527  m_guiMode = MythDisplayMode(pixelwidth, pixelheight, mmwidth, mmheight, -1.0, refreshrate);
528 
529  // Set default video mode
530  pixelwidth = pixelheight = 0;
531  GetMythDB()->GetResolutionSetting("TVVidMode", pixelwidth, pixelheight, aspectratio, refreshrate);
532  m_videoMode = MythDisplayMode(pixelwidth, pixelheight, mmwidth, mmheight, aspectratio, refreshrate);
533 
534  // Initialise video override modes
535  for (int i = 0; true; ++i)
536  {
537  int iw = 0;
538  int ih = 0;
539  int ow = 0;
540  int oh = 0;
541  double iaspect = 0.0;
542  double oaspect = 0.0;
543  double irate = 0.0;
544  double orate = 0.0;
545 
546  GetMythDB()->GetResolutionSetting("VidMode", iw, ih, iaspect, irate, i);
547  GetMythDB()->GetResolutionSetting("TVVidMode", ow, oh, oaspect, orate, i);
548 
549  if (!(iw || ih || !qFuzzyIsNull(irate)) || !(ih && ow && oh))
550  break;
551 
552  uint64_t key = MythDisplayMode::CalcKey(QSize(iw, ih), irate);
553  MythDisplayMode scr(QSize(ow, oh), QSize(mmwidth, mmheight), oaspect, orate);
554  m_overrideVideoModes[key] = scr;
555  }
556 }
557 
558 
567 {
568  QList<QScreen*> screens = QGuiApplication::screens();
569  for (auto *screen : screens)
570  {
571  QRect dim = screen->geometry();
572  QString extra = MythDisplay::GetExtraScreenInfo(screen);
573  LOG(VB_GUI, LOG_INFO, LOC + QString("Screen %1: %2x%3 %4")
574  .arg(screen->name()).arg(dim.width()).arg(dim.height()).arg(extra));
575  }
576 
577  QScreen *primary = QGuiApplication::primaryScreen();
578  LOG(VB_GUI, LOG_INFO, LOC +QString("Primary screen: %1.").arg(primary->name()));
579 
580  int numScreens = MythDisplay::GetScreenCount();
581  QSize dim = primary->virtualSize();
582  LOG(VB_GUI, LOG_INFO, LOC + QString("Total desktop dim: %1x%2, over %3 screen[s].")
583  .arg(dim.width()).arg(dim.height()).arg(numScreens));
584 
586  {
587  LOG(VB_GUI, LOG_INFO, LOC + QString("Using entire desktop."));
588  m_screenBounds = primary->virtualGeometry();
589  return;
590  }
591 
592  if (GetMythDB()->GetBoolSetting("RunFrontendInWindow", false))
593  {
594  LOG(VB_GUI, LOG_INFO, LOC + "Running in a window");
595  // This doesn't include the area occupied by the
596  // Windows taskbar, or the Mac OS X menu bar and Dock
597  m_screenBounds = m_screen->availableGeometry();
598  }
599  else
600  {
601  m_screenBounds = m_screen->geometry();
602  }
603 
604  LOG(VB_GUI, LOG_INFO, LOC + QString("Using screen %1: %2x%3 at %4+%5")
605  .arg(m_screen->name()).arg(m_screenBounds.width()).arg(m_screenBounds.height())
606  .arg(m_screenBounds.left()).arg(m_screenBounds.top()));
607 }
608 
616 {
617  return Size.width() > m_resolution.width() || Size.height() > m_resolution.height();
618 }
619 
625 {
627  if (current == m_desktopMode)
628  return;
630 }
631 
635 bool MythDisplay::SwitchToVideo(QSize Size, double Rate)
636 {
637  if (!m_modeComplete)
639 
642  double targetrate = 0.0;
643  double aspectoverride = 0.0;
644 
645  // try to find video override mode
647  Size.width(), Size.height(), Rate);
648 
649  if (key != 0)
650  {
651  next = m_overrideVideoModes[key];
652  if (next.AspectRatio() > 0.0)
653  aspectoverride = next.AspectRatio();
654  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Found custom screen override %1x%2 Aspect %3")
655  .arg(next.Width()).arg(next.Height()).arg(aspectoverride));
656  }
657 
658  // If requested refresh rate is 0, attempt to match video fps
659  if (qFuzzyIsNull(next.RefreshRate()))
660  {
661  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Trying to match best refresh rate %1Hz")
662  .arg(Rate, 0, 'f', 3));
663  next.SetRefreshRate(Rate);
664  }
665 
666  // need to change video mode?
668  if ((next == current) && (MythDisplayMode::CompareRates(current.RefreshRate(), targetrate)))
669  {
670  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Using current mode %1x%2@%3Hz")
671  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate));
672  return true;
673  }
674 
675  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Trying mode %1x%2@%3Hz")
676  .arg(next.Width()).arg(next.Height()).arg(next.RefreshRate(), 0, 'f', 3));
677 
678  if (!SwitchToVideoMode(next.Resolution(), targetrate))
679  {
680  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to change mode to %1x%2@%3Hz")
681  .arg(next.Width()).arg(next.Height()).arg(next.RefreshRate(), 0, 'f', 3));
682  return false;
683  }
684 
685  if (next.Resolution() != m_resolution)
687 
688  // N.B. We used a computed aspect ratio unless overridden
689  m_aspectRatioOverride = aspectoverride > 0.0 ? aspectoverride : 0.0;
691  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Switched to %1x%2@%3Hz for video %4x%5")
692  .arg(m_resolution.width()).arg(m_resolution.height())
693  .arg(m_refreshRate, 0, 'f', 3).arg(Size.width()).arg(Size.height()));
695  return true;
696 }
697 
701 {
702  if (!m_modeComplete)
704 
705  // If the current resolution is the same as the GUI resolution then do nothing
706  // as refresh rate should not be critical for the GUI.
708  {
709  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Using %1x%2@%3Hz for GUI")
710  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate));
711  return true;
712  }
713 
715  {
716  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to change mode to %1x%2@%3Hz")
717  .arg(m_guiMode.Width()).arg(m_guiMode.Height()).arg(m_guiMode.RefreshRate(), 0, 'f', 3));
718  return false;
719  }
720 
721  if (Wait && (m_resolution != m_guiMode.Resolution()))
723 
725  m_aspectRatioOverride = 0.0;
726  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Switched to %1x%2@%3Hz")
727  .arg(m_resolution.width()).arg(m_resolution.height()).arg(m_refreshRate, 0, 'f', 3));
728  return true;
729 }
730 
731 double MythDisplay::GetRefreshRate(void) const
732 {
733  return m_refreshRate;
734 }
735 
736 int MythDisplay::GetRefreshInterval(int Fallback) const
737 {
738  if (m_refreshRate > 20.0 && m_refreshRate < 200.0)
739  return static_cast<int>(lround(1000000.0 / m_refreshRate));
740  if (Fallback > 33000) // ~30Hz
741  Fallback /= 2;
742  return Fallback;
743 }
744 
745 std::vector<double> MythDisplay::GetRefreshRates(QSize Size)
746 {
747  auto targetrate = static_cast<double>(NAN);
748  const MythDisplayMode mode(Size, QSize(0, 0), -1.0, 0.0);
749  const vector<MythDisplayMode>& modes = GetVideoModes();
750  int match = MythDisplayMode::FindBestMatch(modes, mode, targetrate);
751  if (match < 0)
752  return std::vector<double>();
753  return modes[static_cast<size_t>(match)].RefreshRates();
754 }
755 
756 bool MythDisplay::SwitchToVideoMode(QSize /*Size*/, double /*Framerate*/)
757 {
758  return false;
759 }
760 
761 const vector<MythDisplayMode> &MythDisplay::GetVideoModes(void)
762 {
763  return m_videoModes;
764 }
765 
784 double MythDisplay::GetAspectRatio(QString &Source, bool IgnoreModeOverride)
785 {
786  auto valid = [](double Aspect) { return (Aspect > 0.1 && Aspect < 10.0); };
787 
788  // Override for this video mode
789  // Is this behaviour still needed?
790  if (!IgnoreModeOverride && valid(m_aspectRatioOverride))
791  {
792  Source = tr("Video mode override");
793  return m_aspectRatioOverride;
794  }
795 
796  // General override for invalid/misleading EDIDs or multiscreen setups
797  // New default of -1.0 equates to square pixels for modern displays
798  bool multiscreen = MythDisplay::SpanAllScreens() && GetScreenCount() > 1;
799  double override = gCoreContext->GetFloatSettingOnHost("XineramaMonitorAspectRatio",
800  gCoreContext->GetHostName(), -1.0);
801 
802  // Zero (not valid) indicates auto
803  if (valid(override))
804  {
805  Source = tr("Override");
806  return override;
807  }
808 
809  // Auto for multiscreen is a best guess
810  if (multiscreen)
811  {
812  double aspect = EstimateVirtualAspectRatio();
813  if (valid(aspect))
814  {
815  Source = tr("Multiscreen estimate");
816  return aspect;
817  }
818  }
819 
820  double calculated = m_resolution.isEmpty() ? 0.0 :
821  static_cast<double>(m_resolution.width()) / m_resolution.height();
822  double detected = m_physicalSize.isEmpty() ? 0.0 :
823  static_cast<double>(m_physicalSize.width()) / m_physicalSize.height();
824 
825  // Assume pixel aspect ratio is 1 (square pixels)
826  if (valid(calculated))
827  {
828  if ((override < 0.0) || !valid(detected))
829  {
830  Source = tr("Square pixels");
831  return calculated;
832  }
833  }
834 
835  // Based on actual physical size if available
836  if (valid(detected))
837  {
838  Source = tr("Detected");
839  return detected;
840  }
841 
842  // the aspect ratio of last resort
843  Source = tr("Guessed");
844  return 16.0 / 9.0;
845 }
846 
848 {
849  return m_edid;
850 }
851 
862 {
863  auto sortscreens = [](const QScreen* First, const QScreen* Second)
864  {
865  if (First->geometry().left() < Second->geometry().left())
866  return true;
867  if (First->geometry().top() < Second->geometry().top())
868  return true;
869  return false;
870  };
871 
872  // default
873  double result = 16.0 / 9.0;
874 
875  QList<QScreen*> screens;
876  if (m_screen)
877  screens = m_screen->virtualSiblings();
878  if (screens.empty())
879  return result;
880 
881  // N.B. This sorting may not be needed
882  std::sort(screens.begin(), screens.end(), sortscreens);
883  QList<double> aspectratios;
884  QSize totalresolution;
885  int lasttop = 0;
886  int lastleft = 0;
887  int rows = 1;
888  int columns = 1;
889  for (auto it = screens.constBegin() ; it != screens.constEnd(); ++it)
890  {
891  QRect geom = (*it)->geometry();
892  totalresolution += geom.size();
893  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("%1x%2+%3+%4 %5")
894  .arg(geom.width()).arg(geom.height()).arg(geom.left()).arg(geom.top())
895  .arg((*it)->physicalSize().width() / (*it)->physicalSize().height()));
896  if (lastleft < geom.left())
897  {
898  columns++;
899  lastleft = geom.left();
900  }
901  if (lasttop < geom.top())
902  {
903  rows++;
904  lasttop = geom.top();
905  lastleft = 0;
906  }
907  aspectratios << (*it)->physicalSize().width() / (*it)->physicalSize().height();
908  }
909 
910  // If all else fails, use the total resolution and assume pixel aspect ratio
911  // equals display aspect ratio
912  if (!totalresolution.isEmpty())
913  result = static_cast<double>(totalresolution.width()) / totalresolution.height();
914 
915  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Screen layout: %1x%2").arg(rows).arg(columns));
916  if (rows == columns)
917  {
918  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Grid layout");
919  }
920  else if (rows == 1 && columns > 1)
921  {
922  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Horizontal layout");
923  }
924  else if (columns == 1 && rows > 1)
925  {
926  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Vertical layout");
927  }
928  else
929  {
930  LOG(VB_GENERAL, LOG_INFO,
931  LOC + QString("Unsupported layout - defaulting to %1 (%2/%3)")
932  .arg(result).arg(totalresolution.width()).arg(totalresolution.height()));
933  return result;
934  }
935 
936  // validate aspect ratios - with a little fuzzyness
937  double aspectratio = 0.0;
938  double average = 0.0;
939  int count = 1;
940  for (auto it2 = aspectratios.constBegin() ; it2 != aspectratios.constEnd(); ++it2, ++count)
941  {
942  aspectratio += *it2;
943  average = aspectratio / count;
944  if (qAbs(*it2 - average) > 0.1)
945  {
946  LOG(VB_GENERAL, LOG_INFO, LOC +
947  QString("Inconsistent aspect ratios - defaulting to %1 (%2/%3)")
948  .arg(result).arg(totalresolution.width()).arg(totalresolution.height()));
949  return result;
950  }
951  }
952 
953  aspectratio = (average * columns) / rows;
954  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Estimated aspect ratio: %1")
955  .arg(aspectratio));
956  return aspectratio;
957 }
958 
960 {
961  return m_resolution;
962 }
963 
965 {
966  return m_physicalSize;
967 }
968 
970 {
971  // Some implementations may have their own mechanism for ensuring the mode
972  // is updated before continuing
974  return;
975 
976  LOG(VB_GENERAL, LOG_INFO, LOC + "Waiting for resolution change");
977  QEventLoop loop;
978  QTimer timer;
979  timer.setSingleShot(true);
980  connect(&timer, &QTimer::timeout, [](){ LOG(VB_GENERAL, LOG_WARNING, LOC + "Timed out wating for screen change"); });
981  QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
982  QObject::connect(m_screen, &QScreen::geometryChanged, &loop, &QEventLoop::quit);
983  // 500ms maximum wait
984  timer.start(500);
985  loop.exec();
986 }
987 
989 {
990  // N.B. This isn't working as intended as it always times out rather than
991  // exiting deliberately. It does however somehow filter out unwanted screenChanged
992  // events that otherwise often put the widget in the wrong screen.
993  // Needs more investigation - but for now it works:)
994  if (!m_widget || (m_widget && !m_widget->windowHandle()))
995  return;
996  LOG(VB_GENERAL, LOG_INFO, LOC + "Waiting for new screen");
997  QEventLoop loop;
998  QTimer timer;
999  timer.setSingleShot(true);
1000  connect(&timer, &QTimer::timeout, [](){ LOG(VB_GENERAL, LOG_WARNING, LOC + "Timed out waiting for new screen"); });
1001  QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
1002  QObject::connect(m_widget->windowHandle(), &QWindow::screenChanged, &loop, &QEventLoop::quit);
1003  // 500ms maximum wait
1004  timer.start(500);
1005  loop.exec();
1006 }
1007 
1009 {
1010  int pauselengthinms = gCoreContext->GetNumSetting("VideoModeChangePauseMS", 0);
1011  if (pauselengthinms)
1012  {
1013  LOG(VB_GENERAL, LOG_INFO, LOC +
1014  QString("Pausing %1ms for video mode switch").arg(pauselengthinms));
1015  QEventLoop loop;
1016  QTimer timer;
1017  timer.setSingleShot(true);
1018  QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
1019  // 500ms maximum wait
1020  timer.start(pauselengthinms);
1021  loop.exec();
1022  }
1023 }
1024 
1025 void MythDisplay::DebugModes(void) const
1026 {
1027  // This is intentionally formatted to match the output of xrandr for comparison
1028  if (VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_INFO))
1029  {
1030  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Available modes:");
1031  for (auto it = m_videoModes.crbegin(); it != m_videoModes.crend(); ++it)
1032  {
1033  auto rates = (*it).RefreshRates();
1034  QStringList rateslist;
1035  for (auto it2 = rates.crbegin(); it2 != rates.crend(); ++it2)
1036  rateslist.append(QString("%1").arg(*it2, 2, 'f', 2, '0'));
1037  if (rateslist.empty())
1038  rateslist.append("Variable rate?");
1039  LOG(VB_PLAYBACK, LOG_INFO, QString("%1x%2\t%3")
1040  .arg((*it).Width()).arg((*it).Height()).arg(rateslist.join("\t")));
1041  }
1042  }
1043 }
1044 
1050 void MythDisplay::ConfigureQtGUI(int SwapInterval, const QString& _Display)
1051 {
1052  // Set the default surface format. Explicitly required on some platforms.
1053  QSurfaceFormat format;
1054  format.setAlphaBufferSize(0);
1055  format.setDepthBufferSize(0);
1056  format.setStencilBufferSize(0);
1057  format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
1058  format.setProfile(QSurfaceFormat::CompatibilityProfile);
1059  format.setSwapInterval(SwapInterval);
1060  QSurfaceFormat::setDefaultFormat(format);
1061 
1062 #ifdef Q_OS_MAC
1063  // Without this, we can't set focus to any of the CheckBoxSetting, and most
1064  // of the MythPushButton widgets, and they don't use the themed background.
1065  QApplication::setDesktopSettingsAware(false);
1066 #endif
1067 
1068  // If Wayland decorations are enabled, the default framebuffer format is forced
1069  // to use alpha. This framebuffer is rendered with alpha blending by the wayland
1070  // compositor - so any translucent areas of our UI will allow the underlying
1071  // window to bleed through.
1072  // N.B. this is probably not the most performant solution as compositors MAY
1073  // still render hidden windows. A better solution is probably to call
1074  // wl_surface_set_opaque_region on the wayland surface. This is confirmed to work
1075  // and should allow the compositor to optimise rendering for opaque areas. It does
1076  // however require linking to libwayland-client AND including private Qt headers
1077  // to retrieve the surface and compositor structures (the latter being a significant issue).
1078  // see also setAlphaBufferSize above
1079  setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 0);
1080 
1081 #if defined (Q_OS_LINUX) && defined (USING_EGL) && defined (USING_X11)
1082  // We want to use EGL for VAAPI/MMAL/DRMPRIME rendering to ensure we
1083  // can use zero copy video buffers for the best performance (N.B. not tested
1084  // on AMD desktops). To force Qt to use EGL we must set 'QT_XCB_GL_INTEGRATION'
1085  // to 'xcb_egl' and this must be done before any GUI is created. If the platform
1086  // plugin is not xcb then this should have no effect.
1087  // This does however break when using NVIDIA drivers - which do not support
1088  // EGL like other drivers so we try to check the EGL vendor - and we currently
1089  // have no need for EGL with NVIDIA (that may change however).
1090  // NOTE force using EGL by setting MYTHTV_FORCE_EGL
1091  // NOTE disable using EGL by setting MYTHTV_NO_EGL
1092  // NOTE We have no Qt platform information, window/surface or logging when this is called.
1093  QString soft = qgetenv("LIBGL_ALWAYS_SOFTWARE");
1094  bool ignore = soft == "1" || soft.compare("true", Qt::CaseInsensitive) == 0;
1095  bool allow = qgetenv("MYTHTV_NO_EGL").isEmpty() && !ignore;
1096  bool force = !qgetenv("MYTHTV_FORCE_EGL").isEmpty();
1097  if ((force || allow) && MythDisplayX11::IsAvailable())
1098  {
1099  // N.B. By default, ignore EGL if vendor string is not returned
1100  QString vendor = MythEGL::GetEGLVendor();
1101  if (vendor.contains("nvidia", Qt::CaseInsensitive) && !force)
1102  {
1103  qInfo() << LOC + QString("Not requesting EGL for vendor '%1'").arg(vendor);
1104  }
1105  else if (!vendor.isEmpty() || force)
1106  {
1107  qInfo() << LOC + QString("Requesting EGL for '%1'").arg(vendor);
1108  setenv("QT_XCB_GL_INTEGRATION", "xcb_egl", 0);
1109  }
1110  }
1111 #endif
1112 #ifdef Q_OS_ANDROID
1113  //QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
1114 #endif
1115 
1116  // Ignore desktop scaling
1117  QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
1118 
1119 #ifdef USING_X11
1121 #else
1122  (void)_Display;
1123 #endif
1124 }
force
bool force
Definition: mythtv/programs/mythcommflag/main.cpp:75
MythDisplay::GetScreenCount
static int GetScreenCount(void)
Definition: mythdisplay.cpp:252
MythDisplay::m_physicalSize
QSize m_physicalSize
Definition: mythdisplay.h:89
MythDisplay::GetRefreshRates
std::vector< double > GetRefreshRates(QSize Size)
Definition: mythdisplay.cpp:745
MythDisplay::DebugModes
void DebugModes(void) const
Definition: mythdisplay.cpp:1025
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
MythDisplay::Initialise
void Initialise(void)
Definition: mythdisplay.cpp:493
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
MythDisplay::m_screenBounds
QRect m_screenBounds
Definition: mythdisplay.h:102
MythDisplayMode::FindBestScreen
static uint64_t FindBestScreen(const DisplayModeMap &Map, int Width, int Height, double Rate)
Definition: mythdisplaymode.cpp:222
MythDisplay::DebugScreen
static void DebugScreen(QScreen *qScreen, const QString &Message)
Definition: mythdisplay.cpp:469
mythdisplaywindows.h
MythDisplay::m_resolution
QSize m_resolution
Definition: mythdisplay.h:88
MythDisplay::ScreenChanged
virtual void ScreenChanged(QScreen *qScreen)
The actual screen in use has changed. We must use it.
Definition: mythdisplay.cpp:381
MythDisplayDRM
Definition: mythdisplaydrm.h:13
MythDisplay::m_videoMode
MythDisplayMode m_videoMode
Definition: mythdisplay.h:105
MythXDisplay::SetQtX11Display
static void SetQtX11Display(const QString &Display)
Definition: mythxdisplay.cpp:56
MythDisplayMode::CalcKey
static uint64_t CalcKey(QSize Size, double Rate)
Definition: mythdisplaymode.cpp:126
MythDisplay::UpdateCurrentMode
virtual void UpdateCurrentMode(void)
Retrieve screen details.
Definition: mythdisplay.cpp:431
setenv
#define setenv(x, y, z)
Definition: compat.h:156
arg
arg(title).arg(filename).arg(doDelete))
MythDisplay::GetDescription
static QStringList GetDescription(void)
Definition: mythdisplay.cpp:123
MythDisplay::GetAspectRatio
double GetAspectRatio(QString &Source, bool IgnoreModeOverride=false)
Returns current screen aspect ratio.
Definition: mythdisplay.cpp:784
LOC
#define LOC
Definition: mythdisplay.cpp:36
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythDisplayMode::Width
int Width(void) const
Definition: mythdisplaymode.cpp:58
MythDisplayRPI
Definition: mythdisplayrpi.h:17
MythDisplayMode::Resolution
QSize Resolution(void) const
Definition: mythdisplaymode.cpp:53
GetMythDB
MythDB * GetMythDB(void)
Definition: mythdb.cpp:46
MythDisplay::ScreenRemoved
void ScreenRemoved(QScreen *qScreen)
Definition: mythdisplay.cpp:413
MythEDID::Valid
bool Valid(void) const
Definition: mythedid.cpp:32
MythDisplay::m_videoModes
vector< MythDisplayMode > m_videoModes
Definition: mythdisplay.h:94
MythDisplay::PhysicalDPIChanged
void PhysicalDPIChanged(qreal DPI)
Definition: mythdisplay.cpp:395
MythDisplay::GetPixelAspectRatio
double GetPixelAspectRatio(void)
Definition: mythdisplay.cpp:257
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:85
MythDisplay::CurrentScreenChanged
void CurrentScreenChanged(QScreen *qScreen)
MythDisplay::WaitForNewScreen
void WaitForNewScreen(void)
Definition: mythdisplay.cpp:988
MythDisplay::m_guiMode
MythDisplayMode m_guiMode
Definition: mythdisplay.h:104
mythdisplayosx.h
MythDisplay::GetRefreshRate
double GetRefreshRate(void) const
Definition: mythdisplay.cpp:731
MythDisplay::SwitchToDesktop
void SwitchToDesktop(void)
Return the screen to the original desktop video mode.
Definition: mythdisplay.cpp:624
quit
@ quit
Definition: lirc_client.h:30
MythDisplay::InitScreenBounds
void InitScreenBounds(void)
Get screen size from Qt while respecting the user's multiscreen settings.
Definition: mythdisplay.cpp:566
MythDisplayAndroid
Definition: mythdisplayandroid.h:8
MythEGL::GetEGLVendor
static QString GetEGLVendor(void)
Definition: mythegl.cpp:85
MythDisplay::m_aspectRatioOverride
double m_aspectRatioOverride
Definition: mythdisplay.h:87
mythdisplay.h
mythlogging.h
mythdisplayrpi.h
Source
Definition: channelsettings.cpp:69
MythDisplay::~MythDisplay
~MythDisplay() override
Definition: mythdisplay.cpp:193
MythDisplay::m_overrideVideoModes
DisplayModeMap m_overrideVideoModes
Definition: mythdisplay.h:106
mythdisplaydrm.h
MythDisplay::GetExtraScreenInfo
static QString GetExtraScreenInfo(QScreen *qScreen)
Definition: mythdisplay.cpp:458
MythDisplayWindows
Definition: mythdisplaywindows.h:8
compat.h
MythDisplay::GetCurrentScreen
QScreen * GetCurrentScreen(void)
Return a pointer to the screen to use.
Definition: mythdisplay.cpp:288
MythDisplay::m_edid
MythEDID m_edid
Definition: mythdisplay.h:90
MythDisplay::m_window
QWindow * m_window
Definition: mythdisplay.h:92
MythDisplayMode::Height
int Height(void) const
Definition: mythdisplaymode.cpp:63
MythDisplay::PauseForModeSwitch
static void PauseForModeSwitch(void)
Definition: mythdisplay.cpp:1008
MythDisplay::SetWidget
void SetWidget(QWidget *MainWindow)
Set the QWidget and QWindow in use.
Definition: mythdisplay.cpp:211
MythDisplay::SwitchToVideoMode
virtual bool SwitchToVideoMode(QSize Size, double Framerate)
Definition: mythdisplay.cpp:756
MythDisplayX11
Definition: mythdisplayx11.h:15
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:635
MythMainWindow::WindowIsAlwaysFullscreen
static bool WindowIsAlwaysFullscreen(void)
Return true if the current platform only supports fullscreen windows.
Definition: mythmainwindow.cpp:964
MythDisplay::m_waitForModeChanges
bool m_waitForModeChanges
Definition: mythdisplay.h:84
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
MythDisplay
Definition: mythdisplay.h:19
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:930
MythUIHelper::GetGeometryOverride
static QRect GetGeometryOverride(void)
Return the raw geometry override rectangle.
Definition: mythuihelper.cpp:935
MythDisplayMode
Definition: mythdisplaymode.h:22
MythDisplay::EstimateVirtualAspectRatio
double EstimateVirtualAspectRatio(void)
Estimate the overall display aspect ratio for multi screen setups.
Definition: mythdisplay.cpp:861
MythDisplay::GetPhysicalSize
QSize GetPhysicalSize(void)
Definition: mythdisplay.cpp:964
MythDisplay::AcquireRelease
static MythDisplay * AcquireRelease(bool Acquire=true)
Definition: mythdisplay.cpp:70
MythDisplay::ScreenAdded
void ScreenAdded(QScreen *qScreen)
Definition: mythdisplay.cpp:407
mythuihelper.h
MythUIHelper::IsGeometryOverridden
static bool IsGeometryOverridden(void)
Definition: mythuihelper.cpp:922
MythDisplayMode::FindBestMatch
static int FindBestMatch(const vector< MythDisplayMode > &Modes, const MythDisplayMode &Mode, double &TargetRate)
Definition: mythdisplaymode.cpp:139
next
PictureAttribute next(PictureAttributeSupported Supported, PictureAttribute Attribute)
Definition: videoouttypes.h:350
MythDisplay::SpanAllScreens
static bool SpanAllScreens(void)
Return true if the MythTV windows should span all screens.
Definition: mythdisplay.cpp:453
MythDisplay::m_refreshRate
double m_refreshRate
Definition: mythdisplay.h:86
MythDisplayX11::IsAvailable
static bool IsAvailable(void)
Definition: mythdisplayx11.cpp:17
setAttribute
channel setAttribute("chanid", chanID)
VERBOSE_LEVEL_CHECK
#define VERBOSE_LEVEL_CHECK(_MASK_, _LEVEL_)
Definition: mythlogging.h:14
MythDisplay::NextModeIsLarger
bool NextModeIsLarger(QSize Size)
Check whether the next mode is larger in size than the current mode.
Definition: mythdisplay.cpp:615
MythDisplay::m_widget
QWidget * m_widget
Definition: mythdisplay.h:91
mythcorecontext.h
MythDisplay::SwitchToGUI
bool SwitchToGUI(bool Wait=false)
Switches to the GUI resolution.
Definition: mythdisplay.cpp:700
MythDisplay::ScreenCountChanged
void ScreenCountChanged(int Screens)
MythDisplay::GetRefreshInterval
int GetRefreshInterval(int Fallback) const
Definition: mythdisplay.cpp:736
MythDisplayOSX
Definition: mythdisplayosx.h:11
MythDisplay::GetScreenBounds
QRect GetScreenBounds(void)
Definition: mythdisplay.cpp:271
MythDisplayMode::RefreshRate
double RefreshRate(void) const
Definition: mythdisplaymode.cpp:94
MythDisplay::ConfigureQtGUI
static void ConfigureQtGUI(int SwapInterval=1, const QString &Display=QString())
Shared static initialistaion code for all MythTV GUI applications.
Definition: mythdisplay.cpp:1050
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:134
MythEDID::IsSRGB
bool IsSRGB(void) const
Definition: mythedid.cpp:67
MythDisplay::m_initialised
bool m_initialised
Definition: mythdisplay.h:100
MythDisplay::m_screen
QScreen * m_screen
Definition: mythdisplay.h:93
MythDisplay::GetEDID
MythEDID & GetEDID(void)
Definition: mythdisplay.cpp:847
mythegl.h
MythDisplay::m_desktopMode
MythDisplayMode m_desktopMode
Definition: mythdisplay.h:103
MythDisplay::GetResolution
QSize GetResolution(void)
Definition: mythdisplay.cpp:959
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:856
MythDisplay::GetGUIResolution
QSize GetGUIResolution(void)
Definition: mythdisplay.cpp:266
MythDisplay::GetDesiredScreen
static QScreen * GetDesiredScreen(void)
Definition: mythdisplay.cpp:293
MythDisplay::GeometryChanged
static void GeometryChanged(const QRect &Geometry)
Definition: mythdisplay.cpp:419
mythdisplayandroid.h
MythDisplay::PrimaryScreenChanged
static void PrimaryScreenChanged(QScreen *qScreen)
Definition: mythdisplay.cpp:402
mythdisplayx11.h
ReferenceCounter::IncrRef
virtual int IncrRef(void)
Increments reference count.
Definition: referencecounter.cpp:101
mythmainwindow.h
MythDisplay::MythDisplay
MythDisplay()
Definition: mythdisplay.cpp:173
MythDisplay::GetVideoModes
virtual const vector< MythDisplayMode > & GetVideoModes(void)
Definition: mythdisplay.cpp:761
MythCoreContext::GetFloatSettingOnHost
double GetFloatSettingOnHost(const QString &key, const QString &host, double defaultval=0.0)
Definition: mythcorecontext.cpp:970
ReferenceCounter
General purpose reference counter.
Definition: referencecounter.h:27
MythDisplay::WaitForScreenChange
void WaitForScreenChange(void)
Definition: mythdisplay.cpp:969
MythEDID
Definition: mythedid.h:15
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:916
MythDisplay::CurrentDPIChanged
void CurrentDPIChanged(qreal DPI)
MythDisplay::m_firstScreenChange
bool m_firstScreenChange
Definition: mythdisplay.h:101