8#if defined(_X11_XLIB_H_) && !defined(Bool)
12#define pointer Xpointer
13#include <X11/extensions/Xrandr.h>
16#define LOC QString("DisplayX11: ")
19 QScreen* qScreen, RROutput* Output =
nullptr);
28 static bool s_checked =
false;
29 static bool s_available =
false;
34 s_available = display.
Open();
62 auto * res = XRRGetScreenResourcesCurrent(display->GetDisplay(), display->GetRoot());
67 static_cast<int>(
output->mm_height));
75 auto * currentcrtc = XRRGetCrtcInfo(display->GetDisplay(), res,
m_crtc);
78 for (
int i = 0; i < res->nmode; ++i)
80 if (res->modes[i].id != currentcrtc->mode)
82 auto mode = res->modes[i];
84 static_cast<int>(mode.height));
85 if (mode.dotClock > 1 && mode.vTotal > 1 && mode.hTotal > 1)
87 m_refreshRate =
static_cast<double>(mode.dotClock) / (mode.vTotal * mode.hTotal);
88 if (mode.modeFlags & RR_Interlace)
92 XRRFreeCrtcInfo(currentcrtc);
95 XRRFreeScreenResources(res);
122 auto * res = XRRGetScreenResourcesCurrent(display->GetDisplay(), display->GetRoot());
127 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to find an output that matches '%1'")
129 XRRFreeScreenResources(res);
134 auto mmwidth =
static_cast<int>(
output->mm_width);
135 auto mmheight =
static_cast<int>(
output->mm_height);
139 for (
int i = 0; i <
output->nmode; ++i)
141 RRMode rrmode =
output->modes[i];
142 for (
int j = 0; j < res->nmode; ++j)
144 if (res->modes[j].id != rrmode)
147 auto mode = res->modes[j];
148 if (mode.id != rrmode)
150 if (mode.dotClock <= 1 || mode.vTotal <= 1 || mode.hTotal <= 1)
152 auto width =
static_cast<int>(mode.width);
153 auto height =
static_cast<int>(mode.height);
154 auto rate =
static_cast<double>(mode.dotClock) / (mode.vTotal * mode.hTotal);
159 if ((mode.modeFlags & RR_Interlace) != 0U)
161 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Ignoring interlaced mode %1x%2 %3i")
162 .arg(width).arg(height).arg(rate * 2.0, 2,
'f', 2,
'0'));
166 QSize resolution(width, height);
167 QSize physical(mmwidth, mmheight);
169 if (!screenmap.contains(key))
172 screenmap[key].AddRefreshRate(rate);
177 for (
auto & it : screenmap)
181 XRRFreeOutputInfo(
output);
182 XRRFreeScreenResources(res);
196 auto rate =
static_cast<double>(NAN);
203 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Desired resolution and frame rate not found.");
210 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to find mode");
218 Status status = RRSetConfigFailed;
219 auto * res = XRRGetScreenResourcesCurrent(display->GetDisplay(), display->GetRoot());
222 auto * currentcrtc = XRRGetCrtcInfo(display->GetDisplay(), res,
m_crtc);
225 status = XRRSetCrtcConfig(display->GetDisplay(), res,
m_crtc, CurrentTime,
226 currentcrtc->x, currentcrtc->y,
m_modeMap.value(mode),
227 currentcrtc->rotation, currentcrtc->outputs,
228 currentcrtc->noutput);
229 XRRFreeCrtcInfo(currentcrtc);
230 auto * config = XRRGetScreenInfo(display->GetDisplay(), display->GetRoot());
232 XRRFreeScreenConfigInfo(config);
234 XRRFreeScreenResources(res);
238 if (RRSetConfigSuccess != status)
239 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to set video mode");
240 return RRSetConfigSuccess == status;
245 QScreen* qScreen, RROutput* Output)
250 XRROutputInfo* result =
nullptr;
251 for (
int i = 0; i <
Resources->noutput; ++i)
255 XRRFreeOutputInfo(result);
260 if (!result || result->nameLen < 1)
262 if (result->connection != RR_Connected)
264 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Output '%1' is disconnected")
269 QString name(result->name);
270 if (name == qScreen->name())
272 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Matched '%1' to output %2")
273 .arg(qScreen->name()).arg(
Resources->outputs[i]));
279 XRRFreeOutputInfo(result);
291 auto * res = XRRGetScreenResourcesCurrent(mDisplay->
GetDisplay(), mDisplay->
GetRoot());
292 RROutput rroutput = 0;
297 auto edidproperty = XInternAtom(mDisplay->
GetDisplay(), RR_PROPERTY_RANDR_EDID,
298 static_cast<Bool
>(
false));
302 int propertycount = 0;
303 auto * properties = XRRListOutputProperties(mDisplay->
GetDisplay(), rroutput, &propertycount);
308 for (
int i = 0; i < propertycount; ++i)
310 if (properties[i] == edidproperty)
321 int actualformat = 0;
322 unsigned long bytesafter = 0;
323 unsigned long nitems = 0;
324 unsigned char* data =
nullptr;
325 if (XRRGetOutputProperty(mDisplay->
GetDisplay(), rroutput, edidproperty,
326 0, 128,
static_cast<Bool
>(
false),
static_cast<Bool
>(
false),
327 AnyPropertyType, &actualtype,
328 &actualformat, &nitems, &bytesafter, &data) == Success)
330 if (actualtype == XA_INTEGER && actualformat == 8)
331 m_edid =
MythEDID(
reinterpret_cast<const char*
>(data),
static_cast<int>(nitems));
339 XRRFreeOutputInfo(
output);
340 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