Experimental GPU overclock

This commit is contained in:
Serge
2023-05-06 14:40:52 +02:00
parent 8e1099545a
commit c61f4d1608
497 changed files with 46937 additions and 232 deletions

View File

@@ -0,0 +1,373 @@
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
{
/// <summary>
/// Represents a mosaic grid topology
/// </summary>
public class GridTopology : IEquatable<GridTopology>
{
/// <summary>
/// Creates a new GridTopology
/// </summary>
/// <param name="rows">Mosaic rows</param>
/// <param name="columns">Mosaic columns</param>
/// <param name="displays">Topology displays</param>
public GridTopology(int rows, int columns, GridTopologyDisplay[] displays)
{
SetDisplays(rows, columns, displays);
var possibleDisplaySettings = GetPossibleDisplaySettings();
if (possibleDisplaySettings.Any())
{
SetDisplaySettings(
possibleDisplaySettings.OrderByDescending(
settings => (long) settings.Width *
settings.Height *
settings.BitsPerPixel *
settings.Frequency)
.First());
}
}
/// <summary>
/// Creates a new GridTopology
/// </summary>
/// <param name="gridTopology">A IGridTopology implamented object</param>
public GridTopology(IGridTopology gridTopology)
{
Rows = gridTopology.Rows;
Columns = gridTopology.Columns;
Displays = gridTopology.Displays.Select(display => new GridTopologyDisplay(display)).ToArray();
SetDisplaySettings(gridTopology.DisplaySettings);
ApplyWithBezelCorrectedResolution = gridTopology.ApplyWithBezelCorrectedResolution;
ImmersiveGaming = gridTopology.ImmersiveGaming;
BaseMosaicPanoramic = gridTopology.BaseMosaicPanoramic;
DriverReloadAllowed = gridTopology.DriverReloadAllowed;
AcceleratePrimaryDisplay = gridTopology.AcceleratePrimaryDisplay;
}
/// <summary>
/// Gets or sets a boolean value enabling SLI acceleration on the primary display while in single-wide mode (For
/// Immersive Gaming only).
/// </summary>
public bool AcceleratePrimaryDisplay { get; set; }
/// <summary>
/// Gets or sets a boolean value forcing to the bezel-corrected resolution when enabling and doing the modeset
/// </summary>
public bool ApplyWithBezelCorrectedResolution { get; set; }
/// <summary>
/// Gets or sets a boolean value enabling the Base Mosaic (Panoramic) instead of Mosaic SLI (for NVS and Quadro-boards
/// only)
/// </summary>
public bool BaseMosaicPanoramic { get; set; }
/// <summary>
/// Gets the mosaic columns
/// </summary>
public int Columns { get; private set; }
/// <summary>
/// Gets topology displays
/// </summary>
public GridTopologyDisplay[] Displays { get; private set; }
/// <summary>
/// Gets or sets a boolean value allowing the API to, if necessary, realod the driver (for Vista and above only). Will
/// not be persisted. Value undefined on get.
/// </summary>
public bool DriverReloadAllowed { get; set; }
/// <summary>
/// Gets the topology Frequency
/// </summary>
public int Frequency { get; private set; }
/// <summary>
/// Gets or sets a boolean value enabling as immersive gaming instead of Mosaic SLI (for Quadro-boards only)
/// </summary>
public bool ImmersiveGaming { get; set; }
/// <summary>
/// Gets the topology resolution
/// </summary>
public Resolution Resolution { get; private set; }
/// <summary>
/// Gets the mosaic rows
/// </summary>
public int Rows { get; private set; }
/// <inheritdoc />
public bool Equals(GridTopology other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return Resolution.Equals(other.Resolution) &&
Frequency == other.Frequency &&
Rows == other.Rows &&
Columns == other.Columns &&
Displays.SequenceEqual(other.Displays) &&
ApplyWithBezelCorrectedResolution == other.ApplyWithBezelCorrectedResolution &&
ImmersiveGaming == other.ImmersiveGaming &&
BaseMosaicPanoramic == other.BaseMosaicPanoramic &&
AcceleratePrimaryDisplay == other.AcceleratePrimaryDisplay;
}
/// <summary>
/// Retrieves a list of currently active mosaic grid topologies
/// </summary>
/// <returns>An array of GridTopology objects</returns>
public static GridTopology[] GetGridTopologies()
{
return MosaicApi.EnumDisplayGrids().Select(topology => new GridTopology(topology)).ToArray();
}
/// <summary>
/// Checks for equality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are equal, otherwise false</returns>
public static bool operator ==(GridTopology left, GridTopology right)
{
return right?.Equals(left) ?? ReferenceEquals(left, null);
}
/// <summary>
/// Checks for inequality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are not equal, otherwise false</returns>
public static bool operator !=(GridTopology left, GridTopology right)
{
return !(left == right);
}
/// <summary>
/// Applies the requested grid topologies
/// </summary>
/// <param name="grids">An array of grid topologies to apply</param>
/// <param name="flags">SetDisplayTopologyFlag flag</param>
public static void SetGridTopologies(
GridTopology[] grids,
SetDisplayTopologyFlag flags = SetDisplayTopologyFlag.NoFlag)
{
var gridTopologyV2 = grids.Select(grid => grid.GetGridTopologyV2()).Cast<IGridTopology>().ToArray();
try
{
MosaicApi.SetDisplayGrids(gridTopologyV2, flags);
}
catch (NVIDIAApiException ex)
{
if (ex.Status != Status.IncompatibleStructureVersion)
{
throw;
}
}
catch (NVIDIANotSupportedException)
{
// ignore
}
var gridTopologyV1 = grids.Select(grid => grid.GetGridTopologyV1()).Cast<IGridTopology>().ToArray();
MosaicApi.SetDisplayGrids(gridTopologyV1, flags);
}
/// <summary>
/// Validates a list of grid topologies
/// </summary>
/// <param name="grids">An array of grid topologies to validate</param>
/// <param name="flags">SetDisplayTopologyFlag flag</param>
/// <returns>An array of DisplayTopologyStatus object containing the result of the validation</returns>
public static DisplayTopologyStatus[] ValidateGridTopologies(
GridTopology[] grids,
SetDisplayTopologyFlag flags = SetDisplayTopologyFlag.AllowInvalid)
{
var gridTopologyV2 = grids.Select(grid => grid.GetGridTopologyV2()).Cast<IGridTopology>().ToArray();
try
{
return MosaicApi.ValidateDisplayGrids(gridTopologyV2, flags);
}
catch (NVIDIAApiException ex)
{
if (ex.Status != Status.IncompatibleStructureVersion)
{
throw;
}
}
catch (NVIDIANotSupportedException)
{
// ignore
}
var gridTopologyV1 = grids.Select(grid => grid.GetGridTopologyV1()).Cast<IGridTopology>().ToArray();
return MosaicApi.ValidateDisplayGrids(gridTopologyV1, flags);
}
/// <inheritdoc />
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((GridTopology) obj);
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
var hashCode = Resolution.GetHashCode();
hashCode = (hashCode * 397) ^ Frequency;
hashCode = (hashCode * 397) ^ Rows;
hashCode = (hashCode * 397) ^ Columns;
hashCode = (hashCode * 397) ^ (Displays?.GetHashCode() ?? 0);
hashCode = (hashCode * 397) ^ ApplyWithBezelCorrectedResolution.GetHashCode();
hashCode = (hashCode * 397) ^ ImmersiveGaming.GetHashCode();
hashCode = (hashCode * 397) ^ BaseMosaicPanoramic.GetHashCode();
hashCode = (hashCode * 397) ^ AcceleratePrimaryDisplay.GetHashCode();
return hashCode;
}
}
/// <summary>
/// Creates and fills a DisplaySettingsV1 object
/// </summary>
/// <returns>The newly created DisplaySettingsV1 object</returns>
public DisplaySettingsV1 GetDisplaySettingsV1()
{
return new DisplaySettingsV1(Resolution.Width, Resolution.Height, Resolution.ColorDepth, Frequency);
}
/// <summary>
/// Creates and fills a GridTopologyV1 object
/// </summary>
/// <returns>The newly created GridTopologyV1 object</returns>
public GridTopologyV1 GetGridTopologyV1()
{
var displaySettings = GetDisplaySettingsV1();
return new GridTopologyV1(Rows, Columns,
Displays.Select(display => display.GetGridTopologyDisplayV1()).ToArray(), displaySettings,
ApplyWithBezelCorrectedResolution, ImmersiveGaming, BaseMosaicPanoramic, DriverReloadAllowed,
AcceleratePrimaryDisplay);
}
/// <summary>
/// Creates and fills a GridTopologyV2 object
/// </summary>
/// <returns>The newly created GridTopologyV2 object</returns>
public GridTopologyV2 GetGridTopologyV2()
{
var displaySettings = GetDisplaySettingsV1();
return new GridTopologyV2(Rows, Columns,
Displays.Select(display => display.GetGridTopologyDisplayV2()).ToArray(), displaySettings,
ApplyWithBezelCorrectedResolution, ImmersiveGaming, BaseMosaicPanoramic, DriverReloadAllowed,
AcceleratePrimaryDisplay,
Displays.Any(display => display.PixelShiftType != PixelShiftType.NoPixelShift));
}
/// <summary>
/// Retrieves a list of possible display settings for this topology
/// </summary>
/// <returns>An array of IDisplaySettings implamented objects</returns>
public IDisplaySettings[] GetPossibleDisplaySettings()
{
var gridTopologyV2 = GetGridTopologyV2();
try
{
return MosaicApi.EnumDisplayModes(gridTopologyV2);
}
catch (NVIDIAApiException ex)
{
if (ex.Status != Status.IncompatibleStructureVersion)
{
throw;
}
}
catch (NVIDIANotSupportedException)
{
// ignore
}
var gridTopologyV1 = GetGridTopologyV1();
return MosaicApi.EnumDisplayModes(gridTopologyV1);
}
/// <summary>
/// Changes topology arrangement and displays
/// </summary>
/// <param name="rows">Mosaic rows</param>
/// <param name="columns">Mosaic columns</param>
/// <param name="displays">Topology displays</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid display arrangement.</exception>
/// <exception cref="ArgumentException">Number of displays should match the arrangement.</exception>
public void SetDisplays(int rows, int columns, GridTopologyDisplay[] displays)
{
if (rows * columns <= 0)
{
throw new ArgumentOutOfRangeException($"{nameof(rows)}, {nameof(columns)}",
"Invalid display arrangement.");
}
if (displays.Length != rows * columns)
{
throw new ArgumentException("Number of displays should match the arrangement.", nameof(displays));
}
Rows = rows;
Columns = columns;
Displays = displays;
}
/// <summary>
/// Changes display settings for the topology
/// </summary>
/// <param name="displaySettings">Display settings to use</param>
public void SetDisplaySettings(IDisplaySettings displaySettings)
{
Resolution = new Resolution(displaySettings.Width, displaySettings.Height, displaySettings.BitsPerPixel);
Frequency = displaySettings.Frequency;
}
}
}

