7 #include <QApplication>
8 #include <QElapsedTimer>
23 #ifdef USING_WAYLANDEXTRAS
47 #define LOC QString("Display: ")
93 #ifdef USING_WAYLANDEXTRAS
127 #if defined(Q_OS_WIN)
139 bool spanall =
false;
144 result.append(tr(
"Spanning %1 screens").arg(screencount));
145 result.append(tr(
"Total bounds") + QString(
"\t: %1x%2")
154 result.append(tr(
"Supported HDR formats\t: %1").arg(hdr.join(
",")));
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)));
163 result.append(tr(
"Variable refresh rate '%1': %2 %3")
165 m_vrrState->Enabled() ? tr(
"Enabled") : tr(
"Disabled"),
170 const auto screens = QGuiApplication::screens();
172 for (
auto *screen : qAsConst(screens))
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));
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()));
188 result.append(tr(
"Aspect ratio") + QString(
"\t: %1 (%2)")
189 .arg(aspect, 0,
'f', 3).arg(source));
192 result.append(tr(
"Current mode") + QString(
"\t: %1x%2@%3Hz")
198 result.append(tr(
"Available modes:"));
199 for (
auto it = modes.crbegin(); it != modes.crend(); ++it)
200 result.append(
" " + it->ToString());
219 auto *guiapp = qobject_cast<QGuiApplication *>(QCoreApplication::instance());
220 if (guiapp ==
nullptr)
230 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Deleting");
260 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Have main widget");
264 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Have main window");
290 return QGuiApplication::screens().size();
335 QScreen* newscreen =
nullptr;
345 bool windowed =
GetMythDB()->GetBoolSetting(
"RunFrontendInWindow",
false) &&
351 QPoint point = windowed ?
override.topLeft() :
override.bottomRight();
352 QList screens = QGuiApplication::screens();
353 for (QScreen *screen : qAsConst(screens))
355 if (screen->geometry().contains(point))
358 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
359 "Geometry override places window in screen '%1'").arg(newscreen->name()));
368 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Using primary screen for multiscreen");
369 newscreen = QGuiApplication::primaryScreen();
376 QList screens = QGuiApplication::screens();
377 for (QScreen *screen : qAsConst(screens))
379 if (!name.isEmpty() && name == screen->name())
381 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Found screen '%1'").arg(name));
391 int screen_num = name.toInt(&ok);
392 QList<QScreen *>screens = QGuiApplication::screens();
393 if (ok && (screen_num >= 0) && (screen_num < screens.size()))
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];
404 QScreen *primary = QGuiApplication::primaryScreen();
405 if (name.isEmpty() && primary)
407 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Defaulting to primary screen (%1)")
408 .arg(primary->name()));
410 else if (name !=
"-1" && primary)
412 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Screen '%1' not found, defaulting to primary screen (%2)")
413 .arg(name, primary->name()));
428 disconnect(
m_screen,
nullptr,
this,
nullptr);
439 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Qt screen pixel ratio changed to %1")
440 .arg(DPI, 2,
'f', 2,
'0'));
457 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Screen '%1' removed").arg(qScreen->name()));
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()));
490 m_physicalSize = QSize(
static_cast<int>(screen->physicalSize().width()),
491 static_cast<int>(screen->physicalSize().height()));
502 QString mfg = qScreen->manufacturer();
505 QString model = qScreen->model();
508 return QString(
"(Make: %1 Model: %2)").arg(mfg, model);
516 auto geom = qScreen->geometry();
517 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"%1 screen '%2' %3")
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()));
525 if (qScreen->virtualGeometry() != geom)
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()));
550 LOG(VB_GENERAL, LOG_NOTICE,
LOC + QString(
"Desktop video mode: %1x%2 %3Hz")
555 LOG(VB_GENERAL, LOG_NOTICE,
LOC +
"Display is using sRGB colourspace");
557 LOG(VB_GENERAL, LOG_NOTICE,
LOC +
"Display has custom colourspace");
569 double aspectratio = 0.0;
570 GetMythDB()->GetResolutionSetting(
"GuiVidMode", pixelwidth, pixelheight, aspectratio, refreshrate);
571 GetMythDB()->GetResolutionSetting(
"DisplaySize", mmwidth, mmheight);
575 pixelwidth = pixelheight = 0;
576 GetMythDB()->GetResolutionSetting(
"TVVidMode", pixelwidth, pixelheight, aspectratio, refreshrate);
580 for (
int i = 0;
true; ++i)
586 double iaspect = 0.0;
587 double oaspect = 0.0;
591 GetMythDB()->GetResolutionSetting(
"VidMode", iw, ih, iaspect, irate, i);
592 GetMythDB()->GetResolutionSetting(
"TVVidMode", ow, oh, oaspect, orate, i);
594 if ((!iw && !ih && qFuzzyIsNull(irate)) || !(ih && ow && oh))
598 MythDisplayMode scr(QSize(ow, oh), QSize(mmwidth, mmheight), oaspect, orate);
613 const auto screens = QGuiApplication::screens();
614 for (
auto * screen : qAsConst(screens))
616 auto dim = screen->geometry();
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));
622 const auto * primary = QGuiApplication::primaryScreen();
625 if (!screens.empty())
626 primary = screens.front();
629 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Qt has no screens!");
634 LOG(VB_GUI, LOG_INFO,
LOC +QString(
"Primary screen: %1.").arg(primary->name()));
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));
643 LOG(VB_GUI, LOG_INFO,
LOC + QString(
"Using entire desktop."));
648 if (!
GetMythDB()->GetBoolSetting(
"ForceFullScreen",
false) &&
649 GetMythDB()->GetBoolSetting(
"RunFrontendInWindow",
false))
651 LOG(VB_GUI, LOG_INFO,
LOC +
"Running in a window");
661 LOG(VB_GUI, LOG_INFO,
LOC + QString(
"Using screen %1: %2x%3 at %4+%5")
699 double targetrate = 0.0;
700 double aspectoverride = 0.0;
704 Size.width(), Size.height(), Rate);
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));
718 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Trying to match best refresh rate %1Hz")
719 .arg(Rate, 0,
'f', 3));
734 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Ignoring mode switch to %1Hz - VRR enabled")
735 .arg(Rate, 0,
'f', 3));
738 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Allowing mode switch with VRR enabled for new resolution");
744 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Using current mode %1x%2@%3Hz")
749 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Trying mode %1x%2@%3Hz")
754 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to change mode to %1x%2@%3Hz")
765 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Switched to %1x%2@%3Hz for video %4x%5")
767 .arg(
m_refreshRate, 0,
'f', 3).arg(Size.width()).arg(Size.height()));
783 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Using %1x%2@%3Hz for GUI")
790 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to change mode to %1x%2@%3Hz")
800 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Switched to %1x%2@%3Hz")
821 auto max = std::get<1>(range) > 60 ? std::get<1>(range) : 60;
834 auto targetrate =
static_cast<double>(NAN);
840 return modes[
static_cast<size_t>(match)].RefreshRates();
873 auto valid = [](
double Aspect) {
return (Aspect > 0.1 && Aspect < 10.0); };
879 Source = tr(
"Video mode override");
902 Source = tr(
"Multiscreen estimate");
913 if (valid(calculated))
915 if ((
override < 0.0) || !valid(detected))
917 Source = tr(
"Square pixels");
950 LOG(VB_GENERAL, LOG_NOTICE,
LOC + QString(
"Supported HDR formats: %1")
952 if (
auto brightness =
m_hdrState->GetMaxLuminance(); brightness > 1.0)
954 LOG(VB_GENERAL, LOG_NOTICE,
LOC + QString(
"Display reports max brightness of %1 nits")
955 .arg(
static_cast<int>(brightness)));
971 auto sortscreens = [](
const QScreen* First,
const QScreen* Second)
973 if (First->geometry().left() < Second->geometry().left())
975 if (First->geometry().top() < Second->geometry().top())
981 double result = 16.0 / 9.0;
983 QList<QScreen*> screens;
985 screens =
m_screen->virtualSiblings();
990 std::sort(screens.begin(), screens.end(), sortscreens);
991 QList<double> aspectratios;
992 QSize totalresolution;
997 for (
auto it = screens.constBegin() ; it != screens.constEnd(); ++it)
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())
1007 lastleft = geom.left();
1009 if (lasttop < geom.top())
1012 lasttop = geom.top();
1015 aspectratios << (*it)->physicalSize().width() / (*it)->physicalSize().height();
1020 if (!totalresolution.isEmpty())
1021 result =
static_cast<double>(totalresolution.width()) / totalresolution.height();
1023 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Screen layout: %1x%2").arg(rows).arg(columns));
1024 if (rows == columns)
1026 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Grid layout");
1028 else if (rows == 1 && columns > 1)
1030 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Horizontal layout");
1032 else if (columns == 1 && rows > 1)
1034 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Vertical layout");
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()));
1045 double aspectratio = 0.0;
1046 double average = 0.0;
1048 for (
auto it2 = aspectratios.constBegin() ; it2 != aspectratios.constEnd(); ++it2, ++count)
1050 aspectratio += *it2;
1051 average = aspectratio / count;
1052 if (qAbs(*it2 - average) > 0.1)
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()));
1061 aspectratio = (average * columns) / rows;
1062 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Estimated aspect ratio: %1")
1084 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Waiting for resolution change");
1087 timer.setSingleShot(
true);
1088 connect(&timer, &
QTimer::timeout, [](){
LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Timed out wating for screen change"); });
1104 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Waiting for new screen");
1107 timer.setSingleShot(
true);
1108 connect(&timer, &
QTimer::timeout, [](){
LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Timed out waiting for new screen"); });
1119 if (pauselengthinms)
1121 LOG(VB_GENERAL, LOG_INFO,
LOC +
1122 QString(
"Pausing %1ms for video mode switch").arg(pauselengthinms));
1125 timer.setSingleShot(
true);
1128 timer.start(pauselengthinms);
1138 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Available modes:");
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")));
1160 auto forcevrr = CmdLine.
toBool(
"vrr");
1161 bool gsyncchanged =
false;
1162 bool freesyncchanged =
false;
1164 #ifdef USING_QTWEBENGINE
1165 QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
1169 QSurfaceFormat format;
1172 if (qEnvironmentVariableIsSet(
"MYTHTV_DEPTH"))
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);
1181 format.setDepthBufferSize(0);
1182 format.setStencilBufferSize(0);
1184 format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
1185 format.setProfile(QSurfaceFormat::CompatibilityProfile);
1186 format.setSwapInterval(SwapInterval);
1187 QSurfaceFormat::setDefaultFormat(format);
1192 QApplication::setDesktopSettingsAware(
false);
1195 #if defined (USING_DRM) && defined (USING_QTPRIVATEHEADERS)
1201 #ifdef USING_WAYLANDEXTRAS
1206 MythDRMDevice::SetupDRM(CmdLine);
1212 #if defined (Q_OS_LINUX) && defined (USING_EGL) && defined (USING_X11)
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");
1232 if (vendor.contains(
"nvidia", Qt::CaseInsensitive) && !
force)
1234 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Not requesting EGL for vendor '%1'").arg(vendor));
1236 else if (!vendor.isEmpty() ||
force)
1238 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Requesting EGL for vendor '%1'").arg(vendor));
1239 setenv(
"QT_XCB_GL_INTEGRATION",
"xcb_egl", 0);
1244 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1246 QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
1250 if (
auto display = CmdLine.
toString(
"display"); !display.isEmpty())
1261 if (forcevrr && !(gsyncchanged || freesyncchanged))
1262 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Variable refresh rate not adjusted");