MythTV master
mythnvcontrol.cpp
Go to the documentation of this file.
1#include "mythnvcontrol.h"
2
3#include <QLibrary>
4#include <QString>
5#include <QStringList>
6
8
10
11#include <X11/Xlib.h>
12
13#define LOC QString("NVCtrl: ")
14
15static constexpr int NV_CTRL_TARGET_TYPE_X_SCREEN { 0 };
16static constexpr int NV_CTRL_TARGET_TYPE_DISPLAY { 8 };
18static constexpr uint NV_CTRL_VRR_ALLOWED { 408 };
19static constexpr uint NV_CTRL_DISPLAY_VRR_MODE { 429 };
20enum NV_CTRL_DISPLAY_VRR_MODES : std::uint8_t {
25};
26static constexpr uint NV_CTRL_DISPLAY_VRR_ENABLED { 431 };
28
29using QueryTargetBinary = bool(*)(Display*,int,int,unsigned int,unsigned int, unsigned char**,int*);
30using QueryScreenAttrib = bool(*)(Display*,int,unsigned int,unsigned int,int*);
31using QueryTargetAttrib = bool(*)(Display*,int,int,unsigned int,unsigned int,int*);
32using SetAttribute = void(*)(Display*,int,unsigned int,unsigned int,int);
33
35{
36 public:
37 static NVControl Create();
39
40 int GetDisplayID() const;
41
42 protected:
43 MythNVControl(const QString& Path, MythXDisplay* MDisplay);
44 QLibrary m_lib;
45
46 public:
47 MythXDisplay* m_display { nullptr };
52};
53
60void MythGSync::ForceGSync(bool Enable)
61{
62 auto gsync = CreateGSync({0, 0, false});
63 if (!gsync)
64 {
65 LOG(VB_GENERAL, LOG_INFO, LOC + "No GSync support detected - cannot force");
66 return;
67 }
68
69 if (gsync->Enabled() == Enable)
70 {
71 LOG(VB_GENERAL, LOG_INFO, LOC + QString("GSync already %1")
72 .arg(Enable ? "enabled" : "disabled"));
73 return;
74 }
75
76 gsync->SetEnabled(Enable);
77 // Release GSync to ensure the state is not reset when it is deleted
78 gsync = nullptr;
79 s_gsyncDefaultValue = !Enable;
80 s_gsyncResetOnExit = true;
81 LOG(VB_GENERAL, LOG_INFO, LOC + (Enable ? "Enabled" : "Disabled"));
82}
83
85{
87 if (!Device)
88 return nullptr;
89
90 auto displayid = Device->GetDisplayID();
91 if (displayid < 0)
92 return nullptr;
93
94 auto * display = Device->m_display->GetDisplay();
95 int enabled = 0;
96 if (!Device->m_queryTarget(display, NV_CTRL_TARGET_TYPE_DISPLAY, displayid,
97 0, NV_CTRL_DISPLAY_VRR_ENABLED, &enabled) || !enabled)
98 {
99 return nullptr;
100 }
101
102 // We have a a valid device that has GSync/VRR available
103 int type = 0;
104 int minrate = 0;
105 int allowed = 0;
106 Device->m_queryTarget(display, NV_CTRL_TARGET_TYPE_DISPLAY, displayid, 0,
108 Device->m_queryTarget(display, NV_CTRL_TARGET_TYPE_DISPLAY, displayid, 0,
110 Device->m_queryScreen(display, Device->m_display->GetScreen(), 0, NV_CTRL_VRR_ALLOWED, &allowed);
111
112 if (minrate > 0)
113 {
114 std::get<0>(Range) = minrate;
115 std::get<2>(Range) = true;
116 }
117
119 return std::shared_ptr<MythVRR>(new MythGSync(Device, vrrtype, allowed > 0, Range));
120}
121
135 : MythVRR(true, Type, Enabled, Range),
136 m_nvControl(std::move(Device))
137{
138}
139
141{
143 {
144 LOG(VB_GENERAL, LOG_INFO, LOC + "Resetting GSync to desktop default");
146 s_gsyncResetOnExit = false;
147 }
148}
149
150void MythGSync::SetEnabled(bool Enable)
151{
152 if (!m_nvControl || !m_nvControl->m_display)
153 return;
154 int enable = Enable ? 1 : 0;
155 auto * display = m_nvControl->m_display;
156 m_nvControl->m_setAttrib(display->GetDisplay(), display->GetScreen(), 0, NV_CTRL_VRR_ALLOWED, enable);
157}
158
167{
168 static const QStringList s_paths = { "libXNVCtrl", "libXNVCtrl.so.0" };
169 static bool s_available = false;
170 static bool s_checked = false;
171 if (s_checked && !s_available)
172 return nullptr;
173 s_checked = true;
174
175 // Is libxnvctrl available?
176 for (const auto & path : s_paths)
177 {
178 if (QLibrary lib(path); lib.load())
179 {
180 s_available = true;
181 auto isnvscreen = reinterpret_cast<bool(*)(Display*,int)>(lib.resolve("XNVCTRLIsNvScreen"));
182 auto queryversion = reinterpret_cast<bool(*)(Display*,int,int)>(lib.resolve("XNVCTRLQueryVersion"));
183 if (isnvscreen && queryversion)
184 {
185 auto * xdisplay = MythXDisplay::OpenMythXDisplay(false);
186 if (xdisplay && xdisplay->GetDisplay())
187 {
188 int major = 0;
189 int minor = 0;
190 if (isnvscreen(xdisplay->GetDisplay(), xdisplay->GetScreen()) &&
191 queryversion(xdisplay->GetDisplay(), major, minor))
192 {
193 if (auto res = std::shared_ptr<MythNVControl>(new MythNVControl(path, xdisplay));
194 res->m_queryBinary && res->m_queryScreen && res->m_queryTarget && res->m_setAttrib)
195 {
196 return res;
197 }
198 }
199 }
200 delete xdisplay;
201 }
202 lib.unload();
203 }
204 }
205 return nullptr;
206}
207
211MythNVControl::MythNVControl(const QString &Path, MythXDisplay* MDisplay)
212 : m_lib(Path),
213 m_display(MDisplay),
214 m_queryBinary(reinterpret_cast<QueryTargetBinary>(m_lib.resolve("XNVCTRLQueryTargetBinaryData"))),
215 m_queryScreen(reinterpret_cast<QueryScreenAttrib>(m_lib.resolve("XNVCTRLQueryAttribute"))),
216 m_queryTarget(reinterpret_cast<QueryTargetAttrib>(m_lib.resolve("XNVCTRLQueryTargetAttribute"))),
217 m_setAttrib(reinterpret_cast<SetAttribute>(m_lib.resolve("XNVCTRLSetAttribute")))
218{
219}
220
222{
223 delete m_display;
224 m_lib.unload();
225}
226
228{
229 auto * display = m_display->GetDisplay();
230 auto screen = m_display->GetScreen();
231 uint32_t * data = nullptr;
232 int size = 0;
233 if (!m_queryBinary(display, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0,
235 reinterpret_cast<unsigned char **>(&data), &size))
236 {
237 LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to retrieve display id for screen");
238 return -1;
239 }
240
241 // Minimum result size is 4bytes for number of ids and 4bytes for each id
242 if (size < 8)
243 return -1;
244
245 if (size > 8)
246 {
247 LOG(VB_GENERAL, LOG_INFO, LOC + QString("%1 display id's returned - using first")
248 .arg((size - 4) / 4));
249 }
250
251 int dispId = static_cast<int>(data[1]);
252 // Memory allocated by XNVCTRLQueryTargetBinaryData
253 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
254 free(data);
255 return dispId;
256}
A device containing images (ie. USB stick, CD, storage group etc)
MythGSync(NVControl Device, VRRType Type, bool Enabled, MythVRRRange Range)
void SetEnabled(bool Enable=true) override
static bool s_gsyncResetOnExit
Definition: mythnvcontrol.h:13
static bool s_gsyncDefaultValue
Definition: mythnvcontrol.h:14
~MythGSync() override
static MythVRRPtr CreateGSync(MythVRRRange Range)
NVControl m_nvControl
Definition: mythnvcontrol.h:22
static void ForceGSync(bool Enable)
Enable or disable GSync before the main window is created.
A simple wrapper around libXNVCtrl - which is dynamically loaded on demand.
static NVControl Create()
Create a valid instance of MythNVControl.
SetAttribute m_setAttrib
MythXDisplay * m_display
MythNVControl(const QString &Path, MythXDisplay *MDisplay)
QueryTargetBinary m_queryBinary
int GetDisplayID() const
QueryScreenAttrib m_queryScreen
QueryTargetAttrib m_queryTarget
VRRType
Definition: mythvrr.h:19
@ GSyncCompat
Definition: mythvrr.h:23
@ GSync
Definition: mythvrr.h:22
int GetScreen() const
Definition: mythxdisplay.h:25
Display * GetDisplay()
Definition: mythxdisplay.h:24
static MythXDisplay * OpenMythXDisplay(bool Warn=true)
unsigned int uint
Definition: compat.h:60
#define minor(X)
Definition: compat.h:58
std::tuple< int, int, bool > MythVRRRange
Definition: mythedid.h:19
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
static constexpr uint NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN
#define LOC
bool(*)(Display *, int, int, unsigned int, unsigned int, unsigned char **, int *) QueryTargetBinary
static constexpr uint NV_CTRL_VRR_ALLOWED
bool(*)(Display *, int, int, unsigned int, unsigned int, int *) QueryTargetAttrib
static constexpr uint NV_CTRL_DISPLAY_VRR_ENABLED
static constexpr int NV_CTRL_TARGET_TYPE_X_SCREEN
NV_CTRL_DISPLAY_VRR_MODES
@ NV_CTRL_DISPLAY_VRR_MODE_GSYNC_COMPATIBLE
@ NV_CTRL_DISPLAY_VRR_MODE_NONE
@ NV_CTRL_DISPLAY_VRR_MODE_GSYNC
@ NV_CTRL_DISPLAY_VRR_MODE_GSYNC_COMPATIBLE_UNVALIDATED
void(*)(Display *, int, unsigned int, unsigned int, int) SetAttribute
static constexpr int NV_CTRL_TARGET_TYPE_DISPLAY
bool(*)(Display *, int, unsigned int, unsigned int, int *) QueryScreenAttrib
static constexpr uint NV_CTRL_DISPLAY_VRR_MIN_REFRESH_RATE
static constexpr uint NV_CTRL_DISPLAY_VRR_MODE
std::shared_ptr< class MythNVControl > NVControl
Definition: mythnvcontrol.h:8
std::shared_ptr< class MythVRR > MythVRRPtr
Definition: mythvrr.h:12
STL namespace.
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:86