View File

@@ -0,0 +1,192 @@
using System;
using NvAPIWrapper.Display;
using NvAPIWrapper.Native.Display;
using NvAPIWrapper.Native.Interfaces.Mosaic;
using NvAPIWrapper.Native.Mosaic;
using NvAPIWrapper.Native.Mosaic.Structures;
namespace NvAPIWrapper.Mosaic
{
/// <summary>
/// Represents a display in a mosaic grid topology
/// </summary>
public class GridTopologyDisplay : IEquatable<GridTopologyDisplay>
{
/// <summary>
/// Creates a mew GridTopologyDisplay
/// </summary>
/// <param name="displayId">Corresponding display identification</param>
/// <param name="overlap">The overlap values</param>
/// <param name="rotation">The display rotation</param>
/// <param name="cloneGroup">The display clone group</param>
/// <param name="pixelShiftType">The display pixel shift type</param>
public GridTopologyDisplay(
uint displayId,
Overlap overlap = default(Overlap),
Rotate rotation = Rotate.Degree0,
uint cloneGroup = 0,
PixelShiftType pixelShiftType = PixelShiftType.NoPixelShift)
: this(new DisplayDevice(displayId), overlap, rotation, cloneGroup, pixelShiftType)
{
}
/// <summary>
/// Creates a mew GridTopologyDisplay
/// </summary>
/// <param name="display">Corresponding display device</param>
/// <param name="overlap">The overlap values</param>
/// <param name="rotation">The display rotation</param>
/// <param name="cloneGroup">The display clone group</param>
/// <param name="pixelShiftType">The display pixel shift type</param>
public GridTopologyDisplay(
DisplayDevice display,
Overlap overlap = default(Overlap),
Rotate rotation = Rotate.Degree0,
uint cloneGroup = 0,
PixelShiftType pixelShiftType = PixelShiftType.NoPixelShift)
{
DisplayDevice = display;
Overlap = overlap;
Rotation = rotation;
CloneGroup = cloneGroup;
PixelShiftType = pixelShiftType;
}
/// <summary>
/// Creates a mew GridTopologyDisplay
/// </summary>
/// <param name="gridTopologyDisplay">IGridTopologyDisplay implamented object</param>
public GridTopologyDisplay(IGridTopologyDisplay gridTopologyDisplay)
: this(
new DisplayDevice(gridTopologyDisplay.DisplayId),
new Overlap(gridTopologyDisplay.OverlapX, gridTopologyDisplay.OverlapY),
gridTopologyDisplay.Rotation, gridTopologyDisplay.CloneGroup, gridTopologyDisplay.PixelShiftType)
{
}
/// <summary>
/// Gets the clone group identification; Reserved, must be 0
/// </summary>
public uint CloneGroup { get; set; }
/// <summary>
/// Gets the corresponding DisplayDevice
/// </summary>
public DisplayDevice DisplayDevice { get; }
/// <summary>
/// Gets the overlap values
/// </summary>
public Overlap Overlap { get; set; }
/// <summary>
/// Gets the type of display pixel shift
/// </summary>
public PixelShiftType PixelShiftType { get; set; }
/// <summary>
/// Gets the rotation of the display
/// </summary>
public Rotate Rotation { get; set; }
/// <inheritdoc />
public bool Equals(GridTopologyDisplay other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return DisplayDevice.Equals(other.DisplayDevice) &&
Overlap.Equals(other.Overlap) &&
Rotation == other.Rotation &&
CloneGroup == other.CloneGroup &&
PixelShiftType == other.PixelShiftType;
}
/// <summary>
/// Checks for equality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are equal, otherwise false</returns>
public static bool operator ==(GridTopologyDisplay left, GridTopologyDisplay right)
{
return right?.Equals(left) ?? ReferenceEquals(left, null);
}
/// <summary>
/// Checks for inequality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are not equal, otherwise false</returns>
public static bool operator !=(GridTopologyDisplay left, GridTopologyDisplay right)
{
return !(left == right);
}
/// <inheritdoc />
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((GridTopologyDisplay) obj);
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
var hashCode = DisplayDevice?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ Overlap.GetHashCode();
hashCode = (hashCode * 397) ^ (int) Rotation;
hashCode = (hashCode * 397) ^ (int) CloneGroup;
hashCode = (hashCode * 397) ^ (int) PixelShiftType;
return hashCode;
}
}
/// <summary>
/// Creates and fills a GridTopologyDisplayV1 object
/// </summary>
/// <returns>The newly created GridTopologyDisplayV1 object</returns>
public GridTopologyDisplayV1 GetGridTopologyDisplayV1()
{
return new GridTopologyDisplayV1(DisplayDevice.DisplayId, Overlap.HorizontalOverlap,
Overlap.VerticalOverlap,
Rotation, CloneGroup);
}
/// <summary>
/// Creates and fills a GridTopologyDisplayV2 object
/// </summary>
/// <returns>The newly created GridTopologyDisplayV2 object</returns>
public GridTopologyDisplayV2 GetGridTopologyDisplayV2()
{
return new GridTopologyDisplayV2(DisplayDevice.DisplayId, Overlap.HorizontalOverlap,
Overlap.VerticalOverlap,
Rotation, CloneGroup, PixelShiftType);
}
}
}

