mirror of
https://github.com/rdmsr/zag.git
synced 2026-11-01 15:48:21 +00:00
feat(pl/um): add SDL support
This commit is contained in:
@@ -38,10 +38,11 @@ pub fn build(b: *std.Build) void {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
const optimize = b.standardOptimizeOption(.{ .preferred_optimize_mode = .Debug });
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
const config_module = b.createModule(.{
|
const config_module = b.createModule(.{
|
||||||
.root_source_file = config_wf.getDirectory().path(b, "config.gen.zig"),
|
.root_source_file = config_wf.getDirectory().path(b, "config.gen.zig"),
|
||||||
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
// first pass
|
// first pass
|
||||||
@@ -50,10 +51,12 @@ pub fn build(b: *std.Build) void {
|
|||||||
const empty_zig = empty_cmd.addOutputFileArg("ksyms_empty.gen.zig");
|
const empty_zig = empty_cmd.addOutputFileArg("ksyms_empty.gen.zig");
|
||||||
const empty_ksyms_module = b.createModule(.{
|
const empty_ksyms_module = b.createModule(.{
|
||||||
.root_source_file = empty_zig,
|
.root_source_file = empty_zig,
|
||||||
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
const rtl_module = b.createModule(.{
|
const rtl_module = b.createModule(.{
|
||||||
.root_source_file = b.path("src/rtl/root.zig"),
|
.root_source_file = b.path("src/rtl/root.zig"),
|
||||||
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
rtl_module.addImport("rtl", rtl_module);
|
rtl_module.addImport("rtl", rtl_module);
|
||||||
@@ -64,6 +67,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
.{ .name = "config", .module = config_module },
|
.{ .name = "config", .module = config_module },
|
||||||
.{ .name = "rtl", .module = rtl_module },
|
.{ .name = "rtl", .module = rtl_module },
|
||||||
},
|
},
|
||||||
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
base_module.addImport("base", base_module);
|
base_module.addImport("base", base_module);
|
||||||
@@ -81,6 +85,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
const ksyms_zig = ksyms.addOutputFileArg("ksyms.gen.zig");
|
const ksyms_zig = ksyms.addOutputFileArg("ksyms.gen.zig");
|
||||||
const ksyms_module = b.createModule(.{
|
const ksyms_module = b.createModule(.{
|
||||||
.root_source_file = ksyms_zig,
|
.root_source_file = ksyms_zig,
|
||||||
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
// second pass
|
// second pass
|
||||||
@@ -214,6 +219,9 @@ fn addKernel(b: *std.Build, plat: config.Platform, optimize: std.builtin.Optimiz
|
|||||||
} else {
|
} else {
|
||||||
kernel.linker_script = b.path("build/linker-scripts/uml.lds");
|
kernel.linker_script = b.path("build/linker-scripts/uml.lds");
|
||||||
kernel.root_module.link_libc = true;
|
kernel.root_module.link_libc = true;
|
||||||
|
kernel.linker_allow_shlib_undefined = true;
|
||||||
|
kernel.root_module.linkSystemLibrary("sdl2-compat", .{ .use_pkg_config = .force });
|
||||||
|
kernel.root_module.addLibraryPath(.{ .cwd_relative = "/usr/lib64" });
|
||||||
}
|
}
|
||||||
|
|
||||||
return kernel;
|
return kernel;
|
||||||
|
|||||||
+16
-9
@@ -14,13 +14,13 @@ fn handler(_: ?*anyopaque) void {
|
|||||||
while (true) {}
|
while (true) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_thread(entry: *const fn (?*anyopaque) void, td: *ke.Thread) void {
|
fn make_thread(entry: *const fn (?*anyopaque) void, td: *ke.Thread, arg: ?*anyopaque) void {
|
||||||
const _stack = std.heap.page_allocator.alloc(u8, 16384) catch @panic("wtf");
|
const _stack = std.heap.page_allocator.alloc(u8, 16384) catch @panic("wtf");
|
||||||
|
|
||||||
td.init(@intFromPtr(_stack.ptr), 16384, entry, null);
|
td.init(@intFromPtr(_stack.ptr), 16384, entry, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
var threads: [10]ke.Thread = undefined;
|
var threads: [1]ke.Thread = undefined;
|
||||||
|
|
||||||
pub fn init(boot_info: *pl.BootInfo) linksection(b.init) void {
|
pub fn init(boot_info: *pl.BootInfo) linksection(b.init) void {
|
||||||
pl.early_init();
|
pl.early_init();
|
||||||
@@ -37,14 +37,21 @@ pub fn init(boot_info: *pl.BootInfo) linksection(b.init) void {
|
|||||||
|
|
||||||
ki.sched.late_init();
|
ki.sched.late_init();
|
||||||
|
|
||||||
_ = ke.ipl.raise(.Dispatch);
|
if (boot_info.framebuffer == null) {
|
||||||
|
const ipl = ke.ipl.raise(.Dispatch);
|
||||||
|
|
||||||
for (0..threads.len) |i| {
|
for (&threads) |*td| {
|
||||||
make_thread(handler, &threads[i]);
|
make_thread(&handler, td, null);
|
||||||
ke.sched.enqueue(&threads[i]);
|
td.priority = ke.Thread.Priority.default;
|
||||||
|
td.priority_class = .Batch;
|
||||||
|
ke.sched.enqueue(td);
|
||||||
|
}
|
||||||
|
|
||||||
|
ke.ipl.lower(ipl);
|
||||||
|
} else {
|
||||||
|
make_thread(&b.ex.fireworks.start, &threads[0], boot_info);
|
||||||
|
ke.sched.enqueue(&threads[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ke.ipl.lower(.Passive);
|
|
||||||
|
|
||||||
while (true) {}
|
while (true) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,14 @@ pub const BootInfo = struct {
|
|||||||
entries: [256]Entry,
|
entries: [256]Entry,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Framebuffer = struct {
|
||||||
|
address: usize,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
pitch: u32,
|
||||||
|
bpp: u8,
|
||||||
|
};
|
||||||
|
|
||||||
pub const KernelAddress = struct { physical_base: usize, virtual_base: usize };
|
pub const KernelAddress = struct { physical_base: usize, virtual_base: usize };
|
||||||
|
|
||||||
/// RSDP on ACPI machines
|
/// RSDP on ACPI machines
|
||||||
@@ -70,6 +78,9 @@ pub const BootInfo = struct {
|
|||||||
/// Memory map
|
/// Memory map
|
||||||
memory_map: MemMap,
|
memory_map: MemMap,
|
||||||
|
|
||||||
|
/// Framebuffer info, if available
|
||||||
|
framebuffer: ?Framebuffer,
|
||||||
|
|
||||||
/// Kernel address
|
/// Kernel address
|
||||||
kernel_address: KernelAddress,
|
kernel_address: KernelAddress,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,12 @@ pub const std_options = b.std_options;
|
|||||||
|
|
||||||
pub const rtl = @import("rtl");
|
pub const rtl = @import("rtl");
|
||||||
|
|
||||||
|
const c = @cImport({
|
||||||
|
@cInclude("SDL.h");
|
||||||
|
@cInclude("signal.h");
|
||||||
|
@cInclude("pthread.h");
|
||||||
|
});
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const ke = b.ke;
|
const ke = b.ke;
|
||||||
const pl = b.pl;
|
const pl = b.pl;
|
||||||
@@ -27,6 +33,98 @@ fn parse_mem_size(str: []const u8) !usize {
|
|||||||
return size * mul;
|
return size * mul;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var gui_started = std.atomic.Value(bool).init(false);
|
||||||
|
|
||||||
|
fn gui_thread() void {
|
||||||
|
if (c.SDL_Init(c.SDL_INIT_VIDEO) != 0) {
|
||||||
|
std.debug.panic("Failed to initialize SDL: {s}\n", .{c.SDL_GetError()});
|
||||||
|
}
|
||||||
|
|
||||||
|
const window = c.SDL_CreateWindow(
|
||||||
|
"Zag (UM)",
|
||||||
|
c.SDL_WINDOWPOS_UNDEFINED,
|
||||||
|
c.SDL_WINDOWPOS_UNDEFINED,
|
||||||
|
800,
|
||||||
|
600,
|
||||||
|
c.SDL_WINDOW_SHOWN,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (window == null) {
|
||||||
|
std.debug.panic("Failed to create window: {s}\n", .{c.SDL_GetError()});
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderer = c.SDL_CreateRenderer(window.?, -1, c.SDL_RENDERER_ACCELERATED);
|
||||||
|
if (renderer == null) {
|
||||||
|
std.debug.panic("Failed to create renderer: {s}\n", .{c.SDL_GetError()});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fb_surface: ?*c.SDL_Surface = c.SDL_CreateRGBSurface(0, 800, 600, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
|
||||||
|
if (fb_surface == null) {
|
||||||
|
std.debug.panic("Failed to create surface: {s}\n", .{c
|
||||||
|
.SDL_GetError()});
|
||||||
|
}
|
||||||
|
|
||||||
|
const surface = fb_surface.?;
|
||||||
|
|
||||||
|
const texture = c.SDL_CreateTexture(
|
||||||
|
renderer.?,
|
||||||
|
c.SDL_PIXELFORMAT_RGB888,
|
||||||
|
c.SDL_TEXTUREACCESS_STREAMING,
|
||||||
|
800,
|
||||||
|
600,
|
||||||
|
);
|
||||||
|
|
||||||
|
pl.impl.global_state.boot_info.framebuffer = .{
|
||||||
|
.address = @intFromPtr(surface.pixels),
|
||||||
|
.width = 800,
|
||||||
|
.height = 600,
|
||||||
|
.pitch = @intCast(surface.pitch),
|
||||||
|
.bpp = 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
gui_started.store(true, .release);
|
||||||
|
|
||||||
|
// Mask all signals.
|
||||||
|
var sigset: c.sigset_t = undefined;
|
||||||
|
_ = c.sigfillset(&sigset);
|
||||||
|
_ = c.pthread_sigmask(c.SIG_BLOCK, &sigset, null);
|
||||||
|
|
||||||
|
var event: c.SDL_Event = undefined;
|
||||||
|
var quit = false;
|
||||||
|
|
||||||
|
while (!quit) {
|
||||||
|
const frame_start = c.SDL_GetTicks();
|
||||||
|
|
||||||
|
while (c.SDL_PollEvent(&event) != 0) {
|
||||||
|
if (event.type == c.SDL_QUIT) {
|
||||||
|
quit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the framebuffer (surface) to a texture and render it.
|
||||||
|
_ = c.SDL_UpdateTexture(texture, null, surface.pixels, surface.pitch);
|
||||||
|
_ = c.SDL_RenderClear(renderer.?);
|
||||||
|
_ = c.SDL_RenderCopy(renderer.?, texture, null, null);
|
||||||
|
_ = c.SDL_RenderPresent(renderer.?);
|
||||||
|
|
||||||
|
const frame_time = c.SDL_GetTicks() - frame_start;
|
||||||
|
|
||||||
|
if (frame_time < 16) {
|
||||||
|
c.SDL_Delay(16 - frame_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = c.SDL_DestroyTexture(texture);
|
||||||
|
|
||||||
|
// Exit.
|
||||||
|
c.SDL_Quit();
|
||||||
|
std.process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_gui() void {
|
||||||
|
_ = std.Thread.spawn(.{ .allocator = std.heap.page_allocator }, gui_thread, .{}) catch unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main(init: std.process.Init) !void {
|
pub fn main(init: std.process.Init) !void {
|
||||||
var args = try init.minimal.args.iterateAllocator(init.gpa);
|
var args = try init.minimal.args.iterateAllocator(init.gpa);
|
||||||
defer args.deinit();
|
defer args.deinit();
|
||||||
@@ -36,6 +134,7 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
var mem_size: usize = default_mem_size;
|
var mem_size: usize = default_mem_size;
|
||||||
var cmdline: ?[]const u8 = null;
|
var cmdline: ?[]const u8 = null;
|
||||||
var ncpus: usize = 1;
|
var ncpus: usize = 1;
|
||||||
|
var gui = false;
|
||||||
|
|
||||||
while (args.next()) |arg| {
|
while (args.next()) |arg| {
|
||||||
if (std.mem.eql(u8, arg, "-m") or std.mem.eql(u8, arg, "--mem-size")) {
|
if (std.mem.eql(u8, arg, "-m") or std.mem.eql(u8, arg, "--mem-size")) {
|
||||||
@@ -46,6 +145,8 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
} else if (std.mem.eql(u8, arg, "-t") or std.mem.eql(u8, arg, "--threads")) {
|
} else if (std.mem.eql(u8, arg, "-t") or std.mem.eql(u8, arg, "--threads")) {
|
||||||
const val = args.next() orelse fatal("--threads requires a value", .{});
|
const val = args.next() orelse fatal("--threads requires a value", .{});
|
||||||
ncpus = std.fmt.parseInt(usize, val, 10) catch fatal("invalid thread count", .{});
|
ncpus = std.fmt.parseInt(usize, val, 10) catch fatal("invalid thread count", .{});
|
||||||
|
} else if (std.mem.eql(u8, arg, "-g") or std.mem.eql(u8, arg, "--gui")) {
|
||||||
|
gui = true;
|
||||||
} else if (std.mem.eql(u8, arg, "--help") or std.mem.eql(u8, arg, "-h")) {
|
} else if (std.mem.eql(u8, arg, "--help") or std.mem.eql(u8, arg, "-h")) {
|
||||||
var stderr = std.Io.File.stderr().writerStreaming(init.io, &.{});
|
var stderr = std.Io.File.stderr().writerStreaming(init.io, &.{});
|
||||||
var w = &stderr.interface;
|
var w = &stderr.interface;
|
||||||
@@ -55,6 +156,7 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
\\ -m, --mem-size SIZE Set the memory size
|
\\ -m, --mem-size SIZE Set the memory size
|
||||||
\\ -c, --cmdline STR Set the kernel cmdline
|
\\ -c, --cmdline STR Set the kernel cmdline
|
||||||
\\ -t, --threads COUNT Set the number of threads
|
\\ -t, --threads COUNT Set the number of threads
|
||||||
|
\\ -g, --gui, Enable graphics mode using SDL2
|
||||||
\\
|
\\
|
||||||
, .{exe});
|
, .{exe});
|
||||||
std.process.exit(0);
|
std.process.exit(0);
|
||||||
@@ -72,6 +174,13 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
pl.impl.global_state.boot_info.rsdp = 0;
|
pl.impl.global_state.boot_info.rsdp = 0;
|
||||||
pl.impl.global_state.boot_info.cmdline = cmdline;
|
pl.impl.global_state.boot_info.cmdline = cmdline;
|
||||||
|
|
||||||
|
if (gui) {
|
||||||
|
start_gui();
|
||||||
|
while (gui_started.load(.monotonic) != true) {
|
||||||
|
std.atomic.spinLoopHint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ke.ncpus = ncpus;
|
ke.ncpus = ncpus;
|
||||||
|
|
||||||
ke.private.init(&pl.impl.global_state.boot_info);
|
ke.private.init(&pl.impl.global_state.boot_info);
|
||||||
|
|||||||
Reference in New Issue
Block a user