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