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