MythTV master
mythdisplaydrm.cpp
Go to the documentation of this file.
1// MythTV
2#include "libmythbase/mythconfig.h"
5#include "mythmainwindow.h"
8
9#define LOC QString("DispDRM: ")
10
12{
13#if CONFIG_QTPRIVATEHEADERS
14 if (m_device)
15 m_device->MainWindowReady();
16#endif
17}
18
20{
21#if CONFIG_QTPRIVATEHEADERS
22 if (!HasMythMainWindow())
23 return false;
24
25 if (auto *mainwindow = GetMythMainWindow(); mainwindow)
26 {
27 if (auto *drmdisplay = dynamic_cast<MythDisplayDRM*>(mainwindow->GetDisplay()); drmdisplay)
28 {
29 if (auto drm = drmdisplay->GetDevice(); drm && drm->Atomic() && drm->Authenticated())
30 {
31 if (auto plane = drm->GetVideoPlane(); plane && plane->m_id)
32 return true;
33 }
34 }
35 }
36#endif
37 return false;
38}
39
41{
43 Initialise();
44#if CONFIG_QTPRIVATEHEADERS
45 if (MainWindow && m_device && m_device->GetVideoPlane())
47#endif
48}
49
51{
52 m_device = nullptr;
53}
54
56{
57 return m_device;
58}
59
60// FIXME - I doubt this slot is being called correctly but the screen won't
61// change if we are using a fullscreen platform plugin (e.g. eglfs)
62void MythDisplayDRM::ScreenChanged(QScreen *qScreen)
63{
65
66 if (m_device && m_device->GetScreen() != m_screen)
67 m_device = nullptr;
68
69 if (!m_device)
71
72 emit screenChanged();
73}
74
76{
77 return m_device && m_device->CanSwitchModes();
78}
79
81{
82#if CONFIG_QTPRIVATEHEADERS
83 return m_device && m_device->Authenticated() && m_device->Atomic() &&
84 m_device->GetVideoPlane() && m_device->GetVideoPlane()->m_id;
85#else
86 return false;
87#endif
88}
89
91{
92 if (gCoreContext && m_device && m_device->CanSwitchModes())
93 return gCoreContext->GetBoolSetting("UseVideoModes", false);
94 return false;
95}
96
98{
99 if (m_device)
100 {
101 // Ensure video modes are fetched early
103 m_refreshRate = m_device->GetRefreshRate();
104 m_resolution = m_device->GetResolution();
105 m_physicalSize = m_device->GetPhysicalSize();
106 m_edid = m_device->GetEDID();
107 m_modeComplete = true;
108 return;
109 }
111}
112
114{
115 if (!m_videoModes.empty())
116 return m_videoModes;
117
118 m_videoModes.clear();
119 m_modeMap.clear();
120 if (!m_screen || !m_device || !m_device->CanSwitchModes())
121 return m_videoModes;
122
123 auto mainresolution = m_device->GetResolution();
124 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Filtering out modes that aren't %1x%2")
125 .arg(mainresolution.width()).arg(mainresolution.height()));
126
127 DisplayModeMap screenmap;
128 auto modes = m_device->GetModes();
129 auto physicalsize = m_device->GetPhysicalSize();
130 for (const auto & mode : modes)
131 {
132 auto width = mode->m_width;
133 auto height = mode->m_height;
134 auto rate = mode->m_rate;
135
136 // Filter out interlaced modes
137 if ((mode->m_flags & DRM_MODE_FLAG_INTERLACE) != 0U)
138 {
139 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Ignoring interlaced mode %1x%2 %3i")
140 .arg(width).arg(height).arg(rate, 2, 'f', 2, '0'));
141 continue;
142 }
143
144 // Filter out anything that is not the same size as our current screen
145 // i.e. refresh rate changes only
146 if (auto size = QSize(width, height); size != mainresolution)
147 {
148 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Ignoring mode %1x%2 %3")
149 .arg(width).arg(height).arg(rate, 2, 'f', 2, '0'));
150 continue;
151 }
152
153 QSize resolution(width, height);
154 auto key = MythDisplayMode::CalcKey(resolution, 0.0);
155 if (!screenmap.contains(key))
156 screenmap[key] = MythDisplayMode(resolution, physicalsize, -1.0, rate);
157 else
158 screenmap[key].AddRefreshRate(rate);
159 m_modeMap.insert(MythDisplayMode::CalcKey(resolution, rate), mode->m_index);
160 }
161
162 for (auto & it : screenmap)
163 m_videoModes.push_back(it.second);
164
165 DebugModes();
166 return m_videoModes;
167}
168
169bool MythDisplayDRM::SwitchToVideoMode(QSize Size, double DesiredRate)
170{
171 if (!m_screen || !m_device || !m_device->CanSwitchModes() || m_videoModes.empty())
172 return false;
173
174 auto rate = static_cast<double>(NAN);
175 QSize dummy(0, 0);
176 MythDisplayMode desired(Size, dummy, -1.0, DesiredRate);
177 int index = MythDisplayMode::FindBestMatch(m_videoModes, desired, rate);
178
179 if (index < 0)
180 {
181 LOG(VB_GENERAL, LOG_ERR, LOC + "Desired resolution and frame rate not found.");
182 return false;
183 }
184
185 auto mode = MythDisplayMode::CalcKey(Size, rate);
186 if (!m_modeMap.contains(mode))
187 {
188 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to find mode");
189 return false;
190 }
191
192 return m_device->SwitchMode(m_modeMap.value(mode));
193}
bool GetBoolSetting(const QString &key, bool defaultval=false)
static MythDRMPtr Create(QScreen *qScreen, const QString &Device=QString(), bool NeedPlanes=true)
Create a MythDRMDevice instance.
void UpdateCurrentMode() override
Retrieve screen details.
MythDisplayDRM(MythMainWindow *MainWindow)
~MythDisplayDRM() override
bool VideoModesAvailable() override
MythDRMPtr m_device
const MythDisplayModes & GetVideoModes() override
bool SwitchToVideoMode(QSize Size, double DesiredRate) override
void screenChanged()
MythDRMPtr GetDevice()
static bool DirectRenderingAvailable()
bool UsingVideoModes() override
QMap< uint64_t, int > m_modeMap
void ScreenChanged(QScreen *qScreen) override
bool IsPlanar() override
static int FindBestMatch(const MythDisplayModes &Modes, const MythDisplayMode &Mode, double &TargetRate)
static uint64_t CalcKey(QSize Size, double Rate)
QSize m_resolution
Definition: mythdisplay.h:92
virtual void UpdateCurrentMode()
Retrieve screen details.
QSize m_physicalSize
Definition: mythdisplay.h:93
void Initialise()
double m_refreshRate
Definition: mythdisplay.h:90
virtual void ScreenChanged(QScreen *qScreen)
The actual screen in use has changed. We must use it.
MythDisplayModes m_videoModes
Definition: mythdisplay.h:98
QScreen * m_screen
Definition: mythdisplay.h:97
MythEDID m_edid
Definition: mythdisplay.h:94
bool m_modeComplete
Definition: mythdisplay.h:89
void DebugModes() const
void SignalWindowReady()
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOC
std::map< uint64_t, MythDisplayMode > DisplayModeMap
std::vector< MythDisplayMode > MythDisplayModes
#define DRM_MODE_FLAG_INTERLACE
std::shared_ptr< class MythDRMDevice > MythDRMPtr
Definition: mythdrmdevice.h:19
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
bool HasMythMainWindow(void)
MythMainWindow * GetMythMainWindow(void)