progress: ImGui Port - Desktop UI + ImGui rendering performance overhaul

Full ImGui desktop environment (desktop.pas):
- Gradient wallpaper, taskbar with clock, start menu
- Desktop icons with click-to-open
- Windowed apps: System Info, Terminal, File Browser, Task Manager
- Terminal dispatches to registered kernel commands with output capture

Performance: Software rasterizer rewrite (imgui.pas, imgbridge.c)
- Quad detection: merge consecutive triangle pairs into fast rect fills
- 3 new fast-path rect fillers (solid/gradient/textured) using REP STOSD
  and 16.16 fixed-point integer inner loops
- Triangle rasterizer rewritten with fixed-point edge functions
- Back-buffer clear: DrawPixel loop -> REP STOSD (~200x faster)
- Render stat debug counters added

ISR-safe input buffering (imgbridge.c)
- Keyboard/mouse events buffered in lock-free ring buffers from ISR context
- Drained once per frame from main loop to prevent data races

Other changes:
- imguitypes.pas: InputTextFlags renumbered for cimgui 1.91+
- video.pas: backBufferLocation getter added
- kernel.pas: VFS init moved earlier, main loop uses desktop_frame,
  mouse hook uses ISR-safe buffering
- lmemorymanager.pas: kalloc/kfree exported with public aliases for C linkage
- scheduler.pas: Root_Task moved to interface for desktop task manager
- terminal.pas: freeParams exposed in interface
This commit is contained in:
t3hn3rd committed 2026-02-25 23:28:12 +00:00
1 parent 51a29244ed
commit aac376fa22
13 files changed
+2362 -128

No files matched your search

