Optimize CPU waterfall/spectrum rendering

WaterfallView: drop per-frame TLazIntfImage + LoadFromIntfImage (device
bitmap recreation + full pixel-format conversion every frame). Write
pixels directly into the bitmap via BeginUpdate/ScanLine like
SpectrumView already does, with platform-native byte order (ARGB on
Cocoa, BGRA elsewhere).

Replace per-pixel float colorization with a 512-entry dB->color LUT
rebuilt only when WfLow/WfHigh/theme change beyond a small threshold.

Turn the bitmap itself into a ring buffer: each frame builds a single
new row and writes one ScanLine; scrolling is done at paint time via two
CopyRect calls. Removes both full-frame passes per frame (image memmove
+ buffer->bitmap copy), cutting per-frame cost from O(W*H) to O(W). TX
mode preserved by leaving out-of-span columns untouched in the row buf.

SpectrumView: rewrite the per-frame alpha-restore pass from a strided
per-byte loop to a sequential per-dword OR with the alpha mask
(bit-identical output, sequential memory access).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Uladzimir Karpenka
2026-05-29 14:21:40 +03:00
co-authored by Claude Opus 4.8
parent 16259ed704
commit 55d5bf01cf
2 changed files with 126 additions and 83 deletions
+13 -8
View File
@@ -722,7 +722,8 @@ procedure TSpectrumView.DrawSpectrum;
var
C, GC: TCanvas;
i, Yp, W, H, GX: Integer;
AlphaPtr: PByte;
RowLW: PLongWord;
AMask: LongWord;
DBmin, DBmax, dB: Double;
VfoX, X1, X2: Integer;
TXVfoX, TXX1, TXX2: Integer;
@@ -930,18 +931,22 @@ begin
if Assigned(FVfoOverlay) then
FVfoOverlay.DrawOverlay(FSpectrumBitmap, W, H);
// Восстанавливаем непрозрачность: Canvas-операции (текст/линии со сглаживанием)
// могли занулить альфу. OR маской выставляет альфу в $FF, RGB не меняя.
{$IFDEF DARWIN}
AMask := $000000FF; // ARGB: альфа в байте 0
{$ELSE}
AMask := $FF000000; // BGRA: альфа в байте 3
{$ENDIF}
FSpectrumBitmap.BeginUpdate(False);
for i := 0 to H - 1 do
begin
{$IFDEF DARWIN}
AlphaPtr := PByte(FSpectrumBitmap.ScanLine[i]); // ARGB: alpha at byte 0
{$ELSE}
AlphaPtr := PByte(FSpectrumBitmap.ScanLine[i]) + 3; // BGRA: alpha at byte 3
{$ENDIF}
RowLW := PLongWord(FSpectrumBitmap.ScanLine[i]);
if RowLW = nil then Continue;
for Yp := 0 to W - 1 do
begin
AlphaPtr^ := $FF;
Inc(AlphaPtr, 4);
RowLW^ := RowLW^ or AMask;
Inc(RowLW);
end;
end;
FSpectrumBitmap.EndUpdate(False);