using System; using System.Collections.Generic; using NvAPIWrapper.Native.Display; using NvAPIWrapper.Native.Display.Structures; using NvAPIWrapper.Native.Exceptions; using NvAPIWrapper.Native.GPU; using NvAPIWrapper.Native.Interfaces.Display; namespace NvAPIWrapper.Display { /// /// Represents a display configuration on a path /// public class PathTargetInfo : IEquatable { private TimingOverride _timingOverride; /// /// Creates a new PathTargetInfo /// /// IPathTargetInfo implamented object public PathTargetInfo(IPathTargetInfo info) { DisplayDevice = new DisplayDevice(info.DisplayId); if (info.Details.HasValue) { Rotation = info.Details.Value.Rotation; Scaling = info.Details.Value.Scaling; TVConnectorType = info.Details.Value.ConnectorType; TVFormat = info.Details.Value.TVFormat; RefreshRateInMillihertz = info.Details.Value.RefreshRateInMillihertz; TimingOverride = info.Details.Value.TimingOverride; IsInterlaced = info.Details.Value.IsInterlaced; IsClonePrimary = info.Details.Value.IsClonePrimary; IsClonePanAndScanTarget = info.Details.Value.IsClonePanAndScanTarget; DisableVirtualModeSupport = info.Details.Value.DisableVirtualModeSupport; IsPreferredUnscaledTarget = info.Details.Value.IsPreferredUnscaledTarget; } if (info is PathTargetInfoV2) { WindowsCCDTargetId = ((PathTargetInfoV2) info).WindowsCCDTargetId; } } /// /// Creates a new PathTargetInfo /// /// DisplayDevice object public PathTargetInfo(DisplayDevice device) { DisplayDevice = device; } /// /// Gets or sets the virtual mode support /// public bool DisableVirtualModeSupport { get; set; } /// /// Gets corresponding DisplayDevice /// public DisplayDevice DisplayDevice { get; } /// /// Gets or sets the pan and scan is availability. Valid only when the target is part of clone /// topology. /// public bool IsClonePanAndScanTarget { get; set; } /// /// Gets or sets the primary display in clone configuration. This is *NOT* GDI Primary. /// Only one target can be primary per source. If no primary is specified, the first target will automatically be /// primary. /// public bool IsClonePrimary { get; set; } /// /// Gets or sets the interlaced mode flag, ignored if refreshRate == 0 /// public bool IsInterlaced { get; set; } /// /// Gets or sets the preferred unscaled mode of target /// public bool IsPreferredUnscaledTarget { get; set; } /// /// Gets and sets the non-interlaced Refresh Rate of the mode, multiplied by 1000, 0 = ignored /// This is the value which driver reports to the OS. /// public uint RefreshRateInMillihertz { get; set; } /// /// Gets and sets the rotation setting /// public Rotate Rotation { get; set; } /// /// Gets and sets the scaling setting /// public Scaling Scaling { get; set; } /// /// Gets and sets the custom timing of display /// Ignored if TimingOverride == TimingOverride.Current /// public TimingOverride TimingOverride { get => _timingOverride; set { if (value == TimingOverride.Custom) { throw new NVIDIANotSupportedException("Custom timing is not supported yet."); } _timingOverride = value; } } /// /// Gets and sets the connector type. For TV only, ignored if TVFormat == TVFormat.None. /// public ConnectorType TVConnectorType { get; set; } /// /// Gets and sets the TV format. For TV only, otherwise set to TVFormat.None /// public TVFormat TVFormat { get; set; } /// /// Gets the Windows CCD target ID. Must be present only for non-NVIDIA adapter, for NVIDIA adapter this parameter is /// ignored. /// public uint WindowsCCDTargetId { get; } /// /// Checks for equality with a PathTargetInfo instance /// /// The PathTargetInfo object to check with /// true if both objects are equal, otherwise false public bool Equals(PathTargetInfo other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return _timingOverride == other._timingOverride && Rotation == other.Rotation && Scaling == other.Scaling && RefreshRateInMillihertz == other.RefreshRateInMillihertz && (TVFormat == TVFormat.None || TVConnectorType == other.TVConnectorType) && TVFormat == other.TVFormat && DisplayDevice.Equals(other.DisplayDevice) && IsInterlaced == other.IsInterlaced && IsClonePrimary == other.IsClonePrimary && IsClonePanAndScanTarget == other.IsClonePanAndScanTarget && DisableVirtualModeSupport == other.DisableVirtualModeSupport && IsPreferredUnscaledTarget == other.IsPreferredUnscaledTarget; } /// /// Checks for equality between two objects of same type /// /// The first object /// The second object /// true, if both objects are equal, otherwise false public static bool operator ==(PathTargetInfo left, PathTargetInfo right) { return right?.Equals(left) ?? ReferenceEquals(left, null); } /// /// Checks for inequality between two objects of same type /// /// The first object /// The second object /// true, if both objects are not equal, otherwise false public static bool operator !=(PathTargetInfo left, PathTargetInfo right) { return !(left == right); } /// public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((PathTargetInfo) obj); } /// public override int GetHashCode() { unchecked { var hashCode = (int) _timingOverride; hashCode = (hashCode * 397) ^ (int) Rotation; hashCode = (hashCode * 397) ^ (int) Scaling; hashCode = (hashCode * 397) ^ (int) RefreshRateInMillihertz; hashCode = (hashCode * 397) ^ (int) TVFormat; hashCode = (hashCode * 397) ^ (TVFormat != TVFormat.None ? (int) TVConnectorType : 0); hashCode = (hashCode * 397) ^ (DisplayDevice?.GetHashCode() ?? 0); hashCode = (hashCode * 397) ^ IsInterlaced.GetHashCode(); hashCode = (hashCode * 397) ^ IsClonePrimary.GetHashCode(); hashCode = (hashCode * 397) ^ IsClonePanAndScanTarget.GetHashCode(); hashCode = (hashCode * 397) ^ DisableVirtualModeSupport.GetHashCode(); hashCode = (hashCode * 397) ^ IsPreferredUnscaledTarget.GetHashCode(); return hashCode; } } /// public override string ToString() { var strs = new List { DisplayDevice.ToString() }; if (RefreshRateInMillihertz > 0) { strs.Add($"@ {RefreshRateInMillihertz / 1000}hz"); } if (TVFormat != TVFormat.None) { strs.Add($"- TV {TVFormat}"); } strs.Add(IsInterlaced ? "Interlaced" : "Progressive"); if (Rotation != Rotate.Degree0) { strs.Add($"- Rotation: {Rotation}"); } return string.Join(" ", strs); } /// /// Creates and fills a PathAdvancedTargetInfo object /// /// The newly created PathAdvancedTargetInfo object public PathAdvancedTargetInfo GetPathAdvancedTargetInfo() { if (TVFormat == TVFormat.None) { return new PathAdvancedTargetInfo(Rotation, Scaling, RefreshRateInMillihertz, TimingOverride, IsInterlaced, IsClonePrimary, IsClonePanAndScanTarget, DisableVirtualModeSupport, IsPreferredUnscaledTarget); } return new PathAdvancedTargetInfo(Rotation, Scaling, TVFormat, TVConnectorType, RefreshRateInMillihertz, TimingOverride, IsInterlaced, IsClonePrimary, IsClonePanAndScanTarget, DisableVirtualModeSupport, IsPreferredUnscaledTarget); } /// /// Creates and fills a PathTargetInfoV1 object /// /// The newly created PathTargetInfoV1 object public PathTargetInfoV1 GetPathTargetInfoV1() { var pathAdvancedTargetInfo = GetPathAdvancedTargetInfo(); return new PathTargetInfoV1(DisplayDevice.DisplayId, pathAdvancedTargetInfo); } /// /// Creates and fills a PathTargetInfoV2 object /// /// The newly created PathTargetInfoV2 object public PathTargetInfoV2 GetPathTargetInfoV2() { var pathAdvancedTargetInfo = GetPathAdvancedTargetInfo(); return new PathTargetInfoV2(DisplayDevice.DisplayId, WindowsCCDTargetId, pathAdvancedTargetInfo); } } }