PowerControl: Install custom resolutions (EDID) (experimental feature)

This commit is contained in:
Kamil Trzciński 2023-02-09 12:18:29 +01:00
parent fd93c051fa
commit 862d7afec5
7 changed files with 131 additions and 0 deletions

View file

@ -143,6 +143,30 @@ namespace PowerControl.Helpers.AMD
}
#endregion ADLDisplayInfo
[StructLayout(LayoutKind.Sequential)]
internal struct ADLDisplayEDIDData
{
internal int iSize;
internal int iFlag;
internal int iEDIDSize;
internal int iBlockIndex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)ADL.ADL_MAX_EDIDDATA_SIZE)]
internal byte[] cEDIDData;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
internal int[] iReserved;
};
[StructLayout(LayoutKind.Sequential)]
internal struct ADLDisplayEDIDDataX2
{
internal int iSize;
internal int iFlag;
internal int iEDIDSize;
internal int iIgnored;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)2 * ADL.ADL_MAX_EDIDDATA_SIZE)]
internal byte[] cEDIDData;
};
#region Radeon Image Sharpening
[StructLayout(LayoutKind.Sequential)]
internal struct ADL_RIS_SETTINGS
@ -192,6 +216,8 @@ namespace PowerControl.Helpers.AMD
internal const int ADL_MAX_GLSYNC_PORT_LEDS = 8;
/// <summary> Maximum number of ADLMOdes for the adapter </summary>
internal const int ADL_MAX_NUM_DISPLAYMODES = 1024;
internal const int ADL_MAX_EDIDDATA_SIZE = 256;
internal const int ADL_MAX_EDID_EXTENSION_BLOCKS = 3;
internal const int ADL_DISPLAY_DISPLAYINFO_DISPLAYCONNECTED = 0x00000001;
@ -265,6 +291,12 @@ namespace PowerControl.Helpers.AMD
[DllImport(Atiadlxx_FileName)]
internal static extern int ADL2_RIS_Settings_Set(IntPtr context, int adapterIndex, ADL_RIS_SETTINGS settings, ADL_RIS_NOTFICATION_REASON reason);
[DllImport(Atiadlxx_FileName)]
internal static extern int ADL2_Display_EdidData_Get(IntPtr context, int adapterIndex, int displayIndex, ref ADLDisplayEDIDData edidData);
[DllImport(Atiadlxx_FileName)]
internal static extern int ADL2_Display_EdidData_Set(IntPtr context, int adapterIndex, int displayIndex, ref ADLDisplayEDIDDataX2 edidData);
#endregion DLLImport
#region ADL_Main_Memory_Alloc

View file

@ -0,0 +1,57 @@
using System.Linq;
using System.Runtime.InteropServices;
namespace PowerControl.Helpers.AMD
{
internal class EDID
{
internal static byte[]? GetEDID(int displayIndex = ADL.ADL_DEFAULT_DISPLAY)
{
return ADLContext.WithSafe((context) =>
{
byte[] edid = new byte[0];
for (int block = 0; block < ADL.ADL_MAX_EDID_EXTENSION_BLOCKS; ++block)
{
ADLDisplayEDIDData displayEdidData = new ADLDisplayEDIDData()
{
iSize = Marshal.SizeOf<ADLDisplayEDIDData>(),
iBlockIndex = block,
};
int res = ADL.ADL2_Display_EdidData_Get(context.Context, ADL.ADL_DEFAULT_ADAPTER, ADL.ADL_DEFAULT_DISPLAY, ref displayEdidData);
if (res != 0)
break;
var blockBytes = displayEdidData.cEDIDData.Take(displayEdidData.iEDIDSize);
edid = edid.Concat(blockBytes).ToArray();
}
return edid;
});
}
internal static bool? SetEDID(byte[] value, int displayIndex = ADL.ADL_DEFAULT_DISPLAY)
{
return ADLContext.WithSafe((context) =>
{
var bytes = new byte[ADL.ADL_MAX_EDIDDATA_SIZE * 2];
value.CopyTo(bytes, 0);
var blockData = new ADLDisplayEDIDDataX2()
{
// TODO: Hack to send a full EDID at once
iSize = Marshal.SizeOf<ADLDisplayEDIDData>(),
cEDIDData = bytes,
iEDIDSize = value.Length,
};
int res = ADL.ADL2_Display_EdidData_Set(context.Context,
ADL.ADL_DEFAULT_ADAPTER, ADL.ADL_DEFAULT_DISPLAY,
ref blockData);
return res == 0;
});
}
}
}