View File

@@ -0,0 +1,85 @@
using System;
namespace NvAPIWrapper.Mosaic
{
/// <summary>
/// Holds mosaic overlap values
/// </summary>
public struct Overlap : IEquatable<Overlap>
{
/// <summary>
/// Creates a new Overlap
/// </summary>
/// <param name="overlapX">Horizontal overlap</param>
/// <param name="overlapY">Vertical overlap</param>
public Overlap(int overlapX, int overlapY)
{
HorizontalOverlap = overlapX;
VerticalOverlap = overlapY;
}
/// <summary>
/// Gets or sets horizontal overlap (OverlapX)
/// </summary>
public int HorizontalOverlap { get; }
/// <summary>
/// Gets or sets vertical overlap (OverlapY)
/// </summary>
public int VerticalOverlap { get; }
/// <inheritdoc />
public bool Equals(Overlap other)
{
return HorizontalOverlap == other.HorizontalOverlap && VerticalOverlap == other.VerticalOverlap;
}
/// <inheritdoc />
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
return obj is Overlap && Equals((Overlap) obj);
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
return (HorizontalOverlap * 397) ^ VerticalOverlap;
}
}
/// <summary>
/// Checks for equality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are equal, otherwise false</returns>
public static bool operator ==(Overlap left, Overlap right)
{
return left.Equals(right);
}
/// <summary>
/// Checks for inequality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are not equal, otherwise false</returns>
public static bool operator !=(Overlap left, Overlap right)
{
return !left.Equals(right);
}
/// <inheritdoc />
public override string ToString()
{
return $"({HorizontalOverlap}, {VerticalOverlap})";
}
}
}

