feat(display): скорость водопада с max-hold накоплением + MSAA спектра

- настройка Speed (wf_speed_div 1/2/4/8, Waterfall→Rendering): замедление
  накапливает кадры max-hold'ом в SetWaterfallData — короткие посылки (CW)
  не выпадают из строки; двойная децимация MainForm убрана
  (EffectiveWfInterval, CPU-путь не быстрее полукадровой)
- настройка Anti-aliasing (spec_msaa 1/2/4/8, дефолт 4x, Spectrum→Rendering):
  MultiSampling на GL-контроле спектра; смена в рантайме пересоздаёт
  контекст → ResetGLCache обнуляет текстурные кэши без glDelete

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 16:48:55 +03:00
co-authored by Claude Fable 5
parent 092a202f5f
commit e260995218
6 changed files with 164 additions and 35 deletions
+60 -6
View File
@@ -48,7 +48,8 @@ type
TOnWaterfallParamChange = procedure(WfDetector, WfAvgMode: Integer;
WfAvgTimeMS, WfHigh, WfLow, WfAGCOffset: Double) of object;
TOnWfRenderChange = procedure(Palette: Integer; Gamma: Double;
ResLimit: Integer) of object;
ResLimit, SpeedDiv: Integer) of object;
TOnSpecMSAAChange = procedure(Samples: Integer) of object;
TOnGridParamChange = procedure(RefLevel, Range, GridStep: Double) of object;
TOnAudioDevChange = procedure(DevIndex: Integer; const DevName: string) of object;
TOnAudioInDevChange = procedure(DevIndex: Integer; const DevName: string) of object;
@@ -124,6 +125,8 @@ type
FCmbWfPalette: TFlatComboBox;
FWfGamma: TFlatFloatSpinEdit;
FCmbWfRes: TFlatComboBox;
FCmbWfSpeed: TFlatComboBox;
FCmbSpecMSAA: TFlatComboBox;
FEdRefLevel: TFlatEdit;
FEdRange: TFlatEdit;
FCmbGridStep: TFlatComboBox;
@@ -295,6 +298,7 @@ type
FOnDisplayChange: TOnDisplayParamChange;
FOnWaterfallChange: TOnWaterfallParamChange;
FOnWfRenderChange: TOnWfRenderChange;
FOnSpecMSAAChange: TOnSpecMSAAChange;
FOnGridChange: TOnGridParamChange;
FOnAudioDevChange: TOnAudioDevChange;
FOnAudioInDevChange: TOnAudioInDevChange;
@@ -386,6 +390,7 @@ type
procedure FireWaterfallChange;
procedure FireWfRenderChange;
procedure OnWfRenderCtlChange(Sender: TObject);
procedure OnSpecMSAACtlChange(Sender: TObject);
procedure FireGridChange;
function GetSpecAvgTimeMS: Double;
@@ -431,7 +436,9 @@ type
procedure LoadAlexSettings(const A: TAlexSettings; BoardType: Integer);
procedure LoadXvtrSettings(const X: TXvtrSettings);
procedure LoadWfAGCNF(AGC, NF: Boolean);
procedure LoadWfRender(Palette: Integer; Gamma: Double; ResLimit: Integer);
procedure LoadWfRender(Palette: Integer; Gamma: Double;
ResLimit, SpeedDiv: Integer);
procedure LoadSpecMSAA(Samples: Integer);
procedure LoadADCSettings(Dither, Random: Boolean);
procedure LoadWebSettings(Enabled: Boolean; Port: Integer;
const BindAddr, User, Pass: string);
@@ -445,6 +452,7 @@ type
property OnDisplayChange: TOnDisplayParamChange read FOnDisplayChange write FOnDisplayChange;
property OnWaterfallChange: TOnWaterfallParamChange read FOnWaterfallChange write FOnWaterfallChange;
property OnWfRenderChange: TOnWfRenderChange read FOnWfRenderChange write FOnWfRenderChange;
property OnSpecMSAAChange: TOnSpecMSAAChange read FOnSpecMSAAChange write FOnSpecMSAAChange;
property OnGridChange: TOnGridParamChange read FOnGridChange write FOnGridChange;
property OnAudioDevChange: TOnAudioDevChange read FOnAudioDevChange write FOnAudioDevChange;
property OnAudioInDevChange: TOnAudioInDevChange read FOnAudioInDevChange write FOnAudioInDevChange;
@@ -505,6 +513,10 @@ const
WF_PALETTE_NAMES: array[0..2] of string = ('Classic', 'Inferno', 'Turbo');
DISPLAY_RES_VALUES: array[0..2] of Integer = (1024, 2048, 4096);
DISPLAY_RES_NAMES: array[0..2] of string = ('1024 px', '2048 px', '4096 px');
WF_SPEED_VALUES: array[0..3] of Integer = (1, 2, 4, 8);
WF_SPEED_NAMES: array[0..3] of string = ('Full rate', '1/2', '1/4', '1/8');
MSAA_VALUES: array[0..3] of Integer = (1, 2, 4, 8);
MSAA_NAMES: array[0..3] of string = ('Off', '2x', '4x', '8x');
FPS_VALUES: array[0..12] of Integer = (5, 10, 15, 20, 25, 30, 40, 50, 60, 75, 80, 90, 100);
FPS_NAMES: array[0..12] of string = ('5 fps','10 fps','15 fps','20 fps','25 fps','30 fps',
@@ -1039,6 +1051,13 @@ begin
MakeLbl(Grp, 'Avg Time (ms):', PAD, R1 + 2 * STEP + 5, LW);
FSpecAvgTime := MkFloat(CX, R1 + 2 * STEP, SPW, 30.0, 0.0, 5000.0, 10.0, OnSpecAvgTimeChange);
Grp := MakeGroupPanel(FPageSpectrum, 'Rendering', MARGIN, 602, 650, 128);
MakeLbl(Grp, 'Anti-aliasing:', PAD, R1 + 5, LW);
FCmbSpecMSAA := MakeCombo(Grp, CX, R1, 130, OnSpecMSAACtlChange);
for i := 0 to High(MSAA_NAMES) do FCmbSpecMSAA.Items.Add(MSAA_NAMES[i]);
FCmbSpecMSAA.ItemIndex := 2; // 4x
MakeLbl(Grp, '(GL spectrum curve smoothing, MSAA)', CX + 140, R1 + 5, 300);
Grp := MakeGroupPanel(FPageSpectrum, 'Grid', MARGIN, 416, 650, 170);
MakeLbl(Grp, 'Reference level:', PAD, R1 + 5, LW);
FEdRefLevel := MkEdit(CX, R1, EDT_W, '-20', OnRefLevelChange);
@@ -1108,7 +1127,7 @@ begin
FChkWfNF.Font.Size := 9;
FChkWfNF.OnChange := OnWfAGCNFChkChange;
Grp := MakeGroupPanel(FPageWaterfall, 'Rendering', MARGIN, 614, 650, 170);
Grp := MakeGroupPanel(FPageWaterfall, 'Rendering', MARGIN, 614, 650, 212);
MakeLbl(Grp, 'Palette:', PAD, R1 + 5, LW);
FCmbWfPalette := MakeCombo(Grp, CX, R1, CMB_W, OnWfRenderCtlChange);
for i := 0 to High(WF_PALETTE_NAMES) do FCmbWfPalette.Items.Add(WF_PALETTE_NAMES[i]);
@@ -1120,6 +1139,10 @@ begin
FCmbWfRes := MakeCombo(Grp, CX, R1 + 2 * STEP, 130, OnWfRenderCtlChange);
for i := 0 to High(DISPLAY_RES_NAMES) do FCmbWfRes.Items.Add(DISPLAY_RES_NAMES[i]);
FCmbWfRes.ItemIndex := High(DISPLAY_RES_NAMES);
MakeLbl(Grp, 'Speed:', PAD, R1 + 3 * STEP + 5, LW);
FCmbWfSpeed := MakeCombo(Grp, CX, R1 + 3 * STEP, 130, OnWfRenderCtlChange);
for i := 0 to High(WF_SPEED_NAMES) do FCmbWfSpeed.Items.Add(WF_SPEED_NAMES[i]);
FCmbWfSpeed.ItemIndex := 0;
end;
// ---------------------------------------------------------------------------
@@ -2339,7 +2362,7 @@ end;
procedure TSettingsForm.FireWfRenderChange;
var
ResV: Integer;
ResV, SpeedV: Integer;
begin
if FLoading then Exit;
if not Assigned(FOnWfRenderChange) then Exit;
@@ -2347,13 +2370,26 @@ begin
ResV := DISPLAY_RES_VALUES[FCmbWfRes.ItemIndex]
else
ResV := DISPLAY_RES_VALUES[High(DISPLAY_RES_VALUES)];
FOnWfRenderChange(Max(0, FCmbWfPalette.ItemIndex), FWfGamma.Value, ResV);
if (FCmbWfSpeed.ItemIndex >= 0) and (FCmbWfSpeed.ItemIndex <= High(WF_SPEED_VALUES)) then
SpeedV := WF_SPEED_VALUES[FCmbWfSpeed.ItemIndex]
else
SpeedV := 1;
FOnWfRenderChange(Max(0, FCmbWfPalette.ItemIndex), FWfGamma.Value, ResV, SpeedV);
end;
procedure TSettingsForm.OnWfRenderCtlChange(Sender: TObject);
begin FireWfRenderChange; end;
procedure TSettingsForm.LoadWfRender(Palette: Integer; Gamma: Double; ResLimit: Integer);
procedure TSettingsForm.OnSpecMSAACtlChange(Sender: TObject);
begin
if FLoading then Exit;
if not Assigned(FOnSpecMSAAChange) then Exit;
if (FCmbSpecMSAA.ItemIndex >= 0) and (FCmbSpecMSAA.ItemIndex <= High(MSAA_VALUES)) then
FOnSpecMSAAChange(MSAA_VALUES[FCmbSpecMSAA.ItemIndex]);
end;
procedure TSettingsForm.LoadWfRender(Palette: Integer; Gamma: Double;
ResLimit, SpeedDiv: Integer);
var i: Integer;
begin
FLoading := True;
@@ -2367,6 +2403,24 @@ begin
for i := 0 to High(DISPLAY_RES_VALUES) do
if DISPLAY_RES_VALUES[i] = ResLimit then
begin FCmbWfRes.ItemIndex := i; Break; end;
FCmbWfSpeed.ItemIndex := 0;
for i := 0 to High(WF_SPEED_VALUES) do
if WF_SPEED_VALUES[i] = SpeedDiv then
begin FCmbWfSpeed.ItemIndex := i; Break; end;
finally
FLoading := False;
end;
end;
procedure TSettingsForm.LoadSpecMSAA(Samples: Integer);
var i: Integer;
begin
FLoading := True;
try
FCmbSpecMSAA.ItemIndex := 0;
for i := 0 to High(MSAA_VALUES) do
if MSAA_VALUES[i] = Samples then
begin FCmbSpecMSAA.ItemIndex := i; Break; end;
finally
FLoading := False;
end;