Implemented wayland initialization code
This commit is contained in:
parent
f43e03d6f3
commit
f894fb317d
10 changed files with 244 additions and 155 deletions
|
|
@ -1 +0,0 @@
|
|||
# Sideros
|
||||
|
|
@ -7,5 +7,6 @@ layout (binding = 0) uniform Uniform {
|
|||
} ubo;
|
||||
|
||||
void main() {
|
||||
gl_Position = ubo.proj * vec4(vertPos, 1.0);
|
||||
vec4 out_vec = ubo.proj * vec4(vertPos, 1.0);
|
||||
gl_Position = vec4(out_vec.x, out_vec.y, 0.5, out_vec.w);
|
||||
}
|
||||
|
|
|
|||
56
build.zig
56
build.zig
|
|
@ -6,58 +6,6 @@ pub fn build(b: *std.Build) void {
|
|||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const glfw_module = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
});
|
||||
const glfw = b.addLibrary(.{
|
||||
.name = "glfw",
|
||||
.root_module = glfw_module,
|
||||
});
|
||||
glfw_module.addCSourceFiles(.{ .files = &[_][]const u8{
|
||||
"ext/glfw/src/cocoa_init.m",
|
||||
"ext/glfw/src/cocoa_joystick.m",
|
||||
"ext/glfw/src/cocoa_monitor.m",
|
||||
"ext/glfw/src/cocoa_time.c",
|
||||
"ext/glfw/src/cocoa_window.m",
|
||||
"ext/glfw/src/context.c",
|
||||
"ext/glfw/src/egl_context.c",
|
||||
"ext/glfw/src/glx_context.c",
|
||||
"ext/glfw/src/init.c",
|
||||
"ext/glfw/src/input.c",
|
||||
"ext/glfw/src/linux_joystick.c",
|
||||
"ext/glfw/src/monitor.c",
|
||||
"ext/glfw/src/nsgl_context.m",
|
||||
"ext/glfw/src/null_init.c",
|
||||
"ext/glfw/src/null_joystick.c",
|
||||
"ext/glfw/src/null_monitor.c",
|
||||
"ext/glfw/src/null_window.c",
|
||||
"ext/glfw/src/osmesa_context.c",
|
||||
"ext/glfw/src/platform.c",
|
||||
"ext/glfw/src/posix_module.c",
|
||||
"ext/glfw/src/posix_poll.c",
|
||||
"ext/glfw/src/posix_thread.c",
|
||||
"ext/glfw/src/posix_time.c",
|
||||
"ext/glfw/src/vulkan.c",
|
||||
"ext/glfw/src/wgl_context.c",
|
||||
"ext/glfw/src/win32_init.c",
|
||||
"ext/glfw/src/win32_joystick.c",
|
||||
"ext/glfw/src/win32_module.c",
|
||||
"ext/glfw/src/win32_monitor.c",
|
||||
"ext/glfw/src/win32_thread.c",
|
||||
"ext/glfw/src/win32_time.c",
|
||||
"ext/glfw/src/win32_window.c",
|
||||
"ext/glfw/src/window.c",
|
||||
"ext/glfw/src/wl_init.c",
|
||||
"ext/glfw/src/wl_monitor.c",
|
||||
"ext/glfw/src/wl_window.c",
|
||||
"ext/glfw/src/x11_init.c",
|
||||
"ext/glfw/src/x11_monitor.c",
|
||||
"ext/glfw/src/x11_window.c",
|
||||
"ext/glfw/src/xkb_unicode.c",
|
||||
}, .flags = &[_][]const u8{ "-D_GLFW_X11", "-Wall", "-Wextra" } });
|
||||
|
||||
const sideros = b.createModule(.{
|
||||
.root_source_file = b.path("src/sideros.zig"),
|
||||
.target = target,
|
||||
|
|
@ -88,7 +36,6 @@ pub fn build(b: *std.Build) void {
|
|||
renderer.addImport("ecs", ecs);
|
||||
ecs.addImport("renderer", renderer);
|
||||
|
||||
renderer.addIncludePath(b.path("ext/glfw/include"));
|
||||
compileAllShaders(b, renderer);
|
||||
|
||||
sideros.addImport("mods", mods);
|
||||
|
|
@ -104,10 +51,11 @@ pub fn build(b: *std.Build) void {
|
|||
}),
|
||||
});
|
||||
exe.root_module.addImport("sideros", sideros);
|
||||
exe.root_module.addCSourceFile(.{ .file = b.path("ext/xdg-shell.c") });
|
||||
exe.root_module.addIncludePath(b.path("ext"));
|
||||
|
||||
exe.linkSystemLibrary("vulkan");
|
||||
exe.linkSystemLibrary("wayland-client");
|
||||
exe.linkLibrary(glfw);
|
||||
exe.linkLibC();
|
||||
|
||||
b.installArtifact(exe);
|
||||
|
|
|
|||
4
src/c.zig
Normal file
4
src/c.zig
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
pub const c = @cImport({
|
||||
@cInclude("wayland-client.h");
|
||||
@cInclude("xdg-shell.h");
|
||||
});
|
||||
94
src/main.zig
94
src/main.zig
|
|
@ -4,73 +4,67 @@ const math = @import("sideros").math;
|
|||
const Input = @import("sideros").Input;
|
||||
const mods = @import("sideros").mods;
|
||||
const ecs = @import("sideros").ecs;
|
||||
const Renderer = @import("sideros").Renderer;
|
||||
//const Renderer = @import("sideros").Renderer;
|
||||
const wayland = @import("wayland.zig");
|
||||
|
||||
fn testSystem2(pool: *ecs.Pool) void {
|
||||
std.debug.print("{any}\n", .{pool.resources.input.isKeyDown(.a)});
|
||||
}
|
||||
//fn testSystem2(pool: *ecs.Pool) void {
|
||||
// std.debug.print("{any}\n", .{pool.resources.input.isKeyDown(.a)});
|
||||
//}
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
const allocator = gpa.allocator();
|
||||
defer if (gpa.deinit() != .ok) @panic("Leaked memory");
|
||||
|
||||
var global_runtime = mods.GlobalRuntime.init(allocator);
|
||||
defer global_runtime.deinit();
|
||||
try global_runtime.addFunction("debug", mods.Wasm.debug);
|
||||
//var global_runtime = mods.GlobalRuntime.init(allocator);
|
||||
//defer global_runtime.deinit();
|
||||
//try global_runtime.addFunction("debug", mods.Wasm.debug);
|
||||
|
||||
const file = try std.fs.cwd().openFile("assets/core.wasm", .{});
|
||||
const all = try file.readToEndAlloc(allocator, 1_000_000); // 1 MB
|
||||
defer allocator.free(all);
|
||||
var parser = try mods.Parser.init(allocator, all);
|
||||
defer parser.deinit();
|
||||
parser.parseModule() catch |err| {
|
||||
std.debug.print("[ERROR]: error at byte {x}(0x{x})\n", .{ parser.byte_idx, parser.bytes[parser.byte_idx] });
|
||||
return err;
|
||||
};
|
||||
const module = parser.module();
|
||||
// defer module.deinit(allocator);
|
||||
//const file = try std.fs.cwd().openFile("assets/core.wasm", .{});
|
||||
//const all = try file.readToEndAlloc(allocator, 1_000_000); // 1 MB
|
||||
//defer allocator.free(all);
|
||||
//var parser = try mods.Parser.init(allocator, all);
|
||||
//defer parser.deinit();
|
||||
//parser.parseModule() catch |err| {
|
||||
// std.debug.print("[ERROR]: error at byte {x}(0x{x})\n", .{ parser.byte_idx, parser.bytes[parser.byte_idx] });
|
||||
// return err;
|
||||
//};
|
||||
//const module = parser.module();
|
||||
//// defer module.deinit(allocator);
|
||||
|
||||
var runtime = try mods.Runtime.init(allocator, module, &global_runtime);
|
||||
defer runtime.deinit(allocator);
|
||||
//var runtime = try mods.Runtime.init(allocator, module, &global_runtime);
|
||||
//defer runtime.deinit(allocator);
|
||||
|
||||
var parameters = [_]mods.VM.Value{.{ .i32 = 17 }};
|
||||
try runtime.callExternal(allocator, .preinit, ¶meters);
|
||||
const result = runtime.stack.pop().?;
|
||||
std.debug.print("Result of preinit: {any}\n", .{result});
|
||||
var w = try Renderer.Window.create(800, 600, "sideros");
|
||||
defer w.destroy();
|
||||
//var parameters = [_]mods.VM.Value{.{ .i32 = 17 }};
|
||||
//try runtime.callExternal(allocator, .preinit, ¶meters);
|
||||
//const result = runtime.stack.pop().?;
|
||||
//std.debug.print("Result of preinit: {any}\n", .{result});
|
||||
//var w = try Renderer.Window.create(800, 600, "sideros");
|
||||
//defer w.destroy();
|
||||
|
||||
var r = try Renderer.init(allocator, w);
|
||||
defer r.deinit();
|
||||
//var r = try Renderer.init(allocator, w);
|
||||
//defer r.deinit();
|
||||
|
||||
const resources = ecs.Resources{
|
||||
.window = w,
|
||||
.renderer = r,
|
||||
.input = .{ .key_pressed = .{false} ** @intFromEnum(Input.KeyCode.menu) },
|
||||
};
|
||||
//const resources = ecs.Resources{
|
||||
// .window = w,
|
||||
// .renderer = r,
|
||||
// .input = .{ .key_pressed = .{false} ** @intFromEnum(Input.KeyCode.menu) },
|
||||
//};
|
||||
|
||||
var pool = try ecs.Pool.init(allocator, resources);
|
||||
defer pool.deinit();
|
||||
w.setResources(&pool.resources);
|
||||
try pool.addSystemGroup(&[_]ecs.System{
|
||||
Renderer.render,
|
||||
}, true);
|
||||
// try pool.addSystemGroup(&[_]ecs.System{
|
||||
// testSystem2,
|
||||
// });
|
||||
//var pool = try ecs.Pool.init(allocator, resources);
|
||||
//defer pool.deinit();
|
||||
//w.setResources(&pool.resources);
|
||||
//try pool.addSystemGroup(&[_]ecs.System{
|
||||
// Renderer.render,
|
||||
//}, true);
|
||||
//try pool.addSystemGroup(&[_]ecs.System{
|
||||
// testSystem2,
|
||||
//});
|
||||
|
||||
// for (0..1000) |_| {
|
||||
// const entity = try pool.createEntity();
|
||||
// try pool.addComponent(entity, ecs.components.Position{ .x = 1.0, .y = 0.5, .z = 3.0 });
|
||||
// try pool.addComponent(entity, ecs.components.Speed{ .speed = 5.0 });
|
||||
// }
|
||||
var last_time: f64 = 0.0;
|
||||
while (!w.shouldClose()) {
|
||||
const current_time = Renderer.Window.getTime();
|
||||
pool.resources.delta_time = current_time - last_time;
|
||||
last_time = current_time;
|
||||
Renderer.Window.pollEvents();
|
||||
pool.tick();
|
||||
}
|
||||
try wayland.init(allocator);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ current_frame: u32,
|
|||
vertex_buffer: vk.Buffer,
|
||||
index_buffer: vk.Buffer,
|
||||
|
||||
pub fn init(allocator: Allocator, w: Window) !Renderer {
|
||||
pub fn init(allocator: Allocator, display: ?*anyopaque, s: ?*anyopaque) !Renderer {
|
||||
const instance = try vk.Instance.create(allocator);
|
||||
|
||||
const surface = try vk.Surface.create(instance, w);
|
||||
const surface = try vk.Surface.create(instance, display, s);
|
||||
|
||||
var physical_device = try vk.PhysicalDevice.pick(allocator, instance);
|
||||
const device = try physical_device.create_device(surface, allocator, 2);
|
||||
|
|
@ -34,7 +34,7 @@ pub fn init(allocator: Allocator, w: Window) !Renderer {
|
|||
|
||||
const render_pass = try vk.RenderPass(2).create(allocator, device, surface, physical_device);
|
||||
|
||||
const swapchain = try vk.Swapchain(2).create(allocator, surface, device, physical_device, w, render_pass);
|
||||
const swapchain = try vk.Swapchain(2).create(allocator, surface, device, physical_device, render_pass);
|
||||
|
||||
const graphics_pipeline = try vk.GraphicsPipeline(2).create(device, swapchain, render_pass, vertex_shader, fragment_shader);
|
||||
|
||||
|
|
@ -75,8 +75,9 @@ pub fn deinit(self: Renderer) void {
|
|||
}
|
||||
|
||||
// TODO: render is maybe a bad name? something like present() or submit() is better?
|
||||
pub fn render(pool: *ecs.Pool) anyerror!void {
|
||||
var renderer = pool.resources.renderer;
|
||||
//pub fn render(pool: *ecs.Pool) anyerror!void {
|
||||
pub fn render(renderer: *Renderer) anyerror!void {
|
||||
//var renderer = pool.resources.renderer;
|
||||
|
||||
try renderer.device.waitFence(renderer.current_frame);
|
||||
const image = try renderer.swapchain.nextImage(renderer.device, renderer.current_frame);
|
||||
|
|
@ -94,4 +95,6 @@ pub fn render(pool: *ecs.Pool) anyerror!void {
|
|||
try renderer.device.submit(renderer.swapchain, image, renderer.current_frame);
|
||||
|
||||
renderer.current_frame = (renderer.current_frame + 1) % 2;
|
||||
|
||||
renderer.device.waitIdle();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,9 +10,8 @@ pub const Error = error{
|
|||
};
|
||||
|
||||
pub fn getExtensions() [][*c]const u8 {
|
||||
var extension_count: u32 = undefined;
|
||||
const raw: [*c][*c]const u8 = c.glfwGetRequiredInstanceExtensions(&extension_count);
|
||||
const extensions = raw[0..extension_count];
|
||||
const raw: [*c][*c]const u8 = .{"VK_KHR_wayland_surface", "VK_KHR_surface"};
|
||||
const extensions = raw[0..2];
|
||||
|
||||
return extensions;
|
||||
}
|
||||
|
|
@ -20,25 +19,10 @@ pub fn getExtensions() [][*c]const u8 {
|
|||
title: []const u8,
|
||||
width: usize,
|
||||
height: usize,
|
||||
raw: *c.GLFWwindow,
|
||||
raw: *c.wl_display,
|
||||
|
||||
pub fn create(width: usize, height: usize, title: []const u8) !Window {
|
||||
if (c.glfwInit() != c.GLFW_TRUE) {
|
||||
const status = c.glfwGetError(null);
|
||||
|
||||
return switch (status) {
|
||||
c.GLFW_PLATFORM_UNAVAILABLE => Error.platform_unavailable,
|
||||
c.GLFW_PLATFORM_ERROR => Error.platform_error,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
c.glfwWindowHint(c.GLFW_RESIZABLE, c.GLFW_FALSE);
|
||||
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
||||
const raw = c.glfwCreateWindow(@intCast(width), @intCast(height), title.ptr, null, null);
|
||||
c.glfwShowWindow(raw);
|
||||
_ = c.glfwSetKeyCallback(raw, keyCallback);
|
||||
_ = c.glfwSetCursorPosCallback(raw, cursorCallback);
|
||||
const raw = c.wl_display_connect(null);
|
||||
|
||||
return Window{
|
||||
.title = title,
|
||||
|
|
@ -52,12 +36,8 @@ pub fn setResources(self: *Window, resources: *ecs.Resources) void {
|
|||
c.glfwSetWindowUserPointer(self.raw, resources);
|
||||
}
|
||||
|
||||
pub fn pollEvents() void {
|
||||
c.glfwPollEvents();
|
||||
}
|
||||
|
||||
pub fn shouldClose(self: Window) bool {
|
||||
return c.glfwWindowShouldClose(self.raw) == c.GLFW_TRUE;
|
||||
return c.wl_display_dispatch(self.raw) != -1;
|
||||
}
|
||||
|
||||
pub fn size(self: Window) struct { usize, usize } {
|
||||
|
|
@ -70,8 +50,7 @@ pub fn size(self: Window) struct { usize, usize } {
|
|||
}
|
||||
|
||||
pub fn destroy(self: Window) void {
|
||||
c.glfwDestroyWindow(self.raw);
|
||||
c.glfwTerminate();
|
||||
c.wl_display_disconnect(self.raw);
|
||||
}
|
||||
|
||||
pub fn getTime() f64 {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
pub const c = @cImport({
|
||||
@cDefine("GLFW_INCLUDE_NONE", {});
|
||||
@cInclude("vulkan/vulkan.h");
|
||||
@cInclude("GLFW/glfw3.h");
|
||||
@cInclude("vulkan/vulkan_wayland.h");
|
||||
@cInclude("wayland-client.h");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -73,7 +73,8 @@ pub const Instance = struct {
|
|||
handle: c.VkInstance,
|
||||
|
||||
pub fn create(allocator: Allocator) !Instance {
|
||||
const extensions = Window.getExtensions();
|
||||
const extensions = [_][*c]const u8 {c.VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, c.VK_KHR_SURFACE_EXTENSION_NAME};
|
||||
//const extensions = [_][:0]const u8 {"VK_KHR_wayland_surface\0", "VK_KHR_surface\0"};
|
||||
|
||||
// Querry avaliable extensions size
|
||||
var avaliableExtensionsCount: u32 = 0;
|
||||
|
|
@ -140,7 +141,7 @@ pub const Instance = struct {
|
|||
.sType = c.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pApplicationInfo = &app_info,
|
||||
.enabledExtensionCount = @intCast(extensions.len),
|
||||
.ppEnabledExtensionNames = extensions.ptr,
|
||||
.ppEnabledExtensionNames = @ptrCast(extensions[0..]),
|
||||
.enabledLayerCount = @intCast(newLayers.items.len),
|
||||
.ppEnabledLayerNames = newLayers.items.ptr,
|
||||
};
|
||||
|
|
@ -267,7 +268,7 @@ pub fn RenderPass(comptime n: usize) type {
|
|||
|
||||
pub fn begin(self: Self, swapchain: Swapchain(n), device: Device(n), image: usize, frame: usize) void {
|
||||
std.debug.assert(frame < n);
|
||||
const clear_color: c.VkClearValue = .{ .color = .{ .float32 = .{ 0.0, 0.0, 0.0, 1.0 } } };
|
||||
const clear_color: c.VkClearValue = .{ .color = .{ .float32 = .{ 1.0, 0.0, 0.0, 1.0 } } };
|
||||
|
||||
const begin_info: c.VkRenderPassBeginInfo = .{
|
||||
.sType = c.VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
|
|
@ -604,7 +605,7 @@ pub fn Swapchain(comptime n: usize) type {
|
|||
}
|
||||
|
||||
// TODO: Allow to recreate so Window can be resized
|
||||
pub fn create(allocator: Allocator, surface: Surface, device: Device(n), physical_device: PhysicalDevice, w: Window, render_pass: RenderPass(n)) !Self {
|
||||
pub fn create(allocator: Allocator, surface: Surface, device: Device(n), physical_device: PhysicalDevice, render_pass: RenderPass(n)) !Self {
|
||||
const present_modes = try surface.presentModes(allocator, physical_device);
|
||||
defer allocator.free(present_modes);
|
||||
const capabilities = try surface.capabilities(physical_device);
|
||||
|
|
@ -625,7 +626,7 @@ pub fn Swapchain(comptime n: usize) type {
|
|||
if (capabilities.currentExtent.width != std.math.maxInt(u32)) {
|
||||
extent = capabilities.currentExtent;
|
||||
} else {
|
||||
const width, const height = w.size();
|
||||
const width: u32, const height: u32 = .{800, 600};
|
||||
|
||||
extent = .{
|
||||
.width = @intCast(width),
|
||||
|
|
@ -756,10 +757,16 @@ pub fn Swapchain(comptime n: usize) type {
|
|||
pub const Surface = struct {
|
||||
handle: c.VkSurfaceKHR,
|
||||
|
||||
pub fn create(instance: Instance, w: Window) !Surface {
|
||||
pub fn create(instance: Instance, display: ?*anyopaque, surface: ?*anyopaque) !Surface {
|
||||
var handle: c.VkSurfaceKHR = undefined;
|
||||
try mapError(c.glfwCreateWindowSurface(instance.handle, w.raw, null, &handle));
|
||||
return Surface{
|
||||
const create_info: c.VkWaylandSurfaceCreateInfoKHR = .{
|
||||
.sType = c.VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
|
||||
.display = @ptrCast(display),
|
||||
.surface = @ptrCast(surface),
|
||||
};
|
||||
|
||||
try mapError(c.vkCreateWaylandSurfaceKHR(instance.handle, &create_info, null, &handle));
|
||||
return .{
|
||||
.handle = handle,
|
||||
};
|
||||
}
|
||||
|
|
@ -834,7 +841,7 @@ pub fn Device(comptime n: usize) type {
|
|||
}
|
||||
|
||||
pub fn waitFence(self: Self, frame: usize) !void {
|
||||
std.debug.assert(frame < n);
|
||||
//std.debug.assert(frame < n);
|
||||
try mapError(c.vkWaitForFences(self.handle, 1, &self.in_flight_fence[frame], c.VK_TRUE, std.math.maxInt(u64)));
|
||||
try mapError(c.vkResetFences(self.handle, 1, &self.in_flight_fence[frame]));
|
||||
}
|
||||
|
|
@ -917,28 +924,30 @@ pub fn Device(comptime n: usize) type {
|
|||
|
||||
pub fn submit(self: Self, swapchain: Swapchain(n), image: usize, frame: usize) !void {
|
||||
std.debug.assert(frame < n);
|
||||
//const wait_semaphores: [1]c.VkSemaphore = .{self.image_available[frame]};
|
||||
//const signal_semaphores: [1]c.VkSemaphore = .{self.render_finished[frame]};
|
||||
//const swapchains: [1]c.VkSwapchainKHR = .{swapchain.handle};
|
||||
const wait_semaphores: [1]c.VkSemaphore = .{self.image_available[frame]};
|
||||
const signal_semaphores: [1]c.VkSemaphore = .{self.render_finished[frame]};
|
||||
const swapchains: [1]c.VkSwapchainKHR = .{swapchain.handle};
|
||||
_ = swapchains;
|
||||
const stages: []const u32 = &[_]u32{c.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||
|
||||
const submit_info: c.VkSubmitInfo = .{
|
||||
.sType = c.VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &self.image_available[frame],
|
||||
.pWaitSemaphores = wait_semaphores[0..].ptr,
|
||||
.pWaitDstStageMask = stages.ptr,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &self.command_buffers[frame],
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &self.render_finished[frame],
|
||||
.pSignalSemaphores = signal_semaphores[0..].ptr,
|
||||
};
|
||||
|
||||
_ = c.vkResetFences(self.handle, 1, &self.in_flight_fence[frame]);
|
||||
try mapError(c.vkQueueSubmit(self.graphics_queue, 1, &submit_info, self.in_flight_fence[frame]));
|
||||
|
||||
const present_info: c.VkPresentInfoKHR = .{
|
||||
.sType = c.VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &self.render_finished[frame],
|
||||
.pWaitSemaphores = signal_semaphores[0..].ptr,
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &swapchain.handle,
|
||||
.pImageIndices = @ptrCast(&image),
|
||||
|
|
|
|||
152
src/wayland.zig
Normal file
152
src/wayland.zig
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
const c = @import("c.zig").c;
|
||||
const std = @import("std");
|
||||
const Renderer = @import("sideros").Renderer;
|
||||
|
||||
var resize = false;
|
||||
var quit = false;
|
||||
var new_width: u32 = 0;
|
||||
var new_height: u32 = 0;
|
||||
|
||||
const State = struct {
|
||||
compositor: ?*c.wl_compositor = null,
|
||||
shell: ?*c.xdg_wm_base = null,
|
||||
surface: ?*c.wl_surface = null,
|
||||
renderer: *Renderer = undefined,
|
||||
configured: bool = false,
|
||||
};
|
||||
|
||||
fn registryHandleGlobal(data: ?*anyopaque, registry: ?*c.wl_registry, name: u32, interface: [*c]const u8, version: u32) callconv(.c) void {
|
||||
_ = version;
|
||||
const state: *State = @alignCast(@ptrCast(data));
|
||||
if (std.mem.eql(u8, std.mem.span(interface), std.mem.span(c.wl_compositor_interface.name))) {
|
||||
state.compositor = @ptrCast(c.wl_registry_bind(registry.?, name, &c.wl_compositor_interface, 4));
|
||||
} else if (std.mem.eql(u8, @as([:0]const u8, std.mem.span(interface)), std.mem.span(c.xdg_wm_base_interface.name))) {
|
||||
state.shell = @ptrCast(c.wl_registry_bind(registry.?, name, &c.xdg_wm_base_interface, 4));
|
||||
_ = c.xdg_wm_base_add_listener(state.shell, &shell_listener, null);
|
||||
}
|
||||
}
|
||||
|
||||
fn registryHandleGlobalRemove(data: ?*anyopaque, registry: ?*c.wl_registry, name: u32) callconv(.c) void {
|
||||
_ = data;
|
||||
_ = registry;
|
||||
_ = name;
|
||||
}
|
||||
|
||||
fn shellHandlePing(data: ?*anyopaque, shell: ?*c.xdg_wm_base, serial: u32) callconv(.c) void {
|
||||
_ = data;
|
||||
c.xdg_wm_base_pong(shell, serial);
|
||||
}
|
||||
|
||||
fn shellHandleSurfaceConfigure(data: ?*anyopaque, surface: ?*c.xdg_surface, serial: u32) callconv(.c) void {
|
||||
const state: *State = @alignCast(@ptrCast(data));
|
||||
|
||||
c.xdg_surface_ack_configure(surface, serial);
|
||||
state.configured = true;
|
||||
}
|
||||
|
||||
fn toplevelHandleConfigure(data: ?*anyopaque, toplevel: ?*c.xdg_toplevel, width: i32, height: i32, states: ?*c.wl_array) callconv(.c) void {
|
||||
_ = data;
|
||||
_ = toplevel;
|
||||
_ = states;
|
||||
|
||||
if (width != 0 and height != 0) {
|
||||
resize = true;
|
||||
new_width = @intCast(width);
|
||||
new_height = @intCast(height);
|
||||
}
|
||||
}
|
||||
|
||||
fn toplevelHandleClose(data: ?*anyopaque, toplevel: ?*c.xdg_toplevel) callconv(.c) void {
|
||||
_ = data;
|
||||
_ = toplevel;
|
||||
|
||||
quit = true;
|
||||
}
|
||||
|
||||
fn toplevelHandleConfigureBounds(data: ?*anyopaque, toplevel: ?*c.xdg_toplevel, width: i32, height: i32) callconv(.c) void {
|
||||
_ = data;
|
||||
_ = toplevel;
|
||||
_ = width;
|
||||
_ = height;
|
||||
}
|
||||
|
||||
fn frameHandleDone(data: ?*anyopaque, callback: ?*c.wl_callback, time: u32) callconv(.c) void {
|
||||
_ = time;
|
||||
const state: *State = @alignCast(@ptrCast(data));
|
||||
_ = c.wl_callback_destroy(callback);
|
||||
const cb = c.wl_surface_frame(state.surface);
|
||||
_ = c.wl_callback_add_listener(cb, &frame_listener, state);
|
||||
|
||||
state.renderer.render() catch @panic("can't render");
|
||||
_ = c.wl_surface_commit(state.surface);
|
||||
}
|
||||
|
||||
const frame_listener: c.wl_callback_listener = .{
|
||||
.done = frameHandleDone,
|
||||
};
|
||||
|
||||
const shell_listener: c.xdg_wm_base_listener = .{
|
||||
.ping = shellHandlePing,
|
||||
};
|
||||
|
||||
const surface_listener: c.xdg_surface_listener = .{
|
||||
.configure = shellHandleSurfaceConfigure,
|
||||
};
|
||||
|
||||
const toplevel_listener: c.xdg_toplevel_listener = .{
|
||||
.configure = toplevelHandleConfigure,
|
||||
.configure_bounds = toplevelHandleConfigureBounds,
|
||||
.close = toplevelHandleClose,
|
||||
};
|
||||
|
||||
const registry_listener: c.wl_registry_listener = .{
|
||||
.global = registryHandleGlobal,
|
||||
.global_remove = registryHandleGlobalRemove,
|
||||
};
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) !void {
|
||||
var state: State = .{};
|
||||
const display = c.wl_display_connect(null);
|
||||
defer c.wl_display_disconnect(display);
|
||||
if (display == null) {
|
||||
return error.ConnectionFailed;
|
||||
}
|
||||
|
||||
const registry = c.wl_display_get_registry(display);
|
||||
_ = c.wl_registry_add_listener(registry, ®istry_listener, @ptrCast(&state));
|
||||
_ = c.wl_display_roundtrip(display);
|
||||
|
||||
const surface = c.wl_compositor_create_surface(state.compositor);
|
||||
const xdg_surface = c.xdg_wm_base_get_xdg_surface(state.shell, surface);
|
||||
_ = c.xdg_surface_add_listener(xdg_surface, &surface_listener, @ptrCast(&state));
|
||||
|
||||
state.surface = surface;
|
||||
|
||||
const toplevel = c.xdg_surface_get_toplevel(xdg_surface);
|
||||
_ = c.xdg_toplevel_add_listener(toplevel, &toplevel_listener, null);
|
||||
const title = [_]u8 {'s', 'i', 'd', 'e', 'r', 'o', 's', 0};
|
||||
c.xdg_toplevel_set_title(toplevel, @ptrCast(&title[0]));
|
||||
c.xdg_toplevel_set_app_id(toplevel, @ptrCast(&title[0]));
|
||||
c.xdg_toplevel_set_min_size(toplevel, 800, 600);
|
||||
c.xdg_toplevel_set_max_size(toplevel, 800, 600);
|
||||
|
||||
_ = c.wl_surface_commit(surface);
|
||||
|
||||
while (!state.configured) {
|
||||
_ = c.wl_display_dispatch(display);
|
||||
}
|
||||
|
||||
var renderer = try Renderer.init(allocator, @ptrCast(display), @ptrCast(surface));
|
||||
defer renderer.deinit();
|
||||
try renderer.render();
|
||||
|
||||
state.renderer = &renderer;
|
||||
|
||||
const cb = c.wl_surface_frame(surface);
|
||||
_ = c.wl_callback_add_listener(cb, &frame_listener, @ptrCast(&state));
|
||||
_ = c.wl_surface_commit(surface);
|
||||
|
||||
while (!quit) {
|
||||
_ = c.wl_display_dispatch(display);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue