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:
@@ -351,25 +351,27 @@ fn onMessage(message: []const u8, reply: []u8, sender: u32, capability: ?ipc.Han
|
||||
.format = display.format,
|
||||
}),
|
||||
@intFromEnum(protocol.Operation.create_layer) => {
|
||||
const slot = createLayer(@intCast(request.x), @intCast(request.y), request.width, request.height, request.z, request.visible != 0) orelse return fail(reply);
|
||||
// x/y are signed coordinates carried in the u32 wire fields — reinterpret the
|
||||
// bits (@bitCast), don't range-check (@intCast) which a negative would fail.
|
||||
const slot = createLayer(@bitCast(request.x), @bitCast(request.y), request.width, request.height, request.z, request.visible != 0) orelse return fail(reply);
|
||||
return writeReply(reply, .{ .status = 0, .layer = slot });
|
||||
},
|
||||
@intFromEnum(protocol.Operation.configure_layer) => {
|
||||
return if (configureLayer(request.layer, @intCast(request.x), @intCast(request.y), request.z, request.visible != 0)) ok(reply) else fail(reply);
|
||||
return if (configureLayer(request.layer, @bitCast(request.x), @bitCast(request.y), request.z, request.visible != 0)) ok(reply) else fail(reply);
|
||||
},
|
||||
@intFromEnum(protocol.Operation.destroy_layer) => {
|
||||
return if (destroyLayer(request.layer)) ok(reply) else fail(reply);
|
||||
},
|
||||
@intFromEnum(protocol.Operation.fill_rect) => {
|
||||
const local = Rect.init(@intCast(request.x), @intCast(request.y), @intCast(request.width), @intCast(request.height));
|
||||
const local = Rect.init(@bitCast(request.x), @bitCast(request.y), @intCast(request.width), @intCast(request.height));
|
||||
return if (fillLayer(request.layer, local, request.colour)) ok(reply) else fail(reply);
|
||||
},
|
||||
@intFromEnum(protocol.Operation.blit_tile) => {
|
||||
return if (blitLayer(request.layer, @intCast(request.x), @intCast(request.y), request.width, request.height, payload)) ok(reply) else fail(reply);
|
||||
return if (blitLayer(request.layer, @bitCast(request.x), @bitCast(request.y), request.width, request.height, payload)) ok(reply) else fail(reply);
|
||||
},
|
||||
@intFromEnum(protocol.Operation.damage) => {
|
||||
const l = layerAt(request.layer) orelse return fail(reply);
|
||||
const screen = Rect{ .x = l.x + @as(i32, @intCast(request.x)), .y = l.y + @as(i32, @intCast(request.y)), .w = @intCast(request.width), .h = @intCast(request.height) };
|
||||
const screen = Rect{ .x = l.x + @as(i32, @bitCast(request.x)), .y = l.y + @as(i32, @bitCast(request.y)), .w = @intCast(request.width), .h = @intCast(request.height) };
|
||||
addDamage(screen.intersect(layerScreenRect(l)));
|
||||
return ok(reply);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user