From c87658dbb6be2ad7e757816eb75e4f759922364c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Trzci=C5=84ski?= Date: Thu, 9 Feb 2023 11:03:41 +0100 Subject: [PATCH] WIP --- PowerControl/Controller.cs | 8 ++ PowerControl/Helpers/AMD/ADL.cs | 11 ++ PowerControl/Helpers/AMD/ModeTiming.cs | 175 +++++++++++++++++++++---- PowerControl/Options/RefreshRate.cs | 12 +- PowerControl/Options/Resolution.cs | 13 +- 5 files changed, 187 insertions(+), 32 deletions(-) diff --git a/PowerControl/Controller.cs b/PowerControl/Controller.cs index ab42857..86a642e 100644 --- a/PowerControl/Controller.cs +++ b/PowerControl/Controller.cs @@ -69,6 +69,14 @@ namespace PowerControl rootMenu.VisibleChanged += delegate { updateOSD(); }; contextMenu.Items.Add(new ToolStripSeparator()); + var installResItem = contextMenu.Items.Add("&Install Resolutions"); + installResItem.Click += delegate { Helpers.AMD.ModeTiming.InstallAll(); }; + + var uninstallResItem = contextMenu.Items.Add("&Uninstall Resolutions"); + uninstallResItem.Click += delegate { Helpers.AMD.ModeTiming.UninstallAll(); }; + + contextMenu.Items.Add(new ToolStripSeparator()); + if (startupManager.IsAvailable) { var startupItem = new ToolStripMenuItem("Run On Startup"); diff --git a/PowerControl/Helpers/AMD/ADL.cs b/PowerControl/Helpers/AMD/ADL.cs index 2706eff..b27704e 100644 --- a/PowerControl/Helpers/AMD/ADL.cs +++ b/PowerControl/Helpers/AMD/ADL.cs @@ -272,6 +272,14 @@ namespace PowerControl.Helpers.AMD internal const int ADL_DL_MODETIMING_STANDARD_DRIVER_DEFAULT = 0x00000010; internal const int ADL_DL_MODETIMING_STANDARD_GTF = 0x00000002; + internal const int ADL_DL_TIMINGFLAG_DOUBLE_SCAN = 0x0001; + //sTimingFlags is set when the mode is INTERLACED, if not PROGRESSIVE + internal const int ADL_DL_TIMINGFLAG_INTERLACED = 0x0002; + //sTimingFlags is set when the Horizontal Sync is POSITIVE, if not NEGATIVE + internal const int ADL_DL_TIMINGFLAG_H_SYNC_POLARITY = 0x0004; + //sTimingFlags is set when the Vertical Sync is POSITIVE, if not NEGATIVE + internal const int ADL_DL_TIMINGFLAG_V_SYNC_POLARITY = 0x0008; + #endregion Internal Constant #region Internal Constant @@ -360,6 +368,9 @@ namespace PowerControl.Helpers.AMD [DllImport(Atiadlxx_FileName)] internal static extern int ADL2_Display_ModeTimingOverrideList_Get(IntPtr context, int adapterIndex, int displayIndex, int maxOverrides, out ADLDisplayModeInfoArray modes, out int modesCount); + + [DllImport(Atiadlxx_FileName)] + internal static extern int ADL_Flush_Driver_Data(int adapterIndex); #endregion DLLImport #region ADL_Main_Memory_Alloc diff --git a/PowerControl/Helpers/AMD/ModeTiming.cs b/PowerControl/Helpers/AMD/ModeTiming.cs index a0c9912..d4ec067 100644 --- a/PowerControl/Helpers/AMD/ModeTiming.cs +++ b/PowerControl/Helpers/AMD/ModeTiming.cs @@ -4,29 +4,140 @@ namespace PowerControl.Helpers.AMD { internal class ModeTiming { - internal readonly static ADLDisplayModeInfo Mode1280x800p40 = new ADLDisplayModeInfo() + public struct DetailedTiming { - iPelsHeight = 1280, - iPelsWidth = 800, - iPossibleStandard = 43, - iRefreshRate = 40, - iTimingStandard = 1, - sDetailedTiming = new ADLDetailedTiming() + public ADLDetailedTiming Timing { get; set; } + public List PixelClocks { get; } = new List(); + public List RefreshRates { get; } = new List(); + + public DetailedTiming( + short hDisplay, short hFront, short hSync, short hBack, + short vDisplay, short vFront, short vSync, short vBack, + short timingFlags = ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY, + short pixelClock = 0) { - iSize = 96, - sHDisplay = 800, - sHSyncStart = 848, - sHSyncWidth = 80, - sHTotal = 1056, - sPixelClock = 5525, - sTimingFlags = 4100, - sVDisplay = 1280, - sVSyncStart = 1283, - sVSyncWidth = 10, - sVTotal = 1312 + Timing = new ADLDetailedTiming() + { + iSize = 96, + sPixelClock = pixelClock, + sTimingFlags = timingFlags, + sHDisplay = hDisplay, + sHSyncStart = (short)(hDisplay + hFront), + sHSyncWidth = hSync, + sHTotal = (short)(hDisplay + hFront + hSync + hBack), + sVDisplay = vDisplay, + sVSyncStart = (short)(vDisplay + vFront), + sVSyncWidth = vSync, + sVTotal = (short)(vDisplay + vFront + vSync + vBack), + }; + } + + public IEnumerable EachModeInfo() + { + foreach (var refreshRate in RefreshRates) + // foreach (var pixelClock in PixelClocks) + { + var pixelClock = (short)Math.Ceiling((double)Timing.sHTotal * Timing.sVTotal * refreshRate / 10000); + // var refreshRate = Math.Round((double)pixelClock / (Timing.sHTotal * Timing.sVTotal)); + + ADLDisplayModeInfo modeInfo = new ADLDisplayModeInfo() + { + iPelsHeight = Timing.sVDisplay, + iPelsWidth = Timing.sHDisplay, + iPossibleStandard = 0, + iRefreshRate = (short)refreshRate, + iTimingStandard = ADL.ADL_DL_MODETIMING_STANDARD_CUSTOM, + sDetailedTiming = Timing, + }; + + modeInfo.sDetailedTiming.sPixelClock = (short)pixelClock; + + yield return modeInfo; + } } }; + public static readonly DetailedTiming[] AllTimings = new DetailedTiming[] { + new DetailedTiming(400, 32, 20, 20, 640, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48, 50, 55, 60 } + }, + new DetailedTiming(640, 32, 20, 20, 1024, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48, 50, 55, 60 } + }, + new DetailedTiming(540, 32, 20, 20, 960, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48, 50, 55, 60 } + }, + new DetailedTiming(544, 32, 20, 20, 960, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48, 50, 55, 60 } + }, + new DetailedTiming(600, 32, 20, 20, 800, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48, 50, 55, 60 } + }, + new DetailedTiming(600, 32, 20, 20, 960, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48, 50, 55, 60 } + }, + new DetailedTiming(680, 32, 20, 20, 1088, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48, 50, 55, 60 } + }, + new DetailedTiming(576, 32, 20, 20, 1024, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48, 50, 55, 60 } + }, + new DetailedTiming(768, 32, 20, 20, 1024, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48, 50, 55, 60 } + }, + new DetailedTiming(720, 32, 20, 20, 1152, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48, 50, 55, 60 } + }, + new DetailedTiming(720, 112, 20, 20, 1280, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48, 50, 55, 60 } + }, + new DetailedTiming(800, 32, 20, 20, 1280, 16, 2, 26, ADL.ADL_DL_TIMINGFLAG_H_SYNC_POLARITY | ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 30, 35, 40, 45, 48 } + }, + new DetailedTiming(800, 56, 80, 136, 1280, 3, 10, 27, ADL.ADL_DL_TIMINGFLAG_V_SYNC_POLARITY) { + RefreshRates = { 50, 55 } + } + }; + + internal static IEnumerable AllModeInfos() + { + foreach (var timing in AllTimings) + { + foreach (var modeInfo in timing.EachModeInfo()) + yield return modeInfo; + } + } + + internal static void InstallAll() + { + var modeInfos = AllModeInfos()?.ToArray(); + if (modeInfos is null) + return; + + ADLDisplayModeInfo lastModeInfo = modeInfos.LastOrDefault(); + + foreach (var modeInfo in modeInfos) + { + AddTiming(modeInfo, modeInfo.Equals(lastModeInfo)); + } + } + + internal static void UninstallAll() + { + var modes = GetAllModes()?.ToArray(); + if (modes is null) + return; + + ADLDisplayModeInfo lastMode = modes.LastOrDefault(); + + foreach (var mode in modes) + { + var newMode = mode; + newMode.iTimingStandard = Helpers.AMD.ADL.ADL_DL_MODETIMING_STANDARD_DRIVER_DEFAULT; + AddTiming(newMode, mode.Equals(lastMode)); + } + } + internal static bool AddAndSetTiming(ADLDisplayModeX2 displayMode) { RemoveTiming(displayMode); @@ -55,22 +166,28 @@ namespace PowerControl.Helpers.AMD internal static bool RemoveTiming(ADLDisplayModeX2 displayMode) { - displayMode.TimingStandard = Helpers.AMD.ADL.ADL_DL_MODETIMING_STANDARD_DRIVER_DEFAULT; + displayMode.TimingStandard = ADL.ADL_DL_MODETIMING_STANDARD_DRIVER_DEFAULT; return AddTiming(displayMode); } - internal static bool AddTiming(ADLDisplayModeInfo displayMode) + internal static bool AddTiming(ADLDisplayModeInfo displayMode, bool forceUpdate = true) { return Helpers.AMD.ADLContext.WithSafe((context) => { int res = ADL.ADL2_Display_ModeTimingOverride_Set( - context.Context, - Helpers.AMD.ADL.ADL_DEFAULT_ADAPTER, - 0, - ref displayMode, - 1 + context.Context, + Helpers.AMD.ADL.ADL_DEFAULT_ADAPTER, + 0, + ref displayMode, + forceUpdate ? 1 : 0 ); + CommonHelpers.Log.TraceLine("{0}x{1}p{2} => PCLK: {3} => {4} (forceUpdate={5}, remove={6})", + displayMode.sDetailedTiming.sHDisplay, displayMode.sDetailedTiming.sVDisplay, + displayMode.iRefreshRate, displayMode.sDetailedTiming.sPixelClock, + res == 0 ? "OK" : "FAIL", + forceUpdate, displayMode.iTimingStandard == ADL.ADL_DL_MODETIMING_STANDARD_DRIVER_DEFAULT); + return res == 0; }); } @@ -84,10 +201,10 @@ namespace PowerControl.Helpers.AMD return false; int res = ADL.ADL2_Display_ModeTimingOverrideX2_Get( - context.Context, - Helpers.AMD.ADL.ADL_DEFAULT_ADAPTER, - displays[0].DisplayID, - ref displayMode, out var modeInfOut); + context.Context, + Helpers.AMD.ADL.ADL_DEFAULT_ADAPTER, + displays[0].DisplayID, + ref displayMode, out var modeInfOut); if (res == 0) { diff --git a/PowerControl/Options/RefreshRate.cs b/PowerControl/Options/RefreshRate.cs index 7099ef5..7ade6c4 100644 --- a/PowerControl/Options/RefreshRate.cs +++ b/PowerControl/Options/RefreshRate.cs @@ -13,9 +13,15 @@ namespace PowerControl.Options ResetValue = () => { return DisplayResolutionController.GetRefreshRates().Max().ToString(); }, OptionsValues = delegate () { - return new string[] { "30", "35", "40", "45", "48", "50", "55", "60" }; + var refreshRates = DisplayResolutionController.GetRefreshRates().ToList(); + + var currentRefreshRate = DisplayResolutionController.GetRefreshRate(); + if (currentRefreshRate > 0 && !refreshRates.Contains(currentRefreshRate)) + { + refreshRates.Add(currentRefreshRate); + refreshRates.Sort(); + } - var refreshRates = DisplayResolutionController.GetRefreshRates(); if (refreshRates.Count() > 1) return refreshRates.Select(item => item.ToString()).ToArray(); return null; @@ -28,6 +34,7 @@ namespace PowerControl.Options { var selectedRefreshRate = int.Parse(selected); +#if USE_ADL2 if (ExternalHelpers.DisplayConfig.IsInternalConnected == true) { var currentResolution = DisplayResolutionController.GetResolution(); @@ -55,6 +62,7 @@ namespace PowerControl.Options }); } else +#endif { DisplayResolutionController.SetRefreshRate(selectedRefreshRate); } diff --git a/PowerControl/Options/Resolution.cs b/PowerControl/Options/Resolution.cs index 4bfc40f..a9e2ad5 100644 --- a/PowerControl/Options/Resolution.cs +++ b/PowerControl/Options/Resolution.cs @@ -18,9 +18,18 @@ namespace PowerControl.Options }, OptionsValues = delegate () { - var resolutions = DisplayResolutionController.GetAllResolutions(); + var resolutions = DisplayResolutionController.GetAllResolutions().ToList(); + + var currentResolution = DisplayResolutionController.GetResolution(); + if (currentResolution is not null && !resolutions.Contains(currentResolution.Value)) + { + resolutions.Add(currentResolution.Value); + resolutions.Sort(); + } + if (resolutions.Count() > 1) return resolutions.Select(item => item.ToString()).ToArray(); + return null; }, CurrentValue = delegate () @@ -33,6 +42,7 @@ namespace PowerControl.Options { var selectedResolution = new DisplayResolutionController.DisplayResolution(selected); +#if USE_ADL2 if (ExternalHelpers.DisplayConfig.IsInternalConnected == true) { ModeTiming.ReplaceTiming(new Helpers.AMD.ADLDisplayModeX2() @@ -43,6 +53,7 @@ namespace PowerControl.Options TimingStandard = Helpers.AMD.ADL.ADL_DL_MODETIMING_STANDARD_CVT, }); } +#endif DisplayResolutionController.SetResolution(selectedResolution);