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);
}
}
}