using System;
using System.Collections.Generic;
using System.Linq;
using NvAPIWrapper.GPU;
using NvAPIWrapper.Native;
using NvAPIWrapper.Native.Display;
using NvAPIWrapper.Native.Display.Structures;
using NvAPIWrapper.Native.Exceptions;
using NvAPIWrapper.Native.General;
using NvAPIWrapper.Native.GPU;
using NvAPIWrapper.Native.GPU.Structures;
using NvAPIWrapper.Native.Interfaces.Display;
using NvAPIWrapper.Native.Interfaces.GPU;
namespace NvAPIWrapper.Display
{
///
/// Represents an NVIDIA display device
///
public class DisplayDevice : IEquatable
{
///
/// Creates a new DisplayDevice
///
/// Display identification of the device
public DisplayDevice(uint displayId)
{
DisplayId = displayId;
var extraInformation = PhysicalGPU.GetDisplayDevices().FirstOrDefault(ids => ids.DisplayId == DisplayId);
if (extraInformation != null)
{
IsAvailable = true;
ScanOutInformation = new ScanOutInformation(this);
ConnectionType = extraInformation.ConnectionType;
IsDynamic = extraInformation.IsDynamic;
IsMultiStreamRootNode = extraInformation.IsMultiStreamRootNode;
IsActive = extraInformation.IsActive;
IsCluster = extraInformation.IsCluster;
IsOSVisible = extraInformation.IsOSVisible;
IsWFD = extraInformation.IsWFD;
IsConnected = extraInformation.IsConnected;
IsPhysicallyConnected = extraInformation.IsPhysicallyConnected;
}
}
///
/// Creates a new DisplayDevice
///
/// Display identification and attributes of the display device
public DisplayDevice(IDisplayIds displayIds)
{
IsAvailable = true;
DisplayId = displayIds.DisplayId;
ScanOutInformation = new ScanOutInformation(this);
ConnectionType = displayIds.ConnectionType;
IsDynamic = displayIds.IsDynamic;
IsMultiStreamRootNode = displayIds.IsMultiStreamRootNode;
IsActive = displayIds.IsActive;
IsCluster = displayIds.IsCluster;
IsOSVisible = displayIds.IsOSVisible;
IsWFD = displayIds.IsWFD;
IsConnected = displayIds.IsConnected;
IsPhysicallyConnected = displayIds.IsPhysicallyConnected;
}
///
/// Creates a new DisplayDevice
///
/// Display name of the display device
public DisplayDevice(string displayName) : this(DisplayApi.GetDisplayIdByDisplayName(displayName))
{
}
///
/// Gets the display device connection type
///
public MonitorConnectionType ConnectionType { get; }
///
/// Gets the current display color data
///
public ColorData CurrentColorData
{
get
{
var instances = new IColorData[]
{
new ColorDataV5(ColorDataCommand.Get),
new ColorDataV4(ColorDataCommand.Get),
new ColorDataV3(ColorDataCommand.Get),
new ColorDataV2(ColorDataCommand.Get),
new ColorDataV1(ColorDataCommand.Get)
};
var instance = DisplayApi.ColorControl(DisplayId, instances);
return new ColorData(instance);
}
}
///
/// Gets the current display device timing
///
public Timing CurrentTiming
{
get => DisplayApi.GetTiming(DisplayId, new TimingInput(TimingOverride.Current));
}
///
/// Gets the default display color data
///
public ColorData DefaultColorData
{
get
{
var instances = new IColorData[]
{
new ColorDataV5(ColorDataCommand.GetDefault),
new ColorDataV4(ColorDataCommand.GetDefault),
new ColorDataV3(ColorDataCommand.GetDefault),
new ColorDataV2(ColorDataCommand.GetDefault),
new ColorDataV1(ColorDataCommand.GetDefault)
};
var instance = DisplayApi.ColorControl(DisplayId, instances);
return new ColorData(instance);
}
}
///
/// Gets the NVIDIA display identification
///
public uint DisplayId { get; }
///
/// Gets the monitor Display port capabilities
///
public MonitorColorData[] DisplayPortColorCapabilities
{
get
{
if (ConnectionType != MonitorConnectionType.DisplayPort)
{
return null;
}
return DisplayApi.GetMonitorColorCapabilities(DisplayId);
}
}
///
/// Gets the display driver EDID specified HDR capabilities
///
public HDRCapabilitiesV1 DriverHDRCapabilities
{
get => DisplayApi.GetHDRCapabilities(DisplayId, true);
}
///
/// Gets the display currently effective HDR capabilities
///
public HDRCapabilitiesV1 EffectiveHDRCapabilities
{
get => DisplayApi.GetHDRCapabilities(DisplayId, false);
}
///
/// Gets the HDMI audio info-frame current information
///
public InfoFrameAudio? HDMIAudioFrameCurrentInformation
{
get
{
try
{
var infoFrame = new InfoFrameData(InfoFrameCommand.Get, InfoFrameDataType.AudioInformation);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
return infoFrame.AudioInformation;
}
catch (NVIDIAApiException e)
{
if (e.Status == Status.NotSupported)
{
return null;
}
throw;
}
}
}
///
/// Gets the HDMI audio info-frame default information
///
public InfoFrameAudio? HDMIAudioFrameDefaultInformation
{
get
{
try
{
var infoFrame = new InfoFrameData(InfoFrameCommand.GetDefault, InfoFrameDataType.AudioInformation);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
return infoFrame.AudioInformation;
}
catch (NVIDIAApiException e)
{
if (e.Status == Status.NotSupported)
{
return null;
}
throw;
}
}
}
///
/// Gets the HDMI audio info-frame override information
///
public InfoFrameAudio? HDMIAudioFrameOverrideInformation
{
get
{
try
{
var infoFrame = new InfoFrameData(InfoFrameCommand.GetOverride, InfoFrameDataType.AudioInformation);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
return infoFrame.AudioInformation;
}
catch (NVIDIAApiException e)
{
if (e.Status == Status.NotSupported)
{
return null;
}
throw;
}
}
}
///
/// Gets the HDMI audio info-frame property information
///
public InfoFrameProperty? HDMIAudioFramePropertyInformation
{
get
{
try
{
var infoFrame = new InfoFrameData(InfoFrameCommand.GetProperty, InfoFrameDataType.AudioInformation);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
return infoFrame.PropertyInformation;
}
catch (NVIDIAApiException e)
{
if (e.Status == Status.NotSupported)
{
return null;
}
throw;
}
}
}
///
/// Gets the device HDMI support information
///
public IHDMISupportInfo HDMISupportInfo
{
get => DisplayApi.GetHDMISupportInfo(DisplayId);
}
///
/// Gets the HDMI auxiliary video info-frame current information
///
public InfoFrameVideo? HDMIVideoFrameCurrentInformation
{
get
{
try
{
var infoFrame =
new InfoFrameData(InfoFrameCommand.Get, InfoFrameDataType.AuxiliaryVideoInformation);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
return infoFrame.AuxiliaryVideoInformation;
}
catch (NVIDIAApiException e)
{
if (e.Status == Status.NotSupported)
{
return null;
}
throw;
}
}
}
///
/// Gets the HDMI auxiliary video info-frame default information
///
public InfoFrameVideo? HDMIVideoFrameDefaultInformation
{
get
{
try
{
var infoFrame = new InfoFrameData(InfoFrameCommand.GetDefault,
InfoFrameDataType.AuxiliaryVideoInformation);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
return infoFrame.AuxiliaryVideoInformation;
}
catch (NVIDIAApiException e)
{
if (e.Status == Status.NotSupported)
{
return null;
}
throw;
}
}
}
///
/// Gets the HDMI auxiliary video info-frame override information
///
public InfoFrameVideo? HDMIVideoFrameOverrideInformation
{
get
{
try
{
var infoFrame = new InfoFrameData(InfoFrameCommand.GetOverride,
InfoFrameDataType.AuxiliaryVideoInformation);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
return infoFrame.AuxiliaryVideoInformation;
}
catch (NVIDIAApiException e)
{
if (e.Status == Status.NotSupported)
{
return null;
}
throw;
}
}
}
///
/// Gets the HDMI auxiliary video info-frame property information
///
public InfoFrameProperty? HDMIVideoFramePropertyInformation
{
get
{
try
{
var infoFrame = new InfoFrameData(InfoFrameCommand.GetProperty,
InfoFrameDataType.AuxiliaryVideoInformation);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
return infoFrame.PropertyInformation;
}
catch (NVIDIAApiException e)
{
if (e.Status == Status.NotSupported)
{
return null;
}
throw;
}
}
}
///
/// Gets the HDR color data, or null if the HDR is disabled or unavailable
///
public HDRColorData HDRColorData
{
get
{
try
{
var instances = new IHDRColorData[]
{
new HDRColorDataV2(ColorDataHDRCommand.Get),
new HDRColorDataV1(ColorDataHDRCommand.Get)
};
var instance = DisplayApi.HDRColorControl(DisplayId, instances);
if (instance.HDRMode == ColorDataHDRMode.Off)
{
return null;
}
return new HDRColorData(instance);
}
catch (NVIDIAApiException e)
{
if (e.Status == Status.NotSupported)
{
return null;
}
throw;
}
}
}
///
/// Indicates if the display is being actively driven
///
public bool IsActive { get; }
///
/// Indicates if the display device is currently available
///
public bool IsAvailable { get; }
///
/// Indicates if the display is the representative display
///
public bool IsCluster { get; }
///
/// Indicates if the display is connected
///
public bool IsConnected { get; }
///
/// Indicates if the display is part of MST topology and it's a dynamic
///
public bool IsDynamic { get; }
///
/// Indicates if the display identification belongs to a multi stream enabled connector (root node). Note that when
/// multi stream is enabled and a single multi stream capable monitor is connected to it, the monitor will share the
/// display id with the RootNode.
/// When there is more than one monitor connected in a multi stream topology, then the root node will have a separate
/// displayId.
///
public bool IsMultiStreamRootNode { get; }
///
/// Indicates if the display is reported to the OS
///
public bool IsOSVisible { get; }
///
/// Indicates if the display is a physically connected display; Valid only when IsConnected is true
///
public bool IsPhysicallyConnected { get; }
///
/// Indicates if the display is wireless
///
public bool IsWFD { get; }
///
/// Gets the connected GPU output
///
public GPUOutput Output
{
get
{
PhysicalGPUHandle handle;
var outputId = GPUApi.GetGPUAndOutputIdFromDisplayId(DisplayId, out handle);
return new GPUOutput(outputId, new PhysicalGPU(handle));
}
}
///
/// Gets the connected physical GPU
///
public PhysicalGPU PhysicalGPU
{
get
{
try
{
var gpuHandle = GPUApi.GetPhysicalGPUFromDisplayId(DisplayId);
return new PhysicalGPU(gpuHandle);
}
catch
{
// ignored
}
return Output.PhysicalGPU;
}
}
///
/// Gets information regarding the scan-out settings of this display device
///
public ScanOutInformation ScanOutInformation { get; }
///
/// Gets monitor capabilities from the Video Capability Data Block if available, otherwise null
///
public MonitorVCDBCapabilities? VCDBMonitorCapabilities
{
get => DisplayApi.GetMonitorCapabilities(DisplayId, MonitorCapabilitiesType.VCDB)?.VCDBCapabilities;
}
///
/// Gets monitor capabilities from the Vendor Specific Data Block if available, otherwise null
///
public MonitorVSDBCapabilities? VSDBMonitorCapabilities
{
get => DisplayApi.GetMonitorCapabilities(DisplayId, MonitorCapabilitiesType.VSDB)?.VSDBCapabilities;
}
///
public bool Equals(DisplayDevice other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return DisplayId == other.DisplayId;
}
///
/// Deletes a custom resolution.
///
/// The custom resolution to delete.
/// A list of display ids to remove the custom resolution from.
public static void DeleteCustomResolution(CustomResolution customResolution, uint[] displayIds)
{
var customDisplay = customResolution.AsCustomDisplay(false);
DisplayApi.DeleteCustomDisplay(displayIds, customDisplay);
}
///
/// Returns an instance of representing the primary GDI display device.
///
/// An instance of .
public static DisplayDevice GetGDIPrimaryDisplayDevice()
{
var displayId = DisplayApi.GetGDIPrimaryDisplayId();
if (displayId == 0)
{
return null;
}
return new DisplayDevice(displayId);
}
///
/// 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 ==(DisplayDevice left, DisplayDevice 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 !=(DisplayDevice left, DisplayDevice right)
{
return !(right == left);
}
///
/// Reverts the custom resolution currently on trial.
///
/// A list of display ids to revert the custom resolution from.
public static void RevertCustomResolution(uint[] displayIds)
{
DisplayApi.RevertCustomDisplayTrial(displayIds);
}
///
/// Saves the custom resolution currently on trial.
///
/// A list of display ids to save the custom resolution for.
///
/// If set, the saved custom display will only be applied on the monitor with the same
/// outputId.
///
///
/// If set, the saved custom display will only be applied on the monitor with the same EDID
/// ID or the same TV connector in case of analog TV.
///
public static void SaveCustomResolution(uint[] displayIds, bool isThisOutputIdOnly, bool isThisMonitorOnly)
{
DisplayApi.SaveCustomDisplay(displayIds, isThisOutputIdOnly, isThisMonitorOnly);
}
///
/// Applies a custom resolution into trial
///
/// The custom resolution to apply.
/// A list of display ids to apply the custom resolution on.
///
/// A boolean value indicating that a hardware mode-set without OS update should be
/// performed.
///
public static void TrialCustomResolution(
CustomResolution customResolution,
uint[] displayIds,
bool hardwareModeSetOnly = true)
{
var customDisplay = customResolution.AsCustomDisplay(hardwareModeSetOnly);
DisplayApi.TryCustomDisplay(displayIds.ToDictionary(u => u, u => customDisplay));
}
///
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((DisplayDevice) obj);
}
///
public override int GetHashCode()
{
return (int) DisplayId;
}
///
public override string ToString()
{
return $"Display #{DisplayId}";
}
///
/// Calculates a valid timing based on the argument passed
///
/// The preferred width.
/// The preferred height.
/// The preferred refresh rate.
/// The boolean value indicating if the preferred resolution is an interlaced resolution.
/// Returns a valid instance of .
public Timing CalculateTiming(uint width, uint height, float refreshRate, bool isInterlaced)
{
return DisplayApi.GetTiming(
DisplayId,
new TimingInput(width, height, refreshRate, TimingOverride.Auto, isInterlaced)
);
}
///
/// Deletes a custom resolution.
///
/// The custom resolution to delete.
public void DeleteCustomResolution(CustomResolution customResolution)
{
DeleteCustomResolution(customResolution, new[] {DisplayId});
}
///
/// Retrieves the list of custom resolutions saved for this display device
///
/// A list of instances.
public IEnumerable GetCustomResolutions()
{
return DisplayApi.EnumCustomDisplays(DisplayId).Select(custom => new CustomResolution(custom));
}
///
/// Checks if a color data is supported on this display
///
/// The color data to be checked.
/// true if the color data passed is supported; otherwise false
public bool IsColorDataSupported(ColorData colorData)
{
var instances = new IColorData[]
{
colorData.AsColorDataV5(ColorDataCommand.IsSupportedColor),
colorData.AsColorDataV4(ColorDataCommand.IsSupportedColor),
colorData.AsColorDataV3(ColorDataCommand.IsSupportedColor),
colorData.AsColorDataV2(ColorDataCommand.IsSupportedColor),
colorData.AsColorDataV1(ColorDataCommand.IsSupportedColor)
};
try
{
DisplayApi.ColorControl(DisplayId, instances);
return true;
}
catch (NVIDIAApiException e)
{
if (e.Status == Status.NotSupported)
{
return false;
}
throw;
}
}
///
/// Resets the HDMI audio info-frame information to default
///
public void ResetHDMIAudioFrameInformation()
{
var infoFrame = new InfoFrameData(
InfoFrameCommand.Reset,
InfoFrameDataType.AudioInformation
);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
}
///
/// Resets the HDMI auxiliary video info-frame information to default
///
public void ResetHDMIVideoFrameInformation()
{
var infoFrame = new InfoFrameData(
InfoFrameCommand.Reset,
InfoFrameDataType.AuxiliaryVideoInformation
);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
}
///
/// Reverts the custom resolution currently on trial.
///
public void RevertCustomResolution()
{
RevertCustomResolution(new[] {DisplayId});
}
///
/// Saves the custom resolution currently on trial.
///
///
/// If set, the saved custom display will only be applied on the monitor with the same
/// outputId.
///
///
/// If set, the saved custom display will only be applied on the monitor with the same EDID
/// ID or the same TV connector in case of analog TV.
///
public void SaveCustomResolution(bool isThisOutputIdOnly = true, bool isThisMonitorOnly = true)
{
SaveCustomResolution(new[] {DisplayId}, isThisOutputIdOnly, isThisMonitorOnly);
}
///
/// Changes the display current color data configuration
///
/// The color data to be set.
public void SetColorData(ColorData colorData)
{
var instances = new IColorData[]
{
colorData.AsColorDataV5(ColorDataCommand.Set),
colorData.AsColorDataV4(ColorDataCommand.Set),
colorData.AsColorDataV3(ColorDataCommand.Set),
colorData.AsColorDataV2(ColorDataCommand.Set),
colorData.AsColorDataV1(ColorDataCommand.Set)
};
DisplayApi.ColorControl(DisplayId, instances);
}
///
/// Sets the HDMI video info-frame current or override information
///
/// The new information.
/// A boolean value indicating if the changes should persist mode-set and OS restart.
public void SetHDMIAudioFrameInformation(InfoFrameAudio audio, bool isOverride = false)
{
var infoFrame = new InfoFrameData(
isOverride ? InfoFrameCommand.SetOverride : InfoFrameCommand.Set,
audio
);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
}
///
/// Sets the HDMI audio info-frame property information
///
/// The new property information.
public void SetHDMIAudioFramePropertyInformation(InfoFrameProperty property)
{
var infoFrame = new InfoFrameData(
InfoFrameCommand.SetProperty,
InfoFrameDataType.AudioInformation,
property
);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
}
///
/// Sets the HDMI auxiliary video info-frame current or override information
///
/// The new information.
/// A boolean value indicating if the changes should persist mode-set and OS restart.
public void SetHDMIVideoFrameInformation(InfoFrameVideo video, bool isOverride = false)
{
var infoFrame = new InfoFrameData(
isOverride ? InfoFrameCommand.SetOverride : InfoFrameCommand.Set,
video
);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
}
///
/// Sets the HDMI auxiliary video info-frame property information
///
/// The new property information.
public void SetHDMIVideoFramePropertyInformation(InfoFrameProperty property)
{
var infoFrame = new InfoFrameData(
InfoFrameCommand.SetProperty,
InfoFrameDataType.AuxiliaryVideoInformation,
property
);
DisplayApi.InfoFrameControl(DisplayId, ref infoFrame);
}
///
/// Changes the display HDR color data configuration
///
/// The color data to be set.
public void SetHDRColorData(HDRColorData colorData)
{
var instances = new IHDRColorData[]
{
colorData.AsHDRColorDataV2(ColorDataHDRCommand.Set),
colorData.AsHDRColorDataV1(ColorDataHDRCommand.Set)
};
DisplayApi.HDRColorControl(DisplayId, instances);
}
///
/// Applies a custom resolution into trial.
///
/// The custom resolution to apply.
///
/// A boolean value indicating that a hardware mode-set without OS update should be
/// performed.
///
public void TrialCustomResolution(CustomResolution customResolution, bool hardwareModeSetOnly = true)
{
TrialCustomResolution(customResolution, new[] {DisplayId}, hardwareModeSetOnly);
}
}
}