+45
View File
@@ -838,6 +838,18 @@ const
MAX_WINDOWS = 255; //< Maximum number of Windows open.
DefaultWND = 0; //< The Window assigned for output when no Window is specified. (Default).
type
TWNDCaptureCallback = procedure(s: pchar);
var
WND_CaptureActive : boolean = false;
WND_CaptureHWND : uint32 = 0;
WND_CaptureBuf : array[0..511] of char;
WND_CaptureBufIdx : uint32 = 0;
WND_CaptureCallback : TWNDCaptureCallback = nil;
procedure flushCapture;
implementation
uses
@@ -2259,6 +2271,7 @@ var
x,y: Byte;
begin
if WND_CaptureActive and (WND = WND_CaptureHWND) then exit;
if WindowManager.Windows[WND] <> nil then begin
for y:=0 to Console_Properties.MAX_CELL_Y do begin
for x:=0 to Console_Properties.MAX_CELL_X do begin
@@ -2419,8 +2432,26 @@ begin
console.writeintlnexWND(i, Console_Properties.Default_Attribute, WND);
end;
procedure flushCapture;
begin
if WND_CaptureActive and (WND_CaptureCallback <> nil) and (WND_CaptureBufIdx > 0) then begin
WND_CaptureBuf[WND_CaptureBufIdx] := #0;
WND_CaptureCallback(@WND_CaptureBuf[0]);
WND_CaptureBufIdx := 0;
WND_CaptureBuf[0] := #0;
end;
end;
procedure writecharexWND(character: char; attributes: uint32; WND : uint32);
begin
if WND_CaptureActive and (WND = WND_CaptureHWND) and (WND_CaptureCallback <> nil) then begin
if WND_CaptureBufIdx < 511 then begin
WND_CaptureBuf[WND_CaptureBufIdx] := character;
inc(WND_CaptureBufIdx);
WND_CaptureBuf[WND_CaptureBufIdx] := #0;
end;
exit;
end;
if WindowManager.Windows[WND] <> nil then begin
WindowManager.Windows[WND]^.Buffer[WindowManager.Windows[WND]^.Cursor.Y][WindowManager.Windows[WND]^.Cursor.X].Character:= character;
WindowManager.Windows[WND]^.Buffer[WindowManager.Windows[WND]^.Cursor.Y][WindowManager.Windows[WND]^.Cursor.X].Attributes:= attributes;
@@ -2603,6 +2634,13 @@ end;
procedure backspaceWND(WND : uint32);
begin
if WND_CaptureActive and (WND = WND_CaptureHWND) then begin
if WND_CaptureBufIdx > 0 then begin
dec(WND_CaptureBufIdx);
WND_CaptureBuf[WND_CaptureBufIdx] := #0;
end;
exit;
end;
if WindowManager.Windows[WND] <> nil then begin
Dec(WindowManager.Windows[WND]^.Cursor.X);
writecharWND(' ', WND);
@@ -2659,6 +2697,13 @@ end;
procedure _safeincrement_y_WND(WND : uint32);
begin
if WND_CaptureActive and (WND = WND_CaptureHWND) and (WND_CaptureCallback <> nil) then begin
WND_CaptureBuf[WND_CaptureBufIdx] := #0;
WND_CaptureCallback(@WND_CaptureBuf[0]);
WND_CaptureBufIdx := 0;
WND_CaptureBuf[0] := #0;
exit;
end;
if WindowManager.Windows[WND] <> nil then begin
WindowManager.Windows[WND]^.Cursor.Y:= WindowManager.Windows[WND]^.Cursor.Y+1;
if WindowManager.Windows[WND]^.Cursor.Y > WindowManager.Windows[WND]^.WND_H-1 then begin
+15 -1
View File
@@ -92,6 +92,7 @@ var
Root : PVFSObject;
CurrentDirectory : pchar = nil;
PushPopDirectory : PLinkedListBase;
MountDepth : uint32 = 0;
procedure init();
Function OpenFile(Filename : pchar; OpenMode : TOpenMode; WriteMode : TWriteMode; Lock : Boolean; Error : PError) : TFileHandle;
@@ -104,6 +105,7 @@ function GetDirectories(Handle : uint32; Path : pchar) : PHashMap;
function PathValid(Path : pchar) : TIsPathValid;
function changeDirectory(Path : pchar) : TIsPathValid;
function getWorkingDirectory : pchar;
function GetDirectoryListing(Path : pchar) : PHashMap;
//VFS Functions
function newVirtualDirectory(Path : pchar) : TError;
@@ -288,6 +290,7 @@ begin
NewObj:= PVFSObject(hashmap.get(ht, item));
if NewObj = nil then begin
GetObjectFromPath:= nil;
STRLL_Free(SplitPath);
tracer.push_trace('vfs.GetObjectFromPath.shortexit_1');
exit;
end;
@@ -304,6 +307,7 @@ begin
end;
end;
GetObjectFromPath:= Obj;
STRLL_Free(SplitPath);
tracer.push_trace('vfs.GetObjectFromPath.exit');
end;
@@ -348,7 +352,17 @@ begin
GetDirectoryListing:= nil;
end;
otMOUNT:begin
{ Safety: cap mount-follow depth to prevent infinite recursion
from circular mounts. Use a simple static counter. }
if MountDepth < 16 then begin
Inc(MountDepth);
GetDirectoryListing:= GetDirectoryListing(PVFSMount(Obj^.Reference)^.Path);
Dec(MountDepth);
end else
GetDirectoryListing:= nil;
end;
else begin
GetDirectoryListing:= nil;
end;
end;
end else begin
@@ -420,7 +434,7 @@ begin
NewObj^.Reference:= void(NewDev);
hashmap.add(ht, stringCopy(DeviceName), void(NewDev));
hashmap.add(ht, stringCopy(DeviceName), void(NewObj));
end;
{ Filesystem Functions }
+27 -11
View File
@@ -54,13 +54,8 @@ end;
procedure Flush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer);
var
idx : uint32;
Back,Front : uint32;
BufferSize : uint32;
const
//COPY_WIDTH = 64; //Use this for 64bit copies
COPY_WIDTH = 128; //Use this for SSE copies
Count64 : uint32;
begin
//tracer.push_trace('doublebuffer.Flush.enter');
@@ -68,11 +63,32 @@ begin
if ((FrontBuffer^.Width > BackBuffer^.Width) or (FrontBuffer^.Height > BackBuffer^.Height)) then exit;
Back:= BackBuffer^.Location;
Front:= FrontBuffer^.Location;
BufferSize:= ( ( BackBuffer^.Width * BackBuffer^.Height * BackBuffer^.BitsPerPixel) div COPY_WIDTH ) - 1;
for idx:=0 to BufferSize do begin
//Front[idx]:= Back[idx];
// -- TODO: Get SSE working here for 128bit copies --
__SSE_128_memcpy(Back + (idx * 16), Front + (idx * 16));
{ Number of 64-byte blocks: total_bytes / 64 = (W * H * BPP/8) / 64 }
Count64:= ( BackBuffer^.Width * BackBuffer^.Height * BackBuffer^.BitsPerPixel) div 512;
if Count64 = 0 then exit;
{ Bulk SSE copy: 4 x MOVAPS (64 bytes) per iteration.
4x fewer loop iterations than the old per-16-byte function-call loop. }
asm
PUSH ESI
PUSH EDI
MOV ESI, Back
MOV EDI, Front
MOV ECX, Count64
@sseloop:
MOVAPS XMM0, [ESI]
MOVAPS XMM1, [ESI + 16]
MOVAPS XMM2, [ESI + 32]
MOVAPS XMM3, [ESI + 48]
MOVAPS [EDI], XMM0
MOVAPS [EDI + 16], XMM1
MOVAPS [EDI + 32], XMM2
MOVAPS [EDI + 48], XMM3
ADD ESI, 64
ADD EDI, 64
DEC ECX
JNZ @sseloop
POP EDI
POP ESI
end;
//tracer.push_trace('doublebuffer.Flush.exit');
end;
+6 -4
View File
@@ -125,9 +125,11 @@ char* strcpy(char* dst, const char* src) {
}
char* strncpy(char* dst, const char* src, size_t n) {
char* d = dst;
while (n-- && (*d++ = *src++));
while (n--) *d++ = '\0';
size_t i;
for (i = 0; i < n && src[i] != '\0'; i++)
dst[i] = src[i];
for (; i < n; i++)
dst[i] = '\0';
return dst;
}
@@ -150,8 +152,8 @@ int strcmp(const char* a, const char* b) {
}
int strncmp(const char* a, const char* b, size_t n) {
while (n-- && *a && (*a == *b)) { a++; b++; }
if (!n) return 0;
while (--n && *a && (*a == *b)) { a++; b++; }
return (unsigned char)*a - (unsigned char)*b;
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+24 -18
View File
@@ -137,27 +137,33 @@ const
============================================================ }
const
ImGuiInputTextFlags_None = 0;
{ Character filters }
ImGuiInputTextFlags_CharsDecimal = 1 SHL 0;
ImGuiInputTextFlags_CharsHexadecimal = 1 SHL 1;
ImGuiInputTextFlags_CharsUppercase = 1 SHL 2;
ImGuiInputTextFlags_CharsNoBlank = 1 SHL 3;
ImGuiInputTextFlags_AutoSelectAll = 1 SHL 4;
ImGuiInputTextFlags_EnterReturnsTrue = 1 SHL 5;
ImGuiInputTextFlags_CallbackCompletion = 1 SHL 6;
ImGuiInputTextFlags_CallbackHistory = 1 SHL 7;
ImGuiInputTextFlags_CallbackAlways = 1 SHL 8;
ImGuiInputTextFlags_CallbackCharFilter = 1 SHL 9;
ImGuiInputTextFlags_AllowTabInput = 1 SHL 10;
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 SHL 11;
ImGuiInputTextFlags_NoHorizontalScroll = 1 SHL 12;
ImGuiInputTextFlags_AlwaysOverwrite = 1 SHL 13;
ImGuiInputTextFlags_ReadOnly = 1 SHL 14;
ImGuiInputTextFlags_Password = 1 SHL 15;
ImGuiInputTextFlags_CharsScientific = 1 SHL 2;
ImGuiInputTextFlags_CharsUppercase = 1 SHL 3;
ImGuiInputTextFlags_CharsNoBlank = 1 SHL 4;
{ Inputs }
ImGuiInputTextFlags_AllowTabInput = 1 SHL 5;
ImGuiInputTextFlags_EnterReturnsTrue = 1 SHL 6;
ImGuiInputTextFlags_EscapeClearsAll = 1 SHL 7;
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 SHL 8;
{ Other options }
ImGuiInputTextFlags_ReadOnly = 1 SHL 9;
ImGuiInputTextFlags_Password = 1 SHL 10;
ImGuiInputTextFlags_AlwaysOverwrite = 1 SHL 11;
ImGuiInputTextFlags_AutoSelectAll = 1 SHL 12;
ImGuiInputTextFlags_ParseEmptyRefVal = 1 SHL 13;
ImGuiInputTextFlags_DisplayEmptyRefVal = 1 SHL 14;
ImGuiInputTextFlags_NoHorizontalScroll = 1 SHL 15;
ImGuiInputTextFlags_NoUndoRedo = 1 SHL 16;
ImGuiInputTextFlags_CharsScientific = 1 SHL 17;
ImGuiInputTextFlags_CallbackResize = 1 SHL 18;
ImGuiInputTextFlags_CallbackEdit = 1 SHL 19;
ImGuiInputTextFlags_EscapeClearsAll = 1 SHL 20;
{ Callback features }
ImGuiInputTextFlags_CallbackCompletion = 1 SHL 17;
ImGuiInputTextFlags_CallbackHistory = 1 SHL 18;
ImGuiInputTextFlags_CallbackAlways = 1 SHL 19;
ImGuiInputTextFlags_CallbackCharFilter = 1 SHL 20;
ImGuiInputTextFlags_CallbackResize = 1 SHL 21;
ImGuiInputTextFlags_CallbackEdit = 1 SHL 22;
{ ============================================================
ImGuiTreeNodeFlags
+6
View File
@@ -40,6 +40,7 @@ function frontBufferBpp : uint8;
function backBufferWidth : uint32;
function backBufferHeight : uint32;
function backBufferBpp : uint8;
function backBufferLocation : uint32;
Procedure basicFDrawTexture(Buffer : PVideoBuffer; X : uint32; Y : uint32; Texture : PTexture);
@@ -315,4 +316,9 @@ begin
backBufferBpp:= VideoInterface.BackBuffer.BitsPerPixel;
end;
function backBufferLocation : uint32;
begin
backBufferLocation:= VideoInterface.BackBuffer.Location;
end;
end.
+22 -8
View File
@@ -57,7 +57,7 @@ uses
terminal,
hashmap, vfs,
video, vesa, doublebuffer, color,
imgui, imguitypes;
imgui, imguitypes, desktop;
procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall;
@@ -122,11 +122,16 @@ begin
end;
procedure imgui_mouse_hook(x, y: sint32; lmb, rmb, mmb: boolean);
var
fx, fy: Single;
begin
imgui_feed_mouse_pos(Single(x), Single(y));
imgui_feed_mouse_button(0, lmb);
imgui_feed_mouse_button(1, rmb);
imgui_feed_mouse_button(2, mmb);
{ Buffer mouse events — will be drained before next frame }
fx := x;
fy := y;
imgui_handle_mouse_pos(fx, fy);
imgui_handle_mouse_button(0, sint32(lmb));
imgui_handle_mouse_button(1, sint32(rmb));
imgui_handle_mouse_button(2, sint32(mmb));
end;
procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall; [public, alias: 'kmain'];
@@ -235,6 +240,9 @@ begin
{ Call Tracer }
tracer.init();
{ Virtual File System }
vfs.init();
video.init();
vesa.init(@video.register);
doublebuffer.init(@video.register);
@@ -282,6 +290,11 @@ begin
imgui_init(video.frontBufferWidth, video.frontBufferHeight);
console.outputln('KERNEL', 'ImGui: INIT END.');
{ Initialize desktop }
console.outputln('KERNEL', 'Desktop: INIT BEGIN.');
desktop_init;
console.outputln('KERNEL', 'Desktop: INIT END.');
{ Initialize input drivers }
console.outputln('KERNEL', 'Input: INIT BEGIN.');
keyboard.init(keyboard_layout);
@@ -302,10 +315,10 @@ begin
{ Warm-up frames: ImGui needs 2+ frames for window layout }
imgui_new_frame;
imgui_test_window;
desktop_frame;
imgui_render;
imgui_new_frame;
imgui_test_window;
desktop_frame;
imgui_render;
{ Main interactive render loop }
@@ -321,8 +334,9 @@ begin
else
imgui_feed_delta_time(Single(0.001));
imgui_process_input;
imgui_new_frame;
imgui_test_window;
desktop_frame;
imgui_render;
end;
+2 -2
View File
@@ -170,7 +170,7 @@ begin
klalloc:= Address;
end;
function kalloc(size : uint32) : void;
function kalloc(size : uint32) : void; [public, alias: 'kernel_kalloc'];
var
Heap_Entries : uint32;
i, j : uint32;
@@ -217,7 +217,7 @@ begin
//pop_trace;
end;
procedure kfree(area : void);
procedure kfree(area : void); [public, alias: 'kernel_kfree'];
var
hp : PHeapPage;
entry : uint32;
+1
View File
@@ -72,6 +72,7 @@ procedure registerCommandEx(command : pchar; method : TCommandMethod; descriptio
function getParams(buf : TCommandBuffer) : PParamList;
function paramCount(params : PParamList) : uint32;
function getParam(index : uint32; params : PParamList) : pchar;
procedure freeParams(params : PParamList);
procedure setWorkingDirectory(str : pchar);
function getWorkingDirectory : pchar;
function getTerminalHWND : uint32;
+1 -1
View File
@@ -45,6 +45,7 @@ type
var
Active : Boolean;
Root_Task : PScheduler_Entry;
procedure init;
procedure add_task(priority : uint8);
@@ -53,7 +54,6 @@ implementation
var
Tick : uint32;
Root_Task : PScheduler_Entry = nil;
Current_Task : PScheduler_Entry = nil;
procedure context_switch();