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