View File

@@ -0,0 +1,131 @@
using System;
namespace NvAPIWrapper.Mosaic
{
/// <summary>
/// Holds maximum and minimum possible values for overlaps
/// </summary>
public struct OverlapLimit : IEquatable<OverlapLimit>
{
internal OverlapLimit(int minOverlapX, int maxOverlapX, int minOverlapY, int maxOverlapY)
{
MinimumHorizontalOverlap = minOverlapX;
MaximumHorizontalOverlap = maxOverlapX;
MinimumVerticalOverlap = minOverlapY;
MaximumVerticalOverlap = maxOverlapY;
}
/// <summary>
/// Minimum value for horizontal overlap (OverlapX) or maximum value of horizontal gap
/// </summary>
public int MinimumHorizontalOverlap { get; }
/// <summary>
/// Maximum value for horizontal overlap (OverlapX)
/// </summary>
public int MaximumHorizontalOverlap { get; }
/// <summary>
/// Minimum value for vertical overlap (OverlapY) or maximum value of vertical gap
/// </summary>
public int MinimumVerticalOverlap { get; }
/// <summary>
/// Maximum value for vertical overlap (OverlapY)
/// </summary>
public int MaximumVerticalOverlap { get; }
/// <inheritdoc />
public bool Equals(OverlapLimit other)
{
return MinimumHorizontalOverlap == other.MinimumHorizontalOverlap &&
MaximumHorizontalOverlap == other.MaximumHorizontalOverlap &&
MinimumVerticalOverlap == other.MinimumVerticalOverlap &&
MaximumVerticalOverlap == other.MaximumVerticalOverlap;
}
/// <inheritdoc />
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
return obj is OverlapLimit && Equals((OverlapLimit) obj);
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
var hashCode = MinimumHorizontalOverlap;
hashCode = (hashCode * 397) ^ MaximumHorizontalOverlap;
hashCode = (hashCode * 397) ^ MinimumVerticalOverlap;
hashCode = (hashCode * 397) ^ MaximumVerticalOverlap;
return hashCode;
}
}
/// <summary>
/// Checks for equality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are equal, otherwise false</returns>
public static bool operator ==(OverlapLimit left, OverlapLimit right)
{
return left.Equals(right);
}
/// <summary>
/// Checks for inequality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are not equal, otherwise false</returns>
public static bool operator !=(OverlapLimit left, OverlapLimit right)
{
return !left.Equals(right);
}
/// <inheritdoc />
public override string ToString()
{
return
$"[{MinimumHorizontalOverlap}, {MaximumHorizontalOverlap}], [{MinimumVerticalOverlap}, {MaximumVerticalOverlap}]";
}
/// <summary>
/// Checks to see if the value falls in to the acceptable horizontal overlap range
/// </summary>
/// <param name="overlapX">The horizontal overlap value</param>
/// <returns>true if the value falls into the range, otherwise false</returns>
public bool IsInHorizontalRange(int overlapX)
{
return overlapX >= MinimumHorizontalOverlap && overlapX <= MaximumHorizontalOverlap;
}
/// <summary>
/// Checks to see if the value falls in to the acceptable vertical overlap range
/// </summary>
/// <param name="overlapY">The vertical overlap value</param>
/// <returns>true if the value falls into the range, otherwise false</returns>
public bool IsInVerticalRange(int overlapY)
{
return overlapY >= MinimumVerticalOverlap && overlapY <= MaximumVerticalOverlap;
}
/// <summary>
/// Checks to see if the overlap values fall in to the acceptable overlap ranges
/// </summary>
/// <param name="overlap">The overlap values</param>
/// <returns>true if the values fall into the range, otherwise false</returns>
public bool IsInRange(Overlap overlap)
{
return IsInHorizontalRange(overlap.HorizontalOverlap) && IsInVerticalRange(overlap.VerticalOverlap);
}
}
}

