using System;
using System.Runtime.InteropServices;
using NvAPIWrapper.Native.Attributes;
using NvAPIWrapper.Native.General.Structures;
using NvAPIWrapper.Native.Helpers;
using NvAPIWrapper.Native.Interfaces;
namespace NvAPIWrapper.Native.Display.Structures
{
///
/// Contains the information required for calculating timing for a particular display
///
[StructLayout(LayoutKind.Sequential, Pack = 8)]
[StructureVersion(1)]
public struct TimingInput : IInitializable
{
[StructLayout(LayoutKind.Explicit, Pack = 8, Size = 12)]
internal struct TimingFlag
{
[FieldOffset(0)] internal ushort _Flags;
[FieldOffset(4)] internal byte _TVFormatCEAIdPSFormatId;
[FieldOffset(8)] internal byte _Scaling;
public bool IsInterlaced
{
get => _Flags.GetBit(0);
set => _Flags = _Flags.SetBit(0, value);
}
public TVFormat TVFormat
{
get => (TVFormat) _TVFormatCEAIdPSFormatId;
set => _TVFormatCEAIdPSFormatId = (byte) value;
}
public byte CEAId
{
get => _TVFormatCEAIdPSFormatId;
set => _TVFormatCEAIdPSFormatId = value;
}
public byte PredefinedPSFormatId
{
get => _TVFormatCEAIdPSFormatId;
set => _TVFormatCEAIdPSFormatId = value;
}
public byte Scaling
{
get => _Scaling;
set => _Scaling = value;
}
public TimingFlag(bool isInterlaced, byte scaling) : this()
{
IsInterlaced = isInterlaced;
Scaling = scaling;
}
public TimingFlag(bool isInterlaced, byte scaling, TVFormat tvFormat) : this(isInterlaced, scaling)
{
TVFormat = tvFormat;
}
public TimingFlag(bool isInterlaced, byte scaling, byte ceaIdOrPredefinedPSFormatId) : this(isInterlaced,
scaling)
{
_TVFormatCEAIdPSFormatId = ceaIdOrPredefinedPSFormatId;
}
}
internal StructureVersion _Version;
internal uint _Width;
internal uint _Height;
internal float _RefreshRate;
internal TimingFlag _Flags;
internal TimingOverride _TimingType;
///
/// Gets the visible horizontal size
///
public uint Width
{
get => _Width;
}
///
/// Gets the visible vertical size
///
public uint Height
{
get => _Height;
}
///
/// Gets the timing refresh rate
///
public float RefreshRate
{
get => _RefreshRate;
}
///
/// Gets a boolean value indicating if the requested timing is an interlaced timing
///
public bool IsInterlaced
{
get => _Flags.IsInterlaced;
}
///
/// Gets the preferred scaling
///
public byte Scaling
{
get => _Flags.Scaling;
}
///
/// Gets timing type (formula) to use for calculating the timing
///
public TimingOverride TimingType
{
get => _TimingType;
}
///
/// Creates an instance of the TimingInput
///
/// The preferred visible horizontal size
/// The preferred visible vertical size
/// The preferred timing refresh rate
/// The preferred formula to be used for timing calculation
/// A boolean value indicating if the preferred timing is interlaced
/// The preferred scaling factor
public TimingInput(
uint width,
uint height,
float refreshRate,
TimingOverride timingType,
bool isInterlaced = false,
byte scaling = 0
)
{
this = typeof(TimingInput).Instantiate();
_Width = width;
_Height = height;
_RefreshRate = refreshRate;
_TimingType = timingType;
_Flags = new TimingFlag(isInterlaced, scaling);
}
///
/// Creates an instance of the TimingInput
///
/// The preferred analog TV format
/// A boolean value indicating if the preferred timing is interlaced
/// The preferred scaling factor
public TimingInput(TVFormat tvFormat, bool isInterlaced = false, byte scaling = 0)
: this(0, 0, 0, TimingOverride.AnalogTV, isInterlaced, scaling)
{
_Flags = new TimingFlag(isInterlaced, scaling, tvFormat);
}
///
/// Creates an instance of the TimingInput
///
///
/// The CEA id or the predefined PsF format id depending on the value of other
/// arguments
///
///
/// The preferred formula to be used for timing calculation, valid values for this overload are
/// and .
///
/// A boolean value indicating if the preferred timing is interlaced
/// The preferred scaling factor
public TimingInput(
byte ceaIdOrPredefinedPSFormatId,
TimingOverride timingType,
bool isInterlaced = false,
byte scaling = 0
)
: this(0, 0, 0, timingType, isInterlaced, scaling)
{
if (timingType != TimingOverride.EIA861 && timingType != TimingOverride.Predefined)
{
throw new ArgumentException("Invalid timing type passed.", nameof(timingType));
}
_Flags = new TimingFlag(isInterlaced, scaling, ceaIdOrPredefinedPSFormatId);
}
///
/// Creates an instance of the TimingInput
///
///
/// The preferred formula to be used for timing calculation.
///
public TimingInput(TimingOverride timingType)
: this(0, 0, 0, timingType)
{
}
///
/// Gets the analog TV actual HD/SDTV format
///
public TVFormat? TVFormat
{
get
{
if (Width == 0 && Height == 0 && Math.Abs(RefreshRate) < 0.01 && TimingType == TimingOverride.AnalogTV)
{
return _Flags.TVFormat;
}
return null;
}
}
///
/// Gets the EIA/CEA 861B/D predefined short timing descriptor id
///
public byte? CEAId
{
get
{
if (Width == 0 && Height == 0 && Math.Abs(RefreshRate) < 0.01 && TimingType == TimingOverride.EIA861)
{
return _Flags.CEAId;
}
return null;
}
}
///
/// Gets the Nvidia predefined PsF format id
///
public byte? PredefinedPSFormatId
{
get
{
if (TimingType == TimingOverride.Predefined)
{
return _Flags.PredefinedPSFormatId;
}
return null;
}
}
}
}