Files

398 lines
12 KiB
C#

using ATI.ADL;
using System.ComponentModel;
using System.Runtime.InteropServices;
using ADL_CONTEXT_HANDLE = nint;
namespace ColorControl.Shared.Contracts.AMD;
public enum ADLPixelFormat
{
[Description("Unknown/unsupported")]
UNKNOWN = 0,
RGB_FULL_RANGE = 1,
YCRCB444 = 2,
YCRCB422 = 3,
RGB_LIMITED_RANGE = 4,
YCRCB420 = 8
}
public enum ADLColorDepth
{
[Description("Unknown/unsupported")]
UNKNOWN = 0,
BPC6 = 1,
BPC8 = 2,
BPC10 = 3,
BPC12 = 4,
BPC14 = 5,
BPC16 = 6
}
public enum ADLDitherState
{
DISABLED = 0,
DRIVER_DEFAULT = 1,
FM6 = 2,
FM8 = 3,
FM10 = 4,
DITH6 = 5,
DITH8 = 6,
DITH10 = 7,
DITH6_NO_FRAME_RAND = 8,
DITH8_NO_FRAME_RAND = 9,
DITH10_NO_FRAME_RAND = 10,
TRUN6 = 11,
TRUN8 = 12,
TRUN10 = 13,
TRUN8_DITH8 = 14,
TRUN10_DITH6 = 15,
TRUN10_FM8 = 16,
TRUN10_FM6 = 17,
TRUN10_DITH8_FM6 = 18,
DITH10_FM8 = 19,
DITH10_FM6 = 20,
TRUN8_DITH6 = 21,
TRUN8_FM6 = 22,
DITH8_FM6 = 23
}
public class ADLWrapper
{
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
private static ADL_CONTEXT_HANDLE context = ADL_CONTEXT_HANDLE.Zero;
public static bool Initialize()
{
int ADLRet = -1;
//Logger.Debug("Initialize");
var del = ADL.GetDelegate<ADL.ADL_Main_Control_Create>();
if (del != null)
{
// Second parameter is 1: Get only the present adapters
ADLRet = del(ADL.ADL_Main_Memory_Alloc_Func, 1);
CheckError(ADLRet, nameof(ADL.ADL_Main_Control_Create));
}
var del2 = ADL.GetDelegate<ADL.ADL2_Main_Control_Create>();
if (del2 != null)
{
// Second parameter is 1: Get only the present adapters
ADLRet = del2(ADL.ADL_Main_Memory_Alloc_Func, 1, ref context);
CheckError(ADLRet, nameof(ADL.ADL2_Main_Control_Create));
}
return ADL.ADL_SUCCESS == ADLRet;
}
public static void Uninitialze()
{
if (!ADL.ADLDelegates.Any())
{
return;
}
var del = ADL.GetDelegate<ADL.ADL_Main_Control_Destroy>();
if (null != del)
{
del();
}
var del2 = ADL.GetDelegate<ADL.ADL2_Main_Control_Destroy>();
if (null != del2 && context != ADL_CONTEXT_HANDLE.Zero)
{
del2(context);
}
}
public static ADLAdapterInfoArray? GetAdapters()
{
int ADLRet = -1;
int NumberOfAdapters = 0;
var delNumberOfAdapters = ADL.GetDelegate<ADL.ADL2_Adapter_NumberOfAdapters_Get>();
if (null != delNumberOfAdapters)
{
delNumberOfAdapters(context, ref NumberOfAdapters);
}
Logger.Debug("Number Of Adapters: " + NumberOfAdapters.ToString() + "\n");
if (NumberOfAdapters > 0)
{
// Get OS adpater info from ADL
ADLAdapterInfoArray OSAdapterInfoData;
OSAdapterInfoData = new ADLAdapterInfoArray();
var delAdapterInfo = ADL.GetDelegate<ADL.ADL2_Adapter_AdapterInfo_Get>();
if (null != delAdapterInfo)
{
ADL_CONTEXT_HANDLE AdapterBuffer = ADL_CONTEXT_HANDLE.Zero;
int size = Marshal.SizeOf(OSAdapterInfoData);
AdapterBuffer = Marshal.AllocCoTaskMem(size);
Marshal.StructureToPtr(OSAdapterInfoData, AdapterBuffer, false);
ADLRet = delAdapterInfo(context, AdapterBuffer, size);
if (ADL.ADL_SUCCESS == ADLRet)
{
OSAdapterInfoData = (ADLAdapterInfoArray)Marshal.PtrToStructure(AdapterBuffer, OSAdapterInfoData.GetType());
int IsActive = 0;
var delActive = ADL.GetDelegate<ADL.ADL2_Adapter_Active_Get>();
for (int i = 0; i < NumberOfAdapters; i++)
{
// Check if the adapter is active
if (null != delActive)
ADLRet = delActive(context, OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex, ref IsActive);
if (ADL.ADL_SUCCESS == ADLRet)
{
}
}
}
else
{
Logger.Debug("ADL_Adapter_AdapterInfo_Get() returned error code " + ADLRet.ToString());
}
// Release the memory for the AdapterInfo structure
if (ADL_CONTEXT_HANDLE.Zero != AdapterBuffer)
{
Marshal.FreeCoTaskMem(AdapterBuffer);
}
}
return OSAdapterInfoData;
}
return null;
}
public static List<ADLDisplayInfo> GetAllDisplays(bool connected = true)
{
int ADLRet;
int NumberOfDisplays = 0;
var DisplayInfoData = new List<ADLDisplayInfo>();
var OSAdapterInfoData = GetAdapters();
if (OSAdapterInfoData == null || !OSAdapterInfoData.Value.ADLAdapterInfo.Any())
{
return DisplayInfoData;
}
var primaryAdapter = OSAdapterInfoData.Value.ADLAdapterInfo.First();
ADLDisplayInfo oneDisplayInfo = new ADLDisplayInfo();
var del = ADL.GetDelegate<ADL.ADL2_Display_DisplayInfo_Get>();
if (null != del)
{
ADL_CONTEXT_HANDLE DisplayBuffer = ADL_CONTEXT_HANDLE.Zero;
int j = 0;
// Force the display detection and get the Display Info. Use 0 as last parameter to NOT force detection
ADLRet = del(context, primaryAdapter.AdapterIndex, ref NumberOfDisplays, out DisplayBuffer, 1);
if (ADL.ADL_SUCCESS == ADLRet)
{
for (j = 0; j < NumberOfDisplays; j++)
{
oneDisplayInfo = (ADLDisplayInfo)Marshal.PtrToStructure(new ADL_CONTEXT_HANDLE(DisplayBuffer.ToInt64() + j * Marshal.SizeOf(oneDisplayInfo)), oneDisplayInfo.GetType());
if (!connected || 1 == (oneDisplayInfo.DisplayInfoValue & 1))
{
DisplayInfoData.Add(oneDisplayInfo);
}
}
Logger.Debug("Total Number of Displays supported: " + NumberOfDisplays.ToString());
Logger.Debug("DispID DispPhyId AdpID Type OutType CnctType Connected Mapped InfoValue DisplayName ");
for (j = 0; j < DisplayInfoData.Count; j++)
{
int InfoValue = DisplayInfoData[j].DisplayInfoValue;
string StrConnected = 1 == (InfoValue & 1) ? "Yes" : "No ";
string StrMapped = 2 == (InfoValue & 2) ? "Yes" : "No ";
int AdpID = DisplayInfoData[j].DisplayID.DisplayLogicalAdapterIndex;
string StrAdpID = AdpID < 0 ? "--" : AdpID.ToString("d2");
Logger.Debug(DisplayInfoData[j].DisplayID.DisplayLogicalIndex.ToString() + " " +
DisplayInfoData[j].DisplayID.DisplayPhysicalIndex.ToString() + " " +
StrAdpID + " " +
DisplayInfoData[j].DisplayType.ToString() + " " +
DisplayInfoData[j].DisplayOutputType.ToString() + " " +
DisplayInfoData[j].DisplayConnector.ToString() + " " +
StrConnected + " " +
StrMapped + " " +
InfoValue.ToString("x4") + " " +
DisplayInfoData[j].DisplayName.ToString());
}
}
else
{
Logger.Debug("ADL_Display_DisplayInfo_Get() returned error code " + ADLRet.ToString());
}
// Release the memory for the DisplayInfo structure
if (ADL_CONTEXT_HANDLE.Zero != DisplayBuffer)
Marshal.FreeCoTaskMem(DisplayBuffer);
}
return DisplayInfoData;
}
private static bool CheckError(int ADLRet, string functionName)
{
var result = ADLRet == ADL.ADL_SUCCESS;
if (!result)
{
Logger.Error($"Error calling ADL ({functionName}): {ADLRet}");
}
return result;
}
public static bool GetDisplayResolution(ADLDisplayInfo display, ref int horizontal, ref int vertical)
{
var screen = Screen.PrimaryScreen;
var bounds = screen.Bounds;
horizontal = bounds.Width;
vertical = bounds.Height;
Logger.Debug($"GetDisplayResolution: {horizontal}x{vertical}");
//var del = ADL.GetDelegate<ADL.ADL2_Display_Size_Get>();
//if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
//{
// int lpDefaultWidth, lpDefaultHeight, lpMinWidth, lpMinHeight, lpMaxWidth, lpMaxHeight, lpStepWidth, lpStepHeight;
// lpDefaultWidth = lpDefaultHeight = lpMinWidth = lpMinHeight = lpMaxWidth = lpMaxHeight = lpStepWidth = lpStepHeight = 0;
// var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, ref horizontal, ref vertical, ref lpDefaultWidth, ref lpDefaultHeight, ref lpMinWidth, ref lpMinHeight, ref lpMaxWidth, ref lpMaxHeight, ref lpStepWidth, ref lpStepHeight);
// return CheckError(ADLRet, nameof(ADL.ADL2_Display_Size_Get));
//}
return true;
}
public static bool GetDisplayPixelFormat(ADLDisplayInfo display, ref ADLPixelFormat pixelFormat)
{
var del = ADL.GetDelegate<ADL.ADL2_Display_PixelFormat_Get>();
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
{
int pixelFormatInt = 0;
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, ref pixelFormatInt);
pixelFormat = (ADLPixelFormat)pixelFormatInt;
return CheckError(ADLRet, nameof(ADL.ADL2_Display_PixelFormat_Get));
}
return false;
}
public static bool SetDisplayPixelFormat(ADLDisplayInfo display, ADLPixelFormat pixelFormat)
{
var del = ADL.GetDelegate<ADL.ADL2_Display_PixelFormat_Set>();
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
{
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, (int)pixelFormat);
return CheckError(ADLRet, nameof(ADL.ADL2_Display_PixelFormat_Set));
}
return false;
}
public static bool GetDisplayColorDepth(ADLDisplayInfo display, ref ADLColorDepth colorDepth)
{
var del = ADL.GetDelegate<ADL.ADL2_Display_ColorDepth_Get>();
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
{
int colorDepthInt = 0;
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, ref colorDepthInt);
colorDepth = (ADLColorDepth)colorDepthInt;
return CheckError(ADLRet, nameof(ADL.ADL2_Display_ColorDepth_Get));
}
return false;
}
public static bool SetDisplayColorDepth(ADLDisplayInfo display, ADLColorDepth colorDepth)
{
var del = ADL.GetDelegate<ADL.ADL2_Display_ColorDepth_Set>();
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
{
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, (int)colorDepth);
return CheckError(ADLRet, nameof(ADL.ADL2_Display_ColorDepth_Set));
}
return false;
}
public static bool GetDisplayDitherState(ADLDisplayInfo display, ref ADLDitherState ditherState)
{
var del = ADL.GetDelegate<ADL.ADL2_Display_DitherState_Get>();
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
{
var ditherStateInt = 0;
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, ref ditherStateInt);
ditherState = (ADLDitherState)ditherStateInt;
return CheckError(ADLRet, nameof(ADL.ADL2_Display_DitherState_Get));
}
return false;
}
public static bool SetDisplayDitherState(ADLDisplayInfo display, ADLDitherState ditherState)
{
var del = ADL.GetDelegate<ADL.ADL2_Display_DitherState_Set>();
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
{
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, (int)ditherState);
return CheckError(ADLRet, nameof(ADL.ADL2_Display_DitherState_Set));
}
return false;
}
public static bool GetDisplayHDRState(ADLDisplayInfo display, ref bool supported, ref bool enabled)
{
var del = ADL.GetDelegate<ADL.ADL2_Display_HDRState_Get>();
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
{
var supportedInt = 0;
var enabledInt = 0;
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID, ref supportedInt, ref enabledInt);
supported = supportedInt != 0;
enabled = enabledInt != 0;
return CheckError(ADLRet, nameof(ADL.ADL2_Display_HDRState_Get));
}
return false;
}
public static bool SetDisplayHDRState(ADLDisplayInfo display, bool enabled)
{
var del = ADL.GetDelegate<ADL.ADL2_Display_HDRState_Set>();
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
{
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID, enabled ? 1 : 0);
return CheckError(ADLRet, nameof(ADL.ADL2_Display_HDRState_Set));
}
return false;
}
}