View File

@@ -0,0 +1,361 @@
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
{
/// <summary>
/// Represents a mosaic topology
/// </summary>
[Obsolete("Using Mosaic API Phase 1, please consider using TopologyGrid class on newer drivers", false)]
public class Topology : IEquatable<Topology>
{
/// <summary>
/// Creates a new Topology
/// </summary>
/// <param name="resolution">Mosaic displays resolution</param>
/// <param name="frequency">Mosaic displays frequency</param>
/// <param name="topology">Topology arrangement</param>
/// <param name="overlap">Mosaic overlap</param>
public Topology(
Resolution resolution,
int frequency,
Native.Mosaic.Topology topology,
Overlap overlap)
{
Resolution = resolution;
Frequency = frequency;
FrequencyInMillihertz = (uint) (Frequency * 1000);
TopologyMode = topology;
Overlap = overlap;
}
/// <summary>
/// Creates a new Topology
/// </summary>
/// <param name="resolution">>Mosaic displays resolution</param>
/// <param name="frequency">Mosaic frequency</param>
/// <param name="frequencyInMillihertz">Mosaic frequency x 1000</param>
/// <param name="topology">Topology arrangement</param>
/// <param name="overlap">Mosaic overlap</param>
public Topology(
Resolution resolution,
int frequency,
uint frequencyInMillihertz,
Native.Mosaic.Topology topology,
Overlap overlap)
: this(resolution, frequency, topology, overlap)
{
FrequencyInMillihertz = frequencyInMillihertz;
}
/// <summary>
/// Gets the mosaic displays frequency
/// </summary>
public int Frequency { get; }
/// <summary>
/// Gets the mosaic displays frequency x 1000 (Millihertz)
/// </summary>
public uint FrequencyInMillihertz { get; }
/// <summary>
/// Gets the topology overlap
/// </summary>
public Overlap Overlap { get; }
/// <summary>
/// Gets the mosaic displays resolution
/// </summary>
public Resolution Resolution { get; }
/// <summary>
/// Gets the topology arrangement
/// </summary>
public Native.Mosaic.Topology TopologyMode { get; }
/// <inheritdoc />
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);
}
/// <summary>
/// Disables the current topology
/// </summary>
public static void DisableCurrent()
{
MosaicApi.EnableCurrentTopology(false);
}
/// <summary>
/// Enables the current topology
/// </summary>
public static void EnableCurrent()
{
MosaicApi.EnableCurrentTopology(true);
}
/// <summary>
/// Returns the current topology settings
/// </summary>
/// <returns>The current Topology object</returns>
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));
}
/// <summary>
/// Retrieves all the supported topology modes that are now possible to apply
/// </summary>
/// <param name="type">The type of the topology mode to limit quary</param>
/// <returns>An array of Topology modes</returns>
public static Native.Mosaic.Topology[] GetSupportedTopologyModes(TopologyType type = TopologyType.All)
{
return
MosaicApi.GetSupportedTopologiesInfo(type)
.TopologyBriefs.Where(topologyBrief => topologyBrief.IsPossible)
.Select(topologyBrief => topologyBrief.Topology)
.ToArray();
}
/// <summary>
/// Retrieves all the supported display settings
/// </summary>
/// <param name="type">The type of the topology mode to limit quary</param>
/// <returns>An array of IDisplaySettings implamented objects</returns>
public static IDisplaySettings[] GetSupportedTopologySettings(TopologyType type = TopologyType.All)
{
return MosaicApi.GetSupportedTopologiesInfo(type).DisplaySettings.ToArray();
}
/// <summary>
/// Indicates if the current topology is now active
/// </summary>
/// <returns>true if the current topology is now enable, otherwise false</returns>
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;
}
/// <summary>
/// Indicates if the current topology is possible to apply
/// </summary>
/// <returns>true if the current topology is possible to apply, otherwise false</returns>
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;
}
/// <summary>
/// Checks for equality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are equal, otherwise false</returns>
public static bool operator ==(Topology left, Topology right)
{
return right?.Equals(left) ?? ReferenceEquals(left, null);
}
/// <summary>
/// Checks for inequality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are not equal, otherwise false</returns>
public static bool operator !=(Topology left, Topology right)
{
return !(left == right);
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
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;
}
}
/// <summary>
/// Retrieves topology details
/// </summary>
/// <returns>An array of TopologyDetails</returns>
public TopologyDetails[] GetDetails()
{
var brief = GetTopologyBrief();
return
MosaicApi.GetTopologyGroup(brief)
.TopologyDetails.Select(detail => new TopologyDetails(detail))
.ToArray();
}
/// <summary>
/// Creates and fills a DisplaySettingsV1 object
/// </summary>
/// <returns>The newly created DisplaySettingsV1 object</returns>
public DisplaySettingsV1 GetDisplaySettingsV1()
{
return new DisplaySettingsV1(Resolution.Width, Resolution.Height, Resolution.ColorDepth, Frequency);
}
/// <summary>
/// Creates and fills a DisplaySettingsV2 object
/// </summary>
/// <returns>The newly created DisplaySettingsV2 object</returns>
public DisplaySettingsV2 GetDisplaySettingsV2()
{
return new DisplaySettingsV2(Resolution.Width, Resolution.Height, Resolution.ColorDepth, Frequency,
FrequencyInMillihertz);
}
/// <summary>
/// Retrieve the topology overlap limits
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// Creates and fills a TopologyBrief object
/// </summary>
/// <returns>The newly created TopologyBrief object</returns>
public TopologyBrief GetTopologyBrief()
{
return new TopologyBrief(TopologyMode);
}
/// <summary>
/// Sets this topology as the current topology
/// </summary>
/// <param name="apply">if true, will apply the topology right now</param>
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);
}
}
}

