mirror of
https://mzte.de/git/LordMZTE/dotfiles.git
synced 2024-09-27 20:48:53 +02:00
wlbg: completely remove draw handler from event loop in idle state
the process is completely blocked with no interaction happening
This commit is contained in:
parent
733b7cf4ce
commit
8a2e617f39
3 changed files with 114 additions and 20 deletions
41
scripts/wlbg/src/DrawTimerHandler.zig
Normal file
41
scripts/wlbg/src/DrawTimerHandler.zig
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const xev = @import("xev");
|
||||||
|
|
||||||
|
const options = @import("options.zig");
|
||||||
|
|
||||||
|
loop: *xev.Loop,
|
||||||
|
|
||||||
|
/// Completion of the main redraw timer
|
||||||
|
completion: *xev.Completion,
|
||||||
|
|
||||||
|
/// Contains a bool for each output, true if needs redraw
|
||||||
|
should_redraw: []bool,
|
||||||
|
|
||||||
|
const DrawTimerHandler = @This();
|
||||||
|
|
||||||
|
pub fn nextAction(self: *DrawTimerHandler) xev.CallbackAction {
|
||||||
|
for (self.should_redraw) |ro|
|
||||||
|
if (ro) return .rearm;
|
||||||
|
return .disarm;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn maybeWake(self: *DrawTimerHandler) void {
|
||||||
|
if (self.completion.flags.state == .dead and self.nextAction() == .rearm) {
|
||||||
|
self.resetTimer();
|
||||||
|
self.loop.add(self.completion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resetTimer(self: *DrawTimerHandler) void {
|
||||||
|
const next_time = self.loop.now() + 1000 / options.fps;
|
||||||
|
self.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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn damage(self: *DrawTimerHandler, idx: usize) void {
|
||||||
|
self.should_redraw[idx] = true;
|
||||||
|
self.maybeWake();
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ const c = @import("ffi.zig").c;
|
||||||
const glutil = @import("glutil.zig");
|
const glutil = @import("glutil.zig");
|
||||||
const options = @import("options.zig");
|
const options = @import("options.zig");
|
||||||
|
|
||||||
|
const DrawTimerHandler = @import("DrawTimerHandler.zig");
|
||||||
const OutputInfo = @import("OutputInfo.zig");
|
const OutputInfo = @import("OutputInfo.zig");
|
||||||
const OutputWindow = @import("OutputWindow.zig");
|
const OutputWindow = @import("OutputWindow.zig");
|
||||||
const PointerState = @import("PointerState.zig");
|
const PointerState = @import("PointerState.zig");
|
||||||
|
@ -164,8 +165,11 @@ pub fn preDraw(
|
||||||
pointer_state: *PointerState,
|
pointer_state: *PointerState,
|
||||||
outputs: []const OutputWindow,
|
outputs: []const OutputWindow,
|
||||||
infos: []const OutputInfo,
|
infos: []const OutputInfo,
|
||||||
|
dth: *DrawTimerHandler,
|
||||||
) !void {
|
) !void {
|
||||||
for (self.cursor_positions, self.should_redraw, infos, outputs) |*pos, *redraw, inf, outp| {
|
for (self.cursor_positions, infos, outputs, 0..) |*pos, inf, outp, i| {
|
||||||
|
const lerp_amt = std.math.clamp(@as(f32, @floatFromInt(std.math.clamp(dt, 0, 10))) / 150.0, 0.0, 1.0);
|
||||||
|
|
||||||
const target = if (pointer_state.surface == outp.surface)
|
const target = if (pointer_state.surface == outp.surface)
|
||||||
.{ pointer_state.x, pointer_state.y }
|
.{ pointer_state.x, pointer_state.y }
|
||||||
else
|
else
|
||||||
|
@ -174,16 +178,16 @@ pub fn preDraw(
|
||||||
const new_x: c_int = @intFromFloat(std.math.lerp(
|
const new_x: c_int = @intFromFloat(std.math.lerp(
|
||||||
@as(f32, @floatFromInt(pos[0])),
|
@as(f32, @floatFromInt(pos[0])),
|
||||||
@as(f32, @floatFromInt(target[0])),
|
@as(f32, @floatFromInt(target[0])),
|
||||||
std.math.clamp(@as(f32, @floatFromInt(dt)) / 250.0, 0.0, 1.0),
|
lerp_amt,
|
||||||
));
|
));
|
||||||
const new_y: c_int = @intFromFloat(std.math.lerp(
|
const new_y: c_int = @intFromFloat(std.math.lerp(
|
||||||
@as(f32, @floatFromInt(pos[1])),
|
@as(f32, @floatFromInt(pos[1])),
|
||||||
@as(f32, @floatFromInt(target[1])),
|
@as(f32, @floatFromInt(target[1])),
|
||||||
std.math.clamp(@as(f32, @floatFromInt(dt)) / 250.0, 0.0, 1.0),
|
lerp_amt,
|
||||||
));
|
));
|
||||||
|
|
||||||
if (new_x != pos[0] or new_y != pos[1])
|
if (new_x != pos[0] or new_y != pos[1])
|
||||||
redraw.* = true;
|
dth.damage(i);
|
||||||
|
|
||||||
pos[0] = new_x;
|
pos[0] = new_x;
|
||||||
pos[1] = new_y;
|
pos[1] = new_y;
|
||||||
|
@ -197,15 +201,13 @@ pub fn draw(
|
||||||
output_idx: usize,
|
output_idx: usize,
|
||||||
outputs: []const OutputWindow,
|
outputs: []const OutputWindow,
|
||||||
infos: []const OutputInfo,
|
infos: []const OutputInfo,
|
||||||
|
dth: *DrawTimerHandler,
|
||||||
) !void {
|
) !void {
|
||||||
self.time += dt;
|
self.time += dt;
|
||||||
|
dth.should_redraw[output_idx] = false;
|
||||||
c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0); // use default framebuffer
|
c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0); // use default framebuffer
|
||||||
c.glUseProgram(self.main_shader_program);
|
c.glUseProgram(self.main_shader_program);
|
||||||
|
|
||||||
if (!self.should_redraw[output_idx])
|
|
||||||
return;
|
|
||||||
self.should_redraw[output_idx] = false;
|
|
||||||
|
|
||||||
const vertices = [_]f32{
|
const vertices = [_]f32{
|
||||||
-1.0, -1.0, 0.0, 0.0, 0.0,
|
-1.0, -1.0, 0.0, 0.0, 0.0,
|
||||||
1.0, -1.0, 0.0, 1.0, 0.0,
|
1.0, -1.0, 0.0, 1.0, 0.0,
|
||||||
|
|
|
@ -5,6 +5,7 @@ const wayland = @import("wayland");
|
||||||
const c = @import("ffi.zig").c;
|
const c = @import("ffi.zig").c;
|
||||||
const options = @import("options.zig");
|
const options = @import("options.zig");
|
||||||
|
|
||||||
|
const DrawTimerHandler = @import("DrawTimerHandler.zig");
|
||||||
const Gfx = @import("Gfx.zig");
|
const Gfx = @import("Gfx.zig");
|
||||||
const Globals = @import("Globals.zig");
|
const Globals = @import("Globals.zig");
|
||||||
const OutputInfo = @import("OutputInfo.zig");
|
const OutputInfo = @import("OutputInfo.zig");
|
||||||
|
@ -130,15 +131,32 @@ pub fn main() !void {
|
||||||
}
|
}
|
||||||
defer for (output_windows) |output| output.deinit(egl_ctx);
|
defer for (output_windows) |output| output.deinit(egl_ctx);
|
||||||
|
|
||||||
|
var r_timer_completion: xev.Completion = undefined;
|
||||||
|
var r_timer = try xev.Timer.init();
|
||||||
|
defer r_timer.deinit();
|
||||||
|
|
||||||
|
var dth = DrawTimerHandler{
|
||||||
|
.should_redraw = try std.heap.c_allocator.alloc(bool, output_info.len),
|
||||||
|
.completion = &r_timer_completion,
|
||||||
|
.loop = &loop,
|
||||||
|
};
|
||||||
|
defer std.heap.c_allocator.free(dth.should_redraw);
|
||||||
|
|
||||||
var pointer_state = PointerState{
|
var pointer_state = PointerState{
|
||||||
.surface = null,
|
.surface = null,
|
||||||
.x = 0,
|
.x = 0,
|
||||||
.y = 0,
|
.y = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var pointer_listener_data = PointerListenerData{
|
||||||
|
.pstate = &pointer_state,
|
||||||
|
.outputs = output_windows,
|
||||||
|
.dth = &dth,
|
||||||
|
};
|
||||||
|
|
||||||
const pointer = try globs.seat.getPointer();
|
const pointer = try globs.seat.getPointer();
|
||||||
defer pointer.destroy();
|
defer pointer.destroy();
|
||||||
pointer.setListener(*PointerState, pointerListener, &pointer_state);
|
pointer.setListener(*PointerListenerData, pointerListener, &pointer_listener_data);
|
||||||
|
|
||||||
const base_offset: [2]i32 = off: {
|
const base_offset: [2]i32 = off: {
|
||||||
if (comptime options.multihead_mode == .individual) break :off .{ 0, 0 };
|
if (comptime options.multihead_mode == .individual) break :off .{ 0, 0 };
|
||||||
|
@ -180,6 +198,7 @@ pub fn main() !void {
|
||||||
.last_time = loop.now(),
|
.last_time = loop.now(),
|
||||||
.base_offset = base_offset,
|
.base_offset = base_offset,
|
||||||
.pointer_state = &pointer_state,
|
.pointer_state = &pointer_state,
|
||||||
|
.dth = &dth,
|
||||||
};
|
};
|
||||||
|
|
||||||
var rbg_timer_completion: xev.Completion = undefined;
|
var rbg_timer_completion: xev.Completion = undefined;
|
||||||
|
@ -195,10 +214,6 @@ pub fn main() !void {
|
||||||
renderBackgroundCb,
|
renderBackgroundCb,
|
||||||
);
|
);
|
||||||
|
|
||||||
var r_timer_completion: xev.Completion = undefined;
|
|
||||||
var r_timer = try xev.Timer.init();
|
|
||||||
defer r_timer.deinit();
|
|
||||||
|
|
||||||
r_timer.run(
|
r_timer.run(
|
||||||
&loop,
|
&loop,
|
||||||
&r_timer_completion,
|
&r_timer_completion,
|
||||||
|
@ -228,6 +243,7 @@ const RenderData = struct {
|
||||||
last_time: isize,
|
last_time: isize,
|
||||||
base_offset: [2]c_int,
|
base_offset: [2]c_int,
|
||||||
pointer_state: *PointerState,
|
pointer_state: *PointerState,
|
||||||
|
dth: *DrawTimerHandler,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn renderCb(
|
fn renderCb(
|
||||||
|
@ -236,19 +252,21 @@ fn renderCb(
|
||||||
completion: *xev.Completion,
|
completion: *xev.Completion,
|
||||||
result: xev.Timer.RunError!void,
|
result: xev.Timer.RunError!void,
|
||||||
) xev.CallbackAction {
|
) xev.CallbackAction {
|
||||||
|
_ = completion;
|
||||||
result catch unreachable;
|
result catch unreachable;
|
||||||
|
|
||||||
const now = loop.now();
|
const now = loop.now();
|
||||||
const delta_time = now - data.?.last_time;
|
const delta_time = now - data.?.last_time;
|
||||||
data.?.last_time = now;
|
data.?.last_time = now;
|
||||||
|
|
||||||
resetXevTimerCompletion(completion, now, 1000 / options.fps);
|
data.?.dth.resetTimer();
|
||||||
|
|
||||||
data.?.gfx.preDraw(
|
data.?.gfx.preDraw(
|
||||||
delta_time,
|
delta_time,
|
||||||
data.?.pointer_state,
|
data.?.pointer_state,
|
||||||
data.?.outputs,
|
data.?.outputs,
|
||||||
data.?.output_info,
|
data.?.output_info,
|
||||||
|
data.?.dth,
|
||||||
) catch |e| {
|
) catch |e| {
|
||||||
std.log.err("running preDraw: {}", .{e});
|
std.log.err("running preDraw: {}", .{e});
|
||||||
loop.stop();
|
loop.stop();
|
||||||
|
@ -256,6 +274,9 @@ fn renderCb(
|
||||||
};
|
};
|
||||||
|
|
||||||
for (data.?.outputs, 0..) |output, i| {
|
for (data.?.outputs, 0..) |output, i| {
|
||||||
|
if (!data.?.dth.should_redraw[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
if (c.eglMakeCurrent(
|
if (c.eglMakeCurrent(
|
||||||
data.?.egl_dpy,
|
data.?.egl_dpy,
|
||||||
output.egl_surface,
|
output.egl_surface,
|
||||||
|
@ -273,6 +294,7 @@ fn renderCb(
|
||||||
i,
|
i,
|
||||||
data.?.outputs,
|
data.?.outputs,
|
||||||
data.?.output_info,
|
data.?.output_info,
|
||||||
|
data.?.dth,
|
||||||
) catch |e| {
|
) catch |e| {
|
||||||
std.log.err("drawing: {}", .{e});
|
std.log.err("drawing: {}", .{e});
|
||||||
loop.stop();
|
loop.stop();
|
||||||
|
@ -280,7 +302,7 @@ fn renderCb(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return .rearm;
|
return data.?.dth.nextAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderBackgroundCb(
|
fn renderBackgroundCb(
|
||||||
|
@ -359,14 +381,43 @@ fn xdgOutputListener(_: *zxdg.OutputV1, ev: zxdg.OutputV1.Event, info: *OutputIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pointerListener(_: *wl.Pointer, ev: wl.Pointer.Event, state: *PointerState) void {
|
const PointerListenerData = struct {
|
||||||
|
pstate: *PointerState,
|
||||||
|
outputs: []const OutputWindow,
|
||||||
|
dth: *DrawTimerHandler,
|
||||||
|
|
||||||
|
fn damageCurrentWindow(self: *PointerListenerData) !void {
|
||||||
|
if (self.pstate.surface) |ps| {
|
||||||
|
for (self.outputs, 0..) |o, i| {
|
||||||
|
if (ps == o.surface) {
|
||||||
|
self.dth.damage(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn pointerListener(_: *wl.Pointer, ev: wl.Pointer.Event, d: *PointerListenerData) void {
|
||||||
switch (ev) {
|
switch (ev) {
|
||||||
.motion => |motion| {
|
.motion => |motion| {
|
||||||
state.x = motion.surface_x.toInt();
|
d.pstate.x = motion.surface_x.toInt();
|
||||||
state.y = motion.surface_y.toInt();
|
d.pstate.y = motion.surface_y.toInt();
|
||||||
|
d.damageCurrentWindow() catch |e| {
|
||||||
|
std.log.err("unable to damage window: {}", .{e});
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.enter => |enter| {
|
||||||
|
d.pstate.surface = enter.surface;
|
||||||
|
d.damageCurrentWindow() catch |e| {
|
||||||
|
std.log.err("unable to damage window: {}", .{e});
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.leave => {
|
||||||
|
d.damageCurrentWindow() catch |e| {
|
||||||
|
std.log.err("unable to damage window: {}", .{e});
|
||||||
|
};
|
||||||
|
d.pstate.surface = null;
|
||||||
},
|
},
|
||||||
.enter => |enter| state.surface = enter.surface,
|
|
||||||
.leave => state.surface = null,
|
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue