display: layer client API + the display-demo client (D4)
Drive the compositor from a separate process, proving the pipeline end to end. - runtime.display: a Layer handle (fill / blitTile / configure / damage / destroy), createLayer, and a color(r,g,b) helper that caches the mode and packs via protocol.pack. Coordinates are signed over the u32 wire fields (@bitCast both ways), so a layer may sit or move partly off-screen. - system/services/display-demo: the input-source analog for the compositor — a full-screen wallpaper, a rectangle it slides back and forth (moved by configure each frame, so the damage-driven present repaints old + new), and a cursor. Presents in a loop paced by runtime.time. Wired into build + initrd. Fix this surfaced: protocol.message_maximum was 4096, but the kernel caps every IPC message at MESSAGE_MAXIMUM = 256, so replyWait rejected the oversized receive buffer with -E2BIG and the serve loop had been spinning since D2 (invisibly, as those gates matched init-time heartbeats). Set it to 256; blit_tile is now explicitly a small-tile path (larger bitmaps are the deferred shm surface). Gate: `python3 test/qemu_test.py display-demo` — the demo drives frames of motion through the layer client API and logs `display-demo: ok`. Regression: zig build test, display (D1), display-service (D2/D3), and default zig build.
This commit is contained in:
@@ -99,6 +99,8 @@ pub fn run(case: []const u8, boot_information: *const BootInformation) void {
|
||||
displayTest(boot_information);
|
||||
} else if (eql(case, "display-service")) {
|
||||
displayServiceTest(boot_information);
|
||||
} else if (eql(case, "display-demo")) {
|
||||
displayDemoTest(boot_information);
|
||||
} else if (eql(case, "clock")) {
|
||||
clockTest();
|
||||
} else if (eql(case, "smp")) {
|
||||
@@ -2344,6 +2346,37 @@ fn displayServiceTest(boot_information: *const BootInformation) void {
|
||||
while (true) scheduler.yield();
|
||||
}
|
||||
|
||||
/// D4 — a separate process drives the compositor. Spawn the display service and the
|
||||
/// hardware-free `display-demo` client, which creates a wallpaper, a moving rectangle,
|
||||
/// and a cursor and presents a run of frames. Its `display-demo: ok` heartbeat — printed
|
||||
/// only after it drove frames of motion through the layer client API and the compositor —
|
||||
/// is the harness's marker (the visible motion itself is a screenshot away via run-x86-64).
|
||||
/// The demo keeps presenting, so unlike a lone blocking service the scheduler stays busy;
|
||||
/// we still match on serial rather than poll, for consistency.
|
||||
fn displayDemoTest(boot_information: *const BootInformation) void {
|
||||
log("DANOS-TEST-BEGIN: display-demo\n", .{});
|
||||
if (boot_information.initial_ramdisk_len == 0) {
|
||||
check("bootloader handed over an initial_ramdisk", false);
|
||||
result();
|
||||
return;
|
||||
}
|
||||
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
|
||||
const rd = initial_ramdisk.Reader.init(image) orelse {
|
||||
check("initial_ramdisk image is valid", false);
|
||||
result();
|
||||
return;
|
||||
};
|
||||
|
||||
if (!spawnNamed(rd, "display")) {
|
||||
log("display-demo: could not spawn the display service\n", .{});
|
||||
result();
|
||||
return;
|
||||
}
|
||||
_ = spawnNamed(rd, "display-demo");
|
||||
scheduler.setPriority(1); // below the service + demo, so they run
|
||||
while (true) scheduler.yield();
|
||||
}
|
||||
|
||||
/// Process arguments, end to end: spawn args-echo bare (its argv[0] is the
|
||||
/// initial-ramdisk name). Instance 1 sees argc == 1 and respawns itself through
|
||||
/// `system_spawn` with the extra arguments "alpha beta-42" — the syscall argument
|
||||
|
||||
Reference in New Issue
Block a user