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