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:
Terry MacDonald
2021-11-13 15:06:54 +13:00
parent 2b653999dd
commit d4494aa699
4 changed files with 972 additions and 527 deletions

View File

@ -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 // 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: 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) 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 // 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); 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}."); 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 supportedSLSLayoutImageMode;
int reasonForNotSupportSLS; 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); 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}."); 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 // Create and apply the new SLSMap
int newSlsMapIndex; 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); 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) if (newSlsMapIndex != -1)
{ {
@ -1411,7 +1409,7 @@ namespace DisplayMagicianShared.AMD
{ {
// Turn off this SLS Map Config // Turn off this SLS Map Config
ADLRet = ADLImport.ADL2_Display_SLSMapConfig_SetState(_adlContextHandle, slsMapConfig.SLSMap.AdapterIndex, slsMapConfig.SLSMap.SLSMapIndex, ADLImport.ADL_FALSE); 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}."); 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.");
}
} }
@ -1456,6 +1450,8 @@ namespace DisplayMagicianShared.AMD
{ {
// Try and find the HDR config displays in the list of currently connected displays // Try and find the HDR config displays in the list of currently connected displays
foreach (var displayInfoItem in ActiveDisplayConfig.DisplayTargets) foreach (var displayInfoItem in ActiveDisplayConfig.DisplayTargets)
{
try
{ {
// 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 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) if (hdrConfig.Key == displayInfoItem.DisplayID.DisplayLogicalIndex)
@ -1465,11 +1461,11 @@ namespace DisplayMagicianShared.AMD
ADLRet = ADLImport.ADL2_Display_HDRState_Set(_adlContextHandle, hdrConfig.Value.AdapterIndex, displayInfoItem.DisplayID, 1); ADLRet = ADLImport.ADL2_Display_HDRState_Set(_adlContextHandle, hdrConfig.Value.AdapterIndex, displayInfoItem.DisplayID, 1);
if (ADLRet == ADL_STATUS.ADL_OK) if (ADLRet == ADL_STATUS.ADL_OK)
{ {
SharedLogger.logger.Trace($"AMDLibrary/GetAMDDisplayConfig: ADL2_Display_HDRState_Set was able to turn on HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}."); SharedLogger.logger.Trace($"AMDLibrary/SetActiveConfigOverride: ADL2_Display_HDRState_Set was able to turn on HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
} }
else else
{ {
SharedLogger.logger.Error($"AMDLibrary/GetAMDDisplayConfig: ADL2_Display_HDRState_Set was NOT able to turn on HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}."); SharedLogger.logger.Error($"AMDLibrary/SetActiveConfigOverride: ADL2_Display_HDRState_Set was NOT able to turn on HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
} }
} }
else else
@ -1477,16 +1473,22 @@ namespace DisplayMagicianShared.AMD
ADLRet = ADLImport.ADL2_Display_HDRState_Set(_adlContextHandle, hdrConfig.Value.AdapterIndex, displayInfoItem.DisplayID, 0); ADLRet = ADLImport.ADL2_Display_HDRState_Set(_adlContextHandle, hdrConfig.Value.AdapterIndex, displayInfoItem.DisplayID, 0);
if (ADLRet == ADL_STATUS.ADL_OK) 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}."); SharedLogger.logger.Trace($"AMDLibrary/SetActiveConfigOverride: ADL2_Display_HDRState_Set was able to turn off HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
} }
else else
{ {
SharedLogger.logger.Error($"AMDLibrary/GetAMDDisplayConfig: ADL2_Display_HDRState_Set was NOT able to turn off HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}."); SharedLogger.logger.Error($"AMDLibrary/SetActiveConfigOverride: ADL2_Display_HDRState_Set was NOT able to turn off HDR for display {displayInfoItem.DisplayID.DisplayLogicalIndex}.");
} }
} }
break; 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)) if (!displayIdentifiers.Contains(displayIdentifier))
{ {
displayIdentifiers.Add(displayIdentifier); displayIdentifiers.Add(displayIdentifier);
SharedLogger.logger.Debug($"AMDLibrary/GetSomeDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}"); SharedLogger.logger.Debug($"ProfileRepository/GenerateProfileDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}");
} }
} }
} }

View File

