diff --git a/ColorControl.sln b/ColorControl.sln
index c50f372..d2a632b 100644
--- a/ColorControl.sln
+++ b/ColorControl.sln
@@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorControl", "ColorContro
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nspector", "Nspector\Nspector.csproj", "{76797290-48F5-4A82-86C3-FAD25DAE4500}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvAPIWrapper", "NvAPIWrapper\NvAPIWrapper.csproj", "{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -31,6 +33,14 @@ Global
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Release|Any CPU.Build.0 = Release|Any CPU
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Release|x64.ActiveCfg = Release|Any CPU
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Release|x64.Build.0 = Release|Any CPU
+ {42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Debug|x64.Build.0 = Debug|Any CPU
+ {42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Release|x64.ActiveCfg = Release|Any CPU
+ {42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj
index 3db78ac..986d732 100644
--- a/ColorControl/ColorControl.csproj
+++ b/ColorControl/ColorControl.csproj
@@ -93,13 +93,13 @@
-
+
diff --git a/ColorControl/Common/PipeUtils.cs b/ColorControl/Common/PipeUtils.cs
index 7b300fb..d173640 100644
--- a/ColorControl/Common/PipeUtils.cs
+++ b/ColorControl/Common/PipeUtils.cs
@@ -10,12 +10,12 @@ namespace ColorControl.Common
{
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
- public static string SendMessage(string message)
+ public static string SendMessage(string message, int timeout = 500)
{
var pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.None);
try
{
- pipeClient.Connect(500);
+ pipeClient.Connect(timeout);
try
{
var ss = new StreamString(pipeClient);
@@ -39,11 +39,11 @@ namespace ColorControl.Common
}
}
- public static SvcResultMessage SendMessage(SvcMessage message)
+ public static SvcResultMessage SendMessage(SvcMessage message, int timeout = 500)
{
var messageJson = JsonConvert.SerializeObject(message);
- var resultJson = SendMessage(messageJson);
+ var resultJson = SendMessage(messageJson, timeout);
if (resultJson == null)
{
diff --git a/ColorControl/Common/Utils.cs b/ColorControl/Common/Utils.cs
index 328fca3..7b645b1 100644
--- a/ColorControl/Common/Utils.cs
+++ b/ColorControl/Common/Utils.cs
@@ -1242,5 +1242,8 @@ The best and suggested method to provide this is via a Windows Service. Only whe
{
return SHA256CheckSum(filePath1) == SHA256CheckSum(filePath2);
}
+
+ public static string ToUnitString(this uint value, int div = 1000, string units = "MHz") => $"{value / div}{units}";
+ public static string ToUnitString(this int value, int div = 1000, string units = "MHz") => $"{value / div}{units}";
}
}
diff --git a/ColorControl/Forms/FormUtils.cs b/ColorControl/Forms/FormUtils.cs
index 88169f3..91b3113 100644
--- a/ColorControl/Forms/FormUtils.cs
+++ b/ColorControl/Forms/FormUtils.cs
@@ -198,6 +198,11 @@ namespace ColorControl.Forms
item.Click += onClick;
}
}
+ else
+ {
+ item.Text = text;
+ item.Tag = tag;
+ }
//else if (onClick != null)
//{
// RemoveEvents(item, "Click");
diff --git a/ColorControl/Forms/MessageForms.cs b/ColorControl/Forms/MessageForms.cs
index 75f627f..ea33604 100644
--- a/ColorControl/Forms/MessageForms.cs
+++ b/ColorControl/Forms/MessageForms.cs
@@ -16,6 +16,8 @@ namespace ColorControl.Forms
DropDown,
Flags,
Shortcut,
+ CheckBox,
+ TrackBar
}
public class FieldDefinition
@@ -29,10 +31,14 @@ namespace ColorControl.Forms
public object Value { get; set; }
public int ValueAsInt => int.Parse(Value.ToString());
+ public uint ValueAsUInt => uint.Parse(Value.ToString());
}
public class MessageForm : Form
{
+ private ToolTip _toolTip;
+ public Dictionary _controls = new();
+
public void edtShortcut_KeyDown(object sender, KeyEventArgs e)
{
((TextBox)sender).Text = Utils.FormatKeyboardShortcut(e);
@@ -42,6 +48,25 @@ namespace ColorControl.Forms
{
Utils.HandleKeyboardShortcutUp(e);
}
+
+ public void TrackBar_Scroll(object sender, EventArgs e)
+ {
+ var trackBar = sender as TrackBar;
+ var edit = (NumericUpDown)_controls[trackBar];
+
+ edit.Value = trackBar.Value;
+
+ _toolTip ??= new ToolTip();
+ _toolTip.Show(trackBar.Value.ToString(), trackBar, 50, 10, 1500);
+ }
+
+ public void TrackBarEdit_ValueChanged(object sender, EventArgs e)
+ {
+ var edit = (NumericUpDown)sender;
+ var trackBar = (TrackBar)_controls.First(c => c.Value == edit).Key;
+
+ trackBar.Value = (int)edit.Value;
+ }
}
public static Form MainForm;
@@ -179,12 +204,30 @@ namespace ColorControl.Forms
if (field.Values != null && field.Values.Any())
{
comboBox.Items.AddRange(field.Values.ToArray());
- comboBox.SelectedIndex = field.Value is string strValue ? comboBox.Items.IndexOf(strValue) : 0;
+ comboBox.SelectedIndex = field.Value != null ? comboBox.Items.IndexOf(field.Value.ToString()) : 0;
+
+ if (comboBox.SelectedIndex == -1)
+ {
+ comboBox.SelectedIndex = 0;
+ }
}
control = comboBox;
break;
+ case FieldType.CheckBox:
+ var checkBox = new CheckBox
+ {
+ Left = 40,
+ Top = top,
+ Width = 24,
+ };
+
+ checkBox.Checked = field.Value is bool boolValue && boolValue;
+
+ control = checkBox;
+ break;
+
case FieldType.Flags:
var checkedListBox = new CheckedListBox
{
@@ -215,6 +258,43 @@ namespace ColorControl.Forms
control = checkedListBox;
break;
+ case FieldType.TrackBar:
+ var trackBar = new TrackBar { Left = 40, Top = top, Width = 300 };
+ var trackBarEdit = new NumericUpDown() { Left = trackBar.Left + trackBar.Width + 10, Top = top + 10, Width = 90 };
+
+ trackBarEdit.ValueChanged += prompt.TrackBarEdit_ValueChanged;
+
+ prompt._controls.Add(trackBar, trackBarEdit);
+
+ trackBar.Orientation = Orientation.Horizontal;
+ trackBar.TickStyle = TickStyle.Both;
+ trackBar.Scroll += prompt.TrackBar_Scroll;
+
+ if (field.MinValue != field.MaxValue)
+ {
+ trackBar.Minimum = (int)field.MinValue;
+ trackBar.Maximum = (int)field.MaxValue;
+ trackBar.TickFrequency = (trackBar.Maximum - trackBar.Minimum) / 100;
+
+ trackBarEdit.Minimum = field.MinValue;
+ trackBarEdit.Maximum = field.MaxValue;
+ }
+
+ if (field.Value != null)
+ {
+ trackBar.Value = field.Value is uint ? (int)(uint)field.Value : (int)field.Value;
+ trackBarEdit.Value = trackBar.Value;
+ }
+
+ top += trackBar.Height - 25;
+ prompt.Height += trackBar.Height - 25;
+
+ prompt.Controls.Add(trackBarEdit);
+
+ control = trackBar;
+ break;
+
+
default:
continue;
}
@@ -248,6 +328,21 @@ namespace ColorControl.Forms
field.Value = compoundValue;
break;
+
+ case FieldType.CheckBox:
+ var checkBox = (CheckBox)box;
+
+ field.Value = checkBox.Checked;
+
+ break;
+
+ case FieldType.TrackBar:
+ var trackBar = (TrackBar)box;
+
+ field.Value = trackBar.Value;
+
+ break;
+
default:
field.Value = box.Text.Trim();
break;
diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs
index 4048312..fea08e3 100644
--- a/ColorControl/MainForm.Designer.cs
+++ b/ColorControl/MainForm.Designer.cs
@@ -82,6 +82,8 @@
this.miHDREnabled = new System.Windows.Forms.ToolStripMenuItem();
this.mnuNvDriverSettings = new System.Windows.Forms.ToolStripMenuItem();
this.miNvDriverSettingsIncluded = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnuNvOverclocking = new System.Windows.Forms.ToolStripMenuItem();
+ this.miNvOverclockingIncluded = new System.Windows.Forms.ToolStripMenuItem();
this.miNvCopyId = new System.Windows.Forms.ToolStripMenuItem();
this.btnApply = new System.Windows.Forms.Button();
this.lvNvPresets = new System.Windows.Forms.ListView();
@@ -359,33 +361,31 @@
this.lblNvOverclock.Location = new System.Drawing.Point(578, 496);
this.lblNvOverclock.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lblNvOverclock.Name = "lblNvOverclock";
- this.lblNvOverclock.Size = new System.Drawing.Size(62, 15);
+ this.lblNvOverclock.Size = new System.Drawing.Size(51, 15);
this.lblNvOverclock.TabIndex = 66;
- this.lblNvOverclock.Text = "Set clocks:";
- this.lblNvOverclock.Visible = false;
+ this.lblNvOverclock.Text = "OC info:";
//
// edtNvOverclock
//
- this.edtNvOverclock.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.edtNvOverclock.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
this.edtNvOverclock.Enabled = false;
this.edtNvOverclock.Location = new System.Drawing.Point(648, 493);
this.edtNvOverclock.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.edtNvOverclock.Name = "edtNvOverclock";
- this.edtNvOverclock.Size = new System.Drawing.Size(212, 23);
+ this.edtNvOverclock.Size = new System.Drawing.Size(457, 23);
this.edtNvOverclock.TabIndex = 65;
- this.edtNvOverclock.Visible = false;
//
// btnNvSetClocks
//
this.btnNvSetClocks.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
- this.btnNvSetClocks.Location = new System.Drawing.Point(866, 490);
+ this.btnNvSetClocks.Location = new System.Drawing.Point(868, 433);
this.btnNvSetClocks.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.btnNvSetClocks.Name = "btnNvSetClocks";
this.btnNvSetClocks.Size = new System.Drawing.Size(88, 27);
this.btnNvSetClocks.TabIndex = 64;
this.btnNvSetClocks.Text = "Change...";
this.btnNvSetClocks.UseVisualStyleBackColor = true;
- this.btnNvSetClocks.Visible = false;
this.btnNvSetClocks.Click += new System.EventHandler(this.btnNvSetClocks_Click);
//
// lblNvGpuInfo
@@ -398,18 +398,17 @@
this.lblNvGpuInfo.Size = new System.Drawing.Size(31, 15);
this.lblNvGpuInfo.TabIndex = 63;
this.lblNvGpuInfo.Text = "Info:";
- this.lblNvGpuInfo.Visible = false;
//
// edtNvGpuInfo
//
- this.edtNvGpuInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.edtNvGpuInfo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
this.edtNvGpuInfo.Enabled = false;
this.edtNvGpuInfo.Location = new System.Drawing.Point(648, 466);
this.edtNvGpuInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.edtNvGpuInfo.Name = "edtNvGpuInfo";
- this.edtNvGpuInfo.Size = new System.Drawing.Size(212, 23);
+ this.edtNvGpuInfo.Size = new System.Drawing.Size(457, 23);
this.edtNvGpuInfo.TabIndex = 62;
- this.edtNvGpuInfo.Visible = false;
//
// lblNvGPU
//
@@ -421,7 +420,6 @@
this.lblNvGPU.Size = new System.Drawing.Size(33, 15);
this.lblNvGPU.TabIndex = 61;
this.lblNvGPU.Text = "GPU:";
- this.lblNvGPU.Visible = false;
//
// cbxNvGPU
//
@@ -433,7 +431,7 @@
this.cbxNvGPU.Name = "cbxNvGPU";
this.cbxNvGPU.Size = new System.Drawing.Size(212, 23);
this.cbxNvGPU.TabIndex = 60;
- this.cbxNvGPU.Visible = false;
+ this.cbxNvGPU.SelectedIndexChanged += new System.EventHandler(this.cbxNvGPU_SelectedIndexChanged);
//
// btnNvSettings
//
@@ -595,9 +593,10 @@
this.miNvPresetDithering,
this.miNvHDR,
this.mnuNvDriverSettings,
+ this.mnuNvOverclocking,
this.miNvCopyId});
this.mnuNvPresets.Name = "mnuNvPresets";
- this.mnuNvPresets.Size = new System.Drawing.Size(185, 230);
+ this.mnuNvPresets.Size = new System.Drawing.Size(185, 252);
this.mnuNvPresets.Opening += new System.ComponentModel.CancelEventHandler(this.mnuNvPresets_Opening);
//
// miNvApply
@@ -838,6 +837,21 @@
this.miNvDriverSettingsIncluded.Text = "Included";
this.miNvDriverSettingsIncluded.Click += new System.EventHandler(this.miNvDriverSettingsIncluded_Click);
//
+ // mnuNvOverclocking
+ //
+ this.mnuNvOverclocking.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.miNvOverclockingIncluded});
+ this.mnuNvOverclocking.Name = "mnuNvOverclocking";
+ this.mnuNvOverclocking.Size = new System.Drawing.Size(184, 22);
+ this.mnuNvOverclocking.Text = "Overclocking";
+ //
+ // miNvOverclockingIncluded
+ //
+ this.miNvOverclockingIncluded.Name = "miNvOverclockingIncluded";
+ this.miNvOverclockingIncluded.Size = new System.Drawing.Size(120, 22);
+ this.miNvOverclockingIncluded.Text = "Included";
+ this.miNvOverclockingIncluded.Click += new System.EventHandler(this.miNvOverclockingIncluded_Click);
+ //
// miNvCopyId
//
this.miNvCopyId.Name = "miNvCopyId";
@@ -3168,7 +3182,6 @@
private System.Windows.Forms.Button btnNvPresetDelete;
private System.Windows.Forms.Button btnAddModesNv;
private System.Windows.Forms.ToolStripMenuItem miNvApply;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.GroupBox grpGeneralOptions;
private System.Windows.Forms.CheckBox chkStartMinimized;
private System.Windows.Forms.CheckBox chkStartAfterLogin;
@@ -3385,6 +3398,8 @@
private System.Windows.Forms.Button btnNvSetClocks;
private System.Windows.Forms.Label lblNvOverclock;
private System.Windows.Forms.TextBox edtNvOverclock;
+ private System.Windows.Forms.ToolStripMenuItem mnuNvOverclocking;
+ private System.Windows.Forms.ToolStripMenuItem miNvOverclockingIncluded;
}
}
diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs
index 49aa5a3..9bca56c 100644
--- a/ColorControl/MainForm.cs
+++ b/ColorControl/MainForm.cs
@@ -209,7 +209,7 @@ namespace ColorControl
catch (Exception ex)
{
//Logger.Error("Error initializing NvService: " + e.ToLogString());
- Logger.Debug($"No NVIDIA device detected: {ex.Message}");
+ Logger.Debug($"No NVIDIA device detected: {ex.ToLogString()}");
tcMain.TabPages.Remove(tabNVIDIA);
}
}
@@ -577,24 +577,23 @@ namespace ColorControl
}
}
- //cbxNvGPU.Items.Clear();
- //cbxNvGPU.Items.AddRange(gpus.ToArray());
- //if (cbxNvGPU.Items.Count > 0)
- //{
- // cbxNvGPU.SelectedIndex = 0;
-
- // var gpu = gpus[0];
-
- // var gpuThermal = gpu.ThermalInformation.ThermalSensors.FirstOrDefault(s => s.Target == NvAPIWrapper.Native.GPU.ThermalSettingsTarget.GPU);
-
- // edtNvGpuInfo.Text = $"GPU: {gpu.CurrentClockFrequencies.GraphicsClock.Frequency / 1000}MHz @ {gpuThermal.CurrentTemperature}°C, Mem: {gpu.CurrentClockFrequencies.MemoryClock.Frequency / 1000}MHz";
-
- // edtNvOverclock.Text = _nvService.GetGpuClocks(gpu);
- //}
+ UpdateNvGpuInfo(gpus);
FormUtils.SetNotifyIconText(_trayIcon, text);
}
+ private void UpdateNvGpuInfo(List gpus = null)
+ {
+ gpus ??= _nvService.GetGPUs();
+
+ cbxNvGPU.Items.Clear();
+ cbxNvGPU.Items.AddRange(gpus.ToArray());
+ if (cbxNvGPU.Items.Count > 0 && cbxNvGPU.SelectedIndex == -1)
+ {
+ cbxNvGPU.SelectedIndex = 0;
+ }
+ }
+
private void UpdateDisplayInfoItemsAmd()
{
var displays = _amdService?.GetDisplayInfos();
@@ -724,7 +723,7 @@ namespace ColorControl
var preset = GetSelectedNvPreset();
var enabled = preset != null;
- FormUtils.EnableControls(tabNVIDIA, enabled, new List { lvNvPresets, btnAddModesNv, btnChange, edtNvGpuInfo, btnNvSetClocks, btnNvSettings });
+ FormUtils.EnableControls(tabNVIDIA, enabled, new List { lvNvPresets, btnAddModesNv, btnChange, edtNvGpuInfo, btnNvSetClocks, btnNvSettings, edtNvOverclock });
if (enabled)
{
@@ -1223,6 +1222,7 @@ NOTE: installing the service may cause a User Account Control popup.");
miNvCopyId.Visible = presetItemsVisible;
miNvDriverSettingsIncluded.Visible = presetItemsVisible;
mnuNvDriverSettings.Enabled = preset != null;
+ mnuNvOverclocking.Visible = preset != null && _nvService.Config.ShowOverclocking;
if (preset == null)
{
@@ -1301,6 +1301,9 @@ NOTE: installing the service may cause a User Account Control popup.");
mnuNvResolution.Font = _menuItemFonts[preset.applyResolution];
miNvPresetDithering.Font = _menuItemFonts[preset.applyDithering];
miNvHDR.Font = _menuItemFonts[preset.applyHDR];
+ mnuNvOverclocking.Font = _menuItemFonts[preset.applyOverclocking];
+
+ BuildNvOverclockingMenu(preset);
UpdateNvPresetMenuFont();
@@ -1309,6 +1312,52 @@ NOTE: installing the service may cause a User Account Control popup.");
mnuNvDriverSettings.Font = _menuItemFonts[preset.applyDriverSettings];
}
+ private void BuildNvOverclockingMenu(NvPreset preset)
+ {
+ miNvOverclockingIncluded.Checked = preset.applyOverclocking;
+
+ var gpus = _nvService.GetGPUs();
+
+ foreach (var gpu in gpus)
+ {
+ var gpuPciId = gpu.BusInformation.PCIIdentifiers.ToString();
+
+ var name = $"{mnuNvOverclocking.Name}_{gpu.GPUId}";
+
+ var gpuItem = FormUtils.BuildMenuItem(mnuNvOverclocking.DropDownItems, name, gpu.FullName);
+
+ var subName = $"{name}_change";
+
+ var ocSettings = preset.ocSettings.FirstOrDefault(s => s.PCIIdentifier == gpuPciId) ?? new NvGpuOcSettings { PCIIdentifier = gpuPciId };
+
+ var subText = $"{ocSettings} (click to change)";
+
+ var subItem = FormUtils.BuildMenuItem(gpuItem.DropDownItems, subName, subText, ocSettings, nvChangeOverclockingMenuItem_Click);
+ }
+ }
+
+ private void nvChangeOverclockingMenuItem_Click(object sender, EventArgs e)
+ {
+ var preset = GetSelectedNvPreset();
+
+ var menuItem = (ToolStripItem)sender;
+
+ var currentSettings = (NvGpuOcSettings)menuItem.Tag;
+
+ var gpuInfo = NvGpuInfo.GetGpuInfo(currentSettings.PCIIdentifier);
+
+ var newSettings = AskNvOcSettings(gpuInfo, currentSettings);
+
+ if (newSettings == null)
+ {
+ return;
+ }
+
+ preset.UpdateOverclockingSetting(newSettings);
+
+ AddOrUpdateItem();
+ }
+
private void BuildNvRefreshRateResolutionMenu(NvPreset preset)
{
var displayName = preset.primaryDisplay ? null : preset.displayName;
@@ -2969,9 +3018,9 @@ Do you want to continue?";
ClientPath = new FileInfo(Application.ExecutablePath).Directory.FullName
};
- var result = PipeUtils.SendMessage(message);
+ var result = PipeUtils.SendMessage(message, 10000);
- if (!result.Result)
+ if (result != null && !result.Result)
{
MessageForms.ErrorOk($"Error while updating: {result.ErrorMessage}");
@@ -4400,20 +4449,43 @@ The InStart and Software Update items are now visible under the Expert-button."
private void miNvSettings_Click(object sender, EventArgs e)
{
- var shortcut = EditShortcut(_config.NvQuickAccessShortcut, "Quick Access shortcut", "NVIDIA controller settings");
+ EditNvSettings();
+ }
- if (shortcut == null)
+ private void EditNvSettings()
+ {
+ var values = MessageForms.ShowDialog("NVIDIA controller settings", new[] {
+ new MessageForms.FieldDefinition
+ {
+ Label = "Quick Access shortcut",
+ FieldType = MessageForms.FieldType.Shortcut,
+ Value = _config.NvQuickAccessShortcut
+ },
+ new MessageForms.FieldDefinition
+ {
+ Label = "Enable overclocking",
+ FieldType = MessageForms.FieldType.CheckBox,
+ Value = _nvService.Config.ShowOverclocking
+ }
+ });
+ if (!values.Any())
{
return;
}
+ var shortcut = values[0].Value.ToString();
+ var enableOc = (bool)values[1].Value;
+
var clear = !string.IsNullOrEmpty(_config.NvQuickAccessShortcut);
_config.NvQuickAccessShortcut = shortcut;
Utils.RegisterShortcut(Handle, SHORTCUTID_NVQA, _config.NvQuickAccessShortcut, clear);
+
+ _nvService.Config.ShowOverclocking = enableOc;
}
+
private void btnNvSettings_Click(object sender, EventArgs e)
{
mnuNvSettings.Show(btnNvSettings, btnNvSettings.PointToClient(Cursor.Position));
@@ -4876,30 +4948,316 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad
private void btnNvSetClocks_Click(object sender, EventArgs e)
{
+ var gpu = cbxNvGPU.SelectedItem as PhysicalGPU;
+
+ if (gpu == null)
+ {
+ return;
+ }
+
+ var gpuInfo = NvGpuInfo.GetGpuInfo(gpu);
+ var currentSettings = gpuInfo.GetOverclockSettings();
+
+ var newSettings = AskNvOcSettings(gpuInfo, currentSettings);
+
+ if (newSettings == null)
+ {
+ return;
+ }
+
+ _nvService.ApplyOverclocking(newSettings);
+
+ UpdateNvGpuInfo();
+ }
+
+ public NvGpuOcSettings AskNvOcSettings(NvGpuInfo gpuInfo, NvGpuOcSettings currentSettings)
+ {
+ var overclockTypes = Utils.GetDescriptions();
+
+ var values = MessageForms.ShowDialog("Choose desired overclock settings", new[] {
+ new MessageForms.FieldDefinition
+ {
+ Label = "Overclock method",
+ FieldType = MessageForms.FieldType.DropDown,
+ Values = overclockTypes,
+ Value = currentSettings.Type
+ } });
+ if (!values.Any())
+ {
+ return null;
+ }
+
+ var overclockType = Enum.Parse(values[0].Value.ToString());
+ var newSettings = default(NvGpuOcSettings);
+
+ if (overclockType == NvGpuOcType.Curve)
+ {
+ newSettings = AskNvCurveOcSettings(gpuInfo, currentSettings);
+ }
+ else if (overclockType == NvGpuOcType.Offset)
+ {
+ newSettings = AskNvOffsetOcSettings(gpuInfo, currentSettings);
+ }
+ else
+ {
+ newSettings = new NvGpuOcSettings
+ {
+ Type = overclockType,
+ PCIIdentifier = gpuInfo.GPU.BusInformation.PCIIdentifiers.ToString()
+ };
+ }
+
+ return newSettings;
+ }
+
+ public NvGpuOcSettings AskNvCurveOcSettings(NvGpuInfo gpuInfo, NvGpuOcSettings currentSettings)
+ {
+ var nvOverclockSettings = new NvGpuOcSettings
+ {
+ Type = NvGpuOcType.Curve,
+ PCIIdentifier = gpuInfo.GPU.BusInformation.PCIIdentifiers.ToString()
+ };
+
+ var curveEntries = gpuInfo.CurveV3.GPUCurveEntries;
+
+ var graphicsDelta = gpuInfo.GetDeltaClockMinMax(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics);
+
+ var minCurveFreq = curveEntries.Max(e => e.DefaultFrequencyInkHz) + graphicsDelta.Item1;
+ var freqValues = curveEntries
+ .Where(e => e.DefaultFrequencyInkHz == 0 || e.DefaultFrequencyInkHz >= minCurveFreq)
+ .Select(e => (e.DefaultFrequencyInkHz / 1000).ToString()).Distinct()
+ .OrderBy(x => x)
+ .ToList();
+ var voltValues = curveEntries
+ .Where(e => e.DefaultVoltageInMicroV == 0 || e.DefaultFrequencyInkHz >= minCurveFreq)
+ .OrderBy(e => e.DefaultVoltageInMicroV)
+ .Select(e => (e.DefaultVoltageInMicroV / 1000).ToString())
+ .Distinct()
+ .ToList();
+
+ var currentGraphicsVoltage = currentSettings.MaximumVoltageUv > 0 ? currentSettings.MaximumVoltageUv : 1050000;
+
+ var curveEntry = curveEntries.FirstOrDefault(e => e.VoltageInMicroV == currentGraphicsVoltage);
+ var currentGpuFreq = curveEntry.FrequencyInkHz;
+
+ var memoryDelta = gpuInfo.GetDeltaClockMinMax(NvAPIWrapper.Native.GPU.PublicClockDomain.Memory);
+
+ var powerLimits = gpuInfo.GetPowerLimits();
+
+ var defaultPowerLimitMw = gpuInfo.DefaultPowerInMilliWatts;
+
+ var powerField = defaultPowerLimitMw > 0 ?
+ new MessageForms.FieldDefinition
+ {
+ Label = $"Power limit in milli watts. Min: {gpuInfo.MinPowerInMilliWatts}, max: {gpuInfo.MaxPowerInMilliWatts}",
+ FieldType = MessageForms.FieldType.TrackBar,
+ Value = (int)((decimal)defaultPowerLimitMw / 100000 * currentSettings.PowerPCM),
+ MinValue = gpuInfo.MinPowerInMilliWatts,
+ MaxValue = gpuInfo.MaxPowerInMilliWatts
+ }
+ : new MessageForms.FieldDefinition
+ {
+ Label = $"Power limit in PCM (per cent mille). Min: {powerLimits.Item1}, max: {powerLimits.Item2}",
+ FieldType = MessageForms.FieldType.TrackBar,
+ Value = currentSettings.PowerPCM,
+ MinValue = powerLimits.Item1,
+ MaxValue = powerLimits.Item2
+ };
+
var values = MessageForms.ShowDialog("Set desired clock speeds and voltage", new[] {
+ new MessageForms.FieldDefinition
+ {
+ Label = $"Core offset in MHz ({graphicsDelta.Item1.ToUnitString()} to {graphicsDelta.Item2.ToUnitString()})",
+ FieldType = MessageForms.FieldType.Numeric,
+ MinValue = graphicsDelta.Item1 / 1000,
+ MaxValue = graphicsDelta.Item2 / 1000,
+ Value = currentSettings.GraphicsOffsetKHz / 1000
+ },
+ new MessageForms.FieldDefinition
+ {
+ Label = "Optional undervolt: maximum voltage in milli volt",
+ FieldType = MessageForms.FieldType.DropDown,
+ Value = currentSettings.MaximumVoltageUv / 1000,
+ Values = voltValues,
+ },
+ new MessageForms.FieldDefinition
+ {
+ Label = "Optional undervolt: maximum core frequency in MHz",
+ FieldType = MessageForms.FieldType.DropDown,
+ Value = currentSettings.MaximumFrequencyKHz / 1000,
+ Values = freqValues,
+ },
+ new MessageForms.FieldDefinition
+ {
+ Label = $"Memory offset in MHz ({memoryDelta.Item1.ToUnitString()} to {memoryDelta.Item2.ToUnitString()})",
+ FieldType = MessageForms.FieldType.Numeric,
+ MinValue = memoryDelta.Item1 / 1000,
+ MaxValue = memoryDelta.Item2 / 1000,
+ Value = currentSettings.MemoryOffsetKHz / 1000
+ },
+ new MessageForms.FieldDefinition
+ {
+ Label = "Voltage boost in %",
+ FieldType = MessageForms.FieldType.Numeric,
+ Value = currentSettings.VoltageBoostPercent,
+ MinValue = 0,
+ MaxValue = 100
+ },
+ powerField,
+ });
+ if (!values.Any())
+ {
+ return null;
+ }
+
+ nvOverclockSettings.GraphicsOffsetKHz = values[0].ValueAsInt * 1000;
+ nvOverclockSettings.MaximumVoltageUv = values[1].ValueAsUInt * 1000;
+ nvOverclockSettings.MaximumFrequencyKHz = values[2].ValueAsUInt * 1000;
+ nvOverclockSettings.MemoryOffsetKHz = values[3].ValueAsInt * 1000;
+ nvOverclockSettings.VoltageBoostPercent = values[4].ValueAsUInt;
+
+ var power = values[5].ValueAsUInt;
+
+ nvOverclockSettings.PowerPCM = defaultPowerLimitMw > 0 ? (uint)((decimal)power / defaultPowerLimitMw * 100000) : power;
+
+ return nvOverclockSettings;
+ }
+
+ public NvGpuOcSettings AskNvOffsetOcSettings(NvGpuInfo gpuInfo, NvGpuOcSettings currentSettings)
+ {
+ var nvOverclockSettings = new NvGpuOcSettings
+ {
+ Type = NvGpuOcType.Offset,
+ PCIIdentifier = gpuInfo.GPU.BusInformation.PCIIdentifiers.ToString()
+ };
+
+ var curveEntries = gpuInfo.CurveV3.GPUCurveEntries;
+
+ var freqValues = curveEntries.Select(e => (e.DefaultFrequencyInkHz / 1000).ToString()).Distinct().ToList();
+ var voltValues = curveEntries.Select(e => (e.DefaultVoltageInMicroV / 1000).ToString()).Distinct().ToList();
+
+ var currentGraphicsVoltage = currentSettings.MaximumVoltageUv > 0 ? currentSettings.MaximumVoltageUv : 1050000;
+
+ var curveEntry = curveEntries.FirstOrDefault(e => e.VoltageInMicroV == currentGraphicsVoltage);
+ var currentGpuFreq = curveEntry.FrequencyInkHz;
+
+ var graphicsDelta = gpuInfo.GetDeltaClockMinMax(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics);
+ var memoryDelta = gpuInfo.GetDeltaClockMinMax(NvAPIWrapper.Native.GPU.PublicClockDomain.Memory);
+
+ var powerLimits = gpuInfo.GetPowerLimits();
+
+ var values = MessageForms.ShowDialog("Set desired clock speeds and voltage", new[] {
+ new MessageForms.FieldDefinition
+ {
+ Label = $"Core offset in MHz ({graphicsDelta.Item1.ToUnitString()} to {graphicsDelta.Item2.ToUnitString()})",
+ FieldType = MessageForms.FieldType.Numeric,
+ MinValue = graphicsDelta.Item1 / 1000,
+ MaxValue = graphicsDelta.Item2 / 1000,
+ Value = currentSettings.GraphicsOffsetKHz / 1000
+ },
+ new MessageForms.FieldDefinition
+ {
+ Label = $"Memory offset in MHz ({memoryDelta.Item1.ToUnitString()} to {memoryDelta.Item2.ToUnitString()})",
+ FieldType = MessageForms.FieldType.Numeric,
+ MinValue = memoryDelta.Item1 / 1000,
+ MaxValue = memoryDelta.Item2 / 1000,
+ Value = currentSettings.MemoryOffsetKHz / 1000
+ },
+ new MessageForms.FieldDefinition
+ {
+ Label = "Voltage boost in %",
+ FieldType = MessageForms.FieldType.Numeric,
+ Value = currentSettings.VoltageBoostPercent,
+ MinValue = 0,
+ MaxValue = 100
+ },
+ new MessageForms.FieldDefinition
+ {
+ Label = $"Power limit in PCM (per cent mille). Min: {powerLimits.Item1}, max: {powerLimits.Item2}",
+ FieldType = MessageForms.FieldType.Numeric,
+ Value = currentSettings.PowerPCM,
+ MinValue = powerLimits.Item1,
+ MaxValue = powerLimits.Item2
+ },
+ });
+ if (!values.Any())
+ {
+ return null;
+ }
+
+ nvOverclockSettings.GraphicsOffsetKHz = values[0].ValueAsInt * 1000;
+ nvOverclockSettings.MemoryOffsetKHz = values[1].ValueAsInt * 1000;
+ nvOverclockSettings.VoltageBoostPercent = values[2].ValueAsUInt;
+ nvOverclockSettings.PowerPCM = values[3].ValueAsUInt;
+
+ return nvOverclockSettings;
+ }
+
+ public void SetClocks()
+ {
+ var gpu = cbxNvGPU.SelectedItem as PhysicalGPU;
+
+ var gpuInfo = NvGpuInfo.GetGpuInfo(gpu);
+
+ var curveEntries = gpuInfo.CurveV3.GPUCurveEntries;
+
+ var freqValues = curveEntries.Select(e => e.DefaultFrequencyInkHz.ToString()).Distinct().ToList();
+ var voltValues = curveEntries.Select(e => e.DefaultVoltageInMicroV.ToString()).Distinct().ToList();
+
+ var lockedGraphics = gpuInfo.GetLockedBoost(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics);
+
+ var currentGraphicsVoltage = lockedGraphics.Item1 > 0 ? lockedGraphics.Item1 : 1050000;
+
+ var curveEntry = curveEntries.FirstOrDefault(e => e.VoltageInMicroV == currentGraphicsVoltage);
+ var currentGpuFreq = curveEntry.FrequencyInkHz;
+
+ var graphicsDelta = gpuInfo.GetDeltaClockLimits(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics);
+ var memoryDelta = gpuInfo.GetDeltaClockLimits(NvAPIWrapper.Native.GPU.PublicClockDomain.Memory);
+
+ var graphicsMinValue = graphicsDelta?.DeltaRange.Minimum ?? -502000;
+ var graphicsMaxValue = graphicsDelta?.DeltaRange.Maximum ?? 1000000;
+ var memoryMinValue = memoryDelta?.DeltaRange.Minimum ?? -502000;
+ var memoryMaxValue = memoryDelta?.DeltaRange.Maximum ?? 3000000;
+
+ var currentGraphicsOffset = gpuInfo.GetOffset(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics);
+ var currentMemoryOffset = gpuInfo.GetOffset(NvAPIWrapper.Native.GPU.PublicClockDomain.Memory);
+
+ var values = MessageForms.ShowDialog("Set desired clock speeds and voltage", new[] {
+ new MessageForms.FieldDefinition
+ {
+ Label = $"Core offset in MHz ({graphicsMinValue}KHz to {graphicsMaxValue}KHz)",
+ FieldType = MessageForms.FieldType.Numeric,
+ MinValue = graphicsDelta?.DeltaRange.Minimum ?? -502000,
+ MaxValue = graphicsDelta?.DeltaRange.Maximum ?? 1000000,
+ Value = currentGraphicsOffset
+ },
new MessageForms.FieldDefinition
{
Label = "Voltage in micro volt",
- FieldType = MessageForms.FieldType.Numeric,
- MinValue = 650000,
- MaxValue = 1100000,
- Value = 1050000
+ FieldType = MessageForms.FieldType.DropDown,
+ Values = voltValues,
+ //FieldType = MessageForms.FieldType.Numeric,
+ //MinValue = 650000,
+ //MaxValue = 1100000,
+ //Value = currentGraphicsVoltage
},
new MessageForms.FieldDefinition
{
- Label = "Core offset in KHz",
- FieldType = MessageForms.FieldType.Numeric,
- MinValue = -502000,
- MaxValue = 1000000,
- Value = 0
+ Label = "Core frequency in KHz",
+ FieldType = MessageForms.FieldType.DropDown,
+ Values = freqValues,
+ //FieldType = MessageForms.FieldType.Numeric,
+ //MinValue = 2000000,
+ //MaxValue = 3200000,
+ //Value = currentGpuFreq
},
new MessageForms.FieldDefinition
{
- Label = "Memory offset in KHz",
+ Label = $"Memory offset in KHz ({memoryMinValue}KHz to {memoryMaxValue}KHz)",
FieldType = MessageForms.FieldType.Numeric,
- MinValue = -502000,
+ MinValue = graphicsDelta?.DeltaRange.Minimum ?? -502000,
MaxValue = 2500000,
- Value = 0
+ Value = currentMemoryOffset
},
});
if (!values.Any())
@@ -4908,10 +5266,47 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad
}
var voltage = (uint)values[0].ValueAsInt;
- var coreOffset = values[1].ValueAsInt;
+ //var coreOffset = values[1].ValueAsInt;
+ var coreFreq = values[1].ValueAsInt;
var memoryOffset = values[2].ValueAsInt;
- _nvService.SetGpuClocks(null, voltage, coreOffset, memoryOffset);
+ var normalized = (coreFreq / 15000) * 15000;
+ var newCurveEntryFreq = curveEntries.FirstOrDefault(e => e.DefaultFrequencyInkHz == normalized);
+ var newCurveEntryVolt = curveEntries.FirstOrDefault(e => e.DefaultVoltageInMicroV == voltage);
+
+ var coreOffset = (int)(newCurveEntryFreq.DefaultFrequencyInkHz - newCurveEntryVolt.DefaultFrequencyInkHz);
+
+ gpuInfo.SetGpuClocks(voltage, coreOffset, memoryOffset);
+ }
+
+ private void miNvOverclockingIncluded_Click(object sender, EventArgs e)
+ {
+ var preset = GetSelectedNvPreset();
+
+ preset.applyOverclocking = !preset.applyOverclocking;
+
+ AddOrUpdateItem();
+ }
+
+ private void cbxNvGPU_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ RefreshNvGpuInfo();
+ }
+
+ private void RefreshNvGpuInfo()
+ {
+ var gpu = (PhysicalGPU)cbxNvGPU.SelectedItem;
+
+ if (gpu == null)
+ {
+ return;
+ }
+
+ var gpuInfo = NvGpuInfo.GetGpuInfo(gpu);
+ var ocSettings = gpuInfo.GetOverclockSettings();
+
+ edtNvGpuInfo.Text = gpuInfo.ToString();
+ edtNvOverclock.Text = ocSettings.ToString();
}
}
}
\ No newline at end of file
diff --git a/ColorControl/Services/NVIDIA/Kernel32.cs b/ColorControl/Services/NVIDIA/Kernel32.cs
new file mode 100644
index 0000000..af1948b
--- /dev/null
+++ b/ColorControl/Services/NVIDIA/Kernel32.cs
@@ -0,0 +1,1557 @@
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// Copyright (C) LibreHardwareMonitor and Contributors.
+// All Rights Reserved.
+
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+// ReSharper disable InconsistentNaming
+
+namespace ColorControl.Services.NVIDIA;
+
+public class Kernel32
+{
+ public const int ERROR_SERVICE_ALREADY_RUNNING = unchecked((int)0x80070420);
+
+ public const int ERROR_SERVICE_EXISTS = unchecked((int)0x80070431);
+
+ internal const uint BATTERY_UNKNOWN_TIME = 0xFFFFFFFF;
+ internal const string IntelNVMeMiniPortSignature1 = "NvmeMini";
+ internal const string IntelNVMeMiniPortSignature2 = "IntelNvm";
+
+ internal const uint LPTR = 0x0000 | 0x0040;
+
+ internal const int MAX_DRIVE_ATTRIBUTES = 512;
+ internal const uint NVME_PASS_THROUGH_SRB_IO_CODE = 0xe0002000;
+ internal const byte SMART_LBA_HI = 0xC2;
+ internal const byte SMART_LBA_HI_EXCEEDED = 0x2C;
+ internal const byte SMART_LBA_MID = 0x4F;
+ internal const byte SMART_LBA_MID_EXCEEDED = 0xF4;
+
+ private const string DllName = "kernel32.dll";
+
+ [Flags]
+ public enum NVME_CRITICAL_WARNING
+ {
+ None = 0x00,
+
+ ///
+ /// If set to 1, then the available spare space has fallen below the threshold.
+ ///
+ AvailableSpaceLow = 0x01,
+
+ ///
+ /// If set to 1, then a temperature is above an over temperature threshold or below an under temperature threshold.
+ ///
+ TemperatureThreshold = 0x02,
+
+ ///
+ /// If set to 1, then the device reliability has been degraded due to significant media related errors or any internal error that degrades device reliability.
+ ///
+ ReliabilityDegraded = 0x04,
+
+ ///
+ /// If set to 1, then the media has been placed in read only mode
+ ///
+ ReadOnly = 0x08,
+
+ ///
+ /// If set to 1, then the volatile memory backup device has failed. This field is only valid if the controller has a volatile memory backup solution.
+ ///
+ VolatileMemoryBackupDeviceFailed = 0x10
+ }
+
+ ///
+ /// Create a instance from a struct with zero initialized memory arrays
+ /// no need to init every inner array with the correct sizes
+ ///
+ /// type of struct that is needed
+ ///
+ internal static T CreateStruct()
+ {
+ int size = Marshal.SizeOf();
+ IntPtr ptr = Marshal.AllocHGlobal(size);
+ RtlZeroMemory(ptr, size);
+ T result = Marshal.PtrToStructure(ptr);
+ Marshal.FreeHGlobal(ptr);
+ return result;
+ }
+
+ internal static SafeHandle OpenDevice(string devicePath)
+ {
+ SafeHandle hDevice = CreateFile(devicePath, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);
+ if (hDevice.IsInvalid || hDevice.IsClosed)
+ hDevice = null;
+
+ return hDevice;
+ }
+
+ [DllImport(DllName, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern SafeFileHandle CreateFile
+ (
+ [MarshalAs(UnmanagedType.LPTStr)] string lpFileName,
+ [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
+ [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
+ IntPtr lpSecurityAttributes,
+ [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
+ [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
+ IntPtr hTemplateFile);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeHandle hDevice,
+ DFP dwIoControlCode,
+ ref SENDCMDINPARAMS lpInBuffer,
+ int nInBufferSize,
+ out ATTRIBUTECMDOUTPARAMS lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeHandle hDevice,
+ DFP dwIoControlCode,
+ ref SENDCMDINPARAMS lpInBuffer,
+ int nInBufferSize,
+ out THRESHOLDCMDOUTPARAMS lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeHandle hDevice,
+ DFP dwIoControlCode,
+ ref SENDCMDINPARAMS lpInBuffer,
+ int nInBufferSize,
+ out SENDCMDOUTPARAMS lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeHandle hDevice,
+ DFP dwIoControlCode,
+ ref SENDCMDINPARAMS lpInBuffer,
+ int nInBufferSize,
+ out IDENTIFYCMDOUTPARAMS lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeHandle hDevice,
+ DFP dwIoControlCode,
+ ref SENDCMDINPARAMS lpInBuffer,
+ int nInBufferSize,
+ out STATUSCMDOUTPARAMS lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeHandle hDevice,
+ IOCTL dwIoControlCode,
+ ref STORAGE_PROPERTY_QUERY lpInBuffer,
+ int nInBufferSize,
+ out STORAGE_DEVICE_DESCRIPTOR_HEADER lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeHandle hDevice,
+ IOCTL dwIoControlCode,
+ ref STORAGE_PROPERTY_QUERY lpInBuffer,
+ int nInBufferSize,
+ IntPtr lpOutBuffer,
+ uint nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeHandle hDevice,
+ IOCTL dwIoControlCode,
+ IntPtr lpInBuffer,
+ int nInBufferSize,
+ IntPtr lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeFileHandle hDevice,
+ IOCTL dwIoControlCode,
+ ref BATTERY_QUERY_INFORMATION lpInBuffer,
+ int nInBufferSize,
+ ref BATTERY_INFORMATION lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeFileHandle hDevice,
+ IOCTL dwIoControlCode,
+ ref uint lpInBuffer,
+ int nInBufferSize,
+ ref uint lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeFileHandle hDevice,
+ IOCTL dwIoControlCode,
+ ref BATTERY_WAIT_STATUS lpInBuffer,
+ int nInBufferSize,
+ ref BATTERY_STATUS lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeFileHandle hDevice,
+ IOCTL dwIoControlCode,
+ ref BATTERY_QUERY_INFORMATION lpInBuffer,
+ int nInBufferSize,
+ IntPtr lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeFileHandle hDevice,
+ IOCTL dwIoControlCode,
+ ref BATTERY_QUERY_INFORMATION lpInBuffer,
+ int nInBufferSize,
+ ref uint lpOutBuffer,
+ int nOutBufferSize,
+ out uint lpBytesReturned,
+ IntPtr lpOverlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern IntPtr LocalAlloc(uint uFlags, ulong uBytes);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern IntPtr LocalFree(IntPtr hMem);
+
+ [DllImport(DllName, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern void RtlZeroMemory(IntPtr Destination, int Length);
+
+ [DllImport(DllName, SetLastError = false)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern void RtlCopyMemory(IntPtr Destination, IntPtr Source, uint Length);
+
+ [DllImport(DllName, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern IntPtr LoadLibrary(string lpFileName);
+
+ [DllImport(DllName, ExactSpelling = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern IntPtr GetProcAddress(IntPtr module, string methodName);
+
+ [DllImport(DllName)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool FreeLibrary(IntPtr module);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern IntPtr GetCurrentThread();
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern ushort GetActiveProcessorGroupCount();
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern bool SetThreadGroupAffinity(IntPtr thread, ref GROUP_AFFINITY groupAffinity, out GROUP_AFFINITY previousGroupAffinity);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, MEM flAllocationType, PAGE flProtect);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize, MEM dwFreeType);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern bool DeviceIoControl
+ (
+ SafeFileHandle device,
+ IOControlCode ioControlCode,
+ [MarshalAs(UnmanagedType.AsAny)][In] object inBuffer,
+ uint inBufferSize,
+ [MarshalAs(UnmanagedType.AsAny)][Out] object outBuffer,
+ uint nOutBufferSize,
+ out uint bytesReturned,
+ IntPtr overlapped);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern IntPtr CreateFile
+ (
+ string lpFileName,
+ uint dwDesiredAccess,
+ FileShare dwShareMode,
+ IntPtr lpSecurityAttributes,
+ FileMode dwCreationDisposition,
+ FileAttributes dwFlagsAndAttributes,
+ IntPtr hTemplateFile);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern int EnumSystemFirmwareTables(Provider firmwareTableProviderSignature, IntPtr firmwareTableBuffer, int bufferSize);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
+ internal static extern int GetSystemFirmwareTable(Provider firmwareTableProviderSignature, int firmwareTableID, IntPtr firmwareTableBuffer, int bufferSize);
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ public struct GROUP_AFFINITY
+ {
+ public UIntPtr Mask;
+
+ [MarshalAs(UnmanagedType.U2)]
+ public ushort Group;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U2)]
+ public ushort[] Reserved;
+ }
+
+ internal enum DFP : uint
+ {
+ DFP_GET_VERSION = 0x00074080,
+ DFP_SEND_DRIVE_COMMAND = 0x0007c084,
+ DFP_RECEIVE_DRIVE_DATA = 0x0007c088
+ }
+
+ internal enum IOCTL : uint
+ {
+ IOCTL_SCSI_PASS_THROUGH = 0x04d004,
+ IOCTL_SCSI_MINIPORT = 0x04d008,
+ IOCTL_SCSI_PASS_THROUGH_DIRECT = 0x04d014,
+ IOCTL_SCSI_GET_ADDRESS = 0x41018,
+ IOCTL_STORAGE_QUERY_PROPERTY = 0x2D1400,
+ IOCTL_BATTERY_QUERY_TAG = 0x294040,
+ IOCTL_BATTERY_QUERY_INFORMATION = 0x294044,
+ IOCTL_BATTERY_QUERY_STATUS = 0x29404C
+ }
+
+ [Flags]
+ internal enum BatteryCapabilities : uint
+ {
+ BATTERY_CAPACITY_RELATIVE = 0x40000000,
+ BATTERY_IS_SHORT_TERM = 0x20000000,
+ BATTERY_SET_CHARGE_SUPPORTED = 0x00000001,
+ BATTERY_SET_DISCHARGE_SUPPORTED = 0x00000002,
+ BATTERY_SYSTEM_BATTERY = 0x80000000
+ }
+
+ internal enum BATTERY_QUERY_INFORMATION_LEVEL
+ {
+ BatteryInformation,
+ BatteryGranularityInformation,
+ BatteryTemperature,
+ BatteryEstimatedTime,
+ BatteryDeviceName,
+ BatteryManufactureDate,
+ BatteryManufactureName,
+ BatteryUniqueID,
+ BatterySerialNumber
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct BATTERY_QUERY_INFORMATION
+ {
+ public uint BatteryTag;
+ public BATTERY_QUERY_INFORMATION_LEVEL InformationLevel;
+ public uint AtRate;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct BATTERY_INFORMATION
+ {
+ public BatteryCapabilities Capabilities;
+ public byte Technology;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+ public byte[] Reserved;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
+ public char[] Chemistry;
+
+ public uint DesignedCapacity;
+ public uint FullChargedCapacity;
+ public uint DefaultAlert1;
+ public uint DefaultAlert2;
+ public uint CriticalBias;
+ public uint CycleCount;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct BATTERY_WAIT_STATUS
+ {
+ public uint BatteryTag;
+ public uint Timeout;
+ public uint PowerState;
+ public uint LowCapacity;
+ public uint HighCapacity;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct BATTERY_STATUS
+ {
+ public uint PowerState;
+ public uint Capacity;
+ public uint Voltage;
+ public int Rate;
+ }
+
+ [Flags]
+ internal enum NVME_DIRECTION : uint
+ {
+ NVME_FROM_HOST_TO_DEV = 1,
+ NVME_FROM_DEV_TO_HOST = 2,
+ NVME_BI_DIRECTION = NVME_FROM_DEV_TO_HOST | NVME_FROM_HOST_TO_DEV
+ }
+
+ internal enum NVME_LOG_PAGES
+ {
+ NVME_LOG_PAGE_ERROR_INFO = 0x01,
+ NVME_LOG_PAGE_HEALTH_INFO = 0x02,
+ NVME_LOG_PAGE_FIRMWARE_SLOT_INFO = 0x03,
+ NVME_LOG_PAGE_CHANGED_NAMESPACE_LIST = 0x04,
+ NVME_LOG_PAGE_COMMAND_EFFECTS = 0x05,
+ NVME_LOG_PAGE_DEVICE_SELF_TEST = 0x06,
+ NVME_LOG_PAGE_TELEMETRY_HOST_INITIATED = 0x07,
+ NVME_LOG_PAGE_TELEMETRY_CTLR_INITIATED = 0x08,
+ NVME_LOG_PAGE_RESERVATION_NOTIFICATION = 0x80,
+ NVME_LOG_PAGE_SANITIZE_STATUS = 0x81
+ }
+
+ internal enum ATA_COMMAND : byte
+ {
+ ///
+ /// SMART data requested.
+ ///
+ ATA_SMART = 0xB0,
+
+ ///
+ /// Identify data is requested.
+ ///
+ ATA_IDENTIFY_DEVICE = 0xEC
+ }
+
+ internal enum SCSI_IOCTL_DATA
+ {
+ SCSI_IOCTL_DATA_OUT = 0,
+ SCSI_IOCTL_DATA_IN = 1,
+ SCSI_IOCTL_DATA_UNSPECIFIED = 2
+ }
+
+ internal enum SMART_FEATURES : byte
+ {
+ ///
+ /// Read SMART data.
+ ///
+ SMART_READ_DATA = 0xD0,
+
+ ///
+ /// Read SMART thresholds.
+ /// obsolete
+ ///
+ READ_THRESHOLDS = 0xD1,
+
+ ///
+ /// Autosave SMART data.
+ ///
+ ENABLE_DISABLE_AUTOSAVE = 0xD2,
+
+ ///
+ /// Save SMART attributes.
+ ///
+ SAVE_ATTRIBUTE_VALUES = 0xD3,
+
+ ///
+ /// Set SMART to offline immediately.
+ ///
+ EXECUTE_OFFLINE_DIAGS = 0xD4,
+
+ ///
+ /// Read SMART log.
+ ///
+ SMART_READ_LOG = 0xD5,
+
+ ///
+ /// Write SMART log.
+ ///
+ SMART_WRITE_LOG = 0xD6,
+
+ ///
+ /// Write SMART thresholds.
+ /// obsolete
+ ///
+ WRITE_THRESHOLDS = 0xD7,
+
+ ///
+ /// Enable SMART.
+ ///
+ ENABLE_SMART = 0xD8,
+
+ ///
+ /// Disable SMART.
+ ///
+ DISABLE_SMART = 0xD9,
+
+ ///
+ /// Get SMART status.
+ ///
+ RETURN_SMART_STATUS = 0xDA,
+
+ ///
+ /// Set SMART to offline automatically.
+ ///
+ ENABLE_DISABLE_AUTO_OFFLINE = 0xDB /* obsolete */
+ }
+
+ internal enum STORAGE_BUS_TYPE
+ {
+ BusTypeUnknown = 0x00,
+ BusTypeScsi,
+ BusTypeAtapi,
+ BusTypeAta,
+ BusType1394,
+ BusTypeSsa,
+ BusTypeFibre,
+ BusTypeUsb,
+ BusTypeRAID,
+ BusTypeiScsi,
+ BusTypeSas,
+ BusTypeSata,
+ BusTypeSd,
+ BusTypeMmc,
+ BusTypeVirtual,
+ BusTypeFileBackedVirtual,
+ BusTypeSpaces,
+ BusTypeNvme,
+ BusTypeSCM,
+ BusTypeMax,
+ BusTypeMaxReserved = 0x7F
+ }
+
+ internal enum STORAGE_PROPERTY_ID
+ {
+ StorageDeviceProperty = 0,
+ StorageAdapterProperty,
+ StorageDeviceIdProperty,
+ StorageDeviceUniqueIdProperty,
+ StorageDeviceWriteCacheProperty,
+ StorageMiniportProperty,
+ StorageAccessAlignmentProperty,
+ StorageDeviceSeekPenaltyProperty,
+ StorageDeviceTrimProperty,
+ StorageDeviceWriteAggregationProperty,
+ StorageDeviceDeviceTelemetryProperty,
+ StorageDeviceLBProvisioningProperty,
+ StorageDevicePowerProperty,
+ StorageDeviceCopyOffloadProperty,
+ StorageDeviceResiliencyProperty,
+ StorageDeviceMediumProductType,
+ StorageAdapterRpmbProperty,
+ StorageDeviceIoCapabilityProperty = 48,
+ StorageAdapterProtocolSpecificProperty,
+ StorageDeviceProtocolSpecificProperty,
+ StorageAdapterTemperatureProperty,
+ StorageDeviceTemperatureProperty,
+ StorageAdapterPhysicalTopologyProperty,
+ StorageDevicePhysicalTopologyProperty,
+ StorageDeviceAttributesProperty,
+ StorageDeviceManagementStatus,
+ StorageAdapterSerialNumberProperty,
+ StorageDeviceLocationProperty
+ }
+
+ internal enum STORAGE_PROTOCOL_NVME_DATA_TYPE
+ {
+ NVMeDataTypeUnknown = 0,
+ NVMeDataTypeIdentify,
+ NVMeDataTypeLogPage,
+ NVMeDataTypeFeature
+ }
+
+ internal enum STORAGE_PROTOCOL_NVME_PROTOCOL_DATA_REQUEST_VALUE
+ {
+ NVMeIdentifyCnsSpecificNamespace = 0,
+ NVMeIdentifyCnsController = 1,
+ NVMeIdentifyCnsActiveNamespaces = 2
+ }
+
+ internal enum STORAGE_PROTOCOL_TYPE
+ {
+ ProtocolTypeUnknown = 0x00,
+ ProtocolTypeScsi,
+ ProtocolTypeAta,
+ ProtocolTypeNvme,
+ ProtocolTypeSd,
+ ProtocolTypeProprietary = 0x7E,
+ ProtocolTypeMaxReserved = 0x7F
+ }
+
+ internal enum STORAGE_QUERY_TYPE
+ {
+ PropertyStandardQuery = 0,
+ PropertyExistsQuery,
+ PropertyMaskQuery,
+ PropertyQueryMaxDefined
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct MEMORYSTATUSEX
+ {
+ public uint dwLength;
+ public uint dwMemoryLoad;
+ public ulong ullTotalPhys;
+ public ulong ullAvailPhys;
+ public ulong ullTotalPageFile;
+ public ulong ullAvailPageFile;
+ public ulong ullTotalVirtual;
+ public ulong ullAvailVirtual;
+ public ulong ullAvailExtendedVirtual;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct SMART_ATTRIBUTE
+ {
+ public byte Id;
+ public short Flags;
+ public byte CurrentValue;
+ public byte WorstValue;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
+ public byte[] RawValue;
+
+ public byte Reserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct SMART_THRESHOLD
+ {
+ public byte Id;
+ public byte Threshold;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
+ public byte[] Reserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct SENDCMDINPARAMS
+ {
+ public uint cBufferSize;
+ public IDEREGS irDriveRegs;
+ public byte bDriveNumber;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+ public byte[] bReserved;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
+ public uint[] dwReserved;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
+ public byte[] bBuffer;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct IDEREGS
+ {
+ public SMART_FEATURES bFeaturesReg;
+ public byte bSectorCountReg;
+ public byte bSectorNumberReg;
+ public byte bCylLowReg;
+ public byte bCylHighReg;
+ public byte bDriveHeadReg;
+ public ATA_COMMAND bCommandReg;
+ public byte bReserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct DRIVERSTATUS
+ {
+ public byte bDriverError;
+ public byte bIDEError;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
+ public byte[] Reserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct SENDCMDOUTPARAMS
+ {
+ public uint cBufferSize;
+ public DRIVERSTATUS DriverStatus;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
+ public byte[] bBuffer;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct ATTRIBUTECMDOUTPARAMS
+ {
+ public uint cBufferSize;
+ public DRIVERSTATUS DriverStatus;
+ public byte Version;
+ public byte Reserved;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DRIVE_ATTRIBUTES)]
+ public SMART_ATTRIBUTE[] Attributes;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct THRESHOLDCMDOUTPARAMS
+ {
+ public uint cBufferSize;
+ public DRIVERSTATUS DriverStatus;
+ public byte Version;
+ public byte Reserved;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DRIVE_ATTRIBUTES)]
+ public SMART_THRESHOLD[] Thresholds;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct STATUSCMDOUTPARAMS
+ {
+ public uint cBufferSize;
+ public DRIVERSTATUS DriverStatus;
+ public IDEREGS irDriveRegs;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct IDENTIFY_DATA
+ {
+ public ushort GeneralConfiguration;
+ public ushort NumberOfCylinders;
+ public ushort Reserved1;
+ public ushort NumberOfHeads;
+ public ushort UnformattedBytesPerTrack;
+ public ushort UnformattedBytesPerSector;
+ public ushort SectorsPerTrack;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+ public ushort[] VendorUnique;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
+ public byte[] SerialNumber;
+
+ public ushort BufferType;
+ public ushort BufferSectorSize;
+ public ushort NumberOfEccBytes;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public byte[] FirmwareRevision;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
+ public byte[] ModelNumber;
+
+ public byte MaximumBlockTransfer;
+ public byte VendorUnique2;
+ public ushort DoubleWordIo;
+ public ushort Capabilities;
+ public ushort Reserved2;
+ public byte VendorUnique3;
+ public byte PioCycleTimingMode;
+ public byte VendorUnique4;
+ public byte DmaCycleTimingMode;
+ public ushort TranslationFieldsValid;
+ public ushort NumberOfCurrentCylinders;
+ public ushort NumberOfCurrentHeads;
+ public ushort CurrentSectorsPerTrack;
+ public uint CurrentSectorCapacity;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 197)]
+ public ushort[] Reserved3;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct IDENTIFYCMDOUTPARAMS
+ {
+ public uint cBufferSize;
+ public DRIVERSTATUS DriverStatus;
+ public IDENTIFY_DATA Identify;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct STORAGE_PROPERTY_QUERY
+ {
+ public STORAGE_PROPERTY_ID PropertyId;
+ public STORAGE_QUERY_TYPE QueryType;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
+ public byte[] AdditionalParameters;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct STORAGE_DEVICE_DESCRIPTOR_HEADER
+ {
+ public uint Version;
+ public uint Size;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct STORAGE_DEVICE_DESCRIPTOR
+ {
+ public uint Version;
+ public uint Size;
+ public byte DeviceType;
+ public byte DeviceTypeModifier;
+
+ [MarshalAs(UnmanagedType.U1)]
+ public bool RemovableMedia;
+
+ [MarshalAs(UnmanagedType.U1)]
+ public bool CommandQueueing;
+
+ public uint VendorIdOffset;
+ public uint ProductIdOffset;
+ public uint ProductRevisionOffset;
+ public uint SerialNumberOffset;
+ public STORAGE_BUS_TYPE BusType;
+ public uint RawPropertiesLength;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SRB_IO_CONTROL
+ {
+ public uint HeaderLenght;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public byte[] Signature;
+
+ public uint Timeout;
+ public uint ControlCode;
+ public uint ReturnCode;
+ public uint Length;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct NVME_PASS_THROUGH_IOCTL
+ {
+ public SRB_IO_CONTROL srb;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
+ public uint[] VendorSpecific;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public uint[] NVMeCmd;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
+ public uint[] CplEntry;
+
+ public NVME_DIRECTION Direction;
+ public uint QueueId;
+ public uint DataBufferLen;
+ public uint MetaDataLen;
+ public uint ReturnBufferLen;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4096)]
+ public byte[] DataBuffer;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SCSI_PASS_THROUGH
+ {
+ [MarshalAs(UnmanagedType.U2)]
+ public ushort Length;
+
+ public byte ScsiStatus;
+ public byte PathId;
+ public byte TargetId;
+ public byte Lun;
+ public byte CdbLength;
+ public byte SenseInfoLength;
+ public byte DataIn;
+ public uint DataTransferLength;
+ public uint TimeOutValue;
+ public IntPtr DataBufferOffset;
+ public uint SenseInfoOffset;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] Cdb;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SCSI_PASS_THROUGH_WITH_BUFFERS
+ {
+ public SCSI_PASS_THROUGH Spt;
+
+ public uint Filler;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
+ public byte[] SenseBuf;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4096)]
+ public byte[] DataBuf;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct NVME_POWER_STATE_DESC
+ {
+ ///
+ /// bit 0:15 Maximum Power (MP) in centiwatts
+ ///
+ public ushort MP;
+
+ ///
+ /// bit 16:23
+ ///
+ public byte Reserved0;
+
+ ///
+ /// bit 24 Max Power Scale (MPS), bit 25 Non-Operational State (NOPS)
+ ///
+ public byte MPS_NOPS;
+
+ ///
+ /// bit 32:63 Entry Latency (ENLAT) in microseconds
+ ///
+ public uint ENLAT;
+
+ ///
+ /// bit 64:95 Exit Latency (EXLAT) in microseconds
+ ///
+ public uint EXLAT;
+
+ ///
+ /// bit 96:100 Relative Read Throughput (RRT)
+ ///
+ public byte RRT;
+
+ ///
+ /// bit 104:108 Relative Read Latency (RRL)
+ ///
+ public byte RRL;
+
+ ///
+ /// bit 112:116 Relative Write Throughput (RWT)
+ ///
+ public byte RWT;
+
+ ///
+ /// bit 120:124 Relative Write Latency (RWL)
+ ///
+ public byte RWL;
+
+ ///
+ /// bit 128:143 Idle Power (IDLP)
+ ///
+ public ushort IDLP;
+
+ ///
+ /// bit 150:151 Idle Power Scale (IPS)
+ ///
+ public byte IPS;
+
+ ///
+ /// bit 152:159
+ ///
+ public byte Reserved7;
+
+ ///
+ /// bit 160:175 Active Power (ACTP)
+ ///
+ public ushort ACTP;
+
+ ///
+ /// bit 176:178 Active Power Workload (APW), bit 182:183 Active Power Scale (APS)
+ ///
+ public byte APW_APS;
+
+ ///
+ /// bit 184:255.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
+ public byte[] Reserved9;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct NVME_IDENTIFY_CONTROLLER_DATA
+ {
+ ///
+ /// byte 0:1 M - PCI Vendor ID (VID)
+ ///
+ public ushort VID;
+
+ ///
+ /// byte 2:3 M - PCI Subsystem Vendor ID (SSVID)
+ ///
+ public ushort SSVID;
+
+ ///
+ /// byte 4: 23 M - Serial Number (SN)
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
+ public byte[] SN;
+
+ ///
+ /// byte 24:63 M - Model Number (MN)
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
+ public byte[] MN;
+
+ ///
+ /// byte 64:71 M - Firmware Revision (FR)
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public byte[] FR;
+
+ ///
+ /// byte 72 M - Recommended Arbitration Burst (RAB)
+ ///
+ public byte RAB;
+
+ ///
+ /// byte 73:75 M - IEEE OUI Identifier (IEEE). Controller Vendor code.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+ public byte[] IEEE;
+
+ ///
+ /// byte 76 O - Controller Multi-Path I/O and Namespace Sharing Capabilities (CMIC)
+ ///
+ public byte CMIC;
+
+ ///
+ /// byte 77 M - Maximum Data Transfer Size (MDTS)
+ ///
+ public byte MDTS;
+
+ ///
+ /// byte 78:79 M - Controller ID (CNTLID)
+ ///
+ public ushort CNTLID;
+
+ ///
+ /// byte 80:83 M - Version (VER)
+ ///
+ public uint VER;
+
+ ///
+ /// byte 84:87 M - RTD3 Resume Latency (RTD3R)
+ ///
+ public uint RTD3R;
+
+ ///
+ /// byte 88:91 M - RTD3 Entry Latency (RTD3E)
+ ///
+ public uint RTD3E;
+
+ ///
+ /// byte 92:95 M - Optional Asynchronous Events Supported (OAES)
+ ///
+ public uint OAES;
+
+ ///
+ /// byte 96:239.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 144)]
+ public byte[] Reserved0;
+
+ ///
+ /// byte 240:255. Refer to the NVMe Management Interface Specification for definition.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] ReservedForManagement;
+
+ ///
+ /// byte 256:257 M - Optional Admin Command Support (OACS)
+ ///
+ public ushort OACS;
+
+ ///
+ /// byte 258 M - Abort Command Limit (ACL)
+ ///
+ public byte ACL;
+
+ ///
+ /// byte 259 M - Asynchronous Event Request Limit (AERL)
+ ///
+ public byte AERL;
+
+ ///
+ /// byte 260 M - Firmware Updates (FRMW)
+ ///
+ public byte FRMW;
+
+ ///
+ /// byte 261 M - Log Page Attributes (LPA)
+ ///
+ public byte LPA;
+
+ ///
+ /// byte 262 M - Error Log Page Entries (ELPE)
+ ///
+ public byte ELPE;
+
+ ///
+ /// byte 263 M - Number of Power States Support (NPSS)
+ ///
+ public byte NPSS;
+
+ ///
+ /// byte 264 M - Admin Vendor Specific Command Configuration (AVSCC)
+ ///
+ public byte AVSCC;
+
+ ///
+ /// byte 265 O - Autonomous Power State Transition Attributes (APSTA)
+ ///
+ public byte APSTA;
+
+ ///
+ /// byte 266:267 M - Warning Composite Temperature Threshold (WCTEMP)
+ ///
+ public ushort WCTEMP;
+
+ ///
+ /// byte 268:269 M - Critical Composite Temperature Threshold (CCTEMP)
+ ///
+ public ushort CCTEMP;
+
+ ///
+ /// byte 270:271 O - Maximum Time for Firmware Activation (MTFA)
+ ///
+ public ushort MTFA;
+
+ ///
+ /// byte 272:275 O - Host Memory Buffer Preferred Size (HMPRE)
+ ///
+ public uint HMPRE;
+
+ ///
+ /// byte 276:279 O - Host Memory Buffer Minimum Size (HMMIN)
+ ///
+ public uint HMMIN;
+
+ ///
+ /// byte 280:295 O - Total NVM Capacity (TNVMCAP)
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] TNVMCAP;
+
+ ///
+ /// byte 296:311 O - Unallocated NVM Capacity (UNVMCAP)
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] UNVMCAP;
+
+ ///
+ /// byte 312:315 O - Replay Protected Memory Block Support (RPMBS)
+ ///
+ public uint RPMBS;
+
+ ///
+ /// byte 316:511
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 196)]
+ public byte[] Reserved1;
+
+ ///
+ /// byte 512 M - Submission Queue Entry Size (SQES)
+ ///
+ public byte SQES;
+
+ ///
+ /// byte 513 M - Completion Queue Entry Size (CQES)
+ ///
+ public byte CQES;
+
+ ///
+ /// byte 514:515
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
+ public byte[] Reserved2;
+
+ ///
+ /// byte 516:519 M - Number of Namespaces (NN)
+ ///
+ public uint NN;
+
+ ///
+ /// byte 520:521 M - Optional NVM Command Support (ONCS)
+ ///
+ public ushort ONCS;
+
+ ///
+ /// byte 522:523 M - Fused Operation Support (FUSES)
+ ///
+ public ushort FUSES;
+
+ ///
+ /// byte 524 M - Format NVM Attributes (FNA)
+ ///
+ public byte FNA;
+
+ ///
+ /// byte 525 M - Volatile Write Cache (VWC)
+ ///
+ public byte VWC;
+
+ ///
+ /// byte 526:527 M - Atomic Write Unit Normal (AWUN)
+ ///
+ public ushort AWUN;
+
+ ///
+ /// byte 528:529 M - Atomic Write Unit Power Fail (AWUPF)
+ ///
+ public ushort AWUPF;
+
+ ///
+ /// byte 530 M - NVM Vendor Specific Command Configuration (NVSCC)
+ ///
+ public byte NVSCC;
+
+ ///
+ /// byte 531
+ ///
+ public byte Reserved3;
+
+ ///
+ /// byte 532:533 O - Atomic Compare and Write Unit (ACWU)
+ ///
+ public ushort ACWU;
+
+ ///
+ /// byte 534:535
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
+ public byte[] Reserved4;
+
+ ///
+ /// byte 536:539 O - SGL Support (SGLS)
+ ///
+ public uint SGLS;
+
+ ///
+ /// byte 540:703
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 164)]
+ public byte[] Reserved5;
+
+ ///
+ /// byte 704:2047
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1344)]
+ public byte[] Reserved6;
+
+ ///
+ /// byte 2048:3071 Power State Descriptors
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
+ public NVME_POWER_STATE_DESC[] PDS;
+
+ ///
+ /// byte 3072:4095 Vendor Specific
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
+ public byte[] VS;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct NVME_HEALTH_INFO_LOG
+ {
+ ///
+ /// This field indicates critical warnings for the state of the controller.
+ /// Each bit corresponds to a critical warning type; multiple bits may be set.
+ ///
+ public byte CriticalWarning;
+
+ ///
+ /// Composite Temperature: Contains the temperature of the overall device (controller and NVM included) in units of Kelvin.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
+ public byte[] CompositeTemp;
+
+ ///
+ /// Available Spare: Contains a normalized percentage (0 to 100%) of the remaining spare capacity available
+ ///
+ public byte AvailableSpare;
+
+ ///
+ /// Available Spare Threshold: When the Available Spare falls below the threshold indicated in this field,
+ /// an asynchronous event completion may occur. The value is indicated as a normalized percentage (0 to 100%).
+ ///
+ public byte AvailableSpareThreshold;
+
+ ///
+ /// Percentage Used: Contains a vendor specific estimate of the percentage of NVM subsystem life used based on
+ /// the actual usage and the manufacturer’s prediction of NVM life. A value of 100 indicates that the estimated endurance of
+ /// the NVM in the NVM subsystem has been consumed, but may not indicate an NVM subsystem failure. The value is allowed to exceed 100.
+ ///
+ public byte PercentageUsed;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
+ public byte[] Reserved1;
+
+ ///
+ /// Data Units Read: Contains the number of 512 byte data units the host has read from the controller;
+ /// this value does not include metadata. This value is reported in thousands
+ /// (i.e., a value of 1 corresponds to 1000 units of 512 bytes read) and is rounded up.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] DataUnitRead;
+
+ ///
+ /// Data Units Written: Contains the number of 512 byte data units the host has written to the controller;
+ /// this value does not include metadata. This value is reported in thousands
+ /// (i.e., a value of 1 corresponds to 1000 units of 512 bytes written) and is rounded up.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] DataUnitWritten;
+
+ ///
+ /// Host Read Commands: Contains the number of read commands completed by the controller.
+ /// For the NVM command set, this is the number of Compare and Read commands.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] HostReadCommands;
+
+ ///
+ /// Host Write Commands: Contains the number of write commands completed by the controller.
+ /// For the NVM command set, this is the number of Write commands.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] HostWriteCommands;
+
+ ///
+ /// Controller Busy Time: Contains the amount of time the controller is busy with I/O commands.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] ControllerBusyTime;
+
+ ///
+ /// Power Cycles: Contains the number of power cycles.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] PowerCycles;
+
+ ///
+ /// Power On Hours: Contains the number of power-on hours.
+ /// This does not include time that the controller was powered and in a low power state condition.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] PowerOnHours;
+
+ ///
+ /// Unsafe Shutdowns: Contains the number of unsafe shutdowns.
+ /// This count is incremented when a shutdown notification is not received prior to loss of power.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] UnsafeShutdowns;
+
+ ///
+ /// Media Errors: Contains the number of occurrences where the controller detected an unrecoverable data integrity error.
+ /// Errors such as uncorrectable ECC, CRC checksum failure, or LBA tag mismatch are included in this field.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] MediaAndDataIntegrityErrors;
+
+ ///
+ /// Number of Error Information Log Entries: Contains the number of Error Information log entries over the life of the controller
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public byte[] NumberErrorInformationLogEntries;
+
+ ///
+ /// Warning Composite Temperature Time: Contains the amount of time in minutes that the controller is operational and the Composite Temperature is greater than or equal to the Warning Composite
+ /// Temperature Threshold.
+ ///
+ public uint WarningCompositeTemperatureTime;
+
+ ///
+ /// Critical Composite Temperature Time: Contains the amount of time in minutes that the controller is operational and the Composite Temperature is greater than the Critical Composite Temperature
+ /// Threshold.
+ ///
+ public uint CriticalCompositeTemperatureTime;
+
+ ///
+ /// Contains the current temperature reported by temperature sensor 1-8.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public ushort[] TemperatureSensor;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 296)]
+ internal byte[] Reserved2;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct STORAGE_PROTOCOL_SPECIFIC_DATA
+ {
+ public STORAGE_PROTOCOL_TYPE ProtocolType;
+ public uint DataType;
+ public uint ProtocolDataRequestValue;
+ public uint ProtocolDataRequestSubValue;
+ public uint ProtocolDataOffset;
+ public uint ProtocolDataLength;
+ public uint FixedProtocolReturnData;
+ public uint ProtocolDataRequestSubValue2;
+ public uint ProtocolDataRequestSubValue3;
+ public uint Reserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct STORAGE_QUERY_BUFFER
+ {
+ public STORAGE_PROPERTY_ID PropertyId;
+ public STORAGE_QUERY_TYPE QueryType;
+ public STORAGE_PROTOCOL_SPECIFIC_DATA ProtocolSpecific;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4096)]
+ internal byte[] Buffer;
+ }
+
+ [Flags]
+ internal enum MEM : uint
+ {
+ MEM_COMMIT = 0x1000,
+ MEM_RESERVE = 0x2000,
+ MEM_DECOMMIT = 0x4000,
+ MEM_RELEASE = 0x8000,
+ MEM_RESET = 0x80000,
+ MEM_LARGE_PAGES = 0x20000000,
+ MEM_PHYSICAL = 0x400000,
+ MEM_TOP_DOWN = 0x100000,
+ MEM_WRITE_WATCH = 0x200000
+ }
+
+ [Flags]
+ internal enum PAGE : uint
+ {
+ PAGE_EXECUTE = 0x10,
+ PAGE_EXECUTE_READ = 0x20,
+ PAGE_EXECUTE_READWRITE = 0x40,
+ PAGE_EXECUTE_WRITECOPY = 0x80,
+ PAGE_NOACCESS = 0x01,
+ PAGE_READONLY = 0x02,
+ PAGE_READWRITE = 0x04,
+ PAGE_WRITECOPY = 0x08,
+ PAGE_GUARD = 0x100,
+ PAGE_NOCACHE = 0x200,
+ PAGE_WRITECOMBINE = 0x400
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct IOControlCode
+ {
+ ///
+ /// Gets the resulting IO control code.
+ ///
+ public uint Code { get; }
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// Type of the device.
+ /// The function.
+ /// The access.
+ public IOControlCode(uint deviceType, uint function, Access access) : this(deviceType, function, Method.Buffered, access)
+ { }
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// Type of the device.
+ /// The function.
+ /// The method.
+ /// The access.
+ public IOControlCode(uint deviceType, uint function, Method method, Access access)
+ {
+ Code = (deviceType << 16) | ((uint)access << 14) | (function << 2) | (uint)method;
+ }
+
+ public enum Method : uint
+ {
+ Buffered = 0,
+ InDirect = 1,
+ OutDirect = 2,
+ Neither = 3
+ }
+
+ public enum Access : uint
+ {
+ Any = 0,
+ Read = 1,
+ Write = 2
+ }
+ }
+
+ internal enum Provider
+ {
+ ACPI = (byte)'A' << 24 | (byte)'C' << 16 | (byte)'P' << 8 | (byte)'I',
+ FIRM = (byte)'F' << 24 | (byte)'I' << 16 | (byte)'R' << 8 | (byte)'M',
+ RSMB = (byte)'R' << 24 | (byte)'S' << 16 | (byte)'M' << 8 | (byte)'B'
+ }
+}
diff --git a/ColorControl/Services/NVIDIA/NvGpuInfo.cs b/ColorControl/Services/NVIDIA/NvGpuInfo.cs
new file mode 100644
index 0000000..d052d51
--- /dev/null
+++ b/ColorControl/Services/NVIDIA/NvGpuInfo.cs
@@ -0,0 +1,666 @@
+using ColorControl.Common;
+using NvAPIWrapper.GPU;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+using NvAPIWrapper.Native.Interfaces.GPU;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using static NvAPIWrapper.Native.GPU.Structures.PerformanceStates20ClockEntryV1;
+using static NvAPIWrapper.Native.GPU.Structures.PrivateClockBoostLockV2;
+
+namespace ColorControl.Services.NVIDIA
+{
+ public enum NvGpuOcType
+ {
+ None = 0,
+ Offset = 1,
+ Curve = 2,
+ BoostLock = 3
+ }
+
+ public class NvGpuOcSettings
+ {
+ public string PCIIdentifier { get; set; }
+ public int MemoryOffsetKHz { get; set; }
+ public NvGpuOcType Type { get; set; }
+ public int GraphicsOffsetKHz { get; set; }
+ public uint MaximumFrequencyKHz { get; set; }
+ public uint MaximumVoltageUv { get; set; }
+ public uint VoltageBoostPercent { get; set; }
+ public uint PowerPCM { get; set; }
+
+ public override string ToString()
+ {
+ var value = "";
+
+ if (Type == NvGpuOcType.BoostLock)
+ {
+ value += $"GPU: Locked: {(GraphicsOffsetKHz >= 0 ? "+" : "-")}{GraphicsOffsetKHz.ToUnitString()} @ {MaximumVoltageUv}uv";
+ }
+ else if (Type == NvGpuOcType.Curve)
+ {
+ value += $"GPU: Curve: {(GraphicsOffsetKHz >= 0 ? "+" : "-")}{GraphicsOffsetKHz.ToUnitString()}";
+
+ if (MaximumVoltageUv > 0)
+ {
+ value += $", UV: {MaximumFrequencyKHz.ToUnitString()} @ {MaximumVoltageUv / 1000}mv";
+ }
+ }
+ else if (Type == NvGpuOcType.Offset)
+ {
+ value += $"GPU: {(GraphicsOffsetKHz >= 0 ? "+" : "-")}{GraphicsOffsetKHz.ToUnitString()}";
+ }
+
+ if (MemoryOffsetKHz != 0)
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ value += ", ";
+ }
+
+ value += $"Memory: {(MemoryOffsetKHz >= 0 ? "+" : "-")}{MemoryOffsetKHz.ToUnitString()}";
+ }
+
+ if (PowerPCM != 100000)
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ value += ", ";
+ }
+
+ value += $"Power: {PowerPCM / 1000}%";
+ }
+
+ if (string.IsNullOrEmpty(value))
+ {
+ value = "None";
+ }
+
+ return value;
+ }
+ }
+
+ public class NvGpuInfo
+ {
+ private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
+
+ public PhysicalGPU GPU { get; }
+ public List ClockBoostLocks { get; private set; }
+ public List ClockEntries { get; private set; }
+ public ClockDomainInfo StockGraphicsClock { get; private set; }
+ public ClockDomainInfo StockMemoryClock { get; private set; }
+ public PrivateVFPCurveV3 CurveV3 { get; private set; }
+ public PrivateVFPCurveV1 CurveV1 { get; private set; }
+ public int? DefaultPowerInMilliWatts { get; private set; }
+ public int MinPowerInMilliWatts { get; private set; }
+ public int MaxPowerInMilliWatts { get; private set; }
+
+
+ public static readonly PublicClockDomain[] Domains = new[] { PublicClockDomain.Graphics, PublicClockDomain.Memory };
+
+ public static NvGpuInfo GetGpuInfo(string pciId)
+ {
+ var gpuHandles = GPUApi.EnumPhysicalGPUs();
+
+ var gpus = gpuHandles.Select(h => new PhysicalGPU(h)).ToList();
+
+ //var displays = Display.GetDisplays();
+ //var gpus = displays.Select(d => d.DisplayDevice.PhysicalGPU).Distinct().ToList();
+
+ var gpu = gpus.FirstOrDefault(g => g.BusInformation.PCIIdentifiers.ToString() == pciId);
+
+ return GetGpuInfo(gpu);
+ }
+
+ public static NvGpuInfo GetGpuInfo(PhysicalGPU gpu)
+ {
+ var gpuInfo = new NvGpuInfo(gpu);
+
+ return gpuInfo;
+ }
+
+ private NvGpuInfo(PhysicalGPU gpu)
+ {
+ GPU = gpu;
+
+ StockGraphicsClock = GPU.BoostClockFrequencies.GraphicsClock;
+ StockMemoryClock = GPU.BoostClockFrequencies.MemoryClock;
+
+ var handle = gpu.Handle;
+
+ //var xx = GPUApi.ClientPowerTopologyGetStatus(handle);
+
+ var perf = GPUApi.GetPerformanceStates20(handle);
+ var clock3D = perf.Clocks.FirstOrDefault(c => c.Key == PerformanceStateId.P0_3DPerformance);
+
+ var boostLock = GPUApi.GetClockBoostLock(handle);
+
+ ReadCurve();
+
+ if (NvidiaML.IsAvailable || NvidiaML.Initialize())
+ {
+ var device = NvidiaML.NvmlDeviceGetHandleByIndex(0);
+ DefaultPowerInMilliWatts = NvidiaML.NvmlDeviceGetPowerManagementDefaultLimit(device.Value);
+
+ var powerLimits = GetPowerLimits();
+
+ MinPowerInMilliWatts = (int)((decimal)DefaultPowerInMilliWatts / 100000 * powerLimits.Item1);
+ MaxPowerInMilliWatts = (int)((decimal)DefaultPowerInMilliWatts / 100000 * powerLimits.Item2);
+
+ }
+
+ //var bla2 = GPUApi.GetClockBoostRanges(handle);
+ //var bla3 = GPUApi.GetClockBoostTableV2(handle);
+
+ //for (var i = 0; i < bla3.GPUDeltas.Count(); i++)
+ //{
+ // if (bla3.GPUDeltas[i].ClockType == 0)
+ // {
+ // bla3.GPUDeltas[i].FrequencyDeltaInkHz = 145000;
+ // }
+ // else if (bla3.GPUDeltas[i].ClockType == 1)
+ // {
+ // //bla3.GPUDeltas[i]._FrequencyDeltaInkHz = 50000;
+ // }
+
+ //}
+
+ //GPUApi.SetClockBoostTableV2(handle, bla3);
+
+ //var bla4 = GPUApi.GetAllClockFrequencies(handle);
+
+ ClockBoostLocks = boostLock.ClockBoostLocks.Where(l => l.LockMode == ClockLockMode.Manual).ToList();
+ ClockEntries = clock3D.Value.ToList();
+ }
+
+ public (uint, uint) GetPowerLimits()
+ {
+ var power = GPU.PerformanceControl.PowerLimitInformation.FirstOrDefault();
+
+ if (power == null)
+ {
+ return (20000, 100000);
+ }
+
+ return (power.MinimumPowerInPCM, power.MaximumPowerInPCM);
+ }
+
+ public uint GetPowerUsageInMilliWatts()
+ {
+ if (DefaultPowerInMilliWatts.HasValue)
+ {
+ var powerInPCM = GPU.PowerTopologyInformation.PowerTopologyEntries.FirstOrDefault(e => e.Domain == PowerTopologyDomain.Board);
+ var power = (uint)((decimal)powerInPCM.PowerUsageInPCM / 100000 * DefaultPowerInMilliWatts);
+
+ return power;
+ }
+
+ return 0;
+ }
+
+ private void ReadCurve()
+ {
+ try
+ {
+ CurveV3 = GPUApi.GetVFPCurveV3(GPU.Handle);
+ }
+ catch (Exception ex)
+ {
+ Logger.Debug(ex);
+
+ var bla = GPUApi.GetClockBoostMask(GPU.Handle);
+
+ var masks = bla._Masks;
+ Logger.Debug("MASKS: " + masks[0]);
+
+ Logger.Debug("MASK: " + bla._Unknown1[0]);
+
+ CurveV1 = GPUApi.GetVFPCurve(GPU.Handle, masks);
+
+ var length = CurveV1.GPUCurveEntries.Length;
+ var minFreq = CurveV1.GPUCurveEntries.Min(e => e.FrequencyInkHz);
+ var maxFreq = CurveV1.GPUCurveEntries.Max(e => e.FrequencyInkHz);
+ var minV = CurveV1.GPUCurveEntries.Min(e => e.VoltageInMicroV);
+ var maxV = CurveV1.GPUCurveEntries.Max(e => e.VoltageInMicroV);
+
+ Logger.Debug($"CurveV1: L: {length}, MinF: {minFreq}, MaxF: {maxFreq}, MinV: {minV}, MaxV: {maxV}");
+ }
+ }
+
+ public bool ApplyOcSettings(NvGpuOcSettings settings)
+ {
+ var pciId = GPU.BusInformation.PCIIdentifiers.ToString();
+
+ if (settings.PCIIdentifier != pciId)
+ {
+ Logger.Warn($"Cannot apply OC-settings: PCI-identifier does not match GPU: {settings.PCIIdentifier}");
+
+ return false;
+ }
+
+ ResetGpuClocks();
+
+ if (settings.PowerPCM >= 0)
+ {
+ SetPower(settings.PowerPCM);
+ }
+
+ if (settings.MemoryOffsetKHz != 0)
+ {
+ SetMemoryClockOffsetDelta(settings.MemoryOffsetKHz);
+ }
+
+ if (settings.VoltageBoostPercent >= 0)
+ {
+ SetVoltageBoostPercent(settings.VoltageBoostPercent);
+ }
+
+ if (settings.Type == NvGpuOcType.None)
+ {
+ return true;
+ }
+
+ if (settings.Type == NvGpuOcType.BoostLock)
+ {
+ LockGpuClock(settings.MaximumVoltageUv, settings.GraphicsOffsetKHz);
+
+ return true;
+ }
+
+ if (settings.Type == NvGpuOcType.Offset && settings.MaximumVoltageUv == 0)
+ {
+ SetGraphicsClockOffset(settings.GraphicsOffsetKHz);
+
+ return true;
+ }
+
+ SetCurveOffset(settings.GraphicsOffsetKHz, settings.MaximumVoltageUv, settings.MaximumFrequencyKHz);
+
+ return true;
+ }
+
+ public void SetPower(uint powerPercent)
+ {
+ if (powerPercent == 0)
+ {
+ powerPercent = 100000;
+ }
+
+ var entry = new PrivatePowerPoliciesStatusV1.PowerPolicyStatusEntry(powerPercent);
+ var status = new PrivatePowerPoliciesStatusV1(new[] { entry });
+
+ GPUApi.ClientPowerPoliciesSetStatus(GPU.Handle, status);
+ }
+
+ public override string ToString()
+ {
+ var gpuThermal = GPU.ThermalInformation.ThermalSensors.FirstOrDefault(s => s.Target == ThermalSettingsTarget.GPU);
+ var gpuVoltage = GPUApi.GetCurrentVoltage(GPU.Handle).ValueInMicroVolt;
+
+ try
+ {
+ var temps = GPUApi.QueryThermalSensors(GPU.Handle, 255u);
+ var hotspotTemp = Math.Round(temps.Temperatures[1]);
+ var memoryTemp = temps.Temperatures[7];
+ var power = GetPowerUsageInMilliWatts();
+
+ return $"GPU: {GPU.CurrentClockFrequencies.GraphicsClock.Frequency.ToUnitString()} @ {gpuVoltage / 1000}mv, {gpuThermal.CurrentTemperature}°/{hotspotTemp}°C, Mem: {GPU.CurrentClockFrequencies.MemoryClock.Frequency.ToUnitString()}, {memoryTemp}°C, Pwr: {power / 1000}W";
+ }
+ catch (Exception) { }
+
+ return $"GPU: {GPU.CurrentClockFrequencies.GraphicsClock.Frequency.ToUnitString()} @ {gpuVoltage / 1000}mv, {gpuThermal.CurrentTemperature}°C, Mem: {GPU.CurrentClockFrequencies.MemoryClock.Frequency.ToUnitString()}";
+ }
+
+ public (int, int) GetDeltaClockMinMax(PublicClockDomain domain)
+ {
+ var delta = ClockEntries.FirstOrDefault(e => e.DomainId == domain)?.FrequencyDeltaInkHz;
+
+ return (delta?.DeltaRange.Minimum ?? -502000, delta?.DeltaRange.Maximum ?? (domain == PublicClockDomain.Graphics ? 1000000 : 3000000));
+ }
+
+ public PerformanceStates20ParameterDelta? GetDeltaClockLimits(PublicClockDomain domain)
+ {
+ return ClockEntries.FirstOrDefault(e => e.DomainId == domain)?.FrequencyDeltaInkHz;
+ }
+
+ public bool HasLock(PublicClockDomain domain)
+ {
+ return ClockBoostLocks.Any(l => l.ClockDomain == domain && l.LockMode == ClockLockMode.Manual);
+ }
+
+ public int GetOffset(PublicClockDomain domain)
+ {
+ var entry = ClockEntries.FirstOrDefault(e => e.DomainId == domain);
+
+ var value = entry?.FrequencyDeltaInkHz.DeltaValue ?? 0;
+
+ if (value == 0 && domain == PublicClockDomain.Memory && entry != null)
+ {
+ var maxFreq = entry.SingleFrequency.FrequencyInkHz;
+ var defaultFreq = GPU.BoostClockFrequencies.MemoryClock.Frequency;
+
+ value = (int)(maxFreq - defaultFreq);
+ }
+
+ return value;
+ }
+
+ public (uint, int) GetLockedBoost(PublicClockDomain domain)
+ {
+ var boostLock = ClockBoostLocks.FirstOrDefault(l => l.ClockDomain == domain && l.LockMode == ClockLockMode.Manual);
+
+ if (boostLock.LockMode != ClockLockMode.Manual)
+ {
+ return (0, 0);
+ }
+
+ var offset = GetOffset(domain);
+
+ return (boostLock.VoltageInMicroV, offset);
+ }
+
+ public NvGpuOcSettings GetOverclockSettings()
+ {
+ var ocSettings = new NvGpuOcSettings();
+
+ var power = GPUApi.ClientPowerPoliciesGetStatus(GPU.Handle);
+
+ ocSettings.PowerPCM = power.PowerPolicyStatusEntries.FirstOrDefault(e => e.PerformanceStateId == PerformanceStateId.P0_3DPerformance).PowerTargetInPCM;
+
+ foreach (var domain in Domains)
+ {
+ var locked = GetLockedBoost(domain);
+
+ if (locked.Item1 != 0)
+ {
+ if (ocSettings.Type == NvGpuOcType.None)
+ {
+ ocSettings.Type = NvGpuOcType.BoostLock;
+ }
+
+ ocSettings.MaximumVoltageUv = locked.Item1;
+
+ if (domain == PublicClockDomain.Graphics)
+ {
+ ocSettings.GraphicsOffsetKHz = locked.Item2;
+ }
+ else
+ {
+ ocSettings.MemoryOffsetKHz = locked.Item2;
+ }
+ }
+
+ if (ocSettings.Type == NvGpuOcType.None && domain == PublicClockDomain.Graphics && CurveV3.GPUCurveEntries != null)
+ {
+ var entry = CurveV3.GPUCurveEntries.MaxBy(e => (int)e.FrequencyInkHz - (int)e.DefaultFrequencyInkHz);
+ var offsetCurve = (int)entry.FrequencyInkHz - (int)entry.DefaultFrequencyInkHz;
+ if (offsetCurve != 0)
+ {
+ var isChanged = CurveV3.GPUCurveEntries.Any(e => e.ClockType == 0 && e.DefaultFrequencyInkHz != 0 && ((int)e.FrequencyInkHz - (int)e.DefaultFrequencyInkHz) != offsetCurve);
+
+ ocSettings.Type = isChanged ? NvGpuOcType.Curve : NvGpuOcType.Offset;
+ ocSettings.GraphicsOffsetKHz = offsetCurve;
+
+ if (offsetCurve > 0 && ocSettings.Type == NvGpuOcType.Curve)
+ {
+ var maxOcEntry = CurveV3.GPUCurveEntries.MaxBy(e => e.FrequencyInkHz);
+ var maxDefEntry = CurveV3.GPUCurveEntries.MaxBy(e => e.DefaultFrequencyInkHz);
+
+ if (maxOcEntry.FrequencyInkHz < maxDefEntry.DefaultFrequencyInkHz)
+ {
+ ocSettings.MaximumVoltageUv = maxOcEntry.VoltageInMicroV;
+ ocSettings.MaximumFrequencyKHz = maxDefEntry.FrequencyInkHz;
+ }
+ }
+ }
+ }
+
+ if (ocSettings.Type == NvGpuOcType.None || domain == PublicClockDomain.Memory)
+ {
+ var offset = GetOffset(domain);
+
+ if (offset != 0)
+ {
+ if (ocSettings.Type == NvGpuOcType.None)
+ {
+ ocSettings.Type = NvGpuOcType.Offset;
+ }
+
+ if (domain == PublicClockDomain.Graphics)
+ {
+ ocSettings.GraphicsOffsetKHz = offset;
+ }
+ else
+ {
+ ocSettings.MemoryOffsetKHz = offset;
+ }
+ }
+ }
+ }
+
+ return ocSettings;
+ }
+
+ public void SetGpuClocks(uint lockedVoltageMicroV = 1000000, int coreOffsetKHz = 0, int memOffsetKHz = 0)
+ {
+ var handle = GPU.Handle;
+
+ var perf = GPUApi.GetPerformanceStates20(handle);
+
+ var lockv2 = new PrivateClockBoostLockV2(new[] { new ClockBoostLock(PublicClockDomain.Graphics, ClockLockMode.Manual, lockedVoltageMicroV) });
+
+ var bla = GPUApi.GetClockBoostLock(handle);
+
+ GPUApi.SetClockBoostLock(handle, lockv2);
+
+ //var curve = GPUApi.GetVFPCurve(handle);
+
+ var currentFreq = perf.Clocks.First().Value.First(v => v.DomainId == PublicClockDomain.Graphics).SingleFrequency;
+
+ var delta = new PerformanceStates20ParameterDelta(coreOffsetKHz);
+ //var delta2 = new PerformanceStates20ParameterDelta(0);
+ //var delta3 = new PerformanceStates20ParameterDelta(0);
+ //var single1 = new PerformanceStates20ClockDependentSingleFrequency(2670000);
+ //var single2 = new PerformanceStates20ClockDependentSingleFrequency(2760000);
+ //var single3 = new PerformanceStates20ClockDependentSingleFrequency(2775000);
+
+ //var clockEntry1 = new PerformanceStates20ClockEntryV1(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics, delta, single1);
+ //var clockEntry2 = new PerformanceStates20ClockEntryV1(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics, delta2, single2);
+ //var clockEntry3 = new PerformanceStates20ClockEntryV1(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics, delta3, single3);
+
+ var range = new PerformanceStates20ClockDependentFrequencyRange(2400000, 3000000, PerformanceVoltageDomain.Core, 950000, 1050000);
+ var clockEntry = new PerformanceStates20ClockEntryV1(PublicClockDomain.Graphics, delta, range);
+
+ var memDelta = new PerformanceStates20ParameterDelta(memOffsetKHz);
+ var memClockEntry = new PerformanceStates20ClockEntryV1(PublicClockDomain.Memory, memDelta);
+
+ //var range2 = new PerformanceStates20ClockDependentFrequencyRange(2800001, 3000000, NvAPIWrapper.Native.GPU.PerformanceVoltageDomain.Core, 1000000, 1000000);
+ //var clockEntry2 = new PerformanceStates20ClockEntryV1(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics, delta2, range2);
+
+ var deltaVoltage = new PerformanceStates20ParameterDelta(0);
+ var voltage = new PerformanceStates20BaseVoltageEntryV1(PerformanceVoltageDomain.Core, deltaVoltage);
+
+ var state = new PerformanceStates20InfoV1.PerformanceState20(PerformanceStateId.P0_3DPerformance, new[] { clockEntry, memClockEntry }, new[] { voltage });
+
+ var newPerf = new PerformanceStates20InfoV3(new[] { state }, 2, 1);
+
+ GPUApi.SetPerformanceStates20(handle, newPerf);
+ }
+
+ public void LockGpuClock(uint lockedVoltageMicroV = 1000000, int coreOffsetKHz = 0)
+ {
+ var handle = GPU.Handle;
+
+ var lockv2 = new PrivateClockBoostLockV2(new[] { new ClockBoostLock(PublicClockDomain.Graphics, ClockLockMode.Manual, lockedVoltageMicroV) });
+
+ GPUApi.SetClockBoostLock(handle, lockv2);
+
+ var delta = new PerformanceStates20ParameterDelta(coreOffsetKHz);
+
+ var range = new PerformanceStates20ClockDependentFrequencyRange(1200000, 3000000, PerformanceVoltageDomain.Core, 0, 0);
+ var clockEntry = new PerformanceStates20ClockEntryV1(PublicClockDomain.Graphics, delta, range);
+
+ var state = new PerformanceStates20InfoV1.PerformanceState20(PerformanceStateId.P0_3DPerformance, new[] { clockEntry }, Array.Empty());
+
+ var newPerf = new PerformanceStates20InfoV3(new[] { state }, 1, 1);
+
+ GPUApi.SetPerformanceStates20(handle, newPerf);
+ }
+
+ public void SetGraphicsClockOffset(int coreOffsetKHz = 0)
+ {
+ var delta = new PerformanceStates20ParameterDelta(coreOffsetKHz);
+
+ var range = new PerformanceStates20ClockDependentFrequencyRange(1200000, 3000000, PerformanceVoltageDomain.Core, 0, 0);
+ var clockEntry = new PerformanceStates20ClockEntryV1(PublicClockDomain.Graphics, delta, range);
+
+ var state = new PerformanceStates20InfoV1.PerformanceState20(PerformanceStateId.P0_3DPerformance, new[] { clockEntry }, Array.Empty());
+
+ var newPerf = new PerformanceStates20InfoV3(new[] { state }, 1, 0);
+
+ GPUApi.SetPerformanceStates20(GPU.Handle, newPerf);
+ }
+
+ public void SetMemoryClockOffsetDelta(int memOffsetKHz = 0)
+ {
+ var handle = GPU.Handle;
+
+ var memDelta = new PerformanceStates20ParameterDelta(memOffsetKHz);
+ var memClockEntry = new PerformanceStates20ClockEntryV1(PublicClockDomain.Memory, memDelta);
+
+ var state = new PerformanceStates20InfoV1.PerformanceState20(PerformanceStateId.P0_3DPerformance, new[] { memClockEntry }, Array.Empty());
+
+ var newPerf = new PerformanceStates20InfoV3(new[] { state }, 1, 0);
+
+ GPUApi.SetPerformanceStates20(handle, newPerf);
+ }
+
+ public void SetMemoryClockOffsetRange(int memOffsetKHz = 0)
+ {
+ var handle = GPU.Handle;
+
+ var memDelta = new PerformanceStates20ParameterDelta(0);
+
+ var defaultFreq = GPU.BoostClockFrequencies.MemoryClock.Frequency;
+ var newFreq = (uint)(defaultFreq + memOffsetKHz);
+
+ var memFreq = new PerformanceStates20ClockDependentFrequencyRange(newFreq, newFreq, PerformanceVoltageDomain.Undefined, 0, 0);
+ var memFreq2 = new PerformanceStates20ClockDependentSingleFrequency(newFreq);
+ var memClockEntry = new PerformanceStates20ClockEntryV1(PublicClockDomain.Memory, memDelta, memFreq);
+ var memClockEntry2 = new PerformanceStates20ClockEntryV1(PublicClockDomain.Memory, memDelta, memFreq2);
+
+ var state = new PerformanceStates20InfoV1.PerformanceState20(PerformanceStateId.P0_3DPerformance, new[] { memClockEntry, memClockEntry2 }, Array.Empty());
+
+ var newPerf = new PerformanceStates20InfoV3(new[] { state }, 1, 0);
+
+ GPUApi.SetPerformanceStates20(handle, newPerf);
+ }
+
+ public void SetCurveOffset(int offsetKHz = 0, uint maxVoltageUv = 0, uint maxFreqKHz = 0)
+ {
+ var normalizedOffset = (offsetKHz / 15000) * 15000;
+
+ var handle = GPU.Handle;
+
+ var boostTable = GPUApi.GetClockBoostTableV2(handle);
+
+ var curveEntries = CurveV3.GPUCurveEntries;
+
+ if (maxVoltageUv > 0)
+ {
+ var newCurveEntryVolt = curveEntries.FirstOrDefault(e => e.DefaultVoltageInMicroV == maxVoltageUv);
+ var newFreq = (uint)(newCurveEntryVolt.DefaultFrequencyInkHz + offsetKHz);
+ var newCurveEntryFreq = curveEntries.FirstOrDefault(e => e.DefaultFrequencyInkHz == newFreq);
+
+ maxFreqKHz = newFreq;
+ }
+
+ for (var i = 0; i < boostTable.GPUDeltas.Count(); i++)
+ {
+ if (boostTable.GPUDeltas[i].ClockType != 0)
+ {
+ break;
+ }
+
+ var curOffset = offsetKHz;
+
+ if (maxFreqKHz > 0 && CurveV3.GPUCurveEntries?.Length > i)
+ {
+ var curveEntry = CurveV3.GPUCurveEntries[i];
+
+ if (curveEntry.DefaultFrequencyInkHz + offsetKHz > maxFreqKHz)
+ {
+ curOffset += (int)(maxFreqKHz - (curveEntry.DefaultFrequencyInkHz + offsetKHz));
+ }
+ }
+
+ boostTable.GPUDeltas[i].FrequencyDeltaInkHz = curOffset;
+
+ }
+ GPUApi.SetClockBoostTableV2(handle, boostTable);
+
+ ReadCurve();
+ }
+
+ public void ResetGpuClocks()
+ {
+ var handle = GPU.Handle;
+
+ var lockv2 = new PrivateClockBoostLockV2(new[] { new ClockBoostLock(PublicClockDomain.Graphics, ClockLockMode.None, 0) });
+
+ GPUApi.SetClockBoostLock(handle, lockv2);
+
+ SetMemoryClockOffsetDelta(0);
+ SetGraphicsClockOffset(0);
+ SetCurveOffset(0);
+ SetVoltageBoostPercent(0);
+ }
+
+ public uint GetGpuVoltage()
+ {
+ var voltage = GPUApi.GetCurrentVoltage(GPU.Handle);
+
+ return voltage.ValueInMicroVolt;
+ }
+
+ public void SetVoltageBoostPercent(uint percent)
+ {
+ var voltBoost = new PrivateVoltageBoostPercentV1(percent);
+
+ GPUApi.SetCoreVoltageBoostPercent(GPU.Handle, voltBoost);
+ }
+
+ public string GetGpuLimits()
+ {
+ var handle = GPU.Handle;
+
+ var perf = GPUApi.GetPerformanceStates20(handle);
+ var clock3D = perf.Clocks.FirstOrDefault(c => c.Key == NvAPIWrapper.Native.GPU.PerformanceStateId.P0_3DPerformance);
+
+ var boostLock = GPUApi.GetClockBoostLock(handle);
+
+ var clockFreqs = GPUApi.GetAllClockFrequencies(handle);
+
+ //GPUApi.ClientPowerPoliciesGetStatus(handle);
+
+ //var mask = GPUApi.GetClockBoostMask(handle);
+
+ //var ranges = GPUApi.GetClockBoostRanges(handle);
+
+ //var table = GPUApi.GetClockBoostTable(handle);
+
+ var voltageBoost = GPUApi.GetCoreVoltageBoostPercent(handle);
+
+ //var voltage = GPUApi.GetCurrentVoltage(handle);
+
+ //var dynPerf = GPUApi.GetDynamicPerformanceStatesInfoEx(handle);
+
+ //var pols = GPUApi.PerformancePoliciesGetInfo(handle);
+
+ return string.Empty;
+ }
+
+ }
+}
diff --git a/ColorControl/Services/NVIDIA/NvPreset.cs b/ColorControl/Services/NVIDIA/NvPreset.cs
index 72d080b..0f05ad4 100644
--- a/ColorControl/Services/NVIDIA/NvPreset.cs
+++ b/ColorControl/Services/NVIDIA/NvPreset.cs
@@ -32,6 +32,9 @@ namespace ColorControl.Services.NVIDIA
public uint ditheringMode { get; set; }
public bool applyDriverSettings { get; set; }
public Dictionary driverSettings { get; set; }
+ public bool applyOverclocking { get; set; }
+ public List ocSettings { get; set; }
+
[JsonIgnore]
public bool IsDisplayPreset => Display != null;
public Display Display { get; set; }
@@ -54,6 +57,7 @@ namespace ColorControl.Services.NVIDIA
ditheringMode = 4;
applyDriverSettings = false;
driverSettings = new Dictionary();
+ ocSettings = new List();
}
public NvPreset(ColorData colorData) : this()
@@ -96,7 +100,7 @@ namespace ColorControl.Services.NVIDIA
public static string[] GetColumnNames()
{
- return new[] { "Name", "Display|140", "Color settings (BPC, format, dyn. range, color space)|260", "Refresh rate|100", "Resolution|120", "Dithering", "HDR", "Driver settings|300", "Shortcut", "Apply on startup" };
+ return new[] { "Name", "Display|140", "Color settings (BPC, format, dyn. range, color space)|260", "Refresh rate|100", "Resolution|120", "Dithering", "HDR", "Driver settings|300", "Overclocking|300", "Shortcut", "Apply on startup" };
}
public override List GetDisplayValues(Config config = null)
@@ -129,6 +133,8 @@ namespace ColorControl.Services.NVIDIA
values.Add(string.Format("{0}: {1}", applyDriverSettings ? "Included" : "Excluded", GetDriverSettingsDescription()));
+ values.Add(string.Format("{0}: {1}", applyOverclocking ? "Included" : "Excluded", GetOverclockingSettingsDescription()));
+
values.Add(shortcut);
values.Add(string.Format("{0}", config?.NvPresetId_ApplyOnStartup == id ? "Yes" : string.Empty));
@@ -136,6 +142,25 @@ namespace ColorControl.Services.NVIDIA
return values;
}
+ public string GetOverclockingSettingsDescription(bool useNewLines = false)
+ {
+ if (ocSettings.Count == 0)
+ {
+ return "None";
+ }
+
+ var values = new List();
+
+ foreach (var ocSetting in ocSettings)
+ {
+ var value = ocSetting.ToString();
+
+ values.Add($"{value}");
+ }
+
+ return string.Join(useNewLines ? "\r\n" : ", ", values);
+ }
+
public string GetDriverSettingsDescription(bool useNewLines = false)
{
if (driverSettings.Count == 0)
@@ -293,6 +318,20 @@ namespace ColorControl.Services.NVIDIA
{
driverSettings.Remove(settingId);
}
+
+ internal void UpdateOverclockingSetting(NvGpuOcSettings newSettings)
+ {
+ var index = ocSettings.FindIndex(s => s.PCIIdentifier == newSettings.PCIIdentifier);
+
+ if (index >= 0)
+ {
+ ocSettings[index] = newSettings;
+ }
+ else
+ {
+ ocSettings.Add(newSettings);
+ }
+ }
}
}
diff --git a/ColorControl/Services/NVIDIA/NvService.cs b/ColorControl/Services/NVIDIA/NvService.cs
index 80e226c..3f586f1 100644
--- a/ColorControl/Services/NVIDIA/NvService.cs
+++ b/ColorControl/Services/NVIDIA/NvService.cs
@@ -3,6 +3,7 @@ using ColorControl.Forms;
using ColorControl.Services.Common;
using ColorControl.Svc;
using Microsoft.Extensions.DependencyInjection;
+using Newtonsoft.Json;
using nspector.Common;
using nspector.Common.Meta;
using NvAPIWrapper.Display;
@@ -14,11 +15,10 @@ using NWin32.NativeTypes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
+using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
-using static NvAPIWrapper.Native.GPU.Structures.PerformanceStates20ClockEntryV1;
-using static NvAPIWrapper.Native.GPU.Structures.PrivateClockBoostLockV2;
namespace ColorControl.Services.NVIDIA
{
@@ -93,6 +93,8 @@ namespace ColorControl.Services.NVIDIA
private Display _currentDisplay;
private string _baseProfileName = "";
+ private string _configFilename;
+ public NvServiceConfig Config { get; private set; }
private DrsSettingsService _drs;
private DrsSettingsMetaService _meta;
@@ -139,7 +141,7 @@ namespace ColorControl.Services.NVIDIA
NvPreset.NvService = this;
AddJsonConverter(new ColorDataConverter());
-
+ LoadConfig();
LoadPresets();
}
@@ -211,6 +213,7 @@ namespace ColorControl.Services.NVIDIA
public void GlobalSave()
{
SavePresets();
+ SaveConfig();
}
protected override List GetDefaultPresets()
@@ -317,6 +320,11 @@ namespace ColorControl.Services.NVIDIA
SetDriverSettings(preset.driverSettings);
}
+ if (preset.applyOverclocking)
+ {
+ ApplyOverclocking(preset.ocSettings);
+ }
+
_lastAppliedPreset = preset;
PresetApplied();
@@ -324,6 +332,36 @@ namespace ColorControl.Services.NVIDIA
return result;
}
+ public void ApplyOverclocking(NvGpuOcSettings setting)
+ {
+ ApplyOverclocking(new List { setting });
+ }
+
+ public void ApplyOverclocking(List settings)
+ {
+ if (!Utils.IsAdministrator())
+ {
+ PipeUtils.SendMessage(new SvcNvOverclockingMessage
+ {
+ OverclockingSettings = settings
+ });
+
+ return;
+ }
+
+ foreach (var ocSetting in settings)
+ {
+ var gpuInfo = NvGpuInfo.GetGpuInfo(ocSetting.PCIIdentifier);
+
+ if (gpuInfo == null)
+ {
+ continue;
+ }
+
+ gpuInfo.ApplyOcSettings(ocSetting);
+ }
+ }
+
public bool SetColorData(Display display, ColorData colorData)
{
try
@@ -361,7 +399,7 @@ namespace ColorControl.Services.NVIDIA
return result;
}
- private static void CheckServiceInstance()
+ public static NvService CheckServiceInstance()
{
if (ServiceInstance == null)
{
@@ -371,6 +409,8 @@ namespace ColorControl.Services.NVIDIA
ServiceInstance.Initialize();
ServiceInstance.RefreshProfileSettings();
}
+
+ return ServiceInstance;
}
private void SetDriverSettings(Dictionary settings)
@@ -621,6 +661,15 @@ namespace ColorControl.Services.NVIDIA
return Display.GetDisplays();
}
+ public List GetGPUs()
+ {
+ var gpuHandles = GPUApi.EnumPhysicalGPUs();
+
+ var gpus = gpuHandles.Select(h => new PhysicalGPU(h)).ToList();
+
+ return gpus;
+ }
+
public List GetDisplayInfos()
{
try
@@ -890,94 +939,26 @@ namespace ColorControl.Services.NVIDIA
}
}
- public void SetGpuClocks(PhysicalGPU gpu, uint lockedVoltageMicroV = 1000000, int coreOffsetKHz = 0, int memOffsetKHz = 0)
+ private void LoadConfig()
{
- // TEST ONLY
- gpu ??= PhysicalGPU.GetPhysicalGPUs().FirstOrDefault();
-
- if (gpu == null)
+ _configFilename = Path.Combine(_dataPath, "NvConfig.json");
+ try
{
- Logger.Debug("No GPU");
- return;
+ if (File.Exists(_configFilename))
+ {
+ Config = JsonConvert.DeserializeObject(File.ReadAllText(_configFilename));
+ }
}
-
- var handle = gpu.Handle;
-
- var perf = GPUApi.GetPerformanceStates20(handle);
-
- var lockv2 = new PrivateClockBoostLockV2(new[] { new ClockBoostLock(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics, NvAPIWrapper.Native.GPU.ClockLockMode.Manual, lockedVoltageMicroV) });
-
- var bla = GPUApi.GetClockBoostLock(handle);
-
- GPUApi.SetClockBoostLock(handle, lockv2);
-
- var curve = GPUApi.GetVFPCurve(handle);
-
- var currentFreq = perf.Clocks.First().Value.First(v => v.DomainId == NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics).SingleFrequency;
-
- var delta = new PerformanceStates20ParameterDelta(coreOffsetKHz);
- //var delta2 = new PerformanceStates20ParameterDelta(0);
- //var delta3 = new PerformanceStates20ParameterDelta(0);
- //var single1 = new PerformanceStates20ClockDependentSingleFrequency(2670000);
- //var single2 = new PerformanceStates20ClockDependentSingleFrequency(2760000);
- //var single3 = new PerformanceStates20ClockDependentSingleFrequency(2775000);
-
- //var clockEntry1 = new PerformanceStates20ClockEntryV1(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics, delta, single1);
- //var clockEntry2 = new PerformanceStates20ClockEntryV1(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics, delta2, single2);
- //var clockEntry3 = new PerformanceStates20ClockEntryV1(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics, delta3, single3);
-
- var range = new PerformanceStates20ClockDependentFrequencyRange(2400000, 3000000, NvAPIWrapper.Native.GPU.PerformanceVoltageDomain.Core, 950000, 1050000);
- var clockEntry = new PerformanceStates20ClockEntryV1(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics, delta, range);
-
- var memDelta = new PerformanceStates20ParameterDelta(memOffsetKHz);
- var memClockEntry = new PerformanceStates20ClockEntryV1(NvAPIWrapper.Native.GPU.PublicClockDomain.Memory, memDelta);
-
- //var range2 = new PerformanceStates20ClockDependentFrequencyRange(2800001, 3000000, NvAPIWrapper.Native.GPU.PerformanceVoltageDomain.Core, 1000000, 1000000);
- //var clockEntry2 = new PerformanceStates20ClockEntryV1(NvAPIWrapper.Native.GPU.PublicClockDomain.Graphics, delta2, range2);
-
- var deltaVoltage = new PerformanceStates20ParameterDelta(0);
- var voltage = new PerformanceStates20BaseVoltageEntryV1(NvAPIWrapper.Native.GPU.PerformanceVoltageDomain.Core, deltaVoltage);
-
- var state = new PerformanceStates20InfoV1.PerformanceState20(NvAPIWrapper.Native.GPU.PerformanceStateId.P0_3DPerformance, new[] { clockEntry, memClockEntry }, new[] { voltage });
-
- var newPerf = new PerformanceStates20InfoV3(new[] { state }, 2, 1);
-
- GPUApi.SetPerformanceStates20(handle, newPerf);
+ catch (Exception ex)
+ {
+ Logger.Error($"LoadConfig: {ex.Message}");
+ }
+ Config ??= new NvServiceConfig();
}
- public string GetGpuClocks(PhysicalGPU gpu)
+ private void SaveConfig()
{
- var handle = gpu.Handle;
-
- var perf = GPUApi.GetPerformanceStates20(handle);
- var clock3D = perf.Clocks.FirstOrDefault(c => c.Key == NvAPIWrapper.Native.GPU.PerformanceStateId.P0_3DPerformance);
-
- var boostLock = GPUApi.GetClockBoostLock(handle);
-
- var values = new List();
-
- foreach (var boostClock in boostLock.ClockBoostLocks.Where(l => l.LockMode == NvAPIWrapper.Native.GPU.ClockLockMode.Manual))
- {
- var clock = clock3D.Value.FirstOrDefault(c => c.DomainId == boostClock.ClockDomain);
-
- var value = $"{boostClock.ClockDomain}: ";
-
- if (clock != null)
- {
- value += $"{clock.FrequencyDeltaInkHz.DeltaValue}KHz @ ";
- }
-
- value += $"{boostClock.VoltageInMicroV}uv";
-
- values.Add(value);
- }
-
- if (!values.Any())
- {
- values.Add("None");
- }
-
- return string.Join(", ", values);
+ Utils.WriteObject(_configFilename, Config);
}
}
}
diff --git a/ColorControl/Services/NVIDIA/NvServiceConfig.cs b/ColorControl/Services/NVIDIA/NvServiceConfig.cs
new file mode 100644
index 0000000..9ab9780
--- /dev/null
+++ b/ColorControl/Services/NVIDIA/NvServiceConfig.cs
@@ -0,0 +1,11 @@
+namespace ColorControl.Services.NVIDIA
+{
+ class NvServiceConfig
+ {
+ public bool ShowOverclocking { get; set; }
+
+ public NvServiceConfig()
+ {
+ }
+ }
+}
diff --git a/ColorControl/Services/NVIDIA/NvidiaML.cs b/ColorControl/Services/NVIDIA/NvidiaML.cs
new file mode 100644
index 0000000..77bc075
--- /dev/null
+++ b/ColorControl/Services/NVIDIA/NvidiaML.cs
@@ -0,0 +1,400 @@
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// Copyright (C) LibreHardwareMonitor and Contributors.
+// All Rights Reserved.
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace ColorControl.Services.NVIDIA;
+
+internal static class NvidiaML
+{
+ private const string LinuxDllName = "nvidia-ml";
+ private const string WindowsDllName = "nvml.dll";
+
+ private static readonly object _syncRoot = new();
+
+ private static IntPtr _windowsDll;
+
+ private static WindowsNvmlGetHandleDelegate _windowsNvmlDeviceGetHandleByIndex;
+ private static WindowsNvmlGetHandleByPciBusIdDelegate _windowsNvmlDeviceGetHandleByPciBusId;
+ private static WindowsNvmlDeviceGetPcieThroughputDelegate _windowsNvmlDeviceGetPcieThroughputDelegate;
+ private static WindowsNvmlDeviceGetPciInfo _windowsNvmlDeviceGetPciInfo;
+ private static WindowsNvmlGetPowerUsageDelegate _windowsNvmlDeviceGetPowerUsage;
+ private static WindowsNvmlGetPowerManagementDefaultLimitDelegate _windowsNvmlDevicePowerManagementDefaultLimit;
+ private static WindowsNvmlDelegate _windowsNvmlInit;
+ private static WindowsNvmlDelegate _windowsNvmlShutdown;
+
+ public enum NvmlPcieUtilCounter
+ {
+ TxBytes = 0,
+ RxBytes = 1
+ }
+
+ public enum NvmlReturn
+ {
+ ///
+ /// The operation was successful
+ ///
+ Success = 0,
+
+ ///
+ /// NvidiaML was not first initialized with nvmlInit()
+ ///
+ Uninitialized = 1,
+
+ ///
+ /// A supplied argument is invalid
+ ///
+ InvalidArgument = 2,
+
+ ///
+ /// The requested operation is not available on target device
+ ///
+ NotSupported = 3,
+
+ ///
+ /// The current user does not have permission for operation
+ ///
+ NoPermission = 4,
+
+ ///
+ /// A query to find an object was unsuccessful
+ ///
+ NotFound = 6,
+
+ ///
+ /// An input argument is not large enough
+ ///
+ InsufficientSize = 7,
+
+ ///
+ /// A device's external power cables are not properly attached
+ ///
+ InsufficientPower = 8,
+
+ ///
+ /// NVIDIA driver is not loaded
+ ///
+ DriverNotLoaded = 9,
+
+ ///
+ /// User provided timeout passed
+ ///
+ TimeOut = 10,
+
+ ///
+ /// NVIDIA Kernel detected an interrupt issue with a GPU
+ ///
+ IRQIssue = 11,
+
+ ///
+ /// NvidiaML Shared Library couldn't be found or loaded
+ ///
+ LibraryNotFound = 12,
+
+ ///
+ /// Local version of NvidiaML doesn't implement this function
+ ///
+ FunctionNotFound = 13,
+
+ ///
+ /// infoROM is corrupted
+ ///
+ CorruptedInfoRom = 14,
+
+ ///
+ /// The GPU has fallen off the bus or has otherwise become inaccessible
+ ///
+ GpuIsLost = 15,
+
+ ///
+ /// The GPU requires a reset before it can be used again
+ ///
+ ResetRequired = 16,
+
+ ///
+ /// The GPU control device has been blocked by the operating system/cgroups
+ ///
+ OperatingSystem = 17,
+
+ ///
+ /// RM detects a driver/library version mismatch
+ ///
+ LibRmVersionMismatch = 18,
+
+ ///
+ /// An operation cannot be performed because the GPU is currently in use
+ ///
+ InUse = 19,
+
+ ///
+ /// An public driver error occurred
+ ///
+ Unknown = 999
+ }
+
+ public static bool IsAvailable { get; private set; }
+
+ public static bool Initialize()
+ {
+ lock (_syncRoot)
+ {
+ if (IsAvailable)
+ {
+ return true;
+ }
+
+ // Attempt to load the Nvidia Management Library from the
+ // windows standard search order for applications. This will
+ // help installations that either have the library in
+ // %windir%/system32 or provide their own library
+ _windowsDll = Kernel32.LoadLibrary(WindowsDllName);
+
+ // If there is no dll in the path, then attempt to load it
+ // from program files
+ if (_windowsDll == IntPtr.Zero)
+ {
+ string programFilesDirectory = Environment.ExpandEnvironmentVariables("%ProgramW6432%");
+ string dllPath = Path.Combine(programFilesDirectory, @"NVIDIA Corporation\NVSMI", WindowsDllName);
+
+ _windowsDll = Kernel32.LoadLibrary(dllPath);
+ }
+
+ IsAvailable = (_windowsDll != IntPtr.Zero) && InitialiseDelegates() && (_windowsNvmlInit() == NvmlReturn.Success);
+
+ return IsAvailable;
+ }
+ }
+
+ private static bool InitialiseDelegates()
+ {
+ IntPtr nvmlInit = Kernel32.GetProcAddress(_windowsDll, "nvmlInit_v2");
+
+ if (nvmlInit != IntPtr.Zero)
+ {
+ _windowsNvmlInit = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlInit, typeof(WindowsNvmlDelegate));
+ }
+ else
+ {
+ nvmlInit = Kernel32.GetProcAddress(_windowsDll, "nvmlInit");
+ if (nvmlInit != IntPtr.Zero)
+ _windowsNvmlInit = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlInit, typeof(WindowsNvmlDelegate));
+ else
+ return false;
+ }
+
+ IntPtr nvmlShutdown = Kernel32.GetProcAddress(_windowsDll, "nvmlShutdown");
+ if (nvmlShutdown != IntPtr.Zero)
+ _windowsNvmlShutdown = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlShutdown, typeof(WindowsNvmlDelegate));
+ else
+ return false;
+
+ IntPtr nvmlGetHandle = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetHandleByIndex_v2");
+ if (nvmlGetHandle != IntPtr.Zero)
+ _windowsNvmlDeviceGetHandleByIndex = (WindowsNvmlGetHandleDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandle, typeof(WindowsNvmlGetHandleDelegate));
+ else
+ {
+ nvmlGetHandle = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetHandleByIndex");
+ if (nvmlGetHandle != IntPtr.Zero)
+ _windowsNvmlDeviceGetHandleByIndex = (WindowsNvmlGetHandleDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandle, typeof(WindowsNvmlGetHandleDelegate));
+ else
+ return false;
+ }
+
+ IntPtr nvmlGetPowerUsage = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetPowerUsage");
+ if (nvmlGetPowerUsage != IntPtr.Zero)
+ _windowsNvmlDeviceGetPowerUsage = (WindowsNvmlGetPowerUsageDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetPowerUsage, typeof(WindowsNvmlGetPowerUsageDelegate));
+ else
+ return false;
+
+ IntPtr nvmlGetPowerManagementDefaultLimit = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetPowerManagementDefaultLimit");
+ if (nvmlGetPowerManagementDefaultLimit != IntPtr.Zero)
+ _windowsNvmlDevicePowerManagementDefaultLimit = (WindowsNvmlGetPowerManagementDefaultLimitDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetPowerManagementDefaultLimit, typeof(WindowsNvmlGetPowerManagementDefaultLimitDelegate));
+ else
+ return false;
+
+ IntPtr nvmlGetPcieThroughput = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetPcieThroughput");
+ if (nvmlGetPcieThroughput != IntPtr.Zero)
+ _windowsNvmlDeviceGetPcieThroughputDelegate = (WindowsNvmlDeviceGetPcieThroughputDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetPcieThroughput, typeof(WindowsNvmlDeviceGetPcieThroughputDelegate));
+ else
+ return false;
+
+ IntPtr nvmlGetHandlePciBus = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetHandleByPciBusId_v2");
+ if (nvmlGetHandlePciBus != IntPtr.Zero)
+ _windowsNvmlDeviceGetHandleByPciBusId = (WindowsNvmlGetHandleByPciBusIdDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandlePciBus, typeof(WindowsNvmlGetHandleByPciBusIdDelegate));
+ else
+ return false;
+
+ IntPtr nvmlDeviceGetPciInfo = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetPciInfo_v2");
+ if (nvmlDeviceGetPciInfo != IntPtr.Zero)
+ _windowsNvmlDeviceGetPciInfo = (WindowsNvmlDeviceGetPciInfo)Marshal.GetDelegateForFunctionPointer(nvmlDeviceGetPciInfo, typeof(WindowsNvmlDeviceGetPciInfo));
+ else
+ return false;
+
+ return true;
+ }
+
+ public static void Close()
+ {
+ lock (_syncRoot)
+ {
+ if (IsAvailable)
+ {
+ if (_windowsDll != IntPtr.Zero)
+ {
+ _windowsNvmlShutdown();
+ Kernel32.FreeLibrary(_windowsDll);
+ }
+
+ IsAvailable = false;
+ }
+ }
+ }
+
+ public static NvmlDevice? NvmlDeviceGetHandleByIndex(int index)
+ {
+ if (IsAvailable)
+ {
+ NvmlDevice nvmlDevice;
+ if (_windowsNvmlDeviceGetHandleByIndex(index, out nvmlDevice) == NvmlReturn.Success)
+ return nvmlDevice;
+ }
+
+ return null;
+ }
+
+ public static NvmlDevice? NvmlDeviceGetHandleByPciBusId(string pciBusId)
+ {
+ if (IsAvailable)
+ {
+ NvmlDevice nvmlDevice;
+ if (_windowsNvmlDeviceGetHandleByPciBusId(pciBusId, out nvmlDevice) == NvmlReturn.Success)
+ return nvmlDevice;
+ }
+
+ return null;
+ }
+
+ public static int? NvmlDeviceGetPowerUsage(NvmlDevice nvmlDevice)
+ {
+ if (IsAvailable)
+ {
+ int powerUsage;
+ if (_windowsNvmlDeviceGetPowerUsage(nvmlDevice, out powerUsage) == NvmlReturn.Success)
+ return powerUsage;
+ }
+
+ return null;
+ }
+
+ public static int? NvmlDeviceGetPowerManagementDefaultLimit(NvmlDevice nvmlDevice)
+ {
+ if (IsAvailable)
+ {
+ int defaultLimit;
+ if (_windowsNvmlDevicePowerManagementDefaultLimit(nvmlDevice, out defaultLimit) == NvmlReturn.Success)
+ return defaultLimit;
+ }
+
+ return null;
+ }
+
+ public static uint? NvmlDeviceGetPcieThroughput(NvmlDevice nvmlDevice, NvmlPcieUtilCounter counter)
+ {
+ if (IsAvailable)
+ {
+ uint pcieThroughput;
+ if (_windowsNvmlDeviceGetPcieThroughputDelegate(nvmlDevice, counter, out pcieThroughput) == NvmlReturn.Success)
+ return pcieThroughput;
+ }
+
+ return null;
+ }
+
+ public static NvmlPciInfo? NvmlDeviceGetPciInfo(NvmlDevice nvmlDevice)
+ {
+ if (IsAvailable)
+ {
+ var pci = new NvmlPciInfo();
+
+ if (_windowsNvmlDeviceGetPciInfo(nvmlDevice, ref pci) == NvmlReturn.Success)
+ return pci;
+ }
+
+ return null;
+ }
+
+ [DllImport(LinuxDllName, EntryPoint = "nvmlInit_v2", ExactSpelling = true)]
+ private static extern NvmlReturn nvmlInit();
+
+ [DllImport(LinuxDllName, EntryPoint = "nvmlInit", ExactSpelling = true)]
+ private static extern NvmlReturn nvmlInitLegacy();
+
+ [DllImport(LinuxDllName, EntryPoint = "nvmlShutdown", ExactSpelling = true)]
+ private static extern NvmlReturn nvmlShutdown();
+
+ [DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByIndex_v2", ExactSpelling = true)]
+ private static extern NvmlReturn nvmlDeviceGetHandleByIndex(int index, out NvmlDevice device);
+
+ [DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByPciBusId_v2", ExactSpelling = true)]
+ private static extern NvmlReturn nvmlDeviceGetHandleByPciBusId([MarshalAs(UnmanagedType.LPStr)] string pciBusId, out NvmlDevice device);
+
+ [DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByIndex", ExactSpelling = true)]
+ private static extern NvmlReturn nvmlDeviceGetHandleByIndexLegacy(int index, out NvmlDevice device);
+
+ [DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPowerUsage", ExactSpelling = true)]
+ private static extern NvmlReturn nvmlDeviceGetPowerUsage(NvmlDevice device, out int power);
+
+ [DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPcieThroughput", ExactSpelling = true)]
+ private static extern NvmlReturn nvmlDeviceGetPcieThroughput(NvmlDevice device, NvmlPcieUtilCounter counter, out uint value);
+
+ [DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPciInfo_v2")]
+ private static extern NvmlReturn nvmlDeviceGetPciInfo(NvmlDevice device, ref NvmlPciInfo pci);
+
+ private delegate NvmlReturn WindowsNvmlDelegate();
+
+ private delegate NvmlReturn WindowsNvmlGetHandleDelegate(int index, out NvmlDevice device);
+
+ private delegate NvmlReturn WindowsNvmlGetHandleByPciBusIdDelegate([MarshalAs(UnmanagedType.LPStr)] string pciBusId, out NvmlDevice device);
+
+ private delegate NvmlReturn WindowsNvmlGetPowerUsageDelegate(NvmlDevice device, out int power);
+
+ private delegate NvmlReturn WindowsNvmlGetPowerManagementDefaultLimitDelegate(NvmlDevice device, out int defaultLimit);
+
+ private delegate NvmlReturn WindowsNvmlDeviceGetPcieThroughputDelegate(NvmlDevice device, NvmlPcieUtilCounter counter, out uint value);
+
+ private delegate NvmlReturn WindowsNvmlDeviceGetPciInfo(NvmlDevice device, ref NvmlPciInfo pci);
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct NvmlDevice
+ {
+ public IntPtr Handle;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct NvmlPciInfo
+ {
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
+ public string busId;
+
+ public uint domain;
+
+ public uint bus;
+
+ public uint device;
+
+ public ushort pciVendorId;
+
+ public ushort pciDeviceId;
+
+ public uint pciSubSystemId;
+
+ public uint reserved0;
+ public uint reserved1;
+ public uint reserved2;
+ public uint reserved3;
+ }
+}
\ No newline at end of file
diff --git a/ColorControl/Svc/ColorControlBackgroundService.cs b/ColorControl/Svc/ColorControlBackgroundService.cs
index 095b5f1..24c0734 100644
--- a/ColorControl/Svc/ColorControlBackgroundService.cs
+++ b/ColorControl/Svc/ColorControlBackgroundService.cs
@@ -110,6 +110,7 @@ namespace ColorControl.Svc
SvcMessageType.RestartAfterUpdate => HandleRestartAfterUpdateMessage(),
SvcMessageType.ApplyNvidiaDriverSettings => HandleNvDriverSettingsMessage(JsonConvert.DeserializeObject(json)),
SvcMessageType.RestoreNvidiaDriverSetting => HandleNvRestoreDriverSettingsMessage(JsonConvert.DeserializeObject(json)),
+ SvcMessageType.ApplyNvidiaOverclocking => HandleNvOverclockingMessage(JsonConvert.DeserializeObject(json)),
_ => SvcResultMessage.FromResult(false, "Unexpected message type")
};
@@ -197,6 +198,13 @@ namespace ColorControl.Svc
return SvcResultMessage.FromResult(result);
}
+ private SvcResultMessage HandleNvOverclockingMessage(SvcNvOverclockingMessage message)
+ {
+ NvService.CheckServiceInstance().ApplyOverclocking(message.OverclockingSettings);
+
+ return SvcResultMessage.FromResult(true);
+ }
+
private async Task WakeDevicesAsync()
{
if (!UserSessionInfo.UserLocalSession)
diff --git a/ColorControl/Svc/SvcMessage.cs b/ColorControl/Svc/SvcMessage.cs
index fcb2504..7a58343 100644
--- a/ColorControl/Svc/SvcMessage.cs
+++ b/ColorControl/Svc/SvcMessage.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using ColorControl.Services.NVIDIA;
+using System.Collections.Generic;
namespace ColorControl.Svc
{
@@ -12,6 +13,7 @@ namespace ColorControl.Svc
RestartAfterUpdate = 21,
ApplyNvidiaDriverSettings = 101,
RestoreNvidiaDriverSetting = 102,
+ ApplyNvidiaOverclocking = 110,
}
public class SvcMessage
@@ -43,4 +45,14 @@ namespace ColorControl.Svc
public List> DriverSettings { get; set; }
}
+
+ public class SvcNvOverclockingMessage : SvcMessage
+ {
+ public SvcNvOverclockingMessage(SvcMessageType messageType = SvcMessageType.ApplyNvidiaOverclocking)
+ {
+ MessageType = messageType;
+ }
+
+ public List OverclockingSettings { get; set; }
+ }
}
diff --git a/NvAPIWrapper/Display/ColorData.cs b/NvAPIWrapper/Display/ColorData.cs
new file mode 100644
index 0000000..c856d81
--- /dev/null
+++ b/NvAPIWrapper/Display/ColorData.cs
@@ -0,0 +1,200 @@
+using System;
+using NvAPIWrapper.Native.Display;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ public class ColorData : IColorData, IEquatable
+ {
+ ///
+ /// Creates an instance of to modify the color data
+ ///
+ /// The color data color format.
+ /// The color data color space.
+ /// The color data dynamic range.
+ /// The color data color depth.
+ /// The color data selection policy.
+ /// The color data desktop color depth.
+ public ColorData(
+ ColorDataFormat colorFormat = ColorDataFormat.Auto,
+ ColorDataColorimetry colorimetry = ColorDataColorimetry.Auto,
+ ColorDataDynamicRange? dynamicRange = null,
+ ColorDataDepth? colorDepth = null,
+ ColorDataSelectionPolicy? colorSelectionPolicy = null,
+ ColorDataDesktopDepth? desktopColorDepth = null
+ )
+ {
+ ColorFormat = colorFormat;
+ Colorimetry = colorimetry;
+ DynamicRange = dynamicRange;
+ ColorDepth = colorDepth;
+ SelectionPolicy = colorSelectionPolicy;
+ DesktopColorDepth = desktopColorDepth;
+ }
+
+ internal ColorData(IColorData colorData)
+ {
+ ColorDepth = colorData.ColorDepth;
+ DynamicRange = colorData.DynamicRange;
+ ColorFormat = colorData.ColorFormat;
+ Colorimetry = colorData.Colorimetry;
+ SelectionPolicy = colorData.SelectionPolicy;
+ DesktopColorDepth = colorData.DesktopColorDepth;
+ }
+
+ ///
+ public ColorDataDepth? ColorDepth { get; }
+
+ ///
+ public ColorDataFormat ColorFormat { get; }
+
+ ///
+ public ColorDataColorimetry Colorimetry { get; }
+
+ ///
+ public ColorDataDesktopDepth? DesktopColorDepth { get; }
+
+ ///
+ public ColorDataDynamicRange? DynamicRange { get; }
+
+ ///
+ public ColorDataSelectionPolicy? SelectionPolicy { get; }
+
+ ///
+ public bool Equals(ColorData other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return ColorDepth == other.ColorDepth &&
+ ColorFormat == other.ColorFormat &&
+ Colorimetry == other.Colorimetry &&
+ DesktopColorDepth == other.DesktopColorDepth &&
+ DynamicRange == other.DynamicRange &&
+ SelectionPolicy == other.SelectionPolicy;
+ }
+
+ ///
+ /// Compares two instances of for equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// true if two instances are equal; otherwise false.
+ public static bool operator ==(ColorData left, ColorData right)
+ {
+ return left?.Equals(right) == true;
+ }
+
+ ///
+ /// Compares two instances of for inequality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// true if two instances are not equal; otherwise false.
+ public static bool operator !=(ColorData left, ColorData right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ColorData) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = ColorDepth.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) ColorFormat;
+ hashCode = (hashCode * 397) ^ (int) Colorimetry;
+ hashCode = (hashCode * 397) ^ DesktopColorDepth.GetHashCode();
+ hashCode = (hashCode * 397) ^ DynamicRange.GetHashCode();
+ hashCode = (hashCode * 397) ^ SelectionPolicy.GetHashCode();
+
+ return hashCode;
+ }
+ }
+
+ internal ColorDataV1 AsColorDataV1(ColorDataCommand command)
+ {
+ return new ColorDataV1(
+ command,
+ ColorFormat,
+ Colorimetry
+ );
+ }
+
+ internal ColorDataV2 AsColorDataV2(ColorDataCommand command)
+ {
+ return new ColorDataV2(
+ command,
+ ColorFormat,
+ Colorimetry,
+ DynamicRange ?? ColorDataDynamicRange.Auto
+ );
+ }
+
+ internal ColorDataV3 AsColorDataV3(ColorDataCommand command)
+ {
+ return new ColorDataV3(
+ command,
+ ColorFormat,
+ Colorimetry,
+ DynamicRange ?? ColorDataDynamicRange.Auto,
+ ColorDepth ?? ColorDataDepth.Default
+ );
+ }
+
+ internal ColorDataV4 AsColorDataV4(ColorDataCommand command)
+ {
+ return new ColorDataV4(
+ command,
+ ColorFormat,
+ Colorimetry,
+ DynamicRange ?? ColorDataDynamicRange.Auto,
+ ColorDepth ?? ColorDataDepth.Default,
+ SelectionPolicy ?? ColorDataSelectionPolicy.Default
+ );
+ }
+
+ internal ColorDataV5 AsColorDataV5(ColorDataCommand command)
+ {
+ return new ColorDataV5(
+ command,
+ ColorFormat,
+ Colorimetry,
+ DynamicRange ?? ColorDataDynamicRange.Auto,
+ ColorDepth ?? ColorDataDepth.Default,
+ SelectionPolicy ?? ColorDataSelectionPolicy.Default,
+ DesktopColorDepth ?? ColorDataDesktopDepth.Default
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/CustomResolution.cs b/NvAPIWrapper/Display/CustomResolution.cs
new file mode 100644
index 0000000..8dac9a4
--- /dev/null
+++ b/NvAPIWrapper/Display/CustomResolution.cs
@@ -0,0 +1,245 @@
+using System;
+using NvAPIWrapper.Native.Display;
+using NvAPIWrapper.Native.Display.Structures;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// Hold information about a custom display resolution
+ ///
+ public class CustomResolution : IEquatable
+ {
+ ///
+ /// Creates an instance of .
+ ///
+ /// The screen width.
+ /// The screen height.
+ /// The color format.
+ /// The resolution timing.
+ /// The horizontal scaling ratio.
+ /// The vertical scaling ratio.
+ public CustomResolution(
+ uint width,
+ uint height,
+ ColorFormat colorFormat,
+ Timing timing,
+ float xRatio = 1,
+ float yRatio = 1
+ )
+ {
+ if (xRatio <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(xRatio));
+ }
+
+ if (yRatio <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(yRatio));
+ }
+
+ Width = width;
+ Height = height;
+ ColorFormat = colorFormat;
+ XRatio = xRatio;
+ YRatio = yRatio;
+ Timing = timing;
+
+ switch (ColorFormat)
+ {
+ case ColorFormat.P8:
+ ColorDepth = 8;
+
+ break;
+ case ColorFormat.R5G6B5:
+ ColorDepth = 16;
+
+ break;
+ case ColorFormat.A8R8G8B8:
+ ColorDepth = 24;
+
+ break;
+ case ColorFormat.A16B16G16R16F:
+ ColorDepth = 32;
+
+ break;
+ default:
+ throw new ArgumentException("Color format is invalid.", nameof(colorFormat));
+ }
+ }
+
+ ///
+ /// Creates an instance of .
+ ///
+ /// The screen width.
+ /// The screen height.
+ /// The color depth.
+ /// The resolution timing.
+ /// The horizontal scaling ratio.
+ /// The vertical scaling ratio.
+ public CustomResolution(
+ uint width,
+ uint height,
+ uint colorDepth,
+ Timing timing,
+ float xRatio = 1,
+ float yRatio = 1)
+ {
+ if (xRatio <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(xRatio));
+ }
+
+ if (yRatio <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(yRatio));
+ }
+
+ if (colorDepth != 0 && colorDepth != 8 && colorDepth != 16 && colorDepth != 24 && colorDepth != 32)
+ {
+ throw new ArgumentOutOfRangeException(nameof(colorDepth));
+ }
+
+ Width = width;
+ Height = height;
+ ColorDepth = colorDepth;
+ ColorFormat = ColorFormat.Unknown;
+ XRatio = xRatio;
+ YRatio = yRatio;
+ Timing = timing;
+ }
+
+ internal CustomResolution(CustomDisplay customDisplay)
+ {
+ Width = customDisplay.Width;
+ Height = customDisplay.Height;
+ ColorDepth = customDisplay.Depth;
+ ColorFormat = customDisplay.ColorFormat;
+ Timing = customDisplay.Timing;
+ XRatio = customDisplay.XRatio;
+ YRatio = customDisplay.YRatio;
+ }
+
+ ///
+ /// Gets the source surface color depth. "0" means all 8/16/32bpp.
+ ///
+ public uint ColorDepth { get; }
+
+ ///
+ /// Gets the color format (optional)
+ ///
+ public ColorFormat ColorFormat { get; }
+
+ ///
+ /// Gets the source surface (source mode) height.
+ ///
+ public uint Height { get; }
+
+ ///
+ /// Gets the timing used to program TMDS/DAC/LVDS/HDMI/TVEncoder, etc.
+ ///
+ public Timing Timing { get; }
+
+ ///
+ /// Gets the source surface (source mode) width.
+ ///
+ public uint Width { get; }
+
+ ///
+ /// Gets the horizontal scaling ratio.
+ ///
+ public float XRatio { get; }
+
+ ///
+ /// Gets the vertical scaling ratio.
+ ///
+ public float YRatio { get; }
+
+ ///
+ public bool Equals(CustomResolution other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return Width == other.Width &&
+ Height == other.Height &&
+ ColorDepth == other.ColorDepth &&
+ Timing.Equals(other.Timing) &&
+ ColorFormat == other.ColorFormat &&
+ XRatio.Equals(other.XRatio) &&
+ YRatio.Equals(other.YRatio);
+ }
+
+ ///
+ /// Compares two instance of for equality.
+ ///
+ /// An first instance of to compare.
+ /// An Second instance of to compare.
+ /// True if both instances are equal, otherwise false.
+ public static bool operator ==(CustomResolution left, CustomResolution right)
+ {
+ return Equals(left, right);
+ }
+
+ ///
+ /// Compares two instance of for inequality.
+ ///
+ /// An first instance of to compare.
+ /// An Second instance of to compare.
+ /// True if both instances are not equal, otherwise false.
+ public static bool operator !=(CustomResolution left, CustomResolution right)
+ {
+ return !Equals(left, right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((CustomResolution) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = (int) Width;
+ hashCode = (hashCode * 397) ^ (int) Height;
+ hashCode = (hashCode * 397) ^ (int) ColorDepth;
+ hashCode = (hashCode * 397) ^ Timing.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) ColorFormat;
+ hashCode = (hashCode * 397) ^ XRatio.GetHashCode();
+ hashCode = (hashCode * 397) ^ YRatio.GetHashCode();
+
+ return hashCode;
+ }
+ }
+
+ internal CustomDisplay AsCustomDisplay(bool hardwareModeSetOnly)
+ {
+ return new CustomDisplay(Width, Height, ColorDepth, ColorFormat, XRatio, YRatio, Timing,
+ hardwareModeSetOnly);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/DVCInformation.cs b/NvAPIWrapper/Display/DVCInformation.cs
new file mode 100644
index 0000000..c5a4da3
--- /dev/null
+++ b/NvAPIWrapper/Display/DVCInformation.cs
@@ -0,0 +1,325 @@
+using System;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// This class contains and provides a way to modify the Digital Vibrance Control information regarding the
+ /// saturation level of the display or the output
+ ///
+ public class DVCInformation : IDisplayDVCInfo
+ {
+ private readonly DisplayHandle _displayHandle = DisplayHandle.DefaultHandle;
+ private readonly OutputId _outputId = OutputId.Invalid;
+ private bool? _isLegacy;
+
+ ///
+ /// Creates a new instance of the class using a DisplayHandle
+ ///
+ /// The handle of the display.
+ public DVCInformation(DisplayHandle displayHandle)
+ {
+ _displayHandle = displayHandle;
+ }
+
+ ///
+ /// Creates a new instance of this class using a OutputId
+ ///
+ /// The output identification of a display or an output
+ public DVCInformation(OutputId outputId)
+ {
+ _outputId = outputId;
+ }
+
+ ///
+ /// Gets and sets the normalized saturation level in the [-1,1] inclusive range.
+ /// a -1 value corresponds to the minimum saturation level and maximum under-saturation and the
+ /// a 1 value corresponds to the maximum saturation level and maximum over-saturation.
+ /// The value of 0 indicates the default saturation level.
+ ///
+ public double NormalizedLevel
+ {
+ get
+ {
+ var info = GetInfo();
+
+ if (info == null)
+ {
+ return double.NaN;
+ }
+
+ var deviance = info.CurrentLevel - info.DefaultLevel;
+ var range = deviance >= 0
+ ? info.MaximumLevel - info.DefaultLevel
+ : info.DefaultLevel - info.MinimumLevel;
+
+ if (deviance == 0 || range == 0)
+ {
+ return 0;
+ }
+
+ return Math.Max(Math.Min((double) deviance / range, 1), -1);
+ }
+ set
+ {
+ if (double.IsNaN(value) || double.IsInfinity(value))
+ {
+ throw new ArgumentOutOfRangeException(nameof(value));
+ }
+
+ var info = GetInfo();
+
+ if (info == null)
+ {
+ return;
+ }
+
+ var range = value >= 0 ? info.MaximumLevel - info.DefaultLevel : info.DefaultLevel - info.MinimumLevel;
+ var level = Math.Max(Math.Min((int) (value * range) + info.DefaultLevel, info.MaximumLevel), info.MinimumLevel);
+
+ if (level == info.CurrentLevel)
+ {
+ return;
+ }
+
+ SetLevel(level);
+ }
+ }
+
+ ///
+ /// Gets and sets the current saturation level
+ ///
+ public int CurrentLevel
+ {
+ get => GetInfo()?.CurrentLevel ?? 0;
+ set
+ {
+ var info = GetInfo();
+
+ if (info == null)
+ {
+ return;
+ }
+
+ value = Math.Max(Math.Min(value, info.MaximumLevel), info.MinimumLevel);
+
+ if (info.CurrentLevel == value)
+ {
+ return;
+ }
+
+ SetLevel(value);
+ }
+ }
+
+ ///
+ public int DefaultLevel
+ {
+ get => GetInfo()?.DefaultLevel ?? 0;
+ }
+
+ ///
+ public int MaximumLevel
+ {
+ get => GetInfo()?.MaximumLevel ?? 0;
+ }
+
+ ///
+ public int MinimumLevel
+ {
+ get => GetInfo()?.MinimumLevel ?? 0;
+ }
+
+ ///
+ public override string ToString()
+ {
+ return
+ $"{CurrentLevel:D} @ [{MinimumLevel:D} <= {DefaultLevel:D} <= {MaximumLevel:D}] = {NormalizedLevel:F2}";
+ }
+
+ private IDisplayDVCInfo GetInfo()
+ {
+ if (_isLegacy == true)
+ {
+ return GetLegacyInfo();
+ }
+
+ if (_isLegacy == false)
+ {
+ return GetModernInfo();
+ }
+
+ var info = GetModernInfo() ?? GetLegacyInfo();
+
+ if (info == null)
+ {
+ // exception occured on both, force a mode
+ _isLegacy = false;
+
+ return GetInfo();
+ }
+
+ return info;
+ }
+
+ private IDisplayDVCInfo GetLegacyInfo()
+ {
+ try
+ {
+ var info = _outputId == OutputId.Invalid
+ ? DisplayApi.GetDVCInfo(_displayHandle)
+ : DisplayApi.GetDVCInfo(_outputId);
+
+ if (info.MaximumLevel == 0 && info.MinimumLevel == 0 && info.CurrentLevel == 0)
+ {
+ return null;
+ }
+
+ if (!_isLegacy.HasValue)
+ {
+ _isLegacy = true;
+ }
+
+
+ return info;
+ }
+ catch (Exception)
+ {
+ if (_isLegacy == true)
+ {
+ throw;
+ }
+
+ // ignore
+ }
+
+ return null;
+ }
+
+ private IDisplayDVCInfo GetModernInfo()
+ {
+ try
+ {
+ var info = _outputId == OutputId.Invalid
+ ? DisplayApi.GetDVCInfoEx(_displayHandle)
+ : DisplayApi.GetDVCInfoEx(_outputId);
+
+ if (info.MaximumLevel == 0 && info.MinimumLevel == 0 && info.CurrentLevel == 0)
+ {
+ return null;
+ }
+
+ if (!_isLegacy.HasValue)
+ {
+ _isLegacy = false;
+ }
+
+ return info;
+ }
+ catch (Exception)
+ {
+ if (_isLegacy == false)
+ {
+ throw;
+ }
+
+ // ignore
+ }
+
+ return null;
+ }
+
+ private bool SetLegacyLevel(int level)
+ {
+ try
+ {
+ if (_outputId == OutputId.Invalid)
+ {
+ DisplayApi.SetDVCLevel(_displayHandle, level);
+ }
+ else
+ {
+ DisplayApi.SetDVCLevel(_outputId, level);
+ }
+
+ if (!_isLegacy.HasValue)
+ {
+ _isLegacy = true;
+ }
+
+ return true;
+ }
+ catch (Exception)
+ {
+ if (_isLegacy == true)
+ {
+ throw;
+ }
+
+ // ignore
+ }
+
+ return false;
+ }
+
+ private void SetLevel(int level)
+ {
+ if (_isLegacy == true)
+ {
+ SetLegacyLevel(level);
+ }
+ else if (_isLegacy == false)
+ {
+ SetModernLevel(level);
+ }
+ else
+ {
+ var success = SetModernLevel(level) || SetLegacyLevel(level);
+
+ if (!success)
+ {
+ // exception occured on both, force a mode
+ _isLegacy = false;
+
+ SetLevel(level);
+ }
+ }
+ }
+
+ private bool SetModernLevel(int level)
+ {
+ try
+ {
+ if (_outputId == OutputId.Invalid)
+ {
+ DisplayApi.SetDVCLevelEx(_displayHandle, level);
+ }
+ else
+ {
+ DisplayApi.SetDVCLevelEx(_outputId, level);
+ }
+
+ if (!_isLegacy.HasValue)
+ {
+ _isLegacy = false;
+ }
+
+ return true;
+ }
+ catch (Exception)
+ {
+ if (_isLegacy == false)
+ {
+ throw;
+ }
+
+ // ignore
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/Display.cs b/NvAPIWrapper/Display/Display.cs
new file mode 100644
index 0000000..4da92f7
--- /dev/null
+++ b/NvAPIWrapper/Display/Display.cs
@@ -0,0 +1,232 @@
+using System;
+using System.Linq;
+using NvAPIWrapper.GPU;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.Display;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.Exceptions;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// Represents an attached display
+ ///
+ public class Display : IEquatable
+ {
+ ///
+ /// Creates a new Display
+ ///
+ /// Handle of the display device
+ public Display(DisplayHandle handle)
+ {
+ Handle = handle;
+ }
+
+ ///
+ /// Creates a new Display
+ ///
+ /// Name of the display device
+ public Display(string displayName)
+ {
+ Handle = DisplayApi.GetAssociatedNvidiaDisplayHandle(displayName);
+ }
+
+ ///
+ /// Gets the corresponding Digital Vibrance Control information
+ ///
+ public DVCInformation DigitalVibranceControl
+ {
+ get => new DVCInformation(Handle);
+ }
+
+ ///
+ /// Gets corresponding DisplayDevice based on display name
+ ///
+ public DisplayDevice DisplayDevice
+ {
+ get => new DisplayDevice(Name);
+ }
+
+ ///
+ /// Gets display driver build title
+ ///
+ public string DriverBuildTitle
+ {
+ get => DisplayApi.GetDisplayDriverBuildTitle(Handle);
+ }
+
+ ///
+ /// Gets display handle
+ ///
+ public DisplayHandle Handle { get; }
+
+ ///
+ /// Gets the display HDMI support information
+ ///
+ public IHDMISupportInfo HDMISupportInfo
+ {
+ get
+ {
+ var outputId = OutputId.Invalid;
+ try
+ {
+ outputId = DisplayApi.GetAssociatedDisplayOutputId(Handle);
+ }
+ catch (NVIDIAApiException)
+ {
+ // ignore
+ }
+ return DisplayApi.GetHDMISupportInfo(Handle, outputId);
+ }
+ }
+
+ ///
+ /// Gets the corresponding HUE information
+ ///
+ public HUEInformation HUEControl
+ {
+ get => new HUEInformation(Handle);
+ }
+
+ ///
+ /// Gets the driving logical GPU
+ ///
+ public LogicalGPU LogicalGPU
+ {
+ get => new LogicalGPU(GPUApi.GetLogicalGPUFromDisplay(Handle));
+ }
+
+ ///
+ /// Gets display name
+ ///
+ public string Name
+ {
+ get => DisplayApi.GetAssociatedNvidiaDisplayName(Handle);
+ }
+
+ ///
+ /// Gets the connected GPU output
+ ///
+ public GPUOutput Output
+ {
+ get => new GPUOutput(DisplayApi.GetAssociatedDisplayOutputId(Handle), PhysicalGPUs.FirstOrDefault());
+ }
+
+ ///
+ /// Gets the list of all physical GPUs responsible for this display, with the first GPU returned as the one with the
+ /// attached active output.
+ ///
+ public PhysicalGPU[] PhysicalGPUs
+ {
+ get => GPUApi.GetPhysicalGPUsFromDisplay(Handle).Select(handle => new PhysicalGPU(handle)).ToArray();
+ }
+
+ ///
+ public bool Equals(Display other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return Handle.Equals(other.Handle);
+ }
+
+ ///
+ /// This function returns all NVIDIA displays
+ /// Note: Display handles can get invalidated on a modeset.
+ ///
+ /// An array of Display objects
+ public static Display[] GetDisplays()
+ {
+ return DisplayApi.EnumNvidiaDisplayHandle().Select(handle => new Display(handle)).ToArray();
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(Display left, Display right)
+ {
+ return right?.Equals(left) ?? ReferenceEquals(left, null);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(Display left, Display right)
+ {
+ return !(right == left);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((Display) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return Handle.GetHashCode();
+ }
+
+ ///
+ public override string ToString()
+ {
+ return Name;
+ }
+
+ ///
+ /// Gets all the supported NVIDIA display views (nView and Dualview modes) for this display.
+ ///
+ ///
+ public TargetViewMode[] GetSupportedViews()
+ {
+ return DisplayApi.GetSupportedViews(Handle);
+ }
+
+ ///
+ /// Overrides the refresh rate on this display.
+ /// The new refresh rate can be applied right away or deferred to be applied with the next OS
+ /// mode-set.
+ /// The override is good for only one mode-set (regardless whether it's deferred or immediate).
+ ///
+ /// The refresh rate to be applied.
+ ///
+ /// A boolean value indicating if the refresh rate override should be deferred to the next OS
+ /// mode-set.
+ ///
+ public void OverrideRefreshRate(float refreshRate, bool isDeferred = false)
+ {
+ DisplayApi.SetRefreshRateOverride(Handle, refreshRate, isDeferred);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/DisplayDevice.cs b/NvAPIWrapper/Display/DisplayDevice.cs
new file mode 100644
index 0000000..5d404bf
--- /dev/null
+++ b/NvAPIWrapper/Display/DisplayDevice.cs
@@ -0,0 +1,893 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NvAPIWrapper.GPU;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.Display;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.Exceptions;
+using NvAPIWrapper.Native.General;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+using NvAPIWrapper.Native.Interfaces.Display;
+using NvAPIWrapper.Native.Interfaces.GPU;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// Represents an NVIDIA display device
+ ///
+ public class DisplayDevice : IEquatable
+ {
+ ///
+ /// Creates a new DisplayDevice
+ ///
+ /// Display identification of the device
+ public DisplayDevice(uint displayId)
+ {
+ DisplayId = displayId;
+ var extraInformation = PhysicalGPU.GetDisplayDevices().FirstOrDefault(ids => ids.DisplayId == DisplayId);
+
+ if (extraInformation != null)
+ {
+ IsAvailable = true;
+ ScanOutInformation = new ScanOutInformation(this);
+ ConnectionType = extraInformation.ConnectionType;
+ IsDynamic = extraInformation.IsDynamic;
+ IsMultiStreamRootNode = extraInformation.IsMultiStreamRootNode;
+ IsActive = extraInformation.IsActive;
+ IsCluster = extraInformation.IsCluster;
+ IsOSVisible = extraInformation.IsOSVisible;
+ IsWFD = extraInformation.IsWFD;
+ IsConnected = extraInformation.IsConnected;
+ IsPhysicallyConnected = extraInformation.IsPhysicallyConnected;
+ }
+ }
+
+ ///
+ /// Creates a new DisplayDevice
+ ///
+ /// Display identification and attributes of the display device
+ public DisplayDevice(IDisplayIds displayIds)
+ {
+ IsAvailable = true;
+ DisplayId = displayIds.DisplayId;
+ ScanOutInformation = new ScanOutInformation(this);
+ ConnectionType = displayIds.ConnectionType;
+ IsDynamic = displayIds.IsDynamic;
+ IsMultiStreamRootNode = displayIds.IsMultiStreamRootNode;
+ IsActive = displayIds.IsActive;
+ IsCluster = displayIds.IsCluster;
+ IsOSVisible = displayIds.IsOSVisible;
+ IsWFD = displayIds.IsWFD;
+ IsConnected = displayIds.IsConnected;
+ IsPhysicallyConnected = displayIds.IsPhysicallyConnected;
+ }
+
+ ///
+ /// Creates a new DisplayDevice
+ ///
+ /// Display name of the display device
+ public DisplayDevice(string displayName) : this(DisplayApi.GetDisplayIdByDisplayName(displayName))
+ {
+ }
+
+ ///
+ /// Gets the display device connection type
+ ///
+ public MonitorConnectionType ConnectionType { get; }
+
+ ///
+ /// Gets the current display color data
+ ///
+ public ColorData CurrentColorData
+ {
+ get
+ {
+ var instances = new IColorData[]
+ {
+ new ColorDataV5(ColorDataCommand.Get),
+ new ColorDataV4(ColorDataCommand.Get),
+ new ColorDataV3(ColorDataCommand.Get),
+ new ColorDataV2(ColorDataCommand.Get),
+ new ColorDataV1(ColorDataCommand.Get)
+ };
+
+ var instance = DisplayApi.ColorControl(DisplayId, instances);
+
+ return new ColorData(instance);
+ }
+ }
+
+ ///
+ /// Gets the current display device timing
+ ///
+ public Timing CurrentTiming
+ {
+ get => DisplayApi.GetTiming(DisplayId, new TimingInput(TimingOverride.Current));
+ }
+
+ ///
+ /// Gets the default display color data
+ ///
+ public ColorData DefaultColorData
+ {
+ get
+ {
+ var instances = new IColorData[]
+ {
+ new ColorDataV5(ColorDataCommand.GetDefault),
+ new ColorDataV4(ColorDataCommand.GetDefault),
+ new ColorDataV3(ColorDataCommand.GetDefault),
+ new ColorDataV2(ColorDataCommand.GetDefault),
+ new ColorDataV1(ColorDataCommand.GetDefault)
+ };
+
+ var instance = DisplayApi.ColorControl(DisplayId, instances);
+
+ return new ColorData(instance);
+ }
+ }
+
+ ///
+ /// Gets the NVIDIA display identification
+ ///
+ public uint DisplayId { get; }
+
+ ///
+ /// Gets the monitor Display port capabilities
+ ///
+ public MonitorColorData[] DisplayPortColorCapabilities
+ {
+ get
+ {
+ if (ConnectionType != MonitorConnectionType.DisplayPort)
+ {
+ return null;
+ }
+
+ return DisplayApi.GetMonitorColorCapabilities(DisplayId);
+ }
+ }
+
+ ///
+ /// Gets the display driver EDID specified HDR capabilities
+ ///
+ public HDRCapabilitiesV1 DriverHDRCapabilities
+ {
+ get => DisplayApi.GetHDRCapabilities(DisplayId, true);
+ }
+
+ ///
+ /// Gets the display currently effective HDR capabilities
+ ///
+ public HDRCapabilitiesV1 EffectiveHDRCapabilities
+ {
+ get => DisplayApi.GetHDRCapabilities(DisplayId, false);
+ }
+
+ ///
+ /// Gets the HDMI audio info-frame current information
+ ///
+ public InfoFrameAudio? HDMIAudioFrameCurrentInformation
+ {
+ get
+ {
+ try
+ {
+ var infoFrame = new InfoFrameData(InfoFrameCommand.Get, InfoFrameDataType.AudioInformation);
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+
+ return infoFrame.AudioInformation;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status == Status.NotSupported)
+ {
+ return null;
+ }
+
+ throw;
+ }
+ }
+ }
+
+
+ ///
+ /// Gets the HDMI audio info-frame default information
+ ///
+ public InfoFrameAudio? HDMIAudioFrameDefaultInformation
+ {
+ get
+ {
+ try
+ {
+ var infoFrame = new InfoFrameData(InfoFrameCommand.GetDefault, InfoFrameDataType.AudioInformation);
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+
+ return infoFrame.AudioInformation;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status == Status.NotSupported)
+ {
+ return null;
+ }
+
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Gets the HDMI audio info-frame override information
+ ///
+ public InfoFrameAudio? HDMIAudioFrameOverrideInformation
+ {
+ get
+ {
+ try
+ {
+ var infoFrame = new InfoFrameData(InfoFrameCommand.GetOverride, InfoFrameDataType.AudioInformation);
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+
+ return infoFrame.AudioInformation;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status == Status.NotSupported)
+ {
+ return null;
+ }
+
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Gets the HDMI audio info-frame property information
+ ///
+ public InfoFrameProperty? HDMIAudioFramePropertyInformation
+ {
+ get
+ {
+ try
+ {
+ var infoFrame = new InfoFrameData(InfoFrameCommand.GetProperty, InfoFrameDataType.AudioInformation);
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+
+ return infoFrame.PropertyInformation;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status == Status.NotSupported)
+ {
+ return null;
+ }
+
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Gets the device HDMI support information
+ ///
+ public IHDMISupportInfo HDMISupportInfo
+ {
+ get => DisplayApi.GetHDMISupportInfo(DisplayId);
+ }
+
+
+ ///
+ /// Gets the HDMI auxiliary video info-frame current information
+ ///
+ public InfoFrameVideo? HDMIVideoFrameCurrentInformation
+ {
+ get
+ {
+ try
+ {
+ var infoFrame =
+ new InfoFrameData(InfoFrameCommand.Get, InfoFrameDataType.AuxiliaryVideoInformation);
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+
+ return infoFrame.AuxiliaryVideoInformation;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status == Status.NotSupported)
+ {
+ return null;
+ }
+
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Gets the HDMI auxiliary video info-frame default information
+ ///
+ public InfoFrameVideo? HDMIVideoFrameDefaultInformation
+ {
+ get
+ {
+ try
+ {
+ var infoFrame = new InfoFrameData(InfoFrameCommand.GetDefault,
+ InfoFrameDataType.AuxiliaryVideoInformation);
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+
+ return infoFrame.AuxiliaryVideoInformation;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status == Status.NotSupported)
+ {
+ return null;
+ }
+
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Gets the HDMI auxiliary video info-frame override information
+ ///
+ public InfoFrameVideo? HDMIVideoFrameOverrideInformation
+ {
+ get
+ {
+ try
+ {
+ var infoFrame = new InfoFrameData(InfoFrameCommand.GetOverride,
+ InfoFrameDataType.AuxiliaryVideoInformation);
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+
+ return infoFrame.AuxiliaryVideoInformation;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status == Status.NotSupported)
+ {
+ return null;
+ }
+
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Gets the HDMI auxiliary video info-frame property information
+ ///
+ public InfoFrameProperty? HDMIVideoFramePropertyInformation
+ {
+ get
+ {
+ try
+ {
+ var infoFrame = new InfoFrameData(InfoFrameCommand.GetProperty,
+ InfoFrameDataType.AuxiliaryVideoInformation);
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+
+ return infoFrame.PropertyInformation;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status == Status.NotSupported)
+ {
+ return null;
+ }
+
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Gets the HDR color data, or null if the HDR is disabled or unavailable
+ ///
+ public HDRColorData HDRColorData
+ {
+ get
+ {
+ try
+ {
+ var instances = new IHDRColorData[]
+ {
+ new HDRColorDataV2(ColorDataHDRCommand.Get),
+ new HDRColorDataV1(ColorDataHDRCommand.Get)
+ };
+
+ var instance = DisplayApi.HDRColorControl(DisplayId, instances);
+
+ if (instance.HDRMode == ColorDataHDRMode.Off)
+ {
+ return null;
+ }
+
+ return new HDRColorData(instance);
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status == Status.NotSupported)
+ {
+ return null;
+ }
+
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Indicates if the display is being actively driven
+ ///
+ public bool IsActive { get; }
+
+ ///
+ /// Indicates if the display device is currently available
+ ///
+ public bool IsAvailable { get; }
+
+ ///
+ /// Indicates if the display is the representative display
+ ///
+ public bool IsCluster { get; }
+
+ ///
+ /// Indicates if the display is connected
+ ///
+ public bool IsConnected { get; }
+
+ ///
+ /// Indicates if the display is part of MST topology and it's a dynamic
+ ///
+ public bool IsDynamic { get; }
+
+ ///
+ /// Indicates if the display identification belongs to a multi stream enabled connector (root node). Note that when
+ /// multi stream is enabled and a single multi stream capable monitor is connected to it, the monitor will share the
+ /// display id with the RootNode.
+ /// When there is more than one monitor connected in a multi stream topology, then the root node will have a separate
+ /// displayId.
+ ///
+ public bool IsMultiStreamRootNode { get; }
+
+ ///
+ /// Indicates if the display is reported to the OS
+ ///
+ public bool IsOSVisible { get; }
+
+ ///
+ /// Indicates if the display is a physically connected display; Valid only when IsConnected is true
+ ///
+ public bool IsPhysicallyConnected { get; }
+
+ ///
+ /// Indicates if the display is wireless
+ ///
+ public bool IsWFD { get; }
+
+ ///
+ /// Gets the connected GPU output
+ ///
+ public GPUOutput Output
+ {
+ get
+ {
+ PhysicalGPUHandle handle;
+ var outputId = GPUApi.GetGPUAndOutputIdFromDisplayId(DisplayId, out handle);
+
+ return new GPUOutput(outputId, new PhysicalGPU(handle));
+ }
+ }
+
+ ///
+ /// Gets the connected physical GPU
+ ///
+ public PhysicalGPU PhysicalGPU
+ {
+ get
+ {
+ try
+ {
+ var gpuHandle = GPUApi.GetPhysicalGPUFromDisplayId(DisplayId);
+
+ return new PhysicalGPU(gpuHandle);
+ }
+ catch
+ {
+ // ignored
+ }
+
+ return Output.PhysicalGPU;
+ }
+ }
+
+ ///
+ /// Gets information regarding the scan-out settings of this display device
+ ///
+ public ScanOutInformation ScanOutInformation { get; }
+
+ ///
+ /// Gets monitor capabilities from the Video Capability Data Block if available, otherwise null
+ ///
+ public MonitorVCDBCapabilities? VCDBMonitorCapabilities
+ {
+ get => DisplayApi.GetMonitorCapabilities(DisplayId, MonitorCapabilitiesType.VCDB)?.VCDBCapabilities;
+ }
+
+ ///
+ /// Gets monitor capabilities from the Vendor Specific Data Block if available, otherwise null
+ ///
+ public MonitorVSDBCapabilities? VSDBMonitorCapabilities
+ {
+ get => DisplayApi.GetMonitorCapabilities(DisplayId, MonitorCapabilitiesType.VSDB)?.VSDBCapabilities;
+ }
+
+ ///
+ public bool Equals(DisplayDevice other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return DisplayId == other.DisplayId;
+ }
+
+ ///
+ /// Deletes a custom resolution.
+ ///
+ /// The custom resolution to delete.
+ /// A list of display ids to remove the custom resolution from.
+ public static void DeleteCustomResolution(CustomResolution customResolution, uint[] displayIds)
+ {
+ var customDisplay = customResolution.AsCustomDisplay(false);
+ DisplayApi.DeleteCustomDisplay(displayIds, customDisplay);
+ }
+
+ ///
+ /// Returns an instance of representing the primary GDI display device.
+ ///
+ /// An instance of .
+ public static DisplayDevice GetGDIPrimaryDisplayDevice()
+ {
+ var displayId = DisplayApi.GetGDIPrimaryDisplayId();
+
+ if (displayId == 0)
+ {
+ return null;
+ }
+
+ return new DisplayDevice(displayId);
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(DisplayDevice left, DisplayDevice right)
+ {
+ return right?.Equals(left) ?? ReferenceEquals(left, null);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(DisplayDevice left, DisplayDevice right)
+ {
+ return !(right == left);
+ }
+
+ ///
+ /// Reverts the custom resolution currently on trial.
+ ///
+ /// A list of display ids to revert the custom resolution from.
+ public static void RevertCustomResolution(uint[] displayIds)
+ {
+ DisplayApi.RevertCustomDisplayTrial(displayIds);
+ }
+
+ ///
+ /// Saves the custom resolution currently on trial.
+ ///
+ /// A list of display ids to save the custom resolution for.
+ ///
+ /// If set, the saved custom display will only be applied on the monitor with the same
+ /// outputId.
+ ///
+ ///
+ /// If set, the saved custom display will only be applied on the monitor with the same EDID
+ /// ID or the same TV connector in case of analog TV.
+ ///
+ public static void SaveCustomResolution(uint[] displayIds, bool isThisOutputIdOnly, bool isThisMonitorOnly)
+ {
+ DisplayApi.SaveCustomDisplay(displayIds, isThisOutputIdOnly, isThisMonitorOnly);
+ }
+
+ ///
+ /// Applies a custom resolution into trial
+ ///
+ /// The custom resolution to apply.
+ /// A list of display ids to apply the custom resolution on.
+ ///
+ /// A boolean value indicating that a hardware mode-set without OS update should be
+ /// performed.
+ ///
+ public static void TrialCustomResolution(
+ CustomResolution customResolution,
+ uint[] displayIds,
+ bool hardwareModeSetOnly = true)
+ {
+ var customDisplay = customResolution.AsCustomDisplay(hardwareModeSetOnly);
+ DisplayApi.TryCustomDisplay(displayIds.ToDictionary(u => u, u => customDisplay));
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((DisplayDevice) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return (int) DisplayId;
+ }
+
+
+ ///
+ public override string ToString()
+ {
+ return $"Display #{DisplayId}";
+ }
+
+ ///
+ /// Calculates a valid timing based on the argument passed
+ ///
+ /// The preferred width.
+ /// The preferred height.
+ /// The preferred refresh rate.
+ /// The boolean value indicating if the preferred resolution is an interlaced resolution.
+ /// Returns a valid instance of .
+ public Timing CalculateTiming(uint width, uint height, float refreshRate, bool isInterlaced)
+ {
+ return DisplayApi.GetTiming(
+ DisplayId,
+ new TimingInput(width, height, refreshRate, TimingOverride.Auto, isInterlaced)
+ );
+ }
+
+ ///
+ /// Deletes a custom resolution.
+ ///
+ /// The custom resolution to delete.
+ public void DeleteCustomResolution(CustomResolution customResolution)
+ {
+ DeleteCustomResolution(customResolution, new[] {DisplayId});
+ }
+
+ ///
+ /// Retrieves the list of custom resolutions saved for this display device
+ ///
+ /// A list of instances.
+ public IEnumerable GetCustomResolutions()
+ {
+ return DisplayApi.EnumCustomDisplays(DisplayId).Select(custom => new CustomResolution(custom));
+ }
+
+ ///
+ /// Checks if a color data is supported on this display
+ ///
+ /// The color data to be checked.
+ /// true if the color data passed is supported; otherwise false
+ public bool IsColorDataSupported(ColorData colorData)
+ {
+ var instances = new IColorData[]
+ {
+ colorData.AsColorDataV5(ColorDataCommand.IsSupportedColor),
+ colorData.AsColorDataV4(ColorDataCommand.IsSupportedColor),
+ colorData.AsColorDataV3(ColorDataCommand.IsSupportedColor),
+ colorData.AsColorDataV2(ColorDataCommand.IsSupportedColor),
+ colorData.AsColorDataV1(ColorDataCommand.IsSupportedColor)
+ };
+
+ try
+ {
+ DisplayApi.ColorControl(DisplayId, instances);
+
+ return true;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status == Status.NotSupported)
+ {
+ return false;
+ }
+
+ throw;
+ }
+ }
+
+ ///
+ /// Resets the HDMI audio info-frame information to default
+ ///
+ public void ResetHDMIAudioFrameInformation()
+ {
+ var infoFrame = new InfoFrameData(
+ InfoFrameCommand.Reset,
+ InfoFrameDataType.AudioInformation
+ );
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+ }
+
+ ///
+ /// Resets the HDMI auxiliary video info-frame information to default
+ ///
+ public void ResetHDMIVideoFrameInformation()
+ {
+ var infoFrame = new InfoFrameData(
+ InfoFrameCommand.Reset,
+ InfoFrameDataType.AuxiliaryVideoInformation
+ );
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+ }
+
+ ///
+ /// Reverts the custom resolution currently on trial.
+ ///
+ public void RevertCustomResolution()
+ {
+ RevertCustomResolution(new[] {DisplayId});
+ }
+
+ ///
+ /// Saves the custom resolution currently on trial.
+ ///
+ ///
+ /// If set, the saved custom display will only be applied on the monitor with the same
+ /// outputId.
+ ///
+ ///
+ /// If set, the saved custom display will only be applied on the monitor with the same EDID
+ /// ID or the same TV connector in case of analog TV.
+ ///
+ public void SaveCustomResolution(bool isThisOutputIdOnly = true, bool isThisMonitorOnly = true)
+ {
+ SaveCustomResolution(new[] {DisplayId}, isThisOutputIdOnly, isThisMonitorOnly);
+ }
+
+ ///
+ /// Changes the display current color data configuration
+ ///
+ /// The color data to be set.
+ public void SetColorData(ColorData colorData)
+ {
+ var instances = new IColorData[]
+ {
+ colorData.AsColorDataV5(ColorDataCommand.Set),
+ colorData.AsColorDataV4(ColorDataCommand.Set),
+ colorData.AsColorDataV3(ColorDataCommand.Set),
+ colorData.AsColorDataV2(ColorDataCommand.Set),
+ colorData.AsColorDataV1(ColorDataCommand.Set)
+ };
+
+ DisplayApi.ColorControl(DisplayId, instances);
+ }
+
+ ///
+ /// Sets the HDMI video info-frame current or override information
+ ///
+ /// The new information.
+ /// A boolean value indicating if the changes should persist mode-set and OS restart.
+ public void SetHDMIAudioFrameInformation(InfoFrameAudio audio, bool isOverride = false)
+ {
+ var infoFrame = new InfoFrameData(
+ isOverride ? InfoFrameCommand.SetOverride : InfoFrameCommand.Set,
+ audio
+ );
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+ }
+
+ ///
+ /// Sets the HDMI audio info-frame property information
+ ///
+ /// The new property information.
+ public void SetHDMIAudioFramePropertyInformation(InfoFrameProperty property)
+ {
+ var infoFrame = new InfoFrameData(
+ InfoFrameCommand.SetProperty,
+ InfoFrameDataType.AudioInformation,
+ property
+ );
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+ }
+
+ ///
+ /// Sets the HDMI auxiliary video info-frame current or override information
+ ///
+ /// The new information.
+ /// A boolean value indicating if the changes should persist mode-set and OS restart.
+ public void SetHDMIVideoFrameInformation(InfoFrameVideo video, bool isOverride = false)
+ {
+ var infoFrame = new InfoFrameData(
+ isOverride ? InfoFrameCommand.SetOverride : InfoFrameCommand.Set,
+ video
+ );
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+ }
+
+ ///
+ /// Sets the HDMI auxiliary video info-frame property information
+ ///
+ /// The new property information.
+ public void SetHDMIVideoFramePropertyInformation(InfoFrameProperty property)
+ {
+ var infoFrame = new InfoFrameData(
+ InfoFrameCommand.SetProperty,
+ InfoFrameDataType.AuxiliaryVideoInformation,
+ property
+ );
+ DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
+ }
+
+ ///
+ /// Changes the display HDR color data configuration
+ ///
+ /// The color data to be set.
+ public void SetHDRColorData(HDRColorData colorData)
+ {
+ var instances = new IHDRColorData[]
+ {
+ colorData.AsHDRColorDataV2(ColorDataHDRCommand.Set),
+ colorData.AsHDRColorDataV1(ColorDataHDRCommand.Set)
+ };
+
+ DisplayApi.HDRColorControl(DisplayId, instances);
+ }
+
+ ///
+ /// Applies a custom resolution into trial.
+ ///
+ /// The custom resolution to apply.
+ ///
+ /// A boolean value indicating that a hardware mode-set without OS update should be
+ /// performed.
+ ///
+ public void TrialCustomResolution(CustomResolution customResolution, bool hardwareModeSetOnly = true)
+ {
+ TrialCustomResolution(customResolution, new[] {DisplayId}, hardwareModeSetOnly);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/FloatTexture.cs b/NvAPIWrapper/Display/FloatTexture.cs
new file mode 100644
index 0000000..74ee552
--- /dev/null
+++ b/NvAPIWrapper/Display/FloatTexture.cs
@@ -0,0 +1,183 @@
+using System;
+using System.Linq;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// Represents a texture of float values
+ ///
+ public class FloatTexture : IEquatable
+ {
+ ///
+ /// Underlying float array containing the values of all channels in all pixels
+ ///
+ protected readonly float[] UnderlyingArray;
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The texture width.
+ /// The texture height.
+ /// The number of texture channels.
+ public FloatTexture(int width, int height, int channels) : this(width, height, channels, null)
+ {
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The texture width.
+ /// The texture height.
+ /// The number of texture channels.
+ /// The underlying array containing all float values.
+ // ReSharper disable once TooManyDependencies
+ protected FloatTexture(int width, int height, int channels, float[] array)
+ {
+ Width = width;
+ Height = height;
+ Channels = channels;
+ UnderlyingArray = array ?? new float[width * height * channels];
+ }
+
+ ///
+ /// Gets the number of texture channels
+ ///
+ public int Channels { get; }
+
+ ///
+ /// Gets the texture height in pixel
+ ///
+ public int Height { get; }
+
+ ///
+ /// Gets the texture width in pixels
+ ///
+ public int Width { get; }
+
+ ///
+ public bool Equals(FloatTexture other)
+ {
+ if (other == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.UnderlyingArray.Length != UnderlyingArray.Length)
+ {
+ return false;
+ }
+
+ if (other.Width != Width || other.Height != Height || other.Channels != Channels)
+ {
+ return false;
+ }
+
+ return !UnderlyingArray.Where((t, i) => Math.Abs(other.UnderlyingArray[i] - t) > 0.0001).Any();
+ }
+
+ ///
+ /// Returns a new instance of FloatTexture from the passed array of float values.
+ ///
+ /// The texture width.
+ /// The texture height.
+ /// The texture channels.
+ /// The array of float values.
+ /// A new instance of .
+ // ReSharper disable once TooManyArguments
+ public static FloatTexture FromFloatArray(int width, int height, int channels, float[] floats)
+ {
+ if (floats.Length != width * height * channels)
+ {
+ throw new ArgumentOutOfRangeException(nameof(floats));
+ }
+
+ return new FloatTexture(width, height, channels, floats.ToArray());
+ }
+
+ ///
+ /// Compares two instance of for equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// if both instances are equal, otherwise
+ public static bool operator ==(FloatTexture left, FloatTexture right)
+ {
+ return Equals(left, right) || left?.Equals(right) == true;
+ }
+
+ ///
+ /// Compares two instance of for in-equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// if both instances are not equal, otherwise
+ public static bool operator !=(FloatTexture left, FloatTexture right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ return Equals(obj as FloatTexture);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return UnderlyingArray.GetHashCode();
+ }
+
+ ///
+ /// Gets the values of each channel at a specific location
+ ///
+ /// The horizontal location.
+ /// The vertical location.
+ /// An array of float values each representing a channel value.
+ public float[] GetValues(int x, int y)
+ {
+ return UnderlyingArray.Skip(y * Width + x).Take(Channels).ToArray();
+ }
+
+ ///
+ /// Sets the value of each channel at a specific location
+ ///
+ /// The horizontal location.
+ /// The vertical location.
+ /// An array of float values each representing a channel value.
+ public void SetValues(int x, int y, params float[] floats)
+ {
+ var index = y * Width + x;
+
+ for (var i = 0; i < Math.Min(Channels, floats.Length); i++)
+ {
+ UnderlyingArray[index + i] = floats[i];
+ }
+ }
+
+ ///
+ /// Returns this instance of as an array of float values.
+ ///
+ /// An array of float values representing this instance of .
+ public float[] ToFloatArray()
+ {
+ // Returns a copy of the underlying array
+ return UnderlyingArray.ToArray();
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/HDRColorData.cs b/NvAPIWrapper/Display/HDRColorData.cs
new file mode 100644
index 0000000..935c260
--- /dev/null
+++ b/NvAPIWrapper/Display/HDRColorData.cs
@@ -0,0 +1,157 @@
+using System;
+using NvAPIWrapper.Native.Display;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ public class HDRColorData : IHDRColorData, IEquatable
+ {
+ ///
+ /// Creates an instance of .
+ ///
+ /// The hdr mode.
+ /// The display color space configurations.
+ /// The color data color format.
+ /// The color data dynamic range.
+ /// The color data color depth.
+ public HDRColorData(
+ ColorDataHDRMode hdrMode,
+ MasteringDisplayColorData masteringDisplayData,
+ ColorDataFormat? colorFormat = null,
+ ColorDataDynamicRange? dynamicRange = null,
+ ColorDataDepth? colorDepth = null
+ )
+ {
+ HDRMode = hdrMode;
+ MasteringDisplayData = masteringDisplayData;
+ ColorFormat = colorFormat;
+ DynamicRange = dynamicRange;
+ ColorDepth = colorDepth;
+ }
+
+ internal HDRColorData(IHDRColorData colorData)
+ {
+ HDRMode = colorData.HDRMode;
+ MasteringDisplayData = colorData.MasteringDisplayData;
+ ColorDepth = colorData.ColorDepth;
+ ColorFormat = colorData.ColorFormat;
+ DynamicRange = colorData.DynamicRange;
+ }
+
+ ///
+ public bool Equals(HDRColorData other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return ColorDepth == other.ColorDepth &&
+ ColorFormat == other.ColorFormat &&
+ DynamicRange == other.DynamicRange &&
+ HDRMode == other.HDRMode &&
+ MasteringDisplayData.Equals(other.MasteringDisplayData);
+ }
+
+ ///
+ public ColorDataDepth? ColorDepth { get; }
+
+ ///
+ public ColorDataFormat? ColorFormat { get; }
+
+ ///
+ public ColorDataDynamicRange? DynamicRange { get; }
+
+ ///
+ public ColorDataHDRMode HDRMode { get; }
+
+ ///
+ public MasteringDisplayColorData MasteringDisplayData { get; }
+
+ ///
+ /// Compares two instances of for equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// true if two instances are equal; otherwise false.
+ public static bool operator ==(HDRColorData left, HDRColorData right)
+ {
+ return left?.Equals(right) == true;
+ }
+
+ ///
+ /// Compares two instances of for inequality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// true if two instances are not equal; otherwise false.
+ public static bool operator !=(HDRColorData left, HDRColorData right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((HDRColorData) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = ColorDepth.GetHashCode();
+ hashCode = (hashCode * 397) ^ ColorFormat.GetHashCode();
+ hashCode = (hashCode * 397) ^ DynamicRange.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) HDRMode;
+ hashCode = (hashCode * 397) ^ MasteringDisplayData.GetHashCode();
+
+ return hashCode;
+ }
+ }
+
+ internal HDRColorDataV1 AsHDRColorDataV1(ColorDataHDRCommand command)
+ {
+ return new HDRColorDataV1(
+ command,
+ HDRMode,
+ MasteringDisplayData
+ );
+ }
+
+ internal HDRColorDataV2 AsHDRColorDataV2(ColorDataHDRCommand command)
+ {
+ return new HDRColorDataV2(
+ command,
+ HDRMode,
+ MasteringDisplayData,
+ ColorFormat ?? ColorDataFormat.Auto,
+ DynamicRange ?? ColorDataDynamicRange.Auto,
+ ColorDepth ?? ColorDataDepth.Default
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/HUEInformation.cs b/NvAPIWrapper/Display/HUEInformation.cs
new file mode 100644
index 0000000..22ef2d7
--- /dev/null
+++ b/NvAPIWrapper/Display/HUEInformation.cs
@@ -0,0 +1,97 @@
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.GPU;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// This class contains and provides a way to modify the HUE angle
+ ///
+ public class HUEInformation
+ {
+ private readonly DisplayHandle _displayHandle = DisplayHandle.DefaultHandle;
+ private readonly OutputId _outputId = OutputId.Invalid;
+
+ ///
+ /// Creates a new instance of the class using a DisplayHandle
+ ///
+ /// The handle of the display.
+ public HUEInformation(DisplayHandle displayHandle)
+ {
+ _displayHandle = displayHandle;
+ }
+
+ ///
+ /// Creates a new instance of this class using a OutputId
+ ///
+ /// The output identification of a display or an output
+ public HUEInformation(OutputId outputId)
+ {
+ _outputId = outputId;
+ }
+
+ ///
+ /// Gets or sets the current HUE offset angle [0-359]
+ ///
+ public int CurrentAngle
+ {
+ get
+ {
+ PrivateDisplayHUEInfo? hueInfo = null;
+
+ if (_displayHandle != DisplayHandle.DefaultHandle)
+ {
+ hueInfo = DisplayApi.GetHUEInfo(_displayHandle);
+ }
+ else if (_outputId != OutputId.Invalid)
+ {
+ hueInfo = DisplayApi.GetHUEInfo(_outputId);
+ }
+
+ return hueInfo?.CurrentAngle ?? 0;
+ }
+ set
+ {
+ value %= 360;
+
+ if (_displayHandle != DisplayHandle.DefaultHandle)
+ {
+ DisplayApi.SetHUEAngle(_displayHandle, value);
+ }
+ else if (_outputId != OutputId.Invalid)
+ {
+ DisplayApi.SetHUEAngle(_outputId, value);
+ }
+ }
+ }
+
+ ///
+ /// Gets the default HUE offset angle [0-359]
+ ///
+ public int DefaultAngle
+ {
+ get
+ {
+ PrivateDisplayHUEInfo? hueInfo = null;
+
+ if (_displayHandle != DisplayHandle.DefaultHandle)
+ {
+ hueInfo = DisplayApi.GetHUEInfo(_displayHandle);
+ }
+ else if (_outputId != OutputId.Invalid)
+ {
+ hueInfo = DisplayApi.GetHUEInfo(_outputId);
+ }
+
+ return hueInfo?.DefaultAngle ?? 0;
+ }
+ }
+
+
+ ///
+ public override string ToString()
+ {
+ return $"{CurrentAngle:D}º [{DefaultAngle:D}º]";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/IntensityTexture.cs b/NvAPIWrapper/Display/IntensityTexture.cs
new file mode 100644
index 0000000..0025f3c
--- /dev/null
+++ b/NvAPIWrapper/Display/IntensityTexture.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Linq;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// Represents a texture of intensity values
+ ///
+ public class IntensityTexture : FloatTexture
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The texture width.
+ /// The texture height.
+ public IntensityTexture(int width, int height) : base(width, height, 3)
+ {
+ }
+
+ private IntensityTexture(int width, int height, float[] floats) : base(width, height, 3, floats)
+ {
+ }
+
+ ///
+ /// Returns a new instance of FloatTexture from the passed array of float values.
+ ///
+ /// The texture width.
+ /// The texture height.
+ /// The array of float values.
+ /// A new instance of .
+ // ReSharper disable once TooManyArguments
+ public static IntensityTexture FromFloatArray(int width, int height, float[] floats)
+ {
+ if (floats.Length != width * height * 3)
+ {
+ throw new ArgumentOutOfRangeException(nameof(floats));
+ }
+
+ return new IntensityTexture(width, height, floats.ToArray());
+ }
+
+ ///
+ /// Gets the value of intensity pixel at a specific location.
+ ///
+ /// The horizontal location.
+ /// The vertical location.
+ /// An instance of .
+ public IntensityTexturePixel GetPixel(int x, int y)
+ {
+ return IntensityTexturePixel.FromFloatArray(UnderlyingArray, y * Width + x);
+ }
+
+ ///
+ /// Sets the value of intensity pixel at a specific location
+ ///
+ /// The horizontal location.
+ /// The vertical location.
+ /// An instance of .
+ public void SetPixel(int x, int y, IntensityTexturePixel pixel)
+ {
+ var index = y * Width + x;
+ var floats = pixel.ToFloatArray();
+
+ for (var i = 0; i < Math.Min(Channels, floats.Length); i++)
+ {
+ UnderlyingArray[index + i] = floats[i];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/IntensityTexturePixel.cs b/NvAPIWrapper/Display/IntensityTexturePixel.cs
new file mode 100644
index 0000000..b357773
--- /dev/null
+++ b/NvAPIWrapper/Display/IntensityTexturePixel.cs
@@ -0,0 +1,117 @@
+using System;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// Represents a RGB intensity texture pixel
+ ///
+ public class IntensityTexturePixel : IEquatable
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The intensity of the red light (0-1)
+ /// The intensity of the green light (0-1)
+ /// The intensity of the blue light (0-1)
+ public IntensityTexturePixel(float redIntensity, float greenIntensity, float blueIntensity)
+ {
+ RedIntensity = Math.Max(Math.Min(redIntensity, 1), 0);
+ GreenIntensity = Math.Max(Math.Min(greenIntensity, 1), 0);
+ BlueIntensity = Math.Max(Math.Min(blueIntensity, 1), 0);
+ }
+
+ ///
+ /// Gets the intensity of the blue light (0-1)
+ ///
+ public float BlueIntensity { get; }
+
+ ///
+ /// Gets the intensity of the green light (0-1)
+ ///
+ public float GreenIntensity { get; }
+
+ ///
+ /// Gets the intensity of the red light (0-1)
+ ///
+ public float RedIntensity { get; }
+
+ ///
+ public bool Equals(IntensityTexturePixel other)
+ {
+ if (other == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return Math.Abs(RedIntensity - other.RedIntensity) < 0.0001 &&
+ Math.Abs(GreenIntensity - other.GreenIntensity) < 0.0001 &&
+ Math.Abs(BlueIntensity - other.BlueIntensity) < 0.0001;
+ }
+
+ ///
+ /// Compares two instance of for equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// if both instances are equal, otherwise
+ public static bool operator ==(IntensityTexturePixel left, IntensityTexturePixel right)
+ {
+ return Equals(left, right) || left?.Equals(right) == true;
+ }
+
+ ///
+ /// Compares two instance of for in-equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// if both instances are not equal, otherwise
+ public static bool operator !=(IntensityTexturePixel left, IntensityTexturePixel right)
+ {
+ return !(left == right);
+ }
+
+ internal static IntensityTexturePixel FromFloatArray(float[] floats, int index)
+ {
+ return new IntensityTexturePixel(floats[index], floats[index + 1], floats[index + 2]);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ return Equals(obj as IntensityTexturePixel);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = RedIntensity.GetHashCode();
+ hashCode = (hashCode * 397) ^ GreenIntensity.GetHashCode();
+ hashCode = (hashCode * 397) ^ BlueIntensity.GetHashCode();
+
+ return hashCode;
+ }
+ }
+
+ internal float[] ToFloatArray()
+ {
+ return new[] {RedIntensity, GreenIntensity, BlueIntensity};
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/PathInfo.cs b/NvAPIWrapper/Display/PathInfo.cs
new file mode 100644
index 0000000..02551a1
--- /dev/null
+++ b/NvAPIWrapper/Display/PathInfo.cs
@@ -0,0 +1,288 @@
+using System;
+using System.Linq;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.Display;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.Exceptions;
+using NvAPIWrapper.Native.General;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// Represents a configuration path
+ ///
+ public class PathInfo : IEquatable
+ {
+ ///
+ /// Creates a new PathInfo
+ ///
+ /// Display resolution
+ /// Display color format
+ /// Target configuration informations
+ public PathInfo(Resolution resolution, ColorFormat colorFormat, PathTargetInfo[] targetInfos)
+ {
+ Resolution = resolution;
+ ColorFormat = colorFormat;
+ TargetsInfo = targetInfos;
+ }
+
+ ///
+ /// Creates a new PathInfo
+ ///
+ /// IPathInfo implamented object
+ public PathInfo(IPathInfo info)
+ {
+ SourceId = info.SourceId;
+ Resolution = info.SourceModeInfo.Resolution;
+ ColorFormat = info.SourceModeInfo.ColorFormat;
+ Position = info.SourceModeInfo.Position;
+ SpanningOrientation = info.SourceModeInfo.SpanningOrientation;
+ IsGDIPrimary = info.SourceModeInfo.IsGDIPrimary;
+ IsSLIFocus = info.SourceModeInfo.IsSLIFocus;
+ TargetsInfo =
+ info.TargetsInfo.Select(targetInfo => new PathTargetInfo(targetInfo)).ToArray();
+
+ if (info is PathInfoV2)
+ {
+ OSAdapterLUID = ((PathInfoV2) info).OSAdapterLUID;
+ }
+ }
+
+ ///
+ /// Gets or sets the display color format
+ ///
+ public ColorFormat ColorFormat { get; set; }
+
+ ///
+ /// Gets or sets a boolean value indicating if the this is the primary GDI display
+ ///
+ public bool IsGDIPrimary { get; set; }
+
+ ///
+ /// Gets or sets a boolean value indicating if the this is the SLI focus display
+ ///
+ public bool IsSLIFocus { get; set; }
+
+ ///
+ /// Gets OS Adapter of LUID for Non-NVIDIA adapters
+ ///
+ public LUID? OSAdapterLUID { get; }
+
+ ///
+ /// Gets or sets the display position
+ ///
+ public Position Position { get; set; }
+
+ ///
+ /// Gets or sets the display resolution
+ ///
+ public Resolution Resolution { get; set; }
+
+ ///
+ /// Gets or sets the Windows CCD display source identification. This can be optionally set.
+ ///
+ public uint SourceId { get; set; }
+
+ ///
+ /// Gets or sets the display spanning orientation, valid for XP only
+ ///
+ public SpanningOrientation SpanningOrientation { get; set; }
+
+
+ ///
+ /// Gets information about path targets
+ ///
+ public PathTargetInfo[] TargetsInfo { get; }
+
+
+ ///
+ /// Checks for equality with a PathInfo instance
+ ///
+ /// The PathInfo object to check with
+ /// true if both objects are equal, otherwise false
+ public bool Equals(PathInfo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return Resolution.Equals(other.Resolution) &&
+ ColorFormat == other.ColorFormat &&
+ Position.Equals(other.Position) &&
+ SpanningOrientation == other.SpanningOrientation &&
+ IsGDIPrimary == other.IsGDIPrimary &&
+ IsSLIFocus == other.IsSLIFocus &&
+ TargetsInfo.SequenceEqual(other.TargetsInfo);
+ }
+
+
+ ///
+ /// Creates and fills a PathInfo object
+ ///
+ /// The newly created PathInfo object
+ public static PathInfo[] GetDisplaysConfig()
+ {
+ var configs = DisplayApi.GetDisplayConfig();
+ var logicalDisplays = configs.Select(info => new PathInfo(info)).ToArray();
+ configs.DisposeAll();
+
+ return logicalDisplays;
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(PathInfo left, PathInfo right)
+ {
+ return right?.Equals(left) ?? ReferenceEquals(left, null);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(PathInfo left, PathInfo right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ /// Applies one or more path information configurations
+ ///
+ /// An array of path information configuration
+ /// DisplayConfigFlags flags
+ public static void SetDisplaysConfig(PathInfo[] pathInfos, DisplayConfigFlags flags)
+ {
+ try
+ {
+ var configsV2 = pathInfos.Select(config => config.GetPathInfoV2()).Cast().ToArray();
+ DisplayApi.SetDisplayConfig(configsV2, flags);
+ configsV2.DisposeAll();
+ }
+ catch (NVIDIAApiException ex)
+ {
+ if (ex.Status != Status.IncompatibleStructureVersion)
+ {
+ throw;
+ }
+ }
+ catch (NVIDIANotSupportedException)
+ {
+ // ignore
+ }
+
+ var configsV1 = pathInfos.Select(config => config.GetPathInfoV1()).Cast().ToArray();
+ DisplayApi.SetDisplayConfig(configsV1, flags);
+ configsV1.DisposeAll();
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((PathInfo) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = Resolution.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) ColorFormat;
+ hashCode = (hashCode * 397) ^ Position.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) SpanningOrientation;
+ hashCode = (hashCode * 397) ^ IsGDIPrimary.GetHashCode();
+ hashCode = (hashCode * 397) ^ IsSLIFocus.GetHashCode();
+ hashCode = (hashCode * 397) ^ (TargetsInfo?.GetHashCode() ?? 0);
+
+ return hashCode;
+ }
+ }
+
+
+ ///
+ public override string ToString()
+ {
+ return $"{Resolution} @ {Position} [{TargetsInfo.Length}]";
+ }
+
+ ///
+ /// Creates and fills a GetPathInfoV1 object
+ ///
+ /// The newly created GetPathInfoV1 object
+ public PathInfoV1 GetPathInfoV1()
+ {
+ var sourceModeInfo = GetSourceModeInfo();
+ var pathTargetInfoV1 = GetPathTargetInfoV1Array();
+
+ return new PathInfoV1(pathTargetInfoV1, sourceModeInfo, SourceId);
+ }
+
+ ///
+ /// Creates and fills a GetPathInfoV2 object
+ ///
+ /// The newly created GetPathInfoV2 object
+ public PathInfoV2 GetPathInfoV2()
+ {
+ var sourceModeInfo = GetSourceModeInfo();
+ var pathTargetInfoV2 = GetPathTargetInfoV2Array();
+
+ return new PathInfoV2(pathTargetInfoV2, sourceModeInfo, SourceId);
+ }
+
+ ///
+ /// Creates and fills an array of GetPathTargetInfoV1 object
+ ///
+ /// The newly created array of GetPathTargetInfoV1 objects
+ public PathTargetInfoV1[] GetPathTargetInfoV1Array()
+ {
+ return TargetsInfo.Select(config => config.GetPathTargetInfoV1()).ToArray();
+ }
+
+ ///
+ /// Creates and fills an array of GetPathTargetInfoV2 object
+ ///
+ /// The newly created array of GetPathTargetInfoV2 objects
+ public PathTargetInfoV2[] GetPathTargetInfoV2Array()
+ {
+ return TargetsInfo.Select(config => config.GetPathTargetInfoV2()).ToArray();
+ }
+
+ ///
+ /// Creates and fills a SourceModeInfo object
+ ///
+ /// The newly created SourceModeInfo object
+ public SourceModeInfo GetSourceModeInfo()
+ {
+ return new SourceModeInfo(Resolution, ColorFormat, Position, SpanningOrientation, IsGDIPrimary, IsSLIFocus);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/PathTargetInfo.cs b/NvAPIWrapper/Display/PathTargetInfo.cs
new file mode 100644
index 0000000..dde14d1
--- /dev/null
+++ b/NvAPIWrapper/Display/PathTargetInfo.cs
@@ -0,0 +1,304 @@
+using System;
+using System.Collections.Generic;
+using NvAPIWrapper.Native.Display;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.Exceptions;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// Represents a display configuration on a path
+ ///
+ public class PathTargetInfo : IEquatable
+ {
+ private TimingOverride _timingOverride;
+
+ ///
+ /// Creates a new PathTargetInfo
+ ///
+ /// IPathTargetInfo implamented object
+ public PathTargetInfo(IPathTargetInfo info)
+ {
+ DisplayDevice = new DisplayDevice(info.DisplayId);
+
+ if (info.Details.HasValue)
+ {
+ Rotation = info.Details.Value.Rotation;
+ Scaling = info.Details.Value.Scaling;
+ TVConnectorType = info.Details.Value.ConnectorType;
+ TVFormat = info.Details.Value.TVFormat;
+ RefreshRateInMillihertz = info.Details.Value.RefreshRateInMillihertz;
+ TimingOverride = info.Details.Value.TimingOverride;
+ IsInterlaced = info.Details.Value.IsInterlaced;
+ IsClonePrimary = info.Details.Value.IsClonePrimary;
+ IsClonePanAndScanTarget = info.Details.Value.IsClonePanAndScanTarget;
+ DisableVirtualModeSupport = info.Details.Value.DisableVirtualModeSupport;
+ IsPreferredUnscaledTarget = info.Details.Value.IsPreferredUnscaledTarget;
+ }
+
+ if (info is PathTargetInfoV2)
+ {
+ WindowsCCDTargetId = ((PathTargetInfoV2) info).WindowsCCDTargetId;
+ }
+ }
+
+ ///
+ /// Creates a new PathTargetInfo
+ ///
+ /// DisplayDevice object
+ public PathTargetInfo(DisplayDevice device)
+ {
+ DisplayDevice = device;
+ }
+
+ ///
+ /// Gets or sets the virtual mode support
+ ///
+ public bool DisableVirtualModeSupport { get; set; }
+
+ ///
+ /// Gets corresponding DisplayDevice
+ ///
+ public DisplayDevice DisplayDevice { get; }
+
+ ///
+ /// Gets or sets the pan and scan is availability. Valid only when the target is part of clone
+ /// topology.
+ ///
+ public bool IsClonePanAndScanTarget { get; set; }
+
+ ///
+ /// Gets or sets the primary display in clone configuration. This is *NOT* GDI Primary.
+ /// Only one target can be primary per source. If no primary is specified, the first target will automatically be
+ /// primary.
+ ///
+ public bool IsClonePrimary { get; set; }
+
+ ///
+ /// Gets or sets the interlaced mode flag, ignored if refreshRate == 0
+ ///
+ public bool IsInterlaced { get; set; }
+
+ ///
+ /// Gets or sets the preferred unscaled mode of target
+ ///
+ public bool IsPreferredUnscaledTarget { get; set; }
+
+ ///
+ /// Gets and sets the non-interlaced Refresh Rate of the mode, multiplied by 1000, 0 = ignored
+ /// This is the value which driver reports to the OS.
+ ///
+ public uint RefreshRateInMillihertz { get; set; }
+
+ ///
+ /// Gets and sets the rotation setting
+ ///
+ public Rotate Rotation { get; set; }
+
+ ///
+ /// Gets and sets the scaling setting
+ ///
+ public Scaling Scaling { get; set; }
+
+ ///
+ /// Gets and sets the custom timing of display
+ /// Ignored if TimingOverride == TimingOverride.Current
+ ///
+ public TimingOverride TimingOverride
+ {
+ get => _timingOverride;
+ set
+ {
+ if (value == TimingOverride.Custom)
+ {
+ throw new NVIDIANotSupportedException("Custom timing is not supported yet.");
+ }
+
+ _timingOverride = value;
+ }
+ }
+
+ ///
+ /// Gets and sets the connector type. For TV only, ignored if TVFormat == TVFormat.None.
+ ///
+ public ConnectorType TVConnectorType { get; set; }
+
+ ///
+ /// Gets and sets the TV format. For TV only, otherwise set to TVFormat.None
+ ///
+ public TVFormat TVFormat { get; set; }
+
+ ///
+ /// Gets the Windows CCD target ID. Must be present only for non-NVIDIA adapter, for NVIDIA adapter this parameter is
+ /// ignored.
+ ///
+ public uint WindowsCCDTargetId { get; }
+
+ ///
+ /// Checks for equality with a PathTargetInfo instance
+ ///
+ /// The PathTargetInfo object to check with
+ /// true if both objects are equal, otherwise false
+ public bool Equals(PathTargetInfo other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return _timingOverride == other._timingOverride &&
+ Rotation == other.Rotation &&
+ Scaling == other.Scaling &&
+ RefreshRateInMillihertz == other.RefreshRateInMillihertz &&
+ (TVFormat == TVFormat.None || TVConnectorType == other.TVConnectorType) &&
+ TVFormat == other.TVFormat &&
+ DisplayDevice.Equals(other.DisplayDevice) &&
+ IsInterlaced == other.IsInterlaced &&
+ IsClonePrimary == other.IsClonePrimary &&
+ IsClonePanAndScanTarget == other.IsClonePanAndScanTarget &&
+ DisableVirtualModeSupport == other.DisableVirtualModeSupport &&
+ IsPreferredUnscaledTarget == other.IsPreferredUnscaledTarget;
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(PathTargetInfo left, PathTargetInfo right)
+ {
+ return right?.Equals(left) ?? ReferenceEquals(left, null);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(PathTargetInfo left, PathTargetInfo right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((PathTargetInfo) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = (int) _timingOverride;
+ hashCode = (hashCode * 397) ^ (int) Rotation;
+ hashCode = (hashCode * 397) ^ (int) Scaling;
+ hashCode = (hashCode * 397) ^ (int) RefreshRateInMillihertz;
+ hashCode = (hashCode * 397) ^ (int) TVFormat;
+ hashCode = (hashCode * 397) ^ (TVFormat != TVFormat.None ? (int) TVConnectorType : 0);
+ hashCode = (hashCode * 397) ^ (DisplayDevice?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ IsInterlaced.GetHashCode();
+ hashCode = (hashCode * 397) ^ IsClonePrimary.GetHashCode();
+ hashCode = (hashCode * 397) ^ IsClonePanAndScanTarget.GetHashCode();
+ hashCode = (hashCode * 397) ^ DisableVirtualModeSupport.GetHashCode();
+ hashCode = (hashCode * 397) ^ IsPreferredUnscaledTarget.GetHashCode();
+
+ return hashCode;
+ }
+ }
+
+ ///
+ public override string ToString()
+ {
+ var strs = new List
+ {
+ DisplayDevice.ToString()
+ };
+
+ if (RefreshRateInMillihertz > 0)
+ {
+ strs.Add($"@ {RefreshRateInMillihertz / 1000}hz");
+ }
+
+ if (TVFormat != TVFormat.None)
+ {
+ strs.Add($"- TV {TVFormat}");
+ }
+
+ strs.Add(IsInterlaced ? "Interlaced" : "Progressive");
+
+ if (Rotation != Rotate.Degree0)
+ {
+ strs.Add($"- Rotation: {Rotation}");
+ }
+
+ return string.Join(" ", strs);
+ }
+
+
+ ///
+ /// Creates and fills a PathAdvancedTargetInfo object
+ ///
+ /// The newly created PathAdvancedTargetInfo object
+ public PathAdvancedTargetInfo GetPathAdvancedTargetInfo()
+ {
+ if (TVFormat == TVFormat.None)
+ {
+ return new PathAdvancedTargetInfo(Rotation, Scaling, RefreshRateInMillihertz, TimingOverride,
+ IsInterlaced, IsClonePrimary, IsClonePanAndScanTarget, DisableVirtualModeSupport,
+ IsPreferredUnscaledTarget);
+ }
+
+ return new PathAdvancedTargetInfo(Rotation, Scaling, TVFormat, TVConnectorType, RefreshRateInMillihertz,
+ TimingOverride, IsInterlaced, IsClonePrimary, IsClonePanAndScanTarget, DisableVirtualModeSupport,
+ IsPreferredUnscaledTarget);
+ }
+
+ ///
+ /// Creates and fills a PathTargetInfoV1 object
+ ///
+ /// The newly created PathTargetInfoV1 object
+ public PathTargetInfoV1 GetPathTargetInfoV1()
+ {
+ var pathAdvancedTargetInfo = GetPathAdvancedTargetInfo();
+
+ return new PathTargetInfoV1(DisplayDevice.DisplayId, pathAdvancedTargetInfo);
+ }
+
+ ///
+ /// Creates and fills a PathTargetInfoV2 object
+ ///
+ /// The newly created PathTargetInfoV2 object
+ public PathTargetInfoV2 GetPathTargetInfoV2()
+ {
+ var pathAdvancedTargetInfo = GetPathAdvancedTargetInfo();
+
+ return new PathTargetInfoV2(DisplayDevice.DisplayId, WindowsCCDTargetId, pathAdvancedTargetInfo);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/ScanOutInformation.cs b/NvAPIWrapper/Display/ScanOutInformation.cs
new file mode 100644
index 0000000..4f338cd
--- /dev/null
+++ b/NvAPIWrapper/Display/ScanOutInformation.cs
@@ -0,0 +1,217 @@
+using System.Linq;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.Display;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.General.Structures;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// Contains information regarding the scan-out buffer settings of a display device
+ ///
+ public class ScanOutInformation
+ {
+ internal ScanOutInformation(DisplayDevice displayDevice)
+ {
+ DisplayDevice = displayDevice;
+ }
+
+ ///
+ /// Gets the clone importance assigned to the target if the target is a cloned view of the SourceDesktopRectangle
+ /// (0:primary,1 secondary,...).
+ ///
+ public uint CloneImportance
+ {
+ get => DisplayApi.GetScanOutConfiguration(DisplayDevice.DisplayId).CloneImportance;
+ }
+
+ ///
+ /// Gets the display device that this instance describes
+ ///
+ public DisplayDevice DisplayDevice { get; }
+
+ ///
+ /// Gets a boolean value indicating if the display device scan out output is warped
+ ///
+ public bool IsDisplayWarped
+ {
+ get => DisplayApi.GetScanOutWarpingState(DisplayDevice.DisplayId).IsEnabled;
+ }
+
+ ///
+ /// Gets a boolean value indicating if the display device intensity is modified
+ ///
+ public bool IsIntensityModified
+ {
+ get => DisplayApi.GetScanOutIntensityState(DisplayDevice.DisplayId).IsEnabled;
+ }
+
+ ///
+ /// Gets the operating system display device rectangle in desktop coordinates displayId is scanning out from.
+ ///
+ public Rectangle SourceDesktopRectangle
+ {
+ get => DisplayApi.GetScanOutConfiguration(DisplayDevice.DisplayId).SourceDesktopRectangle;
+ }
+
+ ///
+ /// Gets the rotation performed between the SourceViewPortRectangle and the TargetViewPortRectangle.
+ ///
+ public Rotate SourceToTargetRotation
+ {
+ get => DisplayApi.GetScanOutConfiguration(DisplayDevice.DisplayId).SourceToTargetRotation;
+ }
+
+ ///
+ /// Gets the area inside the SourceDesktopRectangle which is scanned out to the display.
+ ///
+ public Rectangle SourceViewPortRectangle
+ {
+ get => DisplayApi.GetScanOutConfiguration(DisplayDevice.DisplayId).SourceViewPortRectangle;
+ }
+
+ ///
+ /// Gets the vertical size of the active resolution scanned out to the display.
+ ///
+ public uint TargetDisplayHeight
+ {
+ get => DisplayApi.GetScanOutConfiguration(DisplayDevice.DisplayId).TargetDisplayHeight;
+ }
+
+ ///
+ /// Gets the horizontal size of the active resolution scanned out to the display.
+ ///
+ public uint TargetDisplayWidth
+ {
+ get => DisplayApi.GetScanOutConfiguration(DisplayDevice.DisplayId).TargetDisplayWidth;
+ }
+
+ ///
+ /// Gets the area inside the rectangle described by targetDisplayWidth/Height SourceViewPortRectangle is scanned out
+ /// to.
+ ///
+ public Rectangle TargetViewPortRectangle
+ {
+ get => DisplayApi.GetScanOutConfiguration(DisplayDevice.DisplayId).TargetViewPortRectangle;
+ }
+
+ ///
+ /// Disables the intensity modification on the display device scan-out buffer.
+ ///
+ /// A boolean value that indicates whether the settings will be kept over a reboot.
+ public void DisableIntensityModifications(out bool isSticky)
+ {
+ DisplayApi.SetScanOutIntensity(DisplayDevice.DisplayId, null, out isSticky);
+ }
+
+ ///
+ /// Disables the warping of display device scan-out buffer.
+ ///
+ /// A boolean value that indicates whether the settings will be kept over a reboot.
+ public void DisableWarping(out bool isSticky)
+ {
+ var vorticesCount = 0;
+ DisplayApi.SetScanOutWarping(DisplayDevice.DisplayId, null, ref vorticesCount, out isSticky);
+ }
+
+ ///
+ /// Enables the intensity modification on the display device scan-out buffer.
+ ///
+ /// The intensity texture to apply to the scan-out buffer.
+ /// A boolean value that indicates whether the settings will be kept over a reboot.
+ public void EnableIntensityModifications(IntensityTexture intensityTexture, out bool isSticky)
+ {
+ using (
+ var intensity = new ScanOutIntensityV1(
+ (uint) intensityTexture.Width,
+ (uint) intensityTexture.Height,
+ intensityTexture.ToFloatArray()
+ )
+ )
+ {
+ DisplayApi.SetScanOutIntensity(DisplayDevice.DisplayId, intensity, out isSticky);
+ }
+ }
+
+ ///
+ /// Enables the intensity modification on the display device scan-out buffer.
+ ///
+ /// The intensity texture to apply to the scan-out buffer.
+ /// The offset texture to apply to the scan-out buffer.
+ /// A boolean value that indicates whether the settings will be kept over a reboot.
+ public void EnableIntensityModifications(
+ IntensityTexture intensityTexture,
+ FloatTexture offsetTexture,
+ out bool isSticky)
+ {
+ using (
+ var intensity = new ScanOutIntensityV2(
+ (uint) intensityTexture.Width,
+ (uint) intensityTexture.Height,
+ intensityTexture.ToFloatArray(),
+ (uint) offsetTexture.Channels,
+ offsetTexture.ToFloatArray()
+ )
+ )
+ {
+ DisplayApi.SetScanOutIntensity(DisplayDevice.DisplayId, intensity, out isSticky);
+ }
+ }
+
+ ///
+ /// Enables the warping of display device scan-out buffer
+ ///
+ /// The type of warping vortexes.
+ /// An array of warping vortexes.
+ /// The rectangle in desktop coordinates describing the source area for the warping.
+ /// A boolean value that indicates whether the settings will be kept over a reboot.
+ // ReSharper disable once TooManyArguments
+ public void EnableWarping(
+ WarpingVerticeFormat warpingVerticeFormat,
+ XYUVRQVortex[] vortices,
+ Rectangle textureRectangle,
+ out bool isSticky)
+ {
+ using (
+ var warping = new ScanOutWarpingV1(
+ warpingVerticeFormat,
+ vortices.SelectMany(vortex => vortex.AsFloatArray()).ToArray(),
+ textureRectangle
+ )
+ )
+ {
+ var vorticesCount = vortices.Length;
+ DisplayApi.SetScanOutWarping(DisplayDevice.DisplayId, warping, ref vorticesCount, out isSticky);
+ }
+ }
+
+ ///
+ /// Queries the current state of one of the various scan-out composition parameters.
+ ///
+ /// The scan-out composition parameter.
+ /// The additional value included with the parameter value.
+ /// The scan-out composition parameter value.
+ public ScanOutCompositionParameterValue GetCompositionParameterValue(
+ ScanOutCompositionParameter parameter,
+ out float additionalValue)
+ {
+ return DisplayApi.GetScanOutCompositionParameter(DisplayDevice.DisplayId, parameter, out additionalValue);
+ }
+
+
+ ///
+ /// Sets the current state of one of the various scan-out composition parameters.
+ ///
+ /// The scan-out composition parameter.
+ /// The scan-out composition parameter value.
+ /// The additional value included with the parameter value.
+ public void SetCompositionParameterValue(
+ ScanOutCompositionParameter parameter,
+ ScanOutCompositionParameterValue parameterValue,
+ float additionalValue)
+ {
+ DisplayApi.SetScanOutCompositionParameter(DisplayDevice.DisplayId, parameter, parameterValue,
+ ref additionalValue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/UnAttachedDisplay.cs b/NvAPIWrapper/Display/UnAttachedDisplay.cs
new file mode 100644
index 0000000..1af2c33
--- /dev/null
+++ b/NvAPIWrapper/Display/UnAttachedDisplay.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Linq;
+using NvAPIWrapper.GPU;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.Display.Structures;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// Represents an unattached display
+ ///
+ public class UnAttachedDisplay : IEquatable
+ {
+ ///
+ /// Creates a new UnAttachedDisplay
+ ///
+ /// Handle of the unattached display device
+ public UnAttachedDisplay(UnAttachedDisplayHandle handle)
+ {
+ Handle = handle;
+ }
+
+ ///
+ /// Creates a new UnAttachedDisplay
+ ///
+ /// Name of the unattached display device
+ public UnAttachedDisplay(string displayName)
+ {
+ Handle = DisplayApi.GetAssociatedUnAttachedNvidiaDisplayHandle(displayName);
+ }
+
+ ///
+ /// Gets display handle
+ ///
+ public UnAttachedDisplayHandle Handle { get; }
+
+ ///
+ /// Gets display name
+ ///
+ public string Name
+ {
+ get => DisplayApi.GetUnAttachedAssociatedDisplayName(Handle);
+ }
+
+ ///
+ /// Gets corresponding physical GPU
+ ///
+ public PhysicalGPU PhysicalGPU
+ {
+ get => new PhysicalGPU(GPUApi.GetPhysicalGPUFromUnAttachedDisplay(Handle));
+ }
+
+ ///
+ /// Checks for equality with a UnAttachedDisplay instance
+ ///
+ /// The Display object to check with
+ /// true if both objects are equal, otherwise false
+ public bool Equals(UnAttachedDisplay other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return Handle.Equals(other.Handle);
+ }
+
+ ///
+ /// This function returns all unattached NVIDIA displays
+ /// Note: Display handles can get invalidated on a modeset.
+ ///
+ /// An array of Display objects
+ public static UnAttachedDisplay[] GetUnAttachedDisplays()
+ {
+ return
+ DisplayApi.EnumNvidiaUnAttachedDisplayHandle().Select(handle => new UnAttachedDisplay(handle))
+ .ToArray();
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(UnAttachedDisplay left, UnAttachedDisplay right)
+ {
+ return right?.Equals(left) ?? ReferenceEquals(left, null);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(UnAttachedDisplay left, UnAttachedDisplay right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((UnAttachedDisplay) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return Handle.GetHashCode();
+ }
+
+ ///
+ public override string ToString()
+ {
+ return Name;
+ }
+
+ ///
+ /// Creates a new active attached display from this unattached display
+ /// At least one GPU must be present in the system and running an NVIDIA display driver.
+ ///
+ /// An active attached display
+ public Display CreateDisplay()
+ {
+ return new Display(DisplayApi.CreateDisplayFromUnAttachedDisplay(Handle));
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Display/XYUVRQVortex.cs b/NvAPIWrapper/Display/XYUVRQVortex.cs
new file mode 100644
index 0000000..f90a955
--- /dev/null
+++ b/NvAPIWrapper/Display/XYUVRQVortex.cs
@@ -0,0 +1,165 @@
+using System;
+using System.Collections.Generic;
+
+namespace NvAPIWrapper.Display
+{
+ ///
+ /// Represents a XYUVRQ scan-out warping vortex
+ ///
+ public class XYUVRQVortex : IEquatable
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The target view port mesh horizontal coordinate
+ /// The target view port mesh vertical coordinate
+ /// The desktop view port texture horizontal coordinate
+ /// The desktop view port texture vertical coordinate
+ /// The 3D warp perspective R factor
+ /// The 3D warp perspective Q factor
+ // ReSharper disable once TooManyDependencies
+ public XYUVRQVortex(int x, int y, int u, int v, float r, float q)
+ {
+ X = x;
+ Y = y;
+ U = u;
+ V = v;
+ R = r;
+ Q = q;
+ }
+
+ ///
+ /// 3D warp perspective Q factor
+ ///
+ public float Q { get; }
+
+ ///
+ /// 3D warp perspective R factor
+ ///
+ public float R { get; }
+
+ ///
+ /// Desktop view port texture horizontal coordinate
+ ///
+ public int U { get; }
+
+ ///
+ /// Desktop view port texture vertical coordinate
+ ///
+ public int V { get; }
+
+ ///
+ /// Target view port mesh horizontal coordinate
+ ///
+ public int X { get; }
+
+ ///
+ /// Target view port mesh vertical coordinate
+ ///
+ public int Y { get; }
+
+ ///
+ public bool Equals(XYUVRQVortex other)
+ {
+ if (other == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return Math.Abs(Q - other.Q) < 0.0001 &&
+ Math.Abs(R - other.R) < 0.0001 &&
+ U == other.U &&
+ V == other.V &&
+ X == other.X &&
+ Y == other.Y;
+ }
+
+ ///
+ /// Parses an array of floats and returns the corresponding s.
+ ///
+ /// The array of float representing one or more s.
+ /// Instances of .
+ public static IEnumerable FromFloatArray(float[] floats)
+ {
+ for (var i = 0; i + 6 <= floats.Length; i += 6)
+ {
+ yield return new XYUVRQVortex(
+ (int) floats[i],
+ (int) floats[i + 1],
+ (int) floats[i + 2],
+ (int) floats[i + 3],
+ floats[i + 4],
+ floats[i + 5]
+ );
+ }
+ }
+
+ ///
+ /// Compares two instance of for equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// if both instances are equal, otherwise
+ public static bool operator ==(XYUVRQVortex left, XYUVRQVortex right)
+ {
+ return Equals(left, right) || left?.Equals(right) == true;
+ }
+
+ ///
+ /// Compares two instance of for in-equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// if both instances are not equal, otherwise
+ public static bool operator !=(XYUVRQVortex left, XYUVRQVortex right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ return Equals(obj as XYUVRQVortex);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = Q.GetHashCode();
+ hashCode = (hashCode * 397) ^ R.GetHashCode();
+ hashCode = (hashCode * 397) ^ U;
+ hashCode = (hashCode * 397) ^ V;
+ hashCode = (hashCode * 397) ^ X;
+ hashCode = (hashCode * 397) ^ Y;
+
+ return hashCode;
+ }
+ }
+
+ ///
+ /// Returns this instance of as a float array.
+ ///
+ /// An array of float values representing this instance of .
+ public float[] AsFloatArray()
+ {
+ return new[] {X, Y, U, V, R, Q};
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/AGPInformation.cs b/NvAPIWrapper/GPU/AGPInformation.cs
new file mode 100644
index 0000000..25a8084
--- /dev/null
+++ b/NvAPIWrapper/GPU/AGPInformation.cs
@@ -0,0 +1,30 @@
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Contains information about the accelerated graphics connection
+ ///
+ public class AGPInformation
+ {
+ internal AGPInformation(int aperture, int currentRate)
+ {
+ ApertureInMB = aperture;
+ CurrentRate = currentRate;
+ }
+
+ ///
+ /// Gets AGP aperture in megabytes
+ ///
+ public int ApertureInMB { get; }
+
+ ///
+ /// Gets current AGP Rate (0 = AGP not present, 1 = 1x, 2 = 2x, etc.)
+ ///
+ public int CurrentRate { get; }
+
+ ///
+ public override string ToString()
+ {
+ return $"AGP Aperture: {ApertureInMB}MB, Current Rate: {CurrentRate}x";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/ECCMemoryInformation.cs b/NvAPIWrapper/GPU/ECCMemoryInformation.cs
new file mode 100644
index 0000000..486182d
--- /dev/null
+++ b/NvAPIWrapper/GPU/ECCMemoryInformation.cs
@@ -0,0 +1,201 @@
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.GPU;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Contains information about the ECC memory
+ ///
+ public class ECCMemoryInformation
+ {
+ internal ECCMemoryInformation(PhysicalGPU physicalGPU)
+ {
+ PhysicalGPU = physicalGPU;
+ }
+
+ ///
+ /// Gets the number of aggregated ECC memory double bit errors
+ ///
+ public ulong AggregatedDoubleBitErrors
+ {
+ get
+ {
+ if (!IsSupported || !IsEnabled)
+ {
+ return 0;
+ }
+
+ return GPUApi.GetECCErrorInfo(PhysicalGPU.Handle).AggregatedErrors.DoubleBitErrors;
+ }
+ }
+
+
+ ///
+ /// Gets the number of aggregated ECC memory single bit errors
+ ///
+ public ulong AggregatedSingleBitErrors
+ {
+ get
+ {
+ if (!IsSupported || !IsEnabled)
+ {
+ return 0;
+ }
+
+ return GPUApi.GetECCErrorInfo(PhysicalGPU.Handle).AggregatedErrors.SingleBitErrors;
+ }
+ }
+
+ ///
+ /// Gets the ECC memory configuration in regard to how changes are applied
+ ///
+ public ECCConfiguration Configuration
+ {
+ get
+ {
+ try
+ {
+ return GPUApi.GetECCStatusInfo(PhysicalGPU.Handle).ConfigurationOptions;
+ }
+ catch
+ {
+ return ECCConfiguration.NotSupported;
+ }
+ }
+ }
+
+ ///
+ /// Gets the number of current ECC memory double bit errors
+ ///
+ public ulong CurrentDoubleBitErrors
+ {
+ get
+ {
+ if (!IsSupported || !IsEnabled)
+ {
+ return 0;
+ }
+
+ return GPUApi.GetECCErrorInfo(PhysicalGPU.Handle).CurrentErrors.DoubleBitErrors;
+ }
+ }
+
+ ///
+ /// Gets the number of current ECC memory single bit errors
+ ///
+ public ulong CurrentSingleBitErrors
+ {
+ get
+ {
+ if (!IsSupported || !IsEnabled)
+ {
+ return 0;
+ }
+
+ return GPUApi.GetECCErrorInfo(PhysicalGPU.Handle).CurrentErrors.SingleBitErrors;
+ }
+ }
+
+ ///
+ /// Gets a boolean value indicating if ECC memory error correction is enabled
+ ///
+
+ public bool IsEnabled
+ {
+ get => IsSupported &&
+ GPUApi.GetECCStatusInfo(PhysicalGPU.Handle).IsEnabled &&
+ GPUApi.GetECCConfigurationInfo(PhysicalGPU.Handle).IsEnabled;
+ }
+
+ ///
+ /// Gets a boolean value indicating if ECC memory is enabled by default
+ ///
+ public bool IsEnabledByDefault
+ {
+ get => IsSupported &&
+ GPUApi.GetECCConfigurationInfo(PhysicalGPU.Handle).IsEnabledByDefault;
+ }
+
+ ///
+ /// Gets a boolean value indicating if ECC memory is supported and available
+ ///
+ public bool IsSupported
+ {
+ get
+ {
+ try
+ {
+ return GPUApi.GetECCStatusInfo(PhysicalGPU.Handle).IsSupported;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ ///
+ /// Gets the physical GPU that this instance describes
+ ///
+ public PhysicalGPU PhysicalGPU { get; }
+
+ ///
+ public override string ToString()
+ {
+ if (!IsSupported)
+ {
+ return "[Not Supported]";
+ }
+
+ if (!IsEnabled)
+ {
+ return "[Disabled]";
+ }
+
+ return
+ $"{CurrentSingleBitErrors}, {CurrentDoubleBitErrors} ({AggregatedSingleBitErrors}, {AggregatedDoubleBitErrors})";
+ }
+
+ ///
+ /// Clears aggregated error counters.
+ ///
+ public void ClearAggregatedErrors()
+ {
+ GPUApi.ResetECCErrorInfo(PhysicalGPU.Handle, false, true);
+ }
+
+ ///
+ /// Clears current error counters.
+ ///
+ public void ClearCurrentErrors()
+ {
+ GPUApi.ResetECCErrorInfo(PhysicalGPU.Handle, true, false);
+ }
+
+ ///
+ /// Clears all error counters.
+ ///
+ public void ClearErrors()
+ {
+ GPUApi.ResetECCErrorInfo(PhysicalGPU.Handle, true, true);
+ }
+
+ ///
+ /// Disables ECC memory error correction.
+ ///
+ /// A boolean value to indicate if this change should get applied immediately
+ public void Disable(bool immediate)
+ {
+ GPUApi.SetECCConfiguration(PhysicalGPU.Handle, false, immediate);
+ }
+
+ ///
+ /// Enables ECC memory error correction.
+ ///
+ /// A boolean value to indicate if this change should get applied immediately
+ public void Enable(bool immediate)
+ {
+ GPUApi.SetECCConfiguration(PhysicalGPU.Handle, true, immediate);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUArchitectInformation.cs b/NvAPIWrapper/GPU/GPUArchitectInformation.cs
new file mode 100644
index 0000000..c489e25
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUArchitectInformation.cs
@@ -0,0 +1,115 @@
+using NvAPIWrapper.Native;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Contains physical GPU architect information
+ ///
+ public class GPUArchitectInformation
+ {
+ internal GPUArchitectInformation(PhysicalGPU physicalGPU)
+ {
+ PhysicalGPU = physicalGPU;
+ }
+
+ ///
+ /// Gets total number of cores defined for this GPU, or zero for older architectures
+ ///
+ public int NumberOfCores
+ {
+ get => (int) GPUApi.GetGPUCoreCount(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the number of graphics processing clusters (aka GPU Partitions)
+ ///
+ public int NumberOfGPC
+ {
+ get => (int) GPUApi.GetPartitionCount(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the number of render output units
+ ///
+ public int NumberOfROPs
+ {
+ get => (int) GPUApi.GetROPCount(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the number of shader pipelines
+ ///
+ public int NumberOfShaderPipelines
+ {
+ get => (int) GPUApi.GetShaderPipeCount(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the number of shader sub pipelines
+ ///
+ public int NumberOfShaderSubPipelines
+ {
+ get => (int) GPUApi.GetShaderSubPipeCount(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the number of video processing engines
+ ///
+ public int NumberOfVPEs
+ {
+ get => (int) GPUApi.GetVPECount(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the physical GPU that this instance describes
+ ///
+ public PhysicalGPU PhysicalGPU { get; }
+
+ ///
+ /// Gets the GPU revision number (should be displayed as a hex string)
+ ///
+ public int Revision
+ {
+ get => (int) GPUApi.GetArchitectInfo(PhysicalGPU.Handle).Revision;
+ }
+
+ ///
+ /// Gets the GPU short name (aka Codename)
+ ///
+ public string ShortName
+ {
+ get => GPUApi.GetShortName(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the total number of streaming multiprocessors
+ ///
+ public int TotalNumberOfSMs
+ {
+ get => (int) GPUApi.GetTotalSMCount(PhysicalGPU.Handle);
+ }
+
+
+ ///
+ /// Gets the total number of streaming processors
+ ///
+ public int TotalNumberOfSPs
+ {
+ get => (int) GPUApi.GetTotalSPCount(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the total number of texture processing clusters
+ ///
+ public int TotalNumberOfTPCs
+ {
+ get => (int) GPUApi.GetTotalTPCCount(PhysicalGPU.Handle);
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"[{ShortName} REV{Revision:X}] Cores: {NumberOfCores}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUBusInformation.cs b/NvAPIWrapper/GPU/GPUBusInformation.cs
new file mode 100644
index 0000000..4e47776
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUBusInformation.cs
@@ -0,0 +1,118 @@
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.GPU;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Contains information about the GPU bus
+ ///
+ public class GPUBusInformation
+ {
+ internal GPUBusInformation(PhysicalGPU physicalGPU)
+ {
+ PhysicalGPU = physicalGPU;
+ }
+
+ ///
+ /// Gets accelerated graphics port information
+ ///
+ public AGPInformation AGPInformation
+ {
+ get
+ {
+ if (BusType != GPUBusType.AGP)
+ {
+ return null;
+ }
+
+ return new AGPInformation(
+ GPUApi.GetAGPAperture(PhysicalGPU.Handle),
+ GPUApi.GetCurrentAGPRate(PhysicalGPU.Handle)
+ );
+ }
+ }
+
+ ///
+ /// Gets the bus identification
+ ///
+ public int BusId
+ {
+ get => GPUApi.GetBusId(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the bus slot identification
+ ///
+ public int BusSlot
+ {
+ get => GPUApi.GetBusSlotId(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the the bus type
+ ///
+ public GPUBusType BusType
+ {
+ get => GPUApi.GetBusType(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets number of PCIe lanes being used for the PCIe interface downstream
+ ///
+ public int CurrentPCIeLanes
+ {
+ get
+ {
+ if (BusType == GPUBusType.PCIExpress)
+ {
+ return GPUApi.GetCurrentPCIEDownStreamWidth(PhysicalGPU.Handle);
+ }
+
+ return 0;
+ }
+ }
+
+ ///
+ /// Gets GPU interrupt number
+ ///
+ public int IRQ
+ {
+ get => GPUApi.GetIRQ(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the PCI identifiers
+ ///
+ public PCIIdentifiers PCIIdentifiers
+ {
+ get
+ {
+ if (BusType == GPUBusType.FPCI || BusType == GPUBusType.PCI || BusType == GPUBusType.PCIExpress)
+ {
+ GPUApi.GetPCIIdentifiers(
+ PhysicalGPU.Handle,
+ out var deviceId,
+ out var subSystemId,
+ out var revisionId,
+ out var extDeviceId
+ );
+
+ return new PCIIdentifiers(deviceId, subSystemId, revisionId, (int) extDeviceId);
+ }
+
+ return null;
+ }
+ }
+
+ ///
+ /// Gets the physical GPU that this instance describes
+ ///
+ public PhysicalGPU PhysicalGPU { get; }
+
+ ///
+ public override string ToString()
+ {
+ return $"[{BusType}] Bus #{BusId}, Slot #{BusSlot}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUCooler.cs b/NvAPIWrapper/GPU/GPUCooler.cs
new file mode 100644
index 0000000..86d6816
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUCooler.cs
@@ -0,0 +1,130 @@
+using System;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Holds information regarding a GPU cooler entry
+ ///
+ public class GPUCooler
+ {
+ internal GPUCooler(int coolerId, PrivateCoolerSettingsV1.CoolerSetting coolerSetting, int currentRPM = -1)
+ {
+ CoolerId = coolerId;
+ CurrentLevel = (int) coolerSetting.CurrentLevel;
+ DefaultMinimumLevel = (int) coolerSetting.DefaultMinimumLevel;
+ DefaultMaximumLevel = (int) coolerSetting.DefaultMaximumLevel;
+ CurrentMinimumLevel = (int) coolerSetting.CurrentMinimumLevel;
+ CurrentMaximumLevel = (int) coolerSetting.CurrentMaximumLevel;
+ CoolerType = coolerSetting.CoolerType;
+ CoolerController = coolerSetting.CoolerController;
+ DefaultPolicy = coolerSetting.DefaultPolicy;
+ CurrentPolicy = coolerSetting.CurrentPolicy;
+ Target = coolerSetting.Target;
+ ControlMode = coolerSetting.ControlMode;
+ CurrentFanSpeedInRPM = currentRPM;
+ }
+
+ // ReSharper disable once TooManyDependencies
+ internal GPUCooler(
+ PrivateFanCoolersInfoV1.FanCoolersInfoEntry infoEntry,
+ PrivateFanCoolersStatusV1.FanCoolersStatusEntry statusEntry,
+ PrivateFanCoolersControlV1.FanCoolersControlEntry controlEntry)
+ {
+ if (infoEntry.CoolerId != statusEntry.CoolerId || statusEntry.CoolerId != controlEntry.CoolerId)
+ {
+ throw new ArgumentException("Passed arguments are meant to be for different coolers.");
+ }
+
+ CoolerId = (int) statusEntry.CoolerId;
+ CurrentLevel = (int) statusEntry.CurrentLevel;
+ DefaultMinimumLevel = (int) statusEntry.CurrentMinimumLevel;
+ DefaultMaximumLevel = (int) statusEntry.CurrentMaximumLevel;
+ CurrentMinimumLevel = (int) statusEntry.CurrentMinimumLevel;
+ CurrentMaximumLevel = (int) statusEntry.CurrentMaximumLevel;
+ CoolerType = CoolerType.Fan;
+ CoolerController = CoolerController.Internal;
+ DefaultPolicy = CoolerPolicy.None;
+ CurrentPolicy = controlEntry.ControlMode == FanCoolersControlMode.Manual
+ ? CoolerPolicy.Manual
+ : CoolerPolicy.None;
+ Target = CoolerTarget.All;
+ ControlMode = CoolerControlMode.Variable;
+ CurrentFanSpeedInRPM = (int) statusEntry.CurrentRPM;
+ }
+
+ ///
+ /// Gets the cooler control mode
+ ///
+ public CoolerControlMode ControlMode { get; }
+
+ ///
+ /// Gets the cooler controller
+ ///
+ public CoolerController CoolerController { get; }
+
+ ///
+ /// Gets the cooler identification number or index
+ ///
+ public int CoolerId { get; }
+
+ ///
+ /// Gets the cooler type
+ ///
+ public CoolerType CoolerType { get; }
+
+ ///
+ /// Gets the GPU fan speed in revolutions per minute
+ ///
+ public int CurrentFanSpeedInRPM { get; }
+
+ ///
+ /// Gets the cooler current level in percentage
+ ///
+ public int CurrentLevel { get; }
+
+
+ ///
+ /// Gets the cooler current maximum level in percentage
+ ///
+ public int CurrentMaximumLevel { get; }
+
+
+ ///
+ /// Gets the cooler current minimum level in percentage
+ ///
+ public int CurrentMinimumLevel { get; }
+
+ ///
+ /// Gets the cooler current policy
+ ///
+ public CoolerPolicy CurrentPolicy { get; }
+
+ ///
+ /// Gets the cooler default maximum level in percentage
+ ///
+ public int DefaultMaximumLevel { get; }
+
+ ///
+ /// Gets the cooler default minimum level in percentage
+ ///
+ public int DefaultMinimumLevel { get; }
+
+ ///
+ /// Gets the cooler default policy
+ ///
+ public CoolerPolicy DefaultPolicy { get; }
+
+ ///
+ /// Gets the cooler target
+ ///
+ public CoolerTarget Target { get; }
+
+ ///
+ public override string ToString()
+ {
+ return $"[{CoolerId} @ {CoolerController}] {Target}: {CurrentLevel}%";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUCoolerInformation.cs b/NvAPIWrapper/GPU/GPUCoolerInformation.cs
new file mode 100644
index 0000000..9be8cc8
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUCoolerInformation.cs
@@ -0,0 +1,340 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.Exceptions;
+using NvAPIWrapper.Native.General;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Contains information about the GPU coolers and current fan speed
+ ///
+ public class GPUCoolerInformation
+ {
+ internal GPUCoolerInformation(PhysicalGPU physicalGPU)
+ {
+ PhysicalGPU = physicalGPU;
+
+ // TODO: Add Support For Pascal Only Policy Table Method
+ // TODO: GPUApi.GetCoolerPolicyTable & GPUApi.SetCoolerPolicyTable & GPUApi.RestoreCoolerPolicyTable
+ // TODO: Better support of ClientFanCoolers set of APIs
+ }
+
+ ///
+ /// Gets a list of all available coolers along with their current settings and status
+ ///
+ public IEnumerable Coolers
+ {
+ get
+ {
+ PrivateCoolerSettingsV1? settings = null;
+
+ try
+ {
+ settings = GPUApi.GetCoolerSettings(PhysicalGPU.Handle);
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status != Status.NotSupported)
+ {
+ throw;
+ }
+ }
+
+ if (settings != null)
+ {
+ for (var i = 0; i < settings.Value.CoolerSettings.Length; i++)
+ {
+ if (i == 0)
+ {
+ var currentRPM = -1;
+ try
+ {
+ currentRPM = (int)GPUApi.GetTachReading(PhysicalGPU.Handle);
+ }
+ catch (NVIDIAApiException)
+ {
+ // ignored
+ }
+
+ if (currentRPM >= 0)
+ {
+ yield return new GPUCooler(
+ i,
+ settings.Value.CoolerSettings[i],
+ currentRPM
+ );
+ continue;
+ }
+ }
+
+ yield return new GPUCooler(
+ i,
+ settings.Value.CoolerSettings[i]
+ );
+ }
+
+ yield break;
+ }
+
+ PrivateFanCoolersStatusV1? status = null;
+ PrivateFanCoolersInfoV1? info = null;
+ PrivateFanCoolersControlV1? control = null;
+
+ try
+ {
+ status = GPUApi.GetClientFanCoolersStatus(PhysicalGPU.Handle);
+ info = GPUApi.GetClientFanCoolersInfo(PhysicalGPU.Handle);
+ control = GPUApi.GetClientFanCoolersControl(PhysicalGPU.Handle);
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status != Status.NotSupported)
+ {
+ throw;
+ }
+ }
+
+ if (status != null && info != null && control != null)
+ {
+ for (var i = 0; i < status.Value.FanCoolersStatusEntries.Length; i++)
+ {
+ if (info.Value.FanCoolersInfoEntries.Length > i &&
+ control.Value.FanCoolersControlEntries.Length > i)
+ {
+ yield return new GPUCooler(
+ info.Value.FanCoolersInfoEntries[i],
+ status.Value.FanCoolersStatusEntries[i],
+ control.Value.FanCoolersControlEntries[i]
+ );
+ }
+ }
+
+ yield break;
+ }
+
+ throw new NVIDIAApiException(Status.NotSupported);
+ }
+ }
+
+ ///
+ /// Gets the GPU fan speed in revolutions per minute
+ ///
+ public int CurrentFanSpeedInRPM
+ {
+ get
+ {
+ try
+ {
+ return (int) GPUApi.GetTachReading(PhysicalGPU.Handle);
+ }
+ catch
+ {
+ return Coolers.FirstOrDefault(cooler => cooler.Target == CoolerTarget.All)?.CurrentFanSpeedInRPM ??
+ 0;
+ }
+ }
+ }
+
+ ///
+ /// Gets the current fan speed in percentage if available
+ ///
+ public int CurrentFanSpeedLevel
+ {
+ get
+ {
+ try
+ {
+ return (int) GPUApi.GetCurrentFanSpeedLevel(PhysicalGPU.Handle);
+ }
+ catch
+ {
+ return Coolers.FirstOrDefault(cooler => cooler.Target == CoolerTarget.All)?.CurrentLevel ?? 0;
+ }
+ }
+ }
+
+ ///
+ /// Gets the physical GPU that this instance describes
+ ///
+ public PhysicalGPU PhysicalGPU { get; }
+
+ ///
+ public override string ToString()
+ {
+ return $"{CurrentFanSpeedInRPM} RPM ({CurrentFanSpeedLevel}%)";
+ }
+
+ ///
+ /// Resets all cooler settings to default.
+ ///
+ public void RestoreCoolerSettingsToDefault()
+ {
+ RestoreCoolerSettingsToDefault(Coolers.Select(cooler => cooler.CoolerId).ToArray());
+ }
+
+ ///
+ /// Resets one or more cooler settings to default.
+ ///
+ /// The cooler identification numbers (indexes) to reset their settings to default.
+ public void RestoreCoolerSettingsToDefault(params int[] coolerIds)
+ {
+ var availableCoolerIds = Coolers.Select(cooler => cooler.CoolerId).ToArray();
+
+ if (coolerIds.Any(i => !availableCoolerIds.Contains(i)))
+ {
+ throw new ArgumentException("Invalid cooler identification number provided.", nameof(coolerIds));
+ }
+
+ try
+ {
+ GPUApi.RestoreCoolerSettings(PhysicalGPU.Handle, coolerIds.Select(i => (uint) i).ToArray());
+
+ return;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status != Status.NotSupported)
+ {
+ throw;
+ }
+ }
+
+ var currentControl = GPUApi.GetClientFanCoolersControl(PhysicalGPU.Handle);
+ var newControl = new PrivateFanCoolersControlV1(
+ currentControl.FanCoolersControlEntries.Select(
+ entry => coolerIds.Contains((int) entry.CoolerId)
+ ? new PrivateFanCoolersControlV1.FanCoolersControlEntry(
+ entry.CoolerId,
+ FanCoolersControlMode.Auto
+ )
+ : entry
+ )
+ .ToArray(),
+ currentControl.UnknownUInt
+ );
+ GPUApi.SetClientFanCoolersControl(PhysicalGPU.Handle, newControl);
+ }
+
+ ///
+ /// Changes a cooler settings by modifying the policy and the current level
+ ///
+ /// The cooler identification number (index) to change the settings.
+ /// The new cooler policy.
+ /// The new cooler level. Valid only if policy is set to manual.
+ // ReSharper disable once TooManyDeclarations
+ public void SetCoolerSettings(int coolerId, CoolerPolicy policy, int newLevel)
+ {
+ if (Coolers.All(cooler => cooler.CoolerId != coolerId))
+ {
+ throw new ArgumentException("Invalid cooler identification number provided.", nameof(coolerId));
+ }
+
+ try
+ {
+ GPUApi.SetCoolerLevels(
+ PhysicalGPU.Handle,
+ (uint) coolerId,
+ new PrivateCoolerLevelsV1(new[]
+ {
+ new PrivateCoolerLevelsV1.CoolerLevel(policy, (uint) newLevel)
+ }
+ ),
+ 1
+ );
+
+ return;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status != Status.NotSupported)
+ {
+ throw;
+ }
+ }
+
+ var currentControl = GPUApi.GetClientFanCoolersControl(PhysicalGPU.Handle);
+ var newControl = new PrivateFanCoolersControlV1(
+ currentControl.FanCoolersControlEntries.Select(
+ entry => entry.CoolerId == coolerId
+ ? new PrivateFanCoolersControlV1.FanCoolersControlEntry(
+ entry.CoolerId,
+ policy == CoolerPolicy.Manual
+ ? FanCoolersControlMode.Manual
+ : FanCoolersControlMode.Auto,
+ policy == CoolerPolicy.Manual ? (uint)newLevel : 0u)
+ : entry
+ )
+ .ToArray(),
+ currentControl.UnknownUInt
+ );
+ GPUApi.SetClientFanCoolersControl(PhysicalGPU.Handle, newControl);
+ }
+
+ ///
+ /// Changes a cooler setting by modifying the policy
+ ///
+ /// The cooler identification number (index) to change the settings.
+ /// The new cooler policy.
+ // ReSharper disable once TooManyDeclarations
+ public void SetCoolerSettings(int coolerId, CoolerPolicy policy)
+ {
+ if (Coolers.All(cooler => cooler.CoolerId != coolerId))
+ {
+ throw new ArgumentException("Invalid cooler identification number provided.", nameof(coolerId));
+ }
+
+ try
+ {
+ GPUApi.SetCoolerLevels(
+ PhysicalGPU.Handle,
+ (uint) coolerId,
+ new PrivateCoolerLevelsV1(new[]
+ {
+ new PrivateCoolerLevelsV1.CoolerLevel(policy)
+ }
+ ),
+ 1
+ );
+
+ return;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status != Status.NotSupported)
+ {
+ throw;
+ }
+ }
+
+ var currentControl = GPUApi.GetClientFanCoolersControl(PhysicalGPU.Handle);
+ var newControl = new PrivateFanCoolersControlV1(
+ currentControl.FanCoolersControlEntries.Select(
+ entry => entry.CoolerId == coolerId
+ ? new PrivateFanCoolersControlV1.FanCoolersControlEntry(
+ entry.CoolerId,
+ policy == CoolerPolicy.Manual
+ ? FanCoolersControlMode.Manual
+ : FanCoolersControlMode.Auto)
+ : entry
+ )
+ .ToArray(),
+ currentControl.UnknownUInt
+ );
+ GPUApi.SetClientFanCoolersControl(PhysicalGPU.Handle, newControl);
+ }
+
+ ///
+ /// Changes a cooler settings by modifying the policy to manual and sets a new level
+ ///
+ /// The cooler identification number (index) to change the settings.
+ /// The new cooler level.
+ public void SetCoolerSettings(int coolerId, int newLevel)
+ {
+ SetCoolerSettings(coolerId, CoolerPolicy.Manual, newLevel);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUMemoryInformation.cs b/NvAPIWrapper/GPU/GPUMemoryInformation.cs
new file mode 100644
index 0000000..468b1e2
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUMemoryInformation.cs
@@ -0,0 +1,232 @@
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.Interfaces.GPU;
+using System;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Contains information regarding the available and total memory as well as the type of memory and other information
+ /// regarding the GPU RAM and frame buffer
+ ///
+ public class GPUMemoryInformation : IDisplayDriverMemoryInfo
+ {
+ internal GPUMemoryInformation(PhysicalGPU physicalGPU)
+ {
+ PhysicalGPU = physicalGPU;
+ }
+
+ ///
+ /// Gets the frame buffer bandwidth
+ ///
+
+ public int FrameBufferBandwidth
+ {
+ get
+ {
+ GPUApi.GetFrameBufferWidthAndLocation(PhysicalGPU.Handle, out var width, out _);
+
+ return (int)width;
+ }
+ }
+
+ ///
+ /// Gets the frame buffer location index
+ ///
+ public int FrameBufferLocation
+ {
+ get
+ {
+ GPUApi.GetFrameBufferWidthAndLocation(PhysicalGPU.Handle, out _, out var location);
+
+ return (int)location;
+ }
+ }
+
+ ///
+ /// Gets the internal clock to bus clock factor based on the type of RAM
+ ///
+ public int InternalClockToBusClockFactor
+ {
+ get => GetMemoryBusClockFactor(RAMType);
+ }
+
+ ///
+ /// Gets the internal clock to transfer rate factor based on the type of RAM
+ ///
+ public int InternalClockToTransferRateFactor
+ {
+ get => GetMemoryTransferRateFactor(RAMType);
+ }
+
+ ///
+ /// Gets GPU physical frame buffer size in KB. This does NOT include any system RAM that may be dedicated for use by
+ /// the GPU.
+ ///
+ public int PhysicalFrameBufferSizeInkB
+ {
+ get => GPUApi.GetPhysicalFrameBufferSize(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the physical GPU that this instance describes
+ ///
+ public PhysicalGPU PhysicalGPU { get; }
+
+ ///
+ /// Gets the number of memory banks
+ ///
+ public uint RAMBanks
+ {
+ get => GPUApi.GetRAMBankCount(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the memory bus width
+ ///
+ public uint RAMBusWidth
+ {
+ get => GPUApi.GetRAMBusWidth(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the memory maker (brand)
+ ///
+ public GPUMemoryMaker RAMMaker
+ {
+ get => GPUApi.GetRAMMaker(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the memory type
+ ///
+ public GPUMemoryType RAMType
+ {
+ get => GPUApi.GetRAMType(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets virtual size of frame-buffer in KB for this GPU. This includes the physical RAM plus any system RAM that has
+ /// been dedicated for use by the GPU.
+ ///
+ public int VirtualFrameBufferSizeInkB
+ {
+ get => GPUApi.GetVirtualFrameBufferSize(PhysicalGPU.Handle);
+ }
+
+ ///
+ public uint AvailableDedicatedVideoMemoryInkB
+ {
+ get => GPUApi.GetMemoryInfo(PhysicalGPU.Handle).AvailableDedicatedVideoMemoryInkB;
+ }
+
+ ///
+ public uint CurrentAvailableDedicatedVideoMemoryInkB
+ {
+ get => GPUApi.GetMemoryInfo(PhysicalGPU.Handle).CurrentAvailableDedicatedVideoMemoryInkB;
+ }
+
+ ///
+ public uint DedicatedVideoMemoryInkB
+ {
+ get => GPUApi.GetMemoryInfo(PhysicalGPU.Handle).DedicatedVideoMemoryInkB;
+ }
+
+ ///
+ public uint SharedSystemMemoryInkB
+ {
+ get => GPUApi.GetMemoryInfo(PhysicalGPU.Handle).SharedSystemMemoryInkB;
+ }
+
+ ///
+ public uint SystemVideoMemoryInkB
+ {
+ get => GPUApi.GetMemoryInfo(PhysicalGPU.Handle).SystemVideoMemoryInkB;
+ }
+
+ ///
+ /// Gets the memory bus clock to internal memory clock factor
+ ///
+ ///
+ /// The value of X in X(InternalMemoryClock)=(BusMemoryClock)
+ public static int GetMemoryBusClockFactor(GPUMemoryType memoryType)
+ {
+ switch (memoryType)
+ {
+ case GPUMemoryType.SDRAM:
+
+ // Bus Clocks Per Internal Clock = 1
+ return 1;
+ case GPUMemoryType.DDR1:
+ case GPUMemoryType.DDR2:
+ case GPUMemoryType.DDR3:
+ case GPUMemoryType.GDDR2:
+ case GPUMemoryType.GDDR3:
+ case GPUMemoryType.GDDR4:
+ case GPUMemoryType.LPDDR2:
+ case GPUMemoryType.GDDR5:
+ case GPUMemoryType.GDDR5X:
+ case GPUMemoryType.GDDR6:
+ case GPUMemoryType.GDDR6X:
+
+ // Bus Clocks Per Internal Clock = 2
+ return 2;
+ default:
+
+ throw new ArgumentOutOfRangeException(nameof(memoryType));
+ }
+ }
+
+ ///
+ /// Gets the number of transfers per internal memory clock factor
+ ///
+ ///
+ /// The value of X in X(InternalMemoryClock)=(OperationsPerSecond)
+ public static int GetMemoryTransferRateFactor(GPUMemoryType memoryType)
+ {
+ switch (memoryType)
+ {
+ case GPUMemoryType.SDRAM:
+
+ // Transfers Per Internal Clock = 1
+ return 1;
+ case GPUMemoryType.DDR1:
+ case GPUMemoryType.DDR2:
+ case GPUMemoryType.DDR3:
+ case GPUMemoryType.GDDR2:
+ case GPUMemoryType.GDDR3:
+ case GPUMemoryType.GDDR4:
+ case GPUMemoryType.LPDDR2:
+
+ // Transfers Per Internal Clock = 1
+ return 2;
+ case GPUMemoryType.GDDR5:
+
+ // Transfers Per Internal Clock = 2
+ return 4;
+ case GPUMemoryType.GDDR5X:
+
+ // Transfers Per Internal Clock = 4
+ return 8;
+ case GPUMemoryType.GDDR6:
+
+ // Transfers Per Internal Clock = 2
+ return 4;
+ case GPUMemoryType.GDDR6X:
+
+ // Transfers Per Internal Clock = 4
+ return 8;
+ default:
+
+ throw new ArgumentOutOfRangeException(nameof(memoryType));
+ }
+ }
+
+ ///
+ public override string ToString()
+ {
+ return
+ $"[{RAMMaker} {RAMType}] Total: {AvailableDedicatedVideoMemoryInkB:N0} kB - Available: {CurrentAvailableDedicatedVideoMemoryInkB:N0} kB";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUOutput.cs b/NvAPIWrapper/GPU/GPUOutput.cs
new file mode 100644
index 0000000..c9fb3b0
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUOutput.cs
@@ -0,0 +1,264 @@
+using System;
+using NvAPIWrapper.Display;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.Exceptions;
+using NvAPIWrapper.Native.General;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Represents a single GPU output
+ ///
+ public class GPUOutput : IEquatable
+ {
+ internal GPUOutput(OutputId outputId, PhysicalGPUHandle gpuHandle)
+ {
+ OutputId = outputId;
+ OutputType = !gpuHandle.IsNull ? GPUApi.GetOutputType(gpuHandle, outputId) : OutputType.Unknown;
+ PhysicalGPU = new PhysicalGPU(gpuHandle);
+ }
+
+ internal GPUOutput(OutputId outputId, PhysicalGPU gpu)
+ : this(outputId, gpu?.Handle ?? PhysicalGPUHandle.DefaultHandle)
+ {
+ PhysicalGPU = gpu;
+ }
+
+ ///
+ /// Gets the corresponding Digital Vibrance Control information
+ ///
+ public DVCInformation DigitalVibranceControl
+ {
+ get => new DVCInformation(OutputId);
+ }
+
+ ///
+ /// Gets the corresponding HUE information
+ ///
+ public HUEInformation HUEControl
+ {
+ get => new HUEInformation(OutputId);
+ }
+
+ ///
+ /// Gets the output identification as a single bit unsigned integer
+ ///
+ public OutputId OutputId { get; }
+
+ ///
+ /// Gets the output type
+ ///
+ public OutputType OutputType { get; }
+
+ ///
+ /// Gets the corresponding physical GPU
+ ///
+ public PhysicalGPU PhysicalGPU { get; }
+
+ ///
+ public bool Equals(GPUOutput other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return PhysicalGPU.Equals(other.PhysicalGPU) && OutputId == other.OutputId;
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(GPUOutput left, GPUOutput right)
+ {
+ return right?.Equals(left) ?? ReferenceEquals(left, null);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(GPUOutput left, GPUOutput right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((GPUOutput) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return ((PhysicalGPU != null ? PhysicalGPU.GetHashCode() : 0) * 397) ^ (int) OutputId;
+ }
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"{OutputId} {OutputType} @ {PhysicalGPU}";
+ }
+
+ ///
+ /// Overrides the refresh rate on this output.
+ /// The new refresh rate can be applied right away or deferred to be applied with the next OS
+ /// mode-set.
+ /// The override is good for only one mode-set (regardless whether it's deferred or immediate).
+ ///
+ /// The refresh rate to be applied.
+ ///
+ /// A boolean value indicating if the refresh rate override should be deferred to the next OS
+ /// mode-set.
+ ///
+ public void OverrideRefreshRate(float refreshRate, bool isDeferred = false)
+ {
+ DisplayApi.SetRefreshRateOverride(OutputId, refreshRate, isDeferred);
+ }
+
+ ///
+ /// Reads data from the I2C bus
+ ///
+ /// The port id on which device is connected
+ /// A boolean value indicating that the DDC port should be used instead of the communication port
+ /// The device I2C slave address
+ /// The target I2C register address
+ /// The length of the buffer to allocate for the read operation.
+ /// The target speed of the transaction in kHz
+ public byte[] ReadI2C(
+ byte? portId,
+ bool useDDCPort,
+ byte deviceAddress,
+ byte[] registerAddress,
+ uint readDataLength,
+ I2CSpeed speed = I2CSpeed.Default
+ )
+ {
+ try
+ {
+ // ReSharper disable once InconsistentNaming
+ var i2cInfoV3 = new I2CInfoV3(
+ OutputId,
+ portId,
+ useDDCPort,
+ deviceAddress,
+ registerAddress,
+ readDataLength,
+ speed
+ );
+
+ return PhysicalGPU.ReadI2C(i2cInfoV3);
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status != Status.IncompatibleStructureVersion || portId != null)
+ {
+ throw;
+ }
+
+ // ignore
+ }
+
+ // ReSharper disable once InconsistentNaming
+ var i2cInfoV2 = new I2CInfoV2(
+ OutputId,
+ useDDCPort,
+ deviceAddress,
+ registerAddress,
+ readDataLength,
+ speed
+ );
+
+ return PhysicalGPU.ReadI2C(i2cInfoV2);
+ }
+
+ ///
+ /// Writes data to the I2C bus
+ ///
+ /// The port id on which device is connected
+ /// A boolean value indicating that the DDC port should be used instead of the communication port
+ /// The device I2C slave address
+ /// The target I2C register address
+ /// The payload data
+ /// The target speed of the transaction in kHz
+ public void WriteI2C(
+ byte? portId,
+ bool useDDCPort,
+ byte deviceAddress,
+ byte[] registerAddress,
+ byte[] data,
+ I2CSpeed speed = I2CSpeed.Default
+ )
+ {
+ try
+ {
+ // ReSharper disable once InconsistentNaming
+ var i2cInfoV3 = new I2CInfoV3(
+ OutputId,
+ portId,
+ useDDCPort,
+ deviceAddress,
+ registerAddress,
+ data,
+ speed
+ );
+
+ PhysicalGPU.WriteI2C(i2cInfoV3);
+
+ return;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status != Status.IncompatibleStructureVersion || portId != null)
+ {
+ throw;
+ }
+
+ // ignore
+ }
+
+ // ReSharper disable once InconsistentNaming
+ var i2cInfoV2 = new I2CInfoV2(
+ OutputId,
+ useDDCPort,
+ deviceAddress,
+ registerAddress,
+ data,
+ speed
+ );
+
+ PhysicalGPU.WriteI2C(i2cInfoV2);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUPerformanceControl.cs b/NvAPIWrapper/GPU/GPUPerformanceControl.cs
new file mode 100644
index 0000000..6174cf8
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUPerformanceControl.cs
@@ -0,0 +1,124 @@
+using System.Collections.Generic;
+using System.Linq;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.GPU;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Contains information regarding the GPU performance control and limitations
+ ///
+ public class GPUPerformanceControl
+ {
+ internal GPUPerformanceControl(PhysicalGPU physicalGPU)
+ {
+ PhysicalGPU = physicalGPU;
+ }
+
+ ///
+ /// Gets the current active performance limitation
+ ///
+ public PerformanceLimit CurrentActiveLimit
+ {
+ get => GPUApi.PerformancePoliciesGetStatus(PhysicalGPU.Handle).PerformanceLimit;
+ }
+
+ ///
+ /// Gets the current performance decrease reason
+ ///
+ public PerformanceDecreaseReason CurrentPerformanceDecreaseReason
+ {
+ get => GPUApi.GetPerformanceDecreaseInfo(PhysicalGPU.Handle);
+ }
+
+
+ ///
+ /// Gets a boolean value indicating if no load limit is supported with this GPU
+ ///
+ public bool IsNoLoadLimitSupported
+ {
+ get => GPUApi.PerformancePoliciesGetInfo(PhysicalGPU.Handle).IsNoLoadLimitSupported;
+ }
+
+
+ ///
+ /// Gets a boolean value indicating if power limit is supported with this GPU
+ ///
+ public bool IsPowerLimitSupported
+ {
+ get => GPUApi.PerformancePoliciesGetInfo(PhysicalGPU.Handle).IsPowerLimitSupported;
+ }
+
+
+ ///
+ /// Gets a boolean value indicating if temperature limit is supported with this GPU
+ ///
+ public bool IsTemperatureLimitSupported
+ {
+ get => GPUApi.PerformancePoliciesGetInfo(PhysicalGPU.Handle).IsTemperatureLimitSupported;
+ }
+
+ ///
+ /// Gets a boolean value indicating if voltage limit is supported with this GPU
+ ///
+ public bool IsVoltageLimitSupported
+ {
+ get => GPUApi.PerformancePoliciesGetInfo(PhysicalGPU.Handle).IsVoltageLimitSupported;
+ }
+
+ ///
+ /// Gets the physical GPU that this instance describes
+ ///
+ public PhysicalGPU PhysicalGPU { get; }
+
+ ///
+ /// Gets information regarding possible power limit policies and their acceptable range
+ ///
+ public IEnumerable PowerLimitInformation
+ {
+ get
+ {
+ return GPUApi.ClientPowerPoliciesGetInfo(PhysicalGPU.Handle).PowerPolicyInfoEntries
+ .Select(entry => new GPUPowerLimitInfo(entry));
+ }
+ }
+
+ ///
+ /// Gets the current active power limit policies
+ ///
+ public IEnumerable PowerLimitPolicies
+ {
+ get
+ {
+ // TODO: GPUApi.ClientPowerPoliciesSetStatus();
+ return GPUApi.ClientPowerPoliciesGetStatus(PhysicalGPU.Handle).PowerPolicyStatusEntries
+ .Select(entry => new GPUPowerLimitPolicy(entry));
+ }
+ }
+
+ ///
+ /// Gets information regarding possible thermal limit policies and their acceptable range
+ ///
+ public IEnumerable ThermalLimitInformation
+ {
+ get
+ {
+ return GPUApi.GetThermalPoliciesInfo(PhysicalGPU.Handle).ThermalPoliciesInfoEntries
+ .Select(entry => new GPUThermalLimitInfo(entry));
+ }
+ }
+
+ ///
+ /// Gets the current active thermal limit policies
+ ///
+ public IEnumerable ThermalLimitPolicies
+ {
+ get
+ {
+ // TODO: GPUApi.SetThermalPoliciesStatus();
+ return GPUApi.GetThermalPoliciesStatus(PhysicalGPU.Handle).ThermalPoliciesStatusEntries
+ .Select(entry => new GPUThermalLimitPolicy(entry));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUPerformanceState.cs b/NvAPIWrapper/GPU/GPUPerformanceState.cs
new file mode 100644
index 0000000..8344dad
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUPerformanceState.cs
@@ -0,0 +1,70 @@
+using System.Linq;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.Interfaces.GPU;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Represents a performance state
+ ///
+ public class GPUPerformanceState
+ {
+ // ReSharper disable once TooManyDependencies
+ internal GPUPerformanceState(
+ int index,
+ IPerformanceState20 performanceState,
+ IPerformanceStates20ClockEntry[] statesClockEntries,
+ IPerformanceStates20VoltageEntry[] baseVoltageEntries,
+ PCIeInformation pcieInformation)
+ {
+ StateIndex = index;
+ StateId = performanceState.StateId;
+ IsReadOnly = !performanceState.IsEditable;
+ Clocks = statesClockEntries.Select(entry => new GPUPerformanceStateClock(entry)).ToArray();
+ Voltages = baseVoltageEntries.Select(entry => new GPUPerformanceStateVoltage(entry)).ToArray();
+ PCIeInformation = pcieInformation;
+ }
+
+ ///
+ /// Gets a list of clocks associated with this performance state
+ ///
+
+ public GPUPerformanceStateClock[] Clocks { get; }
+
+ ///
+ /// Gets a boolean value indicating if this performance state is readonly
+ ///
+ public bool IsReadOnly { get; }
+
+ ///
+ /// Gets the PCI-e information regarding this performance state.
+ ///
+ public PCIeInformation PCIeInformation { get; }
+
+ ///
+ /// Gets the performance state identification
+ ///
+ public PerformanceStateId StateId { get; }
+
+ ///
+ /// Gets the state index
+ ///
+ public int StateIndex { get; }
+
+ ///
+ /// Gets a list of voltages associated with this performance state
+ ///
+ public GPUPerformanceStateVoltage[] Voltages { get; }
+
+ ///
+ public override string ToString()
+ {
+ if (IsReadOnly)
+ {
+ return $"{StateId} (ReadOnly)";
+ }
+
+ return StateId.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUPerformanceStateClock.cs b/NvAPIWrapper/GPU/GPUPerformanceStateClock.cs
new file mode 100644
index 0000000..e8afe07
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUPerformanceStateClock.cs
@@ -0,0 +1,99 @@
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.Interfaces.GPU;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Represents a performance state clock settings
+ ///
+ public class GPUPerformanceStateClock
+ {
+ internal GPUPerformanceStateClock(IPerformanceStates20ClockEntry states20ClockEntry)
+ {
+ ClockDomain = states20ClockEntry.DomainId;
+ IsReadOnly = !states20ClockEntry.IsEditable;
+ ClockDeltaInkHz = states20ClockEntry.FrequencyDeltaInkHz.DeltaValue;
+ ClockDeltaRangeInkHz = new GPUPerformanceStateValueRange(
+ states20ClockEntry.FrequencyDeltaInkHz.DeltaRange.Minimum,
+ states20ClockEntry.FrequencyDeltaInkHz.DeltaRange.Maximum
+ );
+
+ if (states20ClockEntry.ClockType == PerformanceStates20ClockType.Range)
+ {
+ CurrentClockInkHz = new GPUPerformanceStateValueRange(
+ states20ClockEntry.FrequencyRange.MinimumFrequencyInkHz,
+ states20ClockEntry.FrequencyRange.MaximumFrequencyInkHz
+ );
+ BaseClockInkHz = new GPUPerformanceStateValueRange(
+ CurrentClockInkHz.Minimum - ClockDeltaInkHz,
+ CurrentClockInkHz.Maximum - ClockDeltaInkHz
+ );
+ DependentVoltageDomain = states20ClockEntry.FrequencyRange.VoltageDomainId;
+ DependentVoltageRangeInMicroVolt = new GPUPerformanceStateValueRange(
+ states20ClockEntry.FrequencyRange.MinimumVoltageInMicroVolt,
+ states20ClockEntry.FrequencyRange.MaximumVoltageInMicroVolt
+ );
+ }
+ else
+ {
+ CurrentClockInkHz = new GPUPerformanceStateValueRange(
+ states20ClockEntry.SingleFrequency.FrequencyInkHz
+ );
+ BaseClockInkHz = new GPUPerformanceStateValueRange(
+ CurrentClockInkHz.Minimum - ClockDeltaInkHz
+ );
+ DependentVoltageDomain = PerformanceVoltageDomain.Undefined;
+ DependentVoltageRangeInMicroVolt = null;
+ }
+ }
+
+ ///
+ /// Gets the base clock frequency in kHz
+ ///
+ public GPUPerformanceStateValueRange BaseClockInkHz { get; }
+
+ ///
+ /// Gets the clock frequency delta in kHz
+ ///
+ public int ClockDeltaInkHz { get; }
+
+ ///
+ /// Gets the clock frequency delta range in kHz
+ ///
+ public GPUPerformanceStateValueRange ClockDeltaRangeInkHz { get; }
+
+ ///
+ /// Gets the clock domain
+ ///
+ public PublicClockDomain ClockDomain { get; }
+
+ ///
+ /// Gets the current clock frequency in kHz
+ ///
+ public GPUPerformanceStateValueRange CurrentClockInkHz { get; }
+
+ ///
+ /// Gets the dependent voltage domain
+ ///
+ public PerformanceVoltageDomain DependentVoltageDomain { get; }
+
+ ///
+ /// Gets the dependent voltage range in uV
+ ///
+ public GPUPerformanceStateValueRange DependentVoltageRangeInMicroVolt { get; }
+
+ ///
+ /// Gets a boolean value indicating if this clock setting is readonly
+ ///
+ public bool IsReadOnly { get; }
+
+ ///
+ public override string ToString()
+ {
+ var title = IsReadOnly ? $"{ClockDomain} (ReadOnly)" : ClockDomain.ToString();
+
+ return
+ $"{title}: {BaseClockInkHz} + ({ClockDeltaInkHz}) = {CurrentClockInkHz}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUPerformanceStateValueRange.cs b/NvAPIWrapper/GPU/GPUPerformanceStateValueRange.cs
new file mode 100644
index 0000000..c396575
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUPerformanceStateValueRange.cs
@@ -0,0 +1,115 @@
+using System;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Represents an integer value range
+ ///
+ public class GPUPerformanceStateValueRange : IEquatable
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The lower bound of the range.
+ /// The upper bound of the range.
+ public GPUPerformanceStateValueRange(long min, long max)
+ {
+ Minimum = min;
+ Maximum = max;
+ }
+
+ ///
+ /// Creates a new single value instance of .
+ ///
+ /// The only value in the range
+ public GPUPerformanceStateValueRange(long value)
+ {
+ Minimum = value;
+ Maximum = value;
+ }
+
+ ///
+ /// Gets the upper bound of the inclusive range
+ ///
+ public long Maximum { get; }
+
+ ///
+ /// Gets the lower bound of the inclusive range
+ ///
+ public long Minimum { get; }
+
+ ///
+ public bool Equals(GPUPerformanceStateValueRange other)
+ {
+ if (other == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return Maximum == other.Maximum && Minimum == other.Minimum;
+ }
+
+ ///
+ /// Checks two instances of for equality.
+ ///
+ /// The left side of the comparison.
+ /// The right side of the comparison.
+ /// true if instances are equal, otherwise false
+ public static bool operator ==(GPUPerformanceStateValueRange left, GPUPerformanceStateValueRange right)
+ {
+ return Equals(left, right) || left?.Equals(right) == true;
+ }
+
+ ///
+ /// Checks two instances of for inequality.
+ ///
+ /// The left side of the comparison.
+ /// The right side of the comparison.
+ /// true if instances are in-equal, otherwise false
+ public static bool operator !=(GPUPerformanceStateValueRange left, GPUPerformanceStateValueRange right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ return Equals(obj as GPUPerformanceStateValueRange);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return ((int) Maximum * 397) ^ (int) Minimum;
+ }
+ }
+
+ ///
+ public override string ToString()
+ {
+ if (Minimum == Maximum)
+ {
+ return $"({Minimum})";
+ }
+
+ return $"[({Minimum}) - ({Maximum})]";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUPerformanceStateVoltage.cs b/NvAPIWrapper/GPU/GPUPerformanceStateVoltage.cs
new file mode 100644
index 0000000..97257b9
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUPerformanceStateVoltage.cs
@@ -0,0 +1,65 @@
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.Interfaces.GPU;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Represents a performance state voltage settings
+ ///
+ public class GPUPerformanceStateVoltage
+ {
+ internal GPUPerformanceStateVoltage(IPerformanceStates20VoltageEntry states20BaseVoltageEntry)
+ {
+ VoltageDomain = states20BaseVoltageEntry.DomainId;
+ IsReadOnly = !states20BaseVoltageEntry.IsEditable;
+
+ CurrentVoltageInMicroVolt = states20BaseVoltageEntry.ValueInMicroVolt;
+ VoltageDeltaInMicroVolt = states20BaseVoltageEntry.ValueDeltaInMicroVolt.DeltaValue;
+ BaseVoltageInMicroVolt = (int) (CurrentVoltageInMicroVolt - VoltageDeltaInMicroVolt);
+
+ VoltageDeltaRangeInMicroVolt = new GPUPerformanceStateValueRange(
+ states20BaseVoltageEntry.ValueDeltaInMicroVolt.DeltaRange.Minimum,
+ states20BaseVoltageEntry.ValueDeltaInMicroVolt.DeltaRange.Maximum
+ );
+ }
+
+ ///
+ /// Gets the base voltage in uV
+ ///
+ public int BaseVoltageInMicroVolt { get; }
+
+ ///
+ /// Gets the current voltage in uV
+ ///
+ public uint CurrentVoltageInMicroVolt { get; }
+
+ ///
+ /// Gets a boolean value indicating if this voltage is readonly
+ ///
+ public bool IsReadOnly { get; }
+
+ ///
+ /// Gets the voltage delta in uV
+ ///
+ public int VoltageDeltaInMicroVolt { get; }
+
+ ///
+ /// Gets the voltage delta range in uV
+ ///
+ public GPUPerformanceStateValueRange VoltageDeltaRangeInMicroVolt { get; }
+
+ ///
+ /// Gets the voltage domain
+ ///
+ public PerformanceVoltageDomain VoltageDomain { get; }
+
+ ///
+ public override string ToString()
+ {
+ var title = IsReadOnly ? $"{VoltageDomain} (ReadOnly)" : VoltageDomain.ToString();
+
+ return
+ $"{title}: ({BaseVoltageInMicroVolt}) + ({VoltageDeltaInMicroVolt}) = ({CurrentVoltageInMicroVolt})";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUPerformanceStatesInfo.cs b/NvAPIWrapper/GPU/GPUPerformanceStatesInfo.cs
new file mode 100644
index 0000000..7c26789
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUPerformanceStatesInfo.cs
@@ -0,0 +1,107 @@
+using System.Collections.Generic;
+using System.Linq;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+using NvAPIWrapper.Native.Interfaces.GPU;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Holds the retrieved performance states information
+ ///
+ public class GPUPerformanceStatesInformation
+ {
+ internal GPUPerformanceStatesInformation(
+ IPerformanceStates20Info states20Info,
+ PerformanceStateId currentPerformanceStateId,
+ PrivatePCIeInfoV2? pciInformation)
+ {
+ IsReadOnly = !states20Info.IsEditable;
+
+ GlobalVoltages = states20Info.GeneralVoltages
+ .Select(entry => new GPUPerformanceStateVoltage(entry))
+ .ToArray();
+
+ var clocks = states20Info.Clocks;
+ var baseVoltages = states20Info.Voltages;
+
+ PerformanceStates = states20Info.PerformanceStates.Select((state20, i) =>
+ {
+ PCIeInformation statePCIeInfo = null;
+
+ if (pciInformation != null && pciInformation.Value.PCIePerformanceStateInfos.Length > i)
+ {
+ statePCIeInfo = new PCIeInformation(pciInformation.Value.PCIePerformanceStateInfos[i]);
+ }
+
+ return new GPUPerformanceState(
+ i,
+ state20,
+ clocks[state20.StateId],
+ baseVoltages[state20.StateId],
+ statePCIeInfo
+ );
+ }).ToArray();
+
+ CurrentPerformanceState =
+ PerformanceStates.FirstOrDefault(performanceState =>
+ performanceState.StateId == currentPerformanceStateId);
+ }
+
+ ///
+ /// Gets the currently active performance state
+ ///
+ public GPUPerformanceState CurrentPerformanceState { get; }
+
+ ///
+ /// Gets a list of global voltage settings
+ ///
+ public GPUPerformanceStateVoltage[] GlobalVoltages { get; }
+
+ ///
+ /// Gets a boolean value indicating if performance states are readonly
+ ///
+ public bool IsReadOnly { get; }
+
+ ///
+ /// Gets a list of all available performance states
+ ///
+ public GPUPerformanceState[] PerformanceStates { get; }
+
+ ///
+ public override string ToString()
+ {
+ if (PerformanceStates.Length == 0)
+ {
+ return "No Performance State Available";
+ }
+
+ return string.Join(
+ ", ",
+ PerformanceStates
+ .Select(
+ state =>
+ {
+ var attributes = new List();
+
+ if (state.IsReadOnly)
+ {
+ attributes.Add("ReadOnly");
+ }
+
+ if (CurrentPerformanceState.StateId == state.StateId)
+ {
+ attributes.Add("Active");
+ }
+
+ if (attributes.Any())
+ {
+ return $"{state.StateId} ({string.Join(" - ", attributes)})";
+ }
+
+ return state.StateId.ToString();
+ })
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUPowerLimitInfo.cs b/NvAPIWrapper/GPU/GPUPowerLimitInfo.cs
new file mode 100644
index 0000000..41a0173
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUPowerLimitInfo.cs
@@ -0,0 +1,70 @@
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Holds information regarding a possible power limit policy and its acceptable range
+ ///
+ public class GPUPowerLimitInfo
+ {
+ internal GPUPowerLimitInfo(PrivatePowerPoliciesInfoV1.PowerPolicyInfoEntry powerPolicyInfoEntry)
+ {
+ PerformanceStateId = powerPolicyInfoEntry.PerformanceStateId;
+ MinimumPowerInPCM = powerPolicyInfoEntry.MinimumPowerInPCM;
+ DefaultPowerInPCM = powerPolicyInfoEntry.DefaultPowerInPCM;
+ MaximumPowerInPCM = powerPolicyInfoEntry.MaximumPowerInPCM;
+ }
+
+ ///
+ /// Gets the default policy target power in per cent mille (PCM)
+ ///
+ public uint DefaultPowerInPCM { get; }
+
+ ///
+ /// Gets the default policy target power in percentage
+ ///
+ public float DefaultPowerInPercent
+ {
+ get => DefaultPowerInPCM / 1000f;
+ }
+
+ ///
+ /// Gets the maximum possible policy target power in per cent mille (PCM)
+ ///
+ public uint MaximumPowerInPCM { get; }
+
+ ///
+ /// Gets the maximum possible policy target power in percentage
+ ///
+ public float MaximumPowerInPercent
+ {
+ get => MaximumPowerInPCM / 1000f;
+ }
+
+ ///
+ /// Gets the minimum possible policy target power in per cent mille (PCM)
+ ///
+ public uint MinimumPowerInPCM { get; }
+
+ ///
+ /// Gets the minimum possible policy target power in percentage
+ ///
+ public float MinimumPowerInPercent
+ {
+ get => MinimumPowerInPCM / 1000f;
+ }
+
+ ///
+ /// Gets the corresponding performance state identification
+ ///
+ public PerformanceStateId PerformanceStateId { get; }
+
+ ///
+ public override string ToString()
+ {
+ return
+ $"[{PerformanceStateId}] Default: {DefaultPowerInPercent}% - Range: ({MinimumPowerInPercent}% - {MaximumPowerInPercent}%)";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUPowerLimitPolicy.cs b/NvAPIWrapper/GPU/GPUPowerLimitPolicy.cs
new file mode 100644
index 0000000..3b18cdd
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUPowerLimitPolicy.cs
@@ -0,0 +1,41 @@
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Holds information regarding a currently active power limit policy
+ ///
+ public class GPUPowerLimitPolicy
+ {
+ internal GPUPowerLimitPolicy(PrivatePowerPoliciesStatusV1.PowerPolicyStatusEntry powerPolicyStatusEntry)
+ {
+ PerformanceStateId = powerPolicyStatusEntry.PerformanceStateId;
+ PowerTargetInPCM = powerPolicyStatusEntry.PowerTargetInPCM;
+ }
+
+ ///
+ /// Gets the corresponding performance state identification
+ ///
+ public PerformanceStateId PerformanceStateId { get; }
+
+ ///
+ /// Gets the current policy target power in per cent mille (PCM)
+ ///
+ public uint PowerTargetInPCM { get; }
+
+ ///
+ /// Gets the current policy target power in percentage
+ ///
+ public float PowerTargetInPercent
+ {
+ get => PowerTargetInPCM / 1000f;
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"{PerformanceStateId} Target: {PowerTargetInPercent}%";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUPowerTopologyInformation.cs b/NvAPIWrapper/GPU/GPUPowerTopologyInformation.cs
new file mode 100644
index 0000000..9c61385
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUPowerTopologyInformation.cs
@@ -0,0 +1,34 @@
+using System.Collections.Generic;
+using System.Linq;
+using NvAPIWrapper.Native;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Holds information regarding current power topology and their current power usage
+ ///
+ public class GPUPowerTopologyInformation
+ {
+ internal GPUPowerTopologyInformation(PhysicalGPU physicalGPU)
+ {
+ PhysicalGPU = physicalGPU;
+ }
+
+ ///
+ /// Gets the physical GPU that this instance describes
+ ///
+ public PhysicalGPU PhysicalGPU { get; }
+
+ ///
+ /// Gets the current power topology entries
+ ///
+ public IEnumerable PowerTopologyEntries
+ {
+ get
+ {
+ return GPUApi.ClientPowerTopologyGetStatus(PhysicalGPU.Handle).PowerPolicyStatusEntries
+ .Select(entry => new GPUPowerTopologyStatus(entry));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUPowerTopologyStatus.cs b/NvAPIWrapper/GPU/GPUPowerTopologyStatus.cs
new file mode 100644
index 0000000..54849ca
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUPowerTopologyStatus.cs
@@ -0,0 +1,42 @@
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Contains information about a power domain usage
+ ///
+ public class GPUPowerTopologyStatus
+ {
+ internal GPUPowerTopologyStatus(
+ PrivatePowerTopologiesStatusV1.PowerTopologiesStatusEntry powerTopologiesStatusEntry)
+ {
+ Domain = powerTopologiesStatusEntry.Domain;
+ PowerUsageInPCM = powerTopologiesStatusEntry.PowerUsageInPCM;
+ }
+
+ ///
+ /// Gets the power usage domain
+ ///
+ public PowerTopologyDomain Domain { get; }
+
+ ///
+ /// Gets the current power usage in per cent mille (PCM)
+ ///
+ public uint PowerUsageInPCM { get; }
+
+ ///
+ /// Gets the current power usage in percentage
+ ///
+ public float PowerUsageInPercent
+ {
+ get => PowerUsageInPCM / 1000f;
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"[{Domain}] {PowerUsageInPercent}%";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUThermalInformation.cs b/NvAPIWrapper/GPU/GPUThermalInformation.cs
new file mode 100644
index 0000000..ea20cb7
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUThermalInformation.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using System.Linq;
+using NvAPIWrapper.Native;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Holds information regarding the available thermal sensors and current thermal level of a GPU
+ ///
+ public class GPUThermalInformation
+ {
+ internal GPUThermalInformation(PhysicalGPU physicalGPU)
+ {
+ PhysicalGPU = physicalGPU;
+ }
+
+ ///
+ /// Gets the current thermal level of the GPU
+ ///
+ public int CurrentThermalLevel
+ {
+ get => (int) GPUApi.GetCurrentThermalLevel(PhysicalGPU.Handle);
+ }
+
+ ///
+ /// Gets the physical GPU that this instance describes
+ ///
+ public PhysicalGPU PhysicalGPU { get; }
+
+ ///
+ /// Gets the list of available thermal sensors
+ ///
+ public IEnumerable ThermalSensors
+ {
+ get
+ {
+ return GPUApi.GetThermalSettings(PhysicalGPU.Handle).Sensors
+ .Select((sensor, i) => new GPUThermalSensor(i, sensor));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUThermalLimitInfo.cs b/NvAPIWrapper/GPU/GPUThermalLimitInfo.cs
new file mode 100644
index 0000000..510c80b
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUThermalLimitInfo.cs
@@ -0,0 +1,47 @@
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Holds information regarding a possible thermal limit policy and its acceptable range
+ ///
+ public class GPUThermalLimitInfo
+ {
+ internal GPUThermalLimitInfo(PrivateThermalPoliciesInfoV2.ThermalPoliciesInfoEntry policiesInfoEntry)
+ {
+ Controller = policiesInfoEntry.Controller;
+ MinimumTemperature = policiesInfoEntry.MinimumTemperature;
+ DefaultTemperature = policiesInfoEntry.DefaultTemperature;
+ MaximumTemperature = policiesInfoEntry.MaximumTemperature;
+ }
+
+ ///
+ /// Gets the policy's thermal controller
+ ///
+ public ThermalController Controller { get; }
+
+ ///
+ /// Gets the default policy target temperature in degree Celsius
+ ///
+ public int DefaultTemperature { get; }
+
+
+ ///
+ /// Gets the maximum possible policy target temperature in degree Celsius
+ ///
+ public int MaximumTemperature { get; }
+
+ ///
+ /// Gets the minimum possible policy target temperature in degree Celsius
+ ///
+ public int MinimumTemperature { get; }
+
+ ///
+ public override string ToString()
+ {
+ return
+ $"[{Controller}] Default: {DefaultTemperature}°C - Range: ({MinimumTemperature}°C - {MaximumTemperature}°C)";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUThermalLimitPolicy.cs b/NvAPIWrapper/GPU/GPUThermalLimitPolicy.cs
new file mode 100644
index 0000000..9ad502c
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUThermalLimitPolicy.cs
@@ -0,0 +1,40 @@
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Holds information regarding a currently active temperature limit policy
+ ///
+ public class GPUThermalLimitPolicy
+ {
+ internal GPUThermalLimitPolicy(PrivateThermalPoliciesStatusV2.ThermalPoliciesStatusEntry thermalPoliciesEntry)
+ {
+ Controller = thermalPoliciesEntry.Controller;
+ PerformanceStateId = thermalPoliciesEntry.PerformanceStateId;
+ TargetTemperature = thermalPoliciesEntry.TargetTemperature;
+ }
+
+ ///
+ /// Gets the policy's thermal controller
+ ///
+ public ThermalController Controller { get; }
+
+ ///
+ /// Gets the corresponding performance state identification
+ ///
+ public PerformanceStateId PerformanceStateId { get; }
+
+ ///
+ /// Gets the current policy target temperature in degree Celsius
+ ///
+ public int TargetTemperature { get; }
+
+ ///
+ public override string ToString()
+ {
+ return
+ $"{PerformanceStateId} [{Controller}] Target: {TargetTemperature}°C";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUThermalSensor.cs b/NvAPIWrapper/GPU/GPUThermalSensor.cs
new file mode 100644
index 0000000..a1a8c48
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUThermalSensor.cs
@@ -0,0 +1,48 @@
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.Interfaces.GPU;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Represents a thermal sensor
+ ///
+ public class GPUThermalSensor : IThermalSensor
+ {
+ internal GPUThermalSensor(int sensorId, IThermalSensor thermalSensor)
+ {
+ SensorId = sensorId;
+ Controller = thermalSensor.Controller;
+ DefaultMinimumTemperature = thermalSensor.DefaultMinimumTemperature;
+ DefaultMaximumTemperature = thermalSensor.DefaultMaximumTemperature;
+ CurrentTemperature = thermalSensor.CurrentTemperature;
+ Target = thermalSensor.Target;
+ }
+
+ ///
+ /// Gets the sensor identification number or index
+ ///
+ public int SensorId { get; set; }
+
+ ///
+ public ThermalController Controller { get; }
+
+ ///
+ public int CurrentTemperature { get; }
+
+ ///
+ public int DefaultMaximumTemperature { get; }
+
+ ///
+ public int DefaultMinimumTemperature { get; }
+
+ ///
+ public ThermalSettingsTarget Target { get; }
+
+ ///
+ public override string ToString()
+ {
+ return
+ $"[{Target} @ {Controller}] Current: {CurrentTemperature}°C - Default Range: [({DefaultMinimumTemperature}°C) , ({DefaultMaximumTemperature}°C)]";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUUsageDomainStatus.cs b/NvAPIWrapper/GPU/GPUUsageDomainStatus.cs
new file mode 100644
index 0000000..21d4c0f
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUUsageDomainStatus.cs
@@ -0,0 +1,33 @@
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.Interfaces.GPU;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Holds information about a utilization domain
+ ///
+ public class GPUUsageDomainStatus
+ {
+ internal GPUUsageDomainStatus(UtilizationDomain domain, IUtilizationDomainInfo utilizationDomainInfo)
+ {
+ Domain = domain;
+ Percentage = (int) utilizationDomainInfo.Percentage;
+ }
+
+ ///
+ /// Gets the utilization domain that this instance describes
+ ///
+ public UtilizationDomain Domain { get; }
+
+ ///
+ /// Gets the percentage of time where the domain is considered busy in the last 1 second interval.
+ ///
+ public int Percentage { get; }
+
+ ///
+ public override string ToString()
+ {
+ return $"[{Domain}] {Percentage}%";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/GPUUsageInformation.cs b/NvAPIWrapper/GPU/GPUUsageInformation.cs
new file mode 100644
index 0000000..1d6b687
--- /dev/null
+++ b/NvAPIWrapper/GPU/GPUUsageInformation.cs
@@ -0,0 +1,99 @@
+using System.Collections.Generic;
+using System.Linq;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.GPU;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Holds information about the GPU utilization domains
+ ///
+ public class GPUUsageInformation
+ {
+ internal GPUUsageInformation(PhysicalGPU physicalGPU)
+ {
+ PhysicalGPU = physicalGPU;
+ }
+
+ ///
+ /// Gets the Bus interface (BUS) utilization
+ ///
+ public GPUUsageDomainStatus BusInterface
+ {
+ get => UtilizationDomainsStatus.FirstOrDefault(status => status.Domain == UtilizationDomain.BusInterface);
+ }
+
+ ///
+ /// Gets the frame buffer (FB) utilization
+ ///
+ public GPUUsageDomainStatus FrameBuffer
+ {
+ get => UtilizationDomainsStatus.FirstOrDefault(status => status.Domain == UtilizationDomain.FrameBuffer);
+ }
+
+ ///
+ /// Gets the graphic engine (GPU) utilization
+ ///
+ public GPUUsageDomainStatus GPU
+ {
+ get => UtilizationDomainsStatus.FirstOrDefault(status => status.Domain == UtilizationDomain.GPU);
+ }
+
+ ///
+ /// Gets a boolean value indicating if the dynamic performance states is enabled
+ ///
+ public bool IsDynamicPerformanceStatesEnabled
+ {
+ get => GPUApi.GetDynamicPerformanceStatesInfoEx(PhysicalGPU.Handle).IsDynamicPerformanceStatesEnabled;
+ }
+
+ ///
+ /// Gets the physical GPU that this instance describes
+ ///
+ public PhysicalGPU PhysicalGPU { get; }
+
+ ///
+ /// Gets all valid utilization domains and information
+ ///
+ public IEnumerable UtilizationDomainsStatus
+ {
+ get
+ {
+ try
+ {
+ var dynamicPerformanceStates = GPUApi.GetDynamicPerformanceStatesInfoEx(PhysicalGPU.Handle);
+
+ if (dynamicPerformanceStates.IsDynamicPerformanceStatesEnabled)
+ {
+ return dynamicPerformanceStates.Domains
+ .Select(pair => new GPUUsageDomainStatus(pair.Key, pair.Value));
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+
+ return GPUApi.GetUsages(PhysicalGPU.Handle).Domains
+ .Select(pair => new GPUUsageDomainStatus(pair.Key, pair.Value));
+ }
+ }
+
+
+ ///
+ /// Gets the Video engine (VID) utilization
+ ///
+ public GPUUsageDomainStatus VideoEngine
+ {
+ get => UtilizationDomainsStatus.FirstOrDefault(status => status.Domain == UtilizationDomain.VideoEngine);
+ }
+
+ ///
+ /// Enables dynamic performance states
+ ///
+ public void EnableDynamicPerformanceStates()
+ {
+ GPUApi.EnableDynamicPStates(PhysicalGPU.Handle);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/LogicalGPU.cs b/NvAPIWrapper/GPU/LogicalGPU.cs
new file mode 100644
index 0000000..6f15666
--- /dev/null
+++ b/NvAPIWrapper/GPU/LogicalGPU.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Linq;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.GPU.Structures;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Represents a logical NVIDIA GPU
+ ///
+ public class LogicalGPU : IEquatable
+ {
+ ///
+ /// Creates a new LogicalGPU
+ ///
+ /// Logical GPU handle
+ public LogicalGPU(LogicalGPUHandle handle)
+ {
+ Handle = handle;
+ }
+
+ ///
+ /// Gets a list of all corresponding physical GPUs
+ ///
+ public PhysicalGPU[] CorrespondingPhysicalGPUs
+ {
+ get
+ {
+ return GPUApi.GetPhysicalGPUsFromLogicalGPU(Handle).Select(handle => new PhysicalGPU(handle)).ToArray();
+ }
+ }
+
+ ///
+ /// Gets the logical GPU handle
+ ///
+ public LogicalGPUHandle Handle { get; }
+
+ ///
+ public bool Equals(LogicalGPU other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return Handle.Equals(other.Handle);
+ }
+
+ ///
+ /// Gets all logical GPUs
+ ///
+ /// An array of logical GPUs
+ public static LogicalGPU[] GetLogicalGPUs()
+ {
+ return GPUApi.EnumLogicalGPUs().Select(handle => new LogicalGPU(handle)).ToArray();
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(LogicalGPU left, LogicalGPU right)
+ {
+ return right?.Equals(left) ?? ReferenceEquals(left, null);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(LogicalGPU left, LogicalGPU right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((LogicalGPU) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return Handle.GetHashCode();
+ }
+
+ ///
+ public override string ToString()
+ {
+ return
+ $"Logical GPU [{CorrespondingPhysicalGPUs.Length}] {{{string.Join(", ", CorrespondingPhysicalGPUs.Select(gpu => gpu.FullName).ToArray())}}}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/PCIIdentifiers.cs b/NvAPIWrapper/GPU/PCIIdentifiers.cs
new file mode 100644
index 0000000..0076a86
--- /dev/null
+++ b/NvAPIWrapper/GPU/PCIIdentifiers.cs
@@ -0,0 +1,114 @@
+using System;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Contains information about the PCI connection
+ ///
+ public class PCIIdentifiers : IEquatable
+ {
+ // ReSharper disable once TooManyDependencies
+ internal PCIIdentifiers(uint deviceId, uint subSystemId, uint revisionId, int externalDeviceId = 0)
+ {
+ DeviceId = deviceId;
+ SubSystemId = subSystemId;
+ RevisionId = revisionId;
+
+ if (externalDeviceId > 0)
+ {
+ ExternalDeviceId = (ushort) externalDeviceId;
+ }
+ else
+ {
+ ExternalDeviceId = (ushort) (deviceId >> 16);
+ }
+
+ VendorId = (ushort) ((DeviceId << 16) >> 16);
+ }
+
+ ///
+ /// Gets the internal PCI device identifier
+ ///
+ public uint DeviceId { get; }
+
+ ///
+ /// Gets the external PCI device identifier
+ ///
+ public ushort ExternalDeviceId { get; }
+
+ ///
+ /// Gets the internal PCI device-specific revision identifier
+ ///
+ public uint RevisionId { get; }
+
+ ///
+ /// Gets the internal PCI subsystem identifier
+ ///
+ public uint SubSystemId { get; }
+
+ ///
+ /// Gets the vendor identification calculated from internal device identification
+ ///
+ public ushort VendorId { get; }
+
+ ///
+ public bool Equals(PCIIdentifiers other)
+ {
+ return DeviceId == other.DeviceId &&
+ SubSystemId == other.SubSystemId &&
+ RevisionId == other.RevisionId;
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(PCIIdentifiers left, PCIIdentifiers right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(PCIIdentifiers left, PCIIdentifiers right)
+ {
+ return !left.Equals(right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is PCIIdentifiers identifiers && Equals(identifiers);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = (int) DeviceId;
+ hashCode = (hashCode * 397) ^ (int) SubSystemId;
+ hashCode = (hashCode * 397) ^ (int) RevisionId;
+
+ return hashCode;
+ }
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"PCI\\VEN_{VendorId:X}&DEV_{ExternalDeviceId:X}&SUBSYS_{SubSystemId:X}&REV_{RevisionId:X}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/PCIeInformation.cs b/NvAPIWrapper/GPU/PCIeInformation.cs
new file mode 100644
index 0000000..b585577
--- /dev/null
+++ b/NvAPIWrapper/GPU/PCIeInformation.cs
@@ -0,0 +1,67 @@
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Contains information about the PCI-e connection
+ ///
+ public class PCIeInformation
+ {
+ internal PCIeInformation(PrivatePCIeInfoV2.PCIePerformanceStateInfo stateInfo)
+ {
+ TransferRateInMTps = stateInfo.TransferRateInMTps;
+ Generation = stateInfo.Generation;
+ Lanes = stateInfo.Lanes;
+ Version = stateInfo.Version;
+ }
+
+ ///
+ /// Gets the PCI-e generation
+ ///
+ public PCIeGeneration Generation { get; }
+
+ ///
+ /// Gets the PCI-e down stream lanes
+ ///
+ public uint Lanes { get; }
+
+ ///
+ /// Gets the PCIe transfer rate in Mega Transfers per Second
+ ///
+ public uint TransferRateInMTps { get; }
+
+ ///
+ /// Gets the PCI-e version
+ ///
+ public PCIeGeneration Version { get; }
+
+ ///
+ public override string ToString()
+ {
+ var v = "Unknown";
+
+ switch (Version)
+ {
+ case PCIeGeneration.PCIe1:
+ v = "PCIe 1.0";
+
+ break;
+ case PCIeGeneration.PCIe1Minor1:
+ v = "PCIe 1.1";
+
+ break;
+ case PCIeGeneration.PCIe2:
+ v = "PCIe 2.0";
+
+ break;
+ case PCIeGeneration.PCIe3:
+ v = "PCIe 3.0";
+
+ break;
+ }
+
+ return $"{v} x{Lanes} - {TransferRateInMTps} MTps";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/PhysicalGPU.cs b/NvAPIWrapper/GPU/PhysicalGPU.cs
new file mode 100644
index 0000000..cb8f62a
--- /dev/null
+++ b/NvAPIWrapper/GPU/PhysicalGPU.cs
@@ -0,0 +1,559 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using NvAPIWrapper.Display;
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.Exceptions;
+using NvAPIWrapper.Native.General;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces.GPU;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Represents a physical NVIDIA GPU
+ ///
+ public class PhysicalGPU : IEquatable
+ {
+ ///
+ /// Creates a new PhysicalGPU
+ ///
+ /// Physical GPU handle
+ public PhysicalGPU(PhysicalGPUHandle handle)
+ {
+ Handle = handle;
+ UsageInformation = new GPUUsageInformation(this);
+ ThermalInformation = new GPUThermalInformation(this);
+ BusInformation = new GPUBusInformation(this);
+ ArchitectInformation = new GPUArchitectInformation(this);
+ MemoryInformation = new GPUMemoryInformation(this);
+ CoolerInformation = new GPUCoolerInformation(this);
+ ECCMemoryInformation = new ECCMemoryInformation(this);
+ PerformanceControl = new GPUPerformanceControl(this);
+ PowerTopologyInformation = new GPUPowerTopologyInformation(this);
+ }
+
+ ///
+ /// Gets all active outputs of this GPU
+ ///
+ public GPUOutput[] ActiveOutputs
+ {
+ get
+ {
+ var outputs = new List();
+ var allOutputs = GPUApi.GetActiveOutputs(Handle);
+
+ foreach (OutputId outputId in Enum.GetValues(typeof(OutputId)))
+ {
+ if (outputId != OutputId.Invalid && allOutputs.HasFlag(outputId))
+ {
+ outputs.Add(new GPUOutput(outputId, this));
+ }
+ }
+
+ return outputs.ToArray();
+ }
+ }
+
+ ///
+ /// Gets GPU architect information
+ ///
+ public GPUArchitectInformation ArchitectInformation { get; }
+
+ ///
+ /// Gets GPU base clock frequencies
+ ///
+ public IClockFrequencies BaseClockFrequencies
+ {
+ get => GPUApi.GetAllClockFrequencies(Handle, new ClockFrequenciesV2(ClockType.BaseClock));
+ }
+
+ ///
+ /// Gets GPU video BIOS information
+ ///
+ public VideoBIOS Bios
+ {
+ get => new VideoBIOS(
+ GPUApi.GetVBIOSRevision(Handle),
+ (int) GPUApi.GetVBIOSOEMRevision(Handle),
+ GPUApi.GetVBIOSVersionString(Handle)
+ );
+ }
+
+ ///
+ /// Gets the board information
+ ///
+ public BoardInfo Board
+ {
+ get
+ {
+ try
+ {
+ return GPUApi.GetBoardInfo(Handle);
+ }
+ catch (NVIDIAApiException ex)
+ {
+ if (ex.Status == Status.NotSupported)
+ {
+ return default;
+ }
+
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Gets GPU boost clock frequencies
+ ///
+ public IClockFrequencies BoostClockFrequencies
+ {
+ get => GPUApi.GetAllClockFrequencies(Handle, new ClockFrequenciesV2(ClockType.BoostClock));
+ }
+
+ ///
+ /// Gets GPU bus information
+ ///
+ public GPUBusInformation BusInformation { get; }
+
+ ///
+ /// Gets GPU coolers information
+ ///
+ public GPUCoolerInformation CoolerInformation { get; }
+
+ ///
+ /// Gets corresponding logical GPU
+ ///
+ public LogicalGPU CorrespondingLogicalGPU
+ {
+ get => new LogicalGPU(GPUApi.GetLogicalGPUFromPhysicalGPU(Handle));
+ }
+
+ ///
+ /// Gets GPU current clock frequencies
+ ///
+ public IClockFrequencies CurrentClockFrequencies
+ {
+ get => GPUApi.GetAllClockFrequencies(Handle, new ClockFrequenciesV2(ClockType.CurrentClock));
+ }
+
+ ///
+ /// Gets the driver model number for this GPU
+ ///
+ public uint DriverModel
+ {
+ get => GPUApi.GetDriverModel(Handle);
+ }
+
+ ///
+ /// Gets GPU ECC memory information
+ ///
+ public ECCMemoryInformation ECCMemoryInformation { get; }
+
+ ///
+ /// Gets the chipset foundry
+ ///
+ public GPUFoundry Foundry
+ {
+ get => GPUApi.GetFoundry(Handle);
+ }
+
+ ///
+ /// Gets GPU full name
+ ///
+ public string FullName
+ {
+ get => GPUApi.GetFullName(Handle);
+ }
+
+ ///
+ /// Gets the GPU identification number
+ ///
+ public uint GPUId
+ {
+ get => GPUApi.GetGPUIDFromPhysicalGPU(Handle);
+ }
+
+ ///
+ /// Gets GPU type
+ ///
+ public GPUType GPUType
+ {
+ get => GPUApi.GetGPUType(Handle);
+ }
+
+ ///
+ /// Gets the physical GPU handle
+ ///
+ public PhysicalGPUHandle Handle { get; }
+
+ ///
+ /// Gets a boolean value indicating the Quadro line of products
+ ///
+ public bool IsQuadro
+ {
+ get => GPUApi.GetQuadroStatus(Handle);
+ }
+
+ ///
+ /// Gets GPU memory and RAM information as well as frame-buffer information
+ ///
+ public GPUMemoryInformation MemoryInformation { get; }
+
+ ///
+ /// Gets GPU performance control status and configurations
+ ///
+ public GPUPerformanceControl PerformanceControl { get; }
+
+
+ ///
+ /// Gets the GPU performance states information and configurations
+ ///
+ public GPUPerformanceStatesInformation PerformanceStatesInfo
+ {
+ get
+ {
+ var performanceStates20Info = GPUApi.GetPerformanceStates20(Handle);
+ var currentPerformanceState = GPUApi.GetCurrentPerformanceState(Handle);
+ PrivatePCIeInfoV2? pcieInformation = null;
+
+ if (BusInformation.BusType == GPUBusType.PCIExpress)
+ {
+ try
+ {
+ pcieInformation = GPUApi.GetPCIEInfo(Handle);
+ }
+ catch
+ {
+ // ignore
+ }
+ }
+
+ return new GPUPerformanceStatesInformation(performanceStates20Info, currentPerformanceState,
+ pcieInformation);
+ }
+ }
+
+ ///
+ /// Gets GPU coolers information
+ ///
+ public GPUPowerTopologyInformation PowerTopologyInformation { get; }
+
+ ///
+ /// Gets GPU system type
+ ///
+ public SystemType SystemType
+ {
+ get => GPUApi.GetSystemType(Handle);
+ }
+
+ ///
+ /// Gets GPU thermal sensors information
+ ///
+ public GPUThermalInformation ThermalInformation { get; }
+
+ ///
+ /// Gets the GPU utilization domains and usages
+ ///
+ public GPUUsageInformation UsageInformation { get; }
+
+ ///
+ public bool Equals(PhysicalGPU other)
+ {
+ if (other == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return Handle.Equals(other.Handle);
+ }
+
+ ///
+ /// Gets the corresponding instance from a GPU identification number.
+ ///
+ /// The GPU identification number.
+ /// An instance of or if operation failed.
+ public static PhysicalGPU FromGPUId(uint gpuId)
+ {
+ var handle = GPUApi.GetPhysicalGPUFromGPUID(gpuId);
+
+ if (handle.IsNull)
+ {
+ return null;
+ }
+
+ return new PhysicalGPU(handle);
+ }
+
+ ///
+ /// Gets all physical GPUs
+ ///
+ /// An array of physical GPUs
+ public static PhysicalGPU[] GetPhysicalGPUs()
+ {
+ return GPUApi.EnumPhysicalGPUs().Select(handle => new PhysicalGPU(handle)).ToArray();
+ }
+
+ ///
+ /// Gets all physical GPUs in TCC state
+ ///
+ /// An array of physical GPUs
+ public static PhysicalGPU[] GetTCCPhysicalGPUs()
+ {
+ return GPUApi.EnumTCCPhysicalGPUs().Select(handle => new PhysicalGPU(handle)).ToArray();
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(PhysicalGPU left, PhysicalGPU right)
+ {
+ return Equals(left, right) || left?.Equals(right) == true;
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(PhysicalGPU left, PhysicalGPU right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ return Equals(obj as PhysicalGPU);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return Handle.GetHashCode();
+ }
+
+ ///
+ public override string ToString()
+ {
+ return FullName;
+ }
+
+ ///
+ /// Get a list of all active applications for this GPU
+ ///
+ /// An array of processes
+ public Process[] GetActiveApplications()
+ {
+ return GPUApi.QueryActiveApps(Handle).Select(app => Process.GetProcessById(app.ProcessId)).ToArray();
+ }
+
+ ///
+ /// Get a list of all connected display devices on this GPU
+ ///
+ /// ConnectedIdsFlag flag
+ /// An array of display devices
+ public DisplayDevice[] GetConnectedDisplayDevices(ConnectedIdsFlag flags)
+ {
+ return GPUApi.GetConnectedDisplayIds(Handle, flags).Select(display => new DisplayDevice(display)).ToArray();
+ }
+
+ ///
+ /// Get the display device connected to a specific GPU output
+ ///
+ /// The GPU output to get connected display device for
+ /// DisplayDevice connected to the specified GPU output
+ public DisplayDevice GetDisplayDeviceByOutput(GPUOutput output)
+ {
+ return new DisplayDevice(GPUApi.GetDisplayIdFromGPUAndOutputId(Handle, output.OutputId));
+ }
+
+ ///
+ /// Get a list of all display devices on any possible output
+ ///
+ /// An array of display devices
+ public DisplayDevice[] GetDisplayDevices()
+ {
+ return GPUApi.GetAllDisplayIds(Handle).Select(display => new DisplayDevice(display)).ToArray();
+ }
+
+ ///
+ /// Reads EDID data of an output
+ ///
+ /// The GPU output to read EDID information for
+ /// A byte array containing EDID data
+ public byte[] ReadEDIDData(GPUOutput output)
+ {
+ try
+ {
+ var data = new byte[0];
+ var identification = 0;
+ var totalSize = EDIDV3.MaxDataSize;
+
+ for (var offset = 0; offset < totalSize; offset += EDIDV3.MaxDataSize)
+ {
+ var edid = GPUApi.GetEDID(Handle, output.OutputId, offset, identification);
+ identification = edid.Identification;
+ totalSize = edid.TotalSize;
+
+ var edidData = edid.Data;
+ Array.Resize(ref data, data.Length + edidData.Length);
+ Array.Copy(edidData, 0, data, data.Length - edidData.Length, edidData.Length);
+ }
+
+ return data;
+ }
+ catch (NVIDIAApiException ex)
+ {
+ if (ex.Status == Status.IncompatibleStructureVersion)
+ {
+ return GPUApi.GetEDID(Handle, output.OutputId).Data;
+ }
+
+ throw;
+ }
+ }
+
+ ///
+ /// Reads data from the I2C bus
+ ///
+ /// Information required to read from the I2C bus.
+ /// The returned payload.
+ // ReSharper disable once InconsistentNaming
+ public byte[] ReadI2C(II2CInfo i2cInfo)
+ {
+ GPUApi.I2CRead(Handle, ref i2cInfo);
+
+ return i2cInfo.Data;
+ }
+
+ ///
+ /// Validates a set of GPU outputs to check if they can be active simultaneously
+ ///
+ /// GPU outputs to check
+ /// true if all specified outputs can be active simultaneously, otherwise false
+ public bool ValidateOutputCombination(GPUOutput[] outputs)
+ {
+ var gpuOutpudIds =
+ outputs.Aggregate(OutputId.Invalid, (current, gpuOutput) => current | gpuOutput.OutputId);
+
+ return GPUApi.ValidateOutputCombination(Handle, gpuOutpudIds);
+ }
+
+ ///
+ /// Writes EDID data of an output
+ ///
+ /// The GPU output to write EDID information for
+ /// A byte array containing EDID data
+ public void WriteEDIDData(GPUOutput output, byte[] edidData)
+ {
+ WriteEDIDData((uint) output.OutputId, edidData);
+ }
+
+ ///
+ /// Writes EDID data of an display
+ ///
+ /// The display device to write EDID information for
+ /// A byte array containing EDID data
+ public void WriteEDIDData(DisplayDevice display, byte[] edidData)
+ {
+ WriteEDIDData(display.DisplayId, edidData);
+ }
+
+ ///
+ /// Writes data to the I2C bus
+ ///
+ /// Information required to write to the I2C bus including data payload.
+ // ReSharper disable once InconsistentNaming
+ public void WriteI2C(II2CInfo i2cInfo)
+ {
+ GPUApi.I2CWrite(Handle, i2cInfo);
+ }
+
+ private void WriteEDIDData(uint displayOutputId, byte[] edidData)
+ {
+ try
+ {
+ if (edidData.Length == 0)
+ {
+ var instance = typeof(EDIDV3).Instantiate();
+ GPUApi.SetEDID(Handle, displayOutputId, instance);
+ }
+
+ for (var offset = 0; offset < edidData.Length; offset += EDIDV3.MaxDataSize)
+ {
+ var array = new byte[Math.Min(EDIDV3.MaxDataSize, edidData.Length - offset)];
+ Array.Copy(edidData, offset, array, 0, array.Length);
+ var instance = EDIDV3.CreateWithData(0, (uint) offset, array, edidData.Length);
+ GPUApi.SetEDID(Handle, displayOutputId, instance);
+ }
+
+ return;
+ }
+ catch (NVIDIAApiException ex)
+ {
+ if (ex.Status != Status.IncompatibleStructureVersion)
+ {
+ throw;
+ }
+ }
+ catch (NVIDIANotSupportedException)
+ {
+ // ignore
+ }
+
+ try
+ {
+ if (edidData.Length == 0)
+ {
+ var instance = typeof(EDIDV2).Instantiate();
+ GPUApi.SetEDID(Handle, displayOutputId, instance);
+ }
+
+ for (var offset = 0; offset < edidData.Length; offset += EDIDV2.MaxDataSize)
+ {
+ var array = new byte[Math.Min(EDIDV2.MaxDataSize, edidData.Length - offset)];
+ Array.Copy(edidData, offset, array, 0, array.Length);
+ GPUApi.SetEDID(Handle, displayOutputId, EDIDV2.CreateWithData(array, edidData.Length));
+ }
+
+ return;
+ }
+ catch (NVIDIAApiException ex)
+ {
+ if (ex.Status != Status.IncompatibleStructureVersion)
+ {
+ throw;
+ }
+ }
+ catch (NVIDIANotSupportedException)
+ {
+ // ignore
+ }
+
+ GPUApi.SetEDID(Handle, displayOutputId, EDIDV1.CreateWithData(edidData));
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/GPU/VideoBIOS.cs b/NvAPIWrapper/GPU/VideoBIOS.cs
new file mode 100644
index 0000000..72b522d
--- /dev/null
+++ b/NvAPIWrapper/GPU/VideoBIOS.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace NvAPIWrapper.GPU
+{
+ ///
+ /// Contains information about the GPU Video BIOS
+ ///
+ public class VideoBIOS
+ {
+ internal VideoBIOS(uint revision, int oemRevision, string versionString)
+ {
+ Revision = revision;
+ OEMRevision = oemRevision;
+ VersionString = versionString.ToUpper();
+ }
+
+ ///
+ /// Gets the the OEM revision of the video BIOS
+ ///
+ public int OEMRevision { get; }
+
+ ///
+ /// Gets the revision of the video BIOS
+ ///
+ public uint Revision { get; }
+
+ ///
+ /// Gets the full video BIOS version string
+ ///
+ public string VersionString { get; }
+
+ ///
+ public override string ToString()
+ {
+ return AsVersion().ToString();
+ }
+
+ ///
+ /// Returns the video BIOS version as a .Net Version object
+ ///
+ /// A Version object representing the video BIOS version
+ public Version AsVersion()
+ {
+ return new Version(
+ (int) ((Revision >> 28) + ((Revision << 4) >> 28) * 16), // 8 bit little endian
+ (int) (((Revision << 8) >> 28) + ((Revision << 12) >> 28) * 16), // 8 bit little endian
+ (int) ((Revision << 16) >> 16), // 16 bit big endian
+ OEMRevision // 8 bit integer
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Icon.png b/NvAPIWrapper/Icon.png
new file mode 100644
index 0000000..43914ec
Binary files /dev/null and b/NvAPIWrapper/Icon.png differ
diff --git a/NvAPIWrapper/NVIDIA.cs b/NvAPIWrapper/NVIDIA.cs
new file mode 100644
index 0000000..5fd5825
--- /dev/null
+++ b/NvAPIWrapper/NVIDIA.cs
@@ -0,0 +1,81 @@
+using NvAPIWrapper.Native;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Interfaces.General;
+
+namespace NvAPIWrapper
+{
+ ///
+ /// .Net friendly version of system and general functions of NVAPI library
+ ///
+ public static class NVIDIA
+ {
+ ///
+ /// Gets information about the system's chipset.
+ ///
+ public static IChipsetInfo ChipsetInfo
+ {
+ get => GeneralApi.GetChipsetInfo();
+ }
+
+ ///
+ /// Gets NVIDIA driver branch version as string
+ ///
+ public static string DriverBranchVersion
+ {
+ get
+ {
+ GeneralApi.GetDriverAndBranchVersion(out var branchVersion);
+
+ return branchVersion;
+ }
+ }
+
+ ///
+ /// Gets NVIDIA driver version
+ ///
+ public static uint DriverVersion
+ {
+ get => GeneralApi.GetDriverAndBranchVersion(out _);
+ }
+
+ ///
+ /// Gets NVAPI interface version as string
+ ///
+ public static string InterfaceVersionString
+ {
+ get => GeneralApi.GetInterfaceVersionString();
+ }
+
+ ///
+ /// Gets the current lid and dock information.
+ ///
+ public static LidDockParameters LidAndDockParameters
+ {
+ get => GeneralApi.GetLidAndDockInfo();
+ }
+
+ ///
+ /// Initializes the NvAPI library (if not already initialized) but always increments the ref-counter.
+ ///
+ public static void Initialize()
+ {
+ GeneralApi.Initialize();
+ }
+
+ ///
+ /// PRIVATE - Requests to restart the display driver
+ ///
+ public static void RestartDisplayDriver()
+ {
+ GeneralApi.RestartDisplayDriver();
+ }
+
+ ///
+ /// Decrements the ref-counter and when it reaches ZERO, unloads NVAPI library.
+ ///
+ public static void Unload()
+ {
+ GeneralApi.Unload();
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Attributes/AcceptsAttribute.cs b/NvAPIWrapper/Native/Attributes/AcceptsAttribute.cs
new file mode 100644
index 0000000..7df15fb
--- /dev/null
+++ b/NvAPIWrapper/Native/Attributes/AcceptsAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace NvAPIWrapper.Native.Attributes
+{
+ [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Delegate)]
+ internal class AcceptsAttribute : Attribute
+ {
+ public AcceptsAttribute(params Type[] types)
+ {
+ Types = types;
+ }
+
+ public Type[] Types { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Attributes/FunctionIdAttribute.cs b/NvAPIWrapper/Native/Attributes/FunctionIdAttribute.cs
new file mode 100644
index 0000000..260da7d
--- /dev/null
+++ b/NvAPIWrapper/Native/Attributes/FunctionIdAttribute.cs
@@ -0,0 +1,16 @@
+using System;
+using NvAPIWrapper.Native.Helpers;
+
+namespace NvAPIWrapper.Native.Attributes
+{
+ [AttributeUsage(AttributeTargets.Delegate)]
+ internal class FunctionIdAttribute : Attribute
+ {
+ public FunctionIdAttribute(FunctionId functionId)
+ {
+ FunctionId = functionId;
+ }
+
+ public FunctionId FunctionId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Attributes/StructureVersionAttribute.cs b/NvAPIWrapper/Native/Attributes/StructureVersionAttribute.cs
new file mode 100644
index 0000000..9752e65
--- /dev/null
+++ b/NvAPIWrapper/Native/Attributes/StructureVersionAttribute.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace NvAPIWrapper.Native.Attributes
+{
+ [AttributeUsage(AttributeTargets.Struct)]
+ internal class StructureVersionAttribute : Attribute
+ {
+ public StructureVersionAttribute()
+ {
+ }
+
+ public StructureVersionAttribute(int versionNumber)
+ {
+ VersionNumber = versionNumber;
+ }
+
+ public int VersionNumber { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Constants/Display.cs b/NvAPIWrapper/Native/Constants/Display.cs
new file mode 100644
index 0000000..c7a01b8
--- /dev/null
+++ b/NvAPIWrapper/Native/Constants/Display.cs
@@ -0,0 +1,8 @@
+namespace NvAPIWrapper.Native.Constants
+{
+ internal static class Display
+ {
+ public const int AdvancedDisplayHeads = 4;
+ public const int MaxDisplayHeads = 2;
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Constants/General.cs b/NvAPIWrapper/Native/Constants/General.cs
new file mode 100644
index 0000000..20468c7
--- /dev/null
+++ b/NvAPIWrapper/Native/Constants/General.cs
@@ -0,0 +1,8 @@
+namespace NvAPIWrapper.Native.Constants
+{
+ internal static class General
+ {
+ public const int BinaryDataMax = 4096;
+ public const int UnicodeStringLength = 2048;
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Delegates/Display.cs b/NvAPIWrapper/Native/Delegates/Display.cs
new file mode 100644
index 0000000..fb04283
--- /dev/null
+++ b/NvAPIWrapper/Native/Delegates/Display.cs
@@ -0,0 +1,327 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.Display;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.General;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Helpers.Structures;
+
+// ReSharper disable InconsistentNaming
+
+namespace NvAPIWrapper.Native.Delegates
+{
+ internal static class Display
+ {
+ [FunctionId(FunctionId.NvAPI_CreateDisplayFromUnAttachedDisplay)]
+ public delegate Status NvAPI_CreateDisplayFromUnAttachedDisplay(
+ [In] UnAttachedDisplayHandle display,
+ [Out] out DisplayHandle newDisplay
+ );
+
+ [FunctionId(FunctionId.NvAPI_Disp_ColorControl)]
+ public delegate Status NvAPI_Disp_ColorControl(
+ [In] uint displayId,
+ [In]
+ [Out]
+ [Accepts(
+ typeof(ColorDataV5),
+ typeof(ColorDataV4),
+ typeof(ColorDataV3),
+ typeof(ColorDataV2),
+ typeof(ColorDataV1)
+ )]
+ ValueTypeReference colorData
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_DeleteCustomDisplay)]
+ public delegate Status NvAPI_DISP_DeleteCustomDisplay(
+ [In] [Accepts(typeof(uint))] ValueTypeArray displayIds,
+ [In] uint count,
+ [In] [Accepts(typeof(CustomDisplay))] ValueTypeReference customDisplay
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_EnumCustomDisplay)]
+ public delegate Status NvAPI_DISP_EnumCustomDisplay(
+ [In] uint displayId,
+ [In] uint index,
+ [In] [Accepts(typeof(CustomDisplay))] ValueTypeReference customDisplay
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_GetAssociatedUnAttachedNvidiaDisplayHandle)]
+ public delegate Status NvAPI_DISP_GetAssociatedUnAttachedNvidiaDisplayHandle(
+ [In] [MarshalAs(UnmanagedType.LPStr)] string displayName,
+ [Out] out UnAttachedDisplayHandle display
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_GetDisplayConfig)]
+ public delegate Status NvAPI_DISP_GetDisplayConfig(
+ [In] [Out] ref uint pathInfoCount,
+ [In] [Accepts(typeof(PathInfoV2), typeof(PathInfoV1))]
+ ValueTypeArray pathInfos
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_GetDisplayIdByDisplayName)]
+ public delegate Status NvAPI_DISP_GetDisplayIdByDisplayName([In] string displayName, [Out] out uint displayId);
+
+ [FunctionId(FunctionId.NvAPI_DISP_GetGDIPrimaryDisplayId)]
+ public delegate Status NvAPI_DISP_GetGDIPrimaryDisplayId([Out] out uint displayId);
+
+ [FunctionId(FunctionId.NvAPI_Disp_GetHdrCapabilities)]
+ public delegate Status NvAPI_Disp_GetHdrCapabilities(
+ [In] uint displayId,
+ [In] [Out] [Accepts(typeof(HDRCapabilitiesV1))]
+ ValueTypeReference hdrCapabilities
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_GetMonitorCapabilities)]
+ public delegate Status NvAPI_DISP_GetMonitorCapabilities(
+ [In] uint displayId,
+ [In] [Accepts(typeof(MonitorCapabilities))]
+ ValueTypeReference capabilities
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_GetMonitorColorCapabilities)]
+ public delegate Status NvAPI_DISP_GetMonitorColorCapabilities(
+ [In] uint displayId,
+ [In] [Accepts(typeof(MonitorColorData))]
+ ValueTypeArray capabilities,
+ [In] [Out] ref uint count
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_GetTiming)]
+ public delegate Status NvAPI_DISP_GetTiming(
+ [In] uint displayId,
+ [In] [Accepts(typeof(TimingInput))] ValueTypeReference timingInput,
+ [In] [Accepts(typeof(Timing))] ValueTypeReference timing
+ );
+
+ [FunctionId(FunctionId.NvAPI_Disp_HdrColorControl)]
+ public delegate Status NvAPI_Disp_HdrColorControl(
+ [In] uint displayId,
+ [In] [Out] [Accepts(typeof(HDRColorDataV2), typeof(HDRColorDataV1))]
+ ValueTypeReference hdrColorData
+ );
+
+ [FunctionId(FunctionId.NvAPI_Disp_InfoFrameControl)]
+ public delegate Status NvAPI_Disp_InfoFrameControl(
+ [In] uint displayId,
+ [In] [Accepts(typeof(InfoFrameData))] ValueTypeReference infoFrameData
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_RevertCustomDisplayTrial)]
+ public delegate Status NvAPI_DISP_RevertCustomDisplayTrial(
+ [In] [Accepts(typeof(uint))] ValueTypeArray displayIds,
+ [In] uint count
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_SaveCustomDisplay)]
+ public delegate Status NvAPI_DISP_SaveCustomDisplay(
+ [In] [Accepts(typeof(uint))] ValueTypeArray displayIds,
+ [In] uint count,
+ [In] uint isThisOutputIdOnly,
+ [In] uint isThisMonitorIdOnly
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_SetDisplayConfig)]
+ public delegate Status NvAPI_DISP_SetDisplayConfig(
+ [In] uint pathInfoCount,
+ [In] [Accepts(typeof(PathInfoV2), typeof(PathInfoV1))]
+ ValueTypeArray pathInfos,
+ [In] DisplayConfigFlags flags
+ );
+
+ [FunctionId(FunctionId.NvAPI_DISP_TryCustomDisplay)]
+ public delegate Status NvAPI_DISP_TryCustomDisplay(
+ [In] [Accepts(typeof(uint))] ValueTypeArray displayIds,
+ [In] uint count,
+ [In] [Accepts(typeof(CustomDisplay))] ValueTypeArray customDisplays
+ );
+
+ [FunctionId(FunctionId.NvAPI_EnumNvidiaDisplayHandle)]
+ public delegate Status NvAPI_EnumNvidiaDisplayHandle(
+ [In] uint enumId,
+ [Out] out DisplayHandle display
+ );
+
+ [FunctionId(FunctionId.NvAPI_EnumNvidiaUnAttachedDisplayHandle)]
+ public delegate Status NvAPI_EnumNvidiaUnAttachedDisplayHandle(
+ [In] uint enumId,
+ [Out] out UnAttachedDisplayHandle display
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetAssociatedDisplayOutputId)]
+ public delegate Status NvAPI_GetAssociatedDisplayOutputId(
+ [In] DisplayHandle display,
+ [Out] out OutputId outputId
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetAssociatedNvidiaDisplayHandle)]
+ public delegate Status NvAPI_GetAssociatedNvidiaDisplayHandle(
+ [In] [MarshalAs(UnmanagedType.LPStr)] string displayName,
+ [Out] out DisplayHandle display
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetAssociatedNvidiaDisplayName)]
+ public delegate Status NvAPI_GetAssociatedNvidiaDisplayName(
+ [In] DisplayHandle display,
+ [Out] out ShortString displayName
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetDisplayDriverBuildTitle)]
+ public delegate Status NvAPI_GetDisplayDriverBuildTitle(
+ [In] DisplayHandle displayHandle,
+ [Out] out ShortString name
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetDisplayDriverMemoryInfo)]
+ public delegate Status NvAPI_GetDisplayDriverMemoryInfo(
+ [In] DisplayHandle displayHandle,
+ [In]
+ [Accepts(
+ typeof(DisplayDriverMemoryInfoV3),
+ typeof(DisplayDriverMemoryInfoV2),
+ typeof(DisplayDriverMemoryInfoV1)
+ )]
+ ValueTypeReference memoryInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetDVCInfo)]
+ public delegate Status NvAPI_GetDVCInfo(
+ [In] DisplayHandle displayHandle,
+ [In] OutputId displayId,
+ [In] [Accepts(typeof(PrivateDisplayDVCInfo))]
+ ValueTypeReference dvcInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetDVCInfoEx)]
+ public delegate Status NvAPI_GetDVCInfoEx(
+ [In] DisplayHandle displayHandle,
+ [In] OutputId displayId,
+ [In] [Accepts(typeof(PrivateDisplayDVCInfoEx))]
+ ValueTypeReference dvcInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetHDMISupportInfo)]
+ public delegate Status NvAPI_GetHDMISupportInfo(
+ [In] DisplayHandle displayHandle,
+ [In] uint displayIdOrOutputId,
+ [In] [Accepts(typeof(HDMISupportInfoV2), typeof(HDMISupportInfoV1))]
+ ValueTypeReference supportInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetHUEInfo)]
+ public delegate Status NvAPI_GetHUEInfo(
+ [In] DisplayHandle displayHandle,
+ [In] OutputId displayId,
+ [In] [Accepts(typeof(PrivateDisplayHUEInfo))]
+ ValueTypeReference hueInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetSupportedViews)]
+ public delegate Status NvAPI_GetSupportedViews(
+ [In] DisplayHandle display,
+ [In] [Accepts(typeof(TargetViewMode))] ValueTypeArray viewModes,
+ [Out] [In] ref uint viewCount
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetUnAttachedAssociatedDisplayName)]
+ public delegate Status NvAPI_GetUnAttachedAssociatedDisplayName(
+ [In] UnAttachedDisplayHandle display,
+ [Out] out ShortString displayName
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetScanoutCompositionParameter)]
+ public delegate Status NvAPI_GPU_GetScanOutCompositionParameter(
+ [In] uint displayId,
+ [In] ScanOutCompositionParameter parameter,
+ [Out] out ScanOutCompositionParameterValue parameterValue,
+ [Out] out float container
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetScanoutConfiguration)]
+ public delegate Status NvAPI_GPU_GetScanOutConfiguration(
+ [In] uint displayId,
+ [In] [Accepts(typeof(Rectangle))] ValueTypeReference desktopRectangle,
+ [In] [Accepts(typeof(Rectangle))] ValueTypeReference scanOutRectangle
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetScanoutConfigurationEx)]
+ public delegate Status NvAPI_GPU_GetScanOutConfigurationEx(
+ [In] uint displayId,
+ [In] [Accepts(typeof(ScanOutInformationV1))]
+ ValueTypeReference scanOutInformation
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetScanoutIntensityState)]
+ public delegate Status NvAPI_GPU_GetScanOutIntensityState(
+ [In] uint displayId,
+ [In] [Accepts(typeof(ScanOutIntensityStateV1))]
+ ValueTypeReference scanOutIntensityState
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetScanoutWarpingState)]
+ public delegate Status NvAPI_GPU_GetScanOutWarpingState(
+ [In] uint displayId,
+ [In] [Accepts(typeof(ScanOutWarpingStateV1))]
+ ValueTypeReference scanOutWarpingState
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetScanoutCompositionParameter)]
+ public delegate Status NvAPI_GPU_SetScanOutCompositionParameter(
+ [In] uint displayId,
+ [In] ScanOutCompositionParameter parameter,
+ [In] ScanOutCompositionParameterValue parameterValue,
+ [In] ref float container
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetScanoutIntensity)]
+ public delegate Status NvAPI_GPU_SetScanOutIntensity(
+ [In] uint displayId,
+ [In] [Accepts(typeof(ScanOutIntensityV2), typeof(ScanOutIntensityV1))]
+ ValueTypeReference scanOutIntensityData,
+ [Out] out int isSticky
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetScanoutWarping)]
+ public delegate Status NvAPI_GPU_SetScanOutWarping(
+ [In] uint displayId,
+ [In] [Accepts(typeof(ScanOutWarpingV1))]
+ ValueTypeReference scanOutWarping,
+ [In] [Out] ref int maximumNumberOfVertices,
+ [Out] out int isSticky
+ );
+
+ [FunctionId(FunctionId.NvAPI_SetDVCLevel)]
+ public delegate Status NvAPI_SetDVCLevel(
+ [In] DisplayHandle displayHandle,
+ [In] OutputId displayId,
+ [In] int dvcLevel
+ );
+
+ [FunctionId(FunctionId.NvAPI_SetDVCLevelEx)]
+ public delegate Status NvAPI_SetDVCLevelEx(
+ [In] DisplayHandle displayHandle,
+ [In] OutputId displayId,
+ [In] [Accepts(typeof(PrivateDisplayDVCInfoEx))]
+ ValueTypeReference dvcInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_SetHUEAngle)]
+ public delegate Status NvAPI_SetHUEAngle(
+ [In] DisplayHandle displayHandle,
+ [In] OutputId displayId,
+ [In] int hueAngle
+ );
+
+ [FunctionId(FunctionId.NvAPI_SetRefreshRateOverride)]
+ public delegate Status NvAPI_SetRefreshRateOverride(
+ [In] DisplayHandle displayHandle,
+ [In] OutputId outputMask,
+ [In] float refreshRate,
+ [In] uint isDeferred
+ );
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Delegates/GPU.cs b/NvAPIWrapper/Native/Delegates/GPU.cs
new file mode 100644
index 0000000..e445f3f
--- /dev/null
+++ b/NvAPIWrapper/Native/Delegates/GPU.cs
@@ -0,0 +1,733 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.General;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.GPU.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Helpers.Structures;
+
+// ReSharper disable InconsistentNaming
+
+namespace NvAPIWrapper.Native.Delegates
+{
+ internal static class GPU
+ {
+ [FunctionId(FunctionId.NvAPI_EnumLogicalGPUs)]
+ public delegate Status NvAPI_EnumLogicalGPUs(
+ [In] [Out] [MarshalAs(UnmanagedType.LPArray, SizeConst = LogicalGPUHandle.MaxLogicalGPUs)]
+ LogicalGPUHandle[]
+ gpuHandles,
+ [Out] out uint gpuCount);
+
+ [FunctionId(FunctionId.NvAPI_EnumPhysicalGPUs)]
+ public delegate Status NvAPI_EnumPhysicalGPUs(
+ [In] [Out] [MarshalAs(UnmanagedType.LPArray, SizeConst = PhysicalGPUHandle.MaxPhysicalGPUs)]
+ PhysicalGPUHandle[]
+ gpuHandles,
+ [Out] out uint gpuCount);
+
+ [FunctionId(FunctionId.NvAPI_EnumTCCPhysicalGPUs)]
+ public delegate Status NvAPI_EnumTCCPhysicalGPUs(
+ [In] [Out] [MarshalAs(UnmanagedType.LPArray, SizeConst = PhysicalGPUHandle.MaxPhysicalGPUs)]
+ PhysicalGPUHandle[]
+ gpuHandles,
+ [Out] out uint gpuCount);
+
+ [FunctionId(FunctionId.NvAPI_GPU_QueryThermalSensors)]
+ public delegate Status NvAPI_GPU_QueryThermalSensors(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivateThermalSensorsV2))] [In]
+ ValueTypeReference thermal
+ );
+
+ [FunctionId(FunctionId.NvAPI_GetDriverModel)]
+ public delegate Status NvAPI_GetDriverModel(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint model);
+
+ [FunctionId(FunctionId.NvAPI_GetGPUIDfromPhysicalGPU)]
+ public delegate Status NvAPI_GetGPUIDFromPhysicalGPU(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint gpuId);
+
+ [FunctionId(FunctionId.NvAPI_GetLogicalGPUFromDisplay)]
+ public delegate Status NvAPI_GetLogicalGPUFromDisplay(
+ [In] DisplayHandle displayHandle,
+ [Out] out LogicalGPUHandle gpuHandle);
+
+ [FunctionId(FunctionId.NvAPI_GetLogicalGPUFromPhysicalGPU)]
+ public delegate Status NvAPI_GetLogicalGPUFromPhysicalGPU(
+ [In] PhysicalGPUHandle physicalGPUHandle,
+ [Out] out LogicalGPUHandle logicalGPUHandle);
+
+ [FunctionId(FunctionId.NvAPI_GetPhysicalGPUFromGPUID)]
+ public delegate Status NvAPI_GetPhysicalGPUFromGPUID(
+ [In] uint gpuId,
+ [Out] out PhysicalGPUHandle physicalGpu);
+
+ [FunctionId(FunctionId.NvAPI_GetPhysicalGPUFromUnAttachedDisplay)]
+ public delegate Status NvAPI_GetPhysicalGPUFromUnAttachedDisplay(
+ [In] UnAttachedDisplayHandle displayHandle,
+ [Out] out PhysicalGPUHandle gpuHandle);
+
+ [FunctionId(FunctionId.NvAPI_GetPhysicalGPUsFromDisplay)]
+ public delegate Status NvAPI_GetPhysicalGPUsFromDisplay(
+ [In] DisplayHandle displayHandle,
+ [In] [Out] [MarshalAs(UnmanagedType.LPArray, SizeConst = PhysicalGPUHandle.MaxPhysicalGPUs)]
+ PhysicalGPUHandle[]
+ gpuHandles,
+ [Out] out uint gpuCount);
+
+ [FunctionId(FunctionId.NvAPI_GetPhysicalGPUsFromLogicalGPU)]
+ public delegate Status NvAPI_GetPhysicalGPUsFromLogicalGPU(
+ [In] LogicalGPUHandle logicalGPUHandle,
+ [In] [Out] [MarshalAs(UnmanagedType.LPArray, SizeConst = PhysicalGPUHandle.MaxPhysicalGPUs)]
+ PhysicalGPUHandle[]
+ gpuHandles,
+ [Out] out uint gpuCount);
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientFanCoolersGetControl)]
+ public delegate Status NvAPI_GPU_ClientFanCoolersGetControl(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivateFanCoolersControlV1))] [In]
+ ValueTypeReference control);
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientFanCoolersGetInfo)]
+ public delegate Status NvAPI_GPU_ClientFanCoolersGetInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivateFanCoolersInfoV1))] [In]
+ ValueTypeReference info);
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientFanCoolersGetStatus)]
+ public delegate Status NvAPI_GPU_ClientFanCoolersGetStatus(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivateFanCoolersStatusV1))] [In]
+ ValueTypeReference status);
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientFanCoolersSetControl)]
+ public delegate Status NvAPI_GPU_ClientFanCoolersSetControl(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivateFanCoolersControlV1))] [In]
+ ValueTypeReference control);
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientIllumDevicesGetControl)]
+ public delegate Status NvAPI_GPU_ClientIlluminationDevicesGetControl(
+ [In] PhysicalGPUHandle gpu,
+ [Accepts(typeof(IlluminationDeviceControlParametersV1))] [In]
+ ValueTypeReference illuminationDeviceControlInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientIllumDevicesGetInfo)]
+ public delegate Status NvAPI_GPU_ClientIlluminationDevicesGetInfo(
+ [In] PhysicalGPUHandle gpu,
+ [Accepts(typeof(IlluminationDeviceInfoParametersV1))] [In]
+ ValueTypeReference illuminationDevicesInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientIllumDevicesSetControl)]
+ public delegate Status NvAPI_GPU_ClientIlluminationDevicesSetControl(
+ [In] PhysicalGPUHandle gpu,
+ [Accepts(typeof(IlluminationDeviceControlParametersV1))] [In]
+ ValueTypeReference illuminationDeviceControlInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientIllumZonesGetControl)]
+ public delegate Status NvAPI_GPU_ClientIlluminationZonesGetControl(
+ [In] PhysicalGPUHandle gpu,
+ [Accepts(typeof(IlluminationZoneControlParametersV1))] [In]
+ ValueTypeReference illuminationZoneControlInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientIllumZonesGetInfo)]
+ public delegate Status NvAPI_GPU_ClientIlluminationZonesGetInfo(
+ [In] PhysicalGPUHandle gpu,
+ [Accepts(typeof(IlluminationZoneInfoParametersV1))] [In]
+ ValueTypeReference illuminationZoneInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientIllumZonesSetControl)]
+ public delegate Status NvAPI_GPU_ClientIlluminationZonesSetControl(
+ [In] PhysicalGPUHandle gpu,
+ [Accepts(typeof(IlluminationZoneControlParametersV1))] [In]
+ ValueTypeReference illuminationZoneControlInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientPowerPoliciesGetInfo)]
+ public delegate Status NvAPI_GPU_ClientPowerPoliciesGetInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivatePowerPoliciesInfoV1))] [In]
+ ValueTypeReference powerInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientPowerPoliciesGetStatus)]
+ public delegate Status NvAPI_GPU_ClientPowerPoliciesGetStatus(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivatePowerPoliciesStatusV1))] [In]
+ ValueTypeReference status);
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientPowerPoliciesSetStatus)]
+ public delegate Status NvAPI_GPU_ClientPowerPoliciesSetStatus(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivatePowerPoliciesStatusV1))] [In]
+ ValueTypeReference status);
+
+ [FunctionId(FunctionId.NvAPI_GPU_ClientPowerTopologyGetStatus)]
+ public delegate Status NvAPI_GPU_ClientPowerTopologyGetStatus(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivatePowerTopologiesStatusV1))] [In]
+ ValueTypeReference status);
+
+ [FunctionId(FunctionId.NvAPI_GPU_EnableDynamicPstates)]
+ public delegate Status NvAPI_GPU_EnableDynamicPStates([In] PhysicalGPUHandle physicalGpu);
+
+ [FunctionId(FunctionId.NvAPI_GPU_EnableOverclockedPstates)]
+ public delegate Status NvAPI_GPU_EnableOverclockedPStates([In] PhysicalGPUHandle physicalGpu);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetActiveOutputs)]
+ public delegate Status NvAPI_GPU_GetActiveOutputs(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out OutputId outputMask);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetAGPAperture)]
+ public delegate Status NvAPI_GPU_GetAGPAperture(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint size);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetAllClockFrequencies)]
+ public delegate Status NvAPI_GPU_GetAllClockFrequencies(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(ClockFrequenciesV3), typeof(ClockFrequenciesV2), typeof(ClockFrequenciesV1))]
+ ValueTypeReference nvClocks);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetAllDisplayIds)]
+ public delegate Status NvAPI_GPU_GetAllDisplayIds(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(DisplayIdsV2))] [In] [Out]
+ ValueTypeArray pDisplayIds,
+ [In] [Out] ref uint displayIdCount);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetArchInfo)]
+ public delegate Status NvAPI_GPU_GetArchInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivateArchitectInfoV2))] [In]
+ ValueTypeReference info);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetBoardInfo)]
+ public delegate Status NvAPI_GPU_GetBoardInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] [In] ref BoardInfo info);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetBusId)]
+ public delegate Status NvAPI_GPU_GetBusId(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint gpuBusId);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetBusSlotId)]
+ public delegate Status NvAPI_GPU_GetBusSlotId(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint gpuBusSlotId);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetBusType)]
+ public delegate Status NvAPI_GPU_GetBusType(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out GPUBusType gpuBusType);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetClockBoostLock)]
+ public delegate Status NvAPI_GPU_GetClockBoostLock(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivateClockBoostLockV2))]
+ ValueTypeReference clockLocks);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetClockBoostMask)]
+ public delegate Status NvAPI_GPU_GetClockBoostMask(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivateClockBoostMasksV1))]
+ ValueTypeReference clockMasks);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetClockBoostRanges)]
+ public delegate Status NvAPI_GPU_GetClockBoostRanges(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivateClockBoostRangesV1))]
+ ValueTypeReference clockRanges);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetClockBoostTable)]
+ public delegate Status NvAPI_GPU_GetClockBoostTable(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivateClockBoostTableV1))]
+ ValueTypeReference boostTable);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetConnectedDisplayIds)]
+ public delegate Status NvAPI_GPU_GetConnectedDisplayIds(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(DisplayIdsV2))] [In] [Out]
+ ValueTypeArray pDisplayIds,
+ [In] [Out] ref uint displayIdCount,
+ [In] ConnectedIdsFlag flags);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetCoolerPolicyTable)]
+ public delegate Status NvAPI_GPU_GetCoolerPolicyTable(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] uint index,
+ [In] [Accepts(typeof(PrivateCoolerPolicyTableV1))]
+ ValueTypeReference coolerPolicyTable,
+ [Out] out uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetCoolerSettings)]
+ public delegate Status NvAPI_GPU_GetCoolerSettings(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] CoolerTarget coolerIndex,
+ [In] [Accepts(typeof(PrivateCoolerSettingsV1))]
+ ValueTypeReference coolerSettings);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetCoreVoltageBoostPercent)]
+ public delegate Status NvAPI_GPU_GetCoreVoltageBoostPercent(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivateVoltageBoostPercentV1))]
+ ValueTypeReference voltageBoostPercent);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetCurrentAGPRate)]
+ public delegate Status NvAPI_GPU_GetCurrentAGPRate(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint rate);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetCurrentFanSpeedLevel)]
+ public delegate Status NvAPI_GPU_GetCurrentFanSpeedLevel(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint fanLevel);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetCurrentPCIEDownstreamWidth)]
+ public delegate Status NvAPI_GPU_GetCurrentPCIEDownstreamWidth(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint width);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetCurrentPstate)]
+ public delegate Status NvAPI_GPU_GetCurrentPState(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out PerformanceStateId performanceStateId);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetCurrentThermalLevel)]
+ public delegate Status NvAPI_GPU_GetCurrentThermalLevel(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint thermalLevel);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetCurrentVoltage)]
+ public delegate Status NvAPI_GPU_GetCurrentVoltage(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivateVoltageStatusV1))]
+ ValueTypeReference voltageStatus);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetDynamicPstatesInfoEx)]
+ public delegate Status NvAPI_GPU_GetDynamicPStatesInfoEx(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(DynamicPerformanceStatesInfoV1))]
+ ValueTypeReference performanceStatesInfoEx);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetECCConfigurationInfo)]
+ public delegate Status NvAPI_GPU_GetECCConfigurationInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(ECCConfigurationInfoV1))]
+ ValueTypeReference eccConfigurationInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetECCErrorInfo)]
+ public delegate Status NvAPI_GPU_GetECCErrorInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(ECCErrorInfoV1))] ValueTypeReference eccErrorInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetECCStatusInfo)]
+ public delegate Status NvAPI_GPU_GetECCStatusInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(ECCStatusInfoV1))]
+ ValueTypeReference eccStatusInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetEDID)]
+ public delegate Status NvAPI_GPU_GetEDID(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] OutputId outputId,
+ [Accepts(typeof(EDIDV3), typeof(EDIDV2), typeof(EDIDV1))] [In]
+ ValueTypeReference edid);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetFBWidthAndLocation)]
+ public delegate Status NvAPI_GPU_GetFBWidthAndLocation(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint width,
+ [Out] out uint location);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetFoundry)]
+ public delegate Status NvAPI_GPU_GetFoundry(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out GPUFoundry pFoundry);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetFullName)]
+ public delegate Status NvAPI_GPU_GetFullName(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out ShortString name);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetGpuCoreCount)]
+ public delegate Status NvAPI_GPU_GetGpuCoreCount(
+ [In] PhysicalGPUHandle gpuHandle,
+ [Out] out uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetGPUType)]
+ public delegate Status NvAPI_GPU_GetGPUType(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out GPUType gpuType);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetIllumination)]
+ public delegate Status NvAPI_GPU_GetIllumination(
+ [Accepts(typeof(GetIlluminationParameterV1))] [In]
+ ValueTypeReference illuminationInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetIRQ)]
+ public delegate Status NvAPI_GPU_GetIRQ(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint gpuIRQ);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetLogicalFBWidthAndLocation)]
+ public delegate Status NvAPI_GPU_GetLogicalFBWidthAndLocation(
+ [In] LogicalGPUHandle logicalGpu,
+ [Out] out uint width,
+ [Out] out uint location);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetMemoryInfo)]
+ public delegate Status NvAPI_GPU_GetMemoryInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In]
+ [Accepts(typeof(DisplayDriverMemoryInfoV3), typeof(DisplayDriverMemoryInfoV2),
+ typeof(DisplayDriverMemoryInfoV1))]
+ ValueTypeReference memoryInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetOutputType)]
+ public delegate Status NvAPI_GPU_GetOutputType(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] uint outputId,
+ [Out] out OutputType outputType);
+
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetPartitionCount)]
+ public delegate Status NvAPI_GPU_GetPartitionCount(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetPCIEInfo)]
+ public delegate Status NvAPI_GPU_GetPCIEInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivatePCIeInfoV2))] [In]
+ ValueTypeReference pcieInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetPCIIdentifiers)]
+ public delegate Status NvAPI_GPU_GetPCIIdentifiers(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint deviceId,
+ [Out] out uint subSystemId,
+ [Out] out uint revisionId,
+ [Out] out uint extDeviceId);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetPerfDecreaseInfo)]
+ public delegate Status NvAPI_GPU_GetPerfDecreaseInfo(
+ [In] PhysicalGPUHandle gpu,
+ [Out] out PerformanceDecreaseReason performanceDecreaseReason);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetPhysicalFrameBufferSize)]
+ public delegate Status NvAPI_GPU_GetPhysicalFrameBufferSize(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint size);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetPstates20)]
+ public delegate Status NvAPI_GPU_GetPStates20(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(
+ typeof(PerformanceStates20InfoV3),
+ typeof(PerformanceStates20InfoV2),
+ typeof(PerformanceStates20InfoV1)
+ )]
+ [In]
+ ValueTypeReference performanceStatesInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetPstatesInfoEx)]
+ public delegate Status NvAPI_GPU_GetPStatesInfoEx(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(
+ typeof(PerformanceStatesInfoV3),
+ typeof(PerformanceStatesInfoV2),
+ typeof(PerformanceStatesInfoV1)
+ )]
+ [In]
+ ValueTypeReference performanceStatesInfo,
+ [In] GetPerformanceStatesInfoFlags flags);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetQuadroStatus)]
+ public delegate Status NvAPI_GPU_GetQuadroStatus(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint isQuadro);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetRamBankCount)]
+ public delegate Status NvAPI_GPU_GetRamBankCount(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetRamBusWidth)]
+ public delegate Status NvAPI_GPU_GetRamBusWidth(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint busWidth);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetRamMaker)]
+ public delegate Status NvAPI_GPU_GetRamMaker(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out GPUMemoryMaker maker);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetRamType)]
+ public delegate Status NvAPI_GPU_GetRamType(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out GPUMemoryType type);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetROPCount)]
+ public delegate Status NvAPI_GPU_GetROPCount(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetShaderPipeCount)]
+ public delegate Status NvAPI_GPU_GetShaderPipeCount(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetShaderSubPipeCount)]
+ public delegate Status NvAPI_GPU_GetShaderSubPipeCount(
+ [In] PhysicalGPUHandle gpuHandle,
+ [Out] out uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetShortName)]
+ public delegate Status NvAPI_GPU_GetShortName(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out ShortString name);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetSystemType)]
+ public delegate Status NvAPI_GPU_GetSystemType(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out SystemType systemType);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetTachReading)]
+ public delegate Status NvAPI_GPU_GetTachReading(
+ [In] PhysicalGPUHandle gpuHandle,
+ [Out] out uint value);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetThermalPoliciesInfo)]
+ public delegate Status NvAPI_GPU_GetThermalPoliciesInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivateThermalPoliciesInfoV2))] [In]
+ ValueTypeReference info);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetThermalPoliciesStatus)]
+ public delegate Status NvAPI_GPU_GetThermalPoliciesStatus(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivateThermalPoliciesStatusV2))] [In]
+ ValueTypeReference info);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetThermalSettings)]
+ public delegate Status NvAPI_GPU_GetThermalSettings(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] ThermalSettingsTarget sensorIndex,
+ [In] [Accepts(typeof(ThermalSettingsV2), typeof(ThermalSettingsV1))]
+ ValueTypeReference thermalSettings);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetTotalSMCount)]
+ public delegate Status NvAPI_GPU_GetTotalSMCount(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetTotalSPCount)]
+ public delegate Status NvAPI_GPU_GetTotalSPCount(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetTotalTPCCount)]
+ public delegate Status NvAPI_GPU_GetTotalTPCCount(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetUsages)]
+ public delegate Status NvAPI_GPU_GetUsages(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivateUsagesInfoV1))]
+ ValueTypeReference usageInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetVbiosOEMRevision)]
+ public delegate Status NvAPI_GPU_GetVbiosOEMRevision(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint biosOEMRevision);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetVbiosRevision)]
+ public delegate Status NvAPI_GPU_GetVbiosRevision(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint biosRevision);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetVbiosVersionString)]
+ public delegate Status NvAPI_GPU_GetVbiosVersionString(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out ShortString biosVersion);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetVFPCurve)]
+ public delegate Status NvAPI_GPU_GetVFPCurve(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivateVFPCurveV1))]
+ ValueTypeReference vfpCurve);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetVirtualFrameBufferSize)]
+ public delegate Status NvAPI_GPU_GetVirtualFrameBufferSize(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint size);
+
+ [FunctionId(FunctionId.NvAPI_GPU_GetVPECount)]
+ public delegate Status NvAPI_GPU_GetVPECount(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] out uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_PerfPoliciesGetInfo)]
+ public delegate Status NvAPI_GPU_PerfPoliciesGetInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivatePerformanceInfoV1))]
+ ValueTypeReference performanceInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_PerfPoliciesGetStatus)]
+ public delegate Status NvAPI_GPU_PerfPoliciesGetStatus(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivatePerformanceStatusV1))]
+ ValueTypeReference performanceStatus);
+
+ [FunctionId(FunctionId.NvAPI_GPU_QueryActiveApps)]
+ public delegate Status NvAPI_GPU_QueryActiveApps(
+ [In] PhysicalGPUHandle gpu,
+ [In] [Accepts(typeof(PrivateActiveApplicationV2))]
+ ValueTypeArray applications,
+ [In] [Out] ref uint numberOfApplications
+ );
+
+
+ [FunctionId(FunctionId.NvAPI_GPU_QueryIlluminationSupport)]
+ public delegate Status NvAPI_GPU_QueryIlluminationSupport(
+ [Accepts(typeof(QueryIlluminationSupportParameterV1))] [In]
+ ValueTypeReference illuminationSupportInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_ResetECCErrorInfo)]
+ public delegate Status NvAPI_GPU_ResetECCErrorInfo(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] byte resetCurrent,
+ [In] byte resetAggregated
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_RestoreCoolerPolicyTable)]
+ public delegate Status NvAPI_GPU_RestoreCoolerPolicyTable(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] uint[] indexes,
+ [In] uint indexesCount,
+ [In] CoolerPolicy policy);
+
+ [FunctionId(FunctionId.NvAPI_GPU_RestoreCoolerSettings)]
+ public delegate Status NvAPI_GPU_RestoreCoolerSettings(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] uint[] indexes,
+ [In] uint indexesCount);
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetClockBoostLock)]
+ public delegate Status NvAPI_GPU_SetClockBoostLock(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivateClockBoostLockV2))]
+ ValueTypeReference clockLocks);
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetClockBoostTable)]
+ public delegate Status NvAPI_GPU_SetClockBoostTable(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivateClockBoostTableV1))]
+ ValueTypeReference boostTable);
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetCoolerLevels)]
+ public delegate Status NvAPI_GPU_SetCoolerLevels(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] uint index,
+ [In] [Accepts(typeof(PrivateCoolerLevelsV1))]
+ ValueTypeReference coolerLevels,
+ [In] uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetCoolerPolicyTable)]
+ public delegate Status NvAPI_GPU_SetCoolerPolicyTable(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] uint index,
+ [In] [Accepts(typeof(PrivateCoolerPolicyTableV1))]
+ ValueTypeReference coolerLevels,
+ [In] uint count);
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetCoreVoltageBoostPercent)]
+ public delegate Status NvAPI_GPU_SetCoreVoltageBoostPercent(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(PrivateVoltageBoostPercentV1))]
+ ValueTypeReference voltageBoostPercent);
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetECCConfiguration)]
+ public delegate Status NvAPI_GPU_SetECCConfiguration(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] byte isEnable,
+ [In] byte isEnableImmediately
+ );
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetEDID)]
+ public delegate Status NvAPI_GPU_SetEDID(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] uint outputId,
+ [Accepts(typeof(EDIDV3), typeof(EDIDV2), typeof(EDIDV1))] [In]
+ ValueTypeReference edid);
+
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetIllumination)]
+ public delegate Status NvAPI_GPU_SetIllumination(
+ [Accepts(typeof(SetIlluminationParameterV1))] [In]
+ ValueTypeReference illuminationInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetPstates20)]
+ public delegate Status NvAPI_GPU_SetPStates20(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PerformanceStates20InfoV3), typeof(PerformanceStates20InfoV2),
+ typeof(PerformanceStates20InfoV1))]
+ [In]
+ ValueTypeReference performanceStatesInfo);
+
+ [FunctionId(FunctionId.NvAPI_GPU_SetThermalPoliciesStatus)]
+ public delegate Status NvAPI_GPU_SetThermalPoliciesStatus(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Accepts(typeof(PrivateThermalPoliciesStatusV2))] [In]
+ ValueTypeReference info);
+
+ [FunctionId(FunctionId.NvAPI_GPU_ValidateOutputCombination)]
+ public delegate Status NvAPI_GPU_ValidateOutputCombination(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] OutputId outputMask);
+
+ [FunctionId(FunctionId.NvAPI_I2CRead)]
+ public delegate Status NvAPI_I2CRead(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(I2CInfoV3), typeof(I2CInfoV2))] ValueTypeReference i2cInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_I2CWrite)]
+ public delegate Status NvAPI_I2CWrite(
+ [In] PhysicalGPUHandle physicalGpu,
+ [In] [Accepts(typeof(I2CInfoV3), typeof(I2CInfoV2))] ValueTypeReference i2cInfo
+ );
+
+ [FunctionId(FunctionId.NvAPI_SYS_GetDisplayIdFromGpuAndOutputId)]
+ public delegate Status NvAPI_SYS_GetDisplayIdFromGpuAndOutputId(
+ [In] PhysicalGPUHandle gpu,
+ [In] OutputId outputId,
+ [Out] out uint displayId);
+
+ [FunctionId(FunctionId.NvAPI_SYS_GetGpuAndOutputIdFromDisplayId)]
+ public delegate Status NvAPI_SYS_GetGpuAndOutputIdFromDisplayId(
+ [In] uint displayId,
+ [Out] out PhysicalGPUHandle gpu,
+ [Out] out OutputId outputId);
+
+ [FunctionId(FunctionId.NvAPI_SYS_GetPhysicalGpuFromDisplayId)]
+ public delegate Status NvAPI_SYS_GetPhysicalGpuFromDisplayId(
+ [In] uint displayId,
+ [Out] out PhysicalGPUHandle gpu);
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Delegates/General.cs b/NvAPIWrapper/Native/Delegates/General.cs
new file mode 100644
index 0000000..ab5e2cd
--- /dev/null
+++ b/NvAPIWrapper/Native/Delegates/General.cs
@@ -0,0 +1,43 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Helpers.Structures;
+
+// ReSharper disable InconsistentNaming
+
+namespace NvAPIWrapper.Native.Delegates
+{
+ internal static class General
+ {
+ [FunctionId(FunctionId.NvAPI_GetErrorMessage)]
+ public delegate Status NvAPI_GetErrorMessage([In] Status status, out ShortString message);
+
+ [FunctionId(FunctionId.NvAPI_GetInterfaceVersionString)]
+ public delegate Status NvAPI_GetInterfaceVersionString(out ShortString version);
+
+ [FunctionId(FunctionId.NvAPI_Initialize)]
+ public delegate Status NvAPI_Initialize();
+
+
+ [FunctionId(FunctionId.NvAPI_RestartDisplayDriver)]
+ public delegate Status NvAPI_RestartDisplayDriver();
+
+ [FunctionId(FunctionId.NvAPI_SYS_GetChipSetInfo)]
+ public delegate Status NvAPI_SYS_GetChipSetInfo(
+ [In] [Accepts(typeof(ChipsetInfoV4), typeof(ChipsetInfoV3), typeof(ChipsetInfoV2), typeof(ChipsetInfoV1))]
+ ValueTypeReference chipsetInfo);
+
+ [FunctionId(FunctionId.NvAPI_SYS_GetDriverAndBranchVersion)]
+ public delegate Status NvAPI_SYS_GetDriverAndBranchVersion(
+ out uint driverVersion,
+ out ShortString buildBranchString);
+
+ [FunctionId(FunctionId.NvAPI_SYS_GetLidAndDockInfo)]
+ public delegate Status NvAPI_SYS_GetLidAndDockInfo([In] [Out] ref LidDockParameters lidAndDock);
+
+ [FunctionId(FunctionId.NvAPI_Unload)]
+ public delegate Status NvAPI_Unload();
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/ColorDataColorimetry.cs b/NvAPIWrapper/Native/Display/ColorDataColorimetry.cs
new file mode 100644
index 0000000..e87908a
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ColorDataColorimetry.cs
@@ -0,0 +1,74 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for color data color space
+ ///
+ public enum ColorDataColorimetry : uint
+ {
+ ///
+ /// RGB color space
+ ///
+ RGB = 0,
+
+ ///
+ /// YCC601 color space
+ ///
+ YCC601,
+
+ ///
+ /// YCC709 color space
+ ///
+ YCC709,
+
+ ///
+ /// XVYCC601 color space
+ ///
+ XVYCC601,
+
+ ///
+ /// XVYCC709 color space
+ ///
+ XVYCC709,
+
+ ///
+ /// SYCC601 color space
+ ///
+ SYCC601,
+
+ ///
+ /// ADOBEYCC601 color space
+ ///
+ ADOBEYCC601,
+
+ ///
+ /// ADOBERGB color space
+ ///
+ ADOBERGB,
+
+ ///
+ /// BT2020RGB color space
+ ///
+ BT2020RGB,
+
+ ///
+ /// BT2020YCC color space
+ ///
+ BT2020YCC,
+
+ ///
+ /// BT2020cYCC color space
+ ///
+ // ReSharper disable once InconsistentNaming
+ BT2020cYCC,
+
+ ///
+ /// Default color space
+ ///
+ Default = 0xFE,
+
+ ///
+ /// Automatically select color space
+ ///
+ Auto = 0xFF
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/ColorDataCommand.cs b/NvAPIWrapper/Native/Display/ColorDataCommand.cs
new file mode 100644
index 0000000..cf1761f
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ColorDataCommand.cs
@@ -0,0 +1,28 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for the color data command
+ ///
+ public enum ColorDataCommand : uint
+ {
+ ///
+ /// Get the current color data
+ ///
+ Get = 1,
+
+ ///
+ /// Set the current color data
+ ///
+ Set,
+
+ ///
+ /// Check if the passed color data is supported
+ ///
+ IsSupportedColor,
+
+ ///
+ /// Get the default color data
+ ///
+ GetDefault
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/ColorDataDepth.cs b/NvAPIWrapper/Native/Display/ColorDataDepth.cs
new file mode 100644
index 0000000..e77eb89
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ColorDataDepth.cs
@@ -0,0 +1,38 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for the color data depth
+ ///
+ public enum ColorDataDepth : uint
+ {
+ ///
+ /// Default color depth meaning that the current setting should be kept
+ ///
+ Default = 0,
+
+ ///
+ /// 6bit per color depth
+ ///
+ BPC6 = 1,
+
+ ///
+ /// 8bit per color depth
+ ///
+ BPC8 = 2,
+
+ ///
+ /// 10bit per color depth
+ ///
+ BPC10 = 3,
+
+ ///
+ /// 12bit per color depth
+ ///
+ BPC12 = 4,
+
+ ///
+ /// 16bit per color depth
+ ///
+ BPC16 = 5
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/ColorDataDesktopDepth.cs b/NvAPIWrapper/Native/Display/ColorDataDesktopDepth.cs
new file mode 100644
index 0000000..7d5673d
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ColorDataDesktopDepth.cs
@@ -0,0 +1,38 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for the color data desktop color depth
+ ///
+ public enum ColorDataDesktopDepth : uint
+ {
+ ///
+ /// Default color depth meaning that the current setting should be kept
+ ///
+ Default = 0x0,
+
+ ///
+ /// 8bit per integer color component
+ ///
+ BPC8 = 0x1,
+
+ ///
+ /// 10bit integer per color component
+ ///
+ BPC10 = 0x2,
+
+ ///
+ /// 16bit float per color component
+ ///
+ BPC16Float = 0x3,
+
+ ///
+ /// 16bit float per color component wide color gamut
+ ///
+ BPC16FloatWcg = 0x4,
+
+ ///
+ /// 16bit float per color component HDR
+ ///
+ BPC16FloatHDR = 0x5
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/ColorDataDynamicRange.cs b/NvAPIWrapper/Native/Display/ColorDataDynamicRange.cs
new file mode 100644
index 0000000..16dee35
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ColorDataDynamicRange.cs
@@ -0,0 +1,23 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for color data dynamic range
+ ///
+ public enum ColorDataDynamicRange : uint
+ {
+ ///
+ /// VESA standard progress signal
+ ///
+ VESA = 0,
+
+ ///
+ /// CEA interlaced signal
+ ///
+ CEA,
+
+ ///
+ /// Automatically select the best value
+ ///
+ Auto
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/ColorDataFormat.cs b/NvAPIWrapper/Native/Display/ColorDataFormat.cs
new file mode 100644
index 0000000..42f26e2
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ColorDataFormat.cs
@@ -0,0 +1,38 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible color data color format values
+ ///
+ public enum ColorDataFormat : uint
+ {
+ ///
+ /// RGB color format
+ ///
+ RGB = 0,
+
+ ///
+ /// YUV422 color format
+ ///
+ YUV422,
+
+ ///
+ /// YUV444 color format
+ ///
+ YUV444,
+
+ ///
+ /// YUV420 color format
+ ///
+ YUV420,
+
+ ///
+ /// Default color format
+ ///
+ Default = 0xFE,
+
+ ///
+ /// Automatically select the best color format
+ ///
+ Auto = 0xFF
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/ColorDataHDRCommand.cs b/NvAPIWrapper/Native/Display/ColorDataHDRCommand.cs
new file mode 100644
index 0000000..9cb1fd3
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ColorDataHDRCommand.cs
@@ -0,0 +1,18 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for the HDR color data command
+ ///
+ public enum ColorDataHDRCommand : uint
+ {
+ ///
+ /// Get the current HDR color data
+ ///
+ Get = 0,
+
+ ///
+ /// Set the current HDR color data
+ ///
+ Set = 1
+ }
+}
diff --git a/NvAPIWrapper/Native/Display/ColorDataHDRMode.cs b/NvAPIWrapper/Native/Display/ColorDataHDRMode.cs
new file mode 100644
index 0000000..7d49042
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ColorDataHDRMode.cs
@@ -0,0 +1,61 @@
+using System;
+
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible color data HDR modes
+ ///
+ public enum ColorDataHDRMode : uint
+ {
+ ///
+ /// Turn off HDR.
+ ///
+ Off = 0,
+
+ ///
+ /// Source: CCCS [a.k.a FP16 scRGB, linear, sRGB primaries, [-65504,0, 65504] range, RGB(1,1,1) = 80nits]
+ /// Output: UHDA HDR [a.k.a HDR10, RGB/YCC 10/12bpc ST2084(PQ) EOTF RGB(1,1,1) = 10000 nits, Rec2020 color primaries,
+ /// ST2086 static HDR metadata].
+ /// This is the only supported production HDR mode.
+ ///
+ UHDA = 2,
+
+ ///
+ /// Source: CCCS (a.k.a FP16 scRGB)
+ /// Output: EDR (Extended Dynamic Range) - HDR content is tone-mapped and gamut mapped to output on regular SDR display
+ /// set to max luminance ( ~300 nits ).
+ ///
+ [Obsolete("Do not use! Internal test mode only, to be removed.", false)]
+ EDR = 3,
+
+ ///
+ /// Source: any
+ /// Output: SDR (Standard Dynamic Range), we continuously send SDR EOTF InfoFrame signaling, HDMI compliance testing.
+ ///
+ [Obsolete("Do not use! Internal test mode only, to be removed.", false)]
+ SDR = 4,
+
+ ///
+ /// Source: HDR10 RGB 10bpc
+ /// Output: HDR10 RGB 10 colorDepth - signal UHDA HDR mode (PQ + Rec2020) to the sink but send source pixel values
+ /// unmodified (no PQ or Rec2020 conversions) - assumes source is already in HDR10 format.
+ ///
+ [Obsolete("Experimental mode only, not for production!", false)]
+ UHDAPassthrough = 5,
+
+ ///
+ /// Source: CCCS (a.k.a FP16 scRGB)
+ /// Output: notebook HDR
+ ///
+ [Obsolete("Do not use! Internal test mode only, to be removed.", false)]
+ UHDANB = 6,
+
+ ///
+ /// Source: RGB8 Dolby Vision encoded (12 colorDepth YCbCr422 packed into RGB8)
+ /// Output: Dolby Vision encoded : Application is to encoded frames in DV format and embed DV dynamic metadata as
+ /// described in Dolby Vision specification.
+ ///
+ [Obsolete("Experimental mode only, not for production!", false)]
+ DolbyVision = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/ColorDataSelectionPolicy.cs b/NvAPIWrapper/Native/Display/ColorDataSelectionPolicy.cs
new file mode 100644
index 0000000..86468b2
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ColorDataSelectionPolicy.cs
@@ -0,0 +1,28 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Possible values for the color data selection policy
+ ///
+ public enum ColorDataSelectionPolicy : uint
+ {
+ ///
+ /// Application or the Nvidia Control Panel user configuration are used to decide the best color format
+ ///
+ User = 0,
+
+ ///
+ /// Driver or the Operating System decides the best color format
+ ///
+ BestQuality = 1,
+
+ ///
+ /// Default value,
+ ///
+ Default = BestQuality,
+
+ ///
+ /// Unknown policy
+ ///
+ Unknown = 0xFF
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/ColorFormat.cs b/NvAPIWrapper/Native/Display/ColorFormat.cs
new file mode 100644
index 0000000..56d436f
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ColorFormat.cs
@@ -0,0 +1,33 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Possible color formats
+ ///
+ public enum ColorFormat
+ {
+ ///
+ /// Unknown, driver will choose one automatically.
+ ///
+ Unknown = 0,
+
+ ///
+ /// 8bpp mode
+ ///
+ P8 = 41,
+
+ ///
+ /// 16bpp mode
+ ///
+ R5G6B5 = 23,
+
+ ///
+ /// 32bpp mode
+ ///
+ A8R8G8B8 = 21,
+
+ ///
+ /// 64bpp (floating point)
+ ///
+ A16B16G16R16F = 113
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/DisplayConfigFlags.cs b/NvAPIWrapper/Native/Display/DisplayConfigFlags.cs
new file mode 100644
index 0000000..f92ed18
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/DisplayConfigFlags.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Flags for applying settings, used by NvAPI_DISP_SetDisplayConfig()
+ ///
+ [Flags]
+ public enum DisplayConfigFlags
+ {
+ ///
+ /// None
+ ///
+ None = 0,
+
+ ///
+ /// Do not apply
+ ///
+ ValidateOnly = 0x00000001,
+
+ ///
+ /// Save to the persistence storage
+ ///
+ SaveToPersistence = 0x00000002,
+
+ ///
+ /// Driver reload is permitted if necessary
+ ///
+ DriverReloadAllowed = 0x00000004,
+
+ ///
+ /// Refresh OS mode list.
+ ///
+ ForceModeEnumeration = 0x00000008,
+
+ ///
+ /// Tell OS to avoid optimizing CommitVidPn call during a modeset
+ ///
+ ForceCommitVideoPresentNetwork = 0x00000010
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/DisplayPortColorDepth.cs b/NvAPIWrapper/Native/Display/DisplayPortColorDepth.cs
new file mode 100644
index 0000000..a8ad307
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/DisplayPortColorDepth.cs
@@ -0,0 +1,34 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Possible display port color depths
+ ///
+ public enum DisplayPortColorDepth : uint
+ {
+ ///
+ /// Default color depth
+ ///
+ Default = 0,
+ ///
+ /// 6 bit per color color depth
+ ///
+ BPC6,
+ ///
+ /// 8 bit per color color depth
+ ///
+ BPC8,
+ ///
+ /// 10 bit per color color depth
+ ///
+ BPC10,
+ ///
+ /// 12 bit per color color depth
+ ///
+ BPC12,
+
+ ///
+ /// 16 bit per color color depth
+ ///
+ BPC16,
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/DisplayPortColorFormat.cs b/NvAPIWrapper/Native/Display/DisplayPortColorFormat.cs
new file mode 100644
index 0000000..8ab1367
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/DisplayPortColorFormat.cs
@@ -0,0 +1,23 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Possible display port color formats
+ ///
+ public enum DisplayPortColorFormat : uint
+ {
+ ///
+ /// RGB color format
+ ///
+ RGB = 0,
+
+ ///
+ /// YCbCr422 color format
+ ///
+ YCbCr422 = 1,
+
+ ///
+ /// YCbCr444 color format
+ ///
+ YCbCr444 = 2
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameAudioChannelAllocation.cs b/NvAPIWrapper/Native/Display/InfoFrameAudioChannelAllocation.cs
new file mode 100644
index 0000000..0704a12
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameAudioChannelAllocation.cs
@@ -0,0 +1,300 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible audio channel allocations (speaker placements)
+ ///
+ public enum InfoFrameAudioChannelAllocation : uint
+ {
+ ///
+ /// [0] Empty [1] Empty [2] Empty [3] Empty [4] Empty [5] Empty [6] Front Right [7] Front Left
+ ///
+ FrFl = 0,
+
+ ///
+ /// [0] Empty [1] Empty [2] Empty [3] Empty [4] Empty [5] Low Frequency Effects [6] Front Right [7] Front Left
+ ///
+ LfeFrFl,
+
+ ///
+ /// [0] Empty [1] Empty [2] Empty [3] Empty [4] Front Center [5] Empty [6] Front Right [7] Front Left
+ ///
+ FcFrFl,
+
+ ///
+ /// [0] Empty [1] Empty [2] Empty [3] Empty [4] Front Center [5] Low Frequency Effects [6] Front Right [7] Front Left
+ ///
+ FcLfeFrFl,
+
+ ///
+ /// [0] Empty [1] Empty [2] Empty [3] Rear Center [4] Empty [5] Empty [6] Front Right [7] Front Left
+ ///
+ RcFrFl,
+
+ ///
+ /// [0] Empty [1] Empty [2] Empty [3] Rear Center [4] Empty [5] Low Frequency Effects [6] Front Right [7] Front Left
+ ///
+ RcLfeFrFl,
+
+ ///
+ /// [0] Empty [1] Empty [2] Empty [3] Rear Center [4] Front Center [5] Empty [6] Front Right [7] Front Left
+ ///
+ RcFcFrFl,
+
+ ///
+ /// [0] Empty [1] Empty [2] Empty [3] Rear Center [4] Front Center [5] Low Frequency Effects [6] Front Right [7] Front
+ /// Left
+ ///
+ RcFcLfeFrFl,
+
+ ///
+ /// [0] Empty [1] Empty [2] Rear Right [3] Rear Left [4] Empty [5] Empty [6] Front Right [7] Front Left
+ ///
+ RrRlFrFl,
+
+ ///
+ /// [0] Empty [1] Empty [2] Rear Right [3] Rear Left [4] Empty [5] Low Frequency Effects [6] Front Right [7] Front Left
+ ///
+ RrRlLfeFrFl,
+
+ ///
+ /// [0] Empty [1] Empty [2] Rear Right [3] Rear Left [4] Front Center [5] Empty [6] Front Right [7] Front Left
+ ///
+ RrRlFcFrFl,
+
+ ///
+ /// [0] Empty [1] Empty [2] Rear Right [3] Rear Left [4] Front Center [5] Low Frequency Effects [6] Front Right [7]
+ /// Front Left
+ ///
+ RrRlFcLfeFrFl,
+
+ ///
+ /// [0] Empty [1] Rear Center [2] Rear Right [3] Rear Left [4] Empty [5] Empty [6] Front Right [7] Front Left
+ ///
+ RcRrRlFrFl,
+
+ ///
+ /// [0] Empty [1] Rear Center [2] Rear Right [3] Rear Left [4] Empty [5] Low Frequency Effects [6] Front Right [7]
+ /// Front Left
+ ///
+ RcRrRlLfeFrFl,
+
+ ///
+ /// [0] Empty [1] Rear Center [2] Rear Right [3] Rear Left [4] Front Center [5] Empty [6] Front Right [7] Front Left
+ ///
+ RcRrRlFcFrFl,
+
+ ///
+ /// [0] Empty [1] Rear Center [2] Rear Right [3] Rear Left [4] Front Center [5] Low Frequency Effects [6] Front Right
+ /// [7] Front Left
+ ///
+ RcRrRlFcLfeFrFl,
+
+ ///
+ /// [0] Rear Right Of Center [1] Rear Left Of Center [2] Rear Right [3] Rear Left [4] Empty [5] Empty [6] Front Right
+ /// [7] Front Left
+ ///
+ RrcRlcRrRlFrFl,
+
+ ///
+ /// [0] Rear Right Of Center [1] Rear Left Of Center [2] Rear Right [3] Rear Left [4] Empty [5] Low Frequency Effects
+ /// [6] Front Right [7] Front Left
+ ///
+ RrcRlcRrRlLfeFrFl,
+
+ ///
+ /// [0] Rear Right Of Center [1] Rear Left Of Center [2] Rear Right [3] Rear Left [4] Front Center [5] Empty [6] Front
+ /// Right [7] Front Left
+ ///
+ RrcRlcRrRlFcFrFl,
+
+ ///
+ /// [0] Rear Right Of Center [1] Rear Left Of Center [2] Rear Right [3] Rear Left [4] Front Center [5] Low Frequency
+ /// Effects [6] Front Right [7] Front Left
+ ///
+ RrcRlcRrRlFcLfeFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Empty [3] Empty [4] Empty [5] Empty [6] Front Right [7]
+ /// Front Left
+ ///
+ FrcFlcFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Empty [3] Empty [4] Empty [5] Low Frequency Effects [6]
+ /// Front Right [7] Front Left
+ ///
+ FrcFlcLfeFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Empty [3] Empty [4] Front Center [5] Empty [6] Front Right
+ /// [7] Front Left
+ ///
+ FrcFlcFcFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Empty [3] Empty [4] Front Center [5] Low Frequency Effects
+ /// [6] Front Right [7] Front Left
+ ///
+ FrcFlcFcLfeFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Empty [3] Rear Center [4] Empty [5] Empty [6] Front Right
+ /// [7] Front Left
+ ///
+ FrcFlcRcFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Empty [3] Rear Center [4] Empty [5] Low Frequency Effects
+ /// [6] Front Right [7] Front Left
+ ///
+ FrcFlcRcLfeFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Empty [3] Rear Center [4] Front Center [5] Empty [6] Front
+ /// Right [7] Front Left
+ ///
+ FrcFlcRcFcFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Empty [3] Rear Center [4] Front Center [5] Low Frequency
+ /// Effects [6] Front Right [7] Front Left
+ ///
+ FrcFlcRcFcLfeFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Rear Right [3] Rear Left [4] Empty [5] Empty [6] Front Right
+ /// [7] Front Left
+ ///
+ FrcFlcRrRlFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Rear Right [3] Rear Left [4] Empty [5] Low Frequency Effects
+ /// [6] Front Right [7] Front Left
+ ///
+ FrcFlcRrRlLfeFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Rear Right [3] Rear Left [4] Front Center [5] Empty [6]
+ /// Front Right [7] Front Left
+ ///
+ FrcFlcRrRlFcFrFl,
+
+ ///
+ /// [0] Front Right Of Center [1] Front Left Of Center [2] Rear Right [3] Rear Left [4] Front Center [5] Low Frequency
+ /// Effects [6] Front Right [7] Front Left
+ ///
+ FrcFlcRrRlFcLfeFrFl,
+
+ ///
+ /// [0] Empty [1] Front Center High [2] Rear Right [3] Rear Left [4] Front Center [5] Empty [6] Front Right [7] Front
+ /// Left
+ ///
+ FchRrRlFcFrFl,
+
+ ///
+ /// [0] Empty [1] Front Center High [2] Rear Right [3] Rear Left [4] Front Center [5] Low Frequency Effects [6] Front
+ /// Right [7] Front Left
+ ///
+ FchRrRlFcLfeFrFl,
+
+ ///
+ /// [0] TopCenter [1] Empty [2] Rear Right [3] Rear Left [4] Front Center [5] Empty [6] Front Right [7] Front Left
+ ///
+ TcRrRlFcFrFl,
+
+ ///
+ /// [0] TopCenter [1] Empty [2] Rear Right [3] Rear Left [4] Front Center [5] Low Frequency Effects [6] Front Right [7]
+ /// Front Left
+ ///
+ TcRrRlFcLfeFrFl,
+
+ ///
+ /// [0] Front Right High [1] Front Left High [2] Rear Right [3] Rear Left [4] Empty [5] Empty [6] Front Right [7] Front
+ /// Left
+ ///
+ FrhFlhRrRlFrFl,
+
+ ///
+ /// [0] Front Right High [1] Front Left High [2] Rear Right [3] Rear Left [4] Empty [5] Low Frequency Effects [6] Front
+ /// Right [7] Front Left
+ ///
+ FrhFlhRrRlLfeFrFl,
+
+ ///
+ /// [0] Front Right Wide [1] Front Left Wide [2] Rear Right [3] Rear Left [4] Empty [5] Empty [6] Front Right [7] Front
+ /// Left
+ ///
+ FrwFlwRrRlFrFl,
+
+ ///
+ /// [0] Front Right Wide [1] Front Left Wide [2] Rear Right [3] Rear Left [4] Empty [5] Low Frequency Effects [6] Front
+ /// Right [7] Front Left
+ ///
+ FrwFlwRrRlLfeFrFl,
+
+ ///
+ /// [0] TopCenter [1] Rear Center [2] Rear Right [3] Rear Left [4] Front Center [5] Empty [6] Front Right [7] Front
+ /// Left
+ ///
+ TcRcRrRlFcFrFl,
+
+ ///
+ /// [0] TopCenter [1] Rear Center [2] Rear Right [3] Rear Left [4] Front Center [5] Low Frequency Effects [6] Front
+ /// Right [7] Front Left
+ ///
+ TcRcRrRlFcLfeFrFl,
+
+ ///
+ /// [0] Front Center High [1] Rear Center [2] Rear Right [3] Rear Left [4] Front Center [5] Empty [6] Front Right [7]
+ /// Front Left
+ ///
+ FchRcRrRlFcFrFl,
+
+ ///
+ /// [0] Front Center High [1] Rear Center [2] Rear Right [3] Rear Left [4] Front Center [5] Low Frequency Effects [6]
+ /// Front Right [7] Front Left
+ ///
+ FchRcRrRlFcLfeFrFl,
+
+ ///
+ /// [0] TopCenter [1] Front Center High [2] Rear Right [3] Rear Left [4] Front Center [5] Empty [6] Front Right [7]
+ /// Front Left
+ ///
+ TcFcRrRlFcFrFl,
+
+ ///
+ /// [0] TopCenter [1] Front Center High [2] Rear Right [3] Rear Left [4] Front Center [5] Low Frequency Effects [6]
+ /// Front Right [7] Front Left
+ ///
+ TcFchRrRlFcLfeFrFl,
+
+ ///
+ /// [0] Front Right High [1] Front Left High [2] Rear Right [3] Rear Left [4] Front Center [5] Empty [6] Front Right
+ /// [7] Front Left
+ ///
+ FrhFlhRrRlFcFrFl,
+
+ ///
+ /// [0] Front Right High [1] Front Left High [2] Rear Right [3] Rear Left [4] Front Center [5] Low Frequency Effects
+ /// [6] Front Right [7] Front Left
+ ///
+ FrhFlhRrRlFcLfeFrFl,
+
+ ///
+ /// [0] Front Right Wide [1] Front Left Wide [2] Rear Right [3] Rear Left [4] Front Center [5] Empty [6] Front Right
+ /// [7] Front Left
+ ///
+ FrwFlwRrRlFcFeFl,
+
+ ///
+ /// [0] Front Right Wide [1] Front Left Wide [2] Rear Right [3] Rear Left [4] Front Center [5] Low Frequency Effects
+ /// [6] Front Right [7] Front Left
+ ///
+ FrwFlwRrRlFcLfeFrFl,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 511
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameAudioChannelCount.cs b/NvAPIWrapper/Native/Display/InfoFrameAudioChannelCount.cs
new file mode 100644
index 0000000..71e76c8
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameAudioChannelCount.cs
@@ -0,0 +1,53 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible audio channels
+ ///
+ public enum InfoFrameAudioChannelCount : uint
+ {
+ ///
+ /// Data is available in the header of source data
+ ///
+ InHeader = 0,
+
+ ///
+ /// Two channels
+ ///
+ Two,
+
+ ///
+ /// Three channels
+ ///
+ Three,
+
+ ///
+ /// Four channels
+ ///
+ Four,
+
+ ///
+ /// Five channels
+ ///
+ Five,
+
+ ///
+ /// Six channels
+ ///
+ Six,
+
+ ///
+ /// Seven channels
+ ///
+ Seven,
+
+ ///
+ /// Eight channels
+ ///
+ Eight,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 15
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameAudioCodec.cs b/NvAPIWrapper/Native/Display/InfoFrameAudioCodec.cs
new file mode 100644
index 0000000..0db6fcf
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameAudioCodec.cs
@@ -0,0 +1,93 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible audio codecs
+ ///
+ public enum InfoFrameAudioCodec : uint
+ {
+ ///
+ /// Data is available in the header of source data
+ ///
+ InHeader = 0,
+
+ ///
+ /// Pulse-code modulation
+ ///
+ PCM,
+
+ ///
+ /// Dolby AC-3
+ ///
+ AC3,
+
+ ///
+ /// MPEG1
+ ///
+ MPEG1,
+
+ ///
+ /// MP3 (MPEG-2 Audio Layer III)
+ ///
+ MP3,
+
+ ///
+ /// MPEG2
+ ///
+ MPEG2,
+
+ ///
+ /// Advanced Audio Coding
+ ///
+ AACLC,
+
+ ///
+ /// DTS
+ ///
+ DTS,
+
+ ///
+ /// Adaptive Transform Acoustic Coding
+ ///
+ ATRAC,
+
+ ///
+ /// Direct Stream Digital
+ ///
+ DSD,
+
+ ///
+ /// Dolby Digital Plus
+ ///
+ EAC3,
+
+ ///
+ /// DTS High Definition
+ ///
+ DTSHD,
+
+ ///
+ /// Meridian Lossless Packing
+ ///
+ MLP,
+
+ ///
+ /// DST
+ ///
+ DST,
+
+ ///
+ /// Windows Media Audio Pro
+ ///
+ WMAPRO,
+
+ ///
+ /// Extended audio codec value should be used to get information regarding audio codec
+ ///
+ UseExtendedCodecType,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 31
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameAudioExtendedCodec.cs b/NvAPIWrapper/Native/Display/InfoFrameAudioExtendedCodec.cs
new file mode 100644
index 0000000..82dfdde
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameAudioExtendedCodec.cs
@@ -0,0 +1,33 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible extended audio codecs
+ ///
+ public enum InfoFrameAudioExtendedCodec : uint
+ {
+ ///
+ /// Use the primary audio codec type, data not available
+ ///
+ UseCodecType = 0,
+
+ ///
+ /// High-Efficiency Advanced Audio Coding
+ ///
+ HEAAC,
+
+ ///
+ /// High-Efficiency Advanced Audio Coding 2
+ ///
+ HEAACVersion2,
+
+ ///
+ /// MPEG Surround
+ ///
+ MPEGSurround,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 63
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameAudioLFEPlaybackLevel.cs b/NvAPIWrapper/Native/Display/InfoFrameAudioLFEPlaybackLevel.cs
new file mode 100644
index 0000000..7988db3
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameAudioLFEPlaybackLevel.cs
@@ -0,0 +1,28 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible audio low frequency effects channel playback level
+ ///
+ public enum InfoFrameAudioLFEPlaybackLevel : uint
+ {
+ ///
+ /// Data not available
+ ///
+ NoData = 0,
+
+ ///
+ /// No change to the source audio
+ ///
+ Plus0Decibel,
+
+ ///
+ /// Adds 10 decibel
+ ///
+ Plus10Decibel,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameAudioLevelShift.cs b/NvAPIWrapper/Native/Display/InfoFrameAudioLevelShift.cs
new file mode 100644
index 0000000..64e3b21
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameAudioLevelShift.cs
@@ -0,0 +1,93 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible audio channel level shift values
+ ///
+ public enum InfoFrameAudioLevelShift : uint
+ {
+ ///
+ /// No change to the source audio
+ ///
+ Shift0Decibel = 0,
+
+ ///
+ /// Shifts 1 decibel
+ ///
+ Shift1Decibel,
+
+ ///
+ /// Shifts 2 decibel
+ ///
+ Shift2Decibel,
+
+ ///
+ /// Shifts 3 decibel
+ ///
+ Shift3Decibel,
+
+ ///
+ /// Shifts 4 decibel
+ ///
+ Shift4Decibel,
+
+ ///
+ /// Shifts 5 decibel
+ ///
+ Shift5Decibel,
+
+ ///
+ /// Shifts 6 decibel
+ ///
+ Shift6Decibel,
+
+ ///
+ /// Shifts 7 decibel
+ ///
+ Shift7Decibel,
+
+ ///
+ /// Shifts 8 decibel
+ ///
+ Shift8Decibel,
+
+ ///
+ /// Shifts 9 decibel
+ ///
+ Shift9Decibel,
+
+ ///
+ /// Shifts 10 decibel
+ ///
+ Shift10Decibel,
+
+ ///
+ /// Shifts 11 decibel
+ ///
+ Shift11Decibel,
+
+ ///
+ /// Shifts 12 decibel
+ ///
+ Shift12Decibel,
+
+ ///
+ /// Shifts 13 decibel
+ ///
+ Shift13Decibel,
+
+ ///
+ /// Shifts 14 decibel
+ ///
+ Shift14Decibel,
+
+ ///
+ /// Shifts 15 decibel
+ ///
+ Shift15Decibel,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 31
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameAudioSampleRate.cs b/NvAPIWrapper/Native/Display/InfoFrameAudioSampleRate.cs
new file mode 100644
index 0000000..f283e1c
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameAudioSampleRate.cs
@@ -0,0 +1,53 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible audio sample rates (sampling frequency)
+ ///
+ public enum InfoFrameAudioSampleRate : uint
+ {
+ ///
+ /// Data is available in the header of source data
+ ///
+ InHeader = 0,
+
+ ///
+ /// 31kHz sampling frequency
+ ///
+ F32000Hz,
+
+ ///
+ /// 44.1kHz sampling frequency
+ ///
+ F44100Hz,
+
+ ///
+ /// 48kHz sampling frequency
+ ///
+ F48000Hz,
+
+ ///
+ /// 88.2kHz sampling frequency
+ ///
+ F88200Hz,
+
+ ///
+ /// 96kHz sampling frequency
+ ///
+ F96000Hz,
+
+ ///
+ /// 176.4kHz sampling frequency
+ ///
+ F176400Hz,
+
+ ///
+ /// 192kHz sampling frequency
+ ///
+ F192000Hz,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 15
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameAudioSampleSize.cs b/NvAPIWrapper/Native/Display/InfoFrameAudioSampleSize.cs
new file mode 100644
index 0000000..361279c
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameAudioSampleSize.cs
@@ -0,0 +1,33 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible audio sample size (bit depth)
+ ///
+ public enum InfoFrameAudioSampleSize : uint
+ {
+ ///
+ /// Data is available in the header of source data
+ ///
+ InHeader = 0,
+
+ ///
+ /// 16bit audio sample size
+ ///
+ B16,
+
+ ///
+ /// 20bit audio sample size
+ ///
+ B20,
+
+ ///
+ /// 24bit audio sample size
+ ///
+ B24,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameBoolean.cs b/NvAPIWrapper/Native/Display/InfoFrameBoolean.cs
new file mode 100644
index 0000000..0aa0e45
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameBoolean.cs
@@ -0,0 +1,23 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for info-frame properties that accept or return a boolean value
+ ///
+ public enum InfoFrameBoolean : uint
+ {
+ ///
+ /// False
+ ///
+ False = 0,
+
+ ///
+ /// True
+ ///
+ True,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 3
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameCommand.cs b/NvAPIWrapper/Native/Display/InfoFrameCommand.cs
new file mode 100644
index 0000000..578bb59
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameCommand.cs
@@ -0,0 +1,50 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Possible commands for info-frame operations
+ ///
+ public enum InfoFrameCommand : uint
+ {
+ ///
+ /// Returns the fields in the info-frame with values set by the manufacturer (NVIDIA or OEM)
+ ///
+ GetDefault = 0,
+
+ ///
+ /// Sets the fields in the info-frame to auto, and info-frame to the default info-frame for use in a set.
+ ///
+ Reset,
+
+ ///
+ /// Get the current info-frame state.
+ ///
+ Get,
+
+ ///
+ /// Set the current info-frame state (flushed to the monitor), the values are one time and do not persist.
+ ///
+ Set,
+
+ ///
+ /// Get the override info-frame state, non-override fields will be set to value = AUTO, overridden fields will have the
+ /// current override values.
+ ///
+ GetOverride,
+
+ ///
+ /// Set the override info-frame state, non-override fields will be set to value = AUTO, other values indicate override;
+ /// persist across mode-set and reboot.
+ ///
+ SetOverride,
+
+ ///
+ /// Get properties associated with info-frame (each of the info-frame type will have properties).
+ ///
+ GetProperty,
+
+ ///
+ /// Set properties associated with info-frame.
+ ///
+ SetProperty
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameDataType.cs b/NvAPIWrapper/Native/Display/InfoFrameDataType.cs
new file mode 100644
index 0000000..50db98f
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameDataType.cs
@@ -0,0 +1,18 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible info-frame data type
+ ///
+ public enum InfoFrameDataType : uint
+ {
+ ///
+ /// Auxiliary Video data
+ ///
+ AuxiliaryVideoInformation = 2,
+
+ ///
+ /// Audio data
+ ///
+ AudioInformation = 4,
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFramePropertyMode.cs b/NvAPIWrapper/Native/Display/InfoFramePropertyMode.cs
new file mode 100644
index 0000000..93ac83b
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFramePropertyMode.cs
@@ -0,0 +1,28 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible info-frame property modes
+ ///
+ public enum InfoFramePropertyMode : uint
+ {
+ ///
+ /// Driver determines whether to send info-frames.
+ ///
+ Auto = 0,
+
+ ///
+ /// Driver always sends info-frame.
+ ///
+ Enable,
+
+ ///
+ /// Driver never sends info-frame.
+ ///
+ Disable,
+
+ ///
+ /// Driver only sends info-frame when client requests it via info-frame escape call.
+ ///
+ AllowOverride
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoAspectRatioActivePortion.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoAspectRatioActivePortion.cs
new file mode 100644
index 0000000..5c0ffe7
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoAspectRatioActivePortion.cs
@@ -0,0 +1,58 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for AVI aspect ratio portions
+ ///
+ public enum InfoFrameVideoAspectRatioActivePortion : uint
+ {
+ ///
+ /// Disabled or not available
+ ///
+ Disabled = 0,
+
+ ///
+ /// Letter box 16x9
+ ///
+ LetterboxGreaterThan16X9 = 4,
+
+ ///
+ /// Equal to the source frame size
+ ///
+ EqualCodedFrame = 8,
+
+ ///
+ /// Centered 4x3 ratio
+ ///
+ Center4X3 = 9,
+
+ ///
+ /// Centered 16x9 ratio
+ ///
+ Center16X9 = 10,
+
+ ///
+ /// Centered 14x9 ratio
+ ///
+ Center14X9 = 11,
+
+ ///
+ /// Bordered 4x3 on 14x9
+ ///
+ Bordered4X3On14X9 = 13,
+
+ ///
+ /// Bordered 16x9 on 14x9
+ ///
+ Bordered16X9On14X9 = 14,
+
+ ///
+ /// Bordered 16x9 on 4x3
+ ///
+ Bordered16X9On4X3 = 15,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 31
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoAspectRatioCodedFrame.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoAspectRatioCodedFrame.cs
new file mode 100644
index 0000000..246853d
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoAspectRatioCodedFrame.cs
@@ -0,0 +1,28 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Gets the possible values for AVI source aspect ratio
+ ///
+ public enum InfoFrameVideoAspectRatioCodedFrame : uint
+ {
+ ///
+ /// No data available
+ ///
+ NoData = 0,
+
+ ///
+ /// The 4x3 aspect ratio
+ ///
+ Aspect4X3,
+
+ ///
+ /// The 16x9 aspect ratio
+ ///
+ Aspect16X9,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoBarData.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoBarData.cs
new file mode 100644
index 0000000..16f3e09
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoBarData.cs
@@ -0,0 +1,33 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible AVI bar data that are available and should be used
+ ///
+ public enum InfoFrameVideoBarData : uint
+ {
+ ///
+ /// No bar data present
+ ///
+ NotPresent = 0,
+
+ ///
+ /// Vertical bar
+ ///
+ Vertical,
+
+ ///
+ /// Horizontal bar
+ ///
+ Horizontal,
+
+ ///
+ /// Both sides have bars
+ ///
+ Both,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoColorFormat.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoColorFormat.cs
new file mode 100644
index 0000000..b3c2fae
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoColorFormat.cs
@@ -0,0 +1,28 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible AVI color formats
+ ///
+ public enum InfoFrameVideoColorFormat : uint
+ {
+ ///
+ /// The RGB color format
+ ///
+ RGB = 0,
+
+ ///
+ /// The YCbCr422 color format
+ ///
+ YCbCr422,
+
+ ///
+ /// The YCbCr444 color format
+ ///
+ YCbCr444,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoColorimetry.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoColorimetry.cs
new file mode 100644
index 0000000..9beccb9
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoColorimetry.cs
@@ -0,0 +1,33 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for the AVI color space
+ ///
+ public enum InfoFrameVideoColorimetry : uint
+ {
+ ///
+ /// No data available
+ ///
+ NoData = 0,
+
+ ///
+ /// The SMPTE170M color space
+ ///
+ SMPTE170M,
+
+ ///
+ /// The ITURBT709 color space
+ ///
+ ITURBT709,
+
+ ///
+ /// Extended colorimetry value should be used to get information regarding AVI color space
+ ///
+ UseExtendedColorimetry,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoContentType.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoContentType.cs
new file mode 100644
index 0000000..2d51155
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoContentType.cs
@@ -0,0 +1,33 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible AVI content type
+ ///
+ public enum InfoFrameVideoContentType : uint
+ {
+ ///
+ /// Graphics content
+ ///
+ Graphics = 0,
+
+ ///
+ /// Photo content
+ ///
+ Photo,
+
+ ///
+ /// Cinematic content
+ ///
+ Cinema,
+
+ ///
+ /// Gaming content
+ ///
+ Game,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoExtendedColorimetry.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoExtendedColorimetry.cs
new file mode 100644
index 0000000..dbb374a
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoExtendedColorimetry.cs
@@ -0,0 +1,41 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for the AVI extended color space
+ ///
+ public enum InfoFrameVideoExtendedColorimetry : uint
+ {
+ ///
+ /// The xvYCC601 color space
+ ///
+ // ReSharper disable once InconsistentNaming
+ xvYCC601 = 0,
+
+ ///
+ /// The xvYCC709 color space
+ ///
+ // ReSharper disable once InconsistentNaming
+ xvYCC709,
+
+ ///
+ /// The sYCC601 color space
+ ///
+ // ReSharper disable once InconsistentNaming
+ sYCC601,
+
+ ///
+ /// The AdobeYCC601 color space
+ ///
+ AdobeYCC601,
+
+ ///
+ /// The AdobeRGB color space
+ ///
+ AdobeRGB,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 15
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoITC.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoITC.cs
new file mode 100644
index 0000000..ca2cba4
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoITC.cs
@@ -0,0 +1,23 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible AVI video content modes
+ ///
+ public enum InfoFrameVideoITC : uint
+ {
+ ///
+ /// Normal video content (Consumer Electronics)
+ ///
+ VideoContent = 0,
+
+ ///
+ /// Information Technology content
+ ///
+ ITContent,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 3
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoNonUniformPictureScaling.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoNonUniformPictureScaling.cs
new file mode 100644
index 0000000..63a95c8
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoNonUniformPictureScaling.cs
@@ -0,0 +1,33 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for the AVI non uniform picture scaling
+ ///
+ public enum InfoFrameVideoNonUniformPictureScaling : uint
+ {
+ ///
+ /// No data available
+ ///
+ NoData = 0,
+
+ ///
+ /// Horizontal scaling
+ ///
+ Horizontal,
+
+ ///
+ /// Vertical scaling
+ ///
+ Vertical,
+
+ ///
+ /// Scaling in both directions
+ ///
+ Both,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoPixelRepetition.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoPixelRepetition.cs
new file mode 100644
index 0000000..bb725d6
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoPixelRepetition.cs
@@ -0,0 +1,63 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible AVI pixel repetition values
+ ///
+ public enum InfoFrameVideoPixelRepetition : uint
+ {
+ ///
+ /// No pixel repetition
+ ///
+ None = 0,
+
+ ///
+ /// Two pixel repetition
+ ///
+ X2,
+
+ ///
+ /// Three pixel repetition
+ ///
+ X3,
+
+ ///
+ /// Four pixel repetition
+ ///
+ X4,
+
+ ///
+ /// Five pixel repetition
+ ///
+ X5,
+
+ ///
+ /// Six pixel repetition
+ ///
+ X6,
+
+ ///
+ /// Seven pixel repetition
+ ///
+ X7,
+
+ ///
+ /// Eight pixel repetition
+ ///
+ X8,
+
+ ///
+ /// Nine pixel repetition
+ ///
+ X9,
+
+ ///
+ /// Ten pixel repetition
+ ///
+ X10,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 31
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoRGBQuantization.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoRGBQuantization.cs
new file mode 100644
index 0000000..64b613f
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoRGBQuantization.cs
@@ -0,0 +1,28 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for the AVI RGB quantization
+ ///
+ public enum InfoFrameVideoRGBQuantization : uint
+ {
+ ///
+ /// Default setting
+ ///
+ Default = 0,
+
+ ///
+ /// Limited RGB range [16-235] (86%)
+ ///
+ LimitedRange,
+
+ ///
+ /// Full RGB range [0-255] (100%)
+ ///
+ FullRange,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoScanInfo.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoScanInfo.cs
new file mode 100644
index 0000000..fbed2f3
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoScanInfo.cs
@@ -0,0 +1,28 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for AVI scan information
+ ///
+ public enum InfoFrameVideoScanInfo : uint
+ {
+ ///
+ /// No data available
+ ///
+ NoData = 0,
+
+ ///
+ /// Overscan
+ ///
+ OverScan,
+
+ ///
+ /// Underscan
+ ///
+ UnderScan,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoYCCQuantization.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoYCCQuantization.cs
new file mode 100644
index 0000000..5b8238b
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoYCCQuantization.cs
@@ -0,0 +1,23 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible AVI YCC quantization
+ ///
+ public enum InfoFrameVideoYCCQuantization : uint
+ {
+ ///
+ /// Limited YCC range
+ ///
+ LimitedRange = 0,
+
+ ///
+ /// Full YCC range
+ ///
+ FullRange,
+
+ ///
+ /// Auto (Unspecified)
+ ///
+ Auto = 7
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/MonitorCapabilitiesConnectorType.cs b/NvAPIWrapper/Native/Display/MonitorCapabilitiesConnectorType.cs
new file mode 100644
index 0000000..15c45d7
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/MonitorCapabilitiesConnectorType.cs
@@ -0,0 +1,38 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Possible values for the monitor capabilities connector type
+ ///
+ public enum MonitorCapabilitiesConnectorType : uint
+ {
+ ///
+ /// Unknown or invalid connector
+ ///
+ Unknown = 0,
+
+ ///
+ /// VGA connector
+ ///
+ VGA,
+
+ ///
+ /// Composite connector (TV)
+ ///
+ TV,
+
+ ///
+ /// DVI connector
+ ///
+ DVI,
+
+ ///
+ /// HDMI connector
+ ///
+ HDMI,
+
+ ///
+ /// Display Port connector
+ ///
+ DisplayPort
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/MonitorCapabilitiesType.cs b/NvAPIWrapper/Native/Display/MonitorCapabilitiesType.cs
new file mode 100644
index 0000000..0b6958d
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/MonitorCapabilitiesType.cs
@@ -0,0 +1,18 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for the monitor capabilities type
+ ///
+ public enum MonitorCapabilitiesType : uint
+ {
+ ///
+ /// The Vendor Specific Data Block
+ ///
+ VSDB = 0x1000,
+
+ ///
+ /// The Video Capability Data Block
+ ///
+ VCDB = 0x1001
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Rotate.cs b/NvAPIWrapper/Native/Display/Rotate.cs
new file mode 100644
index 0000000..171d4d3
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Rotate.cs
@@ -0,0 +1,33 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Possible rotate modes
+ ///
+ public enum Rotate : uint
+ {
+ ///
+ /// No rotation
+ ///
+ Degree0 = 0,
+
+ ///
+ /// 90 degree rotation
+ ///
+ Degree90 = 1,
+
+ ///
+ /// 180 degree rotation
+ ///
+ Degree180 = 2,
+
+ ///
+ /// 270 degree rotation
+ ///
+ Degree270 = 3,
+
+ ///
+ /// This value is ignored
+ ///
+ Ignored = 4
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Scaling.cs b/NvAPIWrapper/Native/Display/Scaling.cs
new file mode 100644
index 0000000..7c4e15d
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Scaling.cs
@@ -0,0 +1,48 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Possible scaling modes
+ ///
+ public enum Scaling
+ {
+ ///
+ /// No change
+ ///
+ Default = 0,
+
+ ///
+ /// Balanced - Full Screen
+ ///
+ ToClosest = 1,
+
+ ///
+ /// Force GPU - Full Screen
+ ///
+ ToNative = 2,
+
+ ///
+ /// Force GPU - Centered\No Scaling
+ ///
+ GPUScanOutToNative = 3,
+
+ ///
+ /// Force GPU - Aspect Ratio
+ ///
+ ToAspectScanOutToNative = 5,
+
+ ///
+ /// Balanced - Aspect Ratio
+ ///
+ ToAspectScanOutToClosest = 6,
+
+ ///
+ /// Balanced - Centered\No Scaling
+ ///
+ GPUScanOutToClosest = 7,
+
+ ///
+ /// Customized scaling - For future use
+ ///
+ Customized = 255
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/ScanOutCompositionParameter.cs b/NvAPIWrapper/Native/Display/ScanOutCompositionParameter.cs
new file mode 100644
index 0000000..4d76256
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ScanOutCompositionParameter.cs
@@ -0,0 +1,13 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Holds a list of possible scan out composition configurable parameters
+ ///
+ public enum ScanOutCompositionParameter : uint
+ {
+ ///
+ /// Warping re-sampling method parameter
+ ///
+ WarpingReSamplingMethod = 0
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/ScanOutCompositionParameterValue.cs b/NvAPIWrapper/Native/Display/ScanOutCompositionParameterValue.cs
new file mode 100644
index 0000000..e1ae328
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/ScanOutCompositionParameterValue.cs
@@ -0,0 +1,48 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Holds a list of possible scan out composition parameter values
+ ///
+ public enum ScanOutCompositionParameterValue : uint
+ {
+ ///
+ /// Default parameter value
+ ///
+ Default = 0,
+
+ ///
+ /// BiLinear value for the warping re-sampling method parameter
+ ///
+ WarpingReSamplingMethodBiLinear = 0x100,
+
+ ///
+ /// Bicubic Triangular value for the warping re-sampling method parameter
+ ///
+ WarpingReSamplingMethodBicubicTriangular = 0x101,
+
+ ///
+ /// Bicubic Bell Shaped value for the warping re-sampling method parameter
+ ///
+ WarpingReSamplingMethodBicubicBellShaped = 0x102,
+
+ ///
+ /// Bicubic B-Spline value for the warping re-sampling method parameter
+ ///
+ WarpingReSamplingMethodBicubicBSpline = 0x103,
+
+ ///
+ /// Bicubic Adaptive Triangular value for the warping re-sampling method parameter
+ ///
+ WarpingReSamplingMethodBicubicAdaptiveTriangular = 0x104,
+
+ ///
+ /// Bicubic Adaptive Bell Shaped value for the warping re-sampling method parameter
+ ///
+ WarpingReSamplingMethodBicubicAdaptiveBellShaped = 0x105,
+
+ ///
+ /// Bicubic Adaptive B-Spline value for the warping re-sampling method parameter
+ ///
+ WarpingReSamplingMethodBicubicAdaptiveBSpline = 0x106
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/SpanningOrientation.cs b/NvAPIWrapper/Native/Display/SpanningOrientation.cs
new file mode 100644
index 0000000..ee4b265
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/SpanningOrientation.cs
@@ -0,0 +1,23 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Display spanning for Windows XP
+ ///
+ public enum SpanningOrientation
+ {
+ ///
+ /// No spanning
+ ///
+ None = 0,
+
+ ///
+ /// Horizontal spanning
+ ///
+ Horizontal = 1,
+
+ ///
+ /// Vertical spanning
+ ///
+ Vertical = 2
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/StaticMetadataDescriptorId.cs b/NvAPIWrapper/Native/Display/StaticMetadataDescriptorId.cs
new file mode 100644
index 0000000..4a02f72
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/StaticMetadataDescriptorId.cs
@@ -0,0 +1,13 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Contains possible values for the type of the Static Metadata Descriptor block structure
+ ///
+ public enum StaticMetadataDescriptorId : uint
+ {
+ ///
+ /// Type 1 Static Metadata Descriptor block structure
+ ///
+ StaticMetadataType1 = 0
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ColorDataColorCoordinate.cs b/NvAPIWrapper/Native/Display/Structures/ColorDataColorCoordinate.cs
new file mode 100644
index 0000000..40cef00
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ColorDataColorCoordinate.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds coordinates of a color in the color space
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct ColorDataColorCoordinate : IEquatable
+ {
+ private readonly ushort _X;
+ private readonly ushort _Y;
+
+ ///
+ /// Gets the color space's X coordinate
+ ///
+ public float X
+ {
+ get => (float) _X / 0xC350;
+ }
+
+ ///
+ /// Gets the color space's Y coordinate
+ ///
+ public float Y
+ {
+ get => (float) _Y / 0xC350;
+ }
+
+ ///
+ /// Creates an instance of .
+ ///
+ /// The color space's X coordinate.
+ /// The color space's Y coordinate.
+ public ColorDataColorCoordinate(float x, float y)
+ {
+ _X = (ushort) (Math.Min(Math.Max(x, 0), 1) * 0xC350);
+ _Y = (ushort) (Math.Min(Math.Max(y, 0), 1) * 0xC350);
+ }
+
+ ///
+ /// Creates an instance of .
+ ///
+ /// The color space's coordinates.
+ public ColorDataColorCoordinate(PointF coordinate) : this(coordinate.X, coordinate.Y)
+ {
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"({X:F3}, {Y:F3})";
+ }
+
+ ///
+ public bool Equals(ColorDataColorCoordinate other)
+ {
+ return _X == other._X && _Y == other._Y;
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ return obj is ColorDataColorCoordinate other && Equals(other);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (_X.GetHashCode() * 397) ^ _Y.GetHashCode();
+ }
+ }
+
+ ///
+ /// Checks two instance of for equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// true if both instances are equal, otherwise false.
+ public static bool operator ==(ColorDataColorCoordinate left, ColorDataColorCoordinate right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Checks two instance of for inequality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// true if both instances are not equal, otherwise false.
+ public static bool operator !=(ColorDataColorCoordinate left, ColorDataColorCoordinate right)
+ {
+ return !left.Equals(right);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ColorDataV1.cs b/NvAPIWrapper/Native/Display/Structures/ColorDataV1.cs
new file mode 100644
index 0000000..f2c6eef
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ColorDataV1.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct ColorDataV1 : IInitializable, IColorData
+ {
+ internal StructureVersion _Version;
+ internal ushort _Size;
+
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ private readonly byte _Command;
+ private readonly ColorDataBag _Data;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ private struct ColorDataBag
+ {
+ public readonly byte ColorFormat;
+ public readonly byte Colorimetry;
+
+ public ColorDataBag(ColorDataFormat colorFormat, ColorDataColorimetry colorimetry)
+ {
+ ColorFormat = (byte)colorFormat;
+ Colorimetry = (byte)colorimetry;
+ }
+ }
+
+ ///
+ /// Creates an instance of to retrieve color data information
+ ///
+ /// The command to be executed.
+ public ColorDataV1(ColorDataCommand command)
+ {
+ this = typeof(ColorDataV1).Instantiate();
+ _Size = (ushort)_Version.StructureSize;
+
+ if (command != ColorDataCommand.Get && command != ColorDataCommand.GetDefault)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte)command;
+ }
+
+ ///
+ /// Creates an instance of to modify the color data
+ ///
+ /// The command to be executed.
+ /// The color data color format.
+ /// The color data color space.
+ public ColorDataV1(
+ ColorDataCommand command,
+ ColorDataFormat colorFormat,
+ ColorDataColorimetry colorimetry
+ )
+ {
+ this = typeof(ColorDataV1).Instantiate();
+ _Size = (ushort)_Version.StructureSize;
+
+ if (command != ColorDataCommand.Set && command != ColorDataCommand.IsSupportedColor)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte)command;
+ _Data = new ColorDataBag(colorFormat, colorimetry);
+ }
+
+ ///
+ public ColorDataFormat ColorFormat
+ {
+ get => (ColorDataFormat)_Data.ColorFormat;
+ }
+
+ ///
+ public ColorDataColorimetry Colorimetry
+ {
+ get => (ColorDataColorimetry)_Data.Colorimetry;
+ }
+
+ ///
+ public ColorDataDynamicRange? DynamicRange
+ {
+ get => null;
+ }
+
+ ///
+ public ColorDataDepth? ColorDepth
+ {
+ get => null;
+ }
+
+ ///
+ public ColorDataSelectionPolicy? SelectionPolicy
+ {
+ get => null;
+ }
+
+ ///
+ public ColorDataDesktopDepth? DesktopColorDepth
+ {
+ get => null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ColorDataV2.cs b/NvAPIWrapper/Native/Display/Structures/ColorDataV2.cs
new file mode 100644
index 0000000..4a8c7cb
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ColorDataV2.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(2)]
+ public struct ColorDataV2 : IInitializable, IColorData
+ {
+ internal StructureVersion _Version;
+ internal ushort _Size;
+
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ private readonly byte _Command;
+ private readonly ColorDataBag _Data;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ private struct ColorDataBag
+ {
+ public readonly byte ColorFormat;
+ public readonly byte Colorimetry;
+ public readonly byte ColorDynamicRange;
+
+ public ColorDataBag(
+ ColorDataFormat colorFormat,
+ ColorDataColorimetry colorimetry,
+ ColorDataDynamicRange colorDynamicRange
+ )
+ {
+ ColorFormat = (byte) colorFormat;
+ Colorimetry = (byte) colorimetry;
+ ColorDynamicRange = (byte) colorDynamicRange;
+ }
+ }
+
+ ///
+ /// Creates an instance of to retrieve color data information
+ ///
+ /// The command to be executed.
+ public ColorDataV2(ColorDataCommand command)
+ {
+ this = typeof(ColorDataV2).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != ColorDataCommand.Get && command != ColorDataCommand.GetDefault)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ }
+
+ ///
+ /// Creates an instance of to modify the color data
+ ///
+ /// The command to be executed.
+ /// The color data color format.
+ /// The color data color space.
+ /// The color data dynamic range.
+ public ColorDataV2(
+ ColorDataCommand command,
+ ColorDataFormat colorFormat,
+ ColorDataColorimetry colorimetry,
+ ColorDataDynamicRange colorDynamicRange
+ )
+ {
+ this = typeof(ColorDataV2).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != ColorDataCommand.Set && command != ColorDataCommand.IsSupportedColor)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ _Data = new ColorDataBag(colorFormat, colorimetry, colorDynamicRange);
+ }
+
+ ///
+ public ColorDataFormat ColorFormat
+ {
+ get => (ColorDataFormat) _Data.ColorFormat;
+ }
+
+ ///
+ public ColorDataColorimetry Colorimetry
+ {
+ get => (ColorDataColorimetry) _Data.Colorimetry;
+ }
+
+ ///
+ public ColorDataDynamicRange? DynamicRange
+ {
+ get => (ColorDataDynamicRange) _Data.ColorDynamicRange;
+ }
+
+ ///
+ public ColorDataDepth? ColorDepth
+ {
+ get => null;
+ }
+
+ ///
+ public ColorDataSelectionPolicy? SelectionPolicy
+ {
+ get => null;
+ }
+
+ ///
+ public ColorDataDesktopDepth? DesktopColorDepth
+ {
+ get => null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ColorDataV3.cs b/NvAPIWrapper/Native/Display/Structures/ColorDataV3.cs
new file mode 100644
index 0000000..9757c07
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ColorDataV3.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(3)]
+ public struct ColorDataV3 : IInitializable, IColorData
+ {
+ internal StructureVersion _Version;
+ internal ushort _Size;
+
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ private readonly byte _Command;
+ private readonly ColorDataBag _Data;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ private struct ColorDataBag
+ {
+ public readonly byte ColorFormat;
+ public readonly byte Colorimetry;
+ public readonly byte ColorDynamicRange;
+ public readonly ColorDataDepth ColorDepth;
+
+ public ColorDataBag(
+ ColorDataFormat colorFormat,
+ ColorDataColorimetry colorimetry,
+ ColorDataDynamicRange colorDynamicRange,
+ ColorDataDepth colorDepth
+ )
+ {
+ ColorFormat = (byte) colorFormat;
+ Colorimetry = (byte) colorimetry;
+ ColorDynamicRange = (byte) colorDynamicRange;
+ ColorDepth = colorDepth;
+ }
+ }
+
+ ///
+ /// Creates an instance of to retrieve color data information
+ ///
+ /// The command to be executed.
+ public ColorDataV3(ColorDataCommand command)
+ {
+ this = typeof(ColorDataV3).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != ColorDataCommand.Get && command != ColorDataCommand.GetDefault)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ }
+
+ ///
+ /// Creates an instance of to modify the color data
+ ///
+ /// The command to be executed.
+ /// The color data color format.
+ /// The color data color space.
+ /// The color data dynamic range.
+ /// The color data color depth.
+ public ColorDataV3(
+ ColorDataCommand command,
+ ColorDataFormat colorFormat,
+ ColorDataColorimetry colorimetry,
+ ColorDataDynamicRange colorDynamicRange,
+ ColorDataDepth colorDepth
+ )
+ {
+ this = typeof(ColorDataV3).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != ColorDataCommand.Set && command != ColorDataCommand.IsSupportedColor)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ _Data = new ColorDataBag(colorFormat, colorimetry, colorDynamicRange, colorDepth);
+ }
+
+ ///
+ public ColorDataFormat ColorFormat
+ {
+ get => (ColorDataFormat) _Data.ColorFormat;
+ }
+
+ ///
+ public ColorDataColorimetry Colorimetry
+ {
+ get => (ColorDataColorimetry) _Data.Colorimetry;
+ }
+
+ ///
+ public ColorDataDynamicRange? DynamicRange
+ {
+ get => (ColorDataDynamicRange) _Data.ColorDynamicRange;
+ }
+
+ ///
+ public ColorDataDepth? ColorDepth
+ {
+ get
+ {
+ switch ((int) _Data.ColorDepth)
+ {
+ case 6:
+ return ColorDataDepth.BPC6;
+ case 8:
+ return ColorDataDepth.BPC8;
+ case 10:
+ return ColorDataDepth.BPC10;
+ case 12:
+ return ColorDataDepth.BPC12;
+ case 16:
+ return ColorDataDepth.BPC16;
+ default:
+ return _Data.ColorDepth;
+ }
+ }
+ }
+
+ ///
+ public ColorDataSelectionPolicy? SelectionPolicy
+ {
+ get => null;
+ }
+
+ ///
+ public ColorDataDesktopDepth? DesktopColorDepth
+ {
+ get => null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ColorDataV4.cs b/NvAPIWrapper/Native/Display/Structures/ColorDataV4.cs
new file mode 100644
index 0000000..c7a8a0e
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ColorDataV4.cs
@@ -0,0 +1,148 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(4)]
+ public struct ColorDataV4 : IInitializable, IColorData
+ {
+ internal StructureVersion _Version;
+ internal ushort _Size;
+
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ private readonly byte _Command;
+ private readonly ColorDataBag _Data;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ private struct ColorDataBag
+ {
+ public readonly byte ColorFormat;
+ public readonly byte Colorimetry;
+ public readonly byte ColorDynamicRange;
+ public readonly ColorDataDepth ColorDepth;
+ public readonly ColorDataSelectionPolicy ColorSelectionPolicy;
+
+ public ColorDataBag(
+ ColorDataFormat colorFormat,
+ ColorDataColorimetry colorimetry,
+ ColorDataDynamicRange colorDynamicRange,
+ ColorDataDepth colorDepth,
+ ColorDataSelectionPolicy colorSelectionPolicy
+ )
+ {
+ ColorFormat = (byte) colorFormat;
+ Colorimetry = (byte) colorimetry;
+ ColorDynamicRange = (byte) colorDynamicRange;
+ ColorDepth = colorDepth;
+ ColorSelectionPolicy = colorSelectionPolicy;
+ }
+ }
+
+ ///
+ /// Creates an instance of to retrieve color data information
+ ///
+ /// The command to be executed.
+ public ColorDataV4(ColorDataCommand command)
+ {
+ this = typeof(ColorDataV4).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != ColorDataCommand.Get && command != ColorDataCommand.GetDefault)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ }
+
+ ///
+ /// Creates an instance of to modify the color data
+ ///
+ /// The command to be executed.
+ /// The color data color format.
+ /// The color data color space.
+ /// The color data dynamic range.
+ /// The color data color depth.
+ /// The color data selection policy.
+ public ColorDataV4(
+ ColorDataCommand command,
+ ColorDataFormat colorFormat,
+ ColorDataColorimetry colorimetry,
+ ColorDataDynamicRange colorDynamicRange,
+ ColorDataDepth colorDepth,
+ ColorDataSelectionPolicy colorSelectionPolicy
+ )
+ {
+ this = typeof(ColorDataV4).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != ColorDataCommand.Set && command != ColorDataCommand.IsSupportedColor)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ _Data = new ColorDataBag(colorFormat, colorimetry, colorDynamicRange, colorDepth, colorSelectionPolicy);
+ }
+
+ ///
+ public ColorDataFormat ColorFormat
+ {
+ get => (ColorDataFormat) _Data.ColorFormat;
+ }
+
+ ///
+ public ColorDataColorimetry Colorimetry
+ {
+ get => (ColorDataColorimetry) _Data.Colorimetry;
+ }
+
+ ///
+ public ColorDataDynamicRange? DynamicRange
+ {
+ get => (ColorDataDynamicRange) _Data.ColorDynamicRange;
+ }
+
+ ///
+ public ColorDataDepth? ColorDepth
+ {
+ get
+ {
+ switch ((int) _Data.ColorDepth)
+ {
+ case 6:
+ return ColorDataDepth.BPC6;
+ case 8:
+ return ColorDataDepth.BPC8;
+ case 10:
+ return ColorDataDepth.BPC10;
+ case 12:
+ return ColorDataDepth.BPC12;
+ case 16:
+ return ColorDataDepth.BPC16;
+ default:
+ return _Data.ColorDepth;
+ }
+ }
+ }
+
+ ///
+ public ColorDataSelectionPolicy? SelectionPolicy
+ {
+ get => _Data.ColorSelectionPolicy;
+ }
+
+ ///
+ public ColorDataDesktopDepth? DesktopColorDepth
+ {
+ get => null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ColorDataV5.cs b/NvAPIWrapper/Native/Display/Structures/ColorDataV5.cs
new file mode 100644
index 0000000..919a44e
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ColorDataV5.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(5)]
+ public struct ColorDataV5 : IInitializable, IColorData
+ {
+ internal StructureVersion _Version;
+ internal ushort _Size;
+
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ private readonly byte _Command;
+ private readonly ColorDataBag _Data;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ private struct ColorDataBag
+ {
+ public readonly byte ColorFormat;
+ public readonly byte Colorimetry;
+ public readonly byte ColorDynamicRange;
+ public readonly ColorDataDepth ColorDepth;
+ public readonly ColorDataSelectionPolicy ColorSelectionPolicy;
+ public readonly ColorDataDesktopDepth DesktopColorDepth;
+
+ public ColorDataBag(
+ ColorDataFormat colorFormat,
+ ColorDataColorimetry colorimetry,
+ ColorDataDynamicRange colorDynamicRange,
+ ColorDataDepth colorDepth,
+ ColorDataSelectionPolicy colorSelectionPolicy,
+ ColorDataDesktopDepth desktopColorDepth
+ )
+ {
+ ColorFormat = (byte) colorFormat;
+ Colorimetry = (byte) colorimetry;
+ ColorDynamicRange = (byte) colorDynamicRange;
+ ColorDepth = colorDepth;
+ ColorSelectionPolicy = colorSelectionPolicy;
+ DesktopColorDepth = desktopColorDepth;
+ }
+ }
+
+ ///
+ /// Creates an instance of to retrieve color data information
+ ///
+ /// The command to be executed.
+ public ColorDataV5(ColorDataCommand command)
+ {
+ this = typeof(ColorDataV5).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != ColorDataCommand.Get && command != ColorDataCommand.GetDefault)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ }
+
+ ///
+ /// Creates an instance of to modify the color data
+ ///
+ /// The command to be executed.
+ /// The color data color format.
+ /// The color data color space.
+ /// The color data dynamic range.
+ /// The color data color depth.
+ /// The color data selection policy.
+ /// The color data desktop color depth.
+ public ColorDataV5(
+ ColorDataCommand command,
+ ColorDataFormat colorFormat,
+ ColorDataColorimetry colorimetry,
+ ColorDataDynamicRange dynamicRange,
+ ColorDataDepth colorDepth,
+ ColorDataSelectionPolicy colorSelectionPolicy,
+ ColorDataDesktopDepth desktopColorDepth
+ )
+ {
+ this = typeof(ColorDataV5).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != ColorDataCommand.Set && command != ColorDataCommand.IsSupportedColor)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ _Data = new ColorDataBag(
+ colorFormat,
+ colorimetry,
+ dynamicRange,
+ colorDepth,
+ colorSelectionPolicy,
+ desktopColorDepth
+ );
+ }
+
+ ///
+ public ColorDataFormat ColorFormat
+ {
+ get => (ColorDataFormat) _Data.ColorFormat;
+ }
+
+ ///
+ public ColorDataColorimetry Colorimetry
+ {
+ get => (ColorDataColorimetry) _Data.Colorimetry;
+ }
+
+ ///
+ public ColorDataDynamicRange? DynamicRange
+ {
+ get => (ColorDataDynamicRange) _Data.ColorDynamicRange;
+ }
+
+ ///
+ public ColorDataDepth? ColorDepth
+ {
+ get
+ {
+ switch ((int) _Data.ColorDepth)
+ {
+ case 6:
+ return ColorDataDepth.BPC6;
+ case 8:
+ return ColorDataDepth.BPC8;
+ case 10:
+ return ColorDataDepth.BPC10;
+ case 12:
+ return ColorDataDepth.BPC12;
+ case 16:
+ return ColorDataDepth.BPC16;
+ default:
+ return _Data.ColorDepth;
+ }
+ }
+ }
+
+ ///
+ public ColorDataSelectionPolicy? SelectionPolicy
+ {
+ get => _Data.ColorSelectionPolicy;
+ }
+
+ ///
+ public ColorDataDesktopDepth? DesktopColorDepth
+ {
+ get => _Data.DesktopColorDepth;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/CustomDisplay.cs b/NvAPIWrapper/Native/Display/Structures/CustomDisplay.cs
new file mode 100644
index 0000000..a668934
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/CustomDisplay.cs
@@ -0,0 +1,135 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Hold information about a custom display resolution
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct CustomDisplay : IInitializable
+ {
+ internal StructureVersion _Version;
+ internal uint _Width;
+ internal uint _Height;
+ internal uint _Depth;
+ internal ColorFormat _ColorFormat;
+ internal ViewPortF _SourcePartition;
+ internal float _XRatio;
+ internal float _YRatio;
+ internal Timing _Timing;
+ internal uint _Flags;
+
+ ///
+ /// Gets the source surface (source mode) width.
+ ///
+ public uint Width
+ {
+ get => _Width;
+ }
+
+ ///
+ /// Gets the source surface (source mode) height.
+ ///
+ public uint Height
+ {
+ get => _Height;
+ }
+
+ ///
+ /// Gets the source surface color depth. "0" means all 8/16/32bpp.
+ ///
+ public uint Depth
+ {
+ get => _Depth;
+ }
+
+ ///
+ /// Gets the color format (optional)
+ ///
+ public ColorFormat ColorFormat
+ {
+ get => _ColorFormat;
+ }
+
+ ///
+ /// Gets the source partition viewport. All values are between [0, 1]. For multi-mon support, should be set to
+ /// (0,0,1.0,1.0) for now.
+ ///
+ public ViewPortF SourcePartition
+ {
+ get => _SourcePartition;
+ }
+
+ ///
+ /// Gets the horizontal scaling ratio.
+ ///
+ public float XRatio
+ {
+ get => _XRatio;
+ }
+
+ ///
+ /// Gets the vertical scaling ratio.
+ ///
+ public float YRatio
+ {
+ get => _YRatio;
+ }
+
+ ///
+ /// Gets the timing used to program TMDS/DAC/LVDS/HDMI/TVEncoder, etc.
+ ///
+ public Timing Timing
+ {
+ get => _Timing;
+ }
+
+ ///
+ /// Gets a boolean value indicating that a hardware mode-set without OS update should be performed.
+ ///
+ public bool HardwareModeSetOnly
+ {
+ get => _Flags.GetBit(0);
+ }
+
+ ///
+ /// Creates an instance of
+ ///
+ /// The source surface (source mode) width.
+ /// The source surface (source mode) height.
+ /// The source surface color depth. "0" means all 8/16/32bpp.
+ /// The color format (optional)
+ /// The horizontal scaling ratio.
+ /// The vertical scaling ratio.
+ /// The timing used to program TMDS/DAC/LVDS/HDMI/TVEncoder, etc.
+ /// A boolean value indicating that a hardware mode-set without OS update should be performed.
+ public CustomDisplay(
+ uint width,
+ uint height,
+ uint depth,
+ ColorFormat colorFormat,
+ float xRatio,
+ float yRatio,
+ Timing timing,
+ bool hwModeSetOnly
+ )
+ {
+ this = typeof(CustomDisplay).Instantiate();
+
+ _Width = width;
+ _Height = height;
+ _Depth = depth;
+ _ColorFormat = colorFormat;
+ _SourcePartition = new ViewPortF(0, 0, 1, 1);
+ _XRatio = xRatio;
+ _YRatio = yRatio;
+ _Timing = timing;
+ _Flags = _Flags.SetBit(0, hwModeSetOnly);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/DisplayColorData.cs b/NvAPIWrapper/Native/Display/Structures/DisplayColorData.cs
new file mode 100644
index 0000000..3a59071
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/DisplayColorData.cs
@@ -0,0 +1,70 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct DisplayColorData : IDisplayColorData
+ {
+ private readonly ColorDataColorCoordinate _FirstColorCoordinate;
+ private readonly ColorDataColorCoordinate _SecondColorCoordinate;
+ private readonly ColorDataColorCoordinate _ThirdColorCoordinate;
+ private readonly ColorDataColorCoordinate _WhiteColorCoordinate;
+ private readonly ushort _MaximumDesiredContentLuminance;
+ private readonly ushort _MinimumDesiredContentLuminance;
+ private readonly ushort _MaximumDesiredFrameAverageLightLevel;
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataColorCoordinate FirstColorCoordinate
+ {
+ get => _FirstColorCoordinate;
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataColorCoordinate SecondColorCoordinate
+ {
+ get => _SecondColorCoordinate;
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataColorCoordinate ThirdColorCoordinate
+ {
+ get => _ThirdColorCoordinate;
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataColorCoordinate WhiteColorCoordinate
+ {
+ get => _WhiteColorCoordinate;
+ }
+
+ ///
+ /// Gets the maximum desired content luminance [1.0-65535] in cd/m^2
+ ///
+ public float MaximumDesiredContentLuminance
+ {
+ get => _MaximumDesiredContentLuminance;
+ }
+
+ ///
+ /// Gets the maximum desired content frame average light level (a.k.a MaxFALL) [1.0-65535] in cd/m^2
+ ///
+ public float MaximumDesiredContentFrameAverageLightLevel
+ {
+ get => _MaximumDesiredFrameAverageLightLevel;
+ }
+
+ ///
+ /// Gets the maximum desired content luminance [1.0-6.5535] in cd/m^2
+ ///
+ public float MinimumDesiredContentLuminance
+ {
+ get => _MinimumDesiredContentLuminance / 10000f;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/DisplayHandle.cs b/NvAPIWrapper/Native/Display/Structures/DisplayHandle.cs
new file mode 100644
index 0000000..c19e6cb
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/DisplayHandle.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// DisplayHandle is a one-to-one map to the GDI handle of an attached display in the Windows Display Properties
+ /// Settings page.
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct DisplayHandle : IHandle, IEquatable
+ {
+ internal readonly IntPtr _MemoryAddress;
+
+ ///
+ public IntPtr MemoryAddress
+ {
+ get => _MemoryAddress;
+ }
+
+ ///
+ public bool IsNull
+ {
+ get => _MemoryAddress == IntPtr.Zero;
+ }
+
+ ///
+ public bool Equals(DisplayHandle other)
+ {
+ return _MemoryAddress.Equals(other._MemoryAddress);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is DisplayHandle handle && Equals(handle);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return _MemoryAddress.GetHashCode();
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(DisplayHandle left, DisplayHandle right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(DisplayHandle left, DisplayHandle right)
+ {
+ return !left.Equals(right);
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"DisplayHandle #{MemoryAddress.ToInt64()}";
+ }
+
+ ///
+ /// Gets default DisplayHandle with a null pointer
+ ///
+ public static DisplayHandle DefaultHandle
+ {
+ get => default(DisplayHandle);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/HDMISupportInfoV1.cs b/NvAPIWrapper/Native/Display/Structures/HDMISupportInfoV1.cs
new file mode 100644
index 0000000..2da5ea0
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/HDMISupportInfoV1.cs
@@ -0,0 +1,94 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Explicit, Pack = 8)]
+ [StructureVersion(1)]
+ public struct HDMISupportInfoV1 : IInitializable, IHDMISupportInfo
+ {
+ [FieldOffset(0)] internal StructureVersion _Version;
+ [FieldOffset(4)] private readonly uint _Flags;
+ [FieldOffset(8)] private readonly uint _EDID861ExtensionRevision;
+
+ ///
+ public bool IsGPUCapableOfHDMIOutput
+ {
+ get => _Flags.GetBit(0);
+ }
+
+ ///
+ public bool? IsMonitorCapableOfsYCC601
+ {
+ get => null;
+ }
+
+ ///
+ public bool IsMonitorCapableOfUnderscan
+ {
+ get => _Flags.GetBit(1);
+ }
+
+ ///
+ public bool? IsMonitorCapableOfAdobeYCC601
+ {
+ get => null;
+ }
+
+ ///
+ public bool IsMonitorCapableOfBasicAudio
+ {
+ get => _Flags.GetBit(2);
+ }
+
+ ///
+ public bool IsMonitorCapableOfYCbCr444
+ {
+ get => _Flags.GetBit(3);
+ }
+
+ ///
+ public bool IsMonitorCapableOfYCbCr422
+ {
+ get => _Flags.GetBit(4);
+ }
+
+ ///
+ // ReSharper disable once IdentifierTypo
+ public bool IsMonitorCapableOfxvYCC601
+ {
+ get => _Flags.GetBit(5);
+ }
+
+ ///
+ // ReSharper disable once IdentifierTypo
+ public bool IsMonitorCapableOfxvYCC709
+ {
+ get => _Flags.GetBit(6);
+ }
+
+ ///
+ public bool IsHDMIMonitor
+ {
+ get => _Flags.GetBit(7);
+ }
+
+ ///
+ public bool? IsMonitorCapableOfAdobeRGB
+ {
+ get => null;
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public uint EDID861ExtensionRevision
+ {
+ get => _EDID861ExtensionRevision;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/HDMISupportInfoV2.cs b/NvAPIWrapper/Native/Display/Structures/HDMISupportInfoV2.cs
new file mode 100644
index 0000000..5072ad7
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/HDMISupportInfoV2.cs
@@ -0,0 +1,94 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Explicit, Pack = 8)]
+ [StructureVersion(2)]
+ public struct HDMISupportInfoV2 : IInitializable, IHDMISupportInfo
+ {
+ [FieldOffset(0)] internal StructureVersion _Version;
+ [FieldOffset(4)] private readonly uint _Flags;
+ [FieldOffset(8)] private readonly uint _EDID861ExtensionRevision;
+
+ ///
+ public bool IsGPUCapableOfHDMIOutput
+ {
+ get => _Flags.GetBit(0);
+ }
+
+ ///
+ public bool IsMonitorCapableOfUnderscan
+ {
+ get => _Flags.GetBit(1);
+ }
+
+ ///
+ public bool IsMonitorCapableOfBasicAudio
+ {
+ get => _Flags.GetBit(2);
+ }
+
+ ///
+ public bool IsMonitorCapableOfYCbCr444
+ {
+ get => _Flags.GetBit(3);
+ }
+
+ ///
+ public bool IsMonitorCapableOfYCbCr422
+ {
+ get => _Flags.GetBit(4);
+ }
+
+ ///
+ // ReSharper disable once IdentifierTypo
+ public bool IsMonitorCapableOfxvYCC601
+ {
+ get => _Flags.GetBit(5);
+ }
+
+ ///
+ // ReSharper disable once IdentifierTypo
+ public bool IsMonitorCapableOfxvYCC709
+ {
+ get => _Flags.GetBit(6);
+ }
+
+ ///
+ public bool IsHDMIMonitor
+ {
+ get => _Flags.GetBit(7);
+ }
+
+ ///
+ public bool? IsMonitorCapableOfsYCC601
+ {
+ get => _Flags.GetBit(8);
+ }
+
+ ///
+ public bool? IsMonitorCapableOfAdobeYCC601
+ {
+ get => _Flags.GetBit(9);
+ }
+
+ ///
+ public bool? IsMonitorCapableOfAdobeRGB
+ {
+ get => _Flags.GetBit(10);
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public uint EDID861ExtensionRevision
+ {
+ get => _EDID861ExtensionRevision;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/HDRCapabilitiesV1.cs b/NvAPIWrapper/Native/Display/Structures/HDRCapabilitiesV1.cs
new file mode 100644
index 0000000..cda5283
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/HDRCapabilitiesV1.cs
@@ -0,0 +1,80 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains information regarding HDR capabilities of a display
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct HDRCapabilitiesV1 : IInitializable
+ {
+ internal StructureVersion _Version;
+ private readonly uint _RawReserved;
+
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ private readonly StaticMetadataDescriptorId _StaticMetadataDescriptorId;
+ private readonly DisplayColorData _DisplayData;
+
+ internal HDRCapabilitiesV1(bool expandDriverDefaultHDRParameters)
+ {
+ this = typeof(HDRCapabilitiesV1).Instantiate();
+ _RawReserved = 0u.SetBit(3, expandDriverDefaultHDRParameters);
+ _StaticMetadataDescriptorId = StaticMetadataDescriptorId.StaticMetadataType1;
+ }
+
+ ///
+ /// Gets the display color space configurations
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public DisplayColorData DisplayData
+ {
+ get => _DisplayData;
+ }
+
+ ///
+ /// Gets a boolean value indicating if the HDMI2.0a UHDA HDR with ST2084 EOTF (CEA861.3) is supported.
+ ///
+ public bool IsST2084EOTFSupported
+ {
+ get => _RawReserved.GetBit(0);
+ }
+
+ ///
+ /// Gets a boolean value indicating if the HDMI2.0a traditional HDR gamma (CEA861.3) is supported.
+ ///
+ public bool IsTraditionalHDRGammaSupported
+ {
+ get => _RawReserved.GetBit(1);
+ }
+
+ ///
+ /// Gets a boolean value indicating if the Extended Dynamic Range on SDR displays is supported.
+ ///
+ public bool IsEDRSupported
+ {
+ get => _RawReserved.GetBit(2);
+ }
+
+ ///
+ /// Gets a boolean value indicating if the default EDID HDR parameters is expanded;
+ /// otherwise false if this instance contains actual HDR parameters.
+ ///
+ public bool IsDriverDefaultHDRParametersExpanded
+ {
+ get => _RawReserved.GetBit(3);
+ }
+
+ ///
+ /// Gets a boolean value indicating if the HDMI2.0a traditional SDR gamma is supported.
+ ///
+ public bool IsTraditionalSDRGammaSupported
+ {
+ get => _RawReserved.GetBit(4);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/HDRColorDataV1.cs b/NvAPIWrapper/Native/Display/Structures/HDRColorDataV1.cs
new file mode 100644
index 0000000..2a37132
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/HDRColorDataV1.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct HDRColorDataV1 : IInitializable, IHDRColorData
+ {
+ internal StructureVersion _Version;
+ private readonly ColorDataHDRCommand _Command;
+ private readonly ColorDataHDRMode _HDRMode;
+
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ private readonly StaticMetadataDescriptorId _StaticMetadataDescriptorId;
+ private readonly MasteringDisplayColorData _MasteringDisplayData;
+
+ ///
+ /// Creates an instance of .
+ ///
+ /// The command to be executed.
+ /// The hdr mode.
+ /// The display color space configurations.
+ public HDRColorDataV1(
+ ColorDataHDRCommand command,
+ ColorDataHDRMode hdrMode,
+ MasteringDisplayColorData masteringDisplayData = default
+ )
+ {
+ this = typeof(HDRColorDataV1).Instantiate();
+
+ if (command != ColorDataHDRCommand.Set)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = command;
+ _HDRMode = hdrMode;
+ _MasteringDisplayData = masteringDisplayData;
+ _StaticMetadataDescriptorId = StaticMetadataDescriptorId.StaticMetadataType1;
+ }
+
+
+ ///
+ /// Creates an instance of .
+ ///
+ /// The command to be executed.
+ public HDRColorDataV1(ColorDataHDRCommand command)
+ {
+ this = typeof(HDRColorDataV1).Instantiate();
+
+ if (command != ColorDataHDRCommand.Get)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = command;
+ }
+
+ ///
+ public ColorDataDepth? ColorDepth
+ {
+ get => null;
+ }
+
+ ///
+ public ColorDataFormat? ColorFormat
+ {
+ get => null;
+ }
+
+ ///
+ /// Gets the color data command
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataHDRCommand Command
+ {
+ get => _Command;
+ }
+
+ ///
+ public ColorDataDynamicRange? DynamicRange
+ {
+ get => null;
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataHDRMode HDRMode
+ {
+ get => _HDRMode;
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public MasteringDisplayColorData MasteringDisplayData
+ {
+ get => _MasteringDisplayData;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/HDRColorDataV2.cs b/NvAPIWrapper/Native/Display/Structures/HDRColorDataV2.cs
new file mode 100644
index 0000000..2f9c9d6
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/HDRColorDataV2.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(2)]
+ public struct HDRColorDataV2 : IInitializable, IHDRColorData
+ {
+ internal StructureVersion _Version;
+ private readonly ColorDataHDRCommand _Command;
+ private readonly ColorDataHDRMode _HDRMode;
+
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ private readonly StaticMetadataDescriptorId _StaticMetadataDescriptorId;
+ private readonly MasteringDisplayColorData _MasteringDisplayData;
+ private readonly ColorDataFormat _ColorFormat;
+ private readonly ColorDataDynamicRange _DynamicRange;
+ private readonly ColorDataDepth _ColorDepth;
+
+ ///
+ /// Creates an instance of .
+ ///
+ /// The command to be executed.
+ /// The hdr mode.
+ /// The display color space configurations.
+ /// The color data color format.
+ /// The color data dynamic range.
+ /// The color data color depth.
+ public HDRColorDataV2(
+ ColorDataHDRCommand command,
+ ColorDataHDRMode hdrMode,
+ MasteringDisplayColorData masteringDisplayData = default,
+ ColorDataFormat colorFormat = ColorDataFormat.Default,
+ ColorDataDynamicRange dynamicRange = ColorDataDynamicRange.Auto,
+ ColorDataDepth colorDepth = ColorDataDepth.Default
+ )
+ {
+ this = typeof(HDRColorDataV2).Instantiate();
+
+ if (command != ColorDataHDRCommand.Set)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = command;
+ _HDRMode = hdrMode;
+ _MasteringDisplayData = masteringDisplayData;
+ _ColorFormat = colorFormat;
+ _DynamicRange = dynamicRange;
+ _ColorDepth = colorDepth;
+ _StaticMetadataDescriptorId = StaticMetadataDescriptorId.StaticMetadataType1;
+ }
+
+ ///
+ /// Creates an instance of .
+ ///
+ /// The command to be executed.
+ public HDRColorDataV2(ColorDataHDRCommand command)
+ {
+ this = typeof(HDRColorDataV2).Instantiate();
+
+ if (command != ColorDataHDRCommand.Get)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = command;
+ }
+
+ ///
+ /// Gets the color data command
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataHDRCommand Command
+ {
+ get => _Command;
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataHDRMode HDRMode
+ {
+ get => _HDRMode;
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public MasteringDisplayColorData MasteringDisplayData
+ {
+ get => _MasteringDisplayData;
+ }
+
+ ///
+ public ColorDataFormat? ColorFormat
+ {
+ get => _ColorFormat;
+ }
+
+ ///
+ public ColorDataDynamicRange? DynamicRange
+ {
+ get => _DynamicRange;
+ }
+
+ ///
+ public ColorDataDepth? ColorDepth
+ {
+ get
+ {
+ switch ((uint) _ColorDepth)
+ {
+ case 6:
+ return ColorDataDepth.BPC6;
+ case 8:
+ return ColorDataDepth.BPC8;
+ case 10:
+ return ColorDataDepth.BPC10;
+ case 12:
+ return ColorDataDepth.BPC12;
+ case 16:
+ return ColorDataDepth.BPC16;
+ default:
+ return _ColorDepth;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/InfoFrameAudio.cs b/NvAPIWrapper/Native/Display/Structures/InfoFrameAudio.cs
new file mode 100644
index 0000000..5389707
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/InfoFrameAudio.cs
@@ -0,0 +1,142 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Helpers;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains info-frame audio information
+ ///
+ [StructLayout(LayoutKind.Explicit, Pack = 8)]
+ public struct InfoFrameAudio
+ {
+ [FieldOffset(0)] private readonly uint _WordAt0;
+
+ [FieldOffset(4)] private readonly uint _WordAt4;
+
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ [FieldOffset(8)] private readonly uint _WordAt8;
+
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ [FieldOffset(12)] private readonly byte _ByteAt12;
+
+ ///
+ /// Creates an instance of .
+ ///
+ /// The audio coding type (codec)
+ /// The audio codec from codec extension
+ /// The audio sample size (depth)
+ /// The audio sample rate (sampling frequency)
+ /// The number of audio channels
+ /// The audio channel allocation (speaker placements)
+ /// A value indicating if down-mix is prohibited
+ /// The Low Frequency Effects playback level value
+ /// The audio level shift value
+ public InfoFrameAudio(
+ InfoFrameAudioCodec codec,
+ InfoFrameAudioExtendedCodec codecExtension,
+ InfoFrameAudioSampleSize sampleSize,
+ InfoFrameAudioSampleRate sampleRate,
+ InfoFrameAudioChannelCount channelCount,
+ InfoFrameAudioChannelAllocation channelAllocation,
+ InfoFrameBoolean isDownMixProhibited,
+ InfoFrameAudioLFEPlaybackLevel lfePlaybackLevel,
+ InfoFrameAudioLevelShift levelShift
+ )
+ {
+ _WordAt0 = 0u
+ .SetBits(0, 5, (uint) codec)
+ .SetBits(5, 6, (uint) codecExtension)
+ .SetBits(11, 3, (uint) sampleSize)
+ .SetBits(14, 4, (uint) sampleRate)
+ .SetBits(18, 4, (uint) channelCount)
+ .SetBits(22, 9, (uint) channelAllocation);
+ _WordAt4 = 0u
+ .SetBits(0, 2, (uint) isDownMixProhibited)
+ .SetBits(2, 3, (uint) lfePlaybackLevel)
+ .SetBits(5, 5, (uint) levelShift);
+ _WordAt8 = 0;
+ _ByteAt12 = 0;
+ }
+
+ ///
+ /// Gets the audio coding type (codec)
+ ///
+ public InfoFrameAudioCodec Codec
+ {
+ get => (InfoFrameAudioCodec) _WordAt0.GetBits(0, 5);
+ }
+
+ ///
+ /// Gets the audio codec from codec extension; only valid when
+ /// ==
+ ///
+ public InfoFrameAudioExtendedCodec? ExtendedCodec
+ {
+ get
+ {
+ if (Codec != InfoFrameAudioCodec.UseExtendedCodecType)
+ {
+ return null;
+ }
+
+ return (InfoFrameAudioExtendedCodec) _WordAt0.GetBits(5, 6);
+ }
+ }
+
+ ///
+ /// Gets the audio sample size (depth)
+ ///
+ public InfoFrameAudioSampleSize SampleSize
+ {
+ get => (InfoFrameAudioSampleSize) _WordAt0.GetBits(11, 3);
+ }
+
+ ///
+ /// Gets the audio sample rate (sampling frequency)
+ ///
+ public InfoFrameAudioSampleRate SampleRate
+ {
+ get => (InfoFrameAudioSampleRate) _WordAt0.GetBits(14, 4);
+ }
+
+ ///
+ /// Gets the number of audio channels
+ ///
+ public InfoFrameAudioChannelCount ChannelCount
+ {
+ get => (InfoFrameAudioChannelCount) _WordAt0.GetBits(18, 4);
+ }
+
+ ///
+ /// Gets the audio channel allocation (speaker placements)
+ ///
+ public InfoFrameAudioChannelAllocation ChannelAllocation
+ {
+ get => (InfoFrameAudioChannelAllocation) _WordAt0.GetBits(22, 9);
+ }
+
+ ///
+ /// Gets a value indicating if down-mix is prohibited
+ ///
+ public InfoFrameBoolean IsDownMixProhibited
+ {
+ get => (InfoFrameBoolean) _WordAt4.GetBits(0, 2);
+ }
+
+ ///
+ /// Gets the Low Frequency Effects playback level value
+ ///
+ public InfoFrameAudioLFEPlaybackLevel LFEPlaybackLevel
+ {
+ get => (InfoFrameAudioLFEPlaybackLevel) _WordAt4.GetBits(2, 3);
+ }
+
+ ///
+ /// Gets the audio level shift value
+ ///
+ public InfoFrameAudioLevelShift LevelShift
+ {
+ get => (InfoFrameAudioLevelShift) _WordAt4.GetBits(5, 5);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/InfoFrameData.cs b/NvAPIWrapper/Native/Display/Structures/InfoFrameData.cs
new file mode 100644
index 0000000..d90ded1
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/InfoFrameData.cs
@@ -0,0 +1,199 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains info-frame requested information or information to be overriden
+ ///
+ [StructLayout(LayoutKind.Explicit, Pack = 8)]
+ [StructureVersion(1)]
+ public struct InfoFrameData : IInitializable
+ {
+ [FieldOffset(0)] internal StructureVersion _Version;
+
+ [FieldOffset(4)]
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ private readonly ushort _Size;
+
+ [FieldOffset(6)]
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ private readonly byte _Command;
+
+ [FieldOffset(7)] private readonly byte _Type;
+
+ [FieldOffset(8)] private readonly InfoFrameProperty _Property;
+ [FieldOffset(8)] private readonly InfoFrameAudio _Audio;
+ [FieldOffset(8)] private readonly InfoFrameVideo _Video;
+
+ ///
+ /// Creates a new instance of .
+ ///
+ ///
+ /// The operation to be done. Can be used for information retrieval or to reset configurations to
+ /// default.
+ ///
+ /// The type of information.
+ public InfoFrameData(InfoFrameCommand command, InfoFrameDataType dataType)
+ {
+ this = typeof(InfoFrameData).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != InfoFrameCommand.Get &&
+ command != InfoFrameCommand.GetDefault &&
+ command != InfoFrameCommand.GetOverride &&
+ command != InfoFrameCommand.GetProperty &&
+ command != InfoFrameCommand.Reset)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ _Type = (byte) dataType;
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The operation to be done. Can only be used to change property information.
+ /// The type of information.
+ /// The new property information to be set.
+ public InfoFrameData(
+ InfoFrameCommand command,
+ InfoFrameDataType dataType,
+ InfoFrameProperty propertyInformation)
+ {
+ this = typeof(InfoFrameData).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != InfoFrameCommand.SetProperty)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ _Type = (byte) dataType;
+ _Property = propertyInformation;
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The operation to be done. Can only be used to change current or default audio information.
+ /// The new audio information to be set.
+ public InfoFrameData(InfoFrameCommand command, InfoFrameAudio audioInformation)
+ {
+ this = typeof(InfoFrameData).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != InfoFrameCommand.Set &&
+ command != InfoFrameCommand.SetOverride)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ _Type = (byte) InfoFrameDataType.AudioInformation;
+ _Audio = audioInformation;
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The operation to be done. Can only be used to change current or default video information.
+ /// The new video information to be set.
+ public InfoFrameData(InfoFrameCommand command, InfoFrameVideo videoInformation)
+ {
+ this = typeof(InfoFrameData).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+
+ if (command != InfoFrameCommand.Set &&
+ command != InfoFrameCommand.SetOverride)
+ {
+ throw new ArgumentOutOfRangeException(nameof(command));
+ }
+
+ _Command = (byte) command;
+ _Type = (byte) InfoFrameDataType.AuxiliaryVideoInformation;
+ _Video = videoInformation;
+ }
+
+ ///
+ /// Gets the type of data contained in this instance
+ ///
+ public InfoFrameDataType Type
+ {
+ get => (InfoFrameDataType) _Type;
+ }
+
+ ///
+ /// Gets the operation type
+ ///
+ public InfoFrameCommand Command
+ {
+ get => (InfoFrameCommand) _Command;
+ }
+
+ ///
+ /// Gets the info-frame audio information if available; otherwise null
+ ///
+ public InfoFrameAudio? AudioInformation
+ {
+ get
+ {
+ if (Command == InfoFrameCommand.GetProperty || Command == InfoFrameCommand.SetProperty)
+ {
+ return null;
+ }
+
+ if (Type == InfoFrameDataType.AudioInformation)
+ {
+ return _Audio;
+ }
+
+ return null;
+ }
+ }
+
+ ///
+ /// Gets the info-frame auxiliary video information (AVI) if available; otherwise null
+ ///
+ public InfoFrameVideo? AuxiliaryVideoInformation
+ {
+ get
+ {
+ if (Command == InfoFrameCommand.GetProperty || Command == InfoFrameCommand.SetProperty)
+ {
+ return null;
+ }
+
+ if (Type == InfoFrameDataType.AuxiliaryVideoInformation)
+ {
+ return _Video;
+ }
+
+ return null;
+ }
+ }
+
+ ///
+ /// Gets the info-frame property information if available; otherwise null
+ ///
+ public InfoFrameProperty? PropertyInformation
+ {
+ get
+ {
+ if (Command != InfoFrameCommand.GetProperty && Command != InfoFrameCommand.SetProperty)
+ {
+ return null;
+ }
+
+ return _Property;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/InfoFrameProperty.cs b/NvAPIWrapper/Native/Display/Structures/InfoFrameProperty.cs
new file mode 100644
index 0000000..1489be5
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/InfoFrameProperty.cs
@@ -0,0 +1,58 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Helpers;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains info-frame property information
+ ///
+ [StructLayout(LayoutKind.Explicit, Pack = 8)]
+ public struct InfoFrameProperty
+ {
+ [FieldOffset(0)] private readonly uint _Word;
+
+ ///
+ /// Creates an instance of .
+ ///
+ /// The info-frame operation mode
+ /// A value indicating if this display (monitor) is blacklisted
+ public InfoFrameProperty(InfoFramePropertyMode mode, InfoFrameBoolean isBlackListed)
+ {
+ _Word = 0u
+ .SetBits(0, 4, (uint) mode)
+ .SetBits(4, 2, (uint) isBlackListed);
+ }
+
+ ///
+ /// Gets the info-frame operation mode
+ ///
+ public InfoFramePropertyMode Mode
+ {
+ get => (InfoFramePropertyMode) _Word.GetBits(0, 4);
+ }
+
+ ///
+ /// Gets a value indicating if this display (monitor) is blacklisted
+ ///
+ public InfoFrameBoolean IsBlackListed
+ {
+ get => (InfoFrameBoolean) _Word.GetBits(4, 2);
+ }
+
+ ///
+ /// Gets the info-frame version
+ ///
+ public byte Version
+ {
+ get => (byte) _Word.GetBits(16, 8);
+ }
+
+ ///
+ /// Gets the info-frame length
+ ///
+ public byte Length
+ {
+ get => (byte) _Word.GetBits(24, 8);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/InfoFrameVideo.cs b/NvAPIWrapper/Native/Display/Structures/InfoFrameVideo.cs
new file mode 100644
index 0000000..a366bda
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/InfoFrameVideo.cs
@@ -0,0 +1,320 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Helpers;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains info-frame video information
+ ///
+ [StructLayout(LayoutKind.Explicit, Pack = 8)]
+ public struct InfoFrameVideo
+ {
+ [FieldOffset(0)] private readonly uint _WordAt0;
+ [FieldOffset(4)] private readonly uint _WordAt4;
+ [FieldOffset(8)] private readonly uint _WordAt8;
+ [FieldOffset(12)] private readonly uint _WordAt12;
+ [FieldOffset(16)] private readonly uint _WordAt16;
+ [FieldOffset(20)] private readonly uint _WordAt20;
+
+ ///
+ /// Creates an instance of .
+ ///
+ /// The video identification code (VIC)
+ /// The video pixel repetition
+ /// The video color format
+ /// The video color space
+ /// The extended video color space
+ /// The RGB quantization configuration
+ /// The YCC quantization configuration
+ /// The video content mode
+ /// The video content type
+ /// The video scan information
+ /// A value indicating if the active format information is present
+ /// The active format aspect ratio
+ /// The picture aspect ratio
+ /// The non uniform picture scaling direction
+ /// The video bar information
+ /// The top bar value if not auto and present; otherwise null
+ /// The bottom bar value if not auto and present; otherwise null
+ /// The left bar value if not auto and present; otherwise null
+ /// The right bar value if not auto and present; otherwise null
+ public InfoFrameVideo(
+ byte videoIdentificationCode,
+ InfoFrameVideoPixelRepetition pixelRepetition,
+ InfoFrameVideoColorFormat colorFormat,
+ InfoFrameVideoColorimetry colorimetry,
+ InfoFrameVideoExtendedColorimetry extendedColorimetry,
+ InfoFrameVideoRGBQuantization rgbQuantization,
+ InfoFrameVideoYCCQuantization yccQuantization,
+ InfoFrameVideoITC contentMode,
+ InfoFrameVideoContentType contentType,
+ InfoFrameVideoScanInfo scanInfo,
+ InfoFrameBoolean isActiveFormatInfoPresent,
+ InfoFrameVideoAspectRatioActivePortion activeFormatAspectRatio,
+ InfoFrameVideoAspectRatioCodedFrame pictureAspectRatio,
+ InfoFrameVideoNonUniformPictureScaling nonUniformPictureScaling,
+ InfoFrameVideoBarData barInfo,
+ uint? topBar,
+ uint? bottomBar,
+ uint? leftBar,
+ uint? rightBar
+ )
+ {
+ _WordAt0 = 0u
+ .SetBits(0, 8, videoIdentificationCode)
+ .SetBits(8, 5, (uint) pixelRepetition)
+ .SetBits(13, 3, (uint) colorFormat)
+ .SetBits(16, 3, (uint) colorimetry)
+ .SetBits(19, 4, (uint) extendedColorimetry)
+ .SetBits(23, 3, (uint) rgbQuantization)
+ .SetBits(26, 3, (uint) yccQuantization)
+ .SetBits(29, 2, (uint) contentMode);
+
+ _WordAt4 = 0u
+ .SetBits(0, 3, (uint) contentType)
+ .SetBits(3, 3, (uint) scanInfo)
+ .SetBits(6, 2, (uint) isActiveFormatInfoPresent)
+ .SetBits(8, 5, (uint) activeFormatAspectRatio)
+ .SetBits(13, 3, (uint) pictureAspectRatio)
+ .SetBits(16, 3, (uint) nonUniformPictureScaling)
+ .SetBits(19, 3, (uint) barInfo);
+
+ _WordAt8 = topBar == null ? 0x1FFFF : 0u.SetBits(0, 17, topBar.Value);
+ _WordAt12 = bottomBar == null ? 0x1FFFF : 0u.SetBits(0, 17, bottomBar.Value);
+ _WordAt16 = leftBar == null ? 0x1FFFF : 0u.SetBits(0, 17, leftBar.Value);
+ _WordAt20 = rightBar == null ? 0x1FFFF : 0u.SetBits(0, 17, rightBar.Value);
+ }
+
+ ///
+ /// Gets the video identification code (VIC)
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public byte? VideoIdentificationCode
+ {
+ get
+ {
+ var value = (byte) _WordAt0.GetBits(0, 8);
+
+ if (value == 0xFF)
+ {
+ return null;
+ }
+
+ return value;
+ }
+ }
+
+ ///
+ /// Gets the video pixel repetition
+ ///
+ public InfoFrameVideoPixelRepetition PixelRepetition
+ {
+ get => (InfoFrameVideoPixelRepetition) _WordAt0.GetBits(8, 5);
+ }
+
+ ///
+ /// Gets the video color format
+ ///
+ public InfoFrameVideoColorFormat ColorFormat
+ {
+ get => (InfoFrameVideoColorFormat) _WordAt0.GetBits(13, 3);
+ }
+
+ ///
+ /// Gets the video color space
+ ///
+ public InfoFrameVideoColorimetry Colorimetry
+ {
+ get => (InfoFrameVideoColorimetry) _WordAt0.GetBits(16, 3);
+ }
+
+ ///
+ /// Gets the extended video color space; only valid when ==
+ ///
+ ///
+ public InfoFrameVideoExtendedColorimetry? ExtendedColorimetry
+ {
+ get
+ {
+ if (Colorimetry != InfoFrameVideoColorimetry.UseExtendedColorimetry)
+ {
+ return null;
+ }
+
+ return (InfoFrameVideoExtendedColorimetry) _WordAt0.GetBits(19, 4);
+ }
+ }
+
+ ///
+ /// Gets the RGB quantization configuration
+ ///
+ public InfoFrameVideoRGBQuantization RGBQuantization
+ {
+ get => (InfoFrameVideoRGBQuantization) _WordAt0.GetBits(23, 3);
+ }
+
+ ///
+ /// Gets the YCC quantization configuration
+ ///
+ public InfoFrameVideoYCCQuantization YCCQuantization
+ {
+ get => (InfoFrameVideoYCCQuantization) _WordAt0.GetBits(26, 3);
+ }
+
+ ///
+ /// Gets the video content mode
+ ///
+ public InfoFrameVideoITC ContentMode
+ {
+ get => (InfoFrameVideoITC) _WordAt0.GetBits(29, 2);
+ }
+
+ ///
+ /// Gets the video content type
+ ///
+ public InfoFrameVideoContentType ContentType
+ {
+ get => (InfoFrameVideoContentType) _WordAt4.GetBits(0, 3);
+ }
+
+ ///
+ /// Gets the video scan information
+ ///
+ public InfoFrameVideoScanInfo ScanInfo
+ {
+ get => (InfoFrameVideoScanInfo) _WordAt4.GetBits(3, 3);
+ }
+
+ ///
+ /// Gets a value indicating if the active format information is present
+ ///
+ public InfoFrameBoolean IsActiveFormatInfoPresent
+ {
+ get => (InfoFrameBoolean) _WordAt4.GetBits(6, 2);
+ }
+
+ ///
+ /// Gets the active format aspect ratio
+ ///
+ public InfoFrameVideoAspectRatioActivePortion ActiveFormatAspectRatio
+ {
+ get => (InfoFrameVideoAspectRatioActivePortion) _WordAt4.GetBits(8, 5);
+ }
+
+ ///
+ /// Gets the picture aspect ratio
+ ///
+ public InfoFrameVideoAspectRatioCodedFrame PictureAspectRatio
+ {
+ get => (InfoFrameVideoAspectRatioCodedFrame) _WordAt4.GetBits(13, 3);
+ }
+
+ ///
+ /// Gets the non uniform picture scaling direction
+ ///
+ public InfoFrameVideoNonUniformPictureScaling NonUniformPictureScaling
+ {
+ get => (InfoFrameVideoNonUniformPictureScaling) _WordAt4.GetBits(16, 3);
+ }
+
+ ///
+ /// Gets the video bar information
+ ///
+ public InfoFrameVideoBarData BarInfo
+ {
+ get => (InfoFrameVideoBarData) _WordAt4.GetBits(19, 3);
+ }
+
+ ///
+ /// Gets the top bar value if not auto and present; otherwise null
+ ///
+ public uint? TopBar
+ {
+ get
+ {
+ if (BarInfo == InfoFrameVideoBarData.NotPresent || BarInfo == InfoFrameVideoBarData.Horizontal)
+ {
+ return null;
+ }
+
+ var val = _WordAt8.GetBits(0, 17);
+
+ if (val == 0x1FFFF)
+ {
+ return null;
+ }
+
+ return (uint) val;
+ }
+ }
+
+ ///
+ /// Gets the bottom bar value if not auto and present; otherwise null
+ ///
+ public uint? BottomBar
+ {
+ get
+ {
+ if (BarInfo == InfoFrameVideoBarData.NotPresent || BarInfo == InfoFrameVideoBarData.Horizontal)
+ {
+ return null;
+ }
+
+ var val = _WordAt12.GetBits(0, 17);
+
+ if (val == 0x1FFFF)
+ {
+ return null;
+ }
+
+ return (uint) val;
+ }
+ }
+
+ ///
+ /// Gets the left bar value if not auto and present; otherwise null
+ ///
+ public uint? LeftBar
+ {
+ get
+ {
+ if (BarInfo == InfoFrameVideoBarData.NotPresent || BarInfo == InfoFrameVideoBarData.Vertical)
+ {
+ return null;
+ }
+
+ var val = _WordAt16.GetBits(0, 17);
+
+ if (val == 0x1FFFF)
+ {
+ return null;
+ }
+
+ return (uint) val;
+ }
+ }
+
+ ///
+ /// Gets the right bar value if not auto and present; otherwise null
+ ///
+ public uint? RightBar
+ {
+ get
+ {
+ if (BarInfo == InfoFrameVideoBarData.NotPresent || BarInfo == InfoFrameVideoBarData.Vertical)
+ {
+ return null;
+ }
+
+ var val = _WordAt20.GetBits(0, 17);
+
+ if (val == 0x1FFFF)
+ {
+ return null;
+ }
+
+ return (uint) val;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/LUID.cs b/NvAPIWrapper/Native/Display/Structures/LUID.cs
new file mode 100644
index 0000000..1af8cae
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/LUID.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Locally unique identifier is a 64-bit value guaranteed to be unique only on the system on which it was generated.
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct LUID : IEquatable
+ {
+ ///
+ /// 32Bit unsigned integer, low
+ ///
+ public readonly uint LowPart;
+
+ ///
+ /// 32Bit signed integer, high
+ ///
+ public readonly int HighPart;
+
+ ///
+ public override string ToString()
+ {
+ return $"{{{LowPart:X}-{HighPart:X}}}";
+ }
+
+ ///
+ public bool Equals(LUID other)
+ {
+ return LowPart == other.LowPart && HighPart == other.HighPart;
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is LUID luid && Equals(luid);
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(LUID left, LUID right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(LUID left, LUID right)
+ {
+ return !left.Equals(right);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return ((int) LowPart * 397) ^ HighPart;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/MasteringDisplayColorData.cs b/NvAPIWrapper/Native/Display/Structures/MasteringDisplayColorData.cs
new file mode 100644
index 0000000..0a0f2da
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/MasteringDisplayColorData.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct MasteringDisplayColorData : IDisplayColorData
+ {
+ private readonly ColorDataColorCoordinate _FirstColorCoordinate;
+ private readonly ColorDataColorCoordinate _SecondColorCoordinate;
+ private readonly ColorDataColorCoordinate _ThirdColorCoordinate;
+ private readonly ColorDataColorCoordinate _WhiteColorCoordinate;
+ private readonly ushort _MaximumMasteringLuminance;
+ private readonly ushort _MinimumMasteringLuminance;
+ private readonly ushort _MaximumContentLightLevel;
+ private readonly ushort _MaximumFrameAverageLightLevel;
+
+ ///
+ /// Creates an instance of .
+ ///
+ /// The first primary color coordinate.
+ /// The second primary color coordinate.
+ /// The third primary color coordinate.
+ /// The white color coordinate.
+ /// The maximum mastering display luminance [1.0-65535] in cd/m^2
+ /// The maximum mastering display luminance [1.0-6.5535] in cd/m^2
+ ///
+ /// The maximum mastering display content light level (a.k.a MaxCLL) [1.0-65535] in
+ /// cd/m^2
+ ///
+ ///
+ /// The maximum mastering display frame average light level (a.k.a MaxFALL)
+ /// [1.0-65535] in cd/m^2
+ ///
+ public MasteringDisplayColorData(
+ ColorDataColorCoordinate firstColorCoordinate,
+ ColorDataColorCoordinate secondColorCoordinate,
+ ColorDataColorCoordinate thirdColorCoordinate,
+ ColorDataColorCoordinate whiteColorCoordinate,
+ float maximumMasteringLuminance,
+ float minimumMasteringLuminance,
+ float maximumContentLightLevel,
+ float maximumFrameAverageLightLevel
+ )
+ {
+ _FirstColorCoordinate = firstColorCoordinate;
+ _SecondColorCoordinate = secondColorCoordinate;
+ _ThirdColorCoordinate = thirdColorCoordinate;
+ _WhiteColorCoordinate = whiteColorCoordinate;
+ _MaximumMasteringLuminance = (ushort) Math.Max(Math.Min(maximumMasteringLuminance, uint.MaxValue), 1);
+ _MinimumMasteringLuminance =
+ (ushort) Math.Max(Math.Min(minimumMasteringLuminance * 10000, uint.MaxValue), 1);
+ _MaximumContentLightLevel = (ushort) Math.Max(Math.Min(maximumContentLightLevel, uint.MaxValue), 1);
+ _MaximumFrameAverageLightLevel =
+ (ushort) Math.Max(Math.Min(maximumFrameAverageLightLevel, uint.MaxValue), 1);
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataColorCoordinate FirstColorCoordinate
+ {
+ get => _FirstColorCoordinate;
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataColorCoordinate SecondColorCoordinate
+ {
+ get => _SecondColorCoordinate;
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataColorCoordinate ThirdColorCoordinate
+ {
+ get => _ThirdColorCoordinate;
+ }
+
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public ColorDataColorCoordinate WhiteColorCoordinate
+ {
+ get => _WhiteColorCoordinate;
+ }
+
+ ///
+ /// Gets the maximum mastering display luminance [1.0-65535] in cd/m^2
+ ///
+ public float MaximumMasteringLuminance
+ {
+ get => _MaximumMasteringLuminance;
+ }
+
+ ///
+ /// Gets the maximum mastering display frame average light level (a.k.a MaxFALL) [1.0-65535] in cd/m^2
+ ///
+ public float MaximumFrameAverageLightLevel
+ {
+ get => _MaximumFrameAverageLightLevel;
+ }
+
+ ///
+ /// Gets the maximum mastering display content light level (a.k.a MaxCLL) [1.0-65535] in cd/m^2
+ ///
+ public float MaximumContentLightLevel
+ {
+ get => _MaximumContentLightLevel;
+ }
+
+ ///
+ /// Gets the maximum mastering display luminance [1.0-6.5535] in cd/m^2
+ ///
+ public float MinimumMasteringLuminance
+ {
+ get => _MinimumMasteringLuminance / 10000f;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/MonitorCapabilities.cs b/NvAPIWrapper/Native/Display/Structures/MonitorCapabilities.cs
new file mode 100644
index 0000000..8d38851
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/MonitorCapabilities.cs
@@ -0,0 +1,96 @@
+using System.Linq;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains the monitor capabilities read from the Vendor Specific Data Block or the Video Capability Data Block
+ ///
+ [StructureVersion(1)]
+ [StructLayout(LayoutKind.Explicit, Pack = 8)]
+ public struct MonitorCapabilities : IInitializable
+ {
+ [FieldOffset(0)] internal StructureVersion _Version;
+
+ // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
+ [FieldOffset(4)] private readonly ushort _Size;
+ [FieldOffset(8)] private readonly MonitorCapabilitiesType _Type;
+ [FieldOffset(12)] private readonly MonitorCapabilitiesConnectorType _ConnectorType;
+
+ [FieldOffset(16)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
+ private readonly byte[] _Data;
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The type of information to be retrieved.
+ public MonitorCapabilities(MonitorCapabilitiesType type)
+ {
+ this = typeof(MonitorCapabilities).Instantiate();
+ _Size = (ushort) _Version.StructureSize;
+ _Type = type;
+ }
+
+ ///
+ /// Gets a boolean value indicating if this instance contains valid information
+ ///
+ public bool IsValid
+ {
+ get => _Data[0].GetBit(0);
+ }
+
+ ///
+ /// Gets the monitor capability type
+ ///
+ // ReSharper disable once ConvertToAutoPropertyWhenPossible
+ public MonitorCapabilitiesType Type
+ {
+ get => _Type;
+ }
+
+ ///
+ /// Gets the monitor connector type
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public MonitorCapabilitiesConnectorType ConnectorType
+ {
+ get => _ConnectorType;
+ }
+
+ ///
+ /// Gets the monitor VCDB capabilities information
+ ///
+ public MonitorVCDBCapabilities? VCDBCapabilities
+ {
+ get
+ {
+ if (IsValid && _Type == MonitorCapabilitiesType.VCDB)
+ {
+ return new MonitorVCDBCapabilities(_Data.Skip(1).ToArray());
+ }
+
+ return null;
+ }
+ }
+
+ ///
+ /// Gets the monitor VSDB capabilities information
+ ///
+ public MonitorVSDBCapabilities? VSDBCapabilities
+ {
+ get
+ {
+ if (IsValid && _Type == MonitorCapabilitiesType.VSDB)
+ {
+ return new MonitorVSDBCapabilities(_Data.Skip(1).ToArray());
+ }
+
+ return null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/MonitorColorData.cs b/NvAPIWrapper/Native/Display/Structures/MonitorColorData.cs
new file mode 100644
index 0000000..4cfe3a5
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/MonitorColorData.cs
@@ -0,0 +1,57 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains information about a monitor color data
+ ///
+ [StructureVersion(1)]
+ [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 12)]
+ public struct MonitorColorData : IInitializable
+ {
+ [FieldOffset(0)]
+ internal StructureVersion _Version;
+ [FieldOffset(4)]
+ private readonly DisplayPortColorFormat _ColorFormat;
+ [FieldOffset(8)]
+ private readonly DisplayPortColorDepth _ColorDepth;
+
+ ///
+ ///Gets the monitor display port color format
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public DisplayPortColorFormat ColorFormat
+ {
+ get => _ColorFormat;
+ }
+
+ ///
+ /// Gets the monitor display port color depth
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public DisplayPortColorDepth ColorDepth
+ {
+ get
+ {
+ switch ((uint) _ColorDepth)
+ {
+ case 6:
+ return DisplayPortColorDepth.BPC6;
+ case 8:
+ return DisplayPortColorDepth.BPC8;
+ case 10:
+ return DisplayPortColorDepth.BPC10;
+ case 12:
+ return DisplayPortColorDepth.BPC12;
+ case 16:
+ return DisplayPortColorDepth.BPC16;
+ default:
+ return _ColorDepth;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/MonitorVCDBCapabilities.cs b/NvAPIWrapper/Native/Display/Structures/MonitorVCDBCapabilities.cs
new file mode 100644
index 0000000..7305b7a
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/MonitorVCDBCapabilities.cs
@@ -0,0 +1,54 @@
+using System;
+using NvAPIWrapper.Native.Helpers;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains monitor VCDB capabilities
+ ///
+ public struct MonitorVCDBCapabilities
+ {
+ private readonly byte[] _data;
+
+ internal MonitorVCDBCapabilities(byte[] data)
+ {
+ if (data.Length != 49)
+ {
+ throw new ArgumentOutOfRangeException(nameof(data));
+ }
+
+ _data = data;
+ }
+
+ ///
+ /// Gets a boolean value indicating RGB range quantization
+ ///
+ public bool QuantizationRangeRGB
+ {
+ get => _data[0].GetBit(1);
+ }
+
+ ///
+ /// Gets a boolean value indicating Ycc range quantization
+ ///
+ public bool QuantizationRangeYcc
+ {
+ get => _data[0].GetBit(0);
+ }
+
+ public byte ScanInfoConsumerElectronicsVideoFormats
+ {
+ get => (byte)_data[0].GetBits(6, 2);
+ }
+
+ public byte ScanInfoInformationTechnologyVideoFormats
+ {
+ get => (byte)_data[0].GetBits(4, 2);
+ }
+
+ public byte ScanInfoPreferredVideoFormat
+ {
+ get => (byte)_data[0].GetBits(2, 2);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/MonitorVSDBCapabilities.cs b/NvAPIWrapper/Native/Display/Structures/MonitorVSDBCapabilities.cs
new file mode 100644
index 0000000..b81cdfd
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/MonitorVSDBCapabilities.cs
@@ -0,0 +1,254 @@
+using System;
+using System.Linq;
+using NvAPIWrapper.Native.Helpers;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains monitor VSDB capabilities
+ ///
+ public struct MonitorVSDBCapabilities
+ {
+ private readonly byte[] _data;
+
+ internal MonitorVSDBCapabilities(byte[] data)
+ {
+ if (data.Length != 49)
+ {
+ throw new ArgumentOutOfRangeException(nameof(data));
+ }
+
+ _data = data;
+ }
+
+ ///
+ /// Gets the audio latency if available or null
+ ///
+ public byte? AudioLatency
+ {
+ get
+ {
+ if (!_data[4].GetBit(7))
+ {
+ return null;
+ }
+
+ return _data[6];
+ }
+ }
+
+ public byte[] HDMI3D
+ {
+ get
+ {
+ if (!_data[9].GetBit(7))
+ {
+ return new byte[0];
+ }
+
+ return _data.Skip(18).Take(31).Take((int)_data[10].GetBits(0, 5)).ToArray();
+ }
+ }
+
+ public byte[] HDMIVideoImageCompositors
+ {
+ get
+ {
+ if (!_data[4].GetBit(5))
+ {
+ return new byte[0];
+ }
+
+ return _data.Skip(11).Take(7).Take((int)_data[10].GetBits(5, 3)).ToArray();
+ }
+ }
+
+ ///
+ /// Gets the interlaced audio latency if available or null
+ ///
+ public byte? InterlacedAudioLatency
+ {
+ get
+ {
+ if (!_data[4].GetBit(6))
+ {
+ return null;
+ }
+
+ return _data[8];
+ }
+ }
+
+ ///
+ /// Gets the interlaced video latency if available or null
+ ///
+ public byte? InterlacedVideoLatency
+ {
+ get
+ {
+ if (!_data[4].GetBit(6))
+ {
+ return null;
+ }
+
+ return _data[7];
+ }
+ }
+
+ public bool IsAISupported
+ {
+ get => _data[2].GetBit(7);
+ }
+
+ ///
+ /// Returns a boolean value indicating if the cinematic content is supported by the monitor or the connection
+ ///
+ public bool IsCinemaContentSupported
+ {
+ get => _data[4].GetBit(2);
+ }
+
+ ///
+ /// Returns a boolean value indicating if the 30bit deep color is supported by the monitor or the connection
+ ///
+ public bool IsDeepColor30BitsSupported
+ {
+ get => _data[2].GetBit(4);
+ }
+
+ ///
+ /// Returns a boolean value indicating if the 36bit deep color is supported by the monitor or the connection
+ ///
+ public bool IsDeepColor36BitsSupported
+ {
+ get => _data[2].GetBit(5);
+ }
+
+ ///
+ /// Returns a boolean value indicating if the 48bit deep color is supported by the monitor or the connection
+ ///
+ public bool IsDeepColor48BitsSupported
+ {
+ get => _data[2].GetBit(6);
+ }
+
+
+ ///
+ /// Returns a boolean value indicating if the YCbCr444 deep color is supported by the monitor or the connection
+ ///
+ public bool IsDeepColorYCbCr444Supported
+ {
+ get => _data[2].GetBit(3);
+ }
+
+ ///
+ /// Returns a boolean value indicating if the dual DVI operation is supported by the monitor or the connection
+ ///
+ public bool IsDualDVIOperationSupported
+ {
+ get => _data[2].GetBit(0);
+ }
+
+ ///
+ /// Returns a boolean value indicating if the gaming content is supported by the monitor or the connection
+ ///
+ public bool IsGameContentSupported
+ {
+ get => _data[4].GetBit(3);
+ }
+
+ ///
+ /// Returns a boolean value indicating if the graphics text content is supported by the monitor or the connection
+ ///
+ public bool IsGraphicsTextContentSupported
+ {
+ get => _data[4].GetBit(0);
+ }
+
+ ///
+ /// Returns a boolean value indicating if the photo content is supported by monitor or the connection
+ ///
+ public bool IsPhotoContentSupported
+ {
+ get => _data[4].GetBit(1);
+ }
+
+ ///
+ /// Gets the connection max TMDS clock supported by the monitor or the connection
+ ///
+ public byte MaxTMDSClock
+ {
+ get => _data[3];
+ }
+
+ ///
+ /// Gets the monitor physical address on port
+ ///
+ public MonitorPhysicalAddress PhysicalAddress
+ {
+ get => new MonitorPhysicalAddress(
+ (byte)_data[0].GetBits(4, 4),
+ (byte)_data[0].GetBits(0, 4),
+ (byte)_data[1].GetBits(4, 4),
+ (byte)_data[1].GetBits(0, 4)
+ );
+ }
+
+ ///
+ /// Gets the video latency if available or null
+ ///
+ public byte? VideoLatency
+ {
+ get
+ {
+ if (!_data[4].GetBit(7))
+ {
+ return null;
+ }
+
+ return _data[5];
+ }
+ }
+
+ ///
+ /// Represents a monitor physical address
+ ///
+ public class MonitorPhysicalAddress
+ {
+ internal MonitorPhysicalAddress(byte a, byte b, byte c, byte d)
+ {
+ A = a;
+ B = b;
+ C = c;
+ D = d;
+ }
+
+ ///
+ /// Gets the first part of a monitor physical address
+ ///
+ public byte A { get; set; }
+
+ ///
+ /// Gets the second part of a monitor physical address
+ ///
+ public byte B { get; set; }
+
+
+ ///
+ /// Gets the third part of a monitor physical address
+ ///
+ public byte C { get; set; }
+
+ ///
+ /// Gets the forth part of a monitor physical address
+ ///
+ public byte D { get; set; }
+
+ ///
+ public override string ToString()
+ {
+ return $"{A:D}.{B:D}.{C:D}.{D:D}";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/PathAdvancedTargetInfo.cs b/NvAPIWrapper/Native/Display/Structures/PathAdvancedTargetInfo.cs
new file mode 100644
index 0000000..73e649a
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/PathAdvancedTargetInfo.cs
@@ -0,0 +1,268 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.Exceptions;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds advanced information about a PathTargetInfo
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct PathAdvancedTargetInfo : IInitializable, IEquatable
+ {
+ internal StructureVersion _Version;
+ internal readonly Rotate _Rotation;
+ internal readonly Scaling _Scaling;
+ internal readonly uint _RefreshRateInMillihertz;
+ internal uint _RawReserved;
+ internal readonly ConnectorType _ConnectorType;
+ internal readonly TVFormat _TVFormat;
+ internal readonly TimingOverride _TimingOverride;
+ internal readonly Timing _Timing;
+
+ ///
+ /// Creates a new PathAdvancedTargetInfo for monitors
+ ///
+ /// Screen rotation
+ /// Screen scaling
+ /// Screen refresh rate
+ /// Timing override
+ /// Indicates if the mode is interlaced
+ /// Indicates if the display is the primary display of a clone topology
+ /// Indicates if the target Pan and Scan is enabled
+ ///
+ ///
+ ///
+ public PathAdvancedTargetInfo(
+ Rotate rotation,
+ Scaling scale,
+ uint refreshRateInMillihertz = 0,
+ TimingOverride timingOverride = TimingOverride.Current,
+ bool isInterlaced = false,
+ bool isClonePrimary = false,
+ bool isClonePanAndScanTarget = false,
+ bool disableVirtualModeSupport = false,
+ bool isPreferredUnscaledTarget = false)
+ {
+ if (timingOverride == TimingOverride.Custom)
+ {
+ throw new NVIDIANotSupportedException("Custom timing is not supported yet.");
+ }
+
+ this = typeof(PathAdvancedTargetInfo).Instantiate();
+ _Rotation = rotation;
+ _Scaling = scale;
+ _RefreshRateInMillihertz = refreshRateInMillihertz;
+ _TimingOverride = timingOverride;
+ IsInterlaced = isInterlaced;
+ IsClonePrimary = isClonePrimary;
+ IsClonePanAndScanTarget = isClonePanAndScanTarget;
+ DisableVirtualModeSupport = disableVirtualModeSupport;
+ IsPreferredUnscaledTarget = isPreferredUnscaledTarget;
+ }
+
+ ///
+ /// Creates a new PathAdvancedTargetInfo for TVs
+ ///
+ /// Screen rotation
+ /// Screen scaling
+ /// The TV format to apply
+ /// Specify connector type. For TV only
+ /// Screen refresh rate
+ /// Timing override
+ /// Indicates if the mode is interlaced
+ /// Indicates if the display is the primary display of a clone topology
+ /// Indicates if the target Pan and Scan is enabled
+ ///
+ ///
+ ///
+ public PathAdvancedTargetInfo(
+ Rotate rotation,
+ Scaling scale,
+ TVFormat tvFormat,
+ ConnectorType connectorType,
+ uint refreshRateInMillihertz = 0,
+ TimingOverride timingOverride = TimingOverride.Current,
+ bool isInterlaced = false,
+ bool isClonePrimary = false,
+ bool isClonePanAndScanTarget = false,
+ bool disableVirtualModeSupport = false,
+ bool isPreferredUnscaledTarget = false)
+ : this(
+ rotation, scale, refreshRateInMillihertz, timingOverride, isInterlaced, isClonePrimary,
+ isClonePanAndScanTarget,
+ disableVirtualModeSupport, isPreferredUnscaledTarget)
+ {
+ if (tvFormat == TVFormat.None)
+ {
+ throw new NVIDIANotSupportedException(
+ "This overload is for TV displays, use the other overload(s) if the display is not a TV.");
+ }
+
+ this = typeof(PathAdvancedTargetInfo).Instantiate();
+ _TVFormat = tvFormat;
+ _ConnectorType = connectorType;
+ }
+
+ ///
+ public bool Equals(PathAdvancedTargetInfo other)
+ {
+ return _Rotation == other._Rotation &&
+ _Scaling == other._Scaling &&
+ _RefreshRateInMillihertz == other._RefreshRateInMillihertz &&
+ (TVFormat == TVFormat.None || _ConnectorType == other._ConnectorType) &&
+ _TVFormat == other._TVFormat &&
+ _TimingOverride == other._TimingOverride &&
+ _Timing.Equals(other._Timing) &&
+ _RawReserved == other._RawReserved;
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is PathAdvancedTargetInfo info && Equals(info);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = (int) _Rotation;
+ hashCode = (hashCode * 397) ^ (int) _Scaling;
+ hashCode = (hashCode * 397) ^ (int) _RefreshRateInMillihertz;
+ // ReSharper disable once NonReadonlyMemberInGetHashCode
+ hashCode = (hashCode * 397) ^ (int) _RawReserved;
+ hashCode = (hashCode * 397) ^ (int) _ConnectorType;
+ hashCode = (hashCode * 397) ^ (int) _TVFormat;
+ hashCode = (hashCode * 397) ^ (int) _TimingOverride;
+ hashCode = (hashCode * 397) ^ _Timing.GetHashCode();
+
+ return hashCode;
+ }
+ }
+
+ ///
+ /// Rotation setting
+ ///
+ public Rotate Rotation
+ {
+ get => _Rotation;
+ }
+
+ ///
+ /// Scaling setting
+ ///
+ public Scaling Scaling
+ {
+ get => _Scaling;
+ }
+
+ ///
+ /// Non-interlaced Refresh Rate of the mode, multiplied by 1000, 0 = ignored
+ /// This is the value which driver reports to the OS.
+ ///
+ public uint RefreshRateInMillihertz
+ {
+ get => _RefreshRateInMillihertz;
+ }
+
+ ///
+ /// Specify connector type. For TV only, ignored if TVFormat == TVFormat.None.
+ ///
+ public ConnectorType ConnectorType
+ {
+ get => _ConnectorType;
+ }
+
+ ///
+ /// To choose the last TV format set this value to TVFormat.None
+ /// In case of NvAPI_DISP_GetDisplayConfig(), this field will indicate the currently applied TV format;
+ /// if no TV format is applied, this field will have TVFormat.None value.
+ /// In case of NvAPI_DISP_SetDisplayConfig(), this field should only be set in case of TVs;
+ /// for other displays this field will be ignored and resolution & refresh rate specified in input will be used to
+ /// apply the TV format.
+ ///
+ public TVFormat TVFormat
+ {
+ get => _TVFormat;
+ }
+
+ ///
+ /// Ignored if TimingOverride == TimingOverride.Current
+ ///
+ public TimingOverride TimingOverride
+ {
+ get => _TimingOverride;
+ }
+
+ ///
+ /// Scan out timing, valid only if TimingOverride == TimingOverride.Custom
+ /// The value Timing.PixelClockIn10KHertz is obtained from the EDID. The driver may tweak this value for HDTV, stereo,
+ /// etc., before reporting it to the OS.
+ ///
+ public Timing Timing
+ {
+ get => _Timing;
+ }
+
+ ///
+ /// Interlaced mode flag, ignored if refreshRate == 0
+ ///
+ public bool IsInterlaced
+ {
+ get => _RawReserved.GetBit(0);
+ private set => _RawReserved = _RawReserved.SetBit(0, value);
+ }
+
+ ///
+ /// Declares primary display in clone configuration. This is *NOT* GDI Primary.
+ /// Only one target can be primary per source. If no primary is specified, the first target will automatically be
+ /// primary.
+ ///
+ public bool IsClonePrimary
+ {
+ get => _RawReserved.GetBit(1);
+ private set => _RawReserved = _RawReserved.SetBit(1, value);
+ }
+
+ ///
+ /// Whether on this target Pan and Scan is enabled or has to be enabled. Valid only when the target is part of clone
+ /// topology.
+ ///
+ public bool IsClonePanAndScanTarget
+ {
+ get => _RawReserved.GetBit(2);
+ private set => _RawReserved = _RawReserved.SetBit(2, value);
+ }
+
+ ///
+ /// Indicates if virtual mode support is disabled
+ ///
+ public bool DisableVirtualModeSupport
+ {
+ get => _RawReserved.GetBit(3);
+ private set => _RawReserved = _RawReserved.SetBit(3, value);
+ }
+
+ ///
+ /// Indicates if the target is in preferred unscaled mode
+ ///
+ public bool IsPreferredUnscaledTarget
+ {
+ get => _RawReserved.GetBit(4);
+ private set => _RawReserved = _RawReserved.SetBit(4, value);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/PathInfoV1.cs b/NvAPIWrapper/Native/Display/Structures/PathInfoV1.cs
new file mode 100644
index 0000000..ec49742
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/PathInfoV1.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Helpers.Structures;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds information about a path
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ // ReSharper disable once RedundantExtendsListEntry
+ public struct PathInfoV1 : IPathInfo, IInitializable, IAllocatable, IEquatable
+ {
+ internal StructureVersion _Version;
+ internal readonly uint _ReservedSourceId;
+ internal readonly uint _TargetInfoCount;
+ internal ValueTypeArray _TargetsInfo;
+ internal ValueTypeReference _SourceModeInfo;
+
+ ///
+ public uint SourceId
+ {
+ get => _ReservedSourceId;
+ }
+
+ ///
+ public IEnumerable TargetsInfo
+ {
+ get => _TargetsInfo.ToArray((int) _TargetInfoCount)?.Cast() ?? new IPathTargetInfo[0];
+ }
+
+ ///
+ public SourceModeInfo SourceModeInfo
+ {
+ get => _SourceModeInfo.ToValueType() ?? default(SourceModeInfo);
+ }
+
+ ///
+ /// Creates a new PathInfoV1
+ ///
+ /// Information about path targets
+ /// Source mode information
+ /// Source Id, can be zero
+ public PathInfoV1(
+ PathTargetInfoV1[] targetsInformation,
+ SourceModeInfo sourceModeInformation,
+ uint sourceId = 0)
+ {
+ this = typeof(PathInfoV1).Instantiate();
+ _TargetInfoCount = (uint) targetsInformation.Length;
+ _TargetsInfo = ValueTypeArray.FromArray(targetsInformation);
+ _SourceModeInfo = ValueTypeReference.FromValueType(sourceModeInformation);
+ _ReservedSourceId = sourceId;
+ }
+
+ ///
+ public bool Equals(PathInfoV1 other)
+ {
+ return _TargetInfoCount == other._TargetInfoCount &&
+ _TargetsInfo.Equals(other._TargetsInfo) &&
+ _SourceModeInfo.Equals(other._SourceModeInfo);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is PathInfoV1 && Equals((PathInfoV1) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = (int) _TargetInfoCount;
+ // ReSharper disable once NonReadonlyMemberInGetHashCode
+ hashCode = (hashCode * 397) ^ _TargetsInfo.GetHashCode();
+ // ReSharper disable once NonReadonlyMemberInGetHashCode
+ hashCode = (hashCode * 397) ^ _SourceModeInfo.GetHashCode();
+
+ return hashCode;
+ }
+ }
+
+ ///
+ /// Creates a new PathInfoV1
+ ///
+ /// Information about path targets
+ /// Source Id, can be zero
+ public PathInfoV1(PathTargetInfoV1[] targetsInformation, uint sourceId = 0)
+ {
+ this = typeof(PathInfoV1).Instantiate();
+ _TargetInfoCount = (uint) targetsInformation.Length;
+ _TargetsInfo = ValueTypeArray.FromArray(targetsInformation);
+ _SourceModeInfo = ValueTypeReference.Null;
+ _ReservedSourceId = sourceId;
+ }
+
+ ///
+ /// Creates a new PathInfoV1
+ ///
+ /// Source Id, can be zero
+ public PathInfoV1(uint sourceId)
+ {
+ this = typeof(PathInfoV1).Instantiate();
+ _TargetInfoCount = 0;
+ _TargetsInfo = ValueTypeArray.Null;
+ _SourceModeInfo = ValueTypeReference.Null;
+ _ReservedSourceId = sourceId;
+ }
+
+ ///
+ /// Creates a new PathInfoV1
+ ///
+ /// Source mode information
+ /// Source Id, can be zero
+ public PathInfoV1(SourceModeInfo sourceModeInfo, uint sourceId)
+ {
+ this = typeof(PathInfoV1).Instantiate();
+ _TargetInfoCount = 0;
+ _TargetsInfo = ValueTypeArray.Null;
+ _SourceModeInfo = ValueTypeReference.FromValueType(sourceModeInfo);
+ _ReservedSourceId = sourceId;
+ }
+
+ ///
+ public void Dispose()
+ {
+ TargetsInfo.DisposeAll();
+ _TargetsInfo.Dispose();
+ _SourceModeInfo.Dispose();
+ }
+
+ void IAllocatable.Allocate()
+ {
+ if (_TargetInfoCount > 0 && _TargetsInfo.IsNull)
+ {
+ var targetInfo = typeof(PathTargetInfoV1).Instantiate();
+ var targetInfoList = targetInfo.Repeat((int) _TargetInfoCount).AllocateAll();
+ _TargetsInfo = ValueTypeArray.FromArray(targetInfoList.ToArray());
+ }
+
+ if (_SourceModeInfo.IsNull)
+ {
+ var sourceModeInfo = typeof(SourceModeInfo).Instantiate();
+ _SourceModeInfo = ValueTypeReference.FromValueType(sourceModeInfo);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/PathInfoV2.cs b/NvAPIWrapper/Native/Display/Structures/PathInfoV2.cs
new file mode 100644
index 0000000..ed721fe
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/PathInfoV2.cs
@@ -0,0 +1,181 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Helpers.Structures;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds information about a path
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(2)]
+ // ReSharper disable once RedundantExtendsListEntry
+ public struct PathInfoV2 : IPathInfo, IInitializable, IAllocatable, IEquatable
+ {
+ internal StructureVersion _Version;
+ internal readonly uint _SourceId;
+ internal readonly uint _TargetInfoCount;
+ internal ValueTypeArray _TargetsInfo;
+ internal ValueTypeReference _SourceModeInfo;
+ internal readonly uint _RawReserved;
+ internal ValueTypeReference _OSAdapterLUID;
+
+ ///
+ public uint SourceId
+ {
+ get => _SourceId;
+ }
+
+ ///
+ public bool Equals(PathInfoV2 other)
+ {
+ return _TargetInfoCount == other._TargetInfoCount &&
+ _TargetsInfo.Equals(other._TargetsInfo) &&
+ _SourceModeInfo.Equals(other._SourceModeInfo) &&
+ _RawReserved == other._RawReserved;
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is PathInfoV2 v2 && Equals(v2);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = (int) _TargetInfoCount;
+ // ReSharper disable once NonReadonlyMemberInGetHashCode
+ hashCode = (hashCode * 397) ^ _TargetsInfo.GetHashCode();
+ // ReSharper disable once NonReadonlyMemberInGetHashCode
+ hashCode = (hashCode * 397) ^ _SourceModeInfo.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) _RawReserved;
+
+ return hashCode;
+ }
+ }
+
+ ///
+ public IEnumerable TargetsInfo
+ {
+ get => _TargetsInfo.ToArray((int) _TargetInfoCount)?.Cast() ?? new IPathTargetInfo[0];
+ }
+
+ ///
+ public SourceModeInfo SourceModeInfo
+ {
+ get => _SourceModeInfo.ToValueType() ?? default(SourceModeInfo);
+ }
+
+ ///
+ /// True for non-NVIDIA adapter.
+ ///
+ public bool IsNonNVIDIAAdapter
+ {
+ get => _RawReserved.GetBit(0);
+ }
+
+ ///
+ /// Used by Non-NVIDIA adapter for OS Adapter of LUID
+ ///
+ public LUID? OSAdapterLUID
+ {
+ get => _OSAdapterLUID.ToValueType();
+ }
+
+ ///
+ /// Creates a new PathInfoV2
+ ///
+ /// Information about path targets
+ /// Source mode information
+ /// Source Id, can be zero
+ public PathInfoV2(PathTargetInfoV2[] targetInformations, SourceModeInfo sourceModeInfo, uint sourceId = 0)
+ {
+ this = typeof(PathInfoV2).Instantiate();
+ _TargetInfoCount = (uint) targetInformations.Length;
+ _TargetsInfo = ValueTypeArray.FromArray(targetInformations);
+ _SourceModeInfo = ValueTypeReference.FromValueType(sourceModeInfo);
+ _SourceId = sourceId;
+ }
+
+ ///
+ /// Creates a new PathInfoV2
+ ///
+ /// Information about path targets
+ /// Source Id, can be zero
+ public PathInfoV2(PathTargetInfoV2[] targetInformations, uint sourceId = 0)
+ {
+ this = typeof(PathInfoV2).Instantiate();
+ _TargetInfoCount = (uint) targetInformations.Length;
+ _TargetsInfo = ValueTypeArray.FromArray(targetInformations);
+ _SourceModeInfo = ValueTypeReference.Null;
+ _SourceId = sourceId;
+ }
+
+
+ ///
+ /// Creates a new PathInfoV2
+ ///
+ /// Source Id, can be zero
+ public PathInfoV2(uint sourceId)
+ {
+ this = typeof(PathInfoV2).Instantiate();
+ _TargetInfoCount = 0;
+ _TargetsInfo = ValueTypeArray.Null;
+ _SourceModeInfo = ValueTypeReference.Null;
+ _SourceId = sourceId;
+ }
+
+ ///
+ /// Creates a new PathInfoV2
+ ///
+ /// Source mode information
+ /// Source Id, can be zero
+ public PathInfoV2(SourceModeInfo sourceModeInfo, uint sourceId)
+ {
+ this = typeof(PathInfoV2).Instantiate();
+ _TargetInfoCount = 0;
+ _TargetsInfo = ValueTypeArray.Null;
+ _SourceModeInfo = ValueTypeReference.FromValueType(sourceModeInfo);
+ _SourceId = sourceId;
+ }
+
+ ///
+ public void Dispose()
+ {
+ TargetsInfo.DisposeAll();
+ _TargetsInfo.Dispose();
+ _SourceModeInfo.Dispose();
+ }
+
+ void IAllocatable.Allocate()
+ {
+ if (_TargetInfoCount > 0 && _TargetsInfo.IsNull)
+ {
+ var targetInfo = typeof(PathTargetInfoV2).Instantiate();
+ var targetInfoList = targetInfo.Repeat((int) _TargetInfoCount).AllocateAll();
+ _TargetsInfo = ValueTypeArray.FromArray(targetInfoList.ToArray());
+ }
+
+ if (_SourceModeInfo.IsNull)
+ {
+ var sourceModeInfo = typeof(SourceModeInfo).Instantiate();
+ _SourceModeInfo = ValueTypeReference.FromValueType(sourceModeInfo);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/PathTargetInfoV1.cs b/NvAPIWrapper/Native/Display/Structures/PathTargetInfoV1.cs
new file mode 100644
index 0000000..4bdaddb
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/PathTargetInfoV1.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Helpers.Structures;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+// ReSharper disable RedundantExtendsListEntry
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds information about a path's target
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct PathTargetInfoV1 : IPathTargetInfo,
+ IInitializable,
+ IDisposable,
+ IAllocatable,
+ IEquatable,
+ IEquatable
+ {
+ internal readonly uint _DisplayId;
+ internal ValueTypeReference _Details;
+
+ ///
+ public override string ToString()
+ {
+ return $"PathTargetInfoV2: Display #{_DisplayId}";
+ }
+
+ ///
+ public uint DisplayId
+ {
+ get => _DisplayId;
+ }
+
+ ///
+ public bool Equals(PathTargetInfoV1 other)
+ {
+ return _DisplayId == other._DisplayId && _Details.Equals(other._Details);
+ }
+
+ ///
+ public bool Equals(PathTargetInfoV2 other)
+ {
+ return _DisplayId == other._DisplayId && _Details.Equals(other._Details);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is PathTargetInfoV1 && Equals((PathTargetInfoV1) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ // ReSharper disable once NonReadonlyMemberInGetHashCode
+ return ((int) _DisplayId * 397) ^ _Details.GetHashCode();
+ }
+ }
+
+ ///
+ public PathAdvancedTargetInfo? Details
+ {
+ get => _Details.ToValueType() ?? default(PathAdvancedTargetInfo);
+ }
+
+ ///
+ /// Creates a new PathTargetInfoV1
+ ///
+ /// Display Id
+ public PathTargetInfoV1(uint displayId) : this()
+ {
+ _DisplayId = displayId;
+ }
+
+ ///
+ /// Creates a new PathTargetInfoV1
+ ///
+ /// Display Id
+ /// Extra information
+ public PathTargetInfoV1(uint displayId, PathAdvancedTargetInfo details) : this(displayId)
+ {
+ _Details = ValueTypeReference.FromValueType(details);
+ }
+
+ ///
+ public void Dispose()
+ {
+ _Details.Dispose();
+ }
+
+ void IAllocatable.Allocate()
+ {
+ if (_Details.IsNull)
+ {
+ var detail = typeof(PathAdvancedTargetInfo).Instantiate();
+ _Details = ValueTypeReference.FromValueType(detail);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/PathTargetInfoV2.cs b/NvAPIWrapper/Native/Display/Structures/PathTargetInfoV2.cs
new file mode 100644
index 0000000..00c21ac
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/PathTargetInfoV2.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Helpers.Structures;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+// ReSharper disable RedundantExtendsListEntry
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds information about a path's target
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct PathTargetInfoV2 : IPathTargetInfo,
+ IInitializable,
+ IDisposable,
+ IAllocatable,
+ IEquatable,
+ IEquatable
+ {
+ internal readonly uint _DisplayId;
+ internal ValueTypeReference _Details;
+ internal readonly uint _WindowsCCDTargetId;
+
+ ///
+ public uint DisplayId
+ {
+ get => _DisplayId;
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"PathTargetInfoV2: Display #{_DisplayId}";
+ }
+
+ ///
+ public PathAdvancedTargetInfo? Details
+ {
+ get => _Details.ToValueType();
+ }
+
+ ///
+ /// Windows CCD target ID. Must be present only for non-NVIDIA adapter, for NVIDIA adapter this parameter is ignored.
+ ///
+ public uint WindowsCCDTargetId
+ {
+ get => _WindowsCCDTargetId;
+ }
+
+ ///
+ /// Creates a new PathTargetInfoV1
+ ///
+ /// Display Id
+ public PathTargetInfoV2(uint displayId) : this()
+ {
+ _DisplayId = displayId;
+ }
+
+ ///
+ public bool Equals(PathTargetInfoV2 other)
+ {
+ return _DisplayId == other._DisplayId && _Details.Equals(other._Details);
+ }
+
+ ///
+ public bool Equals(PathTargetInfoV1 other)
+ {
+ return _DisplayId == other._DisplayId && _Details.Equals(other._Details);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is PathTargetInfoV2 v2 && Equals(v2);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = (int) _DisplayId;
+ // ReSharper disable once NonReadonlyMemberInGetHashCode
+ hashCode = (hashCode * 397) ^ _Details.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) _WindowsCCDTargetId;
+
+ return hashCode;
+ }
+ }
+
+ ///
+ /// Creates a new PathTargetInfoV1
+ ///
+ /// Display Id
+ /// Windows CCD target Id
+ public PathTargetInfoV2(uint displayId, uint windowsCCDTargetId) : this(displayId)
+ {
+ _WindowsCCDTargetId = windowsCCDTargetId;
+ }
+
+ ///
+ /// Creates a new PathTargetInfoV1
+ ///
+ /// Display Id
+ /// Extra information
+ public PathTargetInfoV2(uint displayId, PathAdvancedTargetInfo details) : this(displayId)
+ {
+ _Details = ValueTypeReference.FromValueType(details);
+ }
+
+ ///
+ /// Creates a new PathTargetInfoV1
+ ///
+ /// Display Id
+ /// Windows CCD target Id
+ /// Extra information
+ public PathTargetInfoV2(uint displayId, uint windowsCCDTargetId, PathAdvancedTargetInfo details)
+ : this(displayId, windowsCCDTargetId)
+ {
+ _Details = ValueTypeReference.FromValueType(details);
+ }
+
+
+ ///
+ public void Dispose()
+ {
+ _Details.Dispose();
+ }
+
+ void IAllocatable.Allocate()
+ {
+ if (_Details.IsNull)
+ {
+ var detail = typeof(PathAdvancedTargetInfo).Instantiate();
+ _Details = ValueTypeReference.FromValueType(detail);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/Position.cs b/NvAPIWrapper/Native/Display/Structures/Position.cs
new file mode 100644
index 0000000..1d36732
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/Position.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds a [X,Y] pair as a position on a 2D plane
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct Position : IEquatable
+ {
+ internal readonly int _X;
+ internal readonly int _Y;
+
+ ///
+ public override string ToString()
+ {
+ return $"[{X}, {Y}]";
+ }
+
+ ///
+ public bool Equals(Position other)
+ {
+ return _X == other._X && _Y == other._Y;
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is Position position && Equals(position);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (_X * 397) ^ _Y;
+ }
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(Position left, Position right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(Position left, Position right)
+ {
+ return !left.Equals(right);
+ }
+
+ ///
+ /// Creates a new Position
+ ///
+ /// X value
+ /// Y value
+ public Position(int x, int y)
+ {
+ _X = x;
+ _Y = y;
+ }
+
+ ///
+ /// X value
+ ///
+ public int X
+ {
+ get => _X;
+ }
+
+ ///
+ /// Y value
+ ///
+ public int Y
+ {
+ get => _Y;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/PrivateDisplayDVCInfo.cs b/NvAPIWrapper/Native/Display/Structures/PrivateDisplayDVCInfo.cs
new file mode 100644
index 0000000..69efc13
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/PrivateDisplayDVCInfo.cs
@@ -0,0 +1,43 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct PrivateDisplayDVCInfo : IInitializable, IDisplayDVCInfo
+ {
+ internal StructureVersion _Version;
+ internal int _CurrentLevel;
+ internal int _MinimumLevel;
+ internal int _MaximumLevel;
+
+ ///
+ public int CurrentLevel
+ {
+ get => _CurrentLevel;
+ }
+
+ ///
+ public int MinimumLevel
+ {
+ get => _MinimumLevel;
+ }
+
+ ///
+ int IDisplayDVCInfo.DefaultLevel
+ {
+ get => 0;
+ }
+
+ ///
+ public int MaximumLevel
+ {
+ get => _MaximumLevel;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/PrivateDisplayDVCInfoEx.cs b/NvAPIWrapper/Native/Display/Structures/PrivateDisplayDVCInfoEx.cs
new file mode 100644
index 0000000..cb37c2e
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/PrivateDisplayDVCInfoEx.cs
@@ -0,0 +1,51 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+using NvAPIWrapper.Native.Interfaces.Display;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct PrivateDisplayDVCInfoEx : IInitializable, IDisplayDVCInfo
+ {
+ internal StructureVersion _Version;
+ internal int _CurrentLevel;
+ internal int _MinimumLevel;
+ internal int _MaximumLevel;
+ internal int _DefaultLevel;
+
+ ///
+ public int CurrentLevel
+ {
+ get => _CurrentLevel;
+ }
+
+ ///
+ public int MinimumLevel
+ {
+ get => _MinimumLevel;
+ }
+
+ ///
+ public int MaximumLevel
+ {
+ get => _MaximumLevel;
+ }
+
+ ///
+ public int DefaultLevel
+ {
+ get => _DefaultLevel;
+ }
+
+ internal PrivateDisplayDVCInfoEx(int currentLevel)
+ {
+ this = typeof(PrivateDisplayDVCInfoEx).Instantiate();
+ _CurrentLevel = currentLevel;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/PrivateDisplayHUEInfo.cs b/NvAPIWrapper/Native/Display/Structures/PrivateDisplayHUEInfo.cs
new file mode 100644
index 0000000..38e2d10
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/PrivateDisplayHUEInfo.cs
@@ -0,0 +1,35 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds the current and the default HUE information
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct PrivateDisplayHUEInfo : IInitializable
+ {
+ internal StructureVersion _Version;
+ internal int _CurrentAngle;
+ internal int _DefaultAngle;
+
+ ///
+ /// Gets or sets the current HUE offset angle [0-359]
+ ///
+ public int CurrentAngle
+ {
+ get => _CurrentAngle;
+ }
+
+ ///
+ /// Gets or sets the default HUE offset angle [0-359]
+ ///
+ public int DefaultAngle
+ {
+ get => _DefaultAngle;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/Resolution.cs b/NvAPIWrapper/Native/Display/Structures/Resolution.cs
new file mode 100644
index 0000000..ad34a57
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/Resolution.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds a [Width, Height] pair as the resolution of a display device, as well as a color format
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct Resolution : IEquatable
+ {
+ internal readonly uint _Width;
+ internal readonly uint _Height;
+ internal readonly uint _ColorDepth;
+
+ ///
+ /// Creates a new Resolution
+ ///
+ /// Display resolution width
+ /// Display resolution height
+ /// Display color depth
+ public Resolution(int width, int height, int colorDepth)
+ {
+ _Width = (uint) width;
+ _Height = (uint) height;
+ _ColorDepth = (uint) colorDepth;
+ }
+
+ ///
+ public bool Equals(Resolution other)
+ {
+ return _Width == other._Width && _Height == other._Height && _ColorDepth == other._ColorDepth;
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is Resolution resolution && Equals(resolution);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = (int) _Width;
+ hashCode = (hashCode * 397) ^ (int) _Height;
+ hashCode = (hashCode * 397) ^ (int) _ColorDepth;
+
+ return hashCode;
+ }
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(Resolution left, Resolution right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(Resolution left, Resolution right)
+ {
+ return !left.Equals(right);
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"({Width}, {Height}) @ {ColorDepth}bpp";
+ }
+
+ ///
+ /// Display resolution width
+ ///
+ public int Width
+ {
+ get => (int) _Width;
+ }
+
+ ///
+ /// Display resolution height
+ ///
+ public int Height
+ {
+ get => (int) _Height;
+ }
+
+ ///
+ /// Display color depth
+ ///
+ public int ColorDepth
+ {
+ get => (int) _ColorDepth;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ScanOutInformationV1.cs b/NvAPIWrapper/Native/Display/Structures/ScanOutInformationV1.cs
new file mode 100644
index 0000000..a4a6854
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ScanOutInformationV1.cs
@@ -0,0 +1,82 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains information regarding the scan-out configurations
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct ScanOutInformationV1 : IInitializable
+ {
+ internal StructureVersion _Version;
+ internal Rectangle _SourceDesktopRectangle;
+ internal Rectangle _SourceViewPortRectangle;
+ internal Rectangle _TargetViewPortRectangle;
+ internal uint _TargetDisplayWidth;
+ internal uint _TargetDisplayHeight;
+ internal uint _CloneImportance;
+ internal Rotate _SourceToTargetRotation;
+
+ ///
+ /// Gets the operating system display device rectangle in desktop coordinates displayId is scanning out from.
+ ///
+ public Rectangle SourceDesktopRectangle
+ {
+ get => _SourceDesktopRectangle;
+ }
+
+ ///
+ /// Gets the area inside the SourceDesktopRectangle which is scanned out to the display.
+ ///
+ public Rectangle SourceViewPortRectangle
+ {
+ get => _SourceViewPortRectangle;
+ }
+
+ ///
+ /// Gets the area inside the rectangle described by targetDisplayWidth/Height SourceViewPortRectangle is scanned out
+ /// to.
+ ///
+ public Rectangle TargetViewPortRectangle
+ {
+ get => _TargetViewPortRectangle;
+ }
+
+ ///
+ /// Gets the horizontal size of the active resolution scanned out to the display.
+ ///
+ public uint TargetDisplayWidth
+ {
+ get => _TargetDisplayWidth;
+ }
+
+ ///
+ /// Gets the vertical size of the active resolution scanned out to the display.
+ ///
+ public uint TargetDisplayHeight
+ {
+ get => _TargetDisplayHeight;
+ }
+
+ ///
+ /// Gets the clone importance assigned to the target if the target is a cloned view of the SourceDesktopRectangle
+ /// (0:primary,1 secondary,...).
+ ///
+ public uint CloneImportance
+ {
+ get => _CloneImportance;
+ }
+
+ ///
+ /// Gets the rotation performed between the SourceViewPortRectangle and the TargetViewPortRectangle.
+ ///
+ public Rotate SourceToTargetRotation
+ {
+ get => _SourceToTargetRotation;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ScanOutIntensityStateV1.cs b/NvAPIWrapper/Native/Display/Structures/ScanOutIntensityStateV1.cs
new file mode 100644
index 0000000..bb5ef73
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ScanOutIntensityStateV1.cs
@@ -0,0 +1,26 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains information regarding the scan-out intensity state
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct ScanOutIntensityStateV1 : IInitializable
+ {
+ internal StructureVersion _Version;
+ internal uint _IsEnabled;
+
+ ///
+ /// Gets a boolean value indicating if the scan out intensity is enabled or not
+ ///
+ public bool IsEnabled
+ {
+ get => _IsEnabled > 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ScanOutIntensityV1.cs b/NvAPIWrapper/Native/Display/Structures/ScanOutIntensityV1.cs
new file mode 100644
index 0000000..cba0093
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ScanOutIntensityV1.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct ScanOutIntensityV1 : IDisposable, IInitializable, IScanOutIntensity
+ {
+ internal StructureVersion _Version;
+ internal uint _Width;
+ internal uint _Height;
+ internal IntPtr _BlendingTexture;
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The width of the input texture.
+ /// The height of the input texture
+ /// The array of floating values building an intensity RGB texture.
+ public ScanOutIntensityV1(uint width, uint height, float[] blendingTexture)
+ {
+ if (blendingTexture?.Length != width * height * 3)
+ {
+ throw new ArgumentOutOfRangeException(nameof(blendingTexture));
+ }
+
+ this = typeof(ScanOutIntensityV1).Instantiate();
+ _Width = width;
+ _Height = height;
+ _BlendingTexture = Marshal.AllocHGlobal((int) (width * height * 3 * sizeof(float)));
+
+ Marshal.Copy(blendingTexture, 0, _BlendingTexture, blendingTexture.Length);
+ }
+
+ ///
+ public uint Width
+ {
+ get => _Width;
+ }
+
+ ///
+ public uint Height
+ {
+ get => _Height;
+ }
+
+ ///
+ public float[] BlendingTexture
+ {
+ get
+ {
+ var floats = new float[_Width * _Height * 3];
+ Marshal.Copy(_BlendingTexture, floats, 0, floats.Length);
+
+ return floats;
+ }
+ }
+
+ ///
+ public void Dispose()
+ {
+ Marshal.FreeHGlobal(_BlendingTexture);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ScanOutIntensityV2.cs b/NvAPIWrapper/Native/Display/Structures/ScanOutIntensityV2.cs
new file mode 100644
index 0000000..1bc8ffd
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ScanOutIntensityV2.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(2)]
+ public struct ScanOutIntensityV2 : IDisposable, IInitializable, IScanOutIntensity
+ {
+ internal StructureVersion _Version;
+ internal uint _Width;
+ internal uint _Height;
+ internal IntPtr _BlendingTexture;
+ internal IntPtr _OffsetTexture;
+ internal uint _OffsetTextureChannels;
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The width of the input texture.
+ /// The height of the input texture
+ /// The array of floating values building an intensity RGB texture
+ /// The number of channels per pixel in the offset texture
+ /// The array of floating values building an offset texture
+ // ReSharper disable once TooManyDependencies
+ public ScanOutIntensityV2(
+ uint width,
+ uint height,
+ float[] blendingTexture,
+ uint offsetTextureChannels,
+ float[] offsetTexture)
+ {
+ if (blendingTexture?.Length != width * height * 3)
+ {
+ throw new ArgumentOutOfRangeException(nameof(blendingTexture));
+ }
+
+ if (offsetTexture?.Length != width * height * offsetTextureChannels)
+ {
+ throw new ArgumentOutOfRangeException(nameof(offsetTexture));
+ }
+
+ this = typeof(ScanOutIntensityV2).Instantiate();
+ _Width = width;
+ _Height = height;
+ _BlendingTexture = Marshal.AllocHGlobal((int) (width * height * 3 * sizeof(float)));
+ Marshal.Copy(blendingTexture, 0, _BlendingTexture, blendingTexture.Length);
+
+ _OffsetTextureChannels = offsetTextureChannels;
+ _OffsetTexture = Marshal.AllocHGlobal((int) (width * height * offsetTextureChannels * sizeof(float)));
+ Marshal.Copy(offsetTexture, 0, _OffsetTexture, offsetTexture.Length);
+ }
+
+ ///
+ public uint Width
+ {
+ get => _Width;
+ }
+
+ ///
+ public uint Height
+ {
+ get => _Height;
+ }
+
+ ///
+ /// Gets the number of channels per pixel in the offset texture
+ ///
+ public uint OffsetTextureChannels
+ {
+ get => _OffsetTextureChannels;
+ }
+
+ ///
+ public float[] BlendingTexture
+ {
+ get
+ {
+ var floats = new float[_Width * _Height * 3];
+ Marshal.Copy(_BlendingTexture, floats, 0, floats.Length);
+
+ return floats;
+ }
+ }
+
+ ///
+ /// Gets the array of floating values building an offset texture
+ ///
+ public float[] OffsetTexture
+ {
+ get
+ {
+ var floats = new float[_Width * _Height * _OffsetTextureChannels];
+ Marshal.Copy(_OffsetTexture, floats, 0, floats.Length);
+
+ return floats;
+ }
+ }
+
+ ///
+ public void Dispose()
+ {
+ Marshal.FreeHGlobal(_BlendingTexture);
+ Marshal.FreeHGlobal(_OffsetTexture);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ScanOutWarpingStateV1.cs b/NvAPIWrapper/Native/Display/Structures/ScanOutWarpingStateV1.cs
new file mode 100644
index 0000000..a09fa23
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ScanOutWarpingStateV1.cs
@@ -0,0 +1,26 @@
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains information regarding the scan-out warping state
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct ScanOutWarpingStateV1 : IInitializable
+ {
+ internal StructureVersion _Version;
+ internal uint _IsEnabled;
+
+ ///
+ /// Gets a boolean value indicating if the scan out warping is enabled or not
+ ///
+ public bool IsEnabled
+ {
+ get => _IsEnabled > 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ScanOutWarpingV1.cs b/NvAPIWrapper/Native/Display/Structures/ScanOutWarpingV1.cs
new file mode 100644
index 0000000..66d0392
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ScanOutWarpingV1.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains information regarding the scan-out warping data
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct ScanOutWarpingV1 : IDisposable, IInitializable
+ {
+ internal StructureVersion _Version;
+ internal IntPtr _Vertices;
+ internal WarpingVerticeFormat _VertexFormat;
+ internal uint _NumberOfVertices;
+ internal IntPtr _TextureRectangle;
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The format of the input vertices.
+ /// The array of floating values containing the warping vertices.
+ /// The rectangle in desktop coordinates describing the source area for the warping.
+ public ScanOutWarpingV1(WarpingVerticeFormat vertexFormat, float[] vertices, Rectangle textureRectangle)
+ {
+ if (vertices.Length % 6 != 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(vertices));
+ }
+
+ this = typeof(ScanOutWarpingV1).Instantiate();
+ _VertexFormat = vertexFormat;
+ _NumberOfVertices = (uint) (vertices.Length / 6);
+ _Vertices = Marshal.AllocHGlobal(vertices.Length * sizeof(float));
+ Marshal.Copy(vertices, 0, _Vertices, vertices.Length);
+
+ _TextureRectangle = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Rectangle)));
+ Marshal.StructureToPtr(textureRectangle, _TextureRectangle, true);
+ }
+
+ ///
+ /// Gets the format of the input vertices
+ ///
+ public WarpingVerticeFormat VertexFormat
+ {
+ get => _VertexFormat;
+ }
+
+ ///
+ /// Gets the rectangle in desktop coordinates describing the source area for the warping
+ ///
+ public Rectangle TextureRectangle
+ {
+ get => (Rectangle)Marshal.PtrToStructure(_TextureRectangle, typeof(Rectangle));
+ }
+
+ ///
+ /// Gets the array of floating values containing the warping vertices
+ ///
+ public float[] Vertices
+ {
+ get
+ {
+ var floats = new float[_NumberOfVertices * 6];
+ Marshal.Copy(_Vertices, floats, 0, floats.Length);
+
+ return floats;
+ }
+ }
+
+ ///
+ public void Dispose()
+ {
+ Marshal.FreeHGlobal(_Vertices);
+ Marshal.FreeHGlobal(_TextureRectangle);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/SourceModeInfo.cs b/NvAPIWrapper/Native/Display/Structures/SourceModeInfo.cs
new file mode 100644
index 0000000..132777b
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/SourceModeInfo.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Helpers;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds information about a source mode
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct SourceModeInfo : IEquatable
+ {
+ internal readonly Resolution _Resolution;
+ internal readonly ColorFormat _ColorFormat;
+ internal readonly Position _Position;
+ internal readonly SpanningOrientation _SpanningOrientation;
+ internal uint _RawReserved;
+
+ ///
+ /// Creates a new SourceModeInfo
+ ///
+ /// Source resolution
+ /// Must be Format.Unknown
+ /// Source position
+ /// Spanning orientation for XP
+ /// true if this source represents the GDI primary display, otherwise false
+ /// true if this source represents the SLI focus display, otherwise false
+ public SourceModeInfo(
+ Resolution resolution,
+ ColorFormat colorFormat,
+ Position position = default(Position),
+ SpanningOrientation spanningOrientation = SpanningOrientation.None,
+ bool isGDIPrimary = false,
+ bool isSLIFocus = false) : this()
+ {
+ _Resolution = resolution;
+ _ColorFormat = colorFormat;
+ _Position = position;
+ _SpanningOrientation = spanningOrientation;
+ IsGDIPrimary = isGDIPrimary;
+ IsSLIFocus = isSLIFocus;
+ }
+
+ ///
+ public bool Equals(SourceModeInfo other)
+ {
+ return _Resolution.Equals(other._Resolution) &&
+ _ColorFormat == other._ColorFormat &&
+ _Position.Equals(other._Position) &&
+ _SpanningOrientation == other._SpanningOrientation &&
+ _RawReserved == other._RawReserved;
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ return obj is SourceModeInfo info && Equals(info);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = _Resolution.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) _ColorFormat;
+ hashCode = (hashCode * 397) ^ _Position.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) _SpanningOrientation;
+ // ReSharper disable once NonReadonlyMemberInGetHashCode
+ hashCode = (hashCode * 397) ^ (int) _RawReserved;
+
+ return hashCode;
+ }
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"{Resolution} @ {Position} - {ColorFormat}";
+ }
+
+ ///
+ /// Holds the source resolution
+ ///
+ public Resolution Resolution
+ {
+ get => _Resolution;
+ }
+
+ ///
+ /// Ignored at present, must be Format.Unknown
+ ///
+ public ColorFormat ColorFormat
+ {
+ get => _ColorFormat;
+ }
+
+ ///
+ /// Is all positions are 0 or invalid, displays will be automatically positioned from left to right with GDI Primary at
+ /// 0,0, and all other displays in the order of the path array.
+ ///
+ public Position Position
+ {
+ get => _Position;
+ }
+
+ ///
+ /// Spanning is only supported on XP
+ ///
+ public SpanningOrientation SpanningOrientation
+ {
+ get => _SpanningOrientation;
+ }
+
+ ///
+ /// Indicates if the path is for the primary GDI display
+ ///
+ public bool IsGDIPrimary
+ {
+ get => _RawReserved.GetBit(0);
+ private set => _RawReserved = _RawReserved.SetBit(0, value);
+ }
+
+ ///
+ /// Indicates if the path is for the SLI focus display
+ ///
+ public bool IsSLIFocus
+ {
+ get => _RawReserved.GetBit(1);
+ private set => _RawReserved = _RawReserved.SetBit(1, value);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/Timing.cs b/NvAPIWrapper/Native/Display/Structures/Timing.cs
new file mode 100644
index 0000000..e863f3d
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/Timing.cs
@@ -0,0 +1,382 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Helpers;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds VESA scan out timing parameters
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct Timing : IEquatable
+ {
+ internal readonly ushort _HorizontalVisible;
+ internal readonly ushort _HorizontalBorder;
+ internal readonly ushort _HorizontalFrontPorch;
+ internal readonly ushort _HorizontalSyncWidth;
+ internal readonly ushort _HorizontalTotal;
+ internal readonly TimingHorizontalSyncPolarity _HorizontalSyncPolarity;
+ internal readonly ushort _VerticalVisible;
+ internal readonly ushort _VerticalBorder;
+ internal readonly ushort _VerticalFrontPorch;
+ internal readonly ushort _VerticalSyncWidth;
+ internal readonly ushort _VerticalTotal;
+ internal readonly TimingVerticalSyncPolarity _VerticalSyncPolarity;
+ internal readonly TimingScanMode _ScanMode;
+ internal readonly uint _PixelClockIn10KHertz;
+ internal readonly TimingExtra _Extra;
+
+ ///
+ /// Creates an instance of structure.
+ ///
+ /// The horizontal visible pixels
+ /// The vertical visible pixels
+ /// The horizontal border pixels
+ /// The vertical border pixels
+ /// The horizontal front porch pixels
+ /// The vertical front porch pixels
+ /// The horizontal sync width pixels
+ /// The vertical sync width pixels
+ /// The horizontal total pixels
+ /// The vertical total pixels
+ /// The horizontal sync polarity
+ /// The vertical sync polarity
+ /// The scan mode
+ /// The extra timing information
+ public Timing(
+ ushort horizontalVisible,
+ ushort verticalVisible,
+ ushort horizontalBorder,
+ ushort verticalBorder,
+ ushort horizontalFrontPorch,
+ ushort verticalFrontPorch,
+ ushort horizontalSyncWidth,
+ ushort verticalSyncWidth,
+ ushort horizontalTotal,
+ ushort verticalTotal,
+ TimingHorizontalSyncPolarity horizontalPolarity,
+ TimingVerticalSyncPolarity verticalPolarity,
+ TimingScanMode scanMode,
+ TimingExtra extra
+ )
+ {
+ this = typeof(Timing).Instantiate();
+
+ _HorizontalVisible = horizontalVisible;
+ _HorizontalBorder = horizontalBorder;
+ _HorizontalFrontPorch = horizontalFrontPorch;
+ _HorizontalSyncWidth = horizontalSyncWidth;
+ _HorizontalTotal = horizontalTotal;
+ _HorizontalSyncPolarity = horizontalPolarity;
+
+ _VerticalVisible = verticalVisible;
+ _VerticalBorder = verticalBorder;
+ _VerticalFrontPorch = verticalFrontPorch;
+ _VerticalSyncWidth = verticalSyncWidth;
+ _VerticalTotal = verticalTotal;
+ _VerticalSyncPolarity = verticalPolarity;
+
+ _ScanMode = scanMode;
+ _PixelClockIn10KHertz =
+ (uint) (horizontalTotal * verticalTotal * (extra.FrequencyInMillihertz / 1000d) / 10000);
+
+ _Extra = extra;
+ }
+
+ ///
+ /// Creates an instance of structure.
+ ///
+ /// The horizontal visible pixels
+ /// The vertical visible pixels
+ /// The horizontal border pixels
+ /// The vertical border pixels
+ /// The horizontal front porch pixels
+ /// The vertical front porch pixels
+ /// The horizontal sync width pixels
+ /// The vertical sync width pixels
+ /// The horizontal total pixels
+ /// The vertical total pixels
+ /// The horizontal sync polarity
+ /// The vertical sync polarity
+ /// The scan mode
+ /// The frequency in hertz
+ /// The number of identical horizontal pixels that are repeated; 1 = no repetition
+ public Timing(
+ ushort horizontalVisible,
+ ushort verticalVisible,
+ ushort horizontalBorder,
+ ushort verticalBorder,
+ ushort horizontalFrontPorch,
+ ushort verticalFrontPorch,
+ ushort horizontalSyncWidth,
+ ushort verticalSyncWidth,
+ ushort horizontalTotal,
+ ushort verticalTotal,
+ TimingHorizontalSyncPolarity horizontalPolarity,
+ TimingVerticalSyncPolarity verticalPolarity,
+ TimingScanMode scanMode,
+ double refreshRateFrequencyInHz,
+ ushort horizontalPixelRepetition = 1
+ ) : this(
+ horizontalVisible, verticalVisible, horizontalBorder,
+ verticalBorder, horizontalFrontPorch, verticalFrontPorch,
+ horizontalSyncWidth, verticalSyncWidth, horizontalTotal,
+ verticalTotal, horizontalPolarity, verticalPolarity, scanMode,
+ new TimingExtra(
+ refreshRateFrequencyInHz,
+ $"CUST:{horizontalVisible}x{verticalVisible}x{refreshRateFrequencyInHz:F3}Hz",
+ 0,
+ 0,
+ horizontalPixelRepetition
+ )
+ )
+ {
+ }
+
+ ///
+ public bool Equals(Timing other)
+ {
+ return _HorizontalVisible == other._HorizontalVisible &&
+ _HorizontalBorder == other._HorizontalBorder &&
+ _HorizontalFrontPorch == other._HorizontalFrontPorch &&
+ _HorizontalSyncWidth == other._HorizontalSyncWidth &&
+ _HorizontalTotal == other._HorizontalTotal &&
+ _HorizontalSyncPolarity == other._HorizontalSyncPolarity &&
+ _VerticalVisible == other._VerticalVisible &&
+ _VerticalBorder == other._VerticalBorder &&
+ _VerticalFrontPorch == other._VerticalFrontPorch &&
+ _VerticalSyncWidth == other._VerticalSyncWidth &&
+ _VerticalTotal == other._VerticalTotal &&
+ _VerticalSyncPolarity == other._VerticalSyncPolarity &&
+ _ScanMode == other._ScanMode &&
+ _PixelClockIn10KHertz == other._PixelClockIn10KHertz &&
+ _Extra.Equals(other._Extra);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is Timing timing && Equals(timing);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = _HorizontalVisible.GetHashCode();
+ hashCode = (hashCode * 397) ^ _HorizontalBorder.GetHashCode();
+ hashCode = (hashCode * 397) ^ _HorizontalFrontPorch.GetHashCode();
+ hashCode = (hashCode * 397) ^ _HorizontalSyncWidth.GetHashCode();
+ hashCode = (hashCode * 397) ^ _HorizontalTotal.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) _HorizontalSyncPolarity;
+ hashCode = (hashCode * 397) ^ _VerticalVisible.GetHashCode();
+ hashCode = (hashCode * 397) ^ _VerticalBorder.GetHashCode();
+ hashCode = (hashCode * 397) ^ _VerticalFrontPorch.GetHashCode();
+ hashCode = (hashCode * 397) ^ _VerticalSyncWidth.GetHashCode();
+ hashCode = (hashCode * 397) ^ _VerticalTotal.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) _VerticalSyncPolarity;
+ hashCode = (hashCode * 397) ^ (int) _ScanMode;
+ hashCode = (hashCode * 397) ^ (int) _PixelClockIn10KHertz;
+ hashCode = (hashCode * 397) ^ _Extra.GetHashCode();
+
+ return hashCode;
+ }
+ }
+
+ ///
+ /// Checks two instance of for equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// Returns a boolean value indicating if the two instances are equal; otherwise false
+ public static bool operator ==(Timing left, Timing right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Checks two instance of for in equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// Returns a boolean value indicating if the two instances are not equal; otherwise false
+ public static bool operator !=(Timing left, Timing right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ /// Get the horizontal visible pixels
+ ///
+ public int HorizontalVisible
+ {
+ get => _HorizontalVisible;
+ }
+
+ ///
+ /// Get the horizontal border pixels
+ ///
+ public int HorizontalBorder
+ {
+ get => _HorizontalBorder;
+ }
+
+ ///
+ /// Get the horizontal front porch pixels
+ ///
+ public int HorizontalFrontPorch
+ {
+ get => _HorizontalFrontPorch;
+ }
+
+ ///
+ /// Get the horizontal sync width pixels
+ ///
+ public int HorizontalSyncWidth
+ {
+ get => _HorizontalSyncWidth;
+ }
+
+ ///
+ /// Get the horizontal total pixels
+ ///
+ public int HorizontalTotal
+ {
+ get => _HorizontalTotal;
+ }
+
+ ///
+ /// Get the horizontal sync polarity
+ ///
+ public TimingHorizontalSyncPolarity HorizontalSyncPolarity
+ {
+ get => _HorizontalSyncPolarity;
+ }
+
+ ///
+ /// Get the vertical visible pixels
+ ///
+ public int VerticalVisible
+ {
+ get => _VerticalVisible;
+ }
+
+ ///
+ /// Get the vertical border pixels
+ ///
+ public int VerticalBorder
+ {
+ get => _VerticalBorder;
+ }
+
+ ///
+ /// Get the vertical front porch pixels
+ ///
+ public int VerticalFrontPorch
+ {
+ get => _VerticalFrontPorch;
+ }
+
+ ///
+ /// Get the vertical sync width pixels
+ ///
+ public int VerticalSyncWidth
+ {
+ get => _VerticalSyncWidth;
+ }
+
+ ///
+ /// Get the vertical total pixels
+ ///
+ public int VerticalTotal
+ {
+ get => _VerticalTotal;
+ }
+
+ ///
+ /// Get the vertical sync polarity
+ ///
+ public TimingVerticalSyncPolarity VerticalSyncPolarity
+ {
+ get => _VerticalSyncPolarity;
+ }
+
+ ///
+ /// Get the scan mode
+ ///
+ public TimingScanMode ScanMode
+ {
+ get => _ScanMode;
+ }
+
+ ///
+ /// Get the pixel clock in 10 kHz
+ ///
+ public int PixelClockIn10KHertz
+ {
+ get => (int) _PixelClockIn10KHertz;
+ }
+
+ ///
+ /// Get the other timing related extras
+ ///
+ public TimingExtra Extra
+ {
+ get => _Extra;
+ }
+
+ ///
+ /// Gets the horizontal active pixels
+ ///
+ public int HorizontalActive
+ {
+ get => HorizontalVisible + HorizontalBorder;
+ }
+
+ ///
+ /// Gets the vertical active pixels
+ ///
+ public int VerticalActive
+ {
+ get => VerticalVisible + VerticalBorder;
+ }
+
+ ///
+ /// Gets the horizontal back porch pixels
+ ///
+ public int HorizontalBackPorch
+ {
+ get => HorizontalBlanking - (HorizontalFrontPorch + HorizontalSyncWidth);
+ }
+
+ ///
+ /// Gets the horizontal blanking pixels
+ ///
+ public int HorizontalBlanking
+ {
+ get => HorizontalTotal - (HorizontalActive + HorizontalBorder);
+ }
+
+ ///
+ /// Gets vertical back porch pixels
+ ///
+ public int VerticalBackPorch
+ {
+ get => VerticalBlanking - (VerticalFrontPorch + VerticalSyncWidth);
+ }
+
+ ///
+ /// Gets the vertical blanking pixels
+ ///
+ public int VerticalBlanking
+ {
+ get => VerticalTotal - (VerticalActive + VerticalBorder);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/TimingExtra.cs b/NvAPIWrapper/Native/Display/Structures/TimingExtra.cs
new file mode 100644
index 0000000..6c218b2
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/TimingExtra.cs
@@ -0,0 +1,215 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Holds NVIDIA-specific timing extras
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct TimingExtra : IInitializable, IEquatable
+ {
+ internal readonly uint _HardwareFlags;
+ internal readonly ushort _RefreshRate;
+ internal readonly uint _FrequencyInMillihertz;
+ internal readonly ushort _VerticalAspect;
+ internal readonly ushort _HorizontalAspect;
+ internal readonly ushort _HorizontalPixelRepetition;
+ internal readonly uint _Standard;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
+ internal string _Name;
+
+ ///
+ /// Creates a new instance of structure.
+ ///
+ /// The timing frequency in hertz
+ /// The timing source name
+ /// The display horizontal aspect
+ /// The display vertical aspect
+ /// The number of identical horizontal pixels that are repeated; 1 = no repetition
+ /// The NVIDIA hardware-based enhancement, such as double-scan.
+ public TimingExtra(
+ double frequencyInHertz,
+ string name,
+ ushort horizontalAspect = 0,
+ ushort verticalAspect = 0,
+ ushort horizontalPixelRepetition = 1,
+ uint hardwareFlags = 0
+ ) : this(
+ (uint) (frequencyInHertz * 1000d),
+ (ushort) frequencyInHertz,
+ name,
+ horizontalAspect,
+ verticalAspect,
+ horizontalPixelRepetition,
+ hardwareFlags
+ )
+ {
+ }
+
+ ///
+ /// Creates a new instance of structure.
+ ///
+ /// The timing frequency in millihertz
+ /// The refresh rate
+ /// The timing source name
+ /// The display horizontal aspect
+ /// The display vertical aspect
+ /// The number of identical horizontal pixels that are repeated; 1 = no repetition
+ /// The NVIDIA hardware-based enhancement, such as double-scan.
+ public TimingExtra(
+ uint frequencyInMillihertz,
+ ushort refreshRate,
+ string name,
+ ushort horizontalAspect = 0,
+ ushort verticalAspect = 0,
+ ushort horizontalPixelRepetition = 1,
+ uint hardwareFlags = 0
+ )
+ {
+ this = typeof(TimingExtra).Instantiate();
+ _FrequencyInMillihertz = frequencyInMillihertz;
+ _RefreshRate = refreshRate;
+ _HorizontalAspect = horizontalAspect;
+ _VerticalAspect = verticalAspect;
+ _HorizontalPixelRepetition = horizontalPixelRepetition;
+ _HardwareFlags = hardwareFlags;
+ _Name = name?.Length > 40 ? name.Substring(0, 40) : name ?? "";
+ }
+
+ ///
+ public bool Equals(TimingExtra other)
+ {
+ return _HardwareFlags == other._HardwareFlags &&
+ _RefreshRate == other._RefreshRate &&
+ _FrequencyInMillihertz == other._FrequencyInMillihertz &&
+ _VerticalAspect == other._VerticalAspect &&
+ _HorizontalAspect == other._HorizontalAspect &&
+ _HorizontalPixelRepetition == other._HorizontalPixelRepetition &&
+ _Standard == other._Standard;
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is TimingExtra extra && Equals(extra);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = (int) _HardwareFlags;
+ hashCode = (hashCode * 397) ^ _RefreshRate.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) _FrequencyInMillihertz;
+ hashCode = (hashCode * 397) ^ _VerticalAspect.GetHashCode();
+ hashCode = (hashCode * 397) ^ _HorizontalAspect.GetHashCode();
+ hashCode = (hashCode * 397) ^ _HorizontalPixelRepetition.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) _Standard;
+
+ return hashCode;
+ }
+ }
+
+ ///
+ /// Gets the NVIDIA hardware-based enhancement, such as double-scan.
+ ///
+ public uint HardwareFlags
+ {
+ get => _HardwareFlags;
+ }
+
+ ///
+ /// Gets the logical refresh rate to present
+ ///
+ public int RefreshRate
+ {
+ get => _RefreshRate;
+ }
+
+ ///
+ /// Gets the physical vertical refresh rate in 0.001Hz
+ ///
+ public int FrequencyInMillihertz
+ {
+ get => (int) _FrequencyInMillihertz;
+ }
+
+ ///
+ /// Gets the display vertical aspect
+ ///
+ public int VerticalAspect
+ {
+ get => _VerticalAspect;
+ }
+
+ ///
+ /// Gets the display horizontal aspect
+ ///
+ public int HorizontalAspect
+ {
+ get => _HorizontalAspect;
+ }
+
+ ///
+ /// Gets the bit-wise pixel repetition factor: 0x1:no pixel repetition; 0x2:each pixel repeats twice horizontally,..
+ ///
+ public int PixelRepetition
+ {
+ get => _HorizontalPixelRepetition;
+ }
+
+ ///
+ /// Gets the timing standard
+ ///
+ public uint Standard
+ {
+ get => _Standard;
+ }
+
+ ///
+ /// Gets the timing name
+ ///
+ public string Name
+ {
+ get => _Name;
+ }
+
+ ///
+ public override string ToString()
+ {
+ return Name;
+ }
+
+ ///
+ /// Checks two instance of for equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// Returns a boolean value indicating if the two instances are equal; otherwise false
+ public static bool operator ==(TimingExtra left, TimingExtra right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Checks two instance of for equality.
+ ///
+ /// The first instance.
+ /// The second instance.
+ /// Returns a boolean value indicating if the two instances are equal; otherwise false
+ public static bool operator !=(TimingExtra left, TimingExtra right)
+ {
+ return !(left == right);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/TimingInput.cs b/NvAPIWrapper/Native/Display/Structures/TimingInput.cs
new file mode 100644
index 0000000..3303039
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/TimingInput.cs
@@ -0,0 +1,253 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Attributes;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Contains the information required for calculating timing for a particular display
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructureVersion(1)]
+ public struct TimingInput : IInitializable
+ {
+ [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 12)]
+ internal struct TimingFlag
+ {
+ [FieldOffset(0)] internal ushort _Flags;
+ [FieldOffset(4)] internal byte _TVFormatCEAIdPSFormatId;
+ [FieldOffset(8)] internal byte _Scaling;
+
+ public bool IsInterlaced
+ {
+ get => _Flags.GetBit(0);
+ set => _Flags = _Flags.SetBit(0, value);
+ }
+
+ public TVFormat TVFormat
+ {
+ get => (TVFormat) _TVFormatCEAIdPSFormatId;
+ set => _TVFormatCEAIdPSFormatId = (byte) value;
+ }
+
+ public byte CEAId
+ {
+ get => _TVFormatCEAIdPSFormatId;
+ set => _TVFormatCEAIdPSFormatId = value;
+ }
+
+ public byte PredefinedPSFormatId
+ {
+ get => _TVFormatCEAIdPSFormatId;
+ set => _TVFormatCEAIdPSFormatId = value;
+ }
+
+ public byte Scaling
+ {
+ get => _Scaling;
+ set => _Scaling = value;
+ }
+
+ public TimingFlag(bool isInterlaced, byte scaling) : this()
+ {
+ IsInterlaced = isInterlaced;
+ Scaling = scaling;
+ }
+
+ public TimingFlag(bool isInterlaced, byte scaling, TVFormat tvFormat) : this(isInterlaced, scaling)
+ {
+ TVFormat = tvFormat;
+ }
+
+ public TimingFlag(bool isInterlaced, byte scaling, byte ceaIdOrPredefinedPSFormatId) : this(isInterlaced,
+ scaling)
+ {
+ _TVFormatCEAIdPSFormatId = ceaIdOrPredefinedPSFormatId;
+ }
+ }
+
+ internal StructureVersion _Version;
+ internal uint _Width;
+ internal uint _Height;
+ internal float _RefreshRate;
+ internal TimingFlag _Flags;
+ internal TimingOverride _TimingType;
+
+ ///
+ /// Gets the visible horizontal size
+ ///
+ public uint Width
+ {
+ get => _Width;
+ }
+
+ ///
+ /// Gets the visible vertical size
+ ///
+ public uint Height
+ {
+ get => _Height;
+ }
+
+ ///
+ /// Gets the timing refresh rate
+ ///
+ public float RefreshRate
+ {
+ get => _RefreshRate;
+ }
+
+ ///
+ /// Gets a boolean value indicating if the requested timing is an interlaced timing
+ ///
+ public bool IsInterlaced
+ {
+ get => _Flags.IsInterlaced;
+ }
+
+ ///
+ /// Gets the preferred scaling
+ ///
+ public byte Scaling
+ {
+ get => _Flags.Scaling;
+ }
+
+ ///
+ /// Gets timing type (formula) to use for calculating the timing
+ ///
+ public TimingOverride TimingType
+ {
+ get => _TimingType;
+ }
+
+ ///
+ /// Creates an instance of the TimingInput
+ ///
+ /// The preferred visible horizontal size
+ /// The preferred visible vertical size
+ /// The preferred timing refresh rate
+ /// The preferred formula to be used for timing calculation
+ /// A boolean value indicating if the preferred timing is interlaced
+ /// The preferred scaling factor
+ public TimingInput(
+ uint width,
+ uint height,
+ float refreshRate,
+ TimingOverride timingType,
+ bool isInterlaced = false,
+ byte scaling = 0
+ )
+ {
+ this = typeof(TimingInput).Instantiate();
+ _Width = width;
+ _Height = height;
+ _RefreshRate = refreshRate;
+ _TimingType = timingType;
+ _Flags = new TimingFlag(isInterlaced, scaling);
+ }
+
+ ///
+ /// Creates an instance of the TimingInput
+ ///
+ /// The preferred analog TV format
+ /// A boolean value indicating if the preferred timing is interlaced
+ /// The preferred scaling factor
+ public TimingInput(TVFormat tvFormat, bool isInterlaced = false, byte scaling = 0)
+ : this(0, 0, 0, TimingOverride.AnalogTV, isInterlaced, scaling)
+ {
+ _Flags = new TimingFlag(isInterlaced, scaling, tvFormat);
+ }
+
+ ///
+ /// Creates an instance of the TimingInput
+ ///
+ ///
+ /// The CEA id or the predefined PsF format id depending on the value of other
+ /// arguments
+ ///
+ ///
+ /// The preferred formula to be used for timing calculation, valid values for this overload are
+ /// and .
+ ///
+ /// A boolean value indicating if the preferred timing is interlaced
+ /// The preferred scaling factor
+ public TimingInput(
+ byte ceaIdOrPredefinedPSFormatId,
+ TimingOverride timingType,
+ bool isInterlaced = false,
+ byte scaling = 0
+ )
+ : this(0, 0, 0, timingType, isInterlaced, scaling)
+ {
+ if (timingType != TimingOverride.EIA861 && timingType != TimingOverride.Predefined)
+ {
+ throw new ArgumentException("Invalid timing type passed.", nameof(timingType));
+ }
+
+ _Flags = new TimingFlag(isInterlaced, scaling, ceaIdOrPredefinedPSFormatId);
+ }
+
+ ///
+ /// Creates an instance of the TimingInput
+ ///
+ ///
+ /// The preferred formula to be used for timing calculation.
+ ///
+ public TimingInput(TimingOverride timingType)
+ : this(0, 0, 0, timingType)
+ {
+ }
+
+ ///
+ /// Gets the analog TV actual HD/SDTV format
+ ///
+ public TVFormat? TVFormat
+ {
+ get
+ {
+ if (Width == 0 && Height == 0 && Math.Abs(RefreshRate) < 0.01 && TimingType == TimingOverride.AnalogTV)
+ {
+ return _Flags.TVFormat;
+ }
+
+ return null;
+ }
+ }
+
+ ///
+ /// Gets the EIA/CEA 861B/D predefined short timing descriptor id
+ ///
+ public byte? CEAId
+ {
+ get
+ {
+ if (Width == 0 && Height == 0 && Math.Abs(RefreshRate) < 0.01 && TimingType == TimingOverride.EIA861)
+ {
+ return _Flags.CEAId;
+ }
+
+ return null;
+ }
+ }
+
+ ///
+ /// Gets the Nvidia predefined PsF format id
+ ///
+ public byte? PredefinedPSFormatId
+ {
+ get
+ {
+ if (TimingType == TimingOverride.Predefined)
+ {
+ return _Flags.PredefinedPSFormatId;
+ }
+
+ return null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/UnAttachedDisplayHandle.cs b/NvAPIWrapper/Native/Display/Structures/UnAttachedDisplayHandle.cs
new file mode 100644
index 0000000..528e706
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/UnAttachedDisplayHandle.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Runtime.InteropServices;
+using NvAPIWrapper.Native.Interfaces;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// UnAttachedDisplayHandle is a one-to-one map to the GDI handle of an unattached display.
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UnAttachedDisplayHandle : IHandle, IEquatable
+ {
+ internal readonly IntPtr _MemoryAddress;
+
+ ///
+ public bool Equals(UnAttachedDisplayHandle other)
+ {
+ return _MemoryAddress.Equals(other._MemoryAddress);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ return obj is UnAttachedDisplayHandle && Equals((UnAttachedDisplayHandle) obj);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return _MemoryAddress.GetHashCode();
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"UnAttachedDisplayHandle #{MemoryAddress.ToInt64()}";
+ }
+
+ ///
+ /// Checks for equality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are equal, otherwise false
+ public static bool operator ==(UnAttachedDisplayHandle left, UnAttachedDisplayHandle right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Checks for inequality between two objects of same type
+ ///
+ /// The first object
+ /// The second object
+ /// true, if both objects are not equal, otherwise false
+ public static bool operator !=(UnAttachedDisplayHandle left, UnAttachedDisplayHandle right)
+ {
+ return !left.Equals(right);
+ }
+
+ ///
+ public IntPtr MemoryAddress
+ {
+ get => _MemoryAddress;
+ }
+
+ ///
+ public bool IsNull
+ {
+ get => _MemoryAddress == IntPtr.Zero;
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/Structures/ViewPortF.cs b/NvAPIWrapper/Native/Display/Structures/ViewPortF.cs
new file mode 100644
index 0000000..b01d18e
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/Structures/ViewPortF.cs
@@ -0,0 +1,87 @@
+using System.Drawing;
+using System.Runtime.InteropServices;
+
+namespace NvAPIWrapper.Native.Display.Structures
+{
+ ///
+ /// Hold information about the screen view port rectangle
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct ViewPortF
+ {
+ internal float _X;
+ internal float _Y;
+ internal float _Width;
+ internal float _Height;
+
+ ///
+ /// Gets the x-coordinate of the viewport top-left point
+ ///
+ public float X
+ {
+ get => _X;
+ }
+
+ ///
+ /// Gets the y-coordinate of the viewport top-left point
+ ///
+ public float Y
+ {
+ get => _Y;
+ }
+
+ ///
+ /// Gets the width of the viewport.
+ ///
+ public float Width
+ {
+ get => _Width;
+ }
+
+ ///
+ /// Gets the height of the viewport.
+ ///
+ public float Height
+ {
+ get => _Height;
+ }
+
+ ///
+ /// Creates an instance of ViewPortF
+ ///
+ /// The x-coordinate of the viewport top-left point
+ /// The y-coordinate of the viewport top-left point
+ /// The width of the viewport.
+ /// The height of the viewport.
+ public ViewPortF(float x, float y, float width, float height)
+ {
+ _X = x;
+ _Y = y;
+ _Width = width;
+ _Height = height;
+ }
+
+ ///
+ /// Creates an instance of
+ ///
+ /// The rectangle to take view port information from.
+ public ViewPortF(RectangleF rect) : this(rect.X, rect.Y, rect.Width, rect.Height)
+ {
+ }
+
+ ///
+ /// Return an instance of representing this view port.
+ ///
+ ///
+ public RectangleF ToRectangle()
+ {
+ return new RectangleF(X, Y, Width, Height);
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"({Width:F1}, {Height:F1}) @ ({X:F1}, {Y:F1})";
+ }
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/TVFormat.cs b/NvAPIWrapper/Native/Display/TVFormat.cs
new file mode 100644
index 0000000..1571d41
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/TVFormat.cs
@@ -0,0 +1,219 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Possible TV formats
+ ///
+ public enum TVFormat : uint
+ {
+ ///
+ /// Display is not a TV
+ ///
+ None = 0,
+
+ ///
+ /// Standard definition NTSC M signal
+ ///
+ // ReSharper disable once InconsistentNaming
+ SD_NTSCM = 0x00000001,
+
+ ///
+ /// Standard definition NTSC J signal
+ ///
+ // ReSharper disable once InconsistentNaming
+ SD_NTSCJ = 0x00000002,
+
+ ///
+ /// Standard definition PAL M signal
+ ///
+ // ReSharper disable once InconsistentNaming
+ SD_PALM = 0x00000004,
+
+ ///
+ /// Standard definition PAL DFGH signal
+ ///
+ // ReSharper disable once InconsistentNaming
+ SD_PALBDGH = 0x00000008,
+
+ ///
+ /// Standard definition PAL N signal
+ ///
+ // ReSharper disable once InconsistentNaming
+ SD_PAL_N = 0x00000010,
+
+ ///
+ /// Standard definition PAL NC signal
+ ///
+ // ReSharper disable once InconsistentNaming
+ SD_PAL_NC = 0x00000020,
+
+ ///
+ /// Extended definition with height of 576 pixels interlaced
+ ///
+ // ReSharper disable once InconsistentNaming
+ SD576i = 0x00000100,
+
+ ///
+ /// Extended definition with height of 480 pixels interlaced
+ ///
+ // ReSharper disable once InconsistentNaming
+ SD480i = 0x00000200,
+
+ ///
+ /// Extended definition with height of 480 pixels progressive
+ ///
+ // ReSharper disable once InconsistentNaming
+ ED480p = 0x00000400,
+
+ ///
+ /// Extended definition with height of 576 pixels progressive
+ ///
+ // ReSharper disable once InconsistentNaming
+ ED576p = 0x00000800,
+
+ ///
+ /// High definition with height of 720 pixels progressive
+ ///
+ // ReSharper disable once InconsistentNaming
+ HD720p = 0x00001000,
+
+ ///
+ /// High definition with height of 1080 pixels interlaced
+ ///
+ // ReSharper disable once InconsistentNaming
+ HD1080i = 0x00002000,
+
+ ///
+ /// High definition with height of 1080 pixels progressive
+ ///
+ // ReSharper disable once InconsistentNaming
+ HD1080p = 0x00004000,
+
+ ///
+ /// High definition 50 frames per second with height of 720 pixels progressive
+ ///
+ // ReSharper disable once InconsistentNaming
+ HD720p50 = 0x00008000,
+
+ ///
+ /// High definition 24 frames per second with height of 1080 pixels progressive
+ ///
+ // ReSharper disable once InconsistentNaming
+ HD1080p24 = 0x00010000,
+
+ ///
+ /// High definition 50 frames per second with height of 1080 pixels interlaced
+ ///
+ // ReSharper disable once InconsistentNaming
+ HD1080i50 = 0x00020000,
+
+ ///
+ /// High definition 50 frames per second with height of 1080 pixels progressive
+ ///
+ // ReSharper disable once InconsistentNaming
+ HD1080p50 = 0x00040000,
+
+ ///
+ /// Ultra high definition 30 frames per second
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp30 = 0x00080000,
+
+ ///
+ /// Ultra high definition 30 frames per second with width of 3840 pixels
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp30_3840 = UHD4Kp30,
+
+ ///
+ /// Ultra high definition 25 frames per second
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp25 = 0x00100000,
+
+ ///
+ /// Ultra high definition 25 frames per second with width of 3840 pixels
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp25_3840 = UHD4Kp25,
+
+ ///
+ /// Ultra high definition 24 frames per second
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp24 = 0x00200000,
+
+ ///
+ /// Ultra high definition 24 frames per second with width of 3840 pixels
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp24_3840 = UHD4Kp24,
+
+ ///
+ /// Ultra high definition 24 frames per second with SMPTE signal
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp24_SMPTE = 0x00400000,
+
+ ///
+ /// Ultra high definition 50 frames per second with width of 3840 pixels
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp50_3840 = 0x00800000,
+
+ ///
+ /// Ultra high definition 60 frames per second with width of 3840 pixels
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp60_3840 = 0x00900000,
+
+ ///
+ /// Ultra high definition 30 frames per second with width of 4096 pixels
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp30_4096 = 0x00A00000,
+
+ ///
+ /// Ultra high definition 25 frames per second with width of 4096 pixels
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp25_4096 = 0x00B00000,
+
+ ///
+ /// Ultra high definition 24 frames per second with width of 4096 pixels
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp24_4096 = 0x00C00000,
+
+ ///
+ /// Ultra high definition 50 frames per second with width of 4096 pixels
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp50_4096 = 0x00D00000,
+
+ ///
+ /// Ultra high definition 60 frames per second with width of 4096 pixels
+ ///
+ // ReSharper disable once InconsistentNaming
+ UHD4Kp60_4096 = 0x00E00000,
+
+ ///
+ /// Any other standard definition TV format
+ ///
+ SDOther = 0x01000000,
+
+ ///
+ /// Any other extended definition TV format
+ ///
+ EDOther = 0x02000000,
+
+ ///
+ /// Any other high definition TV format
+ ///
+ HDOther = 0x04000000,
+
+ ///
+ /// Any other TV format
+ ///
+ Any = 0x80000000
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/TargetViewMode.cs b/NvAPIWrapper/Native/Display/TargetViewMode.cs
new file mode 100644
index 0000000..39f24b1
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/TargetViewMode.cs
@@ -0,0 +1,38 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Display view modes
+ ///
+ public enum TargetViewMode
+ {
+ ///
+ /// Standard view mode
+ ///
+ Standard = 0,
+
+ ///
+ /// Cloned view mode
+ ///
+ Clone = 1,
+
+ ///
+ /// Horizontal span view mode
+ ///
+ HorizontalSpan = 2,
+
+ ///
+ /// Vertical span view mode
+ ///
+ VerticalSpan = 3,
+
+ ///
+ /// Dual view mode
+ ///
+ DualView = 4,
+
+ ///
+ /// Multi view mode
+ ///
+ MultiView = 5
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/TimingHorizontalSyncPolarity.cs b/NvAPIWrapper/Native/Display/TimingHorizontalSyncPolarity.cs
new file mode 100644
index 0000000..90c541c
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/TimingHorizontalSyncPolarity.cs
@@ -0,0 +1,23 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Horizontal synchronized polarity modes
+ ///
+ public enum TimingHorizontalSyncPolarity : byte
+ {
+ ///
+ /// Positive horizontal synchronized polarity
+ ///
+ Positive = 0,
+
+ ///
+ /// Negative horizontal synchronized polarity
+ ///
+ Negative = 1,
+
+ ///
+ /// Default horizontal synchronized polarity
+ ///
+ Default = Negative
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/TimingOverride.cs b/NvAPIWrapper/Native/Display/TimingOverride.cs
new file mode 100644
index 0000000..ead2b6d
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/TimingOverride.cs
@@ -0,0 +1,88 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Timing override modes
+ ///
+ public enum TimingOverride
+ {
+ ///
+ /// Current timing
+ ///
+ Current = 0,
+
+ ///
+ /// Auto timing
+ ///
+ Auto,
+
+ ///
+ /// EDID timing
+ ///
+ EDID,
+
+ ///
+ /// VESA DMT timing
+ ///
+ DMT,
+
+ ///
+ /// VESA DMT timing with reduced blanking
+ ///
+ DMTReducedBlanking,
+
+ ///
+ /// VESA CVT timing
+ ///
+ CVT,
+
+ ///
+ /// VESA CVT timing with reduced blanking
+ ///
+ CVTReducedBlanking,
+
+ ///
+ /// VESA GTF
+ ///
+ GTF,
+
+ ///
+ /// EIA 861x PreDefined timing
+ ///
+ EIA861,
+
+ ///
+ /// AnalogTV PreDefined timing
+ ///
+ AnalogTV,
+
+ ///
+ /// NVIDIA Custom timing
+ ///
+ Custom,
+
+ ///
+ /// NVIDIA PreDefined timing
+ ///
+ Predefined,
+
+ ///
+ /// NVIDIA PreDefined timing
+ ///
+ PSF = Predefined,
+
+ ///
+ /// ASPR timing
+ ///
+ ASPR,
+
+ ///
+ /// Override for SDI timing
+ ///
+ SDI,
+
+ ///
+ /// Not used
+ ///
+ Max
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/TimingScanMode.cs b/NvAPIWrapper/Native/Display/TimingScanMode.cs
new file mode 100644
index 0000000..a4d4271
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/TimingScanMode.cs
@@ -0,0 +1,28 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Timing scan modes
+ ///
+ public enum TimingScanMode : ushort
+ {
+ ///
+ /// Progressive scan mode
+ ///
+ Progressive = 0,
+
+ ///
+ /// Interlaced scan mode
+ ///
+ Interlaced = 1,
+
+ ///
+ /// Interlaced scan mode with extra vertical blank
+ ///
+ InterlacedWithExtraVerticalBlank = 1,
+
+ ///
+ /// Interlaced scan mode without extra vertical blank
+ ///
+ InterlacedWithNoExtraVerticalBlank = 2
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/TimingVerticalSyncPolarity.cs b/NvAPIWrapper/Native/Display/TimingVerticalSyncPolarity.cs
new file mode 100644
index 0000000..3bf5292
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/TimingVerticalSyncPolarity.cs
@@ -0,0 +1,23 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Vertical synchronized polarity modes
+ ///
+ public enum TimingVerticalSyncPolarity : byte
+ {
+ ///
+ /// Positive vertical synchronized polarity
+ ///
+ Positive = 0,
+
+ ///
+ /// Negative vertical synchronized polarity
+ ///
+ Negative = 1,
+
+ ///
+ /// Default vertical synchronized polarity
+ ///
+ Default = Positive
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/Display/WarpingVerticeFormat.cs b/NvAPIWrapper/Native/Display/WarpingVerticeFormat.cs
new file mode 100644
index 0000000..87dbc7d
--- /dev/null
+++ b/NvAPIWrapper/Native/Display/WarpingVerticeFormat.cs
@@ -0,0 +1,18 @@
+namespace NvAPIWrapper.Native.Display
+{
+ ///
+ /// Holds a list of possible warping vertex formats
+ ///
+ public enum WarpingVerticeFormat : uint
+ {
+ ///
+ /// XYUVRQ Triangle Strip vertex format
+ ///
+ TriangleStripXYUVRQ = 0,
+
+ ///
+ /// XYUVRQ Triangles format
+ ///
+ TrianglesXYUVRQ = 1
+ }
+}
\ No newline at end of file
diff --git a/NvAPIWrapper/Native/DisplayApi.cs b/NvAPIWrapper/Native/DisplayApi.cs
new file mode 100644
index 0000000..18e359e
--- /dev/null
+++ b/NvAPIWrapper/Native/DisplayApi.cs
@@ -0,0 +1,1674 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NvAPIWrapper.Native.Display;
+using NvAPIWrapper.Native.Display.Structures;
+using NvAPIWrapper.Native.Exceptions;
+using NvAPIWrapper.Native.General;
+using NvAPIWrapper.Native.General.Structures;
+using NvAPIWrapper.Native.GPU;
+using NvAPIWrapper.Native.Helpers;
+using NvAPIWrapper.Native.Helpers.Structures;
+using NvAPIWrapper.Native.Interfaces.Display;
+using NvAPIWrapper.Native.Interfaces.GPU;
+
+namespace NvAPIWrapper.Native
+{
+ ///
+ /// Contains display and display control static functions
+ ///
+ public static class DisplayApi
+ {
+ ///
+ /// This API controls the display color configurations.
+ ///
+ /// The targeted display id.
+ /// The structure to be filled with information requested or applied on the display.
+ public static void ColorControl(uint displayId, ref TColorData colorData)
+ where TColorData : struct, IColorData
+ {
+ var c = colorData as IColorData;
+ ColorControl(displayId, ref c);
+ colorData = (TColorData) c;
+ }
+
+ ///
+ /// This API controls the display color configurations.
+ ///
+ /// The targeted display id.
+ /// The structure to be filled with information requested or applied on the display.
+ public static void ColorControl(uint displayId, ref IColorData colorData)
+ {
+ var colorControl = DelegateFactory.GetDelegate();
+ var type = colorData.GetType();
+
+ if (!colorControl.Accepts().Contains(type))
+ {
+ throw new ArgumentOutOfRangeException(nameof(type));
+ }
+
+ using (var colorDataReference = ValueTypeReference.FromValueType(colorData, type))
+ {
+ var status = colorControl(displayId, colorDataReference);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ colorData = colorDataReference.ToValueType(type);
+ }
+ }
+
+ ///
+ /// This API controls the display color configurations.
+ ///
+ /// The targeted display id.
+ /// The list of structures to be filled with information requested or applied on the display.
+ /// The structure that succeed in requesting information or used for applying configuration on the display.
+ // ReSharper disable once IdentifierTypo
+ public static IColorData ColorControl(uint displayId, IColorData[] colorDatas)
+ {
+ foreach (var colorData in colorDatas)
+ {
+ try
+ {
+ var c = colorData;
+ ColorControl(displayId, ref c);
+
+ return c;
+ }
+ catch (NVIDIAApiException e)
+ {
+ if (e.Status == Status.IncompatibleStructureVersion)
+ {
+ continue;
+ }
+
+ throw;
+ }
+ }
+
+ throw new NVIDIANotSupportedException("This operation is not supported.");
+ }
+
+ ///
+ /// This function converts the unattached display handle to an active attached display handle.
+ /// At least one GPU must be present in the system and running an NVIDIA display driver.
+ ///
+ /// An unattached display handle to convert.
+ /// Display handle of newly created display.
+ /// Status.InvalidArgument: Invalid UnAttachedDisplayHandle handle.
+ /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found
+ /// A delegate callback throws an exception.
+ public static DisplayHandle CreateDisplayFromUnAttachedDisplay(UnAttachedDisplayHandle display)
+ {
+ var createDisplayFromUnAttachedDisplay =
+ DelegateFactory.GetDelegate();
+ var status = createDisplayFromUnAttachedDisplay(display, out var newDisplay);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return newDisplay;
+ }
+
+ ///
+ /// This function deletes the custom display configuration, specified from the registry for all the displays whose
+ /// display IDs are passed.
+ ///
+ /// Array of display IDs on which custom display configuration should be removed.
+ /// The custom display to remove.
+ public static void DeleteCustomDisplay(uint[] displayIds, CustomDisplay customDisplay)
+ {
+ if (displayIds.Length == 0)
+ {
+ return;
+ }
+
+ using (var displayIdsReference = ValueTypeArray.FromArray(displayIds))
+ {
+ using (var customDisplayReference = ValueTypeReference.FromValueType(customDisplay))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ displayIdsReference,
+ (uint) displayIds.Length,
+ customDisplayReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+ }
+ }
+ }
+
+ ///
+ /// This API enumerates the custom timing specified by the enum index.
+ ///
+ /// The display id of the display.
+ /// A list of
+ public static IEnumerable EnumCustomDisplays(uint displayId)
+ {
+ var instance = typeof(CustomDisplay).Instantiate();
+
+ using (var customDisplayReference = ValueTypeReference.FromValueType(instance))
+ {
+ for (uint i = 0; i < uint.MaxValue; i++)
+ {
+ var status = DelegateFactory.GetDelegate()(
+ displayId,
+ i,
+ customDisplayReference
+ );
+
+ if (status == Status.EndEnumeration)
+ {
+ yield break;
+ }
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ yield return customDisplayReference.ToValueType().GetValueOrDefault();
+ }
+ }
+ }
+
+ ///
+ /// This function returns the handle of all NVIDIA displays
+ /// Note: Display handles can get invalidated on a mode-set, so the calling applications need to re-enum the handles
+ /// after every mode-set.
+ ///
+ /// Array of display handles.
+ /// Status.NvidiaDeviceNotFound: No NVIDIA device found in the system
+ /// A delegate callback throws an exception.
+ public static DisplayHandle[] EnumNvidiaDisplayHandle()
+ {
+ var enumNvidiaDisplayHandle =
+ DelegateFactory.GetDelegate();
+ var results = new List();
+ uint i = 0;
+
+ while (true)
+ {
+ var status = enumNvidiaDisplayHandle(i, out var displayHandle);
+
+ if (status == Status.EndEnumeration)
+ {
+ break;
+ }
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ results.Add(displayHandle);
+ i++;
+ }
+
+ return results.ToArray();
+ }
+
+ ///
+ /// This function returns the handle of all unattached NVIDIA displays
+ /// Note: Display handles can get invalidated on a mode-set, so the calling applications need to re-enum the handles
+ /// after every mode-set.
+ ///
+ /// Array of unattached display handles.
+ /// Status.NvidiaDeviceNotFound: No NVIDIA device found in the system
+ /// A delegate callback throws an exception.
+ public static UnAttachedDisplayHandle[] EnumNvidiaUnAttachedDisplayHandle()
+ {
+ var enumNvidiaUnAttachedDisplayHandle =
+ DelegateFactory.GetDelegate();
+ var results = new List();
+ uint i = 0;
+
+ while (true)
+ {
+ var status = enumNvidiaUnAttachedDisplayHandle(i, out var displayHandle);
+
+ if (status == Status.EndEnumeration)
+ {
+ break;
+ }
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ results.Add(displayHandle);
+ i++;
+ }
+
+ return results.ToArray();
+ }
+
+ ///
+ /// This function gets the active outputId associated with the display handle.
+ ///
+ ///
+ /// NVIDIA Display selection. It can be DisplayHandle.DefaultHandle or a handle enumerated from
+ /// DisplayApi.EnumNVidiaDisplayHandle().
+ ///
+ ///
+ /// The active display output ID associated with the selected display handle hNvDisplay. The output id will have
+ /// only one bit set. In the case of Clone or Span mode, this will indicate the display outputId of the primary display
+ /// that the GPU is driving.
+ ///
+ /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found.
+ /// Status.ExpectedDisplayHandle: display is not a valid display handle.
+ /// A delegate callback throws an exception.
+ public static OutputId GetAssociatedDisplayOutputId(DisplayHandle display)
+ {
+ var getAssociatedDisplayOutputId =
+ DelegateFactory.GetDelegate();
+ var status = getAssociatedDisplayOutputId(display, out var outputId);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return outputId;
+ }
+
+ ///
+ /// This function returns the handle of the NVIDIA display that is associated with the given display "name" (such as
+ /// "\\.\DISPLAY1").
+ ///
+ /// Display name
+ /// Display handle of associated display
+ /// Status.InvalidArgument: Display name is null.
+ /// Status.NvidiaDeviceNotFound: No NVIDIA device maps to that display name.
+ /// A delegate callback throws an exception.
+ public static DisplayHandle GetAssociatedNvidiaDisplayHandle(string name)
+ {
+ var getAssociatedNvidiaDisplayHandle =
+ DelegateFactory.GetDelegate();
+ var status = getAssociatedNvidiaDisplayHandle(name, out var display);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return display;
+ }
+
+ ///
+ /// For a given NVIDIA display handle, this function returns a string (such as "\\.\DISPLAY1") to identify the display.
+ ///
+ /// Handle of the associated display
+ /// Name of the display
+ /// Status.InvalidArgument: Display handle is null.
+ /// Status.NvidiaDeviceNotFound: No NVIDIA device maps to that display name.
+ /// A delegate callback throws an exception.
+ public static string GetAssociatedNvidiaDisplayName(DisplayHandle display)
+ {
+ var getAssociatedNvidiaDisplayName =
+ DelegateFactory.GetDelegate();
+ var status = getAssociatedNvidiaDisplayName(display, out var displayName);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return displayName.Value;
+ }
+
+ ///
+ /// This function returns the handle of an unattached NVIDIA display that is associated with the given display "name"
+ /// (such as "\\DISPLAY1").
+ ///
+ /// Display name
+ /// Display handle of associated unattached display
+ /// Status.InvalidArgument: Display name is null.
+ /// Status.NvidiaDeviceNotFound: No NVIDIA device maps to that display name.
+ /// A delegate callback throws an exception.
+ public static UnAttachedDisplayHandle GetAssociatedUnAttachedNvidiaDisplayHandle(string name)
+ {
+ var getAssociatedUnAttachedNvidiaDisplayHandle =
+ DelegateFactory.GetDelegate();
+ var status = getAssociatedUnAttachedNvidiaDisplayHandle(name, out var display);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return display;
+ }
+
+ ///
+ /// This API lets caller retrieve the current global display configuration.
+ /// Note: User should dispose all returned PathInfo objects
+ ///
+ /// Array of path information
+ /// This operation is not supported.
+ /// Status.InvalidArgument: Invalid input parameter.
+ /// Status.DeviceBusy: ModeSet has not yet completed. Please wait and call it again.
+ /// A delegate callback throws an exception.
+ public static IPathInfo[] GetDisplayConfig()
+ {
+ var getDisplayConfig = DelegateFactory.GetDelegate();
+ uint allAvailable = 0;
+ var status = getDisplayConfig(ref allAvailable, ValueTypeArray.Null);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ if (allAvailable == 0)
+ {
+ return new IPathInfo[0];
+ }
+
+ foreach (var acceptType in getDisplayConfig.Accepts())
+ {
+ var count = allAvailable;
+ var instances = acceptType.Instantiate().Repeat((int) allAvailable);
+
+ using (var pathInfos = ValueTypeArray.FromArray(instances, acceptType))
+ {
+ status = getDisplayConfig(ref count, pathInfos);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ instances = pathInfos.ToArray((int) count, acceptType);
+ }
+
+ if (instances.Length <= 0)
+ {
+ return new IPathInfo[0];
+ }
+
+ // After allocation, we should make sure to dispose objects
+ // In this case however, the responsibility is on the user shoulders
+ instances = instances.AllocateAll().ToArray();
+
+ using (var pathInfos = ValueTypeArray.FromArray(instances, acceptType))
+ {
+ status = getDisplayConfig(ref count, pathInfos);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return pathInfos.ToArray((int) count, acceptType);
+ }
+ }
+
+ throw new NVIDIANotSupportedException("This operation is not supported.");
+ }
+
+ ///
+ /// Gets the build title of the Driver Settings Database for a display
+ ///
+ /// The display handle to get DRS build title.
+ /// The DRS build title.
+ public static string GetDisplayDriverBuildTitle(DisplayHandle displayHandle)
+ {
+ var status =
+ DelegateFactory.GetDelegate()(displayHandle,
+ out var name);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return name.Value;
+ }
+
+ ///
+ /// This function retrieves the available driver memory footprint for the GPU associated with a display.
+ ///
+ /// Handle of the display for which the memory information of its GPU is to be extracted.
+ /// The memory footprint available in the driver.
+ /// This operation is not supported.
+ /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found.
+ /// A delegate callback throws an exception.
+ public static IDisplayDriverMemoryInfo GetDisplayDriverMemoryInfo(DisplayHandle displayHandle)
+ {
+ var getMemoryInfo = DelegateFactory.GetDelegate();
+
+ foreach (var acceptType in getMemoryInfo.Accepts())
+ {
+ var instance = acceptType.Instantiate();
+
+ using (var displayDriverMemoryInfo = ValueTypeReference.FromValueType(instance, acceptType))
+ {
+ var status = getMemoryInfo(displayHandle, displayDriverMemoryInfo);
+
+ if (status == Status.IncompatibleStructureVersion)
+ {
+ continue;
+ }
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return displayDriverMemoryInfo.ToValueType(acceptType);
+ }
+ }
+
+ throw new NVIDIANotSupportedException("This operation is not supported.");
+ }
+
+ ///
+ /// This API retrieves the Display Id of a given display by display name. The display must be active to retrieve the
+ /// displayId. In the case of clone mode or Surround gaming, the primary or top-left display will be returned.
+ ///
+ /// Name of display (Eg: "\\DISPLAY1" to retrieve the displayId for.
+ /// Display ID of the requested display.
+ /// Status.InvalidArgument: One or more args passed in are invalid.
+ /// Status.ApiNotInitialized: The NvAPI API needs to be initialized first
+ /// Status.NoImplementation: This entry-point not available
+ /// Status.Error: Miscellaneous error occurred
+ /// A delegate callback throws an exception.
+ public static uint GetDisplayIdByDisplayName(string displayName)
+ {
+ var getDisplayIdByDisplayName =
+ DelegateFactory.GetDelegate();
+ var status = getDisplayIdByDisplayName(displayName, out var display);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return display;
+ }
+
+ /// [PRIVATE]
+ ///
+ /// This API returns the current saturation level from the Digital Vibrance Control
+ ///
+ ///
+ /// The targeted display's handle.
+ ///
+ /// An instance of the PrivateDisplayDVCInfo structure containing requested information.
+ public static PrivateDisplayDVCInfo GetDVCInfo(DisplayHandle display)
+ {
+ var instance = typeof(PrivateDisplayDVCInfo).Instantiate();
+
+ using (var displayDVCInfoReference = ValueTypeReference.FromValueType(instance))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ display,
+ OutputId.Invalid,
+ displayDVCInfoReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return displayDVCInfoReference.ToValueType().GetValueOrDefault();
+ }
+ }
+
+ /// [PRIVATE]
+ ///
+ /// This API returns the current saturation level from the Digital Vibrance Control
+ ///
+ ///
+ /// The targeted display output id.
+ ///
+ /// An instance of the PrivateDisplayDVCInfo structure containing requested information.
+ public static PrivateDisplayDVCInfo GetDVCInfo(OutputId displayId)
+ {
+ var instance = typeof(PrivateDisplayDVCInfo).Instantiate();
+
+ using (var displayDVCInfoReference = ValueTypeReference.FromValueType(instance))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ DisplayHandle.DefaultHandle,
+ displayId,
+ displayDVCInfoReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return displayDVCInfoReference.ToValueType().GetValueOrDefault();
+ }
+ }
+
+ /// [PRIVATE]
+ ///
+ /// This API returns the current and the default saturation level from the Digital Vibrance Control.
+ /// The difference between this API and the 'GetDVCInfo()' includes the possibility to get the default
+ /// saturation level as well as to query under saturated configurations.
+ ///
+ ///
+ /// The targeted display's handle.
+ ///
+ /// An instance of the PrivateDisplayDVCInfoEx structure containing requested information.
+ public static PrivateDisplayDVCInfoEx GetDVCInfoEx(DisplayHandle display)
+ {
+ var instance = typeof(PrivateDisplayDVCInfoEx).Instantiate();
+
+ using (var displayDVCInfoReference = ValueTypeReference.FromValueType(instance))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ display,
+ OutputId.Invalid,
+ displayDVCInfoReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return displayDVCInfoReference.ToValueType().GetValueOrDefault();
+ }
+ }
+
+ /// [PRIVATE]
+ ///
+ /// This API returns the current and the default saturation level from the Digital Vibrance Control.
+ /// The difference between this API and the 'GetDVCInfo()' includes the possibility to get the default
+ /// saturation level as well as to query under saturated configurations.
+ ///
+ ///
+ /// The targeted display output id.
+ ///
+ /// An instance of the PrivateDisplayDVCInfoEx structure containing requested information.
+ public static PrivateDisplayDVCInfoEx GetDVCInfoEx(OutputId displayId)
+ {
+ var instance = typeof(PrivateDisplayDVCInfoEx).Instantiate();
+
+ using (var displayDVCInfoReference = ValueTypeReference.FromValueType(instance))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ DisplayHandle.DefaultHandle,
+ displayId,
+ displayDVCInfoReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return displayDVCInfoReference.ToValueType().GetValueOrDefault();
+ }
+ }
+
+ ///
+ /// This API returns the current info-frame data on the specified device (monitor).
+ ///
+ /// The display handle of the device to retrieve HDMI support information for.
+ /// The target display's output id, or to determine automatically.
+ /// An instance of a type implementing the interface.
+ public static IHDMISupportInfo GetHDMISupportInfo(DisplayHandle displayHandle, OutputId outputId = OutputId.Invalid)
+ {
+ var getHDMISupportInfo = DelegateFactory.GetDelegate();
+
+ foreach (var acceptType in getHDMISupportInfo.Accepts())
+ {
+ var instance = acceptType.Instantiate();
+
+ using (var supportInfoReference = ValueTypeReference.FromValueType(instance, acceptType))
+ {
+ var status = getHDMISupportInfo(displayHandle, (uint)outputId, supportInfoReference);
+
+ if (status == Status.IncompatibleStructureVersion)
+ {
+ continue;
+ }
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return supportInfoReference.ToValueType(acceptType);
+ }
+ }
+
+ throw new NVIDIANotSupportedException("This operation is not supported.");
+ }
+
+ ///
+ /// This API returns the current info-frame data on the specified device (monitor).
+ ///
+ /// The display id of the device to retrieve HDMI support information for.
+ /// An instance of a type implementing the interface.
+ public static IHDMISupportInfo GetHDMISupportInfo(uint displayId)
+ {
+ var getHDMISupportInfo = DelegateFactory.GetDelegate();
+
+ foreach (var acceptType in getHDMISupportInfo.Accepts())
+ {
+ var instance = acceptType.Instantiate();
+
+ using (var supportInfoReference = ValueTypeReference.FromValueType(instance, acceptType))
+ {
+ var status = getHDMISupportInfo(DisplayHandle.DefaultHandle, displayId, supportInfoReference);
+
+ if (status == Status.IncompatibleStructureVersion)
+ {
+ continue;
+ }
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return supportInfoReference.ToValueType(acceptType);
+ }
+ }
+
+ throw new NVIDIANotSupportedException("This operation is not supported.");
+ }
+
+ /// [PRIVATE]
+ ///
+ /// This API returns the current default HUE angle
+ ///
+ ///
+ /// The targeted display's handle.
+ ///
+ /// An instance of the PrivateDisplayHUEInfo structure containing requested information.
+ public static PrivateDisplayHUEInfo GetHUEInfo(DisplayHandle display)
+ {
+ var instance = typeof(PrivateDisplayHUEInfo).Instantiate();
+
+ using (var displayDVCInfoReference = ValueTypeReference.FromValueType(instance))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ display,
+ OutputId.Invalid,
+ displayDVCInfoReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return displayDVCInfoReference.ToValueType().GetValueOrDefault();
+ }
+ }
+
+ /// [PRIVATE]
+ ///
+ /// This API returns the current and default HUE angle
+ ///
+ ///
+ /// The targeted display output id.
+ ///
+ /// An instance of the PrivateDisplayHUEInfo structure containing requested information.
+ public static PrivateDisplayHUEInfo GetHUEInfo(OutputId displayId)
+ {
+ var instance = typeof(PrivateDisplayHUEInfo).Instantiate();
+
+ using (var displayDVCInfoReference = ValueTypeReference.FromValueType(instance))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ DisplayHandle.DefaultHandle,
+ displayId,
+ displayDVCInfoReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return displayDVCInfoReference.ToValueType().GetValueOrDefault();
+ }
+ }
+
+ ///
+ /// This API returns all the monitor capabilities.
+ ///
+ /// The target display id.
+ /// The type of capabilities requested.
+ /// An instance of .
+ public static MonitorCapabilities? GetMonitorCapabilities(
+ uint displayId,
+ MonitorCapabilitiesType capabilitiesType)
+ {
+ var instance = new MonitorCapabilities(capabilitiesType);
+
+ using (var monitorCapReference = ValueTypeReference.FromValueType(instance))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ displayId,
+ monitorCapReference
+ );
+
+ if (status == Status.Error)
+ {
+ return null;
+ }
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+
+ instance = monitorCapReference.ToValueType().GetValueOrDefault();
+
+ if (!instance.IsValid)
+ {
+ return null;
+ }
+
+ return instance;
+ }
+ }
+
+ ///
+ /// This API returns all the color formats and bit depth values supported by a given display port monitor.
+ ///
+ /// The target display id.
+ /// A list of instances.
+ public static MonitorColorData[] GetMonitorColorCapabilities(uint displayId)
+ {
+ var getMonitorColorCapabilities =
+ DelegateFactory.GetDelegate();
+ var count = 0u;
+
+ var status = getMonitorColorCapabilities(displayId, ValueTypeArray.Null, ref count);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ if (count == 0)
+ {
+ return new MonitorColorData[0];
+ }
+
+ var array = typeof(MonitorColorData).Instantiate().Repeat((int) count);
+
+ using (var monitorCapsReference = ValueTypeArray.FromArray(array))
+ {
+ status = getMonitorColorCapabilities(displayId, monitorCapsReference, ref count);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return monitorCapsReference.ToArray((int) count);
+
+ }
+ }
+
+ ///
+ /// This API returns the Display ID of the GDI Primary.
+ ///
+ /// Display ID of the GDI Primary.
+ /// Status.NvidiaDeviceNotFound: GDI Primary not on an NVIDIA GPU.
+ /// Status.ApiNotInitialized: The NvAPI API needs to be initialized first
+ /// Status.NoImplementation: This entry-point not available
+ /// Status.Error: Miscellaneous error occurred
+ /// A delegate callback throws an exception.
+ public static uint GetGDIPrimaryDisplayId()
+ {
+ var getGDIPrimaryDisplay =
+ DelegateFactory.GetDelegate();
+ var status = getGDIPrimaryDisplay(out var displayId);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return displayId;
+ }
+
+ ///
+ /// This API gets High Dynamic Range (HDR) capabilities of the display.
+ ///
+ /// The targeted display id.
+ ///
+ /// A boolean value indicating if the EDID HDR parameters should be expanded (true) or the actual current HDR
+ /// parameters should be reported (false).
+ ///
+ /// HDR capabilities of the display
+ public static HDRCapabilitiesV1 GetHDRCapabilities(uint displayId, bool driverExpandDefaultHDRParameters)
+ {
+ var hdrCapabilities = new HDRCapabilitiesV1(driverExpandDefaultHDRParameters);
+
+ using (var hdrCapabilitiesReference = ValueTypeReference.FromValueType(hdrCapabilities))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ displayId,
+ hdrCapabilitiesReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return hdrCapabilitiesReference.ToValueType().GetValueOrDefault();
+ }
+ }
+
+ ///
+ /// This API queries current state of one of the various scan-out composition parameters on the specified display.
+ ///
+ /// Combined physical display and GPU identifier of the display to query the configuration.
+ /// Scan-out composition parameter to by queried.
+ /// Additional container containing the returning data associated with the specified parameter.
+ /// Scan-out composition parameter value.
+ public static ScanOutCompositionParameterValue GetScanOutCompositionParameter(
+ uint displayId,
+ ScanOutCompositionParameter parameter,
+ out float container)
+ {
+ var status = DelegateFactory.GetDelegate()(
+ displayId,
+ parameter,
+ out var parameterValue,
+ out container
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return parameterValue;
+ }
+
+ ///
+ /// This API queries the desktop and scan-out portion of the specified display.
+ ///
+ /// Combined physical display and GPU identifier of the display to query the configuration.
+ /// Desktop area to displayId mapping information.
+ public static ScanOutInformationV1 GetScanOutConfiguration(uint displayId)
+ {
+ var instance = typeof(ScanOutInformationV1).Instantiate();
+
+ using (var scanOutInformationReference = ValueTypeReference.FromValueType(instance))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ displayId,
+ scanOutInformationReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return scanOutInformationReference.ToValueType().GetValueOrDefault();
+ }
+ }
+
+ ///
+ /// This API queries the desktop and scan-out portion of the specified display.
+ ///
+ /// Combined physical display and GPU identifier of the display to query the configuration.
+ /// Desktop area of the display in desktop coordinates.
+ /// Scan-out area of the display relative to desktopRect.
+ public static void GetScanOutConfiguration(
+ uint displayId,
+ out Rectangle desktopRectangle,
+ out Rectangle scanOutRectangle)
+ {
+ var instance1 = typeof(Rectangle).Instantiate();
+ var instance2 = typeof(Rectangle).Instantiate();
+
+ using (var desktopRectangleReference = ValueTypeReference.FromValueType(instance1))
+ {
+ using (var scanOutRectangleReference = ValueTypeReference.FromValueType(instance2))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ displayId,
+ desktopRectangleReference,
+ scanOutRectangleReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ desktopRectangle = desktopRectangleReference.ToValueType().GetValueOrDefault();
+ scanOutRectangle = scanOutRectangleReference.ToValueType().GetValueOrDefault();
+ }
+ }
+ }
+
+ ///
+ /// This API queries current state of the intensity feature on the specified display.
+ ///
+ /// Combined physical display and GPU identifier of the display to query the configuration.
+ /// Intensity state data.
+ public static ScanOutIntensityStateV1 GetScanOutIntensityState(uint displayId)
+ {
+ var instance = typeof(ScanOutIntensityStateV1).Instantiate();
+
+ using (var scanOutIntensityReference = ValueTypeReference.FromValueType(instance))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ displayId,
+ scanOutIntensityReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return scanOutIntensityReference.ToValueType().GetValueOrDefault();
+ }
+ }
+
+ ///
+ /// This API queries current state of the warping feature on the specified display.
+ ///
+ /// Combined physical display and GPU identifier of the display to query the configuration.
+ /// The warping state data.
+ public static ScanOutWarpingStateV1 GetScanOutWarpingState(uint displayId)
+ {
+ var instance = typeof(ScanOutWarpingStateV1).Instantiate();
+
+ using (var scanOutWarpingReference = ValueTypeReference.FromValueType(instance))
+ {
+ var status = DelegateFactory.GetDelegate()(
+ displayId,
+ scanOutWarpingReference
+ );
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ return scanOutWarpingReference.ToValueType().GetValueOrDefault();
+ }
+ }
+
+ ///
+ /// This API lets caller enumerate all the supported NVIDIA display views - nView and DualView modes.
+ ///
+ ///
+ /// NVIDIA Display selection. It can be DisplayHandle.DefaultHandle or a handle enumerated from
+ /// DisplayApi.EnumNVidiaDisplayHandle().
+ ///
+ /// Array of supported views.
+ /// This operation is not supported.
+ /// Status.Error: Miscellaneous error occurred
+ /// Status.InvalidArgument: Invalid input parameter.
+ /// A delegate callback throws an exception.
+ public static TargetViewMode[] GetSupportedViews(DisplayHandle display)
+ {
+ var getSupportedViews = DelegateFactory.GetDelegate();
+ uint allAvailable = 0;
+ var status = getSupportedViews(display, ValueTypeArray.Null, ref allAvailable);
+
+ if (status != Status.Ok)
+ {
+ throw new NVIDIAApiException(status);
+ }
+
+ if (allAvailable == 0)
+ {
+ return new TargetViewMode[0];
+ }
+
+ if (!getSupportedViews.Accepts().Contains(typeof(TargetViewMode)))
+ {
+ throw new NVIDIANotSupportedException("This operation is not supported.");
+ }
+
+ using (
+ var viewModes =
+ ValueTypeArray.FromArray(TargetViewMode.Standard.Repeat((int) allAvailable).Cast