using System; using System.Linq; 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.Helpers; using NvAPIWrapper.Native.Helpers.Structures; using NvAPIWrapper.Native.Interfaces.GPU; namespace NvAPIWrapper.Native { public static partial class GPUApi { /// /// This function is the same as GetAllOutputs() but returns only the set of GPU output identifiers that are actively /// driving display devices. /// /// Physical GPU handle to get information about /// Active output identifications as a flag /// Status.InvalidArgument: display is not valid /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found /// Status.ExpectedPhysicalGPUHandle: gpuHandle was not a physical GPU handle. public static OutputId GetActiveOutputs(PhysicalGPUHandle gpuHandle) { var status = DelegateFactory.GetDelegate()(gpuHandle, out var outputMask); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return outputMask; } /// /// This API returns display IDs for all possible outputs on the GPU. /// For DPMST connector, it will return display IDs for all the video sinks in the topology. /// /// Physical GPU handle to get information about /// An array of display identifications and their attributes /// This operation is not supported. /// See NVIDIAApiException.Status for the reason of the exception. /// A delegate callback throws an exception. public static DisplayIdsV2[] GetAllDisplayIds(PhysicalGPUHandle gpuHandle) { var gpuGetConnectedDisplayIds = DelegateFactory.GetDelegate(); if (!gpuGetConnectedDisplayIds.Accepts().Contains(typeof(DisplayIdsV2))) { throw new NVIDIANotSupportedException("This operation is not supported."); } uint count = 0; var status = gpuGetConnectedDisplayIds(gpuHandle, ValueTypeArray.Null, ref count); if (status != Status.Ok) { throw new NVIDIAApiException(status); } if (count == 0) { return new DisplayIdsV2[0]; } using ( var displayIds = ValueTypeArray.FromArray(typeof(DisplayIdsV2).Instantiate().Repeat((int) count))) { status = gpuGetConnectedDisplayIds(gpuHandle, displayIds, ref count); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return displayIds.ToArray((int) count); } } /// /// Due to space limitation GetConnectedOutputs() can return maximum 32 devices, but this is no longer true for DPMST. /// GetConnectedDisplayIds() will return all the connected display devices in the form of displayIds for the associated /// gpuHandle. /// This function can accept set of flags to request cached, un-cached, sli and lid to get the connected devices. /// Default value for flags will be cached. /// /// Physical GPU handle to get information about /// ConnectedIdsFlag flags /// An array of display identifications and their attributes /// This operation is not supported. /// Status.InvalidArgument: gpuHandle is invalid /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found /// Status.ExpectedPhysicalGPUHandle: gpuHandle was not a physical GPU handle /// A delegate callback throws an exception. public static DisplayIdsV2[] GetConnectedDisplayIds(PhysicalGPUHandle gpuHandle, ConnectedIdsFlag flags) { var gpuGetConnectedDisplayIds = DelegateFactory.GetDelegate(); if (!gpuGetConnectedDisplayIds.Accepts().Contains(typeof(DisplayIdsV2))) { throw new NVIDIANotSupportedException("This operation is not supported."); } uint count = 0; var status = gpuGetConnectedDisplayIds(gpuHandle, ValueTypeArray.Null, ref count, flags); if (status != Status.Ok) { throw new NVIDIAApiException(status); } if (count == 0) { return new DisplayIdsV2[0]; } using ( var displayIds = ValueTypeArray.FromArray(typeof(DisplayIdsV2).Instantiate().Repeat((int) count))) { status = gpuGetConnectedDisplayIds(gpuHandle, displayIds, ref count, flags); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return displayIds.ToArray((int) count); } } /// /// This API converts a Physical GPU handle and output ID to a display ID. /// /// Handle to the physical GPU /// Connected display output identification on the target GPU - must only have one bit set /// Display identification /// Status.ApiNotInitialized: NVAPI not initialized /// Status.Error: miscellaneous error occurred /// Status.InvalidArgument: Invalid input parameter. public static uint GetDisplayIdFromGPUAndOutputId(PhysicalGPUHandle gpuHandle, OutputId outputId) { var status = DelegateFactory.GetDelegate()( gpuHandle, outputId, out var display); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return display; } /// /// This function returns the EDID data for the specified GPU handle and connection bit mask. /// outputId should have exactly 1 bit set to indicate a single display. /// /// Physical GPU handle to check outputs /// Output identification /// EDID offset /// EDID read identification for multi part read, or zero for first run /// Whole or a part of the EDID data /// This operation is not supported. /// /// Status.InvalidArgument: gpuHandle or edid is invalid, outputId has 0 or > 1 bits /// set /// /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found. /// Status.ExpectedPhysicalGPUHandle: gpuHandle was not a physical GPU handle. /// Status.DataNotFound: The requested display does not contain an EDID. /// A delegate callback throws an exception. // ReSharper disable once TooManyArguments public static EDIDV3 GetEDID( PhysicalGPUHandle gpuHandle, OutputId outputId, int offset, int readIdentification = 0) { var gpuGetEDID = DelegateFactory.GetDelegate(); if (!gpuGetEDID.Accepts().Contains(typeof(EDIDV3))) { throw new NVIDIANotSupportedException("This operation is not supported."); } var instance = EDIDV3.CreateWithOffset((uint) readIdentification, (uint) offset); using (var edidReference = ValueTypeReference.FromValueType(instance)) { var status = gpuGetEDID(gpuHandle, outputId, edidReference); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return edidReference.ToValueType().GetValueOrDefault(); } } /// /// This function returns the EDID data for the specified GPU handle and connection bit mask. /// outputId should have exactly 1 bit set to indicate a single display. /// /// Physical GPU handle to check outputs /// Output identification /// Whole or a part of the EDID data /// This operation is not supported. /// /// Status.InvalidArgument: gpuHandle or edid is invalid, outputId has 0 or > 1 bits /// set /// /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found. /// Status.ExpectedPhysicalGPUHandle: gpuHandle was not a physical GPU handle. /// Status.DataNotFound: The requested display does not contain an EDID. /// A delegate callback throws an exception. public static IEDID GetEDID(PhysicalGPUHandle gpuHandle, OutputId outputId) { var gpuGetEDID = DelegateFactory.GetDelegate(); foreach (var acceptType in gpuGetEDID.Accepts()) { using (var edidReference = ValueTypeReference.FromValueType(acceptType.Instantiate(), acceptType) ) { var status = gpuGetEDID(gpuHandle, outputId, edidReference); if (status == Status.IncompatibleStructureVersion) { continue; } if (status != Status.Ok) { throw new NVIDIAApiException(status); } return edidReference.ToValueType(acceptType); } } throw new NVIDIANotSupportedException("This operation is not supported."); } /// /// This API converts a display ID to a Physical GPU handle and output ID. /// /// Display identification of display to retrieve GPU and outputId for /// Handle to the physical GPU /// Connected display output identification on the target GPU will only have one bit set. /// Status.ApiNotInitialized: NVAPI not initialized /// Status.Error: Miscellaneous error occurred /// Status.InvalidArgument: Invalid input parameter /// /// Status.IdOutOfRange: The DisplayId corresponds to a display which is not within /// the normal outputId range. /// public static OutputId GetGPUAndOutputIdFromDisplayId(uint displayId, out PhysicalGPUHandle gpuHandle) { var status = DelegateFactory.GetDelegate()( displayId, out gpuHandle, out var outputId); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return outputId; } /// /// This function returns the logical GPU handle associated with the specified display. /// At least one GPU must be present in the system and running an NVIDIA display driver. /// display can be DisplayHandle.DefaultHandle or a handle enumerated from EnumNVidiaDisplayHandle(). /// /// Display handle to get information about /// Logical GPU handle associated with the specified display /// Status.InvalidArgument: display is not valid /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found public static LogicalGPUHandle GetLogicalGPUFromDisplay(DisplayHandle display) { var status = DelegateFactory.GetDelegate()(display, out var gpu); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return gpu; } /// /// This function returns the output type. User can either specify both 'physical GPU handle and outputId (exactly 1 /// bit set)' or a valid displayId in the outputId parameter. /// /// GPU handle to get information about /// Output identification of the output to get information about /// Type of the output /// Status.InvalidArgument: gpuHandle is NULL /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found /// Status.ExpectedPhysicalGPUHandle: gpuHandle was not a physical GPU handle public static OutputType GetOutputType(PhysicalGPUHandle gpuHandle, OutputId outputId) { return GetOutputType(gpuHandle, (uint) outputId); } /// /// This function returns the output type. User can either specify both 'physical GPU handle and outputId (exactly 1 /// bit set)' or a valid displayId in the outputId parameter. /// /// GPU handle to get information about /// Display identification of the divide to get information about /// Type of the output /// Status.InvalidArgument: gpuHandle is NULL /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found /// Status.ExpectedPhysicalGPUHandle: gpuHandle was not a physical GPU handle public static OutputType GetOutputType(PhysicalGPUHandle gpuHandle, uint displayId) { var status = DelegateFactory.GetDelegate()(gpuHandle, displayId, out var type); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return type; } /// /// This API retrieves the Physical GPU handle of the connected display /// /// Display identification of display to retrieve GPU handle /// Handle to the physical GPU /// Status.ApiNotInitialized: NVAPI not initialized /// Status.Error: Miscellaneous error occurred /// Status.InvalidArgument: Invalid input parameter public static PhysicalGPUHandle GetPhysicalGPUFromDisplayId(uint displayId) { var status = DelegateFactory.GetDelegate()(displayId, out var gpu); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return gpu; } /// /// This function returns a physical GPU handle associated with the specified unattached display. /// The source GPU is a physical render GPU which renders the frame buffer but may or may not drive the scan out. /// At least one GPU must be present in the system and running an NVIDIA display driver. /// /// Display handle to get information about /// Physical GPU handle associated with the specified unattached display. /// Status.InvalidArgument: display is not valid /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found public static PhysicalGPUHandle GetPhysicalGPUFromUnAttachedDisplay(UnAttachedDisplayHandle display) { var status = DelegateFactory.GetDelegate()(display, out var gpu); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return gpu; } /// /// This function returns an array of physical GPU handles associated with the specified display. /// At least one GPU must be present in the system and running an NVIDIA display driver. /// If the display corresponds to more than one physical GPU, the first GPU returned is the one with the attached /// active output. /// /// Display handle to get information about /// An array of physical GPU handles /// Status.InvalidArgument: display is not valid /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found public static PhysicalGPUHandle[] GetPhysicalGPUsFromDisplay(DisplayHandle display) { var gpuList = typeof(PhysicalGPUHandle).Instantiate().Repeat(PhysicalGPUHandle.MaxPhysicalGPUs); var status = DelegateFactory.GetDelegate()(display, gpuList, out var count); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return gpuList.Take((int) count).ToArray(); } /// /// Thus function sets the EDID data for the specified GPU handle and connection bit mask. /// User can either send (Gpu handle and output id) or only display Id in variable outputId parameter and gpuHandle /// parameter can be default handle. /// Note: The EDID will be cached across the boot session and will be enumerated to the OS in this call. To remove the /// EDID set size of EDID to zero. OS and NVAPI connection status APIs will reflect the newly set or removed EDID /// dynamically. /// This feature will NOT be supported on the following boards: GeForce, Quadro VX, Tesla /// /// Physical GPU handle to check outputs /// Output identification /// EDID information /// This operation is not supported. /// /// Status.InvalidArgument: gpuHandle or edid is invalid, outputId has 0 or > 1 bits /// set /// /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found. /// Status.ExpectedPhysicalGPUHandle: gpuHandle was not a physical GPU handle. /// Status.NotSupported: For the above mentioned GPUs public static void SetEDID(PhysicalGPUHandle gpuHandle, OutputId outputId, IEDID edid) { SetEDID(gpuHandle, (uint) outputId, edid); } /// /// Thus function sets the EDID data for the specified GPU handle and connection bit mask. /// User can either send (Gpu handle and output id) or only display Id in variable outputId parameter and gpuHandle /// parameter can be default handle. /// Note: The EDID will be cached across the boot session and will be enumerated to the OS in this call. To remove the /// EDID set size of EDID to zero. OS and NVAPI connection status APIs will reflect the newly set or removed EDID /// dynamically. /// This feature will NOT be supported on the following boards: GeForce, Quadro VX, Tesla /// /// Physical GPU handle to check outputs /// Output identification /// EDID information /// This operation is not supported. /// /// Status.InvalidArgument: gpuHandle or edid is invalid, outputId has 0 or > 1 bits /// set /// /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found. /// Status.ExpectedPhysicalGPUHandle: gpuHandle was not a physical GPU handle. /// Status.NotSupported: For the above mentioned GPUs /// A delegate callback throws an exception. public static void SetEDID(PhysicalGPUHandle gpuHandle, uint displayId, IEDID edid) { var gpuSetEDID = DelegateFactory.GetDelegate(); if (!gpuSetEDID.Accepts().Contains(edid.GetType())) { throw new NVIDIANotSupportedException("This operation is not supported."); } using (var edidReference = ValueTypeReference.FromValueType(edid, edid.GetType())) { var status = gpuSetEDID(gpuHandle, displayId, edidReference); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } } /// /// This function determines if a set of GPU outputs can be active simultaneously. While a GPU may have 'n' outputs, /// typically they cannot all be active at the same time due to internal resource sharing. /// Given a physical GPU handle and a mask of candidate outputs, this call will return true if all of the specified /// outputs can be driven simultaneously. It will return false if they cannot. /// /// Physical GPU handle to check outputs /// Output identification combination /// true if all of the specified outputs can be driven simultaneously. It will return false if they cannot. /// Status.InvalidArgument: display is not valid /// Status.NvidiaDeviceNotFound: No NVIDIA GPU driving a display was found /// Status.ExpectedPhysicalGPUHandle: gpuHandle was not a physical GPU handle. public static bool ValidateOutputCombination(PhysicalGPUHandle gpuHandle, OutputId outputIds) { var status = DelegateFactory.GetDelegate()(gpuHandle, outputIds); if (status == Status.InvalidCombination) { return false; } if (status != Status.Ok) { throw new NVIDIAApiException(status); } return true; } } }