mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Updated NVIDIA, AMD and Windows Video libraries
Updated with enhancements to make application of colour more robust, and to avoid a Windows CCD display validation issue.
This commit is contained in:
parent
2b653999dd
commit
d4494aa699
@ -1336,13 +1336,11 @@ namespace DisplayMagicianShared.AMD
|
||||
// We need to change to an Eyefinity (SLS) profile, so we need to apply the new SLS Topologies
|
||||
SharedLogger.logger.Trace($"AMDLibrary/SetActiveConfig: SLS is enabled in the new display configuration, so we need to set it");
|
||||
|
||||
SharedLogger.logger.Trace($"AMDLibrary/SetActiveConfig: There are {displayConfig.SlsConfig.SLSMapConfigs.Count} SLSMapConfigs in this display configuration");
|
||||
|
||||
foreach (AMD_SLSMAP_CONFIG slsMapConfig in displayConfig.SlsConfig.SLSMapConfigs)
|
||||
{
|
||||
// Attempt to turn on this SLS Map Config if it exists in the AMD Radeon driver config database
|
||||
ADLRet = ADLImport.ADL2_Display_SLSMapConfig_SetState(_adlContextHandle, slsMapConfig.SLSMap.AdapterIndex, slsMapConfig.SLSMap.SLSMapIndex, ADLImport.ADL_TRUE);
|
||||
if (ADLRet == ADL_STATUS.ADL_OK || ADLRet == ADL_STATUS.ADL_OK_MODE_CHANGE || ADLRet == ADL_STATUS.ADL_OK_RESTART || ADLRet == ADL_STATUS.ADL_OK_WAIT || ADLRet == ADL_STATUS.ADL_OK_WARNING)
|
||||
if (ADLRet == ADL_STATUS.ADL_OK)
|
||||
{
|
||||
SharedLogger.logger.Trace($"AMDLibrary/SetActiveConfig: ADL2_Display_SLSMapConfig_SetState successfully set the SLSMAP with index {slsMapConfig.SLSMap.SLSMapIndex} to TRUE for adapter { slsMapConfig.SLSMap.AdapterIndex}.");
|
||||
}
|
||||
@ -1360,7 +1358,7 @@ namespace DisplayMagicianShared.AMD
|
||||
int supportedSLSLayoutImageMode;
|
||||
int reasonForNotSupportSLS;
|
||||
ADLRet = ADLImport.ADL2_Display_SLSMapConfig_Valid(_adlContextHandle, slsMapConfig.SLSMap.AdapterIndex, slsMapConfig.SLSMap, slsMapConfig.SLSTargets.Count, slsMapConfig.SLSTargets.ToArray(), out supportedSLSLayoutImageMode, out reasonForNotSupportSLS, ADLImport.ADL_DISPLAY_SLSMAPCONFIG_CREATE_OPTION_RELATIVETO_CURRENTANGLE);
|
||||
if (ADLRet == ADL_STATUS.ADL_OK || ADLRet == ADL_STATUS.ADL_OK_MODE_CHANGE || ADLRet == ADL_STATUS.ADL_OK_RESTART || ADLRet == ADL_STATUS.ADL_OK_WAIT || ADLRet == ADL_STATUS.ADL_OK_WARNING)
|
||||
if (ADLRet == ADL_STATUS.ADL_OK)
|
||||
{
|
||||
SharedLogger.logger.Trace($"AMDLibrary/SetActiveConfig: ADL2_Display_SLSMapConfig_Valid successfully validated a new SLSMAP config for adapter { slsMapConfig.SLSMap.AdapterIndex}.");
|
||||
}
|
||||
@ -1373,7 +1371,7 @@ namespace DisplayMagicianShared.AMD
|
||||
// Create and apply the new SLSMap
|
||||
int newSlsMapIndex;
|
||||
ADLRet = ADLImport.ADL2_Display_SLSMapConfig_Create(_adlContextHandle, slsMapConfig.SLSMap.AdapterIndex, slsMapConfig.SLSMap, slsMapConfig.SLSTargets.Count, slsMapConfig.SLSTargets.ToArray(), slsMapConfig.BezelModePercent, out newSlsMapIndex, ADLImport.ADL_DISPLAY_SLSMAPCONFIG_CREATE_OPTION_RELATIVETO_CURRENTANGLE);
|
||||
if (ADLRet == ADL_STATUS.ADL_OK || ADLRet == ADL_STATUS.ADL_OK_MODE_CHANGE || ADLRet == ADL_STATUS.ADL_OK_RESTART || ADLRet == ADL_STATUS.ADL_OK_WAIT || ADLRet == ADL_STATUS.ADL_OK_WARNING)
|
||||
if (ADLRet == ADL_STATUS.ADL_OK)
|
||||
{
|
||||
if (newSlsMapIndex != -1)
|
||||
{
|
||||
@ -1411,7 +1409,7 @@ namespace DisplayMagicianShared.AMD
|
||||
{
|
||||
// Turn off this SLS Map Config
|
||||
ADLRet = ADLImport.ADL2_Display_SLSMapConfig_SetState(_adlContextHandle, slsMapConfig.SLSMap.AdapterIndex, slsMapConfig.SLSMap.SLSMapIndex, ADLImport.ADL_FALSE);
|
||||
if (ADLRet == ADL_STATUS.ADL_OK || ADLRet == ADL_STATUS.ADL_OK_MODE_CHANGE || ADLRet == ADL_STATUS.ADL_OK_RESTART || ADLRet == ADL_STATUS.ADL_OK_WAIT || ADLRet == ADL_STATUS.ADL_OK_WARNING)
|
||||
if (ADLRet == ADL_STATUS.ADL_OK)
|
||||
{
|
||||
SharedLogger.logger.Trace($"AMDLibrary/SetActiveConfig: ADL2_Display_SLSMapConfig_SetState successfully disabled the SLSMAP with index {slsMapConfig.SLSMap.SLSMapIndex} for adapter { slsMapConfig.SLSMap.AdapterIndex}.");
|
||||
}
|
||||
@ -1423,10 +1421,6 @@ namespace DisplayMagicianShared.AMD
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Trace($"AMDLibrary/SetActiveConfig: SLS is not used in the wanted display configuration, or the current display configuration. Nothing to do.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1457,34 +1451,42 @@ namespace DisplayMagicianShared.AMD
|
||||
// Try and find the HDR config displays in the list of currently connected displays
|
||||
foreach (var displayInfoItem in ActiveDisplayConfig.DisplayTargets)
|
||||
{
|
||||
// If we find the HDR config display in the list of currently connected displays then try to set the HDR setting we recorded earlier
|
||||
if (hdrConfig.Key == displayInfoItem.DisplayID.DisplayLogicalIndex)
|
||||
try
|
||||
{
|
||||
if (hdrConfig.Value.HDREnabled)
|
||||
// If we find the HDR config display in the list of currently connected displays then try to set the HDR setting we recorded earlier
|
||||
if (hdrConfig.Key == displayInfoItem.DisplayID.DisplayLogicalIndex)
|
||||
{
|
||||
ADLRet = ADLImport.ADL2_Display_HDRState_Set(_adlContextHandle, hdrConfig.Value.AdapterIndex, displayInfoItem.DisplayID, 1);
|
||||
if (ADLRet == ADL_STATUS.ADL_OK)
|
||||
if (hdrConfig.Value.HDREnabled)
|
||||
{
|
||||
SharedLogger.logger.Trace($"AMDLibrary/GetAMDDisplayConfig: ADL2_Display_HDRState_Set was able to turn on HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
|
||||
ADLRet = ADLImport.ADL2_Display_HDRState_Set(_adlContextHandle, hdrConfig.Value.AdapterIndex, displayInfoItem.DisplayID, 1);
|
||||
if (ADLRet == ADL_STATUS.ADL_OK)
|
||||
{
|
||||
SharedLogger.logger.Trace($"AMDLibrary/SetActiveConfigOverride: ADL2_Display_HDRState_Set was able to turn on HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Error($"AMDLibrary/SetActiveConfigOverride: ADL2_Display_HDRState_Set was NOT able to turn on HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Error($"AMDLibrary/GetAMDDisplayConfig: ADL2_Display_HDRState_Set was NOT able to turn on HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
|
||||
ADLRet = ADLImport.ADL2_Display_HDRState_Set(_adlContextHandle, hdrConfig.Value.AdapterIndex, displayInfoItem.DisplayID, 0);
|
||||
if (ADLRet == ADL_STATUS.ADL_OK)
|
||||
{
|
||||
SharedLogger.logger.Trace($"AMDLibrary/SetActiveConfigOverride: ADL2_Display_HDRState_Set was able to turn off HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Error($"AMDLibrary/SetActiveConfigOverride: ADL2_Display_HDRState_Set was NOT able to turn off HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ADLRet = ADLImport.ADL2_Display_HDRState_Set(_adlContextHandle, hdrConfig.Value.AdapterIndex, displayInfoItem.DisplayID, 0);
|
||||
if (ADLRet == ADL_STATUS.ADL_OK)
|
||||
{
|
||||
SharedLogger.logger.Trace($"AMDLibrary/GetAMDDisplayConfig: ADL2_Display_HDRState_Set was able to turn off HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Error($"AMDLibrary/GetAMDDisplayConfig: ADL2_Display_HDRState_Set was NOT able to turn off HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SharedLogger.logger.Error(ex, $"AMDLibrary/GetAMDDisplayConfig: Exception! ADL2_Display_HDRState_Set was NOT able to change HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1907,7 +1909,7 @@ namespace DisplayMagicianShared.AMD
|
||||
if (!displayIdentifiers.Contains(displayIdentifier))
|
||||
{
|
||||
displayIdentifiers.Add(displayIdentifier);
|
||||
SharedLogger.logger.Debug($"AMDLibrary/GetSomeDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}");
|
||||
SharedLogger.logger.Debug($"ProfileRepository/GenerateProfileDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -364,6 +364,72 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
UNKNOWN = 0xFFFFFFFF,
|
||||
}
|
||||
|
||||
public enum NV_DISPLAYCONFIG_SPANNING_ORIENTATION : UInt32
|
||||
{
|
||||
NV_DISPLAYCONFIG_SPAN_NONE = 0,
|
||||
NV_DISPLAYCONFIG_SPAN_HORIZONTAL = 1,
|
||||
NV_DISPLAYCONFIG_SPAN_VERTICAL = 2,
|
||||
}
|
||||
|
||||
public enum TIMING_SCAN_MODE : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Progressive scan mode
|
||||
/// </summary>
|
||||
Progressive = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Interlaced scan mode
|
||||
/// </summary>
|
||||
Interlaced = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Interlaced scan mode with extra vertical blank
|
||||
/// </summary>
|
||||
InterlacedWithExtraVerticalBlank = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Interlaced scan mode without extra vertical blank
|
||||
/// </summary>
|
||||
InterlacedWithNoExtraVerticalBlank = 2
|
||||
}
|
||||
|
||||
public enum TIMING_VERTICAL_SYNC_POLARITY : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Positive vertical synchronized polarity
|
||||
/// </summary>
|
||||
Positive = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Negative vertical synchronized polarity
|
||||
/// </summary>
|
||||
Negative = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Default vertical synchronized polarity
|
||||
/// </summary>
|
||||
Default = Positive
|
||||
}
|
||||
|
||||
public enum TIMING_HORIZONTAL_SYNC_POLARITY : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Positive horizontal synchronized polarity
|
||||
/// </summary>
|
||||
Positive = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Negative horizontal synchronized polarity
|
||||
/// </summary>
|
||||
Negative = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Default horizontal synchronized polarity
|
||||
/// </summary>
|
||||
Default = Negative
|
||||
}
|
||||
|
||||
public enum NV_TIMING_OVERRIDE : UInt32
|
||||
{
|
||||
CURRENT = 0, //!< get the current timing
|
||||
@ -822,36 +888,39 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)]
|
||||
public struct NV_TIMINGEXT : IEquatable<NV_TIMINGEXT>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi)]
|
||||
public struct NV_TIMING_EXTRA : IEquatable<NV_TIMING_EXTRA>
|
||||
{
|
||||
public UInt32 Flag; //!< Reserved for NVIDIA hardware-based enhancement, such as double-scan.
|
||||
public ushort Rr; //!< Logical refresh rate to present
|
||||
public UInt32 Rrx1k; //!< Physical vertical refresh rate in 0.001Hz
|
||||
public UInt32 Aspect; //!< Display aspect ratio Hi(aspect):horizontal-aspect, Low(aspect):vertical-aspect
|
||||
public ushort Rep; //!< Bit-wise pixel repetition factor: 0x1:no pixel repetition; 0x2:each pixel repeats twice horizontally,..
|
||||
public UInt32 Status; //!< Timing standard
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (Int32)NVImport.NVAPI_UNICODE_STRING_MAX)]
|
||||
public UInt32 Flags; //!< Reserved for NVIDIA hardware-based enhancement, such as double-scan.
|
||||
public ushort RefreshRate; //!< Logical refresh rate to present
|
||||
public UInt32 FrequencyInMillihertz; //!< Physical vertical refresh rate in 0.001Hz
|
||||
public ushort VerticalAspect; //!< Display aspect ratio Hi(aspect):horizontal-aspect, Low(aspect):vertical-aspect
|
||||
public ushort HorizontalAspect; //!< Display aspect ratio Hi(aspect):horizontal-aspect, Low(aspect):vertical-aspect
|
||||
public ushort HorizontalPixelRepetition; //!< Bit-wise pixel repetition factor: 0x1:no pixel repetition; 0x2:each pixel repeats twice horizontally,..
|
||||
public UInt32 TimingStandard; //!< Timing standard
|
||||
//[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
|
||||
public string Name; //!< Timing name
|
||||
|
||||
public override bool Equals(object obj) => obj is NV_TIMINGEXT other && this.Equals(other);
|
||||
public override bool Equals(object obj) => obj is NV_TIMING_EXTRA other && this.Equals(other);
|
||||
|
||||
public bool Equals(NV_TIMINGEXT other)
|
||||
=> Flag == other.Flag &&
|
||||
Rr == other.Rr &&
|
||||
Rrx1k == other.Rrx1k &&
|
||||
Aspect == other.Aspect &&
|
||||
Rep == other.Rep &&
|
||||
Status == other.Status &&
|
||||
public bool Equals(NV_TIMING_EXTRA other)
|
||||
=> Flags == other.Flags &&
|
||||
RefreshRate == other.RefreshRate &&
|
||||
FrequencyInMillihertz == other.FrequencyInMillihertz &&
|
||||
VerticalAspect == other.VerticalAspect &&
|
||||
HorizontalAspect == other.HorizontalAspect &&
|
||||
HorizontalPixelRepetition == other.HorizontalPixelRepetition &&
|
||||
TimingStandard == other.TimingStandard &&
|
||||
Name == other.Name;
|
||||
|
||||
public override Int32 GetHashCode()
|
||||
{
|
||||
return (Flag, Rr, Rrx1k, Aspect, Rep, Status, Name).GetHashCode();
|
||||
return (Flags, RefreshRate, FrequencyInMillihertz, HorizontalAspect, HorizontalPixelRepetition, TimingStandard, Name).GetHashCode();
|
||||
}
|
||||
public static bool operator ==(NV_TIMINGEXT lhs, NV_TIMINGEXT rhs) => lhs.Equals(rhs);
|
||||
public static bool operator ==(NV_TIMING_EXTRA lhs, NV_TIMING_EXTRA rhs) => lhs.Equals(rhs);
|
||||
|
||||
public static bool operator !=(NV_TIMINGEXT lhs, NV_TIMINGEXT rhs) => !(lhs == rhs);
|
||||
public static bool operator !=(NV_TIMING_EXTRA lhs, NV_TIMING_EXTRA rhs) => !(lhs == rhs);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
@ -863,20 +932,20 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
public ushort HFrontPorch; //!< horizontal front porch
|
||||
public ushort HSyncWidth; //!< horizontal sync width
|
||||
public ushort HTotal; //!< horizontal total
|
||||
public byte HSyncPol; //!< horizontal sync polarity: 1-negative, 0-positive
|
||||
public TIMING_HORIZONTAL_SYNC_POLARITY HSyncPol; //!< horizontal sync polarity: 1-negative, 0-positive
|
||||
|
||||
public ushort VVisible; //!< vertical visible
|
||||
public ushort VBorder; //!< vertical border
|
||||
public ushort VFrontPorch; //!< vertical front porch
|
||||
public ushort VSyncWidth; //!< vertical sync width
|
||||
public ushort VTotal; //!< vertical total
|
||||
public byte VSyncPol; //!< vertical sync polarity: 1-negative, 0-positive
|
||||
public TIMING_VERTICAL_SYNC_POLARITY VSyncPol; //!< vertical sync polarity: 1-negative, 0-positive
|
||||
|
||||
public ushort Interlaced; //!< 1-Int32erlaced, 0-progressive
|
||||
public TIMING_SCAN_MODE ScanMode; //!< 1-Int32erlaced, 0-progressive
|
||||
public UInt32 Pclk; //!< pixel clock in 10 kHz
|
||||
|
||||
//other timing related extras
|
||||
NV_TIMINGEXT Etc;
|
||||
public NV_TIMING_EXTRA Extra;
|
||||
|
||||
public override bool Equals(object obj) => obj is NV_TIMING other && this.Equals(other);
|
||||
|
||||
@ -893,13 +962,13 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
VSyncWidth == other.VSyncWidth &&
|
||||
VTotal == other.VTotal &&
|
||||
VSyncPol == other.VSyncPol &&
|
||||
Interlaced == other.Interlaced &&
|
||||
ScanMode == other.ScanMode &&
|
||||
Pclk == other.Pclk &&
|
||||
Etc.Equals(other.Etc);
|
||||
Extra.Equals(other.Extra);
|
||||
|
||||
public override Int32 GetHashCode()
|
||||
{
|
||||
return (HVisible, HBorder, HFrontPorch, HSyncWidth, HTotal, HSyncPol, VVisible, VBorder, VFrontPorch, VSyncWidth, VTotal, VSyncPol, Interlaced, Pclk, Etc).GetHashCode();
|
||||
return (HVisible, HBorder, HFrontPorch, HSyncWidth, HTotal, HSyncPol, VVisible, VBorder, VFrontPorch, VSyncWidth, VTotal, VSyncPol, ScanMode, Pclk, Extra).GetHashCode();
|
||||
}
|
||||
public static bool operator ==(NV_TIMING lhs, NV_TIMING rhs) => lhs.Equals(rhs);
|
||||
|
||||
@ -931,6 +1000,27 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
public static bool operator !=(NV_RECT lhs, NV_RECT rhs) => !(lhs == rhs);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
public struct NV_LUID : IEquatable<NV_LUID>
|
||||
{
|
||||
public UInt32 LowPart;
|
||||
public UInt32 HighPart;
|
||||
|
||||
public override bool Equals(object obj) => obj is NV_LUID other && this.Equals(other);
|
||||
|
||||
public bool Equals(NV_LUID other)
|
||||
=> LowPart == other.LowPart &&
|
||||
HighPart == other.HighPart;
|
||||
|
||||
public override Int32 GetHashCode()
|
||||
{
|
||||
return (LowPart, HighPart).GetHashCode();
|
||||
}
|
||||
public static bool operator ==(NV_LUID lhs, NV_LUID rhs) => lhs.Equals(rhs);
|
||||
|
||||
public static bool operator !=(NV_LUID lhs, NV_LUID rhs) => !(lhs == rhs);
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
public struct NV_POSITION : IEquatable<NV_POSITION>
|
||||
@ -985,6 +1075,14 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
public float W; //!< Width of the viewport
|
||||
public float H; //!< Height of the viewport
|
||||
|
||||
public NV_VIEWPORTF(float myX, float myY, float myW, float myH) : this()
|
||||
{
|
||||
X = myX;
|
||||
Y = myY;
|
||||
W = myW;
|
||||
H = myH;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj) => obj is NV_VIEWPORTF other && this.Equals(other);
|
||||
|
||||
// NOTE: Using Math.Round for equality testing between floats.
|
||||
@ -1018,20 +1116,21 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
public NV_SCALING Scaling; //!< (IN) scaling setting.
|
||||
|
||||
// Refresh Rate
|
||||
public UInt32 RefreshRate1K; //!< (IN) Non-Int32erlaced Refresh Rate of the mode, multiplied by 1000, 0 = ignored
|
||||
//!< This is the value which driver reports to the OS.
|
||||
// Flags
|
||||
//public UInt32 Int32erlaced:1; //!< (IN) Interlaced mode flag, ignored if refreshRate == 0
|
||||
//public UInt32 primary:1; //!< (IN) Declares primary display in clone configuration. This is *NOT* GDI Primary.
|
||||
//!< Only one target can be primary per source. If no primary is specified, the first
|
||||
//!< target will automatically be primary.
|
||||
//public UInt32 isPanAndScanTarget:1; //!< Whether on this target Pan and Scan is enabled or has to be enabled. Valid only
|
||||
//!< when the target is part of clone topology.
|
||||
//public UInt32 disableVirtualModeSupport:1;
|
||||
//public UInt32 isPreferredUnscaledTarget:1;
|
||||
//public UInt32 reserved:27;
|
||||
// TV format information
|
||||
public NV_GPU_CONNECTOR_TYPE Connector; //!< Specify connector type. For TV only, ignored if tvFormat == NV_DISPLAY_TV_FORMAT_NONE
|
||||
public UInt32 RefreshRateInMillihertz; //!< (IN) Non-Int32erlaced Refresh Rate of the mode, multiplied by 1000, 0 = ignored
|
||||
//!< This is the value which driver reports to the OS.
|
||||
// Flags
|
||||
//public UInt32 Int32erlaced:1; //!< (IN) Interlaced mode flag, ignored if refreshRate == 0
|
||||
//public UInt32 primary:1; //!< (IN) Declares primary display in clone configuration. This is *NOT* GDI Primary.
|
||||
//!< Only one target can be primary per source. If no primary is specified, the first
|
||||
//!< target will automatically be primary.
|
||||
//public UInt32 isPanAndScanTarget:1; //!< Whether on this target Pan and Scan is enabled or has to be enabled. Valid only
|
||||
//!< when the target is part of clone topology.
|
||||
//public UInt32 disableVirtualModeSupport:1;
|
||||
//public UInt32 isPreferredUnscaledTarget:1;
|
||||
//public UInt32 reserved:27;
|
||||
public UInt32 Flags;
|
||||
// TV format information
|
||||
public NV_GPU_CONNECTOR_TYPE ConnectorType; //!< Specify connector type. For TV only, ignored if tvFormat == NV_DISPLAY_TV_FORMAT_NONE
|
||||
public NV_DISPLAY_TV_FORMAT TvFormat; //!< (IN) to choose the last TV format set this value to NV_DISPLAY_TV_FORMAT_NONE
|
||||
//!< In case of NvAPI_DISP_GetDisplayConfig(), this field will indicate the currently applied TV format;
|
||||
//!< if no TV format is applied, this field will have NV_DISPLAY_TV_FORMAT_NONE value.
|
||||
@ -1050,15 +1149,16 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
=> Version == other.Version &&
|
||||
Rotation == other.Rotation &&
|
||||
Scaling == other.Scaling &&
|
||||
RefreshRate1K == other.RefreshRate1K &&
|
||||
Connector == other.Connector &&
|
||||
RefreshRateInMillihertz == other.RefreshRateInMillihertz &&
|
||||
Flags == other.Flags &&
|
||||
ConnectorType == other.ConnectorType &&
|
||||
TvFormat == other.TvFormat &&
|
||||
TimingOverride == other.TimingOverride &&
|
||||
Timing.Equals(other.Timing);
|
||||
|
||||
public override Int32 GetHashCode()
|
||||
{
|
||||
return (Version, Rotation, Scaling, RefreshRate1K, Connector, TvFormat, TimingOverride, Timing).GetHashCode();
|
||||
return (Version, Rotation, Scaling, RefreshRateInMillihertz, Flags, ConnectorType, TvFormat, TimingOverride, Timing).GetHashCode();
|
||||
}
|
||||
public static bool operator ==(NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO lhs, NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO rhs) => lhs.Equals(rhs);
|
||||
|
||||
@ -1069,19 +1169,19 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
public struct NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 : IEquatable<NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2>
|
||||
{
|
||||
public UInt32 DisplayId; //!< Display ID
|
||||
NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO Details; //!< May be NULL if no advanced settings are required
|
||||
public UInt32 TargetId; //!< Windows CCD target ID. Must be present only for non-NVIDIA adapter, for NVIDIA adapter this parameter is ignored.
|
||||
public NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO Details; //!< May be NULL if no advanced settings are required
|
||||
public UInt32 WindowsCCDTargetId; //!< Windows CCD target ID. Must be present only for non-NVIDIA adapter, for NVIDIA adapter this parameter is ignored.
|
||||
|
||||
public override bool Equals(object obj) => obj is NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 other && this.Equals(other);
|
||||
|
||||
public bool Equals(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 other)
|
||||
=> DisplayId == other.DisplayId &&
|
||||
Details.Equals(other.Details) &&
|
||||
TargetId == other.TargetId;
|
||||
WindowsCCDTargetId == other.WindowsCCDTargetId;
|
||||
|
||||
public override Int32 GetHashCode()
|
||||
{
|
||||
return (DisplayId, Details, TargetId).GetHashCode();
|
||||
return (DisplayId, Details, WindowsCCDTargetId).GetHashCode();
|
||||
}
|
||||
public static bool operator ==(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 lhs, NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 rhs) => lhs.Equals(rhs);
|
||||
|
||||
@ -1092,7 +1192,7 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
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 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);
|
||||
|
||||
@ -1109,23 +1209,26 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
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, Pack = 8)]
|
||||
public struct NV_DISPLAYCONFIG_PATH_INFO_V2 : IEquatable<NV_DISPLAYCONFIG_PATH_INFO_V2> // Version is 2
|
||||
{
|
||||
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 UInt32 Reserved;
|
||||
//[MarshalAs(UnmanagedType.ByValArray)]
|
||||
public IntPtr TargetInfo;
|
||||
public IntPtr SourceModeInfo; //!< May be NULL if mode info is not important
|
||||
//public IntPtr 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 UInt32 Flags;
|
||||
//!< Used by Non-NVIDIA adapter for pointer to OS Adapter of LUID
|
||||
//!< type, type casted to void *.
|
||||
public IntPtr OSAdapterID;
|
||||
|
||||
public bool IsNonNVIDIAAdapter => Flags.GetBit(0); //!< if bit is set then this path uses a non-nvidia adapter
|
||||
|
||||
public override bool Equals(object obj) => obj is NV_DISPLAYCONFIG_PATH_INFO_V2 other && this.Equals(other);
|
||||
|
||||
public bool Equals(NV_DISPLAYCONFIG_PATH_INFO_V2 other)
|
||||
@ -1134,12 +1237,11 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
TargetInfoCount == other.TargetInfoCount &&
|
||||
TargetInfo.Equals(other.TargetInfo) &&
|
||||
SourceModeInfo.Equals(other.SourceModeInfo) &&
|
||||
Reserved == other.Reserved &&
|
||||
OSAdapterID == other.OSAdapterID;
|
||||
Flags == other.Flags;
|
||||
|
||||
public override Int32 GetHashCode()
|
||||
{
|
||||
return (Version, SourceId, TargetInfoCount, TargetInfo, SourceModeInfo).GetHashCode();
|
||||
return (Version, SourceId, TargetInfoCount, TargetInfo, SourceModeInfo, Flags).GetHashCode();
|
||||
}
|
||||
public static bool operator ==(NV_DISPLAYCONFIG_PATH_INFO_V2 lhs, NV_DISPLAYCONFIG_PATH_INFO_V2 rhs) => lhs.Equals(rhs);
|
||||
|
||||
@ -1188,10 +1290,11 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
public NV_POSITION Position; //!< Is all positions are 0 or invalid, displays will be automatically
|
||||
//!< positioned from left to right with GDI Primary at 0,0, and all
|
||||
//!< other displays in the order of the path array.
|
||||
//public NV_DISPLAYCONFIG_SPANNING_ORIENTATION spanningOrientation; //!< Spanning is only supported on XP
|
||||
//public UInt32 bGDIPrimary : 1;
|
||||
//public UInt32 bSLIFocus : 1;
|
||||
//public UInt32 reserved : 30; //!< Must be 0
|
||||
public NV_DISPLAYCONFIG_SPANNING_ORIENTATION SpanningOrientation; //!< Spanning is only supported on XP
|
||||
public UInt32 Flags;
|
||||
|
||||
public bool IsGDIPrimary => (Flags & 0x1) == 0x1; //!< if bit is set then this source is the primary GDI source
|
||||
public bool IsSLIFocus => (Flags & 0x2) == 0x2; //!< if bit is set then this source has SLI focus
|
||||
|
||||
public override bool Equals(object obj) => obj is NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1 other && this.Equals(other);
|
||||
|
||||
@ -2083,6 +2186,7 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
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);
|
||||
public static UInt32 NV_CUSTOM_DISPLAY_V1_VER = MAKE_NVAPI_VERSION<NV_CUSTOM_DISPLAY_V1>(1);
|
||||
|
||||
|
||||
#region Internal Constant
|
||||
@ -2217,9 +2321,10 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
GetDelegate(NvId_Disp_GetHdrCapabilities, out Disp_GetHdrCapabilitiesInternal);
|
||||
GetDelegate(NvId_Disp_HdrColorControl, out Disp_HdrColorControlInternal);
|
||||
GetDelegate(NvId_Disp_ColorControl, out Disp_ColorControlInternal);
|
||||
/*GetDelegate(NvId_DISP_GetDisplayConfig, out DISP_GetDisplayConfigInternal);
|
||||
GetDelegate(NvId_DISP_GetDisplayConfig, out DISP_GetDisplayConfigInternalNull); // null version of the submission*/
|
||||
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);
|
||||
GetDelegate(NvId_DISP_EnumCustomDisplay, out Disp_EnumCustomDisplayInternal);
|
||||
|
||||
// GPUs
|
||||
GetDelegate(NvId_EnumPhysicalGPUs, out EnumPhysicalGPUsInternal);
|
||||
@ -3271,152 +3376,180 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
|
||||
// ******** 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;
|
||||
// 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)
|
||||
/// <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_V2[] PathInfos, bool thirdPass = false)
|
||||
{
|
||||
NVAPI_STATUS status;
|
||||
IntPtr pathInfoBuffer = IntPtr.Zero;
|
||||
IntPtr currentPathInfoBuffer = IntPtr.Zero;
|
||||
if (thirdPass)
|
||||
{
|
||||
// Copy the supplied object for the third pass (when we have the pathInfoCount and the targetInfoCount for each pathInfo, but we want the details)
|
||||
// Third Pass(Optional, only required if target information is required): Allocate memory for targetInfo with respect
|
||||
//! to number of targetInfoCount(from Second Pass).
|
||||
NV_DISPLAYCONFIG_PATH_INFO_V2[] passedPathInfo = PathInfos;
|
||||
PathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V2[PathInfoCount];
|
||||
// Go through the array and create the structure
|
||||
int overallTargetCount = 0;
|
||||
for (Int32 x = 0; x < (Int32)PathInfoCount; x++)
|
||||
{
|
||||
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]));
|
||||
}
|
||||
// Copy the information passed in, into the buffer we want to pass
|
||||
|
||||
}
|
||||
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;
|
||||
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;
|
||||
PathInfos[x].Version = MAKE_NVAPI_VERSION(Marshal.SizeOf(passedPathInfo[x]), 1);
|
||||
}
|
||||
// Initialize unmanged memory to hold the unmanaged array of structs
|
||||
int memorySizeRequired = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_INFO_V2)) * (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]));
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the second pass
|
||||
// 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.
|
||||
// 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_V2[PathInfoCount];
|
||||
// Prepare the struct for second pass duties
|
||||
for (Int32 x = 0; x < (Int32)PathInfoCount; x++)
|
||||
{
|
||||
NVAPI_STATUS status;
|
||||
IntPtr pathInfos = IntPtr.Zero;
|
||||
NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1 sourceMode = new NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1();
|
||||
IntPtr sourceModeBuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1)));
|
||||
Marshal.StructureToPtr(sourceMode, sourceModeBuffer, true);
|
||||
PathInfos[x].Version = NVImport.NV_DISPLAYCONFIG_PATH_INFO_V2_VER;
|
||||
PathInfos[x].SourceModeInfo = sourceModeBuffer;
|
||||
/*PathInfos[x].SourceModeInfo.Resolution = new NV_RESOLUTION();
|
||||
PathInfos[x].SourceModeInfo.Position = new NV_POSITION();
|
||||
//PathInfos[x].SourceModeInfo = null;
|
||||
PathInfos[x].TargetInfoCount = 0;
|
||||
PathInfos[x].TargetInfo = IntPtr.Zero;
|
||||
//!< This field is reserved. There is ongoing debate if we need this field.
|
||||
//!< Identifies sourceIds used by Windows. If all sourceIds are 0,
|
||||
//!< these will be computed automatically.
|
||||
PathInfos[x].SourceId = 0;
|
||||
PathInfos[x].Flags = 0;
|
||||
PathInfos[x].OSAdapterID = new NV_LUID();
|
||||
//PathInfos[x].OSAdapterID = IntPtr.Zero;*/
|
||||
}
|
||||
// Initialize unmanged memory to hold the unmanaged array of structs
|
||||
int sizeOfOneStruct = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_INFO_V2));
|
||||
int sizeOfAllStructs = sizeOfOneStruct * (int)PathInfoCount;
|
||||
//int sizeOfOneStruct = Marshal.SizeOf(PathInfos);
|
||||
pathInfoBuffer = Marshal.AllocCoTaskMem(sizeOfAllStructs);
|
||||
// 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, true);
|
||||
// advance the buffer forwards to the next object
|
||||
currentPathInfoBuffer = (IntPtr)((long)currentPathInfoBuffer.ToInt64() + Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2)));
|
||||
}
|
||||
}
|
||||
|
||||
if (DISP_GetDisplayConfigInternalNull != null) { status = DISP_GetDisplayConfigInternalNull(ref PathInfoCount, pathInfos); }
|
||||
else { status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND; }
|
||||
|
||||
return status;
|
||||
}*/
|
||||
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_V2[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_V2();
|
||||
// fill the array slot structure with the data from the buffer
|
||||
PathInfos[i] = (NV_DISPLAYCONFIG_PATH_INFO_V2)Marshal.PtrToStructure(currentPathInfoBuffer, typeof(NV_DISPLAYCONFIG_PATH_INFO_V2));
|
||||
// destroy the bit of memory we no longer need
|
||||
Marshal.DestroyStructure(currentPathInfoBuffer, typeof(NV_DISPLAYCONFIG_PATH_INFO_V2));
|
||||
// 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);
|
||||
@ -4173,6 +4306,28 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
return status;
|
||||
}
|
||||
|
||||
//NVAPI_INTERFACE NvAPI_DISP_EnumCustomDisplay(__in NvU32 displayId, __inout NV_HDR_CAPABILITIES *pHdrCapabilities);
|
||||
private delegate NVAPI_STATUS Disp_EnumCustomDisplayDelegate(
|
||||
[In] UInt32 displayId,
|
||||
[In] UInt32 index,
|
||||
[In][Out] ref NV_CUSTOM_DISPLAY_V1 pCustDisp);
|
||||
private static readonly Disp_EnumCustomDisplayDelegate Disp_EnumCustomDisplayInternal;
|
||||
/// <summary>
|
||||
//! This API gets High Dynamic Range (HDR) capabilities of the display.
|
||||
/// <param name="displayId"></param>
|
||||
/// <param name="pHdrCapabilities"></param>
|
||||
/// <returns></returns>
|
||||
public static NVAPI_STATUS NvAPI_DISP_EnumCustomDisplay(UInt32 displayId, UInt32 index, ref NV_CUSTOM_DISPLAY_V1 pCustDisp)
|
||||
{
|
||||
NVAPI_STATUS status;
|
||||
pCustDisp.Version = NVImport.NV_CUSTOM_DISPLAY_V1_VER;
|
||||
pCustDisp.SourcePartition = new NV_VIEWPORTF(0, 0, 1, 1);
|
||||
if (Disp_EnumCustomDisplayInternal != null) { status = Disp_EnumCustomDisplayInternal(displayId, index, ref pCustDisp); }
|
||||
else { status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND; }
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//NVAPI_INTERFACE NvAPI_GPU_GetFullName(NvPhysicalGpuHandle hPhysicalGpu, NvAPI_ShortString szName);
|
||||
private delegate NVAPI_STATUS GPU_GetFullNameDelegate(
|
||||
[In] PhysicalGpuHandle gpuHandle,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1017,33 +1017,84 @@ namespace DisplayMagicianShared.Windows
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Patching the adapter IDs to make the saved config valid");
|
||||
PatchAdapterIDs(ref displayConfig, allWindowsDisplayConfig.DisplayAdapters);
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Testing whether the display configuration is valid");
|
||||
// Test whether a specified display configuration is supported on the computer
|
||||
uint myPathsCount = (uint)displayConfig.DisplayConfigPaths.Length;
|
||||
uint myModesCount = (uint)displayConfig.DisplayConfigModes.Length;
|
||||
/*SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Testing whether the display configuration is valid");
|
||||
// Test whether a specified display configuration is supported on the computer
|
||||
// Note: THe flags are different as we cannot use SDC_FORCE_MODE_ENUMERATION unless we're actually applying the config
|
||||
WIN32STATUS err = CCDImport.SetDisplayConfig(myPathsCount, displayConfig.DisplayConfigPaths, myModesCount, displayConfig.DisplayConfigModes, SDC.DISPLAYMAGICIAN_VALIDATE);
|
||||
if (err == WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Successfully validated that the display configuration supplied would work!");
|
||||
}
|
||||
else
|
||||
else if (err == WIN32STATUS.ERROR_INVALID_PARAMETER)
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/SetActiveConfig: ERROR - SetDisplayConfig couldn't validate the display configuration supplied. This display configuration won't work if applied.");
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: The combination of parameters and flags specified is invalid. This display configuration won't work if applied.");
|
||||
return false;
|
||||
}
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Yay! The display configuration is valid! Attempting to set the Display Config now");
|
||||
else if (err == WIN32STATUS.ERROR_NOT_SUPPORTED)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: The system is not running a graphics driver that was written according to the Windows Display Driver Model (WDDM). The function is only supported on a system with a WDDM driver running. This display configuration won't work if applied.");
|
||||
return false;
|
||||
}
|
||||
else if (err == WIN32STATUS.ERROR_ACCESS_DENIED)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: The caller does not have access to the console session. This error occurs if the calling process does not have access to the current desktop or is running on a remote session. This display configuration won't work if applied.");
|
||||
return false;
|
||||
}
|
||||
else if (err == WIN32STATUS.ERROR_GEN_FAILURE)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: An unspecified error occurred. This display configuration won't work if applied.");
|
||||
return false;
|
||||
}
|
||||
else if (err == WIN32STATUS.ERROR_BAD_CONFIGURATION)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: The function could not find a workable solution for the source and target modes that the caller did not specify. This display configuration won't work if applied.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/SetActiveConfig: SetDisplayConfig couldn't validate the display configuration supplied. This display configuration won't work if applied.");
|
||||
return false;
|
||||
}
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Yay! The display configuration is valid! Attempting to set the Display Config now");*/
|
||||
|
||||
|
||||
// Now set the specified display configuration for this computer
|
||||
err = CCDImport.SetDisplayConfig(myPathsCount, displayConfig.DisplayConfigPaths, myModesCount, displayConfig.DisplayConfigModes, SDC.DISPLAYMAGICIAN_SET | SDC.SDC_FORCE_MODE_ENUMERATION);
|
||||
WIN32STATUS err = CCDImport.SetDisplayConfig(myPathsCount, displayConfig.DisplayConfigPaths, myModesCount, displayConfig.DisplayConfigModes, SDC.DISPLAYMAGICIAN_SET | SDC.SDC_FORCE_MODE_ENUMERATION);
|
||||
if (err == WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Successfully set the display configuration to the settings supplied!");
|
||||
}
|
||||
else if (err == WIN32STATUS.ERROR_INVALID_PARAMETER)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: The combination of parameters and flags specified is invalid. Display configuration not applied.");
|
||||
return false;
|
||||
}
|
||||
else if (err == WIN32STATUS.ERROR_NOT_SUPPORTED)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: The system is not running a graphics driver that was written according to the Windows Display Driver Model (WDDM). The function is only supported on a system with a WDDM driver running. Display configuration not applied.");
|
||||
return false;
|
||||
}
|
||||
else if (err == WIN32STATUS.ERROR_ACCESS_DENIED)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: The caller does not have access to the console session. This error occurs if the calling process does not have access to the current desktop or is running on a remote session. Display configuration not applied.");
|
||||
return false;
|
||||
}
|
||||
else if (err == WIN32STATUS.ERROR_GEN_FAILURE)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: An unspecified error occurred. Display configuration not applied.");
|
||||
return false;
|
||||
}
|
||||
else if (err == WIN32STATUS.ERROR_BAD_CONFIGURATION)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: The function could not find a workable solution for the source and target modes that the caller did not specify. Display configuration not applied.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/SetActiveConfig: ERROR - SetDisplayConfig couldn't set the display configuration using the settings supplied. Something is wrong.");
|
||||
throw new WinLibraryException($"SetDisplayConfig couldn't set the display configuration using the settings supplied. Something is wrong.");
|
||||
SharedLogger.logger.Error($"WinLibrary/SetActiveConfig: SetDisplayConfig couldn't set the display configuration using the settings supplied. Display configuration not applied.");
|
||||
return false;
|
||||
}
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: SUCCESS! The display configuration has been successfully applied");
|
||||
@ -1445,7 +1496,7 @@ namespace DisplayMagicianShared.Windows
|
||||
if (!displayIdentifiers.Contains(displayIdentifier))
|
||||
{
|
||||
displayIdentifiers.Add(displayIdentifier);
|
||||
SharedLogger.logger.Debug($"WinLibrary/GetSomeDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}");
|
||||
SharedLogger.logger.Debug($"ProfileRepository/GenerateProfileDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}");
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user