using System;
using NvAPIWrapper.Display;
using NvAPIWrapper.Native;
using NvAPIWrapper.Native.Exceptions;
using NvAPIWrapper.Native.General;
using NvAPIWrapper.Native.GPU;
using NvAPIWrapper.Native.GPU.Structures;
namespace NvAPIWrapper.GPU
{
///
/// Represents a single GPU output
///
public class GPUOutput : IEquatable
{
internal GPUOutput(OutputId outputId, PhysicalGPUHandle gpuHandle)
{
OutputId = outputId;
OutputType = !gpuHandle.IsNull ? GPUApi.GetOutputType(gpuHandle, outputId) : OutputType.Unknown;
PhysicalGPU = new PhysicalGPU(gpuHandle);
}
internal GPUOutput(OutputId outputId, PhysicalGPU gpu)
: this(outputId, gpu?.Handle ?? PhysicalGPUHandle.DefaultHandle)
{
PhysicalGPU = gpu;
}
///
/// Gets the corresponding Digital Vibrance Control information
///
public DVCInformation DigitalVibranceControl
{
get => new DVCInformation(OutputId);
}
///
/// Gets the corresponding HUE information
///
public HUEInformation HUEControl
{
get => new HUEInformation(OutputId);
}
///
/// Gets the output identification as a single bit unsigned integer
///
public OutputId OutputId { get; }
///
/// Gets the output type
///
public OutputType OutputType { get; }
///
/// Gets the corresponding physical GPU
///
public PhysicalGPU PhysicalGPU { get; }
///
public bool Equals(GPUOutput other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return PhysicalGPU.Equals(other.PhysicalGPU) && OutputId == other.OutputId;
}
///
/// 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 ==(GPUOutput left, GPUOutput 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 !=(GPUOutput left, GPUOutput right)
{
return !(left == right);
}
///
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((GPUOutput) obj);
}
///
public override int GetHashCode()
{
unchecked
{
return ((PhysicalGPU != null ? PhysicalGPU.GetHashCode() : 0) * 397) ^ (int) OutputId;
}
}
///
public override string ToString()
{
return $"{OutputId} {OutputType} @ {PhysicalGPU}";
}
///
/// Overrides the refresh rate on this output.
/// The new refresh rate can be applied right away or deferred to be applied with the next OS
/// mode-set.
/// The override is good for only one mode-set (regardless whether it's deferred or immediate).
///
/// The refresh rate to be applied.
///
/// A boolean value indicating if the refresh rate override should be deferred to the next OS
/// mode-set.
///
public void OverrideRefreshRate(float refreshRate, bool isDeferred = false)
{
DisplayApi.SetRefreshRateOverride(OutputId, refreshRate, isDeferred);
}
///
/// Reads data from the I2C bus
///
/// The port id on which device is connected
/// A boolean value indicating that the DDC port should be used instead of the communication port
/// The device I2C slave address
/// The target I2C register address
/// The length of the buffer to allocate for the read operation.
/// The target speed of the transaction in kHz
public byte[] ReadI2C(
byte? portId,
bool useDDCPort,
byte deviceAddress,
byte[] registerAddress,
uint readDataLength,
I2CSpeed speed = I2CSpeed.Default
)
{
try
{
// ReSharper disable once InconsistentNaming
var i2cInfoV3 = new I2CInfoV3(
OutputId,
portId,
useDDCPort,
deviceAddress,
registerAddress,
readDataLength,
speed
);
return PhysicalGPU.ReadI2C(i2cInfoV3);
}
catch (NVIDIAApiException e)
{
if (e.Status != Status.IncompatibleStructureVersion || portId != null)
{
throw;
}
// ignore
}
// ReSharper disable once InconsistentNaming
var i2cInfoV2 = new I2CInfoV2(
OutputId,
useDDCPort,
deviceAddress,
registerAddress,
readDataLength,
speed
);
return PhysicalGPU.ReadI2C(i2cInfoV2);
}
///
/// Writes data to the I2C bus
///
/// The port id on which device is connected
/// A boolean value indicating that the DDC port should be used instead of the communication port
/// The device I2C slave address
/// The target I2C register address
/// The payload data
/// The target speed of the transaction in kHz
public void WriteI2C(
byte? portId,
bool useDDCPort,
byte deviceAddress,
byte[] registerAddress,
byte[] data,
I2CSpeed speed = I2CSpeed.Default
)
{
try
{
// ReSharper disable once InconsistentNaming
var i2cInfoV3 = new I2CInfoV3(
OutputId,
portId,
useDDCPort,
deviceAddress,
registerAddress,
data,
speed
);
PhysicalGPU.WriteI2C(i2cInfoV3);
return;
}
catch (NVIDIAApiException e)
{
if (e.Status != Status.IncompatibleStructureVersion || portId != null)
{
throw;
}
// ignore
}
// ReSharper disable once InconsistentNaming
var i2cInfoV2 = new I2CInfoV2(
OutputId,
useDDCPort,
deviceAddress,
registerAddress,
data,
speed
);
PhysicalGPU.WriteI2C(i2cInfoV2);
}
}
}