9#define pointer Xpointer
10#include <X11/extensions/Xrandr.h>
13#define LOC QString("DisplayX11: ")
16 QScreen* qScreen, RROutput* Output =
nullptr);
25 static bool s_checked =
false;
26 static bool s_available =
false;
31 s_available = display.
Open();
59 auto * res = XRRGetScreenResourcesCurrent(display->GetDisplay(), display->GetRoot());
64 static_cast<int>(
output->mm_height));
72 auto * currentcrtc = XRRGetCrtcInfo(display->GetDisplay(), res,
m_crtc);
75 for (
int i = 0; i < res->nmode; ++i)
77 if (res->modes[i].id != currentcrtc->mode)
79 auto mode = res->modes[i];
81 static_cast<int>(mode.height));
82 if (mode.dotClock > 1 && mode.vTotal > 1 && mode.hTotal > 1)
84 m_refreshRate =
static_cast<double>(mode.dotClock) / (mode.vTotal * mode.hTotal);
85 if (mode.modeFlags & RR_Interlace)
89 XRRFreeCrtcInfo(currentcrtc);
92 XRRFreeScreenResources(res);
119 auto * res = XRRGetScreenResourcesCurrent(display->GetDisplay(), display->GetRoot());
124 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to find an output that matches '%1'")
126 XRRFreeScreenResources(res);
131 auto mmwidth =
static_cast<int>(
output->mm_width);
132 auto mmheight =
static_cast<int>(
output->mm_height);
136 for (
int i = 0; i <
output->nmode; ++i)
138 RRMode rrmode =
output->modes[i];
139 for (
int j = 0; j < res->nmode; ++j)
141 if (res->modes[j].id != rrmode)
144 auto mode = res->modes[j];
145 if (mode.id != rrmode)
147 if (mode.dotClock <= 1 || mode.vTotal <= 1 || mode.hTotal <= 1)
149 auto width =
static_cast<int>(mode.width);
150 auto height =
static_cast<int>(mode.height);
151 auto rate =
static_cast<double>(mode.dotClock) / (mode.vTotal * mode.hTotal);
156 if ((mode.modeFlags & RR_Interlace) != 0U)
158 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Ignoring interlaced mode %1x%2 %3i")
159 .arg(width).arg(height).arg(rate * 2.0, 2,
'f', 2,
'0'));
163 QSize resolution(width, height);
164 QSize physical(mmwidth, mmheight);
166 if (screenmap.find(key) == screenmap.end())
169 screenmap[key].AddRefreshRate(rate);
174 for (
auto & it : screenmap)
178 XRRFreeOutputInfo(
output);
179 XRRFreeScreenResources(res);
193 auto rate =
static_cast<double>(NAN);
200 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Desired resolution and frame rate not found.");
207 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to find mode");
215 Status status = RRSetConfigFailed;
216 auto * res = XRRGetScreenResourcesCurrent(display->GetDisplay(), display->GetRoot());
219 auto * currentcrtc = XRRGetCrtcInfo(display->GetDisplay(), res,
m_crtc);
222 status = XRRSetCrtcConfig(display->GetDisplay(), res,
m_crtc, CurrentTime,
223 currentcrtc->x, currentcrtc->y,
m_modeMap.value(mode),
224 currentcrtc->rotation, currentcrtc->outputs,
225 currentcrtc->noutput);
226 XRRFreeCrtcInfo(currentcrtc);
227 auto * config = XRRGetScreenInfo(display->GetDisplay(), display->GetRoot());
229 XRRFreeScreenConfigInfo(config);
231 XRRFreeScreenResources(res);
235 if (RRSetConfigSuccess != status)
236 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to set video mode");
237 return RRSetConfigSuccess == status;
242 QScreen* qScreen, RROutput* Output)
247 XRROutputInfo* result =
nullptr;
248 for (
int i = 0; i <
Resources->noutput; ++i)
252 XRRFreeOutputInfo(result);
257 if (!result || result->nameLen < 1)
259 if (result->connection != RR_Connected)
261 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Output '%1' is disconnected")
266 QString name(result->name);
267 if (name == qScreen->name())
269 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Matched '%1' to output %2")
270 .arg(qScreen->name()).arg(
Resources->outputs[i]));
276 XRRFreeOutputInfo(result);
288 auto * res = XRRGetScreenResourcesCurrent(mDisplay->
GetDisplay(), mDisplay->
GetRoot());
289 RROutput rroutput = 0;
294 auto edidproperty = XInternAtom(mDisplay->
GetDisplay(), RR_PROPERTY_RANDR_EDID,
295 static_cast<Bool
>(
false));
299 int propertycount = 0;
300 auto * properties = XRRListOutputProperties(mDisplay->
GetDisplay(), rroutput, &propertycount);
305 for (
int i = 0; i < propertycount; ++i)
307 if (properties[i] == edidproperty)
318 int actualformat = 0;
319 unsigned long bytesafter = 0;
320 unsigned long nitems = 0;
321 unsigned char* data =
nullptr;
322 if (XRRGetOutputProperty(mDisplay->
GetDisplay(), rroutput, edidproperty,
323 0, 128,
static_cast<Bool
>(
false),
static_cast<Bool
>(
false),
324 AnyPropertyType, &actualtype,
325 &actualformat, &nitems, &bytesafter, &data) == Success)
327 if (actualtype == XA_INTEGER && actualformat == 8)
328 m_edid =
MythEDID(
reinterpret_cast<const char*
>(data),
static_cast<int>(nitems));
336 XRRFreeOutputInfo(
output);
337 XRRFreeScreenResources(res);
bool GetBoolSetting(const QString &key, bool defaultval=false)
static int FindBestMatch(const MythDisplayModes &Modes, const MythDisplayMode &Mode, double &TargetRate)
static uint64_t CalcKey(QSize Size, double Rate)
static bool IsAvailable()
bool SwitchToVideoMode(QSize Size, double DesiredRate) override
bool UsingVideoModes() override
const MythDisplayModes & GetVideoModes() override
QMap< uint64_t, unsigned long > m_modeMap
void UpdateCurrentMode() override
Retrieve details for the current video mode.
virtual void UpdateCurrentMode()
Retrieve screen details.
MythDisplayModes m_videoModes
bool Open()
Open the display.
static MythXDisplay * OpenMythXDisplay(bool Warn=true)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
std::map< uint64_t, MythDisplayMode > DisplayModeMap
std::vector< MythDisplayMode > MythDisplayModes
static XRROutputInfo * GetOutput(XRRScreenResources *Resources, MythXDisplay *mDisplay, QScreen *qScreen, RROutput *Output=nullptr)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
QList< Resource * > Resources