Compare commits
5
Commits
65c62176b0
...
e5548c878b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5548c878b | ||
|
|
33985afea1 | ||
|
|
a3b766464b | ||
|
|
262d064b6d | ||
|
|
738e5828f6 |
No files matched your search
@@ -29,14 +29,11 @@ unit contextswitcher;
|
||||
interface
|
||||
|
||||
uses
|
||||
idt, isrmanager, processmanager, proctypes, util, syslog, tracer;
|
||||
idt, isrmanager, processmanager, proctypes, util, tracer;
|
||||
|
||||
{ Initialise: overwrite IDT gate 32 with our custom ISR. }
|
||||
procedure init;
|
||||
|
||||
{ No idle ESP variable needed — idle is now a formal process (PID 0)
|
||||
with its SavedESP managed like any other process. }
|
||||
|
||||
implementation
|
||||
|
||||
{ -----------------------------------------------------------------------
|
||||
|
||||
@@ -957,11 +957,14 @@ end;
|
||||
procedure usb_check_hotplug;
|
||||
var
|
||||
i : uint32;
|
||||
count: uint32;
|
||||
hc : PUSBHCDriver;
|
||||
port : uint8;
|
||||
begin
|
||||
if HCList = nil then exit;
|
||||
for i := 0 to LL_Size(HCList) - 1 do begin
|
||||
count := LL_Size(HCList);
|
||||
if count = 0 then exit;
|
||||
for i := 0 to count - 1 do begin
|
||||
hc := PUSBHCDriver(LL_Get(HCList, i));
|
||||
if (hc <> nil) and hc^.PortChangePending then begin
|
||||
hc^.PortChangePending := false;
|
||||
|
||||
@@ -119,8 +119,12 @@ var
|
||||
x32, y32 : sint32;
|
||||
r : pchar;
|
||||
begin
|
||||
{ mouse_wait(0) checks OBF with a short timeout (100 iterations).
|
||||
When it returns true, data is ready — read it directly with inb($60).
|
||||
Do NOT call mouse_read here: it uses mouse_wait_long (100k iterations)
|
||||
and would spin-block the ISR if the next packet byte hasn't arrived yet. }
|
||||
while mouse_wait(0) do begin
|
||||
b := mouse_read;
|
||||
b := inb($60);
|
||||
if Cycle = 0 then begin
|
||||
if (b AND $08) = $08 then begin
|
||||
Mouse_Byte[Cycle] := b;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
{
|
||||
Driver->Timer->TMR_0_ISR - 1024hz Timer Driver.
|
||||
Driver->Timer->TMR_0_ISR - 8khz Timer Driver.
|
||||
|
||||
@author(Kieron Morris <[email protected]>)
|
||||
}
|
||||
@@ -37,7 +37,7 @@ var
|
||||
Hooks : Array[1..MAX_HOOKS] of pp_hook_method;
|
||||
Registered : boolean = false;
|
||||
|
||||
procedure Main; //IRQ0, 1024.19hz aprox
|
||||
procedure Main; //IRQ0, ~8001hz
|
||||
var
|
||||
i : integer;
|
||||
|
||||
@@ -54,7 +54,7 @@ procedure register();
|
||||
begin
|
||||
if not registered then begin
|
||||
asm
|
||||
mov ax, 1193
|
||||
mov ax, 149
|
||||
out $40, al
|
||||
mov al, ah
|
||||
out $40, al
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
{
|
||||
Driver->Timer->GraphicsRefresh - Timer-driven graphics refresh at ~120FPS.
|
||||
|
||||
Hooks into the 1024Hz timer (TMR_0_ISR) and calls the desktop, uidebug,
|
||||
LVGL and video flush routines every ~9 ticks (1024/9 ≈ 113.8 FPS).
|
||||
|
||||
@author(Kieron Morris <[email protected]>)
|
||||
}
|
||||
unit graphicsrefresh;
|
||||
|
||||
interface
|
||||
|
||||
procedure init;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
util,
|
||||
TMR_0_ISR,
|
||||
desktop,
|
||||
uidebug,
|
||||
lvgl,
|
||||
video,
|
||||
windows,
|
||||
syslog;
|
||||
|
||||
const
|
||||
{ 1024 / 4 ≈ 256 FPS }
|
||||
TICKS_PER_FRAME = 4;
|
||||
|
||||
var
|
||||
TickCounter : uint32;
|
||||
|
||||
procedure on_tick(data : void);
|
||||
begin
|
||||
TickCounter := TickCounter + 1;
|
||||
if TickCounter >= TICKS_PER_FRAME then begin
|
||||
TickCounter := 0;
|
||||
windows.reapOrphanedWindows;
|
||||
desktop.update;
|
||||
uidebug.update;
|
||||
lvgl_handler;
|
||||
video.Flush;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure init;
|
||||
begin
|
||||
TickCounter := 0;
|
||||
TMR_0_ISR.hook(uint32(@on_tick));
|
||||
syslog.logln('GFXREFRESH', 'Hooked into 1024Hz timer (~120 FPS).');
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -1,46 +0,0 @@
|
||||
{
|
||||
Driver->Timer->USBHotplug - Timer-driven USB hotplug polling at ~1Hz.
|
||||
|
||||
Hooks into the 1024Hz timer (TMR_0_ISR) and calls
|
||||
usbcore.usb_check_hotplug every 1024 ticks (approximately once per second).
|
||||
|
||||
@author(Kieron Morris <[email protected]>)
|
||||
}
|
||||
unit usbhotplug;
|
||||
|
||||
interface
|
||||
|
||||
procedure init;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
util,
|
||||
TMR_0_ISR,
|
||||
usbcore,
|
||||
syslog;
|
||||
|
||||
const
|
||||
{ 1024 ticks at 1024Hz ≈ 1 second }
|
||||
TICKS_PER_POLL = 1024;
|
||||
|
||||
var
|
||||
TickCounter : uint32;
|
||||
|
||||
procedure on_tick(data : void);
|
||||
begin
|
||||
TickCounter := TickCounter + 1;
|
||||
if TickCounter >= TICKS_PER_POLL then begin
|
||||
TickCounter := 0;
|
||||
usbcore.usb_check_hotplug;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure init;
|
||||
begin
|
||||
TickCounter := 0;
|
||||
TMR_0_ISR.hook(uint32(@on_tick));
|
||||
syslog.logln('USBHOTPLUG', 'Hooked into 1024Hz timer (~1Hz polling).');
|
||||
end;
|
||||
|
||||
end.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -15,7 +15,7 @@ unit desktop;
|
||||
interface
|
||||
|
||||
uses
|
||||
lvgl, video, RTC, strings, util, tracer, multiboot, cpu, serial, windows, asuro;
|
||||
lvgl, video, gpu, RTC, strings, util, tracer, multiboot, cpu, serial, windows, asuro;
|
||||
|
||||
type
|
||||
TProgLaunchProc = procedure;
|
||||
@@ -25,6 +25,7 @@ procedure registerProgram(name: pchar; launcher: TProgLaunchProc);
|
||||
|
||||
procedure init;
|
||||
procedure update;
|
||||
procedure relayout;
|
||||
|
||||
implementation
|
||||
|
||||
@@ -36,7 +37,7 @@ const
|
||||
DOCK_ITEM_H = 36;
|
||||
|
||||
SEARCH_W = 220;
|
||||
SEARCH_RADIUS = 18;
|
||||
SEARCH_RADIUS = 16;
|
||||
|
||||
RESULTS_W = SEARCH_W;
|
||||
RESULTS_ROW_H = 36;
|
||||
@@ -299,12 +300,12 @@ begin
|
||||
addInfoRow(content, cw, 'CPU Clock', clk_str);
|
||||
mem_str := stringConcat(intToString(((multibootinfo^.mem_upper + 1000) div 1024) + 1), ' MB');
|
||||
addInfoRow(content, cw, 'Memory', mem_str);
|
||||
res_str := stringConcat(intToString(multibootinfo^.framebuffer_width), 'x');
|
||||
res_str := stringConcat(res_str, intToString(multibootinfo^.framebuffer_height));
|
||||
res_str := stringConcat(intToString(video.frontBufferWidth), 'x');
|
||||
res_str := stringConcat(res_str, intToString(video.frontBufferHeight));
|
||||
res_str := stringConcat(res_str, 'x');
|
||||
res_str := stringConcat(res_str, intToString(multibootinfo^.framebuffer_bpp));
|
||||
res_str := stringConcat(res_str, intToString(video.frontBufferBpp));
|
||||
addInfoRow(content, cw, 'Resolution', res_str);
|
||||
addInfoRow(content, cw, 'Graphics', 'VESA VBE');
|
||||
addInfoRow(content, cw, 'Graphics', gpu.activeDriverName);
|
||||
|
||||
addSeparator(content, cw);
|
||||
|
||||
@@ -677,6 +678,14 @@ begin
|
||||
lv_obj_set_pos(results_panel, lv_obj_get_x(results_panel), anim_current_y);
|
||||
end;
|
||||
|
||||
{ ============================================================
|
||||
Mode-change callback — fired by GPU framework after setMode
|
||||
============================================================ }
|
||||
procedure desktopModeChanged(const info : TGPUModeInfo);
|
||||
begin
|
||||
relayout;
|
||||
end;
|
||||
|
||||
{ ============================================================
|
||||
Init — create the desktop UI
|
||||
============================================================ }
|
||||
@@ -819,6 +828,43 @@ begin
|
||||
{ ---- Register built-in programs ---- }
|
||||
registerProgram('System Information', @openSysInfo);
|
||||
|
||||
{ Register for resolution-change notifications from GPU framework }
|
||||
gpu.registerModeChangeCallback(@desktopModeChanged);
|
||||
|
||||
tracer.pop_trace;
|
||||
end;
|
||||
|
||||
{ ============================================================
|
||||
Relayout — reposition all desktop UI after resolution change
|
||||
============================================================ }
|
||||
procedure relayout;
|
||||
var
|
||||
scr_w, scr_h : sint32;
|
||||
dock_w : sint32;
|
||||
dock_x : sint32;
|
||||
dock_y : sint32;
|
||||
begin
|
||||
tracer.push_trace('desktop.relayout');
|
||||
|
||||
scr_w := sint32(video.frontBufferWidth);
|
||||
scr_h := sint32(video.frontBufferHeight);
|
||||
|
||||
{ Close any open search/results first }
|
||||
clearAndClose;
|
||||
|
||||
{ Reposition dock }
|
||||
dock_w := scr_w - (DOCK_HPAD * 2);
|
||||
dock_x := DOCK_HPAD;
|
||||
dock_y := scr_h - DOCK_HEIGHT - DOCK_MARGIN;
|
||||
lv_obj_set_size(dock, dock_w, DOCK_HEIGHT);
|
||||
lv_obj_set_pos(dock, dock_x, dock_y);
|
||||
|
||||
{ Watermark stays centered (LV_ALIGN_CENTER is relative to parent) }
|
||||
lv_obj_align(desktop_label, LV_ALIGN_CENTER, 0, -30);
|
||||
|
||||
{ Force layout recalculation }
|
||||
lv_obj_update_layout(lv_screen_active);
|
||||
|
||||
tracer.pop_trace;
|
||||
end;
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -13,7 +13,7 @@ interface
|
||||
|
||||
uses
|
||||
video, videotypes, color, serial, tracer, lmemorymanager,
|
||||
mouse, keyboard, TMR_0_ISR, util;
|
||||
mouse, keyboard, TMR_0_ISR, util, syslog, gpu;
|
||||
|
||||
{ ============================================================
|
||||
Opaque LVGL pointer types (internal C structs)
|
||||
@@ -1670,6 +1670,7 @@ function lvgl_get_display: Plv_display;
|
||||
procedure lvgl_set_mouse_cursor(cursor: Plv_obj);
|
||||
function lvgl_get_ticks: uint32;
|
||||
function lvgl_get_kb_group: Plv_group;
|
||||
procedure lvgl_update_resolution(screen_w, screen_h: uint32);
|
||||
|
||||
{ Color helper (Pascal wrapper for inline C function) }
|
||||
function lv_color_make(r, g, b: uint8): lv_color_t;
|
||||
@@ -1909,6 +1910,14 @@ begin
|
||||
tick_accumulator := tick_accumulator + 1;
|
||||
end;
|
||||
|
||||
{ ============================================================
|
||||
GPU mode-change callback — updates LVGL display resolution
|
||||
============================================================ }
|
||||
procedure lvglModeChanged(const info : TGPUModeInfo);
|
||||
begin
|
||||
lvgl_update_resolution(info.Width, info.Height);
|
||||
end;
|
||||
|
||||
{ ============================================================
|
||||
High-level init
|
||||
============================================================ }
|
||||
@@ -1962,9 +1971,45 @@ begin
|
||||
{ Hook 1024Hz timer for accurate LVGL tick }
|
||||
TMR_0_ISR.hook(uint32(@lvgl_timer_tick));
|
||||
|
||||
{ Register for GPU mode-change notifications so LVGL resolution updates automatically }
|
||||
gpu.registerModeChangeCallback(@lvglModeChanged);
|
||||
|
||||
tracer.push_trace('lvgl.init.exit');
|
||||
end;
|
||||
|
||||
procedure lvgl_update_resolution(screen_w, screen_h: uint32);
|
||||
var
|
||||
new_buf : pointer;
|
||||
new_size : uint32;
|
||||
|
||||
begin
|
||||
tracer.push_trace('lvgl.update_resolution.enter');
|
||||
|
||||
{ Allocate new render buffer for the new width }
|
||||
new_size := screen_w * LV_BUF_LINES * SizeOf(lv_color_t);
|
||||
new_buf := pointer(kalloc(new_size));
|
||||
|
||||
if new_buf <> nil then begin
|
||||
{ Free old render buffer }
|
||||
if lv_buf1 <> nil then
|
||||
kfree(lv_buf1);
|
||||
|
||||
lv_buf1 := new_buf;
|
||||
lv_buf1_size := new_size;
|
||||
|
||||
{ Update LVGL display resolution and buffers }
|
||||
lv_display_set_resolution(disp, sint32(screen_w), sint32(screen_h));
|
||||
lv_display_set_buffers(disp, lv_buf1, nil,
|
||||
lv_buf1_size, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||
|
||||
syslog.logln('LVGL', 'Resolution updated successfully.');
|
||||
end else begin
|
||||
syslog.logln('LVGL', 'Failed to allocate new render buffer.');
|
||||
end;
|
||||
|
||||
tracer.push_trace('lvgl.update_resolution.exit');
|
||||
end;
|
||||
|
||||
function lvgl_handler: uint32;
|
||||
var
|
||||
elapsed: uint32;
|
||||
|
||||
+162
-2
File diff suppressed because it is too large.
Load diff
@@ -22,7 +22,7 @@ unit video;
|
||||
interface
|
||||
|
||||
uses
|
||||
lmemorymanager, tracer, color, videotypes, hashmap, util, texture;
|
||||
lmemorymanager, tracer, color, videotypes, hashmap, util, texture, gpu;
|
||||
|
||||
procedure init();
|
||||
procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32);
|
||||
@@ -30,6 +30,7 @@ procedure DrawLine(x1,y1,x2,y2 : uint32; thickness : uint32; Color : TRGB32);
|
||||
procedure DrawRect(x1,y1,x2,y2 : uint32; line_thickness : uint32; Color : TRGB32);
|
||||
procedure FillRect(x1,y1,x2,y2 : uint32; line_thickness : uint32; Line_Color : TRGB32; Fill_Color : TRGB32);
|
||||
procedure Flush();
|
||||
procedure reinit(fb_addr, width, height, pitch : uint32; bpp : uint8);
|
||||
|
||||
function register(DriverIdentifier : pchar; EnableCallback : FEnableDriver) : boolean;
|
||||
function enable(DriverIdentifier : pchar) : boolean;
|
||||
@@ -47,6 +48,9 @@ Procedure basicFDrawTexture(Buffer : PVideoBuffer; X : uint32; Y : uint32; Textu
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
VESA8, VESA16, VESA24, VESA32;
|
||||
|
||||
Procedure dummyFDrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32);
|
||||
begin
|
||||
tracer.push_trace('video.dummyFDrawPixel.enter');
|
||||
@@ -191,6 +195,14 @@ var
|
||||
VideoInterface : TVideoInterface;
|
||||
DriverMap : PHashMap;
|
||||
|
||||
{ ============================================================
|
||||
GPU mode-change callback — reinits front/back buffers
|
||||
============================================================ }
|
||||
procedure videoModeChanged(const info : TGPUModeInfo);
|
||||
begin
|
||||
reinit(info.Framebuffer, info.Width, info.Height, info.Pitch, info.BPP);
|
||||
end;
|
||||
|
||||
procedure init();
|
||||
var
|
||||
RGB : TRGB32;
|
||||
@@ -226,6 +238,9 @@ begin
|
||||
//Initialize our 'DriverMap', a hashmap of loadable display drivers.
|
||||
DriverMap:= hashmap.new;
|
||||
|
||||
{ Register for GPU mode-change notifications so reinit fires automatically }
|
||||
gpu.registerModeChangeCallback(@videoModeChanged);
|
||||
|
||||
tracer.push_trace('video.init.exit');
|
||||
end;
|
||||
|
||||
@@ -327,4 +342,47 @@ begin
|
||||
frontBufferLocation:= VideoInterface.FrontBuffer.Location;
|
||||
end;
|
||||
|
||||
procedure reinit(fb_addr, width, height, pitch : uint32; bpp : uint8);
|
||||
begin
|
||||
tracer.push_trace('video.reinit.enter');
|
||||
{ Free old back buffer if allocated }
|
||||
if VideoInterface.BackBuffer.Initialized then begin
|
||||
kfree(void(VideoInterface.BackBuffer.Location));
|
||||
VideoInterface.BackBuffer.Initialized := false;
|
||||
VideoInterface.BackBuffer.Location := 0;
|
||||
VideoInterface.BackBuffer.Width := 0;
|
||||
VideoInterface.BackBuffer.Height := 0;
|
||||
end;
|
||||
|
||||
{ Reset front buffer so it can be re-initialized }
|
||||
VideoInterface.FrontBuffer.Initialized := false;
|
||||
VideoInterface.FrontBuffer.Location := 0;
|
||||
VideoInterface.FrontBuffer.Width := 0;
|
||||
VideoInterface.FrontBuffer.Height := 0;
|
||||
|
||||
{ Point default buffer back to front (in case doublebuffer re-enable fails) }
|
||||
VideoInterface.DefaultBuffer := @VideoInterface.FrontBuffer;
|
||||
|
||||
{ Set front buffer directly from GPU mode info }
|
||||
VideoInterface.FrontBuffer.Location := fb_addr;
|
||||
VideoInterface.FrontBuffer.Width := width;
|
||||
VideoInterface.FrontBuffer.Height := height;
|
||||
VideoInterface.FrontBuffer.BitsPerPixel := bpp;
|
||||
if fb_addr <> 0 then
|
||||
VideoInterface.FrontBuffer.Initialized := true;
|
||||
|
||||
{ Set up BPP-specific draw routines }
|
||||
case bpp of
|
||||
08: VESA8.init(@VideoInterface.DrawRoutines);
|
||||
16: VESA16.init(@VideoInterface.DrawRoutines);
|
||||
24: VESA24.init(@VideoInterface.DrawRoutines);
|
||||
32: VESA32.init(@VideoInterface.DrawRoutines);
|
||||
end;
|
||||
|
||||
{ Re-enable double buffer (allocates new back buffer matching front) }
|
||||
enable('BASIC_DOUBLE_BUFFER');
|
||||
|
||||
tracer.push_trace('video.reinit.exit');
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -18,7 +18,7 @@ const
|
||||
PROCESS_STACK_SIZE = 8192;
|
||||
|
||||
{ Base quantum multiplier: quantum = Priority * BASE_QUANTUM ticks }
|
||||
BASE_QUANTUM = 8;
|
||||
BASE_QUANTUM = 5;
|
||||
|
||||
type
|
||||
{ Forward declaration }
|
||||
|
||||
+32
-12
@@ -25,7 +25,7 @@ interface
|
||||
uses
|
||||
multiboot, bios_data_area,
|
||||
util,
|
||||
gdt, idt, isr, irq, tss,
|
||||
gdt, idt, isr, irq,
|
||||
TMR_0_ISR,
|
||||
syslog, stdio,
|
||||
keyboard, mouse,
|
||||
@@ -33,7 +33,6 @@ uses
|
||||
vmemorymanager, pmemorymanager, lmemorymanager,
|
||||
tracer,
|
||||
drivermanagement,
|
||||
scheduler,
|
||||
progmanager,
|
||||
processmanager, contextswitcher,
|
||||
testprocs,
|
||||
@@ -66,11 +65,29 @@ uses
|
||||
md5,
|
||||
base64,
|
||||
rand,
|
||||
hashmap, vfs,
|
||||
video, vesa, doublebuffer, color, lvgl, desktop, uidebug,
|
||||
hashmap,
|
||||
vfs,
|
||||
video,
|
||||
vesa,
|
||||
doublebuffer,
|
||||
color,
|
||||
lvgl,
|
||||
desktop,
|
||||
uidebug,
|
||||
gpu,
|
||||
bga,
|
||||
vterminal,
|
||||
graphicsrefresh, usbhotplug,
|
||||
fifo, cfifo, cfifols, lifo, circ, minh, maxh, prio;
|
||||
graphicsrefresh,
|
||||
usbhotplug,
|
||||
fifo,
|
||||
cfifo,
|
||||
cfifols,
|
||||
lifo,
|
||||
circ,
|
||||
minh,
|
||||
maxh,
|
||||
prio,
|
||||
v86;
|
||||
|
||||
procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall;
|
||||
|
||||
@@ -166,13 +183,13 @@ begin
|
||||
vmemorymanager.init();
|
||||
lmemorymanager.init();
|
||||
|
||||
{ V86 Monitor Init }
|
||||
v86.init();
|
||||
|
||||
{ Stdio Init }
|
||||
stdio.init();
|
||||
stdio.registerCommand('BSOD', @terminal_command_bsod, 'Force a Panic Screen.');
|
||||
|
||||
tss.init();
|
||||
scheduler.init();
|
||||
|
||||
{ CPUID }
|
||||
syslog.logln('CPU', 'Init begin');
|
||||
cpu.init();
|
||||
@@ -181,10 +198,15 @@ begin
|
||||
{ Call Tracer }
|
||||
tracer.init();
|
||||
|
||||
tracer.push_trace('kmain.DRVMGMT');
|
||||
drivermanagement.init();
|
||||
|
||||
{ Video Init }
|
||||
gpu.init();
|
||||
video.init();
|
||||
vesa.init(@video.register);
|
||||
doublebuffer.init(@video.register);
|
||||
bga.init();
|
||||
video.enable('VESA');
|
||||
video.enable('BASIC_DOUBLE_BUFFER');
|
||||
|
||||
@@ -192,8 +214,6 @@ begin
|
||||
vfs.init();
|
||||
|
||||
{ Management Interfaces }
|
||||
tracer.push_trace('kmain.DRVMGMT');
|
||||
drivermanagement.init();
|
||||
tracer.push_trace('kmain.STRMGMT');
|
||||
storagemanagement.init();
|
||||
|
||||
@@ -277,7 +297,7 @@ begin
|
||||
|
||||
{ Enable preemptive context switching (replaces ISR_32) }
|
||||
contextswitcher.init;
|
||||
|
||||
|
||||
{ All work is now driven by timer interrupts — idle the CPU }
|
||||
syslog.logln('KERNEL', 'All tasks registered. Halting into idle.');
|
||||
kernel.yield();
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
{
|
||||
prog->GraphicsRefresh - Continuous graphics rendering process.
|
||||
|
||||
Spawns a dedicated render process that loops indefinitely, driving the
|
||||
desktop, LVGL and video-flush pipeline. The loop does real work every
|
||||
iteration (especially the 7.3 MB SSE framebuffer copy in video.Flush),
|
||||
which keeps the vCPU active so the NEM/Hyper-V back-end never
|
||||
deschedules it and starves the PIT of interrupts.
|
||||
|
||||
@author(Kieron Morris <[email protected]>)
|
||||
}
|
||||
unit graphicsrefresh;
|
||||
|
||||
interface
|
||||
|
||||
procedure init;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
desktop,
|
||||
uidebug,
|
||||
lvgl,
|
||||
video,
|
||||
windows,
|
||||
processmanager,
|
||||
proctypes,
|
||||
syslog,
|
||||
TMR_0_ISR;
|
||||
|
||||
{ Render process entry point — runs as a normal scheduled process with
|
||||
interrupts enabled. Continuously drives the full render pipeline so
|
||||
the vCPU is always executing real work (no HLT / PAUSE spin-waits
|
||||
that would trigger pause-loop exits under NEM/Hyper-V). }
|
||||
|
||||
const
|
||||
TICKS_PER_FRAME = 32; { target ticks per frame; adjust as needed to balance refresh rate and CPU usage }
|
||||
|
||||
var
|
||||
LAST_UPDATE : uint32 = 0;
|
||||
CURRENT_TICK : uint32 = 0;
|
||||
|
||||
procedure render_loop(ctx : PProcessContext);
|
||||
var
|
||||
should_update : boolean;
|
||||
|
||||
begin
|
||||
while true do begin
|
||||
should_update := (CURRENT_TICK - LAST_UPDATE) >= TICKS_PER_FRAME;
|
||||
should_update := should_update or (CURRENT_TICK < LAST_UPDATE); { handle tick counter wraparound }
|
||||
if (should_update) then begin
|
||||
LAST_UPDATE := CURRENT_TICK;
|
||||
windows.reapOrphanedWindows;
|
||||
desktop.update;
|
||||
uidebug.update;
|
||||
lvgl_handler;
|
||||
video.Flush;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure tick;
|
||||
begin
|
||||
{ This function is called on every timer tick (interrupt 32) via the ISR hooks.
|
||||
It can be used to trigger periodic tasks without needing a dedicated process. }
|
||||
CURRENT_TICK := CURRENT_TICK + 1;
|
||||
end;
|
||||
|
||||
procedure init;
|
||||
begin
|
||||
TMR_0_ISR.hook(uint32(@tick)); { Register the tick handler to run on every timer interrupt }
|
||||
processmanager.create('gfxd', @render_loop, nil, 5);
|
||||
syslog.logln('gfxd', 'Render process spawned.');
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,83 @@
|
||||
{
|
||||
Prog->setres - Set display resolution via GPU driver framework.
|
||||
|
||||
Usage: SETRES <width> <height>
|
||||
Example: SETRES 1024 768
|
||||
|
||||
Uses the GPU driver framework to switch display modes. Tries BGA first,
|
||||
then falls back to VBE/VESA.
|
||||
|
||||
@author(Kieron Morris <[email protected]>)
|
||||
}
|
||||
unit setres;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
stdio, gpu, util, strings, tracer, syslog;
|
||||
|
||||
procedure init();
|
||||
|
||||
implementation
|
||||
|
||||
procedure run(Params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
|
||||
var
|
||||
w, h : uint32;
|
||||
wStr, hStr : pchar;
|
||||
info : TGPUModeInfo;
|
||||
|
||||
begin
|
||||
tracer.push_trace('setres.run');
|
||||
|
||||
if paramCount(params) < 2 then begin
|
||||
stdio.bufWriteStrLn(stderr_buf, 'Usage: SETRES <width> <height>');
|
||||
stdio.bufWriteStrLn(stderr_buf, 'Example: SETRES 1024 768');
|
||||
tracer.pop_trace;
|
||||
exit;
|
||||
end;
|
||||
|
||||
wStr := getParam(0, params);
|
||||
hStr := getParam(1, params);
|
||||
|
||||
w := stringToInt(wStr);
|
||||
h := stringToInt(hStr);
|
||||
|
||||
if (w = 0) or (h = 0) then begin
|
||||
stdio.bufWriteStrLn(stderr_buf, 'Error: Invalid resolution values.');
|
||||
tracer.pop_trace;
|
||||
exit;
|
||||
end;
|
||||
|
||||
stdio.bufWriteStr(stdout_buf, 'Setting resolution to ');
|
||||
stdio.bufWriteInt(stdout_buf, w);
|
||||
stdio.bufWriteStr(stdout_buf, 'x');
|
||||
stdio.bufWriteInt(stdout_buf, h);
|
||||
stdio.bufWriteStrLn(stdout_buf, 'x32...');
|
||||
|
||||
{ Step 1: Set display mode via GPU framework (tries BGA first, then VBE) }
|
||||
if not gpu.setMode(w, h, 32, info) then begin
|
||||
stdio.bufWriteStrLn(stderr_buf, 'Error: Mode switch failed. Mode may not be supported.');
|
||||
tracer.pop_trace;
|
||||
exit;
|
||||
end;
|
||||
|
||||
stdio.bufWriteStr(stdout_buf, 'Mode set via ');
|
||||
stdio.bufWriteStrLn(stdout_buf, gpu.activeDriverName());
|
||||
|
||||
stdio.bufWriteStr(stdout_buf, 'Resolution set to ');
|
||||
stdio.bufWriteInt(stdout_buf, w);
|
||||
stdio.bufWriteStr(stdout_buf, 'x');
|
||||
stdio.bufWriteInt(stdout_buf, h);
|
||||
stdio.bufWriteStrLn(stdout_buf, 'x32 successfully.');
|
||||
|
||||
tracer.pop_trace;
|
||||
end;
|
||||
|
||||
procedure init();
|
||||
begin
|
||||
tracer.push_trace('setres.init');
|
||||
stdio.registerCommand('SETRES', @Run, 'Set display resolution. Usage: SETRES <width> <height>');
|
||||
tracer.pop_trace;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -365,7 +365,7 @@ begin
|
||||
now_tick := lvgl_get_ticks;
|
||||
|
||||
if (now_tick - last_tick) >= FPS_INTERVAL then begin
|
||||
current_fps := safeDiv32(frame_count * 1000, now_tick - last_tick);
|
||||
current_fps := safeDiv32(frame_count * 8000, now_tick - last_tick);
|
||||
frame_count := 0;
|
||||
last_tick := now_tick;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
Prog->USBHotplug - USB hotplug daemon process.
|
||||
|
||||
Spawns a dedicated 'usbd' process that polls for USB port changes
|
||||
approximately once per second using processmanager.proc_sleep_ms.
|
||||
|
||||
@author(Kieron Morris <[email protected]>)
|
||||
}
|
||||
unit usbhotplug;
|
||||
|
||||
interface
|
||||
|
||||
procedure init;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
usbcore,
|
||||
processmanager,
|
||||
proctypes,
|
||||
syslog;
|
||||
|
||||
{ USB daemon process entry point — polls for hotplug events once per second. }
|
||||
procedure usbd_loop(ctx : PProcessContext);
|
||||
begin
|
||||
while true do begin
|
||||
usbcore.usb_check_hotplug;
|
||||
processmanager.proc_sleep_ms(1000);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure init;
|
||||
begin
|
||||
processmanager.create('usbd', @usbd_loop, nil, 2);
|
||||
syslog.logln('usbd', 'USB hotplug daemon spawned.');
|
||||
end;
|
||||
|
||||
end.
|
||||
+2
-1
@@ -24,7 +24,7 @@ interface
|
||||
uses
|
||||
tracer,
|
||||
//progs
|
||||
base64_prog, md5sum, dhclient, vbeinfo, testcmd, ping, meminfo;
|
||||
base64_prog, md5sum, dhclient, vbeinfo, testcmd, ping, meminfo, setres;
|
||||
|
||||
{ Initialize all baked-in programs }
|
||||
procedure init();
|
||||
@@ -64,6 +64,7 @@ begin
|
||||
testcmd.init();
|
||||
ping.init();
|
||||
meminfo.init();
|
||||
setres.init();
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -1,132 +0,0 @@
|
||||
// Copyright 2021 Kieron Morris
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
{
|
||||
Scheduler - Schedules Context Switches.
|
||||
|
||||
@author(Kieron Morris <[email protected]>)
|
||||
}
|
||||
|
||||
unit scheduler;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
syslog, stdio,
|
||||
TMR_0_ISR,
|
||||
lmemorymanager;
|
||||
|
||||
const
|
||||
Quantum = 64;
|
||||
|
||||
type
|
||||
TTaskState = packed record
|
||||
//EAX, EDX,
|
||||
end;
|
||||
TScheduler_Entry = packed record
|
||||
ThreadID : uint32;
|
||||
Priority : uint8;
|
||||
Delta : uint32;
|
||||
Next : void;
|
||||
end;
|
||||
PScheduler_Entry = ^TScheduler_Entry;
|
||||
|
||||
var
|
||||
Active : Boolean;
|
||||
|
||||
procedure init;
|
||||
procedure add_task(priority : uint8);
|
||||
|
||||
implementation
|
||||
|
||||
var
|
||||
Tick : uint32;
|
||||
Root_Task : PScheduler_Entry = nil;
|
||||
Current_Task : PScheduler_Entry = nil;
|
||||
|
||||
procedure context_switch();
|
||||
begin
|
||||
Current_Task:= PScheduler_Entry(Current_Task^.Next);
|
||||
end;
|
||||
|
||||
procedure add_task(priority : uint8);
|
||||
var
|
||||
new_task : PScheduler_Entry;
|
||||
task : PScheduler_Entry;
|
||||
i : uint32;
|
||||
|
||||
begin
|
||||
new_task:= PScheduler_Entry(kalloc(sizeof(TScheduler_Entry)));
|
||||
new_task^.Priority:= priority;
|
||||
new_task^.Delta:= Tick;
|
||||
new_task^.Next:= void(Root_Task);
|
||||
task:= Root_Task;
|
||||
i:= 1;
|
||||
while PScheduler_Entry(task^.next) <> Root_Task do begin
|
||||
i:= i+1;
|
||||
task:= PScheduler_Entry(task^.next);
|
||||
end;
|
||||
task^.next:= void(new_task);
|
||||
new_task^.ThreadID:= i;
|
||||
end;
|
||||
|
||||
procedure delta(data : void);
|
||||
begin
|
||||
If Active then begin
|
||||
Tick:= Tick + 1;
|
||||
If Tick = 0 then context_switch();
|
||||
If (Current_Task^.Delta + (Current_Task^.Priority * Quantum)) <= Tick then context_switch();
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure terminal_command_tasks(params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
|
||||
var
|
||||
list : PScheduler_Entry;
|
||||
|
||||
begin
|
||||
stdio.bufWriteStrLn(stdout_buf, 'ThreadID - Priority - Delta');
|
||||
list:= Root_Task;
|
||||
stdio.bufWriteInt(stdout_buf, list^.ThreadID);
|
||||
stdio.bufWriteStr(stdout_buf, ' - ');
|
||||
stdio.bufWriteInt(stdout_buf, list^.Priority);
|
||||
stdio.bufWriteStr(stdout_buf, ' - ');
|
||||
stdio.bufWriteIntLn(stdout_buf, list^.Delta);
|
||||
list:= PScheduler_Entry(list^.Next);
|
||||
while list <> Root_Task do begin
|
||||
stdio.bufWriteInt(stdout_buf, list^.ThreadID);
|
||||
stdio.bufWriteStr(stdout_buf, ' - ');
|
||||
stdio.bufWriteInt(stdout_buf, list^.Priority);
|
||||
stdio.bufWriteStr(stdout_buf, ' - ');
|
||||
stdio.bufWriteIntLn(stdout_buf, list^.Delta);
|
||||
list:= PScheduler_Entry(list^.Next);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure init;
|
||||
begin
|
||||
syslog.logln('SCHEDULER','INIT BEGIN.');
|
||||
Root_Task:= PScheduler_Entry(kalloc(sizeof(TScheduler_Entry)));
|
||||
Root_Task^.ThreadID:= 0;
|
||||
Root_Task^.Priority:= 1;
|
||||
Root_Task^.Delta:= 0;
|
||||
Root_Task^.Next:= void(Root_Task);
|
||||
Current_Task:= Root_Task;
|
||||
Tick:= 0;
|
||||
Active:= False;
|
||||
TMR_0_ISR.hook(uint32(@delta));
|
||||
//stdio.registerCommand('TASKS', @terminal_command_tasks, 'List Active Processes.');
|
||||
syslog.logln('SCHEDULER','INIT END.');
|
||||
end;
|
||||
|
||||
end.
|
||||
Loaded 20 of 23 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user