View File

@@ -0,0 +1,124 @@
using System;
using System.Linq;
using NvAPIWrapper.GPU;
using NvAPIWrapper.Native.Mosaic;
namespace NvAPIWrapper.Mosaic
{
/// <summary>
/// Holds extra information about a topology
/// </summary>
public class TopologyDetails : IEquatable<TopologyDetails>
{
internal TopologyDetails(Native.Mosaic.Structures.TopologyDetails details)
{
Rows = details.Rows;
Columns = details.Columns;
LogicalGPU = !details.LogicalGPUHandle.IsNull ? new LogicalGPU(details.LogicalGPUHandle) : null;
ValidityFlags = details.ValidityFlags;
Displays =
details.Layout.Select(cells => cells.Select(cell => new TopologyDisplay(cell)).ToArray()).ToArray();
}
/// <summary>
/// Gets the number of columns in the topology
/// </summary>
public int Columns { get; }
/// <summary>
/// Gets the list of topology displays
/// </summary>
public TopologyDisplay[][] Displays { get; }
/// <summary>
/// Gets the logical GPU in charge of controling the topology
/// </summary>
public LogicalGPU LogicalGPU { get; }
/// <summary>
/// Gets the number of rows in the topology
/// </summary>
public int Rows { get; }
/// <summary>
/// Gets the validity status of this topology
/// </summary>
public TopologyValidity ValidityFlags { get; }
/// <inheritdoc />
public bool Equals(TopologyDetails other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return Rows == other.Rows &&
Columns == other.Columns &&
LogicalGPU.Equals(other.LogicalGPU) &&
Displays.SequenceEqual(other.Displays);
}
/// <summary>
/// Checks for equality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are equal, otherwise false</returns>
public static bool operator ==(TopologyDetails left, TopologyDetails right)
{
return right?.Equals(left) ?? ReferenceEquals(left, null);
}
/// <summary>
/// Checks for inequality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are not equal, otherwise false</returns>
public static bool operator !=(TopologyDetails left, TopologyDetails right)
{
return !(left == right);
}
/// <inheritdoc />
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((TopologyDetails) obj);
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
var hashCode = Rows;
hashCode = (hashCode * 397) ^ Columns;
hashCode = (hashCode * 397) ^ (LogicalGPU != null ? LogicalGPU.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (Displays?.GetHashCode() ?? 0);
return hashCode;
}
}
}
}

