mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
787 lines
50 KiB
C#
787 lines
50 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Runtime.InteropServices;
|
|
using ATI.ADL;
|
|
using Microsoft.Win32.SafeHandles;
|
|
using DisplayMagicianShared;
|
|
|
|
namespace DisplayMagicianShared.AMD
|
|
{
|
|
public class ADLWrapper : IDisposable
|
|
{
|
|
// Static members are 'eagerly initialized', that is,
|
|
// immediately when class is loaded for the first time.
|
|
// .NET guarantees thread safety for static initialization
|
|
private static ADLWrapper _instance = new ADLWrapper();
|
|
|
|
private bool _initialised = false;
|
|
private bool _initialisedADL2 = false;
|
|
|
|
// To detect redundant calls
|
|
private bool _disposed = false;
|
|
|
|
// Instantiate a SafeHandle instance.
|
|
private SafeHandle _safeHandle = new SafeFileHandle(IntPtr.Zero, true);
|
|
private IntPtr _adlContextHandle = IntPtr.Zero;
|
|
|
|
|
|
static ADLWrapper() { }
|
|
public ADLWrapper()
|
|
{
|
|
int ADLRet = ADL.ADL_ERR;
|
|
|
|
SharedLogger.logger.Trace("ADLWrapper/ADLWrapper: Intialising ADL library");
|
|
try
|
|
{
|
|
if (ADL.ADL_Main_Control_Create != null)
|
|
{
|
|
// Second parameter is 1: Get only the present adapters
|
|
ADLRet = ADL.ADL_Main_Control_Create(ADL.ADL_Main_Memory_Alloc, 1);
|
|
}
|
|
|
|
if (ADLRet == ADL.ADL_OK)
|
|
{
|
|
_initialised = true;
|
|
SharedLogger.logger.Trace("ADLWrapper/ADLWrapper: ADL library was initialised successfully");
|
|
}
|
|
else
|
|
{
|
|
SharedLogger.logger.Error("ADLWrapper/ADLWrapper: Error intialising ADL library. ADL_Main_Control_Create() returned error code " + ADLRet.ToString());
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Error("ADLWrapper/ADLWrapper: Exception intialising ADL library. ADL_Main_Control_Create() caused an exception");
|
|
}
|
|
|
|
try
|
|
{
|
|
if (ADL.ADL2_Main_Control_Create != null)
|
|
{
|
|
// Second parameter is 1: Get only the present adapters
|
|
ADLRet = ADL.ADL2_Main_Control_Create(ADL.ADL_Main_Memory_Alloc, 1, out _adlContextHandle);
|
|
}
|
|
|
|
if (ADLRet == ADL.ADL_OK)
|
|
{
|
|
_initialisedADL2 = true;
|
|
SharedLogger.logger.Trace("ADLWrapper/ADLWrapper: ADL2 library was initialised successfully");
|
|
}
|
|
else
|
|
{
|
|
SharedLogger.logger.Error("ADLWrapper/ADLWrapper: Error intialising ADL2 library. ADL2_Main_Control_Create() returned error code " + ADL.ConvertADLReturnValueIntoWords(ADLRet));
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Error("ADLWrapper/ADLWrapper: Exception intialising ADL2 library. ADL2_Main_Control_Create() caused an exception");
|
|
}
|
|
|
|
}
|
|
|
|
~ADLWrapper()
|
|
{
|
|
// If the ADL library was initialised, then we need to free it up.
|
|
if (_initialised)
|
|
{
|
|
if (null != ADL.ADL_Main_Control_Destroy)
|
|
ADL.ADL_Main_Control_Destroy();
|
|
}
|
|
// If the ADL2 library was initialised, then we need to free it up.
|
|
if (_initialisedADL2)
|
|
{
|
|
if (null != ADL.ADL2_Main_Control_Destroy)
|
|
ADL.ADL2_Main_Control_Destroy(_adlContextHandle);
|
|
}
|
|
}
|
|
|
|
// Public implementation of Dispose pattern callable by consumers.
|
|
public void Dispose() => Dispose(true);
|
|
|
|
// Protected implementation of Dispose pattern.
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (disposing)
|
|
{
|
|
if (null != ADL.ADL_Main_Control_Destroy)
|
|
ADL.ADL_Main_Control_Destroy();
|
|
|
|
// Dispose managed state (managed objects).
|
|
_safeHandle?.Dispose();
|
|
}
|
|
|
|
_disposed = true;
|
|
}
|
|
|
|
|
|
public bool IsInstalled
|
|
{
|
|
get { return _initialised; }
|
|
}
|
|
|
|
public static ADLWrapper GetLibrary()
|
|
{
|
|
return _instance;
|
|
}
|
|
|
|
public List<string> GenerateProfileDisplayIdentifiers()
|
|
{
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Getting AMD active adapter count");
|
|
|
|
int ADLRet = ADL.ADL_ERR;
|
|
int NumberOfAdapters = 0;
|
|
int NumberOfDisplays = 0;
|
|
|
|
List<string> displayIdentifiers = new List<string>();
|
|
|
|
// Get the DisplayMap info (Desktops) for all adapters on the machine in one go
|
|
// Keep a list of things we want to track
|
|
/*List<ADLDisplayMap> allDisplayMaps = new List<ADLDisplayMap>();
|
|
List<ADLDisplayTarget> allDisplayTargets = new List<ADLDisplayTarget>();
|
|
|
|
if (ADL.ADL_Display_DisplayMapConfig_Get != null)
|
|
{
|
|
IntPtr DisplayMapBuffer = IntPtr.Zero;
|
|
IntPtr DisplayTargetBuffer = IntPtr.Zero;
|
|
int numDisplayMaps = 0;
|
|
int numDisplayTargets = 0;
|
|
|
|
// Get the DisplayMap info (Desktops) for all adapters on the machine in one go
|
|
ADLRet = ADL.ADL_Display_DisplayMapConfig_Get(-1, out numDisplayMaps, out DisplayMapBuffer, out numDisplayTargets, out DisplayTargetBuffer, 0);
|
|
if (ADLRet == ADL.ADL_SUCCESS)
|
|
{
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Number Of DisplayMaps (Desktops): {numDisplayMaps.ToString()} ");
|
|
|
|
// Marshal the Display Maps
|
|
ADLDisplayMap oneDisplayMap = new ADLDisplayMap();
|
|
|
|
for (int displayMapNum = 0; displayMapNum < numDisplayMaps; displayMapNum++)
|
|
{
|
|
// NOTE: the ToInt64 work on 64 bit, need to change to ToInt32 for 32 bit OS
|
|
oneDisplayMap = (ADLDisplayMap)Marshal.PtrToStructure(new IntPtr(DisplayMapBuffer.ToInt64() + (displayMapNum * Marshal.SizeOf(oneDisplayMap))), oneDisplayMap.GetType());
|
|
allDisplayMaps.Add(oneDisplayMap);
|
|
}
|
|
|
|
//Marshall the DisplayTargets
|
|
ADLDisplayTarget oneDisplayTarget = new ADLDisplayTarget();
|
|
|
|
for (int displayTargetNum = 0; displayTargetNum < numDisplayTargets; displayTargetNum++)
|
|
{
|
|
// NOTE: the ToInt64 work on 64 bit, need to change to ToInt32 for 32 bit OS
|
|
oneDisplayTarget = (ADLDisplayTarget)Marshal.PtrToStructure(new IntPtr(DisplayMapBuffer.ToInt64() + (displayTargetNum * Marshal.SizeOf(oneDisplayTarget))), oneDisplayTarget.GetType());
|
|
allDisplayTargets.Add(oneDisplayTarget);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (ADL.ADL_Display_DisplayMapConfig_PossibleAddAndRemove != null)
|
|
{
|
|
int numDisplayMap = 1;
|
|
int numDisplayTarget = 1;
|
|
|
|
IntPtr PossibleAddTargetBuffer = IntPtr.Zero;
|
|
IntPtr PossibleRemoveTargetBuffer = IntPtr.Zero;
|
|
int numPossibleAddTargets = 0;
|
|
int numPossibleRemoveTargets = 0;
|
|
|
|
List<ADLDisplayTarget> allPossibleAddDisplayTargets = new List<ADLDisplayTarget>();
|
|
List<ADLDisplayTarget> allPossibleRemoveDisplayTargets = new List<ADLDisplayTarget>();
|
|
|
|
// Force the display detection and get the Display Info. Use 0 as last parameter to NOT force detection
|
|
ADLRet = ADL.ADL_Display_DisplayMapConfig_PossibleAddAndRemove(0, numDisplayMap, allDisplayMaps[0], numDisplayTarget, allDisplayTargets[0], out numPossibleAddTargets, out PossibleAddTargetBuffer, out numPossibleRemoveTargets, out PossibleRemoveTargetBuffer);
|
|
if (ADLRet == ADL.ADL_SUCCESS)
|
|
{
|
|
// Marshal the Possible Add Targets
|
|
ADLDisplayTarget oneDisplayTarget = new ADLDisplayTarget();
|
|
|
|
for (int displayTargetNum = 0; displayTargetNum < numPossibleAddTargets; displayTargetNum++)
|
|
{
|
|
// NOTE: the ToInt64 work on 64 bit, need to change to ToInt32 for 32 bit OS
|
|
oneDisplayTarget = (ADLDisplayTarget)Marshal.PtrToStructure(new IntPtr(PossibleAddTargetBuffer.ToInt64() + (displayTargetNum * Marshal.SizeOf(oneDisplayTarget))), oneDisplayTarget.GetType());
|
|
allPossibleAddDisplayTargets.Add(oneDisplayTarget);
|
|
}
|
|
|
|
// Marshal the Possible Remove Targets too
|
|
for (int displayTargetNum = 0; displayTargetNum < numPossibleRemoveTargets; displayTargetNum++)
|
|
{
|
|
// NOTE: the ToInt64 work on 64 bit, need to change to ToInt32 for 32 bit OS
|
|
oneDisplayTarget = (ADLDisplayTarget)Marshal.PtrToStructure(new IntPtr(PossibleRemoveTargetBuffer.ToInt64() + (displayTargetNum * Marshal.SizeOf(oneDisplayTarget))), oneDisplayTarget.GetType());
|
|
allPossibleAddDisplayTargets.Add(oneDisplayTarget);
|
|
}
|
|
}
|
|
}*/
|
|
|
|
|
|
if (null != ADL.ADL2_Adapter_NumberOfAdapters_Get)
|
|
{
|
|
ADL.ADL2_Adapter_NumberOfAdapters_Get(_adlContextHandle, ref NumberOfAdapters);
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Number Of Adapters: {NumberOfAdapters.ToString()} ");
|
|
}
|
|
|
|
if (NumberOfAdapters > 0)
|
|
{
|
|
// Get OS adpater info from ADL
|
|
ADLAdapterInfoX2Array OSAdapterInfoData;
|
|
OSAdapterInfoData = new ADLAdapterInfoX2Array();
|
|
|
|
IntPtr AdapterBuffer = IntPtr.Zero;
|
|
if (ADL.ADL2_Adapter_AdapterInfoX4_Get != null)
|
|
{
|
|
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
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Running ADL2_Adapter_AdapterInfoX4_Get to find all known AMD adapters.");
|
|
//ADLRet = ADL.ADL2_Adapter_AdapterInfoX4_Get(_adlContextHandle, AdapterBuffer, size);
|
|
int numAdapters = 0;
|
|
ADLRet = ADL.ADL2_Adapter_AdapterInfoX4_Get(_adlContextHandle, ADL.ADL_ADAPTER_INDEX_ALL, out numAdapters, out AdapterBuffer);
|
|
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
|
|
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Successfully run ADL2_Adapter_AdapterInfoX4_Get to find information about all known AMD adapters.");
|
|
|
|
// Go through each adapter
|
|
for (int i = 0; i < NumberOfAdapters; i++)
|
|
{
|
|
ADLAdapterInfoX2 oneAdapter = OSAdapterInfoData.ADLAdapterInfoX2[i];
|
|
|
|
|
|
// Check if the adapter is active
|
|
if (ADL.ADL2_Adapter_Active_Get != null)
|
|
ADLRet = ADL.ADL2_Adapter_Active_Get(_adlContextHandle, oneAdapter.AdapterIndex, ref IsActive);
|
|
|
|
if (ADLRet == ADL.ADL_OK)
|
|
{
|
|
// Only continue if the adapter is enabled
|
|
if (IsActive != ADL.ADL_TRUE)
|
|
{
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: AMD Adapter #{i} isn't active ({oneAdapter.AdapterName}).");
|
|
continue;
|
|
}
|
|
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: AMD Adapter #{i} is active! ({oneAdapter.AdapterName}).");
|
|
|
|
Console.WriteLine($"### Adapter Info for Adapter #{oneAdapter.AdapterIndex} ###");
|
|
Console.WriteLine($"Adapter ID = {oneAdapter}");
|
|
|
|
// Get the Adapter Capabilities
|
|
ADLAdapterCapsX2 AdapterCapabilities = new ADLAdapterCapsX2();
|
|
if (ADL.ADL_AdapterX2_Caps != null)
|
|
{
|
|
ADLRet = ADL.ADL_AdapterX2_Caps(oneAdapter.AdapterIndex, out AdapterCapabilities);
|
|
}
|
|
|
|
//ADLAdapterCapsX2 AdapterCapabilities = (ADLAdapterCapsX2)Marshal.PtrToStructure(AdapterCapabilitiesBuffer, typeof(ADLAdapterCapsX2));
|
|
Console.WriteLine($"### Adapter Capabilities for Adapter #{oneAdapter.AdapterIndex} ###");
|
|
Console.WriteLine($"Adapter ID = {AdapterCapabilities.AdapterID}");
|
|
Console.WriteLine($"Adapter Capabilities Mask = {AdapterCapabilities.CapsMask}");
|
|
Console.WriteLine($"Adapter Capabilities Value = {AdapterCapabilities.CapsValue}");
|
|
Console.WriteLine($"Adapter Num of Connectors = {AdapterCapabilities.NumConnectors}");
|
|
Console.WriteLine($"Adapter Num of Controllers = {AdapterCapabilities.NumControllers}");
|
|
Console.WriteLine($"Adapter Num of Displays = {AdapterCapabilities.NumDisplays}");
|
|
Console.WriteLine($"Adapter Num of GL Sync Connectors = {AdapterCapabilities.NumOfGLSyncConnectors}");
|
|
Console.WriteLine($"Adapter Num of Overlays = {AdapterCapabilities.NumOverlays}");
|
|
|
|
// Obtain information about displays
|
|
ADLDisplayInfo oneDisplayInfo = new ADLDisplayInfo();
|
|
|
|
if (ADL.ADL_Display_DisplayInfo_Get != null)
|
|
{
|
|
IntPtr DisplayBuffer = IntPtr.Zero;
|
|
int j = 0;
|
|
|
|
// Force the display detection and get the Display Info. Use 0 as last parameter to NOT force detection
|
|
ADLRet = ADL.ADL_Display_DisplayInfo_Get(oneAdapter.AdapterIndex, ref NumberOfDisplays, out DisplayBuffer, 0);
|
|
if (ADLRet == ADL.ADL_OK)
|
|
{
|
|
|
|
try
|
|
{
|
|
|
|
for (j = 0; j < NumberOfDisplays; j++)
|
|
{
|
|
// Marshal the returned array of displayinfo into managed objects one by one
|
|
// NOTE: the ToInt64 work on 64 bit, need to change to ToInt32 for 32 bit OS
|
|
oneDisplayInfo = (ADLDisplayInfo)Marshal.PtrToStructure(new IntPtr(DisplayBuffer.ToInt64() + (j * Marshal.SizeOf(oneDisplayInfo))), oneDisplayInfo.GetType());
|
|
// Skip non connected displays
|
|
|
|
Console.WriteLine($"### Display Info for Display #{oneDisplayInfo.DisplayID.DisplayLogicalIndex} on Adapter #{oneAdapter.AdapterIndex} ###");
|
|
Console.WriteLine($"Display Connector = {oneDisplayInfo.DisplayConnector}");
|
|
Console.WriteLine($"Display Controller Index = {oneDisplayInfo.DisplayControllerIndex}");
|
|
Console.WriteLine($"Display Logical Adapter Index = {oneDisplayInfo.DisplayID.DisplayLogicalAdapterIndex}");
|
|
Console.WriteLine($"Display Logical Index = {oneDisplayInfo.DisplayID.DisplayLogicalIndex}");
|
|
Console.WriteLine($"Display Physical Adapter Index = {oneDisplayInfo.DisplayID.DisplayPhysicalAdapterIndex}");
|
|
Console.WriteLine($"Display Physical Index = {oneDisplayInfo.DisplayID.DisplayPhysicalIndex}");
|
|
Console.WriteLine($"Display Info Mask = {oneDisplayInfo.DisplayInfoMask}");
|
|
Console.WriteLine($"Display Info Value = {oneDisplayInfo.DisplayInfoValue}");
|
|
Console.WriteLine($"Display Manufacturer Name = {oneDisplayInfo.DisplayManufacturerName}");
|
|
Console.WriteLine($"Display Name = {oneDisplayInfo.DisplayName}");
|
|
Console.WriteLine($"Display Output Type = {oneDisplayInfo.DisplayOutputType}");
|
|
Console.WriteLine($"Display Type = {oneDisplayInfo.DisplayType}");
|
|
|
|
// Convert the displayInfoValue to something usable using a library function I made
|
|
ConvertedDisplayInfoValue displayInforValue = ADL.ConvertDisplayInfoValue(oneDisplayInfo.DisplayInfoValue);
|
|
Console.WriteLine($"Display Info Value DISPLAYCONNECTED = {displayInforValue.DISPLAYCONNECTED}");
|
|
Console.WriteLine($"Display Info Value DISPLAYMAPPED = {displayInforValue.DISPLAYMAPPED}");
|
|
Console.WriteLine($"Display Info Value FORCIBLESUPPORTED = {displayInforValue.FORCIBLESUPPORTED}");
|
|
Console.WriteLine($"Display Info Value GENLOCKSUPPORTED = {displayInforValue.GENLOCKSUPPORTED}");
|
|
Console.WriteLine($"Display Info Value LDA_DISPLAY = {displayInforValue.LDA_DISPLAY}");
|
|
Console.WriteLine($"Display Info Value MANNER_SUPPORTED_2HSTRETCH = {displayInforValue.MANNER_SUPPORTED_2HSTRETCH}");
|
|
Console.WriteLine($"Display Info Value MANNER_SUPPORTED_2VSTRETCH = {displayInforValue.MANNER_SUPPORTED_2VSTRETCH}");
|
|
Console.WriteLine($"Display Info Value MANNER_SUPPORTED_CLONE = {displayInforValue.MANNER_SUPPORTED_CLONE}");
|
|
Console.WriteLine($"Display Info Value MANNER_SUPPORTED_EXTENDED = {displayInforValue.MANNER_SUPPORTED_EXTENDED}");
|
|
Console.WriteLine($"Display Info Value MANNER_SUPPORTED_NSTRETCH1GPU = {displayInforValue.MANNER_SUPPORTED_NSTRETCH1GPU}");
|
|
Console.WriteLine($"Display Info Value MANNER_SUPPORTED_NSTRETCHNGPU = {displayInforValue.MANNER_SUPPORTED_NSTRETCHNGPU}");
|
|
Console.WriteLine($"Display Info Value MANNER_SUPPORTED_SINGLE = {displayInforValue.MANNER_SUPPORTED_SINGLE}");
|
|
Console.WriteLine($"Display Info Value MODETIMING_OVERRIDESSUPPORTED = {displayInforValue.MODETIMING_OVERRIDESSUPPORTED}");
|
|
Console.WriteLine($"Display Info Value MULTIVPU_SUPPORTED = {displayInforValue.MULTIVPU_SUPPORTED}");
|
|
Console.WriteLine($"Display Info Value NONLOCAL = {displayInforValue.NONLOCAL}");
|
|
Console.WriteLine($"Display Info Value SHOWTYPE_PROJECTOR = {displayInforValue.SHOWTYPE_PROJECTOR}");
|
|
|
|
if ((oneDisplayInfo.DisplayInfoValue & 1) != 1)
|
|
{
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: AMD Adapter #{i} ({oneAdapter.AdapterName}) AdapterID display ID#{j} is not connected");
|
|
continue;
|
|
}
|
|
|
|
// Skip connected but non-mapped displays (not mapped in windows) - wae want all displays currently visible in the OS
|
|
if ((oneDisplayInfo.DisplayInfoValue & 2) != 2)
|
|
{
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: AMD Adapter #{i} ({oneAdapter.AdapterName}) AdapterID display ID#{j} is not connected");
|
|
continue;
|
|
}
|
|
|
|
ADLDisplayConfig displayConfig = new ADLDisplayConfig();
|
|
if (ADL.ADL_Display_DeviceConfig_Get != null)
|
|
{
|
|
// Get the DisplayConfig from the Display
|
|
ADLRet = ADL.ADL_Display_DeviceConfig_Get(oneAdapter.AdapterIndex, oneDisplayInfo.DisplayID.DisplayLogicalIndex, out displayConfig);
|
|
if (ADLRet == ADL.ADL_OK)
|
|
{
|
|
Console.WriteLine($"### Display Device Config for Display #{oneDisplayInfo.DisplayID.DisplayLogicalIndex} on Adapter #{oneAdapter.AdapterIndex} ###");
|
|
Console.WriteLine($"Display Connector Type = {displayConfig.ConnectorType}");
|
|
Console.WriteLine($"Display Device Data = {displayConfig.DeviceData}");
|
|
Console.WriteLine($"Display Overridded Device Data = {displayConfig.OverriddedDeviceData}");
|
|
Console.WriteLine($"Display Reserved Data = {displayConfig.Reserved}");
|
|
Console.WriteLine($"Display Size = {displayConfig.Size}");
|
|
}
|
|
}
|
|
|
|
ADLDDCInfo2 displayDDCInfo2 = new ADLDDCInfo2();
|
|
// Create a stringbuilder buffer that EDID can be loaded into
|
|
//displayEDIDData.EDIDData = new StringBuilder(256);
|
|
|
|
if (ADL.ADL2_Display_DDCInfo2_Get != null)
|
|
{
|
|
// Get the EDID Data from the Display
|
|
ADLRet = ADL.ADL2_Display_DDCInfo2_Get(_adlContextHandle, oneAdapter.AdapterIndex, oneDisplayInfo.DisplayID.DisplayPhysicalIndex, out displayDDCInfo2);
|
|
if (ADLRet == ADL.ADL_OK)
|
|
{
|
|
Console.WriteLine($"### Display EDID Data for Display #{oneDisplayInfo.DisplayID.DisplayLogicalIndex} on Adapter #{oneAdapter.AdapterIndex} ###");
|
|
Console.WriteLine($"Display Manufacturer ID = {displayDDCInfo2.ManufacturerID}");
|
|
/*Console.WriteLine($"Display EDID Data = {displayDDCInfo2.EDIDData}");
|
|
Console.WriteLine($"Display EDID Size = {displayDDCInfo2.EDIDSize}");
|
|
Console.WriteLine($"Display EDID Flag = {displayDDCInfo2.Flag}");
|
|
Console.WriteLine($"Display EDID Reserved = {displayDDCInfo2.Reserved}");
|
|
Console.WriteLine($"Display EDID Data Size = {displayDDCInfo2.Size}");*/
|
|
} else
|
|
{
|
|
Console.WriteLine($"Error running ADL_Display_EdidData_Get on Display #{oneDisplayInfo.DisplayID.DisplayLogicalIndex} on Adapter #{oneAdapter.AdapterIndex}: {ADL.ConvertADLReturnValueIntoWords(ADLRet)}");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Create an array of all the important display info we need to record
|
|
List<string> displayInfoIdentifierSection = new List<string>();
|
|
displayInfoIdentifierSection.Add("AMD");
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(oneAdapter.AdapterName);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting AMD Adapter Name from video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(oneAdapter.AdapterIndex.ToString());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting AMD Adapter Index from video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(oneAdapter.VendorID.ToString());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting AMD VendorID from video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("1002");
|
|
}
|
|
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(AdapterCapabilities.AdapterID.ToString());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting AMD AdapterID from video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
try
|
|
{
|
|
ADL.ADLConnectionType connector = (ADL.ADLConnectionType)oneDisplayInfo.DisplayOutputType;
|
|
displayInfoIdentifierSection.Add(connector.ToString("G"));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting AMD Display Connector from video card to display. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(oneDisplayInfo.DisplayManufacturerName);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting Display manufacturer from AMD video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(oneDisplayInfo.DisplayName);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting Display Name from AMD video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
// Create a display identifier out of it
|
|
string displayIdentifier = String.Join("|", displayInfoIdentifierSection);
|
|
// Add it to the list of display identifiers so we can return it
|
|
displayIdentifiers.Add(displayIdentifier);
|
|
|
|
SharedLogger.logger.Debug($"ProfileRepository/GenerateProfileDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("Exception caused trying to access attached displays");
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("ADL_Display_DisplayInfo_Get() returned error code " + ADLRet.ToString());
|
|
}
|
|
// Release the memory for the DisplayInfo structure
|
|
if (IntPtr.Zero != DisplayBuffer)
|
|
Marshal.FreeCoTaskMem(DisplayBuffer);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("ADL_Adapter_Active_Get() returned error code " + ADLRet.ToString());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("ADL_Adapter_AdapterInfo_Get() returned error code " + ADLRet.ToString());
|
|
}
|
|
}
|
|
// Release the memory for the AdapterInfo structure
|
|
if (IntPtr.Zero != AdapterBuffer)
|
|
{
|
|
Marshal.FreeCoTaskMem(AdapterBuffer);
|
|
}
|
|
|
|
// Return all the identifiers we've found
|
|
return displayIdentifiers;
|
|
}
|
|
else
|
|
{
|
|
SharedLogger.logger.Error($"ADLWrapper/GenerateProfileDisplayIdentifiers: There were no AMD adapters found by AMD ADL.");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public List<string> GenerateAllAvailableDisplayIdentifiers()
|
|
{
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Getting AMD active adapter count");
|
|
|
|
int ADLRet = ADL.ADL_ERR;
|
|
int NumberOfAdapters = 0;
|
|
int NumberOfDisplays = 0;
|
|
|
|
List<string> displayIdentifiers = new List<string>();
|
|
|
|
|
|
if (null != ADL.ADL_Adapter_NumberOfAdapters_Get)
|
|
{
|
|
ADL.ADL_Adapter_NumberOfAdapters_Get(ref NumberOfAdapters);
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Number Of Adapters: {NumberOfAdapters.ToString()} ");
|
|
}
|
|
|
|
if (NumberOfAdapters > 0)
|
|
{
|
|
// Get OS adpater info from ADL
|
|
ADLAdapterInfoArray OSAdapterInfoData;
|
|
OSAdapterInfoData = new ADLAdapterInfoArray();
|
|
|
|
IntPtr AdapterBuffer = IntPtr.Zero;
|
|
if (ADL.ADL2_Adapter_AdapterInfoX4_Get != null)
|
|
{
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: ADL_Adapter_AdapterInfo_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
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Running ADL_Adapter_AdapterInfo_Get to find all known AMD adapters.");
|
|
ADLRet = ADL.ADL_Adapter_AdapterInfo_Get(out AdapterBuffer, size);
|
|
if (ADLRet == ADL.ADL_OK)
|
|
{
|
|
// Use the AdapterBuffer pointer to marshal the OS Adapter Info into a structure
|
|
OSAdapterInfoData = (ADLAdapterInfoArray)Marshal.PtrToStructure(AdapterBuffer, OSAdapterInfoData.GetType());
|
|
int IsActive = ADL.ADL_TRUE; // We only want to search for active adapters
|
|
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: Successfully run ADL_Adapter_AdapterInfo_Get to find information about all known AMD adapters.");
|
|
|
|
// Go through each adapter
|
|
for (int i = 0; i < NumberOfAdapters; i++)
|
|
{
|
|
// Check if the adapter is active
|
|
if (ADL.ADL_Adapter_Active_Get != null)
|
|
ADLRet = ADL.ADL_Adapter_Active_Get(OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex, ref IsActive);
|
|
|
|
if (ADLRet == ADL.ADL_OK)
|
|
{
|
|
// Only continue if the adapter is enabled
|
|
if (IsActive != ADL.ADL_TRUE)
|
|
{
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: AMD Adapter #{i} isn't active ({OSAdapterInfoData.ADLAdapterInfo[i].AdapterName}).");
|
|
continue;
|
|
}
|
|
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: AMD Adapter #{i} is active! ({OSAdapterInfoData.ADLAdapterInfo[i].AdapterName}).");
|
|
|
|
// Get the unique identifier from the Adapter
|
|
int AdapterID = 0;
|
|
if (ADL.ADL_Adapter_ID_Get != null)
|
|
{
|
|
ADLRet = ADL.ADL_Adapter_ID_Get(OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex, ref AdapterID);
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: AMD Adapter #{i} ({OSAdapterInfoData.ADLAdapterInfo[i].AdapterName}) AdapterID is {AdapterID.ToString()}");
|
|
}
|
|
|
|
// Get the Adapter Capabilities
|
|
ADLAdapterCapsX2 AdapterCapabilities = new ADLAdapterCapsX2();
|
|
if (ADL.ADL_AdapterX2_Caps != null)
|
|
{
|
|
ADLRet = ADL.ADL_AdapterX2_Caps(OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex, out AdapterCapabilities);
|
|
}
|
|
|
|
//ADLAdapterCapsX2 AdapterCapabilities = (ADLAdapterCapsX2)Marshal.PtrToStructure(AdapterCapabilitiesBuffer, typeof(ADLAdapterCapsX2));
|
|
Console.Write(AdapterCapabilities.AdapterID);
|
|
|
|
// Obtain information about displays
|
|
ADLDisplayInfo oneDisplayInfo = new ADLDisplayInfo();
|
|
|
|
if (ADL.ADL_Display_DisplayInfo_Get != null)
|
|
{
|
|
IntPtr DisplayBuffer = IntPtr.Zero;
|
|
int j = 0;
|
|
|
|
// Force the display detection and get the Display Info. Use 0 as last parameter to NOT force detection
|
|
ADLRet = ADL.ADL_Display_DisplayInfo_Get(OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex, ref NumberOfDisplays, out DisplayBuffer, 0);
|
|
if (ADLRet == ADL.ADL_OK)
|
|
{
|
|
|
|
List<ADLDisplayInfo> DisplayInfoData = new List<ADLDisplayInfo>();
|
|
|
|
try
|
|
{
|
|
|
|
for (j = 0; j < NumberOfDisplays; j++)
|
|
{
|
|
// NOTE: the ToInt64 work on 64 bit, need to change to ToInt32 for 32 bit OS
|
|
oneDisplayInfo = (ADLDisplayInfo)Marshal.PtrToStructure(new IntPtr(DisplayBuffer.ToInt64() + (j * Marshal.SizeOf(oneDisplayInfo))), oneDisplayInfo.GetType());
|
|
DisplayInfoData.Add(oneDisplayInfo);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("Exception caused trying to access attached displays");
|
|
continue;
|
|
}
|
|
Console.WriteLine("\nTotal Number of Displays supported: " + NumberOfDisplays.ToString());
|
|
Console.WriteLine("\nDispID AdpID Type OutType CnctType Connected Mapped InfoValue DisplayName ");
|
|
|
|
for (j = 0; j < NumberOfDisplays; j++)
|
|
{
|
|
// Skip non connected displays - we want only connected displays that could potentially be used now (thats both mapped and non-mapped displays)
|
|
if ((DisplayInfoData[j].DisplayInfoValue & 1) != 1)
|
|
{
|
|
SharedLogger.logger.Trace($"ADLWrapper/GenerateProfileDisplayIdentifiers: AMD Adapter #{i} ({OSAdapterInfoData.ADLAdapterInfo[i].AdapterName}) AdapterID display ID#{j} is not connected");
|
|
continue;
|
|
}
|
|
|
|
ADLDisplayConfig DisplayConfig = new ADLDisplayConfig();
|
|
if (ADL.ADL_Display_DeviceConfig_Get != null)
|
|
{
|
|
// Get the device config
|
|
ADLRet = ADL.ADL_Display_DeviceConfig_Get(OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex, DisplayInfoData[j].DisplayID.DisplayLogicalIndex, out DisplayConfig);
|
|
if (ADLRet == ADL.ADL_OK)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
// Create an array of all the important display info we need to record
|
|
List<string> displayInfoIdentifierSection = new List<string>();
|
|
displayInfoIdentifierSection.Add("AMD");
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(OSAdapterInfoData.ADLAdapterInfo[i].AdapterName);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting AMD Adapter Name from video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex.ToString());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting AMD Adapter Index from video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(OSAdapterInfoData.ADLAdapterInfo[i].VendorID.ToString());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting AMD VendorID from video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("1002");
|
|
}
|
|
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(AdapterID.ToString());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting AMD AdapterID from video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
try
|
|
{
|
|
ADL.ADLConnectionType connector = (ADL.ADLConnectionType)DisplayInfoData[j].DisplayOutputType;
|
|
displayInfoIdentifierSection.Add(connector.ToString());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting AMD Display Connector from video card to display. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(DisplayInfoData[j].DisplayManufacturerName);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting Display manufacturer from AMD video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
try
|
|
{
|
|
displayInfoIdentifierSection.Add(DisplayInfoData[j].DisplayName);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ADLWrapper/GenerateProfileDisplayIdentifiers: Exception getting Display Name from AMD video card. Substituting with a # instead");
|
|
displayInfoIdentifierSection.Add("#");
|
|
}
|
|
|
|
// Create a display identifier out of it
|
|
string displayIdentifier = String.Join("|", displayInfoIdentifierSection);
|
|
// Add it to the list of display identifiers so we can return it
|
|
displayIdentifiers.Add(displayIdentifier);
|
|
|
|
SharedLogger.logger.Debug($"ProfileRepository/GenerateProfileDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}");
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("ADL_Display_DisplayInfo_Get() returned error code " + ADLRet.ToString());
|
|
}
|
|
// Release the memory for the DisplayInfo structure
|
|
if (IntPtr.Zero != DisplayBuffer)
|
|
Marshal.FreeCoTaskMem(DisplayBuffer);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("ADL_Adapter_Active_Get() returned error code " + ADLRet.ToString());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("ADL_Adapter_AdapterInfo_Get() returned error code " + ADLRet.ToString());
|
|
}
|
|
}
|
|
// Release the memory for the AdapterInfo structure
|
|
if (IntPtr.Zero != AdapterBuffer)
|
|
{
|
|
Marshal.FreeCoTaskMem(AdapterBuffer);
|
|
}
|
|
|
|
// Return all the identifiers we've found
|
|
return displayIdentifiers;
|
|
}
|
|
else
|
|
{
|
|
SharedLogger.logger.Error($"ADLWrapper/GenerateProfileDisplayIdentifiers: There were no AMD adapters found by AMD ADL.");
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|