mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Updated NVIDIALibrary and WinLibrary based on NVIDIAInfo testing
Added in the ability to map the Windows CCD Display name to NVAPI DisplayId, which will make it possible to use that information within DisplayMagician.
This commit is contained in:
@ -1025,6 +1025,27 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
public static bool operator !=(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 lhs, NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 rhs) => !(lhs == rhs);
|
public static bool operator !=(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 lhs, NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 rhs) => !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||||
|
public struct NV_DISPLAYCONFIG_PATH_TARGET_INFO_V1 : IEquatable<NV_DISPLAYCONFIG_PATH_TARGET_INFO_V1>
|
||||||
|
{
|
||||||
|
public UInt32 DisplayId; //!< Display ID
|
||||||
|
NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO Details; //!< May be NULL if no advanced settings are required
|
||||||
|
|
||||||
|
public override bool Equals(object obj) => obj is NV_DISPLAYCONFIG_PATH_TARGET_INFO_V1 other && this.Equals(other);
|
||||||
|
|
||||||
|
public bool Equals(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V1 other)
|
||||||
|
=> DisplayId == other.DisplayId &&
|
||||||
|
Details.Equals(other.Details);
|
||||||
|
|
||||||
|
public override Int32 GetHashCode()
|
||||||
|
{
|
||||||
|
return (DisplayId, Details).GetHashCode();
|
||||||
|
}
|
||||||
|
public static bool operator ==(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V1 lhs, NV_DISPLAYCONFIG_PATH_TARGET_INFO_V1 rhs) => lhs.Equals(rhs);
|
||||||
|
|
||||||
|
public static bool operator !=(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V1 lhs, NV_DISPLAYCONFIG_PATH_TARGET_INFO_V1 rhs) => !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct NV_DISPLAYCONFIG_PATH_INFO_V2 : IEquatable<NV_DISPLAYCONFIG_PATH_INFO_V2> // Version is 2
|
public struct NV_DISPLAYCONFIG_PATH_INFO_V2 : IEquatable<NV_DISPLAYCONFIG_PATH_INFO_V2> // Version is 2
|
||||||
{
|
{
|
||||||
@ -1032,12 +1053,15 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
public UInt32 SourceId; //!< Identifies sourceId used by Windows CCD. This can be optionally set.
|
public UInt32 SourceId; //!< Identifies sourceId used by Windows CCD. This can be optionally set.
|
||||||
|
|
||||||
public UInt32 TargetInfoCount; //!< Number of elements in targetInfo array
|
public UInt32 TargetInfoCount; //!< Number of elements in targetInfo array
|
||||||
public NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 TargetInfo;
|
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||||
public NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1 sourceModeInfo; //!< May be NULL if mode info is not important
|
public NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2[] TargetInfo;
|
||||||
|
public NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1 SourceModeInfo; //!< May be NULL if mode info is not important
|
||||||
//public UInt32 IsNonNVIDIAAdapter : 1; //!< True for non-NVIDIA adapter.
|
//public UInt32 IsNonNVIDIAAdapter : 1; //!< True for non-NVIDIA adapter.
|
||||||
//public UInt32 reserved : 31; //!< Must be 0
|
//public UInt32 reserved : 31; //!< Must be 0
|
||||||
//public LUID pOSAdapterID; //!< Used by Non-NVIDIA adapter for poInt32er to OS Adapter of LUID
|
//public LUID pOSAdapterID; //!< Used by Non-NVIDIA adapter for poInt32er to OS Adapter of LUID
|
||||||
//!< type, type casted to void *.
|
//!< type, type casted to void *.
|
||||||
|
public UInt32 Reserved;
|
||||||
|
public IntPtr OSAdapterID;
|
||||||
|
|
||||||
public override bool Equals(object obj) => obj is NV_DISPLAYCONFIG_PATH_INFO_V2 other && this.Equals(other);
|
public override bool Equals(object obj) => obj is NV_DISPLAYCONFIG_PATH_INFO_V2 other && this.Equals(other);
|
||||||
|
|
||||||
@ -1046,17 +1070,53 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
SourceId == other.SourceId &&
|
SourceId == other.SourceId &&
|
||||||
TargetInfoCount == other.TargetInfoCount &&
|
TargetInfoCount == other.TargetInfoCount &&
|
||||||
TargetInfo.Equals(other.TargetInfo) &&
|
TargetInfo.Equals(other.TargetInfo) &&
|
||||||
sourceModeInfo.Equals(other.sourceModeInfo);
|
SourceModeInfo.Equals(other.SourceModeInfo) &&
|
||||||
|
Reserved == other.Reserved &&
|
||||||
|
OSAdapterID == other.OSAdapterID;
|
||||||
|
|
||||||
public override Int32 GetHashCode()
|
public override Int32 GetHashCode()
|
||||||
{
|
{
|
||||||
return (Version, SourceId, TargetInfoCount, TargetInfo, sourceModeInfo).GetHashCode();
|
return (Version, SourceId, TargetInfoCount, TargetInfo, SourceModeInfo).GetHashCode();
|
||||||
}
|
}
|
||||||
public static bool operator ==(NV_DISPLAYCONFIG_PATH_INFO_V2 lhs, NV_DISPLAYCONFIG_PATH_INFO_V2 rhs) => lhs.Equals(rhs);
|
public static bool operator ==(NV_DISPLAYCONFIG_PATH_INFO_V2 lhs, NV_DISPLAYCONFIG_PATH_INFO_V2 rhs) => lhs.Equals(rhs);
|
||||||
|
|
||||||
public static bool operator !=(NV_DISPLAYCONFIG_PATH_INFO_V2 lhs, NV_DISPLAYCONFIG_PATH_INFO_V2 rhs) => !(lhs == rhs);
|
public static bool operator !=(NV_DISPLAYCONFIG_PATH_INFO_V2 lhs, NV_DISPLAYCONFIG_PATH_INFO_V2 rhs) => !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct NV_DISPLAYCONFIG_PATH_INFO_V1 : IEquatable<NV_DISPLAYCONFIG_PATH_INFO_V1> // Version is 1
|
||||||
|
{
|
||||||
|
public UInt32 Version;
|
||||||
|
public UInt32 SourceId; //!< Identifies sourceId used by Windows CCD. This can be optionally set.
|
||||||
|
|
||||||
|
public UInt32 TargetInfoCount; //!< Number of elements in targetInfo array
|
||||||
|
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||||
|
public NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2[] TargetInfo;
|
||||||
|
public NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1 SourceModeInfo; //!< May be NULL if mode info is not important
|
||||||
|
//public UInt32 IsNonNVIDIAAdapter : 1; //!< True for non-NVIDIA adapter.
|
||||||
|
//public UInt32 reserved : 31; //!< Must be 0
|
||||||
|
//public LUID pOSAdapterID; //!< Used by Non-NVIDIA adapter for poInt32er to OS Adapter of LUID
|
||||||
|
//!< type, type casted to void *.
|
||||||
|
|
||||||
|
public override bool Equals(object obj) => obj is NV_DISPLAYCONFIG_PATH_INFO_V1 other && this.Equals(other);
|
||||||
|
|
||||||
|
public bool Equals(NV_DISPLAYCONFIG_PATH_INFO_V1 other)
|
||||||
|
=> Version == other.Version &&
|
||||||
|
SourceId == other.SourceId &&
|
||||||
|
TargetInfoCount == other.TargetInfoCount &&
|
||||||
|
TargetInfo.Equals(other.TargetInfo) &&
|
||||||
|
SourceModeInfo.Equals(other.SourceModeInfo);
|
||||||
|
|
||||||
|
public override Int32 GetHashCode()
|
||||||
|
{
|
||||||
|
return (Version, SourceId, TargetInfoCount, TargetInfo, SourceModeInfo).GetHashCode();
|
||||||
|
}
|
||||||
|
public static bool operator ==(NV_DISPLAYCONFIG_PATH_INFO_V1 lhs, NV_DISPLAYCONFIG_PATH_INFO_V1 rhs) => lhs.Equals(rhs);
|
||||||
|
|
||||||
|
public static bool operator !=(NV_DISPLAYCONFIG_PATH_INFO_V1 lhs, NV_DISPLAYCONFIG_PATH_INFO_V1 rhs) => !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||||
public struct NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1 : IEquatable<NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1>
|
public struct NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1 : IEquatable<NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1>
|
||||||
{
|
{
|
||||||
@ -1880,6 +1940,8 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
public static UInt32 NV_GPU_DISPLAYIDS_V2_VER = MAKE_NVAPI_VERSION<NV_GPU_DISPLAYIDS_V2>(3); // NOTE: There is a bug in R470 that sets the NV_GPU_DISPLAYIDS_V2 version to 3!
|
public static UInt32 NV_GPU_DISPLAYIDS_V2_VER = MAKE_NVAPI_VERSION<NV_GPU_DISPLAYIDS_V2>(3); // NOTE: There is a bug in R470 that sets the NV_GPU_DISPLAYIDS_V2 version to 3!
|
||||||
public static UInt32 NV_BOARD_INFO_V1_VER = MAKE_NVAPI_VERSION<NV_BOARD_INFO_V1>(1);
|
public static UInt32 NV_BOARD_INFO_V1_VER = MAKE_NVAPI_VERSION<NV_BOARD_INFO_V1>(1);
|
||||||
public static UInt32 NV_EDID_V3_VER = MAKE_NVAPI_VERSION<NV_EDID_V3>(3);
|
public static UInt32 NV_EDID_V3_VER = MAKE_NVAPI_VERSION<NV_EDID_V3>(3);
|
||||||
|
public static UInt32 NV_DISPLAYCONFIG_PATH_INFO_V1_VER = MAKE_NVAPI_VERSION<NV_DISPLAYCONFIG_PATH_INFO_V1>(1);
|
||||||
|
public static UInt32 NV_DISPLAYCONFIG_PATH_INFO_V2_VER = MAKE_NVAPI_VERSION<NV_DISPLAYCONFIG_PATH_INFO_V2>(2);
|
||||||
|
|
||||||
|
|
||||||
#region Internal Constant
|
#region Internal Constant
|
||||||
@ -1901,6 +1963,10 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
{
|
{
|
||||||
return (UInt32)((Marshal.SizeOf(typeof(T))) | (Int32)(version << 16));
|
return (UInt32)((Marshal.SizeOf(typeof(T))) | (Int32)(version << 16));
|
||||||
}
|
}
|
||||||
|
private static UInt32 MAKE_NVAPI_VERSION(Int32 size, Int32 version)
|
||||||
|
{
|
||||||
|
return (UInt32)((Int32)size | (Int32)(version << 16));
|
||||||
|
}
|
||||||
|
|
||||||
private static void GetDelegate<T>(UInt32 apiId, out T newDelegate) where T : class
|
private static void GetDelegate<T>(UInt32 apiId, out T newDelegate) where T : class
|
||||||
{
|
{
|
||||||
@ -2008,7 +2074,9 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
GetDelegate(NvId_DISP_GetGDIPrimaryDisplayId, out DISP_GetGDIPrimaryDisplayIdInternal);
|
GetDelegate(NvId_DISP_GetGDIPrimaryDisplayId, out DISP_GetGDIPrimaryDisplayIdInternal);
|
||||||
GetDelegate(NvId_Disp_GetHdrCapabilities, out Disp_GetHdrCapabilitiesInternal);
|
GetDelegate(NvId_Disp_GetHdrCapabilities, out Disp_GetHdrCapabilitiesInternal);
|
||||||
GetDelegate(NvId_Disp_HdrColorControl, out Disp_HdrColorControlInternal);
|
GetDelegate(NvId_Disp_HdrColorControl, out Disp_HdrColorControlInternal);
|
||||||
|
GetDelegate(NvId_DISP_GetDisplayConfig, out DISP_GetDisplayConfigInternal);
|
||||||
|
GetDelegate(NvId_DISP_GetDisplayConfig, out DISP_GetDisplayConfigInternalNull); // null version of the submission
|
||||||
|
GetDelegate(NvId_DISP_GetDisplayIdByDisplayName, out DISP_GetDisplayIdByDisplayNameInternal);
|
||||||
|
|
||||||
// GPUs
|
// GPUs
|
||||||
GetDelegate(NvId_EnumPhysicalGPUs, out EnumPhysicalGPUsInternal);
|
GetDelegate(NvId_EnumPhysicalGPUs, out EnumPhysicalGPUsInternal);
|
||||||
@ -3060,6 +3128,189 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
// ******** IMPORTANT! This code has an error when attempting to perform the third pass as required by NVAPI documentation *********
|
||||||
|
// ******** FOr this reason I have disabled the code as I don't actually need to get it going. ********
|
||||||
|
/* // NVAPI_INTERFACE NvAPI_DISP_GetDisplayConfig(__inout NvU32 *pathInfoCount, __out_ecount_full_opt(*pathInfoCount) NV_DISPLAYCONFIG_PATH_INFO *pathInfo);
|
||||||
|
private delegate NVAPI_STATUS DISP_GetDisplayConfigDelegate(
|
||||||
|
[In][Out] ref UInt32 pathInfoCount,
|
||||||
|
[In][Out] IntPtr pathInfoBuffer);
|
||||||
|
private static readonly DISP_GetDisplayConfigDelegate DISP_GetDisplayConfigInternal;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DESCRIPTION: This API lets caller retrieve the current global display configuration.
|
||||||
|
/// USAGE: The caller might have to call this three times to fetch all the required configuration details as follows:
|
||||||
|
/// First Pass: Caller should Call NvAPI_DISP_GetDisplayConfig() with pathInfo set to NULL to fetch pathInfoCount.
|
||||||
|
/// Second Pass: Allocate memory for pathInfo with respect to the number of pathInfoCount(from First Pass) to fetch
|
||||||
|
/// targetInfoCount. If sourceModeInfo is needed allocate memory or it can be initialized to NULL.
|
||||||
|
/// Third Pass(Optional, only required if target information is required): Allocate memory for targetInfo with respect
|
||||||
|
// to number of targetInfoCount(from Second Pass).
|
||||||
|
/// SUPPORTED OS: Windows 7 and higher
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="PathInfoCount"></param>
|
||||||
|
/// <param name="PathInfo"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static NVAPI_STATUS NvAPI_DISP_GetDisplayConfig(ref UInt32 PathInfoCount, ref NV_DISPLAYCONFIG_PATH_INFO_V1[] PathInfos, bool partFilledIn = false)
|
||||||
|
{
|
||||||
|
NVAPI_STATUS status;
|
||||||
|
IntPtr pathInfoBuffer = IntPtr.Zero;
|
||||||
|
IntPtr currentPathInfoBuffer = IntPtr.Zero;
|
||||||
|
if (partFilledIn)
|
||||||
|
{
|
||||||
|
// Copy the supplied object for the third pass (when we have the pathInfoCount and the targetInfoCount for each pathInfo, but we want the details)
|
||||||
|
//NV_DISPLAYCONFIG_PATH_INFO_V1[] passedPathInfo = PathInfos;
|
||||||
|
//PathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V1[PathInfoCount];
|
||||||
|
// Go through the array and create the structure
|
||||||
|
int overallTargetCount = 0;
|
||||||
|
for (Int32 x = 0; x < (Int32)PathInfoCount; x++)
|
||||||
|
{
|
||||||
|
// Copy the information passed in, into the buffer we want to pass
|
||||||
|
//PathInfos[x].Version = MAKE_NVAPI_VERSION(Marshal.SizeOf(passedPathInfo[x]),1);
|
||||||
|
*//*PathInfos[x].SourceId = passedPathInfo[x].SourceId;
|
||||||
|
PathInfos[x].TargetInfoCount = passedPathInfo[x].TargetInfoCount;
|
||||||
|
PathInfos[x].TargetInfo = passedPathInfo[x].TargetInfo;
|
||||||
|
PathInfos[x].SourceModeInfo = = passedPathInfo[x].SourceModeInfo;*//*
|
||||||
|
overallTargetCount += (int)PathInfos[x].TargetInfoCount;
|
||||||
|
}
|
||||||
|
// Initialize unmanged memory to hold the unmanaged array of structs
|
||||||
|
int memorySizeRequired = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_INFO_V1)) * (int)PathInfoCount;
|
||||||
|
pathInfoBuffer = Marshal.AllocCoTaskMem(memorySizeRequired);
|
||||||
|
// Also set another memory pointer to the same place so that we can do the memory copying item by item
|
||||||
|
// as we have to do it ourselves (there isn't an easy to use Marshal equivalent)
|
||||||
|
currentPathInfoBuffer = pathInfoBuffer;
|
||||||
|
// Go through the array and copy things from managed code to unmanaged code
|
||||||
|
for (Int32 x = 0; x < (Int32)PathInfoCount; x++)
|
||||||
|
{
|
||||||
|
// Marshal a single gridtopology into unmanaged code ready for sending to the unmanaged NVAPI function
|
||||||
|
Marshal.StructureToPtr(PathInfos[x], currentPathInfoBuffer, false);
|
||||||
|
// advance the buffer forwards to the next object
|
||||||
|
currentPathInfoBuffer = (IntPtr)((long)currentPathInfoBuffer + Marshal.SizeOf(PathInfos[x]));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Build a new blank object for the second pass (when we have the pathInfoCount, but want the targetInfoCount for each pathInfo)
|
||||||
|
// Build a managed structure for us to use as a data source for another object that the unmanaged NVAPI C library can use
|
||||||
|
PathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V1[PathInfoCount];
|
||||||
|
// Initialize unmanged memory to hold the unmanaged array of structs
|
||||||
|
pathInfoBuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_INFO_V1)) * (int)PathInfoCount);
|
||||||
|
// Also set another memory pointer to the same place so that we can do the memory copying item by item
|
||||||
|
// as we have to do it ourselves (there isn't an easy to use Marshal equivalent)
|
||||||
|
currentPathInfoBuffer = pathInfoBuffer;
|
||||||
|
// Go through the array and copy things from managed code to unmanaged code
|
||||||
|
for (Int32 x = 0; x < (Int32)PathInfoCount; x++)
|
||||||
|
{
|
||||||
|
PathInfos[x].Version = MAKE_NVAPI_VERSION(Marshal.SizeOf(PathInfos[x]), 1);
|
||||||
|
PathInfos[x].SourceModeInfo = new NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1();
|
||||||
|
// Marshal a single gridtopology into unmanaged code ready for sending to the unmanaged NVAPI function
|
||||||
|
Marshal.StructureToPtr(PathInfos[x], currentPathInfoBuffer, false);
|
||||||
|
// advance the buffer forwards to the next object
|
||||||
|
currentPathInfoBuffer = (IntPtr)((long)currentPathInfoBuffer + Marshal.SizeOf(PathInfos[x]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (DISP_GetDisplayConfigInternal != null)
|
||||||
|
{
|
||||||
|
// Use the unmanaged buffer in the unmanaged C call
|
||||||
|
status = DISP_GetDisplayConfigInternal(ref PathInfoCount, pathInfoBuffer);
|
||||||
|
|
||||||
|
if (status == NVAPI_STATUS.NVAPI_OK)
|
||||||
|
{
|
||||||
|
// If everything worked, then copy the data back from the unmanaged array into the managed array
|
||||||
|
// So that we can use it in C# land
|
||||||
|
// Reset the memory pointer we're using for tracking where we are back to the start of the unmanaged memory buffer
|
||||||
|
currentPathInfoBuffer = pathInfoBuffer;
|
||||||
|
// Create a managed array to store the received information within
|
||||||
|
PathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V1[PathInfoCount];
|
||||||
|
// Go through the memory buffer item by item and copy the items into the managed array
|
||||||
|
for (int i = 0; i < PathInfoCount; i++)
|
||||||
|
{
|
||||||
|
// build a structure in the array slot
|
||||||
|
PathInfos[i] = new NV_DISPLAYCONFIG_PATH_INFO_V1();
|
||||||
|
// fill the array slot structure with the data from the buffer
|
||||||
|
PathInfos[i] = (NV_DISPLAYCONFIG_PATH_INFO_V1)Marshal.PtrToStructure(currentPathInfoBuffer, typeof(NV_DISPLAYCONFIG_PATH_INFO_V1));
|
||||||
|
// destroy the bit of memory we no longer need
|
||||||
|
Marshal.DestroyStructure(currentPathInfoBuffer, typeof(NV_DISPLAYCONFIG_PATH_INFO_V1));
|
||||||
|
// advance the buffer forwards to the next object
|
||||||
|
currentPathInfoBuffer = (IntPtr)((long)currentPathInfoBuffer + Marshal.SizeOf(PathInfos[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
Marshal.FreeCoTaskMem(pathInfoBuffer);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NVAPI_INTERFACE NvAPI_DISP_GetDisplayConfig(__inout NvU32 *pathInfoCount, __out_ecount_full_opt(*pathInfoCount) NV_DISPLAYCONFIG_PATH_INFO *pathInfo);
|
||||||
|
// NvAPIMosaic_EnumDisplayGrids
|
||||||
|
private delegate NVAPI_STATUS DISP_GetDisplayConfigDelegateNull(
|
||||||
|
[In][Out] ref UInt32 pathInfoCount,
|
||||||
|
[In][Out] IntPtr pathInfoBuffer);
|
||||||
|
private static readonly DISP_GetDisplayConfigDelegateNull DISP_GetDisplayConfigInternalNull;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DESCRIPTION: This API lets caller retrieve the current global display configuration.
|
||||||
|
/// USAGE: The caller might have to call this three times to fetch all the required configuration details as follows:
|
||||||
|
/// First Pass: Caller should Call NvAPI_DISP_GetDisplayConfig() with pathInfo set to NULL to fetch pathInfoCount.
|
||||||
|
/// Second Pass: Allocate memory for pathInfo with respect to the number of pathInfoCount(from First Pass) to fetch
|
||||||
|
/// targetInfoCount. If sourceModeInfo is needed allocate memory or it can be initialized to NULL.
|
||||||
|
/// Third Pass(Optional, only required if target information is required): Allocate memory for targetInfo with respect
|
||||||
|
// to number of targetInfoCount(from Second Pass).
|
||||||
|
/// SUPPORTED OS: Windows 7 and higher
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="PathInfoCount"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static NVAPI_STATUS NvAPI_DISP_GetDisplayConfig(ref UInt32 PathInfoCount)
|
||||||
|
{
|
||||||
|
NVAPI_STATUS status;
|
||||||
|
IntPtr pathInfos = IntPtr.Zero;
|
||||||
|
|
||||||
|
if (DISP_GetDisplayConfigInternalNull != null) { status = DISP_GetDisplayConfigInternalNull(ref PathInfoCount, pathInfos); }
|
||||||
|
else { status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND; }
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
// NVAPI_INTERFACE NvAPI_DISP_GetDisplayIdByDisplayName(const char *displayName, NvU32* displayId);
|
||||||
|
private delegate NVAPI_STATUS DISP_GetDisplayIdByDisplayNameDelegate(
|
||||||
|
[In] string displayName,
|
||||||
|
[Out] out UInt32 displayId);
|
||||||
|
private static readonly DISP_GetDisplayIdByDisplayNameDelegate DISP_GetDisplayIdByDisplayNameInternal;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// DESCRIPTION: This API retrieves the Display Id of a given display by
|
||||||
|
/// display name. The display must be active to retrieve the
|
||||||
|
/// displayId. In the case of clone mode or Surround gaming,
|
||||||
|
/// the primary or top-left display will be returned.
|
||||||
|
///
|
||||||
|
/// \param [in] displayName Name of display (Eg: "\\DISPLAY1" to
|
||||||
|
/// retrieve the displayId for.
|
||||||
|
/// \param [out] displayId Display ID of the requested display.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="displayName"></param>
|
||||||
|
/// <param name="displayId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static NVAPI_STATUS NvAPI_DISP_GetDisplayIdByDisplayName(string displayName, out UInt32 displayId)
|
||||||
|
{
|
||||||
|
NVAPI_STATUS status;
|
||||||
|
displayId = 0;
|
||||||
|
|
||||||
|
if (DISP_GetDisplayIdByDisplayNameInternal != null) { status = DISP_GetDisplayIdByDisplayNameInternal(displayName, out displayId); }
|
||||||
|
else { status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND; }
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// EnumPhysicalGPUs
|
// EnumPhysicalGPUs
|
||||||
private delegate NVAPI_STATUS EnumPhysicalGPUsDelegate(
|
private delegate NVAPI_STATUS EnumPhysicalGPUsDelegate(
|
||||||
[In][Out][MarshalAs(UnmanagedType.LPArray, SizeConst = (int)NV_MAX_PHYSICAL_GPUS)] PhysicalGpuHandle[] gpuHandles,
|
[In][Out][MarshalAs(UnmanagedType.LPArray, SizeConst = (int)NV_MAX_PHYSICAL_GPUS)] PhysicalGpuHandle[] gpuHandles,
|
||||||
|
@ -70,22 +70,43 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
public static bool operator !=(NVIDIA_HDR_CONFIG lhs, NVIDIA_HDR_CONFIG rhs) => !(lhs == rhs);
|
public static bool operator !=(NVIDIA_HDR_CONFIG lhs, NVIDIA_HDR_CONFIG rhs) => !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct NVIDIA_WINDOWS_DISPLAY_CONFIG : IEquatable<NVIDIA_WINDOWS_DISPLAY_CONFIG>
|
||||||
|
{
|
||||||
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = (Int32)NVImport.NV_MAX_DISPLAYS)]
|
||||||
|
public NV_DISPLAYCONFIG_PATH_INFO_V2[] WindowsPaths;
|
||||||
|
|
||||||
|
public override bool Equals(object obj) => obj is NVIDIA_WINDOWS_DISPLAY_CONFIG other && this.Equals(other);
|
||||||
|
public bool Equals(NVIDIA_WINDOWS_DISPLAY_CONFIG other)
|
||||||
|
=> WindowsPaths.SequenceEqual(other.WindowsPaths);
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (WindowsPaths).GetHashCode();
|
||||||
|
}
|
||||||
|
public static bool operator ==(NVIDIA_WINDOWS_DISPLAY_CONFIG lhs, NVIDIA_WINDOWS_DISPLAY_CONFIG rhs) => lhs.Equals(rhs);
|
||||||
|
|
||||||
|
public static bool operator !=(NVIDIA_WINDOWS_DISPLAY_CONFIG lhs, NVIDIA_WINDOWS_DISPLAY_CONFIG rhs) => !(lhs == rhs);
|
||||||
|
}*/
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct NVIDIA_DISPLAY_CONFIG : IEquatable<NVIDIA_DISPLAY_CONFIG>
|
public struct NVIDIA_DISPLAY_CONFIG : IEquatable<NVIDIA_DISPLAY_CONFIG>
|
||||||
{
|
{
|
||||||
public NVIDIA_MOSAIC_CONFIG MosaicConfig;
|
public NVIDIA_MOSAIC_CONFIG MosaicConfig;
|
||||||
public NVIDIA_HDR_CONFIG HdrConfig;
|
public NVIDIA_HDR_CONFIG HdrConfig;
|
||||||
|
public Dictionary<string, UInt32> DisplayNames;
|
||||||
public List<string> DisplayIdentifiers;
|
public List<string> DisplayIdentifiers;
|
||||||
|
|
||||||
public override bool Equals(object obj) => obj is NVIDIA_DISPLAY_CONFIG other && this.Equals(other);
|
public override bool Equals(object obj) => obj is NVIDIA_DISPLAY_CONFIG other && this.Equals(other);
|
||||||
public bool Equals(NVIDIA_DISPLAY_CONFIG other)
|
public bool Equals(NVIDIA_DISPLAY_CONFIG other)
|
||||||
=> MosaicConfig.Equals(other.MosaicConfig) &&
|
=> MosaicConfig.Equals(other.MosaicConfig) &&
|
||||||
HdrConfig.Equals(other.HdrConfig) &&
|
HdrConfig.Equals(other.HdrConfig) &&
|
||||||
DisplayIdentifiers.SequenceEqual(other.DisplayIdentifiers);
|
DisplayIdentifiers.SequenceEqual(other.DisplayIdentifiers) &&
|
||||||
|
DisplayNames.Equals(other.DisplayNames);
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return (MosaicConfig, HdrConfig, DisplayIdentifiers).GetHashCode();
|
return (MosaicConfig, HdrConfig, DisplayIdentifiers, DisplayNames).GetHashCode();
|
||||||
}
|
}
|
||||||
public static bool operator ==(NVIDIA_DISPLAY_CONFIG lhs, NVIDIA_DISPLAY_CONFIG rhs) => lhs.Equals(rhs);
|
public static bool operator ==(NVIDIA_DISPLAY_CONFIG lhs, NVIDIA_DISPLAY_CONFIG rhs) => lhs.Equals(rhs);
|
||||||
|
|
||||||
@ -768,6 +789,129 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*// Get the NVIDIA Windows Display Config too
|
||||||
|
// Figure out how many pathInfo objects there are
|
||||||
|
uint pathInfoCount = 0;
|
||||||
|
NVStatus = NVImport.NvAPI_DISP_GetDisplayConfig(ref pathInfoCount);
|
||||||
|
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_DISP_GetDisplayConfig returned OK. We know we have {pathInfoCount} pathInfo objects to get");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now get the number of targetInfoCount for each returned pathInfoCount object
|
||||||
|
NV_DISPLAYCONFIG_PATH_INFO_V1[] pathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V1[pathInfoCount];
|
||||||
|
NVStatus = NVImport.NvAPI_DISP_GetDisplayConfig(ref pathInfoCount, ref pathInfos);
|
||||||
|
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_DISP_GetDisplayConfig returned OK.");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Mosaic is not supported with the existing hardware. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more argumentss passed in are invalid. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_DEVICE_BUSY)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: ModeSet has not yet completed. Please wait and call it again. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we send the same partially filled object back in a third time to get the target information
|
||||||
|
NVStatus = NVImport.NvAPI_DISP_GetDisplayConfig(ref pathInfoCount, ref pathInfos, true);
|
||||||
|
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_DISP_GetDisplayConfig returned OK.");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Mosaic is not supported with the existing hardware. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more argumentss passed in are invalid. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_DEVICE_BUSY)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: ModeSet has not yet completed. Please wait and call it again. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus}");
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
// Now we need to loop through each of the windows paths so we can record the Windows DisplayName to DisplayID mapping
|
||||||
|
// This is needed for us to piece together the Screen layout for when we draw the NVIDIA screens!
|
||||||
|
myDisplayConfig.DisplayNames = new Dictionary<string, uint>();
|
||||||
|
foreach (KeyValuePair<uint, string> displaySource in WinLibrary.GetDisplaySourceNames())
|
||||||
|
{
|
||||||
|
// Now we try to get the information about the displayIDs and map them to windows \\DISPLAY names e.g. \\DISPLAY1
|
||||||
|
string displayName = displaySource.Value;
|
||||||
|
UInt32 displayId = 0;
|
||||||
|
NVStatus = NVImport.NvAPI_DISP_GetDisplayIdByDisplayName(displayName, out displayId);
|
||||||
|
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_DISP_GetDisplayIdByDisplayName returned OK. The display {displayName} has NVIDIA DisplayID {displayId}");
|
||||||
|
myDisplayConfig.DisplayNames.Add(displayName, displayId);
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_NVIDIA_DEVICE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: GDI Primary not on an NVIDIA GPU. NvAPI_DISP_GetDisplayIdByDisplayName() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more args passed in are invalid. NvAPI_DISP_GetDisplayIdByDisplayName() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_DISP_GetDisplayIdByDisplayName() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_DISP_GetDisplayIdByDisplayName() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_DISP_GetDisplayIdByDisplayName() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_DISP_GetDisplayIdByDisplayName() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the display identifiers
|
||||||
myDisplayConfig.DisplayIdentifiers = GetCurrentDisplayIdentifiers();
|
myDisplayConfig.DisplayIdentifiers = GetCurrentDisplayIdentifiers();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -41,6 +41,7 @@ namespace DisplayMagicianShared.Windows
|
|||||||
public DISPLAYCONFIG_PATH_INFO[] DisplayConfigPaths;
|
public DISPLAYCONFIG_PATH_INFO[] DisplayConfigPaths;
|
||||||
public DISPLAYCONFIG_MODE_INFO[] DisplayConfigModes;
|
public DISPLAYCONFIG_MODE_INFO[] DisplayConfigModes;
|
||||||
public ADVANCED_HDR_INFO_PER_PATH[] DisplayHDRStates;
|
public ADVANCED_HDR_INFO_PER_PATH[] DisplayHDRStates;
|
||||||
|
public Dictionary<uint, string> DisplaySources;
|
||||||
public List<string> DisplayIdentifiers;
|
public List<string> DisplayIdentifiers;
|
||||||
|
|
||||||
public override bool Equals(object obj) => obj is WINDOWS_DISPLAY_CONFIG other && this.Equals(other);
|
public override bool Equals(object obj) => obj is WINDOWS_DISPLAY_CONFIG other && this.Equals(other);
|
||||||
@ -278,6 +279,7 @@ namespace DisplayMagicianShared.Windows
|
|||||||
WINDOWS_DISPLAY_CONFIG windowsDisplayConfig = new WINDOWS_DISPLAY_CONFIG();
|
WINDOWS_DISPLAY_CONFIG windowsDisplayConfig = new WINDOWS_DISPLAY_CONFIG();
|
||||||
windowsDisplayConfig.DisplayAdapters = new Dictionary<ulong, string>();
|
windowsDisplayConfig.DisplayAdapters = new Dictionary<ulong, string>();
|
||||||
windowsDisplayConfig.DisplayHDRStates = new ADVANCED_HDR_INFO_PER_PATH[pathCount];
|
windowsDisplayConfig.DisplayHDRStates = new ADVANCED_HDR_INFO_PER_PATH[pathCount];
|
||||||
|
windowsDisplayConfig.DisplaySources = new Dictionary<uint, string>();
|
||||||
|
|
||||||
// Now cycle through the paths and grab the HDR state information
|
// Now cycle through the paths and grab the HDR state information
|
||||||
// and map the adapter name to adapter id
|
// and map the adapter name to adapter id
|
||||||
@ -285,6 +287,24 @@ namespace DisplayMagicianShared.Windows
|
|||||||
int hdrInfoCount = 0;
|
int hdrInfoCount = 0;
|
||||||
foreach (var path in paths)
|
foreach (var path in paths)
|
||||||
{
|
{
|
||||||
|
// get display source name
|
||||||
|
var sourceInfo = new DISPLAYCONFIG_SOURCE_DEVICE_NAME();
|
||||||
|
sourceInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
||||||
|
sourceInfo.Header.Size = (uint)Marshal.SizeOf<DISPLAYCONFIG_SOURCE_DEVICE_NAME>();
|
||||||
|
sourceInfo.Header.AdapterId = path.SourceInfo.AdapterId;
|
||||||
|
sourceInfo.Header.Id = path.SourceInfo.Id;
|
||||||
|
err = CCDImport.DisplayConfigGetDeviceInfo(ref sourceInfo);
|
||||||
|
if (err == WIN32STATUS.ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
// Store it for later
|
||||||
|
windowsDisplayConfig.DisplaySources.Add(path.SourceInfo.Id, sourceInfo.ViewGdiDeviceName);
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found Display Source {sourceInfo.ViewGdiDeviceName} for source {path.SourceInfo.Id}.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"WinLibrary/PrintActiveConfig: WARNING - DisplayConfigGetDeviceInfo returned WIN32STATUS {err} when trying to get the source info for source adapter #{path.SourceInfo.AdapterId}");
|
||||||
|
}
|
||||||
|
|
||||||
// Get adapter ID for later
|
// Get adapter ID for later
|
||||||
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Attempting to get adapter name for adapter {path.TargetInfo.AdapterId.Value}.");
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Attempting to get adapter name for adapter {path.TargetInfo.AdapterId.Value}.");
|
||||||
if (!windowsDisplayConfig.DisplayAdapters.ContainsKey(path.TargetInfo.AdapterId.Value))
|
if (!windowsDisplayConfig.DisplayAdapters.ContainsKey(path.TargetInfo.AdapterId.Value))
|
||||||
@ -374,6 +394,88 @@ namespace DisplayMagicianShared.Windows
|
|||||||
return windowsDisplayConfig;
|
return windowsDisplayConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Dictionary<uint, string> GetDisplaySourceNames()
|
||||||
|
{
|
||||||
|
// Get the size of the largest Active Paths and Modes arrays
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Getting the size of the largest Active Paths and Modes arrays");
|
||||||
|
int pathCount = 0;
|
||||||
|
int modeCount = 0;
|
||||||
|
WIN32STATUS err = CCDImport.GetDisplayConfigBufferSizes(QDC.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
|
||||||
|
if (err != WIN32STATUS.ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: ERROR - GetDisplayConfigBufferSizes returned WIN32STATUS {err} when trying to get the maximum path and mode sizes");
|
||||||
|
throw new WinLibraryException($"GetDisplayConfigBufferSizes returned WIN32STATUS {err} when trying to get the maximum path and mode sizes");
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Getting the current Display Config path and mode arrays");
|
||||||
|
var paths = new DISPLAYCONFIG_PATH_INFO[pathCount];
|
||||||
|
var modes = new DISPLAYCONFIG_MODE_INFO[modeCount];
|
||||||
|
err = CCDImport.QueryDisplayConfig(QDC.QDC_ONLY_ACTIVE_PATHS, ref pathCount, paths, ref modeCount, modes, IntPtr.Zero);
|
||||||
|
if (err == WIN32STATUS.ERROR_INSUFFICIENT_BUFFER)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: The displays were modified between GetDisplayConfigBufferSizes and QueryDisplayConfig so we need to get the buffer sizes again.");
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Getting the size of the largest Active Paths and Modes arrays");
|
||||||
|
// Screen changed in between GetDisplayConfigBufferSizes and QueryDisplayConfig, so we need to get buffer sizes again
|
||||||
|
// as per https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-querydisplayconfig
|
||||||
|
err = CCDImport.GetDisplayConfigBufferSizes(QDC.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
|
||||||
|
if (err != WIN32STATUS.ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: ERROR - GetDisplayConfigBufferSizes returned WIN32STATUS {err} when trying to get the maximum path and mode sizes again");
|
||||||
|
throw new WinLibraryException($"GetDisplayConfigBufferSizes returned WIN32STATUS {err} when trying to get the maximum path and mode sizes again");
|
||||||
|
}
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Getting the current Display Config path and mode arrays");
|
||||||
|
paths = new DISPLAYCONFIG_PATH_INFO[pathCount];
|
||||||
|
modes = new DISPLAYCONFIG_MODE_INFO[modeCount];
|
||||||
|
err = CCDImport.QueryDisplayConfig(QDC.QDC_ONLY_ACTIVE_PATHS, ref pathCount, paths, ref modeCount, modes, IntPtr.Zero);
|
||||||
|
if (err == WIN32STATUS.ERROR_INSUFFICIENT_BUFFER)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: ERROR - The displays were still modified between GetDisplayConfigBufferSizes and QueryDisplayConfig, even though we tried twice. Something is wrong.");
|
||||||
|
throw new WinLibraryException($"The displays were still modified between GetDisplayConfigBufferSizes and QueryDisplayConfig, even though we tried twice. Something is wrong.");
|
||||||
|
}
|
||||||
|
else if (err != WIN32STATUS.ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: ERROR - QueryDisplayConfig returned WIN32STATUS {err} when trying to query all available displays again");
|
||||||
|
throw new WinLibraryException($"QueryDisplayConfig returned WIN32STATUS {err} when trying to query all available displays again.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (err != WIN32STATUS.ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: ERROR - QueryDisplayConfig returned WIN32STATUS {err} when trying to query all available displays");
|
||||||
|
throw new WinLibraryException($"QueryDisplayConfig returned WIN32STATUS {err} when trying to query all available displays.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the empty DisplaySources dictionary
|
||||||
|
Dictionary<uint, string> DisplaySources = new Dictionary<uint, string>();
|
||||||
|
|
||||||
|
// Now cycle through the paths and grab the HDR state information
|
||||||
|
// and map the adapter name to adapter id
|
||||||
|
var hdrInfos = new ADVANCED_HDR_INFO_PER_PATH[pathCount];
|
||||||
|
int hdrInfoCount = 0;
|
||||||
|
foreach (var path in paths)
|
||||||
|
{
|
||||||
|
// get display source name
|
||||||
|
var sourceInfo = new DISPLAYCONFIG_SOURCE_DEVICE_NAME();
|
||||||
|
sourceInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
||||||
|
sourceInfo.Header.Size = (uint)Marshal.SizeOf<DISPLAYCONFIG_SOURCE_DEVICE_NAME>();
|
||||||
|
sourceInfo.Header.AdapterId = path.SourceInfo.AdapterId;
|
||||||
|
sourceInfo.Header.Id = path.SourceInfo.Id;
|
||||||
|
err = CCDImport.DisplayConfigGetDeviceInfo(ref sourceInfo);
|
||||||
|
if (err == WIN32STATUS.ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
// Store it for later
|
||||||
|
DisplaySources.Add(path.SourceInfo.Id, sourceInfo.ViewGdiDeviceName);
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found Display Source {sourceInfo.ViewGdiDeviceName} for source {path.SourceInfo.Id}.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"WinLibrary/PrintActiveConfig: WARNING - DisplayConfigGetDeviceInfo returned WIN32STATUS {err} when trying to get the source info for source adapter #{path.SourceInfo.AdapterId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return DisplaySources;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private LUID AdapterValueToLUID(ulong adapterValue)
|
private LUID AdapterValueToLUID(ulong adapterValue)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user