@ -364,6 +364,72 @@ namespace DisplayMagicianShared.NVIDIA
UNKNOWN = 0xFFFFFFFF, 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 public enum NV_TIMING_OVERRIDE : UInt32
{ {
CURRENT = 0, //!< get the current timing CURRENT = 0, //!< get the current timing
@ -822,36 +888,39 @@ namespace DisplayMagicianShared.NVIDIA
} }
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)] [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi)]
public struct NV_TIMINGEXT : IEquatable<NV_TIMINGEXT> public struct NV_TIMING_EXTRA : IEquatable<NV_TIMING_EXTRA>
{ {
public UInt32 Flag; //!< Reserved for NVIDIA hardware-based enhancement, such as double-scan. public UInt32 Flags; //!< Reserved for NVIDIA hardware-based enhancement, such as double-scan.
public ushort Rr; //!< Logical refresh rate to present public ushort RefreshRate; //!< Logical refresh rate to present
public UInt32 Rrx1k; //!< Physical vertical refresh rate in 0.001Hz public UInt32 FrequencyInMillihertz; //!< Physical vertical refresh rate in 0.001Hz
public UInt32 Aspect; //!< Display aspect ratio Hi(aspect):horizontal-aspect, Low(aspect):vertical-aspect public ushort VerticalAspect; //!< 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 ushort HorizontalAspect; //!< Display aspect ratio Hi(aspect):horizontal-aspect, Low(aspect):vertical-aspect
public UInt32 Status; //!< Timing standard public ushort HorizontalPixelRepetition; //!< Bit-wise pixel repetition factor: 0x1:no pixel repetition; 0x2:each pixel repeats twice horizontally,..
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (Int32)NVImport.NVAPI_UNICODE_STRING_MAX)] public UInt32 TimingStandard; //!< Timing standard
//[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
public string Name; //!< Timing name 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) public bool Equals(NV_TIMING_EXTRA other)
=> Flag == other.Flag && => Flags == other.Flags &&
Rr == other.Rr && RefreshRate == other.RefreshRate &&
Rrx1k == other.Rrx1k && FrequencyInMillihertz == other.FrequencyInMillihertz &&
Aspect == other.Aspect && VerticalAspect == other.VerticalAspect &&
Rep == other.Rep && HorizontalAspect == other.HorizontalAspect &&
Status == other.Status && HorizontalPixelRepetition == other.HorizontalPixelRepetition &&
TimingStandard == other.TimingStandard &&
Name == other.Name; Name == other.Name;
public override Int32 GetHashCode() 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)] [StructLayout(LayoutKind.Sequential, Pack = 8)]
@ -863,20 +932,20 @@ namespace DisplayMagicianShared.NVIDIA
public ushort HFrontPorch; //!< horizontal front porch public ushort HFrontPorch; //!< horizontal front porch
public ushort HSyncWidth; //!< horizontal sync width public ushort HSyncWidth; //!< horizontal sync width
public ushort HTotal; //!< horizontal total 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 VVisible; //!< vertical visible
public ushort VBorder; //!< vertical border public ushort VBorder; //!< vertical border
public ushort VFrontPorch; //!< vertical front porch public ushort VFrontPorch; //!< vertical front porch
public ushort VSyncWidth; //!< vertical sync width public ushort VSyncWidth; //!< vertical sync width
public ushort VTotal; //!< vertical total 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 public UInt32 Pclk; //!< pixel clock in 10 kHz
//other timing related extras //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); public override bool Equals(object obj) => obj is NV_TIMING other && this.Equals(other);
@ -893,13 +962,13 @@ namespace DisplayMagicianShared.NVIDIA
VSyncWidth == other.VSyncWidth && VSyncWidth == other.VSyncWidth &&
VTotal == other.VTotal && VTotal == other.VTotal &&
VSyncPol == other.VSyncPol && VSyncPol == other.VSyncPol &&
Interlaced == other.Interlaced && ScanMode == other.ScanMode &&
Pclk == other.Pclk && Pclk == other.Pclk &&
Etc.Equals(other.Etc); Extra.Equals(other.Extra);
public override Int32 GetHashCode() 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); 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); 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)] [StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct NV_POSITION : IEquatable<NV_POSITION> public struct NV_POSITION : IEquatable<NV_POSITION>
@ -985,6 +1075,14 @@ namespace DisplayMagicianShared.NVIDIA
public float W; //!< Width of the viewport public float W; //!< Width of the viewport
public float H; //!< Height 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); public override bool Equals(object obj) => obj is NV_VIEWPORTF other && this.Equals(other);
// NOTE: Using Math.Round for equality testing between floats. // NOTE: Using Math.Round for equality testing between floats.
@ -1018,7 +1116,7 @@ namespace DisplayMagicianShared.NVIDIA
public NV_SCALING Scaling; //!< (IN) scaling setting. public NV_SCALING Scaling; //!< (IN) scaling setting.
// Refresh Rate // Refresh Rate
public UInt32 RefreshRate1K; //!< (IN) Non-Int32erlaced Refresh Rate of the mode, multiplied by 1000, 0 = ignored 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. //!< This is the value which driver reports to the OS.
// Flags // Flags
//public UInt32 Int32erlaced:1; //!< (IN) Interlaced mode flag, ignored if refreshRate == 0 //public UInt32 Int32erlaced:1; //!< (IN) Interlaced mode flag, ignored if refreshRate == 0
@ -1030,8 +1128,9 @@ namespace DisplayMagicianShared.NVIDIA
//public UInt32 disableVirtualModeSupport:1; //public UInt32 disableVirtualModeSupport:1;
//public UInt32 isPreferredUnscaledTarget:1; //public UInt32 isPreferredUnscaledTarget:1;
//public UInt32 reserved:27; //public UInt32 reserved:27;
public UInt32 Flags;
// TV format information // TV format information
public NV_GPU_CONNECTOR_TYPE Connector; //!< Specify connector type. For TV only, ignored if tvFormat == NV_DISPLAY_TV_FORMAT_NONE 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 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; //!< 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. //!< 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 && => Version == other.Version &&
Rotation == other.Rotation && Rotation == other.Rotation &&
Scaling == other.Scaling && Scaling == other.Scaling &&
RefreshRate1K == other.RefreshRate1K && RefreshRateInMillihertz == other.RefreshRateInMillihertz &&
Connector == other.Connector && Flags == other.Flags &&
ConnectorType == other.ConnectorType &&
TvFormat == other.TvFormat && TvFormat == other.TvFormat &&
TimingOverride == other.TimingOverride && TimingOverride == other.TimingOverride &&
Timing.Equals(other.Timing); Timing.Equals(other.Timing);
public override Int32 GetHashCode() 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); 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 struct NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 : IEquatable<NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2>
{ {
public UInt32 DisplayId; //!< Display ID 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 UInt32 TargetId; //!< Windows CCD target ID. Must be present only for non-NVIDIA adapter, for NVIDIA adapter this parameter is ignored. 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 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) public bool Equals(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2 other)
=> DisplayId == other.DisplayId && => DisplayId == other.DisplayId &&
Details.Equals(other.Details) && Details.Equals(other.Details) &&
TargetId == other.TargetId; WindowsCCDTargetId == other.WindowsCCDTargetId;
public override Int32 GetHashCode() 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); 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 struct NV_DISPLAYCONFIG_PATH_TARGET_INFO_V1 : IEquatable<NV_DISPLAYCONFIG_PATH_TARGET_INFO_V1>
{ {
public UInt32 DisplayId; //!< Display ID 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); 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); 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 struct NV_DISPLAYCONFIG_PATH_INFO_V2 : IEquatable<NV_DISPLAYCONFIG_PATH_INFO_V2> // Version is 2
{ {
public UInt32 Version; public UInt32 Version;
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
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] //[MarshalAs(UnmanagedType.ByValArray)]
public NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2[] TargetInfo; public IntPtr TargetInfo;
public NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1 SourceModeInfo; //!< May be NULL if mode info is not important 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 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 UInt32 Flags;
//!< Used by Non-NVIDIA adapter for pointer to OS Adapter of LUID
//!< type, type casted to void *. //!< type, type casted to void *.
public UInt32 Reserved;
public IntPtr OSAdapterID; 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 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) public bool Equals(NV_DISPLAYCONFIG_PATH_INFO_V2 other)
@ -1134,12 +1237,11 @@ namespace DisplayMagicianShared.NVIDIA
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 && Flags == other.Flags;
OSAdapterID == other.OSAdapterID;
public override Int32 GetHashCode() 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); 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 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 //!< positioned from left to right with GDI Primary at 0,0, and all
//!< other displays in the order of the path array. //!< other displays in the order of the path array.
//public NV_DISPLAYCONFIG_SPANNING_ORIENTATION spanningOrientation; //!< Spanning is only supported on XP public NV_DISPLAYCONFIG_SPANNING_ORIENTATION SpanningOrientation; //!< Spanning is only supported on XP
//public UInt32 bGDIPrimary : 1; public UInt32 Flags;
//public UInt32 bSLIFocus : 1;
//public UInt32 reserved : 30; //!< Must be 0 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); 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_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_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_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 #region Internal Constant
@ -2217,9 +2321,10 @@ namespace DisplayMagicianShared.NVIDIA
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_ColorControl, out Disp_ColorControlInternal); GetDelegate(NvId_Disp_ColorControl, out Disp_ColorControlInternal);
/*GetDelegate(NvId_DISP_GetDisplayConfig, out DISP_GetDisplayConfigInternal); 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_GetDisplayConfigInternalNull); // null version of the submission
GetDelegate(NvId_DISP_GetDisplayIdByDisplayName, out DISP_GetDisplayIdByDisplayNameInternal); GetDelegate(NvId_DISP_GetDisplayIdByDisplayName, out DISP_GetDisplayIdByDisplayNameInternal);
GetDelegate(NvId_DISP_EnumCustomDisplay, out Disp_EnumCustomDisplayInternal);
// GPUs // GPUs
GetDelegate(NvId_EnumPhysicalGPUs, out EnumPhysicalGPUsInternal); GetDelegate(NvId_EnumPhysicalGPUs, out EnumPhysicalGPUsInternal);
@ -3271,7 +3376,7 @@ namespace DisplayMagicianShared.NVIDIA
// ******** IMPORTANT! This code has an error when attempting to perform the third pass as required by NVAPI documentation ********* // ******** 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. ******** // ******** 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); // NVAPI_INTERFACE NvAPI_DISP_GetDisplayConfig(__inout NvU32 *pathInfoCount, __out_ecount_full_opt(*pathInfoCount) NV_DISPLAYCONFIG_PATH_INFO *pathInfo);
private delegate NVAPI_STATUS DISP_GetDisplayConfigDelegate( private delegate NVAPI_STATUS DISP_GetDisplayConfigDelegate(
[In][Out] ref UInt32 pathInfoCount, [In][Out] ref UInt32 pathInfoCount,
[In][Out] IntPtr pathInfoBuffer); [In][Out] IntPtr pathInfoBuffer);
@ -3290,30 +3395,33 @@ namespace DisplayMagicianShared.NVIDIA
/// <param name="PathInfoCount"></param> /// <param name="PathInfoCount"></param>
/// <param name="PathInfo"></param> /// <param name="PathInfo"></param>
/// <returns></returns> /// <returns></returns>
public static NVAPI_STATUS NvAPI_DISP_GetDisplayConfig(ref UInt32 PathInfoCount, ref NV_DISPLAYCONFIG_PATH_INFO_V1[] PathInfos, bool partFilledIn = false) public static NVAPI_STATUS NvAPI_DISP_GetDisplayConfig(ref UInt32 PathInfoCount, ref NV_DISPLAYCONFIG_PATH_INFO_V2[] PathInfos, bool thirdPass = false)
{ {
NVAPI_STATUS status; NVAPI_STATUS status;
IntPtr pathInfoBuffer = IntPtr.Zero; IntPtr pathInfoBuffer = IntPtr.Zero;
IntPtr currentPathInfoBuffer = IntPtr.Zero; IntPtr currentPathInfoBuffer = IntPtr.Zero;
if (partFilledIn) 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) // 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; // Third Pass(Optional, only required if target information is required): Allocate memory for targetInfo with respect
//PathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V1[PathInfoCount]; //! 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 // Go through the array and create the structure
int overallTargetCount = 0; int overallTargetCount = 0;
for (Int32 x = 0; x < (Int32)PathInfoCount; x++) for (Int32 x = 0; x < (Int32)PathInfoCount; x++)
{ {
// Copy the information passed in, into the buffer we want to pass // 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].SourceId = passedPathInfo[x].SourceId;
PathInfos[x].TargetInfoCount = passedPathInfo[x].TargetInfoCount; PathInfos[x].TargetInfoCount = passedPathInfo[x].TargetInfoCount;
PathInfos[x].TargetInfo = passedPathInfo[x].TargetInfo; PathInfos[x].TargetInfo = passedPathInfo[x].TargetInfo;
PathInfos[x].SourceModeInfo = = passedPathInfo[x].SourceModeInfo;*//* PathInfos[x].SourceModeInfo = passedPathInfo[x].SourceModeInfo;
overallTargetCount += (int)PathInfos[x].TargetInfoCount; 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 // Initialize unmanged memory to hold the unmanaged array of structs
int memorySizeRequired = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_INFO_V1)) * (int)PathInfoCount; int memorySizeRequired = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_INFO_V2)) * (int)PathInfoCount;
pathInfoBuffer = Marshal.AllocCoTaskMem(memorySizeRequired); pathInfoBuffer = Marshal.AllocCoTaskMem(memorySizeRequired);
// Also set another memory pointer to the same place so that we can do the memory copying item by item // 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) // as we have to do it ourselves (there isn't an easy to use Marshal equivalent)
@ -3330,23 +3438,48 @@ namespace DisplayMagicianShared.NVIDIA
} }
else 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 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 // 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]; PathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V2[PathInfoCount];
// Prepare the struct for second pass duties
for (Int32 x = 0; x < (Int32)PathInfoCount; x++)
{
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 // Initialize unmanged memory to hold the unmanaged array of structs
pathInfoBuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_INFO_V1)) * (int)PathInfoCount); 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 // 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) // as we have to do it ourselves (there isn't an easy to use Marshal equivalent)
currentPathInfoBuffer = pathInfoBuffer; currentPathInfoBuffer = pathInfoBuffer;
// Go through the array and copy things from managed code to unmanaged code // Go through the array and copy things from managed code to unmanaged code
for (Int32 x = 0; x < (Int32)PathInfoCount; x++) 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 a single gridtopology into unmanaged code ready for sending to the unmanaged NVAPI function
Marshal.StructureToPtr(PathInfos[x], currentPathInfoBuffer, false); Marshal.StructureToPtr(PathInfos[x], currentPathInfoBuffer, true);
// advance the buffer forwards to the next object // advance the buffer forwards to the next object
currentPathInfoBuffer = (IntPtr)((long)currentPathInfoBuffer + Marshal.SizeOf(PathInfos[x])); currentPathInfoBuffer = (IntPtr)((long)currentPathInfoBuffer.ToInt64() + Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2)));
} }
} }
@ -3363,16 +3496,16 @@ namespace DisplayMagicianShared.NVIDIA
// Reset the memory pointer we're using for tracking where we are back to the start of the unmanaged memory buffer // Reset the memory pointer we're using for tracking where we are back to the start of the unmanaged memory buffer
currentPathInfoBuffer = pathInfoBuffer; currentPathInfoBuffer = pathInfoBuffer;
// Create a managed array to store the received information within // Create a managed array to store the received information within
PathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V1[PathInfoCount]; PathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V2[PathInfoCount];
// Go through the memory buffer item by item and copy the items into the managed array // Go through the memory buffer item by item and copy the items into the managed array
for (int i = 0; i < PathInfoCount; i++) for (int i = 0; i < PathInfoCount; i++)
{ {
// build a structure in the array slot // build a structure in the array slot
PathInfos[i] = new NV_DISPLAYCONFIG_PATH_INFO_V1(); PathInfos[i] = new NV_DISPLAYCONFIG_PATH_INFO_V2();
// fill the array slot structure with the data from the buffer // 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)); 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 // destroy the bit of memory we no longer need
Marshal.DestroyStructure(currentPathInfoBuffer, typeof(NV_DISPLAYCONFIG_PATH_INFO_V1)); Marshal.DestroyStructure(currentPathInfoBuffer, typeof(NV_DISPLAYCONFIG_PATH_INFO_V2));
// advance the buffer forwards to the next object // advance the buffer forwards to the next object
currentPathInfoBuffer = (IntPtr)((long)currentPathInfoBuffer + Marshal.SizeOf(PathInfos[i])); currentPathInfoBuffer = (IntPtr)((long)currentPathInfoBuffer + Marshal.SizeOf(PathInfos[i]));
} }
@ -3416,7 +3549,7 @@ namespace DisplayMagicianShared.NVIDIA
else { status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND; } else { status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND; }
return status; return status;
}*/ }
// NVAPI_INTERFACE NvAPI_DISP_GetDisplayIdByDisplayName(const char *displayName, NvU32* displayId); // NVAPI_INTERFACE NvAPI_DISP_GetDisplayIdByDisplayName(const char *displayName, NvU32* displayId);
@ -4173,6 +4306,28 @@ namespace DisplayMagicianShared.NVIDIA
return status; 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); //NVAPI_INTERFACE NvAPI_GPU_GetFullName(NvPhysicalGpuHandle hPhysicalGpu, NvAPI_ShortString szName);
private delegate NVAPI_STATUS GPU_GetFullNameDelegate( private delegate NVAPI_STATUS GPU_GetFullNameDelegate(
[In] PhysicalGpuHandle gpuHandle, [In] PhysicalGpuHandle gpuHandle,

View File

@ -51,8 +51,8 @@ namespace DisplayMagicianShared.NVIDIA
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct NVIDIA_HDR_CONFIG : IEquatable<NVIDIA_HDR_CONFIG> public struct NVIDIA_HDR_CONFIG : IEquatable<NVIDIA_HDR_CONFIG>
{ {
public Dictionary<UInt32, NV_HDR_CAPABILITIES_V2> HdrCapabilities; public Dictionary<string, NV_HDR_CAPABILITIES_V2> HdrCapabilities;
public Dictionary<UInt32, NV_HDR_COLOR_DATA_V2> HdrColorData; public Dictionary<string, NV_HDR_COLOR_DATA_V2> HdrColorData;
public bool IsNvHdrEnabled; public bool IsNvHdrEnabled;
public override bool Equals(object obj) => obj is NVIDIA_HDR_CONFIG other && this.Equals(other); public override bool Equals(object obj) => obj is NVIDIA_HDR_CONFIG other && this.Equals(other);
@ -73,7 +73,7 @@ namespace DisplayMagicianShared.NVIDIA
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct NVIDIA_COLOR_CONFIG : IEquatable<NVIDIA_COLOR_CONFIG> public struct NVIDIA_COLOR_CONFIG : IEquatable<NVIDIA_COLOR_CONFIG>
{ {
public Dictionary<UInt32, NV_COLOR_DATA_V5> ColorData; public Dictionary<string, NV_COLOR_DATA_V5> ColorData;
public override bool Equals(object obj) => obj is NVIDIA_COLOR_CONFIG other && this.Equals(other); public override bool Equals(object obj) => obj is NVIDIA_COLOR_CONFIG other && this.Equals(other);
public bool Equals(NVIDIA_COLOR_CONFIG other) public bool Equals(NVIDIA_COLOR_CONFIG other)
@ -88,7 +88,7 @@ namespace DisplayMagicianShared.NVIDIA
public static bool operator !=(NVIDIA_COLOR_CONFIG lhs, NVIDIA_COLOR_CONFIG rhs) => !(lhs == rhs); public static bool operator !=(NVIDIA_COLOR_CONFIG lhs, NVIDIA_COLOR_CONFIG rhs) => !(lhs == rhs);
} }
[StructLayout(LayoutKind.Sequential)] /*[StructLayout(LayoutKind.Sequential)]
public struct NVIDIA_CUSTOM_DISPLAY_CONFIG : IEquatable<NVIDIA_CUSTOM_DISPLAY_CONFIG> public struct NVIDIA_CUSTOM_DISPLAY_CONFIG : IEquatable<NVIDIA_CUSTOM_DISPLAY_CONFIG>
{ {
public List<NV_CUSTOM_DISPLAY_V1> CustomDisplay; public List<NV_CUSTOM_DISPLAY_V1> CustomDisplay;
@ -104,8 +104,7 @@ namespace DisplayMagicianShared.NVIDIA
public static bool operator ==(NVIDIA_CUSTOM_DISPLAY_CONFIG lhs, NVIDIA_CUSTOM_DISPLAY_CONFIG rhs) => lhs.Equals(rhs); public static bool operator ==(NVIDIA_CUSTOM_DISPLAY_CONFIG lhs, NVIDIA_CUSTOM_DISPLAY_CONFIG rhs) => lhs.Equals(rhs);
public static bool operator !=(NVIDIA_CUSTOM_DISPLAY_CONFIG lhs, NVIDIA_CUSTOM_DISPLAY_CONFIG rhs) => !(lhs == rhs); public static bool operator !=(NVIDIA_CUSTOM_DISPLAY_CONFIG lhs, NVIDIA_CUSTOM_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>
@ -113,12 +112,12 @@ namespace DisplayMagicianShared.NVIDIA
public NVIDIA_MOSAIC_CONFIG MosaicConfig; public NVIDIA_MOSAIC_CONFIG MosaicConfig;
public NVIDIA_HDR_CONFIG HdrConfig; public NVIDIA_HDR_CONFIG HdrConfig;
public NVIDIA_COLOR_CONFIG ColorConfig; public NVIDIA_COLOR_CONFIG ColorConfig;
public Dictionary<UInt32, NVIDIA_CUSTOM_DISPLAY_CONFIG> CustomDisplays; public Dictionary<string, List<NV_CUSTOM_DISPLAY_V1>> CustomDisplays;
public List<NV_DISPLAYCONFIG_PATH_INFO_V2> DisplayConfigs; public List<NV_DISPLAYCONFIG_PATH_INFO_V2> DisplayConfigs;
// Note: We purposely have left out the DisplayNames from the Equals as it's order keeps changing after each reboot and after each profile swap // Note: We purposely have left out the DisplayNames from the Equals as it's order keeps changing after each reboot and after each profile swap
// and it is informational only and doesn't contribute to the configuration (it's used for generating the Screens structure, and therefore for // and it is informational only and doesn't contribute to the configuration (it's used for generating the Screens structure, and therefore for
// generating the profile icon. // generating the profile icon.
public Dictionary<UInt32, string> DisplayNames; public Dictionary<string, string> 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);
@ -127,13 +126,13 @@ namespace DisplayMagicianShared.NVIDIA
=> MosaicConfig.Equals(other.MosaicConfig) && => MosaicConfig.Equals(other.MosaicConfig) &&
HdrConfig.Equals(other.HdrConfig) && HdrConfig.Equals(other.HdrConfig) &&
ColorConfig.Equals(other.ColorConfig) && ColorConfig.Equals(other.ColorConfig) &&
//CustomDisplays.SequenceEqual(other.CustomDisplays) && CustomDisplays.SequenceEqual(other.CustomDisplays) &&
//DisplayConfigs.SequenceEqual(other.DisplayConfigs) && DisplayConfigs.SequenceEqual(other.DisplayConfigs) &&
DisplayIdentifiers.SequenceEqual(other.DisplayIdentifiers); DisplayIdentifiers.SequenceEqual(other.DisplayIdentifiers);
public override int GetHashCode() public override int GetHashCode()
{ {
return (MosaicConfig, HdrConfig, DisplayIdentifiers, DisplayNames).GetHashCode(); return (MosaicConfig, HdrConfig, CustomDisplays, DisplayConfigs, 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);
@ -274,12 +273,12 @@ namespace DisplayMagicianShared.NVIDIA
myDefaultConfig.MosaicConfig.MosaicGridTopos = new NV_MOSAIC_GRID_TOPO_V2[0]; myDefaultConfig.MosaicConfig.MosaicGridTopos = new NV_MOSAIC_GRID_TOPO_V2[0];
myDefaultConfig.MosaicConfig.MosaicViewports = new List<NV_RECT[]>(); myDefaultConfig.MosaicConfig.MosaicViewports = new List<NV_RECT[]>();
myDefaultConfig.HdrConfig.HdrCapabilities = new Dictionary<uint, NV_HDR_CAPABILITIES_V2>(); myDefaultConfig.HdrConfig.HdrCapabilities = new Dictionary<string, NV_HDR_CAPABILITIES_V2>();
myDefaultConfig.HdrConfig.HdrColorData = new Dictionary<uint, NV_HDR_COLOR_DATA_V2>(); myDefaultConfig.HdrConfig.HdrColorData = new Dictionary<string, NV_HDR_COLOR_DATA_V2>();
myDefaultConfig.ColorConfig.ColorData = new Dictionary<uint, NV_COLOR_DATA_V5>(); myDefaultConfig.ColorConfig.ColorData = new Dictionary<string, NV_COLOR_DATA_V5>();
myDefaultConfig.CustomDisplays = new Dictionary<uint, NVIDIA_CUSTOM_DISPLAY_CONFIG>(); myDefaultConfig.CustomDisplays = new Dictionary<string, List<NV_CUSTOM_DISPLAY_V1>>();
myDefaultConfig.DisplayConfigs = new List<NV_DISPLAYCONFIG_PATH_INFO_V2>(); myDefaultConfig.DisplayConfigs = new List<NV_DISPLAYCONFIG_PATH_INFO_V2>();
myDefaultConfig.DisplayNames = new Dictionary<uint, string>(); myDefaultConfig.DisplayNames = new Dictionary<string, string>();
myDefaultConfig.DisplayIdentifiers = new List<string>(); myDefaultConfig.DisplayIdentifiers = new List<string>();
return myDefaultConfig; return myDefaultConfig;
@ -547,6 +546,126 @@ namespace DisplayMagicianShared.NVIDIA
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NVIDIA Mosaic is NOT possible."); SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NVIDIA Mosaic is NOT possible.");
} }
// Now we try to get the NVIDIA Windows Display Config. This is needed for handling some of the advanced scaling settings that some advanced users make use of
///////////////////////////////////////////////////////////////////////////////
// FUNCTION NAME: NvAPI_DISP_GetDisplayConfig
//
//! 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
// First pass: Figure out how many pathInfo objects there are
List<NV_DISPLAYCONFIG_PATH_INFO_V2> allDisplayConfigs = new List<NV_DISPLAYCONFIG_PATH_INFO_V2>();
/*uint pathInfoCount = 0;
NVStatus = NVImport.NvAPI_DISP_GetDisplayConfig(ref pathInfoCount);
if (NVStatus == NVAPI_STATUS.NVAPI_OK && pathInfoCount > 0)
{
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_DISP_GetDisplayConfig returned OK on first pass. We know we have {pathInfoCount} pathInfo objects to get");
// Second pass: Now get the number of targetInfoCount for each returned pathInfoCount object
NV_DISPLAYCONFIG_PATH_INFO_V2[] pathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V2[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 on second pass.");
// Third pass: 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 on third pass.");
}
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} on third pass.");
}
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} on third pass.");
}
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} on third pass.");
}
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} on third pass.");
}
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} on third pass.");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
{
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus} on third pass.");
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting NVIDIA Display Config! NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus} on third pass.");
}
}
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} on second pass.");
}
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} on second pass.");
}
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} on second pass.");
}
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} on second pass.");
}
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} on second pass.");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
{
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus} on second pass.");
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting NVIDIA Display Config! NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus} on second pass.");
}
}
else if (NVStatus == NVAPI_STATUS.NVAPI_OK && pathInfoCount == 0)
{
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The call was successful but no display paths were found. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus} on first pass");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
{
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more arguments passed in are invalid. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus} on first pass");
}
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} on first pass");
}
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} on first pass");
}
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} on first pass");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
{
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus} on first pass");
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting NVIDIA Display Config! NvAPI_DISP_GetDisplayConfig() returned error code {NVStatus} on first pass");
}*/
// We want to get the primary monitor // We want to get the primary monitor
NVStatus = NVImport.NvAPI_DISP_GetGDIPrimaryDisplayId(out UInt32 primaryDisplayId); NVStatus = NVImport.NvAPI_DISP_GetGDIPrimaryDisplayId(out UInt32 primaryDisplayId);
@ -577,7 +696,7 @@ namespace DisplayMagicianShared.NVIDIA
} }
else else
{ {
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_DISP_GetGDIPrimaryDisplayId() returned error code {NVStatus}"); SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting primary display id! NvAPI_DISP_GetGDIPrimaryDisplayId() returned error code {NVStatus}");
} }
// We want to get the number of displays we have // We want to get the number of displays we have
@ -589,31 +708,31 @@ namespace DisplayMagicianShared.NVIDIA
NVStatus = NVImport.NvAPI_GPU_GetConnectedDisplayIds(physicalGpus[physicalGpuIndex], ref displayCount, 0); NVStatus = NVImport.NvAPI_GPU_GetConnectedDisplayIds(physicalGpus[physicalGpuIndex], ref displayCount, 0);
if (NVStatus == NVAPI_STATUS.NVAPI_OK) if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{ {
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_DISP_GetGDIPrimaryDisplayId returned OK. We have {displayCount} physical GPUs"); SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_GPU_GetConnectedDisplayIds returned OK on first pass. We have {displayCount} physical GPUs");
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER) else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER)
{ {
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The input buffer is not large enough to hold it's contents. NvAPI_DISP_GetGDIPrimaryDisplayId() returned error code {NVStatus}"); SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The input buffer is not large enough to hold it's contents. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus} on first pass.");
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_DISPLAY_ID) else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_DISPLAY_ID)
{ {
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The input monitor is either not connected or is not a DP or HDMI panel. NvAPI_DISP_GetGDIPrimaryDisplayId() returned error code {NVStatus}"); SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The input monitor is either not connected or is not a DP or HDMI panel. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus} on first pass.");
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED) else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
{ {
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_DISP_GetGDIPrimaryDisplayId() returned error code {NVStatus}"); SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus} on first pass.");
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION) else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
{ {
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_DISP_GetGDIPrimaryDisplayId() returned error code {NVStatus}"); SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus} on first pass.");
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR) else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
{ {
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_DISP_GetGDIPrimaryDisplayId() returned error code {NVStatus}"); SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus} on first pass.");
} }
else else
{ {
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_DISP_GetGDIPrimaryDisplayId() returned error code {NVStatus}"); SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting connected display ids! NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus} on first pass.");
} }
if (displayCount > 0) if (displayCount > 0)
@ -623,42 +742,40 @@ namespace DisplayMagicianShared.NVIDIA
NVStatus = NVImport.NvAPI_GPU_GetConnectedDisplayIds(physicalGpus[physicalGpuIndex], ref displayIds, ref displayCount, 0); NVStatus = NVImport.NvAPI_GPU_GetConnectedDisplayIds(physicalGpus[physicalGpuIndex], ref displayIds, ref displayCount, 0);
if (NVStatus == NVAPI_STATUS.NVAPI_OK) if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{ {
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_GPU_GetConnectedDisplayIds returned OK. We have {displayCount} physical GPUs"); SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_GPU_GetConnectedDisplayIds returned OK on second pass. We have {displayCount} physical GPUs");
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER) else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER)
{ {
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The input buffer is not large enough to hold it's contents. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus}"); SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The input buffer is not large enough to hold it's contents. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus} on second pass.");
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_DISPLAY_ID) else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_DISPLAY_ID)
{ {
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The input monitor is either not connected or is not a DP or HDMI panel. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus}"); SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The input monitor is either not connected or is not a DP or HDMI panel. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus} on second pass.");
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED) else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
{ {
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus}"); SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus} on second pass.");
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION) else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
{ {
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus}"); SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus} on second pass.");
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR) else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
{ {
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus}"); SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_GPU_GetConnectedDisplayIds() returned error code {NVStatus} on second pass.");
} }
else else
{ {
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_DISP_GetGDIPrimaryDisplayId() returned error code {NVStatus}"); SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting connected display ids! NvAPI_DISP_GetGDIPrimaryDisplayId() returned error code {NVStatus} on second pass.");
} }
// Time to get the color settings, HDR capabilities and settings for each display // Time to get the color settings, HDR capabilities and settings for each display
bool isNvHdrEnabled = false; bool isNvHdrEnabled = false;
Dictionary<UInt32, NV_HDR_CAPABILITIES_V2> allHdrCapabilities = new Dictionary<UInt32, NV_HDR_CAPABILITIES_V2>(); Dictionary<string, NV_HDR_CAPABILITIES_V2> allHdrCapabilities = new Dictionary<string, NV_HDR_CAPABILITIES_V2>();
Dictionary<UInt32, NV_HDR_COLOR_DATA_V2> allHdrColorData = new Dictionary<UInt32, NV_HDR_COLOR_DATA_V2>(); Dictionary<string, NV_HDR_COLOR_DATA_V2> allHdrColorData = new Dictionary<string, NV_HDR_COLOR_DATA_V2>();
Dictionary<UInt32, NV_COLOR_DATA_V5> allColorData = new Dictionary<UInt32, NV_COLOR_DATA_V5>(); Dictionary<string, NV_COLOR_DATA_V5> allColorData = new Dictionary<string, NV_COLOR_DATA_V5>();
Dictionary<UInt32, NVIDIA_CUSTOM_DISPLAY_CONFIG> allCustomDisplays = new Dictionary<UInt32, NVIDIA_CUSTOM_DISPLAY_CONFIG>(); Dictionary<string, List<NV_CUSTOM_DISPLAY_V1>> allCustomDisplays = new Dictionary<string, List<NV_CUSTOM_DISPLAY_V1>>();
List<NV_DISPLAYCONFIG_PATH_INFO_V2> allDisplayConfigs = new List<NV_DISPLAYCONFIG_PATH_INFO_V2>();
for (int displayIndex = 0; displayIndex < displayCount; displayIndex++) for (int displayIndex = 0; displayIndex < displayCount; displayIndex++)
{ {
if (allDisplays) if (allDisplays)
@ -686,7 +803,7 @@ namespace DisplayMagicianShared.NVIDIA
if (NVStatus == NVAPI_STATUS.NVAPI_OK) if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{ {
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Your monitor {displayIds[displayIndex].DisplayId} has the following color settings set. BPC = {colorData.Bpc.ToString("G")}. Color Format = {colorData.ColorFormat.ToString("G")}. Colorimetry = {colorData.Colorimetry.ToString("G")}. Color Selection Policy = {colorData.ColorSelectionPolicy.ToString("G")}. Color Depth = {colorData.Depth.ToString("G")}. Dynamic Range = {colorData.DynamicRange.ToString("G")}. NvAPI_Disp_ColorControl() returned error code {NVStatus}"); SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Your monitor {displayIds[displayIndex].DisplayId} has the following color settings set. BPC = {colorData.Bpc.ToString("G")}. Color Format = {colorData.ColorFormat.ToString("G")}. Colorimetry = {colorData.Colorimetry.ToString("G")}. Color Selection Policy = {colorData.ColorSelectionPolicy.ToString("G")}. Color Depth = {colorData.Depth.ToString("G")}. Dynamic Range = {colorData.DynamicRange.ToString("G")}. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
allColorData.Add(displayIds[displayIndex].DisplayId, colorData); allColorData.Add(displayIds[displayIndex].DisplayId.ToString(), colorData);
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER) else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER)
{ {
@ -773,7 +890,7 @@ namespace DisplayMagicianShared.NVIDIA
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Display {displayIds[displayIndex].DisplayId} DOES NOT support Driver Expanded Default HDR Parameters "); SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Display {displayIds[displayIndex].DisplayId} DOES NOT support Driver Expanded Default HDR Parameters ");
} }
allHdrCapabilities.Add(displayIds[displayIndex].DisplayId, hdrCapabilities); allHdrCapabilities.Add(displayIds[displayIndex].DisplayId.ToString(), hdrCapabilities);
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER) else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER)
{ {
@ -811,7 +928,7 @@ namespace DisplayMagicianShared.NVIDIA
{ {
isNvHdrEnabled = true; isNvHdrEnabled = true;
} }
allHdrColorData.Add(displayIds[displayIndex].DisplayId, hdrColorData); allHdrColorData.Add(displayIds[displayIndex].DisplayId.ToString(), hdrColorData);
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER) else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER)
{ {
@ -837,9 +954,66 @@ namespace DisplayMagicianShared.NVIDIA
{ {
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting HDR color settings! NvAPI_Disp_HdrColorControl() returned error code {NVStatus}. It's most likely that your monitor {displayIds[displayIndex].DisplayId} doesn't support HDR."); SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting HDR color settings! NvAPI_Disp_HdrColorControl() returned error code {NVStatus}. It's most likely that your monitor {displayIds[displayIndex].DisplayId} doesn't support HDR.");
} }
// TEMPORARILY DISABLING THE CUSTOM DISPLAY CODE FOR NOW, AS NOT SURE WHAT NVIDIA SETTINGS IT TRACKS
// KEEPING IT IN CASE I NEED IT FOR LATER. I ORIGINALLY THOUGHT THAT IS WHERE INTEGER SCALING SETTINGS LIVED< BUT WAS WRONG
/*// Now we get the Custom Display settings of the display (if there are any)
//NVIDIA_CUSTOM_DISPLAY_CONFIG customDisplayConfig = new NVIDIA_CUSTOM_DISPLAY_CONFIG();
List<NV_CUSTOM_DISPLAY_V1> customDisplayConfig = new List<NV_CUSTOM_DISPLAY_V1>();
for (UInt32 d = 0; d < UInt32.MaxValue; d++)
{
NV_CUSTOM_DISPLAY_V1 customDisplay = new NV_CUSTOM_DISPLAY_V1();
NVStatus = NVImport.NvAPI_DISP_EnumCustomDisplay(displayIds[displayIndex].DisplayId, d, ref customDisplay);
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_DISP_EnumCustomDisplay returned OK. Custom Display settings retrieved.");
customDisplayConfig.Add(customDisplay);
}
else if (NVStatus == NVAPI_STATUS.NVAPI_END_ENUMERATION)
{
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: We've reached the end of the list of Custom Displays. Breaking the polling loop.");
break;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_DISPLAY_ID)
{
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The input monitor is either not connected or is not a DP or HDMI panel. NvAPI_DISP_EnumCustomDisplay() returned error code {NVStatus}");
break;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
{
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_DISP_EnumCustomDisplay() returned error code {NVStatus}");
break;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
{
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_DISP_EnumCustomDisplay() returned error code {NVStatus}");
break;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INCOMPATIBLE_STRUCT_VERSION)
{
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The supplied struct is incompatible. NvAPI_DISP_EnumCustomDisplay() returned error code {NVStatus}");
break;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
{
SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_DISP_EnumCustomDisplay() returned error code {NVStatus}.");
break;
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while enumerating the custom displays! NvAPI_DISP_EnumCustomDisplay() returned error code {NVStatus}.");
break;
} }
// Store the information }
if (customDisplayConfig.Count > 0)
{
allCustomDisplays.Add(displayIds[displayIndex].DisplayId, customDisplayConfig);
}*/
}
// Store the HDR information
myDisplayConfig.HdrConfig.IsNvHdrEnabled = isNvHdrEnabled; myDisplayConfig.HdrConfig.IsNvHdrEnabled = isNvHdrEnabled;
myDisplayConfig.HdrConfig.HdrCapabilities = allHdrCapabilities; myDisplayConfig.HdrConfig.HdrCapabilities = allHdrCapabilities;
myDisplayConfig.HdrConfig.HdrColorData = allHdrColorData; myDisplayConfig.HdrConfig.HdrColorData = allHdrColorData;
@ -853,7 +1027,7 @@ namespace DisplayMagicianShared.NVIDIA
// Now we need to loop through each of the windows paths so we can record the Windows DisplayName to DisplayID mapping // 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! // This is needed for us to piece together the Screen layout for when we draw the NVIDIA screens!
myDisplayConfig.DisplayNames = new Dictionary<uint, string>(); myDisplayConfig.DisplayNames = new Dictionary<string, string>();
foreach (KeyValuePair<string, List<uint>> displaySource in WinLibrary.GetDisplaySourceNames()) foreach (KeyValuePair<string, List<uint>> displaySource in WinLibrary.GetDisplaySourceNames())
{ {
// Now we try to get the information about the displayIDs and map them to windows \\DISPLAY names e.g. \\DISPLAY1 // Now we try to get the information about the displayIDs and map them to windows \\DISPLAY names e.g. \\DISPLAY1
@ -863,7 +1037,7 @@ namespace DisplayMagicianShared.NVIDIA
if (NVStatus == NVAPI_STATUS.NVAPI_OK) if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{ {
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_DISP_GetDisplayIdByDisplayName returned OK. The display {displayName} has NVIDIA DisplayID {displayId}"); SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_DISP_GetDisplayIdByDisplayName returned OK. The display {displayName} has NVIDIA DisplayID {displayId}");
myDisplayConfig.DisplayNames.Add(displayId, displayName); myDisplayConfig.DisplayNames.Add(displayId.ToString(), displayName);
} }
else if (NVStatus == NVAPI_STATUS.NVAPI_NVIDIA_DEVICE_NOT_FOUND) else if (NVStatus == NVAPI_STATUS.NVAPI_NVIDIA_DEVICE_NOT_FOUND)
{ {
@ -1023,7 +1197,7 @@ namespace DisplayMagicianShared.NVIDIA
// Start printing out things // Start printing out things
stringToReturn += $"\n****** NVIDIA COLOR CONFIG *******\n"; stringToReturn += $"\n****** NVIDIA COLOR CONFIG *******\n";
foreach (KeyValuePair<uint, NV_COLOR_DATA_V5> colorData in displayConfig.ColorConfig.ColorData) foreach (KeyValuePair<string, NV_COLOR_DATA_V5> colorData in displayConfig.ColorConfig.ColorData)
{ {
string displayId = colorData.Key.ToString(); string displayId = colorData.Key.ToString();
stringToReturn += $"Display {displayId} BPC is {colorData.Value.Bpc.ToString("G")}.\n"; stringToReturn += $"Display {displayId} BPC is {colorData.Value.Bpc.ToString("G")}.\n";
@ -1052,7 +1226,7 @@ namespace DisplayMagicianShared.NVIDIA
stringToReturn += $"There are no NVIDIA HDR devices in use.\n"; stringToReturn += $"There are no NVIDIA HDR devices in use.\n";
} }
foreach (KeyValuePair<uint, NV_HDR_CAPABILITIES_V2> hdrCapabilityItem in displayConfig.HdrConfig.HdrCapabilities) foreach (KeyValuePair<string, NV_HDR_CAPABILITIES_V2> hdrCapabilityItem in displayConfig.HdrConfig.HdrCapabilities)
{ {
string displayId = hdrCapabilityItem.Key.ToString(); string displayId = hdrCapabilityItem.Key.ToString();
if (hdrCapabilityItem.Value.IsDolbyVisionSupported) if (hdrCapabilityItem.Value.IsDolbyVisionSupported)
@ -1117,6 +1291,176 @@ namespace DisplayMagicianShared.NVIDIA
NVAPI_STATUS NVStatus = NVAPI_STATUS.NVAPI_ERROR; NVAPI_STATUS NVStatus = NVAPI_STATUS.NVAPI_ERROR;
// Remove any custom NVIDIA Colour settings
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn off colour if it's default set colour.");
// Now we try to set each display color
foreach (var colorDataDict in displayConfig.ColorConfig.ColorData)
{
NV_COLOR_DATA_V5 colorData = colorDataDict.Value;
string displayId = colorDataDict.Key;
try
{
UInt32 displayIdAsUInt32 = UInt32.Parse(displayId);
if (!ActiveDisplayConfig.ColorConfig.ColorData.ContainsKey(displayId))
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Display {displayId} doesn't exist in this setup, so skipping turning off prior NVIDIA Color Settings.");
continue;
}
// If this is a setting that says it will use default windows colour settings, then we turn it off
if (colorData.ColorSelectionPolicy == NV_COLOR_SELECTION_POLICY.NV_COLOR_SELECTION_POLICY_DEFAULT &&
ActiveDisplayConfig.ColorConfig.ColorData[displayId].ColorSelectionPolicy != colorData.ColorSelectionPolicy)
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn off NVIDIA customer colour settings for display {displayId}.");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want the standard colour settings to be {displayConfig.ColorConfig.ColorData[displayId].ColorSelectionPolicy.ToString("G")} for Mosaic display {displayId}.");
colorData = displayConfig.ColorConfig.ColorData[displayId];
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want the standard colour settings to be {displayConfig.ColorConfig.ColorData[displayId].ColorSelectionPolicy.ToString("G")} and they are {ActiveDisplayConfig.ColorConfig.ColorData[displayId].ColorSelectionPolicy.ToString("G")} for Mosaic display {displayId}.");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn off standard colour mode for Mosaic display {displayId}.");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings Color selection policy {colorData.ColorSelectionPolicy.ToString("G")} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings BPC {colorData.Bpc} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings colour format {colorData.ColorFormat} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings colourimetry {colorData.Colorimetry} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings colour depth {colorData.Depth} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings dynamic range {colorData.DynamicRange} for Mosaic display {displayId}");
// Set the command as a 'SET'
colorData.Cmd = NV_COLOR_CMD.NV_COLOR_CMD_SET;
NVStatus = NVImport.NvAPI_Disp_ColorControl(displayIdAsUInt32, ref colorData);
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: NvAPI_Disp_ColorControl returned OK. BPC is set to {colorData.Bpc.ToString("G")}. Color Format is set to {colorData.ColorFormat.ToString("G")}. Colorimetry is set to {colorData.Colorimetry.ToString("G")}. Color Selection Policy is set to {colorData.ColorSelectionPolicy.ToString("G")}. Color Depth is set to {colorData.Depth.ToString("G")}. Dynamic Range is set to {colorData.DynamicRange.ToString("G")}");
switch (colorData.ColorSelectionPolicy)
{
case NV_COLOR_SELECTION_POLICY.NV_COLOR_SELECTION_POLICY_USER:
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Color Selection Policy is set to NV_COLOR_SELECTION_POLICY_USER so the color settings have been set by the user in the NVIDIA Control Panel.");
break;
case NV_COLOR_SELECTION_POLICY.NV_COLOR_SELECTION_POLICY_BEST_QUALITY: // Also matches NV_COLOR_SELECTION_POLICY_DEFAULT as it is 1
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Color Selection Policy is set to NV_COLOR_SELECTION_POLICY_BEST_QUALITY so the color settings are being handled by the Windows OS.");
break;
case NV_COLOR_SELECTION_POLICY.NV_COLOR_SELECTION_POLICY_UNKNOWN:
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: Color Selection Policy is set to NV_COLOR_SELECTION_POLICY_UNKNOWN so the color settings aren't being handled by either the Windows OS or the NVIDIA Setup!");
break;
}
}
else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: Your monitor {displayId} doesn't support the requested color settings. BPC = {colorData.Bpc.ToString("G")}. Color Format = {colorData.ColorFormat.ToString("G")}. Colorimetry = {colorData.Colorimetry.ToString("G")}. Color Selection Policy = {colorData.ColorSelectionPolicy.ToString("G")}. Color Depth = {colorData.Depth.ToString("G")}. Dynamic Range = {colorData.DynamicRange.ToString("G")}. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The input buffer is not large enough to hold it's contents. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_DISPLAY_ID)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The input monitor is either not connected or is not a DP or HDMI panel. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The NvAPI API needs to be initialized first. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: This entry point not available in this NVIDIA Driver. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: A miscellaneous error occurred. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Some non standard error occurred while seting the color settings! NvAPI_Disp_ColorControl() returned error code {NVStatus}. It's most likely that your monitor {displayId} doesn't support this color mode.");
}
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want only want to turn off custom NVIDIA colour settings if needed for display {displayId}, and that currently isn't required. Skipping changing NVIDIA colour mode.");
}
}
catch (Exception ex)
{
SharedLogger.logger.Error(ex, $"NVIDIALibrary/SetActiveConfigOverride: Exception caused while turning off prior NVIDIA specific colour settings for display {displayId}.");
}
}
// Remove any custom NVIDIA HDR Colour settings
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn off HDR colour if it's user set HDR colour.");
// Now we try to set each display color
foreach (var hdrColorDataDict in displayConfig.HdrConfig.HdrColorData)
{
NV_HDR_COLOR_DATA_V2 hdrColorData = hdrColorDataDict.Value;
string displayId = hdrColorDataDict.Key;
try
{
UInt32 displayIdAsUInt32 = UInt32.Parse(displayId);
if (!ActiveDisplayConfig.HdrConfig.HdrColorData.ContainsKey(displayId))
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Display {displayId} doesn't exist in this setup, so skipping turning off HDR.");
continue;
}
// if it's not an HDR then we turn off HDR
if (hdrColorData.HdrMode == NV_HDR_MODE.OFF && ActiveDisplayConfig.HdrConfig.HdrColorData[displayId].HdrMode != hdrColorData.HdrMode)
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn on custom HDR mode for display {displayId}.");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: HDR mode is currently {ActiveDisplayConfig.HdrConfig.HdrColorData[displayId].HdrMode.ToString("G")} for Mosaic display {displayId}.");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings BPC {hdrColorData.HdrBpc} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings HDR Colour Format {hdrColorData.HdrColorFormat} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings HDR dynamic range {hdrColorData.HdrDynamicRange} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings HDR Mode {hdrColorData.HdrMode} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings Mastering Display Data {hdrColorData.MasteringDisplayData} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings Static Meradata Description ID {hdrColorData.StaticMetadataDescriptorId} for Mosaic display {displayId}");
// Apply the HDR removal
hdrColorData.Cmd = NV_HDR_CMD.CMD_SET;
NVStatus = NVImport.NvAPI_Disp_HdrColorControl(displayIdAsUInt32, ref hdrColorData);
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: NvAPI_Disp_HdrColorControl returned OK. We just successfully turned off the HDR mode for Mosaic display {displayId}.");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The input buffer is not large enough to hold it's contents. NvAPI_Disp_HdrColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_DISPLAY_ID)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The input monitor is either not connected or is not a DP or HDMI panel. NvAPI_Disp_HdrColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The NvAPI API needs to be initialized first. NvAPI_Disp_HdrColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: This entry point not available in this NVIDIA Driver. NvAPI_Disp_HdrColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: A miscellaneous error occurred. NvAPI_Disp_HdrColorControl() returned error code {NVStatus}");
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Some non standard error occurred while getting Mosaic Topology! NvAPI_Disp_HdrColorControl() returned error code {NVStatus}. It's most likely that your monitor {displayId} doesn't support HDR.");
}
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want only want to turn off custom NVIDIA HDR settings if needed for display {displayId}, and that currently isn't required. Skipping changing NVIDIA HDR mode.");
}
}
catch (Exception ex)
{
SharedLogger.logger.Error(ex, $"NVIDIALibrary/SetActiveConfigOverride: Exception caused while turning off prior NVIDIA HDR colour settings for display {displayId}.");
}
}
// We want to check the NVIDIA Surround (Mosaic) config is valid // We want to check the NVIDIA Surround (Mosaic) config is valid
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Testing whether the display configuration is valid"); SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Testing whether the display configuration is valid");
// //
@ -1250,150 +1594,21 @@ namespace DisplayMagicianShared.NVIDIA
NVAPI_STATUS NVStatus = NVAPI_STATUS.NVAPI_ERROR; NVAPI_STATUS NVStatus = NVAPI_STATUS.NVAPI_ERROR;
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn off colour if it's default set colour.");
// Now we try to set each display color
foreach (var colorDataDict in displayConfig.ColorConfig.ColorData)
{
NV_COLOR_DATA_V5 colorData = colorDataDict.Value;
UInt32 displayId = colorDataDict.Key;
// If this is a setting that says it will use default windows colour settings, then we turn it off
if (colorData.ColorSelectionPolicy == NV_COLOR_SELECTION_POLICY.NV_COLOR_SELECTION_POLICY_DEFAULT &&
ActiveDisplayConfig.ColorConfig.ColorData[displayId].ColorSelectionPolicy != colorData.ColorSelectionPolicy)
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn off NVIDIA customer colour settings for display {displayId}.");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want the standard colour settings to be {displayConfig.ColorConfig.ColorData[displayId].ColorSelectionPolicy.ToString("G")} for Mosaic display {displayId}.");
colorData = displayConfig.ColorConfig.ColorData[displayId];
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want the standard colour settings to be {displayConfig.ColorConfig.ColorData[displayId].ColorSelectionPolicy.ToString("G")} and they are {ActiveDisplayConfig.ColorConfig.ColorData[displayId].ColorSelectionPolicy.ToString("G")} for Mosaic display {displayId}.");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn off standard colour mode for Mosaic display {displayId}.");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings Color selection policy {colorData.ColorSelectionPolicy.ToString("G")} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings BPC {colorData.Bpc} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings colour format {colorData.ColorFormat} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings colourimetry {colorData.Colorimetry} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings colour depth {colorData.Depth} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want standard colour settings dynamic range {colorData.DynamicRange} for Mosaic display {displayId}");
// Set the command as a 'SET'
colorData.Cmd = NV_COLOR_CMD.NV_COLOR_CMD_SET;
NVStatus = NVImport.NvAPI_Disp_ColorControl(displayId, ref colorData);
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: NvAPI_Disp_ColorControl returned OK. BPC is set to {colorData.Bpc.ToString("G")}. Color Format is set to {colorData.ColorFormat.ToString("G")}. Colorimetry is set to {colorData.Colorimetry.ToString("G")}. Color Selection Policy is set to {colorData.ColorSelectionPolicy.ToString("G")}. Color Depth is set to {colorData.Depth.ToString("G")}. Dynamic Range is set to {colorData.DynamicRange.ToString("G")}");
switch (colorData.ColorSelectionPolicy)
{
case NV_COLOR_SELECTION_POLICY.NV_COLOR_SELECTION_POLICY_USER:
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Color Selection Policy is set to NV_COLOR_SELECTION_POLICY_USER so the color settings have been set by the user in the NVIDIA Control Panel.");
break;
case NV_COLOR_SELECTION_POLICY.NV_COLOR_SELECTION_POLICY_BEST_QUALITY: // Also matches NV_COLOR_SELECTION_POLICY_DEFAULT as it is 1
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Color Selection Policy is set to NV_COLOR_SELECTION_POLICY_BEST_QUALITY so the color settings are being handled by the Windows OS.");
break;
case NV_COLOR_SELECTION_POLICY.NV_COLOR_SELECTION_POLICY_UNKNOWN:
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: Color Selection Policy is set to NV_COLOR_SELECTION_POLICY_UNKNOWN so the color settings aren't being handled by either the Windows OS or the NVIDIA Setup!");
break;
}
}
else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: Your monitor {displayId} doesn't support the requested color settings. BPC = {colorData.Bpc.ToString("G")}. Color Format = {colorData.ColorFormat.ToString("G")}. Colorimetry = {colorData.Colorimetry.ToString("G")}. Color Selection Policy = {colorData.ColorSelectionPolicy.ToString("G")}. Color Depth = {colorData.Depth.ToString("G")}. Dynamic Range = {colorData.DynamicRange.ToString("G")}. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The input buffer is not large enough to hold it's contents. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_DISPLAY_ID)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The input monitor is either not connected or is not a DP or HDMI panel. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The NvAPI API needs to be initialized first. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: This entry point not available in this NVIDIA Driver. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: A miscellaneous error occurred. NvAPI_Disp_ColorControl() returned error code {NVStatus}");
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Some non standard error occurred while seting the color settings! NvAPI_Disp_ColorControl() returned error code {NVStatus}. It's most likely that your monitor {displayId} doesn't support this color mode.");
}
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want only want to turn off custom NVIDIA colour settings if needed for display {displayId}, and that currently isn't required. Skipping changing NVIDIA colour mode.");
}
}
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn off HDR colour if it's user set HDR colour.");
// Now we try to set each display color
foreach (var hdrColorDataDict in displayConfig.HdrConfig.HdrColorData)
{
NV_HDR_COLOR_DATA_V2 hdrColorData = hdrColorDataDict.Value;
UInt32 displayId = hdrColorDataDict.Key;
// if it's not an HDR then we turn off HDR
if (hdrColorData.HdrMode == NV_HDR_MODE.OFF && ActiveDisplayConfig.HdrConfig.HdrColorData[displayId].HdrMode != hdrColorData.HdrMode)
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn on custom HDR mode for display {displayId}.");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: HDR mode is currently {ActiveDisplayConfig.HdrConfig.HdrColorData[displayId].HdrMode.ToString("G")} for Mosaic display {displayId}.");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings BPC {hdrColorData.HdrBpc} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings HDR Colour Format {hdrColorData.HdrColorFormat} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings HDR dynamic range {hdrColorData.HdrDynamicRange} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings HDR Mode {hdrColorData.HdrMode} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings Mastering Display Data {hdrColorData.MasteringDisplayData} for Mosaic display {displayId}");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings Static Meradata Description ID {hdrColorData.StaticMetadataDescriptorId} for Mosaic display {displayId}");
// Apply the HDR removal
hdrColorData.Cmd = NV_HDR_CMD.CMD_SET;
NVStatus = NVImport.NvAPI_Disp_HdrColorControl(displayId, ref hdrColorData);
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: NvAPI_Disp_HdrColorControl returned OK. We just successfully turned off the HDR mode for Mosaic display {displayId}.");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INSUFFICIENT_BUFFER)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The input buffer is not large enough to hold it's contents. NvAPI_Disp_HdrColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_DISPLAY_ID)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The input monitor is either not connected or is not a DP or HDMI panel. NvAPI_Disp_HdrColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: The NvAPI API needs to be initialized first. NvAPI_Disp_HdrColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: This entry point not available in this NVIDIA Driver. NvAPI_Disp_HdrColorControl() returned error code {NVStatus}");
}
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
{
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfigOverride: A miscellaneous error occurred. NvAPI_Disp_HdrColorControl() returned error code {NVStatus}");
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Some non standard error occurred while getting Mosaic Topology! NvAPI_Disp_HdrColorControl() returned error code {NVStatus}. It's most likely that your monitor {displayId} doesn't support HDR.");
}
}
else
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want only want to turn off custom NVIDIA HDR settings if needed for display {displayId}, and that currently isn't required. Skipping changing NVIDIA HDR mode.");
}
}
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn on colour if it's user set colour."); SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn on colour if it's user set colour.");
// Now we try to set each display color // Now we try to set each display color
foreach (var colorDataDict in displayConfig.ColorConfig.ColorData) foreach (var colorDataDict in displayConfig.ColorConfig.ColorData)
{ {
NV_COLOR_DATA_V5 colorData = colorDataDict.Value; NV_COLOR_DATA_V5 colorData = colorDataDict.Value;
UInt32 displayId = colorDataDict.Key; string displayId = colorDataDict.Key;
try
{
UInt32 displayIdAsUInt32 = UInt32.Parse(displayId);
if (!ActiveDisplayConfig.ColorConfig.ColorData.ContainsKey(displayId))
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Display {displayId} doesn't exist in this setup, so skipping setting the NVIDIA Color Settings.");
continue;
}
// If this is a setting that says it uses user colour settings, then we turn it off // If this is a setting that says it uses user colour settings, then we turn it off
if (colorData.ColorSelectionPolicy != NV_COLOR_SELECTION_POLICY.NV_COLOR_SELECTION_POLICY_DEFAULT && if (colorData.ColorSelectionPolicy != NV_COLOR_SELECTION_POLICY.NV_COLOR_SELECTION_POLICY_DEFAULT &&
@ -1415,7 +1630,7 @@ namespace DisplayMagicianShared.NVIDIA
// Set the command as a 'SET' // Set the command as a 'SET'
colorData.Cmd = NV_COLOR_CMD.NV_COLOR_CMD_SET; colorData.Cmd = NV_COLOR_CMD.NV_COLOR_CMD_SET;
NVStatus = NVImport.NvAPI_Disp_ColorControl(displayId, ref colorData); NVStatus = NVImport.NvAPI_Disp_ColorControl(displayIdAsUInt32, ref colorData);
if (NVStatus == NVAPI_STATUS.NVAPI_OK) if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{ {
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: NvAPI_Disp_ColorControl returned OK. BPC is set to {colorData.Bpc.ToString("G")}. Color Format is set to {colorData.ColorFormat.ToString("G")}. Colorimetry is set to {colorData.Colorimetry.ToString("G")}. Color Selection Policy is set to {colorData.ColorSelectionPolicy.ToString("G")}. Color Depth is set to {colorData.Depth.ToString("G")}. Dynamic Range is set to {colorData.DynamicRange.ToString("G")}"); SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: NvAPI_Disp_ColorControl returned OK. BPC is set to {colorData.Bpc.ToString("G")}. Color Format is set to {colorData.ColorFormat.ToString("G")}. Colorimetry is set to {colorData.Colorimetry.ToString("G")}. Color Selection Policy is set to {colorData.ColorSelectionPolicy.ToString("G")}. Color Depth is set to {colorData.Depth.ToString("G")}. Dynamic Range is set to {colorData.DynamicRange.ToString("G")}");
@ -1466,13 +1681,29 @@ namespace DisplayMagicianShared.NVIDIA
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want only want to turn on custom NVIDIA colour settings if needed for display {displayId}, and that currently isn't required. Skipping changing NVIDIA colour mode."); SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want only want to turn on custom NVIDIA colour settings if needed for display {displayId}, and that currently isn't required. Skipping changing NVIDIA colour mode.");
} }
} }
catch (Exception ex)
{
SharedLogger.logger.Error(ex, $"NVIDIALibrary/SetActiveConfigOverride: Exception caused while turning on NVIDIA custom colour settings for display {displayId}.");
}
}
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn on NVIDIA HDR colour if it's user wants to use NVIDIA HDR colour."); SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want to turn on NVIDIA HDR colour if it's user wants to use NVIDIA HDR colour.");
// Now we try to set each display color // Now we try to set each display color
foreach (var hdrColorDataDict in displayConfig.HdrConfig.HdrColorData) foreach (var hdrColorDataDict in displayConfig.HdrConfig.HdrColorData)
{ {
NV_HDR_COLOR_DATA_V2 hdrColorData = hdrColorDataDict.Value; NV_HDR_COLOR_DATA_V2 hdrColorData = hdrColorDataDict.Value;
UInt32 displayId = hdrColorDataDict.Key; string displayId = hdrColorDataDict.Key;
try
{
UInt32 displayIdAsUInt32 = UInt32.Parse(displayId);
if (!ActiveDisplayConfig.HdrConfig.HdrColorData.ContainsKey(displayId))
{
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: Display {displayId} doesn't exist in this setup, so skipping setting the HdrColorData.");
continue;
}
// if it's HDR and it's a different mode than what we are in now, then set HDR // if it's HDR and it's a different mode than what we are in now, then set HDR
if (hdrColorData.HdrMode != NV_HDR_MODE.OFF && if (hdrColorData.HdrMode != NV_HDR_MODE.OFF &&
@ -1488,7 +1719,7 @@ namespace DisplayMagicianShared.NVIDIA
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings Static Meradata Description ID {hdrColorData.StaticMetadataDescriptorId} for Mosaic display {displayId}"); SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want HDR settings Static Meradata Description ID {hdrColorData.StaticMetadataDescriptorId} for Mosaic display {displayId}");
// Apply the HDR removal // Apply the HDR removal
hdrColorData.Cmd = NV_HDR_CMD.CMD_SET; hdrColorData.Cmd = NV_HDR_CMD.CMD_SET;
NVStatus = NVImport.NvAPI_Disp_HdrColorControl(displayId, ref hdrColorData); NVStatus = NVImport.NvAPI_Disp_HdrColorControl(displayIdAsUInt32, ref hdrColorData);
if (NVStatus == NVAPI_STATUS.NVAPI_OK) if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{ {
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: NvAPI_Disp_HdrColorControl returned OK. We just successfully turned off the HDR mode for Mosaic display {displayId}."); SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: NvAPI_Disp_HdrColorControl returned OK. We just successfully turned off the HDR mode for Mosaic display {displayId}.");
@ -1523,6 +1754,12 @@ namespace DisplayMagicianShared.NVIDIA
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want only want to turn on custom NVIDIA HDR if needed for display {displayId} and that currently isn't required. Skipping changing NVIDIA HDR mode."); SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfigOverride: We want only want to turn on custom NVIDIA HDR if needed for display {displayId} and that currently isn't required. Skipping changing NVIDIA HDR mode.");
} }
} }
catch (Exception ex)
{
SharedLogger.logger.Error(ex, $"NVIDIALibrary/SetActiveConfigOverride: Exception caused while turning on custom NVIDIA HDR colour settings for display {displayId}.");
}
}
} }
else else
@ -2195,7 +2432,7 @@ namespace DisplayMagicianShared.NVIDIA
if (!displayIdentifiers.Contains(displayIdentifier)) if (!displayIdentifiers.Contains(displayIdentifier))
{ {
displayIdentifiers.Add(displayIdentifier); displayIdentifiers.Add(displayIdentifier);
SharedLogger.logger.Debug($"NVIDIALibrary/GetSomeDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}"); SharedLogger.logger.Debug($"ProfileRepository/GenerateProfileDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}");
} }
} }
} }

