Changed marshalling to be more reliable

This commit is contained in:
Terry MacDonald 2021-06-19 20:19:29 +12:00
parent aaaf0287ac
commit 65653df73a
3 changed files with 39 additions and 60 deletions

View File

@ -419,15 +419,6 @@ namespace ATI.ADL
internal int InfoValue; internal int InfoValue;
} }
/// <summary> ADLAdapterInfoX2 Array</summary>
[StructLayout(LayoutKind.Sequential)]
internal struct ADLAdapterInfoX2Array
{
/// <summary> ADLAdapterInfo Array </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)ADL.ADL_MAX_ADAPTERS)]
internal ADLAdapterInfoX2[] ADLAdapterInfoX2;
}
#endregion ADLAdapterInfo #endregion ADLAdapterInfo
@ -646,15 +637,6 @@ namespace ATI.ADL
internal bool SHOWTYPE_PROJECTOR; internal bool SHOWTYPE_PROJECTOR;
} }
/// <summary> ADLDisplayInfo Array</summary>
[StructLayout(LayoutKind.Sequential)]
internal struct ADLDisplayInfoArray
{
/// <summary> ADLDisplayInfo Array </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)ADL.ADL_MAX_DISPLAYS)]
internal ADLDisplayInfo[] ADLDisplayInfo;
}
/// <summary> ADLDisplayConfig Structure</summary> /// <summary> ADLDisplayConfig Structure</summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct ADLDisplayConfig internal struct ADLDisplayConfig
@ -887,12 +869,14 @@ namespace ATI.ADL
#region Internal Constant #region Internal Constant
/// <summary> Selects all adapters instead of aparticular single adapter</summary> /// <summary> Selects all adapters instead of aparticular single adapter</summary>
internal const int ADL_ADAPTER_INDEX_ALL = -1; internal const int ADL_ADAPTER_INDEX_ALL = -1;
/// <summary> Define the maximum char</summary>
internal const int ADL_MAX_CHAR = 4096;
/// <summary> Define the maximum path</summary> /// <summary> Define the maximum path</summary>
internal const int ADL_MAX_PATH = 256; internal const int ADL_MAX_PATH = 256;
/// <summary> Define the maximum adapters</summary> /// <summary> Define the maximum adapters</summary>
internal const int ADL_MAX_ADAPTERS = 40 /* 150 */; internal const int ADL_MAX_ADAPTERS = 250;
/// <summary> Define the maximum displays</summary> /// <summary> Define the maximum displays</summary>
internal const int ADL_MAX_DISPLAYS = 40 /* 150 */; internal const int ADL_MAX_DISPLAYS = 150;
/// <summary> Define the maximum device name length</summary> /// <summary> Define the maximum device name length</summary>
internal const int ADL_MAX_DEVICENAME = 32; internal const int ADL_MAX_DEVICENAME = 32;
/// <summary> Define the maximum EDID Data length</summary> /// <summary> Define the maximum EDID Data length</summary>

View File

