aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.zig13
-rw-r--r--src/wl/buffer.zig51
-rw-r--r--src/wl/compositor.zig16
-rw-r--r--src/wl/display.zig14
-rw-r--r--src/wl/root.zig2
-rw-r--r--src/wl/shm/format.zig19
-rw-r--r--src/wl/shm/pool.zig48
-rw-r--r--src/wl/surface.zig105
8 files changed, 262 insertions, 6 deletions
diff --git a/src/main.zig b/src/main.zig
index b822109..f02a603 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -44,8 +44,19 @@ pub fn main() !void {
log.debug("{}", .{shm});
}
- const pool = try wl.Shm.instances.items[0].create_pool(&ctx, 1024);
+ const pool = try wl.Shm.instances.items[0].create_pool(&ctx, 800 * 600 * (wl.Shm.Format.argb8888).bytes_per_pixel());
defer pool.deinit(&ctx);
try display.roundtrip(allocator);
+
+ const buffer = try pool.create_buffer(&ctx, 0, 800, 600, .argb8888);
+ defer ctx.display.request(buffer, .{ .destroy = {} }) catch |e| log.err("error {}", .{e});
+
+ const surface = try wl.Compositor.instances.items[0].create_surface(&ctx);
+ defer surface.deinit(&ctx);
+
+ try display.roundtrip(allocator);
+
+ log.debug("{}", .{buffer});
+ log.debug("{}", .{surface});
}
diff --git a/src/wl/buffer.zig b/src/wl/buffer.zig
new file mode 100644
index 0000000..6dd83be
--- /dev/null
+++ b/src/wl/buffer.zig
@@ -0,0 +1,51 @@
+const std = @import("std");
+const wayland = @import("../root.zig");
+const wl = wayland.wl;
+
+pub fn Buffer(fmt: wl.Shm.Format) type {
+ return struct {
+ const Self = @This();
+
+ pub const Request = union(enum) {
+ destroy: void,
+ };
+
+ pub const Events = wayland.EventSet(Self, .{});
+
+ handle: wayland.Object.Ref,
+ data: []wl.Shm.Format.Pixel(fmt),
+ width: usize,
+ height: usize,
+
+ pub fn init(
+ self: *Self,
+ ctx: *const wayland.Context,
+ width: usize,
+ height: usize,
+ data: []u8,
+ ) !void {
+ self.* = .{
+ .handle = try ctx.display.registry.add_object(
+ ctx.allocator,
+ wayland.Object.from_self(self),
+ ),
+ .data = @alignCast(@ptrCast(data)),
+ .width = width,
+ .height = height,
+ };
+ }
+
+ pub fn format(
+ self: *const Self,
+ comptime f: []const u8,
+ options: std.fmt.FormatOptions,
+ writer: anytype,
+ ) !void {
+ _ = f;
+ _ = options;
+
+ try writer.print("wl.buffer<{s}> {{ {}x{} }}", .{@tagName(fmt), self.width, self.height});
+ }
+ };
+}
+
diff --git a/src/wl/compositor.zig b/src/wl/compositor.zig
index 18db0f0..ae8d15e 100644
--- a/src/wl/compositor.zig
+++ b/src/wl/compositor.zig
@@ -5,7 +5,7 @@ const wl = wayland.wl;
const Self = @This();
pub const Events = wayland.EventSet(Self, .{});
-pub const Requests = union(enum) {
+pub const Request = union(enum) {
create_surface: struct { wayland.Object.Ref },
create_region: struct { wayland.Object.Ref },
};
@@ -52,3 +52,17 @@ pub fn format(
try writer.print("wl.compositor", .{});
}
+
+pub fn create_surface(
+ self: *Self,
+ ctx: *const wayland.Context
+) !*wl.Surface {
+ const surface = try ctx.allocator.create(wl.Surface);
+ errdefer ctx.allocator.destroy(surface);
+
+ try surface.init(ctx);
+
+ try ctx.display.request(self, .{ .create_surface = .{ surface.handle } });
+
+ return surface;
+}
diff --git a/src/wl/display.zig b/src/wl/display.zig
index c9e2e6e..2a7b94c 100644
--- a/src/wl/display.zig
+++ b/src/wl/display.zig
@@ -82,7 +82,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
inline for (@typeInfo(tag_type).@"enum".fields) |f| {
if (f.value == opcode) {
- const data = @field(args, f.name);
+ const data = if (@FieldType(@TypeOf(args), f.name) == void) .{} else @field(args, f.name);
const id: u32 = @truncate(object.handle);
var size: u32 = 8;
@@ -103,6 +103,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
const padding_size: usize = padding_len(ptr.child, value.len);
size += @intCast(@sizeOf(u32) + (value.len * @sizeOf(ptr.child)) + padding_size);
} else @compileError(std.fmt.comptimePrint("size: unsupported type {}", .{t})),
+ .@"enum" => size += @sizeOf(u32),
else => @compileError(std.fmt.comptimePrint("size: unsupported type {}", .{t})),
},
}
@@ -150,6 +151,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
_ = try self.stream.writeAll(std.mem.asBytes(&@as(u8, 0)));
}
} else @compileError(std.fmt.comptimePrint("size: unsupported type {}", .{t})),
+ .@"enum" => _ = try self.stream.writeAll(std.mem.asBytes(&@as(u32, @intFromEnum(value)))),
else => @compileError(std.fmt.comptimePrint("size: unsupported type {}", .{t})),
},
}
@@ -239,6 +241,7 @@ test "request" {
req3: struct { []const u8 },
req4: struct { []const u16 },
req5: struct { wayland.types.Fd },
+ req6: void,
};
pub const Events = wayland.EventSet(@This(), .{});
@@ -271,6 +274,7 @@ test "request" {
try displ.request(&sample, .{ .req3 = .{"abcd"} });
try displ.request(&sample, .{ .req4 = .{&[_]u16{ 1, 32, 4, 5, 5 }} });
try displ.request(&sample, .{ .req5 = .{ .{ .fd = displ.stream.handle } } });
+ try displ.request(&sample, .{ .req6 = {} });
}
const conn = try server.accept();
@@ -330,6 +334,14 @@ test "request" {
test_buffer[0..size],
);
+ size = try file.readAll(test_buffer[0..8]);
+ try std.testing.expectEqualSlices(
+ u8,
+ &(std.mem.toBytes(@as(u32, 42)) ++
+ std.mem.toBytes(@as(u32, (8 << 16) | 5))),
+ test_buffer[0..size],
+ );
+
size = try file.readAll(test_buffer[0..]);
try std.testing.expectEqual(0, size);
}
diff --git a/src/wl/root.zig b/src/wl/root.zig
index 43eb531..887811c 100644
--- a/src/wl/root.zig
+++ b/src/wl/root.zig
@@ -4,3 +4,5 @@ pub const Callback = @import("callback.zig");
pub const Output = @import("output/root.zig");
pub const Compositor = @import("compositor.zig");
pub const Shm = @import("shm/root.zig");
+pub const Buffer = @import("buffer.zig").Buffer;
+pub const Surface = @import("surface.zig");
diff --git a/src/wl/shm/format.zig b/src/wl/shm/format.zig
index e2766ab..6c2a30f 100644
--- a/src/wl/shm/format.zig
+++ b/src/wl/shm/format.zig
@@ -122,4 +122,23 @@ pub const Format = enum(u32) {
xvuy8888 = 0x59555658,
vyuy = 0x59555956,
uyvy = 0x59565955,
+
+ pub fn bytes_per_pixel(self: @This()) usize {
+ return switch (self) {
+ .argb8888 => 4,
+ else => @panic("unimplemented"),
+ };
+ }
+
+ pub fn Pixel(self: @This()) type {
+ return switch (self) {
+ .argb8888 => packed struct {
+ alpha: u8,
+ red: u8,
+ green: u8,
+ blue: u8
+ },
+ else => @panic("unimplemented"),
+ };
+ }
};
diff --git a/src/wl/shm/pool.zig b/src/wl/shm/pool.zig
index 1f42a17..40486d6 100644
--- a/src/wl/shm/pool.zig
+++ b/src/wl/shm/pool.zig
@@ -6,10 +6,12 @@ const AnonymousFile = wl.Shm.AnonymousFile;
const Self = @This();
+const log = std.log.scoped(.@"wl.shm.pool");
+
pub const Events = wayland.EventSet(@This(), .{});
-pub const Requests = union(enum) {
- create_buffer: struct { u32, u32, u32, u32, u32, Format },
- destroy: struct {},
+pub const Request = union(enum) {
+ create_buffer: struct { wayland.Object.Ref, u32, u32, u32, u32, Format },
+ destroy: void,
resize: struct { u32 },
};
@@ -40,5 +42,45 @@ pub fn deinit(self: *Self, ctx: *const wayland.Context) void {
self.file.close();
std.posix.munmap(@alignCast(self.buffer));
ctx.display.registry.disable_object(self.handle);
+ ctx.display.request(self, .{ .destroy = {} }) catch |e| {
+ log.err("error on deinit: {}", .{e});
+ };
self.* = undefined;
}
+
+pub fn create_buffer(
+ self: *Self,
+ ctx: *const wayland.Context,
+ offset: usize,
+ width: usize,
+ height: usize,
+ comptime format: Format,
+) !*wl.Buffer(format) {
+ const stride = width * format.bytes_per_pixel();
+ const data = self.buffer[offset..offset + stride * height];
+
+ const buffer = try ctx.allocator.create(wl.Buffer(format));
+ errdefer ctx.allocator.destroy(buffer);
+ try buffer.init(
+ ctx,
+ width,
+ height,
+ data,
+ );
+
+ try ctx.display.request(
+ self,
+ .{
+ .create_buffer = .{
+ buffer.handle,
+ @truncate(offset),
+ @truncate(width),
+ @truncate(height),
+ @truncate(stride),
+ format,
+ }
+ }
+ );
+
+ return buffer;
+}
diff --git a/src/wl/surface.zig b/src/wl/surface.zig
new file mode 100644
index 0000000..7b5116e
--- /dev/null
+++ b/src/wl/surface.zig
@@ -0,0 +1,105 @@
+const std = @import("std");
+const wayland = @import("../root.zig");
+const wl = wayland.wl;
+
+const Self = @This();
+
+pub const Request = union(enum) {
+ destroy: void,
+ attach: struct { ?wayland.Object.Ref, u32, u32 },
+ damage: struct { u32, u32, u32, u32 },
+ frame: struct { wayland.Object.Ref },
+ set_opaque_region: struct { ?wayland.Object.Ref },
+ set_input_region: struct { ?wayland.Object.Ref },
+ commit: void,
+ set_buffer_transform: struct { wl.Output.Format },
+ set_buffer_scale: struct { u32 },
+ damage_buffer: struct { u32, u32, u32, u32 },
+ offset: struct { i32, i32 },
+};
+
+pub const Events = wayland.EventSet(Self, .{
+ enter,
+ leave,
+ preferred_buffer_scale_announced,
+ preferred_buffer_transform_announced,
+});
+
+handle: wayland.Object.Ref,
+preferred_buffer_scale: u32 = 1,
+preferred_buffer_transform: wl.Output.Transform = .normal,
+
+pub fn init(
+ self: *Self,
+ ctx: *const wayland.Context,
+) !void {
+ self.* = .{
+ .handle = try ctx.display.registry.add_object(
+ ctx.allocator,
+ wayland.Object.from_self(self),
+ ),
+ };
+}
+
+pub fn deinit(
+ self: *Self,
+ ctx: *const wayland.Context,
+) void {
+ ctx.display.registry.disable_object(self.handle);
+}
+
+fn enter(
+ self: *Self,
+ ctx: *const wayland.Context,
+ output: *wayland.Object,
+) void {
+ _ = self;
+ _ = ctx;
+ _ = output;
+ // TODO: implement
+}
+
+fn leave(
+ self: *Self,
+ ctx: *const wayland.Context,
+ output: *wayland.Object,
+) void {
+ _ = self;
+ _ = ctx;
+ _ = output;
+ // TODO: implement
+}
+
+fn preferred_buffer_scale_announced(
+ self: *Self,
+ ctx: *const wayland.Context,
+ factor: u32,
+) void {
+ _ = ctx;
+ self.preferred_buffer_scale = factor;
+}
+
+
+fn preferred_buffer_transform_announced(
+ self: *Self,
+ ctx: *const wayland.Context,
+ transform: wl.Output.Transform,
+) void {
+ _ = ctx;
+ self.preferred_buffer_transform = transform;
+}
+
+pub fn format(
+ self: *const Self,
+ comptime fmt: []const u8,
+ options: std.fmt.FormatOptions,
+ writer: anytype,
+) !void {
+ _ = fmt;
+ _ = options;
+
+ try writer.print("wl.surface {{ preferred_scale = {}, preferred_transform = {s} }}", .{
+ self.preferred_buffer_scale,
+ @tagName(self.preferred_buffer_transform),
+ });
+}