MythTV master
mythnvcontrol.cpp
Go to the documentation of this file.
1// MythTV
2#include "mythnvcontrol.h"
4
5#define LOC QString("NVCtrl: ")
6
7static constexpr int NV_CTRL_TARGET_TYPE_X_SCREEN { 0 };
8static constexpr int NV_CTRL_TARGET_TYPE_DISPLAY { 8 };
10static constexpr uint NV_CTRL_VRR_ALLOWED { 408 };
11static constexpr uint NV_CTRL_DISPLAY_VRR_MODE { 429 };
12enum NV_CTRL_DISPLAY_VRR_MODES : std::uint8_t {
17};
18static constexpr uint NV_CTRL_DISPLAY_VRR_ENABLED { 431 };
20
27void MythGSync::ForceGSync(bool Enable)
28{
29 if (auto nvcontrol = MythNVControl::Create(); nvcontrol)
30 {
31 auto gsync = CreateGSync(nvcontrol, {0,0,false});
32 if (!gsync)
33 {
34 LOG(VB_GENERAL, LOG_INFO, LOC + "No GSync support detected - cannot force");
35 return;
36 }
37
38 if (gsync->Enabled() == Enable)
39 {
40 LOG(VB_GENERAL, LOG_INFO, LOC + QString("GSync already %1abled")
41 .arg(Enable ? "en" : "dis"));
42 return;
43 }
44
45 gsync->SetEnabled(Enable);
46 // Release GSync to ensure the state is not reset when it is deleted
47 gsync = nullptr;
48 s_gsyncDefaultValue = !Enable;
49 s_gsyncResetOnExit = true;
50 LOG(VB_GENERAL, LOG_INFO, LOC + (Enable ? "Enabled" : "Disabled"));
51 }
52}
53
55{
56 if (!Device)
57 return nullptr;
58
59 auto displayid = Device->GetDisplayID();
60 if (displayid < 0)
61 return nullptr;
62
63 auto * display = Device->m_display->GetDisplay();
64 int enabled = 0;
65 if (!Device->m_queryTarget(display, NV_CTRL_TARGET_TYPE_DISPLAY, displayid,
66 0, NV_CTRL_DISPLAY_VRR_ENABLED, &enabled) || !enabled)
67 {
68 return nullptr;
69 }
70
71 // We have a a valid device that has GSync/VRR available
72 int type = 0;
73 int minrate = 0;
74 int allowed = 0;
75 Device->m_queryTarget(display, NV_CTRL_TARGET_TYPE_DISPLAY, displayid, 0,
77 Device->m_queryTarget(display, NV_CTRL_TARGET_TYPE_DISPLAY, displayid, 0,
79 Device->m_queryScreen(display, Device->m_display->GetScreen(), 0, NV_CTRL_VRR_ALLOWED, &allowed);
80
81 if (minrate > 0)
82 {
83 std::get<0>(Range) = minrate;
84 std::get<2>(Range) = true;
85 }
86
88 return std::shared_ptr<MythVRR>(new MythGSync(Device, vrrtype, allowed > 0, Range));
89}
90
104 : MythVRR(true, Type, Enabled, Range),
105 m_nvControl(std::move(Device))
106{
107}
108
110{
112 {
113 LOG(VB_GENERAL, LOG_INFO, LOC + "Resetting GSync to desktop default");
115 s_gsyncResetOnExit = false;
116 }
117}
118
119void MythGSync::SetEnabled(bool Enable)
120{
121 if (!m_nvControl || !m_nvControl->m_display)
122 return;
123 int enable = Enable ? 1 : 0;
124 auto * display = m_nvControl->m_display;
125 m_nvControl->m_setAttrib(display->GetDisplay(), display->GetScreen(), 0, NV_CTRL_VRR_ALLOWED, enable);
126}
127
136{
137 static const QStringList s_paths = { "libXNVCtrl", "libXNVCtrl.so.0" };
138 static bool s_available = false;
139 static bool s_checked = false;
140 if (s_checked && !s_available)
141 return nullptr;
142 s_checked = true;
143
144 // Is libxnvctrl available?
145 for (const auto & path : s_paths)
146 {
147 if (QLibrary lib(path); lib.load())
148 {
149 s_available = true;
150 auto isnvscreen = reinterpret_cast<bool(*)(Display*,int)>(lib.resolve("XNVCTRLIsNvScreen"));
151 auto queryversion = reinterpret_cast<bool(*)(Display*,int,int)>(lib.resolve("XNVCTRLQueryVersion"));
152 if (isnvscreen && queryversion)
153 {
154 auto * xdisplay = MythXDisplay::OpenMythXDisplay(false);
155 if (xdisplay && xdisplay->GetDisplay())
156 {
157 int major = 0;
158 int minor = 0;
159 if (isnvscreen(xdisplay->GetDisplay(), xdisplay->GetScreen()) &&
160 queryversion(xdisplay->GetDisplay(), major, minor))
161 {
162 if (auto res = std::shared_ptr<MythNVControl>(new MythNVControl(path, xdisplay));
163 res->m_queryBinary && res->m_queryScreen && res->m_queryTarget && res->m_setAttrib)
164 {
165 return res;
166 }
167 }
168 }
169 delete xdisplay;
170 }
171 lib.unload();
172 }
173 }
174 return nullptr;
175}
176
180MythNVControl::MythNVControl(const QString &Path, MythXDisplay* MDisplay)
181 : m_lib(Path),
182 m_display(MDisplay),
183 m_queryBinary(reinterpret_cast<QueryTargetBinary>(m_lib.resolve("XNVCTRLQueryTargetBinaryData"))),
184 m_queryScreen(reinterpret_cast<QueryScreenAttrib>(m_lib.resolve("XNVCTRLQueryAttribute"))),
185 m_queryTarget(reinterpret_cast<QueryTargetAttrib>(m_lib.resolve("XNVCTRLQueryTargetAttribute"))),
186 m_setAttrib(reinterpret_cast<SetAttribute>(m_lib.resolve("XNVCTRLSetAttribute")))
187{
188}
189
191{
192 delete m_display;
193 m_lib.unload();
194}
195
197{
198 auto * display = m_display->GetDisplay();
199 auto screen = m_display->GetScreen();
200 uint32_t * data = nullptr;
201 int size = 0;
202 if (!m_queryBinary(display, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0,
204 reinterpret_cast<unsigned char **>(&data), &size))
205 {
206 LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to retrieve display id for screen");
207 return -1;
208 }
209
210 // Minimum result size is 4bytes for number of ids and 4bytes for each id
211 if (size < 8)
212 return -1;
213
214 if (size > 8)
215 {
216 LOG(VB_GENERAL, LOG_INFO, LOC + QString("%1 display id's returned - using first")
217 .arg((size - 4) / 4));
218 }
219
220 int dispId = static_cast<int>(data[1]);
221 free(data);
222 return dispId;
223}
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:26
static MythVRRPtr CreateGSync(const NVControl &Device, MythVRRRange Range)
static bool s_gsyncDefaultValue
Definition: mythnvcontrol.h:27
~MythGSync() override
NVControl m_nvControl
Definition: mythnvcontrol.h:35
static void ForceGSync(bool Enable)
Enable or disable GSync before the main window is created.
static NVControl Create()
Create a valid instance of MythNVControl.
QLibrary m_lib
Definition: mythnvcontrol.h:48
MythXDisplay * m_display
Definition: mythnvcontrol.h:51
MythNVControl(const QString &Path, MythXDisplay *MDisplay)
QueryTargetBinary m_queryBinary
Definition: mythnvcontrol.h:52
int GetDisplayID() const
VRRType
Definition: mythvrr.h:19
@ GSyncCompat
Definition: mythvrr.h:23
@ GSync
Definition: mythvrr.h:22
int GetScreen() const
Definition: mythxdisplay.h:27
Display * GetDisplay()
Definition: mythxdisplay.h:25
static MythXDisplay * OpenMythXDisplay(bool Warn=true)
#define minor(X)
Definition: compat.h:74
unsigned int uint
Definition: freesurround.h:24
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
static constexpr uint NV_CTRL_VRR_ALLOWED
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
static constexpr int NV_CTRL_TARGET_TYPE_DISPLAY
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:17
bool(*)(Display *, int, int, unsigned int, unsigned int, unsigned char **, int *) QueryTargetBinary
Definition: mythnvcontrol.h:18
bool(*)(Display *, int, int, unsigned int, unsigned int, int *) QueryTargetAttrib
Definition: mythnvcontrol.h:20
void(*)(Display *, int, unsigned int, unsigned int, int) SetAttribute
Definition: mythnvcontrol.h:21
bool(*)(Display *, int, unsigned int, unsigned int, int *) QueryScreenAttrib
Definition: mythnvcontrol.h:19
std::shared_ptr< class MythVRR > MythVRRPtr
Definition: mythvrr.h:12
STL namespace.
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:95