@ -7,6 +7,7 @@ using System.Runtime.InteropServices;
using ATI.ADL; using ATI.ADL;
using Microsoft.Win32.SafeHandles; using Microsoft.Win32.SafeHandles;
using DisplayMagicianShared; using DisplayMagicianShared;
using System.Threading;
namespace DisplayMagicianShared.AMD namespace DisplayMagicianShared.AMD
{ {
@ -138,7 +139,6 @@ namespace DisplayMagicianShared.AMD
int ADLRet = ADL.ADL_ERR; int ADLRet = ADL.ADL_ERR;
int NumberOfAdapters = 0; int NumberOfAdapters = 0;
int NumberOfDisplays = 0;
List<string> displayIdentifiers = new List<string>(); List<string> displayIdentifiers = new List<string>();
@ -150,18 +150,11 @@ namespace DisplayMagicianShared.AMD
if (NumberOfAdapters > 0) if (NumberOfAdapters > 0)
{ {
// Get OS adpater info from ADL
ADLAdapterInfoX2Array OSAdapterInfoData;
OSAdapterInfoData = new ADLAdapterInfoX2Array();
IntPtr AdapterBuffer = IntPtr.Zero; IntPtr AdapterBuffer = IntPtr.Zero;
if (ADL.ADL2_Adapter_AdapterInfoX4_Get != null) if (ADL.ADL2_Adapter_AdapterInfoX4_Get != null)
{ {
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: ADL2_Adapter_AdapterInfoX4_Get DLL function exists."); SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: ADL2_Adapter_AdapterInfoX4_Get DLL function exists.");
// Figure out the size of the AdapterBuffer we need to build
int size = Marshal.SizeOf(OSAdapterInfoData);
AdapterBuffer = Marshal.AllocCoTaskMem((int)size);
Marshal.StructureToPtr(OSAdapterInfoData, AdapterBuffer, false);
// Get the Adapter info and put it in the AdapterBuffer // Get the Adapter info and put it in the AdapterBuffer
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Running ADL2_Adapter_AdapterInfoX4_Get to find all known AMD adapters."); SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Running ADL2_Adapter_AdapterInfoX4_Get to find all known AMD adapters.");
@ -169,16 +162,18 @@ namespace DisplayMagicianShared.AMD
int numAdapters = 0; int numAdapters = 0;
ADLRet = ADL.ADL2_Adapter_AdapterInfoX4_Get(_adlContextHandle, ADL.ADL_ADAPTER_INDEX_ALL, out numAdapters, out AdapterBuffer); ADLRet = ADL.ADL2_Adapter_AdapterInfoX4_Get(_adlContextHandle, ADL.ADL_ADAPTER_INDEX_ALL, out numAdapters, out AdapterBuffer);
if (ADLRet == ADL.ADL_OK) if (ADLRet == ADL.ADL_OK)
{ {
// Use the AdapterBuffer pointer to marshal the OS Adapter Info into a structure
OSAdapterInfoData = (ADLAdapterInfoX2Array)Marshal.PtrToStructure(AdapterBuffer, OSAdapterInfoData.GetType());
int IsActive = ADL.ADL_TRUE; // We only want to search for active adapters int IsActive = ADL.ADL_TRUE; // We only want to search for active adapters
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Successfully run ADL2_Adapter_AdapterInfoX4_Get to find information about all known AMD adapters."); SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Successfully run ADL2_Adapter_AdapterInfoX4_Get to find information about all known AMD adapters.");
ADLAdapterInfoX2 oneAdapter = new ADLAdapterInfoX2();
// Go through each adapter // Go through each adapter
foreach (ADLAdapterInfoX2 oneAdapter in OSAdapterInfoData.ADLAdapterInfoX2) for (int adapterLoop = 0; adapterLoop < numAdapters; adapterLoop++)
{ {
oneAdapter = (ADLAdapterInfoX2)Marshal.PtrToStructure(new IntPtr(AdapterBuffer.ToInt64() + (adapterLoop * Marshal.SizeOf(oneAdapter))), oneAdapter.GetType());
if (oneAdapter.Exist != 1) if (oneAdapter.Exist != 1)
{ {
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: AMD Adapter #{oneAdapter.AdapterIndex.ToString()} doesn't exist at present so skipping detection for this adapter."); SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: AMD Adapter #{oneAdapter.AdapterIndex.ToString()} doesn't exist at present so skipping detection for this adapter.");
@ -252,23 +247,24 @@ namespace DisplayMagicianShared.AMD
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Adapter Num of Overlays = {AdapterCapabilities.NumOverlays}"); SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Adapter Num of Overlays = {AdapterCapabilities.NumOverlays}");
// Obtain information about displays // Obtain information about displays
ADLDisplayInfoArray displayInfoArray = new ADLDisplayInfoArray(); //ADLDisplayInfoArray displayInfoArray = new ADLDisplayInfoArray();
if (ADL.ADL2_Display_DisplayInfo_Get != null) if (ADL.ADL2_Display_DisplayInfo_Get != null)
{ {
IntPtr DisplayBuffer = IntPtr.Zero; IntPtr DisplayBuffer = IntPtr.Zero;
int numDisplays = 0;
// Force the display detection and get the Display Info. Use 0 as last parameter to NOT force detection // Force the display detection and get the Display Info. Use 0 as last parameter to NOT force detection
ADLRet = ADL.ADL2_Display_DisplayInfo_Get(_adlContextHandle, oneAdapter.AdapterIndex, ref NumberOfDisplays, out DisplayBuffer, 0); ADLRet = ADL.ADL2_Display_DisplayInfo_Get(_adlContextHandle, oneAdapter.AdapterIndex, ref numDisplays, out DisplayBuffer, 0);
if (ADLRet == ADL.ADL_OK) if (ADLRet == ADL.ADL_OK)
{ {
try try
{ {
displayInfoArray = (ADLDisplayInfoArray)Marshal.PtrToStructure(DisplayBuffer, displayInfoArray.GetType()); ADLDisplayInfo oneDisplayInfo = new ADLDisplayInfo();
foreach (ADLDisplayInfo oneDisplayInfo in displayInfoArray.ADLDisplayInfo) for (int displayLoop = 0; displayLoop < numDisplays; displayLoop++)
{ {
oneDisplayInfo = (ADLDisplayInfo)Marshal.PtrToStructure(new IntPtr(AdapterBuffer.ToInt64() + (displayLoop * Marshal.SizeOf(oneAdapter))), oneAdapter.GetType());
if (oneDisplayInfo.DisplayID.DisplayLogicalAdapterIndex == -1) if (oneDisplayInfo.DisplayID.DisplayLogicalAdapterIndex == -1)
{ {
@ -602,7 +598,6 @@ namespace DisplayMagicianShared.AMD
int ADLRet = ADL.ADL_ERR; int ADLRet = ADL.ADL_ERR;
int NumberOfAdapters = 0; int NumberOfAdapters = 0;
int NumberOfDisplays = 0;
List<string> displayIdentifiers = new List<string>(); List<string> displayIdentifiers = new List<string>();
@ -614,18 +609,11 @@ namespace DisplayMagicianShared.AMD
if (NumberOfAdapters > 0) if (NumberOfAdapters > 0)
{ {
// Get OS adpater info from ADL
ADLAdapterInfoX2Array OSAdapterInfoData;
OSAdapterInfoData = new ADLAdapterInfoX2Array();
IntPtr AdapterBuffer = IntPtr.Zero; IntPtr AdapterBuffer = IntPtr.Zero;
if (ADL.ADL2_Adapter_AdapterInfoX4_Get != null) if (ADL.ADL2_Adapter_AdapterInfoX4_Get != null)
{ {
SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: ADL2_Adapter_AdapterInfoX4_Get DLL function exists."); SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: ADL2_Adapter_AdapterInfoX4_Get DLL function exists.");
// Figure out the size of the AdapterBuffer we need to build
int size = Marshal.SizeOf(OSAdapterInfoData);
AdapterBuffer = Marshal.AllocCoTaskMem((int)size);
Marshal.StructureToPtr(OSAdapterInfoData, AdapterBuffer, false);
// Get the Adapter info and put it in the AdapterBuffer // Get the Adapter info and put it in the AdapterBuffer
SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: Running ADL2_Adapter_AdapterInfoX4_Get to find all known AMD adapters."); SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: Running ADL2_Adapter_AdapterInfoX4_Get to find all known AMD adapters.");
@ -634,15 +622,17 @@ namespace DisplayMagicianShared.AMD
ADLRet = ADL.ADL2_Adapter_AdapterInfoX4_Get(_adlContextHandle, ADL.ADL_ADAPTER_INDEX_ALL, out numAdapters, out AdapterBuffer); ADLRet = ADL.ADL2_Adapter_AdapterInfoX4_Get(_adlContextHandle, ADL.ADL_ADAPTER_INDEX_ALL, out numAdapters, out AdapterBuffer);
if (ADLRet == ADL.ADL_OK) if (ADLRet == ADL.ADL_OK)
{ {
// Use the AdapterBuffer pointer to marshal the OS Adapter Info into a structure
OSAdapterInfoData = (ADLAdapterInfoX2Array)Marshal.PtrToStructure(AdapterBuffer, OSAdapterInfoData.GetType());
int IsActive = ADL.ADL_TRUE; // We only want to search for active adapters int IsActive = ADL.ADL_TRUE; // We only want to search for active adapters
SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: Successfully run ADL2_Adapter_AdapterInfoX4_Get to find information about all known AMD adapters."); SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: Successfully run ADL2_Adapter_AdapterInfoX4_Get to find information about all known AMD adapters.");
ADLAdapterInfoX2 oneAdapter = new ADLAdapterInfoX2();
// Go through each adapter // Go through each adapter
foreach (ADLAdapterInfoX2 oneAdapter in OSAdapterInfoData.ADLAdapterInfoX2) for (int adapterLoop = 0; adapterLoop < numAdapters; adapterLoop++)
{ {
oneAdapter = (ADLAdapterInfoX2)Marshal.PtrToStructure(new IntPtr(AdapterBuffer.ToInt64() + (adapterLoop * Marshal.SizeOf(oneAdapter))), oneAdapter.GetType());
if (oneAdapter.Exist != 1) if (oneAdapter.Exist != 1)
{ {
SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: AMD Adapter #{oneAdapter.AdapterIndex.ToString()} doesn't exist at present so skipping detection for this adapter."); SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: AMD Adapter #{oneAdapter.AdapterIndex.ToString()} doesn't exist at present so skipping detection for this adapter.");
@ -716,23 +706,24 @@ namespace DisplayMagicianShared.AMD
SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: Adapter Num of Overlays = {AdapterCapabilities.NumOverlays}"); SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: Adapter Num of Overlays = {AdapterCapabilities.NumOverlays}");
// Obtain information about displays // Obtain information about displays
ADLDisplayInfoArray displayInfoArray = new ADLDisplayInfoArray(); //ADLDisplayInfoArray displayInfoArray = new ADLDisplayInfoArray();
if (ADL.ADL2_Display_DisplayInfo_Get != null) if (ADL.ADL2_Display_DisplayInfo_Get != null)
{ {
IntPtr DisplayBuffer = IntPtr.Zero; IntPtr DisplayBuffer = IntPtr.Zero;
int numDisplays = 0;
// Force the display detection and get the Display Info. Use 0 as last parameter to NOT force detection // Force the display detection and get the Display Info. Use 0 as last parameter to NOT force detection
ADLRet = ADL.ADL2_Display_DisplayInfo_Get(_adlContextHandle, oneAdapter.AdapterIndex, ref NumberOfDisplays, out DisplayBuffer, 0); ADLRet = ADL.ADL2_Display_DisplayInfo_Get(_adlContextHandle, oneAdapter.AdapterIndex, ref numDisplays, out DisplayBuffer, 0);
if (ADLRet == ADL.ADL_OK) if (ADLRet == ADL.ADL_OK)
{ {
try try
{ {
displayInfoArray = (ADLDisplayInfoArray)Marshal.PtrToStructure(DisplayBuffer, displayInfoArray.GetType()); ADLDisplayInfo oneDisplayInfo = new ADLDisplayInfo();
foreach (ADLDisplayInfo oneDisplayInfo in displayInfoArray.ADLDisplayInfo) for (int displayLoop = 0; displayLoop < numDisplays; displayLoop++)
{ {
oneDisplayInfo = (ADLDisplayInfo)Marshal.PtrToStructure(new IntPtr(AdapterBuffer.ToInt64() + (displayLoop * Marshal.SizeOf(oneAdapter))), oneAdapter.GetType());
if (oneDisplayInfo.DisplayID.DisplayLogicalAdapterIndex == -1) if (oneDisplayInfo.DisplayID.DisplayLogicalAdapterIndex == -1)
{ {
@ -749,8 +740,7 @@ namespace DisplayMagicianShared.AMD
continue; continue;
} }
// We want any connected display, wheteher they are mapped or non-mapped displays in the OS // We want connected displays whether they are mapped or not mapped in Windows OS
SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: AMD Adapter #{oneAdapter.AdapterIndex.ToString()} ({oneAdapter.AdapterName}) AdapterID display ID#{oneDisplayInfo.DisplayID.DisplayLogicalIndex} is connected and mapped in Windows OS"); SharedLogger.logger.Trace($"ADLWrapper/GenerateAllAvailableDisplayIdentifiers: AMD Adapter #{oneAdapter.AdapterIndex.ToString()} ({oneAdapter.AdapterName}) AdapterID display ID#{oneDisplayInfo.DisplayID.DisplayLogicalIndex} is connected and mapped in Windows OS");

View File

@ -1259,13 +1259,18 @@ namespace DisplayMagicianShared
} }
} }
} }
// else videocard is not NVIDIA so we just use the WindowsAPI access method // else if there is an AMD video card then we use that mode
// Note: This won't support any special AMD EyeFinity profiles unfortunately..... else if (AMDLibrary.IsInstalled)
// TODO: Add the detection and generation of the device ids using an AMD library {
// so that we can match valid AMD Eyefinity profiles with valid AMD standard profiles. //isAMD = true;
SharedLogger.logger.Debug($"ProfileRepository/GenerateProfileDisplayIdentifiers: The video card is an AMD video card.");
// Needs a lot of work here! We need to check if the AMD returned the right stuff, and then use Windows if there is an error.
return AMDLibrary.GenerateProfileDisplayIdentifiers();
}
// else video card is not NVIDIA or AMD so we just use the standard WindowsAPI access method
else else
{ {
// Then go through the adapters we have running using the WindowsDisplayAPI // Then go through the adapters we have running using the WindowsDisplayAPI
List<Display> attachedDisplayDevices = Display.GetDisplays().ToList(); List<Display> attachedDisplayDevices = Display.GetDisplays().ToList();
List<UnAttachedDisplay> unattachedDisplayDevices = UnAttachedDisplay.GetUnAttachedDisplays().ToList(); List<UnAttachedDisplay> unattachedDisplayDevices = UnAttachedDisplay.GetUnAttachedDisplays().ToList();