This commit is contained in:
Kamil Trzciński 2023-02-09 11:03:41 +01:00
parent 70c58dd568
commit c87658dbb6
5 changed files with 187 additions and 32 deletions

View file

@ -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");

View file

@ -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

View file

@ -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<int> PixelClocks { get; } = new List<int>();
public List<int> RefreshRates { get; } = new List<int>();
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<ADLDisplayModeInfo> 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<ADLDisplayModeInfo> 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)
{

View file

@ -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);
}

View file

@ -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);