mirror of
https://mzte.de/git/LordMZTE/dotfiles.git
synced 2024-11-13 05:22:08 +01:00
wlbg: only do one frame per minute
F gpu
This commit is contained in:
parent
1e04919f26
commit
7c64072005
4 changed files with 125 additions and 31 deletions
|
@ -16,6 +16,10 @@ pub fn build(b: *std.Build) void {
|
|||
.optimize = optimize,
|
||||
});
|
||||
|
||||
exe.addModule("xev", b.dependency("xev", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}).module("xev"));
|
||||
exe.addModule("wayland", wayland_mod);
|
||||
|
||||
scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml");
|
||||
|
|
|
@ -7,5 +7,9 @@
|
|||
.url = "https://git.mzte.de/LordMZTE/zig-wayland/archive/85722422985f928087e56d90c3617ecb04232486.tar.gz",
|
||||
.hash = "1220d992b223e473988d203d66d262e54141b59559c09587eb00231c800d46f9b408",
|
||||
},
|
||||
.xev = .{
|
||||
.url = "https://github.com/mitchellh/libxev/archive/5ecbc871f3bfa80fb7bf0fa853866cb93b99bc18.tar.gz",
|
||||
.hash = "1220416854e424601ecc9814afb461a5dc9cf95db5917d82f794594a58ffc723b82c",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ const OutputInfo = @import("OutputInfo.zig");
|
|||
|
||||
egl_dpy: c.EGLDisplay,
|
||||
bg_shader_program: c_uint,
|
||||
time: f64,
|
||||
|
||||
const Gfx = @This();
|
||||
|
||||
|
@ -31,7 +30,6 @@ pub fn init(egl_dpy: c.EGLDisplay) !Gfx {
|
|||
return .{
|
||||
.egl_dpy = egl_dpy,
|
||||
.bg_shader_program = program,
|
||||
.time = 0.0,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -40,15 +38,15 @@ pub fn deinit(self: *Gfx) void {
|
|||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
pub fn drawBackground(
|
||||
self: *Gfx,
|
||||
dt: f32,
|
||||
dt: i64,
|
||||
egl_surface: c.EGLSurface,
|
||||
info: OutputInfo,
|
||||
base_xoff: i32,
|
||||
base_yoff: i32,
|
||||
) !void {
|
||||
self.time += dt;
|
||||
_ = dt;
|
||||
|
||||
// There's just about a 0% chance this works properly when monitors have different resolutions,
|
||||
// but I can't even begin thinking about that.
|
||||
|
@ -76,9 +74,11 @@ pub fn draw(
|
|||
c.glVertexAttribPointer(1, 2, c.GL_FLOAT, c.GL_FALSE, @sizeOf(f32) * 5, @ptrFromInt(@intFromPtr(&vertices) + @sizeOf(f32) * 3));
|
||||
c.glEnableVertexAttribArray(1);
|
||||
|
||||
c.glUniform1f(c.glGetUniformLocation(self.bg_shader_program, "time"), @as(f32, @floatCast(self.time / 10000.0)));
|
||||
const rand = std.crypto.random.float(f32);
|
||||
c.glUniform1f(c.glGetUniformLocation(self.bg_shader_program, "time"), rand * 2000.0 - 1000.0);
|
||||
|
||||
c.glDrawArrays(c.GL_TRIANGLES, 0, vertices.len / 3);
|
||||
|
||||
if (c.eglSwapBuffers(self.egl_dpy, egl_surface) != c.EGL_TRUE) return error.EGLError;
|
||||
if (c.eglSwapInterval(self.egl_dpy, 0) != c.EGL_TRUE or
|
||||
c.eglSwapBuffers(self.egl_dpy, egl_surface) != c.EGL_TRUE) return error.EGLError;
|
||||
}
|
||||
|
|
|
@ -12,9 +12,11 @@ const wl = wayland.client.wl;
|
|||
const zwlr = wayland.client.zwlr;
|
||||
const zxdg = wayland.client.zxdg;
|
||||
|
||||
const fps = 10;
|
||||
|
||||
pub fn main() !void {
|
||||
std.log.info("initializing event loop", .{});
|
||||
var loop = try xev.Loop.init(.{});
|
||||
defer loop.deinit();
|
||||
|
||||
std.log.info("connecting to wayland display", .{});
|
||||
const dpy = try wl.Display.connect(null);
|
||||
defer dpy.disconnect();
|
||||
|
@ -146,32 +148,116 @@ pub fn main() !void {
|
|||
var gfx = try Gfx.init(egl_dpy);
|
||||
defer gfx.deinit();
|
||||
|
||||
var timer = try std.time.Timer.start();
|
||||
var prev_time = std.time.milliTimestamp();
|
||||
while (true) {
|
||||
const now_time = std.time.milliTimestamp();
|
||||
const delta_time: f32 = @floatFromInt(now_time - prev_time);
|
||||
prev_time = now_time;
|
||||
var rbgdata = RenderBackgroundData{
|
||||
.gfx = &gfx,
|
||||
.egl_dpy = egl_dpy,
|
||||
.egl_ctx = egl_ctx,
|
||||
.outputs = output_windows,
|
||||
.output_info = output_info,
|
||||
.last_time = loop.now(),
|
||||
.base_offset = .{ base_xoff, base_yoff },
|
||||
};
|
||||
|
||||
for (output_windows, output_info) |output, info| {
|
||||
if (c.eglMakeCurrent(
|
||||
egl_dpy,
|
||||
output.egl_surface,
|
||||
output.egl_surface,
|
||||
egl_ctx,
|
||||
) != c.EGL_TRUE) return error.EGLError;
|
||||
try gfx.draw(delta_time, output.egl_surface, info, base_xoff, base_yoff);
|
||||
var rbg_timer_completion: xev.Completion = undefined;
|
||||
var rbg_timer = try xev.Timer.init();
|
||||
defer rbg_timer.deinit();
|
||||
|
||||
rbg_timer.run(
|
||||
&loop,
|
||||
&rbg_timer_completion,
|
||||
0,
|
||||
RenderBackgroundData,
|
||||
&rbgdata,
|
||||
renderBackgroundCb,
|
||||
);
|
||||
|
||||
var wl_poll_completion = xev.Completion{
|
||||
.op = .{ .poll = .{ .fd = dpy.getFd() } },
|
||||
.userdata = dpy,
|
||||
.callback = wlPollCb,
|
||||
};
|
||||
loop.add(&wl_poll_completion);
|
||||
|
||||
std.log.info("running event loop", .{});
|
||||
try loop.run(.until_done);
|
||||
}
|
||||
|
||||
const RenderBackgroundData = struct {
|
||||
gfx: *Gfx,
|
||||
egl_dpy: c.EGLDisplay,
|
||||
egl_ctx: c.EGLContext,
|
||||
outputs: []const OutputWindow,
|
||||
output_info: []const OutputInfo,
|
||||
last_time: isize,
|
||||
base_offset: [2]c_int,
|
||||
};
|
||||
|
||||
fn renderBackgroundCb(
|
||||
data: ?*RenderBackgroundData,
|
||||
loop: *xev.Loop,
|
||||
completion: *xev.Completion,
|
||||
result: xev.Timer.RunError!void,
|
||||
) xev.CallbackAction {
|
||||
result catch unreachable;
|
||||
|
||||
const now = loop.now();
|
||||
|
||||
const delta_time = now - data.?.last_time;
|
||||
data.?.last_time = now;
|
||||
const next_time = now + std.time.ms_per_min;
|
||||
completion.op.timer.reset = .{
|
||||
.tv_sec = @divTrunc(next_time, std.time.ms_per_s),
|
||||
.tv_nsec = @mod(next_time, std.time.ms_per_s) * std.time.ns_per_ms,
|
||||
};
|
||||
|
||||
for (data.?.outputs, data.?.output_info) |output, info| {
|
||||
if (c.eglMakeCurrent(
|
||||
data.?.egl_dpy,
|
||||
output.egl_surface,
|
||||
output.egl_surface,
|
||||
data.?.egl_ctx,
|
||||
) != c.EGL_TRUE) {
|
||||
std.log.err("failed to set EGL context", .{});
|
||||
loop.stop();
|
||||
return .disarm;
|
||||
}
|
||||
|
||||
if (dpy.dispatchPending() != .SUCCESS or dpy.flush() != .SUCCESS) {
|
||||
std.log.err("error processing wayland events", .{});
|
||||
return error.DispatchFail;
|
||||
}
|
||||
|
||||
const elapsed = timer.lap();
|
||||
if (elapsed < 1000 * std.time.ns_per_ms / fps)
|
||||
std.os.nanosleep(0, (1000 * std.time.ns_per_ms) / fps - elapsed);
|
||||
data.?.gfx.drawBackground(
|
||||
delta_time,
|
||||
output.egl_surface,
|
||||
info,
|
||||
data.?.base_offset[0],
|
||||
data.?.base_offset[1],
|
||||
) catch |e| {
|
||||
std.log.err("drawing: {}", .{e});
|
||||
loop.stop();
|
||||
return .disarm;
|
||||
};
|
||||
}
|
||||
|
||||
return .rearm;
|
||||
}
|
||||
|
||||
fn wlPollCb(
|
||||
userdata: ?*anyopaque,
|
||||
loop: *xev.Loop,
|
||||
_: *xev.Completion,
|
||||
result: xev.Result,
|
||||
) xev.CallbackAction {
|
||||
result.poll catch |e| {
|
||||
std.log.err("unable to poll wayland FD: {}", .{e});
|
||||
loop.stop();
|
||||
return .disarm;
|
||||
};
|
||||
|
||||
const dpy: *wl.Display = @ptrCast(@alignCast(userdata));
|
||||
if (dpy.dispatchPending() != .SUCCESS or dpy.flush() != .SUCCESS) {
|
||||
std.log.err("error processing wayland events", .{});
|
||||
loop.stop();
|
||||
return .disarm;
|
||||
}
|
||||
|
||||
return .rearm;
|
||||
}
|
||||
|
||||
const OutputWindow = struct {
|
||||
|
|
Loading…
Reference in a new issue