diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj
index aed9d6f..1c5b1c5 100644
--- a/ColorControl/ColorControl.csproj
+++ b/ColorControl/ColorControl.csproj
@@ -18,8 +18,8 @@
Maassoft
Maassoft
0
- 5.2.0.0
- 5.2.0.0
+ 5.3.0.0
+ 5.3.0.0
false
true
false
diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs
index 70f2a95..f561b11 100644
--- a/ColorControl/MainForm.Designer.cs
+++ b/ColorControl/MainForm.Designer.cs
@@ -1693,8 +1693,9 @@
this.chkDitheringEnabled.Size = new System.Drawing.Size(120, 19);
this.chkDitheringEnabled.TabIndex = 3;
this.chkDitheringEnabled.Text = "Dithering enabled";
+ this.chkDitheringEnabled.ThreeState = true;
this.chkDitheringEnabled.UseVisualStyleBackColor = true;
- this.chkDitheringEnabled.CheckedChanged += new System.EventHandler(this.chkDitheringEnabled_CheckedChanged);
+ this.chkDitheringEnabled.CheckStateChanged += new System.EventHandler(this.chkDitheringEnabled_CheckStateChanged);
//
// pbGradient
//
diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs
index ab78e97..9f548d7 100644
--- a/ColorControl/MainForm.cs
+++ b/ColorControl/MainForm.cs
@@ -55,6 +55,7 @@ namespace ColorControl
private FileVersionInfo _currentVersionInfo;
private bool _checkedForUpdates = false;
private string _updateHtmlUrl;
+ private bool _updatingDitherSettings;
private LgGameBar _gameBarForm;
@@ -1350,6 +1351,10 @@ namespace ColorControl
{
InitOptionsTab();
}
+ else if (tcMain.SelectedTab == tabNVIDIA)
+ {
+ UpdateDisplayInfoItems();
+ }
}
private void InitLgTab()
@@ -1371,39 +1376,42 @@ namespace ColorControl
grpNvidiaOptions.Visible = _nvService != null;
if (grpNvidiaOptions.Visible)
{
- var firstTime = cbxDitheringBitDepth.Items.Count == 0;
-
- if (firstTime)
+ if (cbxDitheringBitDepth.Items.Count == 0)
{
cbxDitheringBitDepth.Items.AddRange(Utils.GetDescriptions().ToArray());
cbxDitheringMode.Items.AddRange(Utils.GetDescriptions().ToArray());
- }
-
- var preset = _nvService.GetLastAppliedPreset() ?? GetSelectedNvPreset();
- if (firstTime || preset != null)
- {
- var ditheringEnabled = true;
- int ditherBitsIndex;
- int ditherModeIndex;
- if (preset == null)
- {
- var hdrEnabled = _nvService.IsHDREnabled();
- var minBits = _nvService.GetPresets().Where(p => p.HDREnabled == hdrEnabled && p.applyDithering).DefaultIfEmpty().Min(p => p?.ditheringBits);
- ditherBitsIndex = minBits.HasValue ? (int)minBits.Value : (int)(hdrEnabled ? NvDitherBits.Bits8 : NvDitherBits.Bits6);
- ditherModeIndex = (int)NvDitherMode.Temporal;
- }
- else
- {
- ditheringEnabled = preset.ditheringEnabled;
- ditherBitsIndex = (int)preset.ditheringBits;
- ditherModeIndex = (int)preset.ditheringMode;
- }
-
- chkDitheringEnabled.Checked = ditheringEnabled;
- cbxDitheringBitDepth.SelectedIndex = ditherBitsIndex;
- cbxDitheringMode.SelectedIndex = ditherModeIndex;
FillGradient();
}
+
+ UpdateDitherSettings();
+ }
+ }
+
+ private void UpdateDitherSettings()
+ {
+ var ditherInfo = _nvService.GetDithering();
+
+ if (ditherInfo.state == -1)
+ {
+ MessageForms.ErrorOk("Error retrieving dithering settings. See log for details.");
+ return;
+ }
+
+ var state = (NvDitherState)ditherInfo.state;
+
+ _updatingDitherSettings = true;
+ try
+ {
+ chkDitheringEnabled.CheckState = state switch { NvDitherState.Enabled => CheckState.Checked, NvDitherState.Disabled => CheckState.Unchecked, _ => CheckState.Indeterminate };
+ cbxDitheringBitDepth.SelectedIndex = ditherInfo.bits;
+ cbxDitheringMode.SelectedIndex = ditherInfo.mode;
+
+ cbxDitheringBitDepth.Enabled = state == NvDitherState.Enabled;
+ cbxDitheringMode.Enabled = state == NvDitherState.Enabled;
+ }
+ finally
+ {
+ _updatingDitherSettings = false;
}
}
@@ -2061,17 +2069,21 @@ Do you want to continue?";
}
}
- private void chkDitheringEnabled_CheckedChanged(object sender, EventArgs e)
- {
- ApplyDitheringOptions();
- }
-
private void ApplyDitheringOptions()
{
+ if (_updatingDitherSettings)
+ {
+ return;
+ }
+
+ var state = chkDitheringEnabled.CheckState switch { CheckState.Checked => NvDitherState.Enabled, CheckState.Unchecked => NvDitherState.Disabled, _ => NvDitherState.Auto };
var bitDepth = cbxDitheringBitDepth.SelectedIndex;
var mode = cbxDitheringMode.SelectedIndex;
- _nvService.SetDithering(chkDitheringEnabled.Checked, (uint)bitDepth, (uint)(mode > -1 ? mode : (int)NvDitherMode.Temporal));
+ if (_nvService.SetDithering(state, (uint)bitDepth, (uint)(mode > -1 ? mode : (int)NvDitherMode.Temporal)) && state == NvDitherState.Auto)
+ {
+ UpdateDitherSettings();
+ }
}
private void cbxDitheringBitDepth_SelectedIndexChanged(object sender, EventArgs e)
@@ -3034,5 +3046,13 @@ The InStart and Software Update items are now visible under the Expert-button."
{
ResumeLayout(true);
}
+
+ private void chkDitheringEnabled_CheckStateChanged(object sender, EventArgs e)
+ {
+ cbxDitheringBitDepth.Enabled = chkDitheringEnabled.CheckState == CheckState.Checked;
+ cbxDitheringMode.Enabled = chkDitheringEnabled.CheckState == CheckState.Checked;
+
+ ApplyDitheringOptions();
+ }
}
}
\ No newline at end of file
diff --git a/ColorControl/NvService.cs b/ColorControl/NvService.cs
index ff27218..3e4dfea 100644
--- a/ColorControl/NvService.cs
+++ b/ColorControl/NvService.cs
@@ -13,6 +13,16 @@ using System.Windows.Forms;
namespace ColorControl
{
+ enum NvDitherState
+ {
+ [Description("Auto")]
+ Auto = 0,
+ [Description("Enabled")]
+ Enabled = 1,
+ [Description("Disabled")]
+ Disabled = 2
+ }
+
enum NvDitherBits
{
[Description("6-bit")]
@@ -45,7 +55,7 @@ namespace ColorControl
PreserveSig = true)]
private static extern IntPtr NvAPI64_QueryInterface(uint interfaceId);
- public delegate long NvAPI_Disp_SetDitherControl(
+ public delegate int NvAPI_Disp_SetDitherControl(
[In] PhysicalGPUHandle physicalGpu,
[In] uint OutputId,
[In] uint state,
@@ -53,18 +63,19 @@ namespace ColorControl
[In] uint mode
);
- public delegate long NvAPI_Disp_GetDitherControl(
- [In] PhysicalGPUHandle physicalGpu,
- [In] uint OutputId,
- [In] IntPtr ditherControl);
+ public delegate int NvAPI_Disp_GetDitherControl(
+ [In] uint DisplayId,
+ [MarshalAs(UnmanagedType.Struct)] ref NV_GPU_DITHER_CONTROL_V1 ditherControl);
[StructLayout(LayoutKind.Sequential)]
public struct NV_GPU_DITHER_CONTROL_V1
{
- public int version;
- public uint state;
- public uint bits;
- public uint mode;
+ public uint version;
+ public int state;
+ public int bits;
+ public int mode;
+ public uint bitsCaps;
+ public uint modeCaps;
};
private Display _currentDisplay;
@@ -233,7 +244,7 @@ namespace ColorControl
if (preset.applyDithering)
{
- if (!SetDithering(preset.ditheringEnabled, preset: preset))
+ if (!SetDithering(preset.ditheringEnabled ? NvDitherState.Enabled : NvDitherState.Disabled, preset: preset))
{
result = false;
}
@@ -304,7 +315,7 @@ namespace ColorControl
//}
}
- public bool SetDithering(bool enabled, uint bits = 1, uint mode = 4, NvPreset preset = null)
+ public bool SetDithering(NvDitherState state, uint bits = 1, uint mode = 4, NvPreset preset = null)
{
var result = true;
@@ -317,14 +328,20 @@ namespace ColorControl
var gpuHandle = displayDevice.PhysicalGPU.Handle;
var displayId = displayDevice.DisplayId;
-
- if (preset != null)
+
+ if (state == NvDitherState.Auto)
+ {
+ // These seem to be ignored in Auto-state
+ bits = 0;
+ mode = 0;
+ }
+ else if (preset != null)
{
bits = preset.ditheringBits;
mode = preset.ditheringMode;
}
- var resultValue = delegateValue(gpuHandle, displayId, (uint)(enabled ? 1 : 2), bits, mode);
+ var resultValue = delegateValue(gpuHandle, displayId, (uint)state, bits, mode);
if (resultValue != 0)
{
Logger.Error($"Could not set dithering because NvAPI_Disp_SetDitherControl returned a non-zero return code: {resultValue}");
@@ -340,40 +357,31 @@ namespace ColorControl
return result;
}
- public bool GetDithering()
+ public NV_GPU_DITHER_CONTROL_V1 GetDithering()
{
- // Requires elevation, too bad :(
- //Utils.GetRegistryKeyValue(@"SYSTEM\CurrentControlSet\Services\nvlddmkm\State\DisplayDatabase", "DitherRegistryKey");
+ var dither = new NV_GPU_DITHER_CONTROL_V1 { version = 0x10018 };
- /*
var ptr = NvAPI64_QueryInterface(0x932AC8FB);
if (ptr != IntPtr.Zero)
{
var delegateValue = Marshal.GetDelegateForFunctionPointer(ptr, typeof(NvAPI_Disp_GetDitherControl)) as NvAPI_Disp_GetDitherControl;
var displayDevice = GetCurrentDisplay().DisplayDevice;
-
- var gpuHandle = displayDevice.PhysicalGPU.Handle;
var displayId = displayDevice.DisplayId;
- NV_GPU_DITHER_CONTROL_V1 info = new NV_GPU_DITHER_CONTROL_V1();
- info.version = 1;
- var size = Marshal.SizeOf(info.GetType());
- IntPtr bla = Marshal.AllocHGlobal(size);
- Marshal.StructureToPtr(info, bla, false);
-
- // Does not work yet...What is the exact interface of NvAPI_Disp_GetDitherControl?
-
- var result = delegateValue(gpuHandle, displayId, bla);
+ var result = delegateValue(displayId, ref dither);
if (result != 0)
{
Logger.Error($"Could not get dithering because NvAPI_Disp_GetDitherControl returned a non-zero return code: {result}");
+ dither.state = -1;
}
-
- return info.state == 1;
}
- */
- return false;
+ else
+ {
+ dither.state = -2;
+ }
+
+ return dither;
}
public bool SetRefreshRate(uint refreshRate)
@@ -458,16 +466,27 @@ namespace ColorControl
values.Add($"{refreshRate}Hz");
- var lastPreset = GetLastAppliedPreset();
- if (lastPreset != null)
+ var ditherInfo = GetDithering();
+
+ string dithering;
+ if (ditherInfo.state == -1)
{
- values.Add(lastPreset.GetDitheringDescription());
+ dithering = "Error";
}
else
{
- values.Add(string.Empty);
+ var state = (NvDitherState)ditherInfo.state;
+ dithering = state switch { NvDitherState.Disabled => "Disabled", NvDitherState.Auto => "Auto: ", _ => string.Empty };
+ if (state is NvDitherState.Enabled or NvDitherState.Auto)
+ {
+ var ditherBitsDescription = ((NvDitherBits)ditherInfo.bits).GetDescription();
+ var ditherModeDescription = ((NvDitherMode)ditherInfo.mode).GetDescription();
+ dithering = string.Format("{0}{1} {2}", dithering, ditherBitsDescription, ditherModeDescription);
+ }
}
+ values.Add(dithering);
+
var hdrEnabled = IsHDREnabled();
values.Add(hdrEnabled ? "Yes" : "No");