Decouple rendering from data processing with timer-based display
Data parsing (ProcessChar) is now purely memory operations. EndUpdate and ParseData set FRenderPending instead of calling FlipToScreen. A 55ms timer (~18 Hz, matching Win16 tick resolution) drives rendering: dirty rows are painted and BitBlt'd to screen only on timer ticks. Blink toggles every 9 ticks (~500ms). This prevents high-throughput data (door games, file transfers) from saturating the CPU with GDI calls — between timer ticks, data just accumulates in cell buffers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a96dbb3faa
commit
c565be8489
1 changed files with 26 additions and 37 deletions
|
|
@ -62,6 +62,8 @@ type
|
||||||
FPaintFont: HFont;
|
FPaintFont: HFont;
|
||||||
FStockFont: Boolean;
|
FStockFont: Boolean;
|
||||||
FBlinkPhase: Integer;
|
FBlinkPhase: Integer;
|
||||||
|
FBlinkCount: Integer;
|
||||||
|
FRenderPending: Boolean;
|
||||||
FUpdateCount: Integer;
|
FUpdateCount: Integer;
|
||||||
FDirtyRow: array[0..255] of Boolean;
|
FDirtyRow: array[0..255] of Boolean;
|
||||||
FAllDirty: Boolean;
|
FAllDirty: Boolean;
|
||||||
|
|
@ -163,7 +165,10 @@ const
|
||||||
$00FFFFFF { 15 White (bright) }
|
$00FFFFFF { 15 White (bright) }
|
||||||
);
|
);
|
||||||
|
|
||||||
CursorBlinkMs = 500;
|
{ Timer fires at ~18 Hz (Win16 tick resolution is ~55 ms). }
|
||||||
|
{ Cursor and text blink toggle every 9 ticks (~500 ms). }
|
||||||
|
RenderTickMs = 55;
|
||||||
|
BlinkInterval = 9;
|
||||||
|
|
||||||
{ OUT_RASTER_PRECIS may not be defined in Delphi 1.0 WinTypes }
|
{ OUT_RASTER_PRECIS may not be defined in Delphi 1.0 WinTypes }
|
||||||
OutRasterPrecis = 6;
|
OutRasterPrecis = 6;
|
||||||
|
|
@ -334,6 +339,8 @@ begin
|
||||||
FPaintFont := 0;
|
FPaintFont := 0;
|
||||||
FStockFont := False;
|
FStockFont := False;
|
||||||
FBlinkPhase := 0;
|
FBlinkPhase := 0;
|
||||||
|
FBlinkCount := 0;
|
||||||
|
FRenderPending := False;
|
||||||
FUpdateCount := 0;
|
FUpdateCount := 0;
|
||||||
FAllDirty := True;
|
FAllDirty := True;
|
||||||
FBufDC[0] := 0;
|
FBufDC[0] := 0;
|
||||||
|
|
@ -875,7 +882,7 @@ begin
|
||||||
if FUpdateCount <= 0 then
|
if FUpdateCount <= 0 then
|
||||||
begin
|
begin
|
||||||
FUpdateCount := 0;
|
FUpdateCount := 0;
|
||||||
FlipToScreen;
|
FRenderPending := True;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -1539,7 +1546,7 @@ begin
|
||||||
FBlinkOn := True;
|
FBlinkOn := True;
|
||||||
|
|
||||||
if FUpdateCount = 0 then
|
if FUpdateCount = 0 then
|
||||||
FlipToScreen;
|
FRenderPending := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1827,10 +1834,10 @@ begin
|
||||||
CreateBuffers;
|
CreateBuffers;
|
||||||
FAllDirty := True;
|
FAllDirty := True;
|
||||||
|
|
||||||
{ Start cursor blink timer }
|
{ Start render/blink timer }
|
||||||
if not FTimerActive then
|
if not FTimerActive then
|
||||||
begin
|
begin
|
||||||
SetTimer(Handle, 1, CursorBlinkMs, nil);
|
SetTimer(Handle, 1, RenderTickMs, nil);
|
||||||
FTimerActive := True;
|
FTimerActive := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -1976,43 +1983,25 @@ end;
|
||||||
|
|
||||||
procedure TKPAnsi.WMTimer(var Msg: TWMTimer);
|
procedure TKPAnsi.WMTimer(var Msg: TWMTimer);
|
||||||
var
|
var
|
||||||
DC: HDC;
|
NeedFlip: Boolean;
|
||||||
Line: PTermLine;
|
|
||||||
X: Integer;
|
|
||||||
Y: Integer;
|
|
||||||
begin
|
begin
|
||||||
FBlinkOn := not FBlinkOn;
|
NeedFlip := FRenderPending;
|
||||||
|
FRenderPending := False;
|
||||||
|
|
||||||
{ Toggle text blink phase by swapping which buffer is displayed. }
|
{ Blink counter: toggle cursor and text blink every BlinkInterval ticks }
|
||||||
{ Buffers are already up-to-date; just BitBlt the other one. }
|
Inc(FBlinkCount);
|
||||||
|
if FBlinkCount >= BlinkInterval then
|
||||||
|
begin
|
||||||
|
FBlinkCount := 0;
|
||||||
|
FBlinkOn := not FBlinkOn;
|
||||||
Inc(FBlinkPhase);
|
Inc(FBlinkPhase);
|
||||||
if FBlinkPhase > 1 then
|
if FBlinkPhase > 1 then
|
||||||
FBlinkPhase := 0;
|
FBlinkPhase := 0;
|
||||||
|
NeedFlip := True;
|
||||||
if not HandleAllocated then
|
|
||||||
Exit;
|
|
||||||
if FBufDC[0] = 0 then
|
|
||||||
Exit;
|
|
||||||
|
|
||||||
DC := GetDC(Handle);
|
|
||||||
BitBlt(DC, 0, 0, FBufW, FBufH,
|
|
||||||
FBufDC[FBlinkPhase], 0, 0, SRCCOPY);
|
|
||||||
|
|
||||||
{ Cursor overlay }
|
|
||||||
if FCursorVisible and FBlinkOn and (FScrollPos = 0) and
|
|
||||||
(FCursorRow >= 0) and (FCursorRow < FRows) and
|
|
||||||
(FCursorRow < FScreen.Count) and
|
|
||||||
(FCursorCol >= 0) and (FCursorCol < FCols) then
|
|
||||||
begin
|
|
||||||
Line := FScreen[FCursorRow];
|
|
||||||
X := FCursorCol * FCellWidth;
|
|
||||||
Y := FCursorRow * FCellHeight;
|
|
||||||
SetTextColor(DC, ColorToRGB(Line^.Cells[FCursorCol].BG));
|
|
||||||
SetBkColor(DC, ColorToRGB(Line^.Cells[FCursorCol].FG));
|
|
||||||
WinProcs.TextOut(DC, X, Y, @Line^.Cells[FCursorCol].Ch, 1);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ReleaseDC(Handle, DC);
|
if NeedFlip then
|
||||||
|
FlipToScreen;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue