diff --git a/D/App.config b/D/App.config index 2b933e2..4e8ed4f 100644 --- a/D/App.config +++ b/D/App.config @@ -43,6 +43,9 @@ 1955-11-05 + + False + \ No newline at end of file diff --git a/D/Configuration.cs b/D/Configuration.cs index d1fad94..7dc3c8a 100644 --- a/D/Configuration.cs +++ b/D/Configuration.cs @@ -158,6 +158,12 @@ namespace D /// public static bool SlowPhosphor; + /// + /// Whether to apply linear or nearest-neighbor filtering to the display, when + /// scaled. + /// + public static bool FullScreenStretch; + /// /// How to set the TOD clock at power up/reset /// @@ -236,6 +242,7 @@ namespace D HostPacketInterfaceName = Properties.Settings.Default.HostPacketInterfaceName; ThrottleSpeed = Properties.Settings.Default.ThrottleSpeed; DisplayScale = Properties.Settings.Default.DisplayScale; + FullScreenStretch = Properties.Settings.Default.FullScreenFilter; SlowPhosphor = Properties.Settings.Default.SlowPhosphor; TODSetMode = (TODPowerUpSetMode)Properties.Settings.Default.TODSetMode; TODDateTime = Properties.Settings.Default.TODDateTime; @@ -251,6 +258,7 @@ namespace D Properties.Settings.Default.HostPacketInterfaceName = HostPacketInterfaceName; Properties.Settings.Default.ThrottleSpeed = ThrottleSpeed; Properties.Settings.Default.DisplayScale = DisplayScale; + Properties.Settings.Default.FullScreenFilter = FullScreenStretch; Properties.Settings.Default.SlowPhosphor = SlowPhosphor; Properties.Settings.Default.TODSetMode = (int)TODSetMode; Properties.Settings.Default.TODDateTime = TODDateTime; diff --git a/D/Properties/Settings.Designer.cs b/D/Properties/Settings.Designer.cs index 25c2e8b..59de473 100644 --- a/D/Properties/Settings.Designer.cs +++ b/D/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace D.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -154,5 +154,17 @@ namespace D.Properties { this["TODDate"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool FullScreenFilter { + get { + return ((bool)(this["FullScreenFilter"])); + } + set { + this["FullScreenFilter"] = value; + } + } } } diff --git a/D/Properties/Settings.settings b/D/Properties/Settings.settings index 7b8a3e7..b70704b 100644 --- a/D/Properties/Settings.settings +++ b/D/Properties/Settings.settings @@ -35,5 +35,8 @@ 1955-11-05 + + False + \ No newline at end of file diff --git a/D/UI/ConfigurationDialog.Designer.cs b/D/UI/ConfigurationDialog.Designer.cs index aef4625..b04d050 100644 --- a/D/UI/ConfigurationDialog.Designer.cs +++ b/D/UI/ConfigurationDialog.Designer.cs @@ -72,6 +72,9 @@ namespace D.UI this.label3 = new System.Windows.Forms.Label(); this.SlowPhosphorCheckBox = new System.Windows.Forms.CheckBox(); this.TimeTabPage = new System.Windows.Forms.TabPage(); + this.TODDatePicker = new System.Windows.Forms.DateTimePicker(); + this.SpecifiedDateRadioButton = new System.Windows.Forms.RadioButton(); + this.NoTimeDateChangeRadioButton = new System.Windows.Forms.RadioButton(); this.TODDateTimePicker = new System.Windows.Forms.DateTimePicker(); this.SpecifiedTimeDateRadioButton = new System.Windows.Forms.RadioButton(); this.CurrentTimeDateY2KRadioButton = new System.Windows.Forms.RadioButton(); @@ -79,9 +82,7 @@ namespace D.UI this.label4 = new System.Windows.Forms.Label(); this.OKButton = new System.Windows.Forms.Button(); this.Cancel_Button = new System.Windows.Forms.Button(); - this.NoTimeDateChangeRadioButton = new System.Windows.Forms.RadioButton(); - this.SpecifiedDateRadioButton = new System.Windows.Forms.RadioButton(); - this.TODDatePicker = new System.Windows.Forms.DateTimePicker(); + this.FullScreenStretchCheckBox = new System.Windows.Forms.CheckBox(); this.TabControl.SuspendLayout(); this.SystemPage.SuspendLayout(); this.EthernetTab.SuspendLayout(); @@ -199,6 +200,7 @@ namespace D.UI // // DisplayTab // + this.DisplayTab.Controls.Add(this.FullScreenStretchCheckBox); this.DisplayTab.Controls.Add(this.DisplayScaleComboBox); this.DisplayTab.Controls.Add(this.label3); this.DisplayTab.Controls.Add(this.SlowPhosphorCheckBox); @@ -261,6 +263,38 @@ namespace D.UI this.TimeTabPage.Text = "Time"; this.TimeTabPage.UseVisualStyleBackColor = true; // + // TODDatePicker + // + this.TODDatePicker.CustomFormat = "MM\'/\'dd\'/\'yyyy"; + this.TODDatePicker.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.TODDatePicker.Location = new System.Drawing.Point(136, 93); + this.TODDatePicker.Name = "TODDatePicker"; + this.TODDatePicker.ShowUpDown = true; + this.TODDatePicker.Size = new System.Drawing.Size(200, 20); + this.TODDatePicker.TabIndex = 7; + // + // SpecifiedDateRadioButton + // + this.SpecifiedDateRadioButton.AutoSize = true; + this.SpecifiedDateRadioButton.Location = new System.Drawing.Point(10, 93); + this.SpecifiedDateRadioButton.Name = "SpecifiedDateRadioButton"; + this.SpecifiedDateRadioButton.Size = new System.Drawing.Size(118, 17); + this.SpecifiedDateRadioButton.TabIndex = 6; + this.SpecifiedDateRadioButton.TabStop = true; + this.SpecifiedDateRadioButton.Text = "Specified date only:"; + this.SpecifiedDateRadioButton.UseVisualStyleBackColor = true; + // + // NoTimeDateChangeRadioButton + // + this.NoTimeDateChangeRadioButton.AutoSize = true; + this.NoTimeDateChangeRadioButton.Location = new System.Drawing.Point(10, 119); + this.NoTimeDateChangeRadioButton.Name = "NoTimeDateChangeRadioButton"; + this.NoTimeDateChangeRadioButton.Size = new System.Drawing.Size(205, 17); + this.NoTimeDateChangeRadioButton.TabIndex = 5; + this.NoTimeDateChangeRadioButton.TabStop = true; + this.NoTimeDateChangeRadioButton.Text = "No change (do not modify TOD clock)"; + this.NoTimeDateChangeRadioButton.UseVisualStyleBackColor = true; + // // TODDateTimePicker // this.TODDateTimePicker.CustomFormat = "MM\'/\'dd\'/\'yyyy HH\':\'mm\':\'ss"; @@ -333,37 +367,15 @@ namespace D.UI this.Cancel_Button.Text = "Cancel"; this.Cancel_Button.UseVisualStyleBackColor = true; // - // NoTimeDateChangeRadioButton + // FullScreenFilterCheckBox // - this.NoTimeDateChangeRadioButton.AutoSize = true; - this.NoTimeDateChangeRadioButton.Location = new System.Drawing.Point(10, 119); - this.NoTimeDateChangeRadioButton.Name = "NoTimeDateChangeRadioButton"; - this.NoTimeDateChangeRadioButton.Size = new System.Drawing.Size(205, 17); - this.NoTimeDateChangeRadioButton.TabIndex = 5; - this.NoTimeDateChangeRadioButton.TabStop = true; - this.NoTimeDateChangeRadioButton.Text = "No change (do not modify TOD clock)"; - this.NoTimeDateChangeRadioButton.UseVisualStyleBackColor = true; - // - // SpecifiedDateRadioButton - // - this.SpecifiedDateRadioButton.AutoSize = true; - this.SpecifiedDateRadioButton.Location = new System.Drawing.Point(10, 93); - this.SpecifiedDateRadioButton.Name = "SpecifiedDateRadioButton"; - this.SpecifiedDateRadioButton.Size = new System.Drawing.Size(118, 17); - this.SpecifiedDateRadioButton.TabIndex = 6; - this.SpecifiedDateRadioButton.TabStop = true; - this.SpecifiedDateRadioButton.Text = "Specified date only:"; - this.SpecifiedDateRadioButton.UseVisualStyleBackColor = true; - // - // TODDatePicker - // - this.TODDatePicker.CustomFormat = "MM\'/\'dd\'/\'yyyy"; - this.TODDatePicker.Format = System.Windows.Forms.DateTimePickerFormat.Custom; - this.TODDatePicker.Location = new System.Drawing.Point(136, 93); - this.TODDatePicker.Name = "TODDatePicker"; - this.TODDatePicker.ShowUpDown = true; - this.TODDatePicker.Size = new System.Drawing.Size(200, 20); - this.TODDatePicker.TabIndex = 7; + this.FullScreenStretchCheckBox.AutoSize = true; + this.FullScreenStretchCheckBox.Location = new System.Drawing.Point(6, 55); + this.FullScreenStretchCheckBox.Name = "FullScreenFilterCheckBox"; + this.FullScreenStretchCheckBox.Size = new System.Drawing.Size(186, 17); + this.FullScreenStretchCheckBox.TabIndex = 3; + this.FullScreenStretchCheckBox.Text = "Stretch screen in Fullscreen mode"; + this.FullScreenStretchCheckBox.UseVisualStyleBackColor = true; // // ConfigurationDialog // @@ -423,5 +435,6 @@ namespace D.UI private System.Windows.Forms.RadioButton NoTimeDateChangeRadioButton; private System.Windows.Forms.DateTimePicker TODDatePicker; private System.Windows.Forms.RadioButton SpecifiedDateRadioButton; + private System.Windows.Forms.CheckBox FullScreenStretchCheckBox; } } \ No newline at end of file diff --git a/D/UI/ConfigurationDialog.cs b/D/UI/ConfigurationDialog.cs index 756c2f3..fb690de 100644 --- a/D/UI/ConfigurationDialog.cs +++ b/D/UI/ConfigurationDialog.cs @@ -51,6 +51,7 @@ namespace D.UI public bool SlowPhosphor; public uint DisplayScale; + public bool FullScreenStretch; public TODPowerUpSetMode TODSetMode; public DateTime TODDateTime; @@ -86,7 +87,8 @@ namespace D.UI } } - SlowPhosphorCheckBox.Checked = SlowPhosphor; + SlowPhosphorCheckBox.Checked = SlowPhosphor; + FullScreenStretchCheckBox.Checked = FullScreenStretch; // Time Tab switch (TODSetMode) @@ -223,6 +225,7 @@ namespace D.UI { ThrottleSpeed = ThrottleSpeedCheckBox.Checked; SlowPhosphor = SlowPhosphorCheckBox.Checked; + FullScreenStretch = FullScreenStretchCheckBox.Checked; HostPacketInterfaceName = ((EthernetInterface)EthernetInterfaceListBox.SelectedItem).Name; diff --git a/D/UI/DWindow-IO.cs b/D/UI/DWindow-IO.cs index 72c4398..c7f2aaf 100644 --- a/D/UI/DWindow-IO.cs +++ b/D/UI/DWindow-IO.cs @@ -54,7 +54,8 @@ namespace D.UI public partial class DWindow : Form { private void InitializeIO() - { + { + _textureLock = new ReaderWriterLockSlim(); UpdateDisplayScale(); UpdateSlowPhosphor(); @@ -147,6 +148,8 @@ namespace D.UI // // Stuff the display data into the display texture // + + _textureLock.EnterReadLock(); IntPtr textureBits = IntPtr.Zero; int pitch = 0; SDL.SDL_LockTexture(_displayTexture, IntPtr.Zero, out textureBits, out pitch); @@ -164,6 +167,7 @@ namespace D.UI // And show it to us. // SDL.SDL_RenderPresent(_sdlRenderer); + _textureLock.ExitReadLock(); } private void SDLMessageLoopThread() @@ -1016,6 +1020,21 @@ namespace D.UI } } + CreateDisplayTexture(false); + + SDL.SDL_SetRenderDrawColor(_sdlRenderer, 0x00, 0x00, 0x00, 0xff); + + // Register a User event for rendering. + _renderEventType = SDL.SDL_RegisterEvents(1); + _renderEvent = new SDL.SDL_Event(); + _renderEvent.type = (SDL.SDL_EventType)_renderEventType; + } + + private void CreateDisplayTexture(bool filter) + { + _textureLock.EnterWriteLock(); + SDL.SDL_SetHint(SDL.SDL_HINT_RENDER_SCALE_QUALITY, filter ? "linear" : "nearest"); + _displayTexture = SDL.SDL_CreateTexture( _sdlRenderer, SDL.SDL_PIXELFORMAT_ARGB8888, @@ -1029,12 +1048,7 @@ namespace D.UI } SDL.SDL_SetTextureBlendMode(_displayTexture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); - SDL.SDL_SetRenderDrawColor(_sdlRenderer, 0x00, 0x00, 0x00, 0xff); - - // Register a User event for rendering. - _renderEventType = SDL.SDL_RegisterEvents(1); - _renderEvent = new SDL.SDL_Event(); - _renderEvent.type = (SDL.SDL_EventType)_renderEventType; + _textureLock.ExitWriteLock(); } private void ToggleFullScreen(bool fullScreen) @@ -1050,15 +1064,23 @@ namespace D.UI this.WindowState = FormWindowState.Maximized; this.BackColor = Color.Black; DisplayBox.Dock = DockStyle.None; + _windowedUIPanelLocation = UIPanel.Location; + UIPanel.Location = new Point(0, 0); // Select scale based on aspect ratio of screen. if (this.Width < this.Height) { - _displayScale = Math.Floor((double)this.Width / (double)_displayWidth); + _displayScale = (double)this.Width / (double)_displayWidth; } else { - _displayScale = Math.Floor((double)this.Height / (double)_displayHeight); + _displayScale = (double)this.Height / (double)_displayHeight; + } + + if (!Configuration.FullScreenStretch) + { + // Take floor of scale so that the display fits. + _displayScale = Math.Floor(_displayScale); } // Scale the DisplayBox @@ -1076,6 +1098,8 @@ namespace D.UI CaptureMouse(); + CreateDisplayTexture(Configuration.FullScreenStretch); + // Force a display render to clean up garbage. Render(); } @@ -1089,12 +1113,16 @@ namespace D.UI this.BackColor = SystemColors.Window; DisplayBox.Dock = DockStyle.Fill; + UIPanel.Location = _windowedUIPanelLocation; + _displayScale = Configuration.DisplayScale; UpdateDisplayScale(); ResumeLayout(); PerformLayout(); + CreateDisplayTexture(false); + // Force a display render to clean up garbage. Render(); } @@ -1126,6 +1154,7 @@ namespace D.UI private double _displayScale; private int _frameCount; private bool _fullScreenDisplay; + private Point _windowedUIPanelLocation; // // Keyboard data @@ -1155,5 +1184,6 @@ namespace D.UI // Rendering textures private IntPtr _displayTexture = IntPtr.Zero; + private ReaderWriterLockSlim _textureLock; } } diff --git a/D/UI/DWindow.cs b/D/UI/DWindow.cs index bd3926d..a59506f 100644 --- a/D/UI/DWindow.cs +++ b/D/UI/DWindow.cs @@ -290,6 +290,7 @@ namespace D.UI configDialog.HostPacketInterfaceName = Configuration.HostPacketInterfaceName; configDialog.ThrottleSpeed = Configuration.ThrottleSpeed; configDialog.DisplayScale = Configuration.DisplayScale; + configDialog.FullScreenStretch = Configuration.FullScreenStretch; configDialog.SlowPhosphor = Configuration.SlowPhosphor; configDialog.TODDateTime = Configuration.TODDateTime; configDialog.TODDate = Configuration.TODDate; @@ -335,10 +336,11 @@ namespace D.UI } } - Configuration.MemorySize = configDialog.MemorySize; + Configuration.MemorySize = configDialog.MemorySize; Configuration.ThrottleSpeed = configDialog.ThrottleSpeed; Configuration.DisplayScale = configDialog.DisplayScale; Configuration.SlowPhosphor = configDialog.SlowPhosphor; + Configuration.FullScreenStretch = configDialog.FullScreenStretch; Configuration.TODDateTime = configDialog.TODDateTime; Configuration.TODDate = configDialog.TODDate; Configuration.TODSetMode = configDialog.TODSetMode;