using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using NvAPIWrapper.Native.Attributes; using NvAPIWrapper.Native.General.Structures; using NvAPIWrapper.Native.Helpers; using NvAPIWrapper.Native.Interfaces; using NvAPIWrapper.Native.Interfaces.Mosaic; namespace NvAPIWrapper.Native.Mosaic.Structures { /// /// Holds information about a grid topology /// [StructLayout(LayoutKind.Sequential, Pack = 8)] [StructureVersion(1)] public struct GridTopologyV1 : IGridTopology, IInitializable, IEquatable { /// /// Maximum number of displays in a topology /// public const int MaxDisplays = 64; internal StructureVersion _Version; internal readonly uint _Rows; internal readonly uint _Columns; internal readonly uint _DisplayCount; internal uint _RawReserved; [MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxDisplays)] internal readonly GridTopologyDisplayV1[] _Displays; internal readonly DisplaySettingsV1 _DisplaySettings; /// /// Creates a new GridTopologyV1 /// /// Number of rows /// Number of columns /// Topology displays; Displays are done as [(row * columns) + column] /// Display settings /// /// When enabling and doing the modeset, do we switch to the /// bezel-corrected resolution /// /// Enable as immersive gaming instead of Mosaic SLI (for Quadro-boards only) /// /// Enable as Base Mosaic (Panoramic) instead of Mosaic SLI (for NVS and Quadro-boards /// only) /// /// /// If necessary, reloading the driver is permitted (for Vista and above only). Will not /// be persisted. /// /// /// Enable SLI acceleration on the primary display while in single-wide mode (For /// Immersive Gaming only). Will not be persisted. /// /// Total number of topology displays is below or equal to zero /// Number of displays doesn't match the arrangement // ReSharper disable once TooManyDependencies public GridTopologyV1( int rows, int columns, GridTopologyDisplayV1[] displays, DisplaySettingsV1 displaySettings, bool applyWithBezelCorrectedResolution, bool immersiveGaming, bool baseMosaicPanoramic, bool driverReloadAllowed, bool acceleratePrimaryDisplay) { if (rows * columns <= 0) { throw new ArgumentOutOfRangeException($"{nameof(rows)}, {nameof(columns)}", "Invalid display arrangement."); } if (displays.Length > MaxDisplays) { throw new ArgumentException("Too many displays."); } if (displays.Length != rows * columns) { throw new ArgumentException("Number of displays should match the arrangement.", nameof(displays)); } this = typeof(GridTopologyV1).Instantiate(); _Rows = (uint) rows; _Columns = (uint) columns; _DisplayCount = (uint) displays.Length; _Displays = displays; _DisplaySettings = displaySettings; ApplyWithBezelCorrectedResolution = applyWithBezelCorrectedResolution; ImmersiveGaming = immersiveGaming; BaseMosaicPanoramic = baseMosaicPanoramic; DriverReloadAllowed = driverReloadAllowed; AcceleratePrimaryDisplay = acceleratePrimaryDisplay; Array.Resize(ref _Displays, MaxDisplays); } /// public bool Equals(GridTopologyV1 other) { return _Rows == other._Rows && _Columns == other._Columns && _DisplayCount == other._DisplayCount && _RawReserved == other._RawReserved && _Displays.SequenceEqual(other._Displays) && _DisplaySettings.Equals(other._DisplaySettings); } /// public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } return obj is GridTopologyV1 v1 && Equals(v1); } /// public override int GetHashCode() { unchecked { var hashCode = (int) _Rows; hashCode = (hashCode * 397) ^ (int) _Columns; hashCode = (hashCode * 397) ^ (int) _DisplayCount; // ReSharper disable once NonReadonlyMemberInGetHashCode hashCode = (hashCode * 397) ^ (int) _RawReserved; hashCode = (hashCode * 397) ^ (_Displays?.GetHashCode() ?? 0); hashCode = (hashCode * 397) ^ _DisplaySettings.GetHashCode(); return hashCode; } } /// public int Rows { get => (int) _Rows; } /// public int Columns { get => (int) _Columns; } /// public IEnumerable Displays { get => _Displays.Take((int) _DisplayCount).Cast(); } /// public DisplaySettingsV1 DisplaySettings { get => _DisplaySettings; } /// public bool ApplyWithBezelCorrectedResolution { get => _RawReserved.GetBit(0); private set => _RawReserved = _RawReserved.SetBit(0, value); } /// public bool ImmersiveGaming { get => _RawReserved.GetBit(1); private set => _RawReserved = _RawReserved.SetBit(1, value); } /// public bool BaseMosaicPanoramic { get => _RawReserved.GetBit(2); private set => _RawReserved = _RawReserved.SetBit(2, value); } /// public bool DriverReloadAllowed { get => _RawReserved.GetBit(3); private set => _RawReserved = _RawReserved.SetBit(3, value); } /// public bool AcceleratePrimaryDisplay { get => _RawReserved.GetBit(4); private set => _RawReserved = _RawReserved.SetBit(4, value); } } }