MythTV  master
mythnvcontrol.cpp
Go to the documentation of this file.
1 // MythTV
2 #include "mythnvcontrol.h"
4 
5 #define LOC QString("NVCtrl: ")
6 
7 static constexpr int NV_CTRL_TARGET_TYPE_X_SCREEN { 0 };
8 static constexpr int NV_CTRL_TARGET_TYPE_DISPLAY { 8 };
10 static constexpr uint NV_CTRL_VRR_ALLOWED { 408 };
11 static constexpr uint NV_CTRL_DISPLAY_VRR_MODE { 429 };
17 };
18 static constexpr uint NV_CTRL_DISPLAY_VRR_ENABLED { 431 };
19 static constexpr uint NV_CTRL_DISPLAY_VRR_MIN_REFRESH_RATE { 430 };
20 
27 void 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 {
111  if (s_gsyncResetOnExit)
112  {
113  LOG(VB_GENERAL, LOG_INFO, LOC + "Resetting GSync to desktop default");
115  s_gsyncResetOnExit = false;
116  }
117 }
118 
119 void 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 
180 MythNVControl::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  return static_cast<int>(data[1]);
221 }
QueryTargetBinary
bool(*)(Display *, int, int, unsigned int, unsigned int, unsigned char **, int *) QueryTargetBinary
Definition: mythnvcontrol.h:18
NV_CTRL_DISPLAY_VRR_MODE_GSYNC
@ NV_CTRL_DISPLAY_VRR_MODE_GSYNC
Definition: mythnvcontrol.cpp:14
NV_CTRL_VRR_ALLOWED
static constexpr uint NV_CTRL_VRR_ALLOWED
Definition: mythnvcontrol.cpp:10
NV_CTRL_DISPLAY_VRR_MODES
NV_CTRL_DISPLAY_VRR_MODES
Definition: mythnvcontrol.cpp:12
MythXDisplay::GetDisplay
Display * GetDisplay()
Definition: mythxdisplay.h:25
NV_CTRL_DISPLAY_VRR_MODE_GSYNC_COMPATIBLE
@ NV_CTRL_DISPLAY_VRR_MODE_GSYNC_COMPATIBLE
Definition: mythnvcontrol.cpp:15
NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN
static constexpr uint NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN
Definition: mythnvcontrol.cpp:9
MythXDisplay::GetScreen
int GetScreen() const
Definition: mythxdisplay.h:27
NVControl
std::shared_ptr< class MythNVControl > NVControl
Definition: mythnvcontrol.h:17
NV_CTRL_DISPLAY_VRR_MIN_REFRESH_RATE
static constexpr uint NV_CTRL_DISPLAY_VRR_MIN_REFRESH_RATE
Definition: mythnvcontrol.cpp:19
MythGSync::~MythGSync
~MythGSync() override
Definition: mythnvcontrol.cpp:109
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
Device
A device containing images (ie. USB stick, CD, storage group etc)
Definition: imagemanager.cpp:35
NV_CTRL_DISPLAY_VRR_ENABLED
static constexpr uint NV_CTRL_DISPLAY_VRR_ENABLED
Definition: mythnvcontrol.cpp:18
true
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:95
MythXDisplay::OpenMythXDisplay
static MythXDisplay * OpenMythXDisplay(bool Warn=true)
Definition: mythxdisplay.cpp:25
MythNVControl::MythNVControl
MythNVControl(const QString &Path, MythXDisplay *MDisplay)
Definition: mythnvcontrol.cpp:180
QueryScreenAttrib
bool(*)(Display *, int, unsigned int, unsigned int, int *) QueryScreenAttrib
Definition: mythnvcontrol.h:19
MythVRR
Definition: mythvrr.h:14
minor
#define minor(X)
Definition: compat.h:78
MythVRR::GSync
@ GSync
Definition: mythvrr.h:21
mythlogging.h
MythGSync::m_nvControl
NVControl m_nvControl
Definition: mythnvcontrol.h:35
NV_CTRL_TARGET_TYPE_DISPLAY
static constexpr int NV_CTRL_TARGET_TYPE_DISPLAY
Definition: mythnvcontrol.cpp:8
MythNVControl::m_display
MythXDisplay * m_display
Definition: mythnvcontrol.h:51
MythNVControl::~MythNVControl
~MythNVControl()
Definition: mythnvcontrol.cpp:190
MythGSync::CreateGSync
static MythVRRPtr CreateGSync(const NVControl &Device, MythVRRRange Range)
Definition: mythnvcontrol.cpp:54
MythNVControl::m_lib
QLibrary m_lib
Definition: mythnvcontrol.h:48
QueryTargetAttrib
bool(*)(Display *, int, int, unsigned int, unsigned int, int *) QueryTargetAttrib
Definition: mythnvcontrol.h:20
MythGSync::s_gsyncDefaultValue
static bool s_gsyncDefaultValue
Definition: mythnvcontrol.h:27
uint
unsigned int uint
Definition: compat.h:81
MythVRRRange
std::tuple< int, int, bool > MythVRRRange
Definition: mythedid.h:19
MythVRR::GSyncCompat
@ GSyncCompat
Definition: mythvrr.h:22
NV_CTRL_DISPLAY_VRR_MODE
static constexpr uint NV_CTRL_DISPLAY_VRR_MODE
Definition: mythnvcontrol.cpp:11
MythNVControl::m_queryBinary
QueryTargetBinary m_queryBinary
Definition: mythnvcontrol.h:52
NV_CTRL_DISPLAY_VRR_MODE_NONE
@ NV_CTRL_DISPLAY_VRR_MODE_NONE
Definition: mythnvcontrol.cpp:13
MythNVControl::Create
static NVControl Create()
Create a valid instance of MythNVControl.
Definition: mythnvcontrol.cpp:135
std
Definition: mythchrono.h:23
LOC
#define LOC
Definition: mythnvcontrol.cpp:5
MythXDisplay
Definition: mythxdisplay.h:15
MythGSync::MythGSync
MythGSync(NVControl Device, VRRType Type, bool Enabled, MythVRRRange Range)
Definition: mythnvcontrol.cpp:103
MythNVControl::GetDisplayID
int GetDisplayID() const
Definition: mythnvcontrol.cpp:196
SetAttribute
void(*)(Display *, int, unsigned int, unsigned int, int) SetAttribute
Definition: mythnvcontrol.h:21
mythnvcontrol.h
MythGSync::s_gsyncResetOnExit
static bool s_gsyncResetOnExit
Definition: mythnvcontrol.h:26
MythGSync::SetEnabled
void SetEnabled(bool Enable=true) override
Definition: mythnvcontrol.cpp:119
NV_CTRL_DISPLAY_VRR_MODE_GSYNC_COMPATIBLE_UNVALIDATED
@ NV_CTRL_DISPLAY_VRR_MODE_GSYNC_COMPATIBLE_UNVALIDATED
Definition: mythnvcontrol.cpp:16
NV_CTRL_TARGET_TYPE_X_SCREEN
static constexpr int NV_CTRL_TARGET_TYPE_X_SCREEN
Definition: mythnvcontrol.cpp:7
MythGSync::ForceGSync
static void ForceGSync(bool Enable)
Enable or disable GSync before the main window is created.
Definition: mythnvcontrol.cpp:27
MythVRRPtr
std::shared_ptr< class MythVRR > MythVRRPtr
Definition: mythvrr.h:11
MythVRR::VRRType
VRRType
Definition: mythvrr.h:17