View File

@ -1017,33 +1017,84 @@ namespace DisplayMagicianShared.Windows
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Patching the adapter IDs to make the saved config valid"); SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Patching the adapter IDs to make the saved config valid");
PatchAdapterIDs(ref displayConfig, allWindowsDisplayConfig.DisplayAdapters); 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 myPathsCount = (uint)displayConfig.DisplayConfigPaths.Length;
uint myModesCount = (uint)displayConfig.DisplayConfigModes.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); WIN32STATUS err = CCDImport.SetDisplayConfig(myPathsCount, displayConfig.DisplayConfigPaths, myModesCount, displayConfig.DisplayConfigModes, SDC.DISPLAYMAGICIAN_VALIDATE);
if (err == WIN32STATUS.ERROR_SUCCESS) if (err == WIN32STATUS.ERROR_SUCCESS)
{ {
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Successfully validated that the display configuration supplied would work!"); 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; 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 // 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) if (err == WIN32STATUS.ERROR_SUCCESS)
{ {
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Successfully set the display configuration to the settings supplied!"); 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 else
{ {
SharedLogger.logger.Error($"WinLibrary/SetActiveConfig: ERROR - 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.");
throw new WinLibraryException($"SetDisplayConfig couldn't set the display configuration using the settings supplied. Something is wrong."); return false;
} }
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: SUCCESS! The display configuration has been successfully applied"); SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: SUCCESS! The display configuration has been successfully applied");
@ -1445,7 +1496,7 @@ namespace DisplayMagicianShared.Windows
if (!displayIdentifiers.Contains(displayIdentifier)) if (!displayIdentifiers.Contains(displayIdentifier))
{ {
displayIdentifiers.Add(displayIdentifier); displayIdentifiers.Add(displayIdentifier);
SharedLogger.logger.Debug($"WinLibrary/GetSomeDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}"); SharedLogger.logger.Debug($"ProfileRepository/GenerateProfileDisplayIdentifiers: DisplayIdentifier: {displayIdentifier}");
} }
} }