View File

@@ -0,0 +1,107 @@
using System;
using NvAPIWrapper.GPU;
namespace NvAPIWrapper.Mosaic
{
/// <summary>
/// Holds information about a display in a topology
/// </summary>
public class TopologyDisplay : IEquatable<TopologyDisplay>
{
internal TopologyDisplay(Native.Mosaic.Structures.TopologyDetails.LayoutCell layoutCell)
{
PhysicalGPU = !layoutCell.PhysicalGPUHandle.IsNull ? new PhysicalGPU(layoutCell.PhysicalGPUHandle) : null;
Output = new GPUOutput(layoutCell.DisplayOutputId, PhysicalGPU);
Overlap = new Overlap(layoutCell.OverlapX, layoutCell.OverlapY);
}
/// <summary>
/// Gets the GPU output used for this display
/// </summary>
public GPUOutput Output { get; }
/// <summary>
/// Gets the display overlap values
/// </summary>
public Overlap Overlap { get; }
/// <summary>
/// Gets the corresponding physical GPU of this display
/// </summary>
public PhysicalGPU PhysicalGPU { get; }
/// <inheritdoc />
public bool Equals(TopologyDisplay other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return PhysicalGPU.Equals(other.PhysicalGPU) &&
Output.Equals(other.Output) &&
Overlap.Equals(other.Overlap);
}
/// <summary>
/// Checks for equality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are equal, otherwise false</returns>
public static bool operator ==(TopologyDisplay left, TopologyDisplay right)
{
return right?.Equals(left) ?? ReferenceEquals(left, null);
}
/// <summary>
/// Checks for inequality between two objects of same type
/// </summary>
/// <param name="left">The first object</param>
/// <param name="right">The second object</param>
/// <returns>true, if both objects are not equal, otherwise false</returns>
public static bool operator !=(TopologyDisplay left, TopologyDisplay right)
{
return !(left == right);
}
/// <inheritdoc />
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((TopologyDisplay) obj);
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
var hashCode = PhysicalGPU != null ? PhysicalGPU.GetHashCode() : 0;
hashCode = (hashCode * 397) ^ (Output != null ? Output.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ Overlap.GetHashCode();
return hashCode;
}
}
}
}