using System; using System.Linq; using NvAPIWrapper.Native; using NvAPIWrapper.Native.Display.Structures; using NvAPIWrapper.Native.Exceptions; using NvAPIWrapper.Native.General; using NvAPIWrapper.Native.Interfaces.Mosaic; using NvAPIWrapper.Native.Mosaic; using NvAPIWrapper.Native.Mosaic.Structures; namespace NvAPIWrapper.Mosaic { /// /// Represents a mosaic topology /// [Obsolete("Using Mosaic API Phase 1, please consider using TopologyGrid class on newer drivers", false)] public class Topology : IEquatable { /// /// Creates a new Topology /// /// Mosaic displays resolution /// Mosaic displays frequency /// Topology arrangement /// Mosaic overlap public Topology( Resolution resolution, int frequency, Native.Mosaic.Topology topology, Overlap overlap) { Resolution = resolution; Frequency = frequency; FrequencyInMillihertz = (uint) (Frequency * 1000); TopologyMode = topology; Overlap = overlap; } /// /// Creates a new Topology /// /// >Mosaic displays resolution /// Mosaic frequency /// Mosaic frequency x 1000 /// Topology arrangement /// Mosaic overlap public Topology( Resolution resolution, int frequency, uint frequencyInMillihertz, Native.Mosaic.Topology topology, Overlap overlap) : this(resolution, frequency, topology, overlap) { FrequencyInMillihertz = frequencyInMillihertz; } /// /// Gets the mosaic displays frequency /// public int Frequency { get; } /// /// Gets the mosaic displays frequency x 1000 (Millihertz) /// public uint FrequencyInMillihertz { get; } /// /// Gets the topology overlap /// public Overlap Overlap { get; } /// /// Gets the mosaic displays resolution /// public Resolution Resolution { get; } /// /// Gets the topology arrangement /// public Native.Mosaic.Topology TopologyMode { get; } /// public bool Equals(Topology other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return Resolution.Equals(other.Resolution) && Frequency == other.Frequency && FrequencyInMillihertz == other.FrequencyInMillihertz && TopologyMode == other.TopologyMode && Overlap.Equals(other.Overlap); } /// /// Disables the current topology /// public static void DisableCurrent() { MosaicApi.EnableCurrentTopology(false); } /// /// Enables the current topology /// public static void EnableCurrent() { MosaicApi.EnableCurrentTopology(true); } /// /// Returns the current topology settings /// /// The current Topology object public static Topology GetCurrentTopology() { TopologyBrief brief; IDisplaySettings displaySettings; int overlapX; int overlapY; MosaicApi.GetCurrentTopology(out brief, out displaySettings, out overlapX, out overlapY); return new Topology( new Resolution(displaySettings.Width, displaySettings.Height, displaySettings.BitsPerPixel), displaySettings.Frequency, displaySettings.FrequencyInMillihertz, brief.Topology, new Overlap(overlapX, overlapY)); } /// /// Retrieves all the supported topology modes that are now possible to apply /// /// The type of the topology mode to limit quary /// An array of Topology modes public static Native.Mosaic.Topology[] GetSupportedTopologyModes(TopologyType type = TopologyType.All) { return MosaicApi.GetSupportedTopologiesInfo(type) .TopologyBriefs.Where(topologyBrief => topologyBrief.IsPossible) .Select(topologyBrief => topologyBrief.Topology) .ToArray(); } /// /// Retrieves all the supported display settings /// /// The type of the topology mode to limit quary /// An array of IDisplaySettings implamented objects public static IDisplaySettings[] GetSupportedTopologySettings(TopologyType type = TopologyType.All) { return MosaicApi.GetSupportedTopologiesInfo(type).DisplaySettings.ToArray(); } /// /// Indicates if the current topology is now active /// /// true if the current topology is now enable, otherwise false public static bool IsCurrentTopologyEnabled() { TopologyBrief brief; IDisplaySettings displaySettings; int overlapX; int overlapY; MosaicApi.GetCurrentTopology(out brief, out displaySettings, out overlapX, out overlapY); return brief.IsEnable; } /// /// Indicates if the current topology is possible to apply /// /// true if the current topology is possible to apply, otherwise false public static bool IsCurrentTopologyPossible() { TopologyBrief brief; IDisplaySettings displaySettings; int overlapX; int overlapY; MosaicApi.GetCurrentTopology(out brief, out displaySettings, out overlapX, out overlapY); return brief.IsPossible; } /// /// 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 ==(Topology left, Topology 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 !=(Topology left, Topology 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((Topology) obj); } /// public override int GetHashCode() { unchecked { var hashCode = Resolution.GetHashCode(); hashCode = (hashCode * 397) ^ Frequency; hashCode = (hashCode * 397) ^ (int) FrequencyInMillihertz; hashCode = (hashCode * 397) ^ (int) TopologyMode; hashCode = (hashCode * 397) ^ Overlap.GetHashCode(); return hashCode; } } /// /// Retrieves topology details /// /// An array of TopologyDetails public TopologyDetails[] GetDetails() { var brief = GetTopologyBrief(); return MosaicApi.GetTopologyGroup(brief) .TopologyDetails.Select(detail => new TopologyDetails(detail)) .ToArray(); } /// /// Creates and fills a DisplaySettingsV1 object /// /// The newly created DisplaySettingsV1 object public DisplaySettingsV1 GetDisplaySettingsV1() { return new DisplaySettingsV1(Resolution.Width, Resolution.Height, Resolution.ColorDepth, Frequency); } /// /// Creates and fills a DisplaySettingsV2 object /// /// The newly created DisplaySettingsV2 object public DisplaySettingsV2 GetDisplaySettingsV2() { return new DisplaySettingsV2(Resolution.Width, Resolution.Height, Resolution.ColorDepth, Frequency, FrequencyInMillihertz); } /// /// Retrieve the topology overlap limits /// /// public OverlapLimit GetOverlapLimits() { int minX; int maxX; int minY; int maxY; var brief = GetTopologyBrief(); var displaySettingsV2 = GetDisplaySettingsV2(); try { MosaicApi.GetOverlapLimits(brief, displaySettingsV2, out minX, out maxX, out minY, out maxY); return new OverlapLimit(minX, maxX, minY, maxY); } catch (NVIDIAApiException ex) { if (ex.Status != Status.IncompatibleStructureVersion) { throw; } } catch (NVIDIANotSupportedException) { // ignore } var displaySettingsV1 = GetDisplaySettingsV1(); MosaicApi.GetOverlapLimits(brief, displaySettingsV1, out minX, out maxX, out minY, out maxY); return new OverlapLimit(minX, maxX, minY, maxY); } /// /// Creates and fills a TopologyBrief object /// /// The newly created TopologyBrief object public TopologyBrief GetTopologyBrief() { return new TopologyBrief(TopologyMode); } /// /// Sets this topology as the current topology /// /// if true, will apply the topology right now public void SetAsCurrentTopology(bool apply = false) { var brief = GetTopologyBrief(); var displaySettingsV2 = GetDisplaySettingsV2(); try { MosaicApi.SetCurrentTopology(brief, displaySettingsV2, Overlap.HorizontalOverlap, Overlap.VerticalOverlap, apply); } catch (NVIDIAApiException ex) { if (ex.Status != Status.IncompatibleStructureVersion) { throw; } } catch (NVIDIANotSupportedException) { // ignore } var displaySettingsV1 = GetDisplaySettingsV1(); MosaicApi.SetCurrentTopology(brief, displaySettingsV1, Overlap.HorizontalOverlap, Overlap.VerticalOverlap, apply); } } }