git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commite9d78d4c68622d7ae433ad320ad89bd5d451d20d
parentd3a384684a
authorIsaac Freund <mail@isaacfreund.com>
date2023-03-24 15:27
session-lock: fix assertion failures and clean up

The removed assertions aren't possible to guarantee due to the fact that
the lock render state is updated asynchronously as the output is
rendered.

 river/LockManager.zig | 10 +---------
 river/LockSurface.zig |  5 +----
 river/Output.zig      | 27 +++++++++++++++++++--------
 3 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/river/LockManager.zig b/river/LockManager.zig
index fdafc320..71963987 100644
--- a/river/LockManager.zig
+++ b/river/LockManager.zig
@@ -142,14 +142,6 @@ fn handleLockSurfacesTimeout(manager: *LockManager) c_int {
         while (it) |node| : (it = node.next) {
             const output = &node.data;
 
-            switch (output.lock_render_state) {
-                .unlocked, .pending_lock_surface => {},
-                .pending_blank, .blanked, .lock_surface => {
-                    assert(!output.normal_content.node.enabled);
-                    assert(output.locked_content.node.enabled);
-                },
-            }
-
             output.normal_content.node.setEnabled(false);
             output.locked_content.node.setEnabled(true);
         }
@@ -169,7 +161,7 @@ pub fn maybeLock(manager: *LockManager) void {
         while (it) |node| : (it = node.next) {
             const output = &node.data;
             switch (output.lock_render_state) {
-                .unlocked, .pending_blank, .pending_lock_surface => {
+                .pending_unlock, .unlocked, .pending_blank, .pending_lock_surface => {
                     all_outputs_blanked = false;
                     all_outputs_rendered_lock_surface = false;
                 },
diff --git a/river/LockSurface.zig b/river/LockSurface.zig
index 8f58f455..9cfb4ff1 100644
--- a/river/LockSurface.zig
+++ b/river/LockSurface.zig
@@ -100,12 +100,9 @@ fn handleOutputMode(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
 
 fn handleMap(listener: *wl.Listener(void)) void {
     const lock_surface = @fieldParentPtr(LockSurface, "map", listener);
-
     const output = lock_surface.getOutput();
-    assert(output.normal_content.node.enabled);
-    output.normal_content.node.setEnabled(false);
 
-    assert(!output.locked_content.node.enabled);
+    output.normal_content.node.setEnabled(false);
     output.locked_content.node.setEnabled(true);
 
     {
diff --git a/river/Output.zig b/river/Output.zig
index b28fb66c..361358c8 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -78,6 +78,8 @@ layers: struct {
 /// If using the DRM backend it will be blanked with the initial modeset.
 /// If using the Wayland or X11 backend nothing will be visible until the first frame is rendered.
 lock_render_state: enum {
+    /// Submitted an unlocked buffer but the buffer has not yet been presented.
+    pending_unlock,
     /// Normal, "unlocked" content may be visible.
     unlocked,
     /// Submitted a blank buffer but the buffer has not yet been presented.
@@ -393,7 +395,7 @@ fn handleEnable(listener: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) vo
     if (wlr_output.enabled) {
         switch (server.lock_manager.state) {
             .unlocked => {
-                self.lock_render_state = .unlocked;
+                assert(self.lock_render_state == .blanked);
                 self.normal_content.node.setEnabled(true);
                 self.locked_content.node.setEnabled(false);
             },
@@ -406,6 +408,8 @@ fn handleEnable(listener: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) vo
     } else {
         // Disabling and re-enabling an output always blanks it.
         self.lock_render_state = .blanked;
+        self.normal_content.node.setEnabled(false);
+        self.locked_content.node.setEnabled(true);
     }
 
     // Add the output to root.outputs and the output layout if it has not
@@ -447,7 +451,7 @@ fn handleFrame(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
             switch (server.lock_manager.state) {
                 .unlocked => unreachable,
                 .locked => switch (output.lock_render_state) {
-                    .unlocked, .pending_blank, .pending_lock_surface => unreachable,
+                    .pending_unlock, .unlocked, .pending_blank, .pending_lock_surface => unreachable,
                     .blanked, .lock_surface => {},
                 },
                 .waiting_for_blank => {
@@ -461,6 +465,10 @@ fn handleFrame(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
                     }
                 },
             }
+        } else {
+            if (output.lock_render_state != .unlocked) {
+                output.lock_render_state = .pending_unlock;
+            }
         }
     } else {
         log.err("output commit failed for {s}", .{output.wlr_output.name});
@@ -477,18 +485,21 @@ fn handlePresent(
 ) void {
     const output = @fieldParentPtr(Self, "present", listener);
 
+    if (!event.presented) {
+        return;
+    }
+
     switch (output.lock_render_state) {
+        .pending_unlock => {
+            assert(server.lock_manager.state != .locked);
+            output.lock_render_state = .unlocked;
+        },
         .unlocked => assert(server.lock_manager.state != .locked),
         .pending_blank, .pending_lock_surface => {
-            if (!event.presented) {
-                output.lock_render_state = .unlocked;
-                return;
-            }
-
             output.lock_render_state = switch (output.lock_render_state) {
                 .pending_blank => .blanked,
                 .pending_lock_surface => .lock_surface,
-                .unlocked, .blanked, .lock_surface => unreachable,
+                .pending_unlock, .unlocked, .blanked, .lock_surface => unreachable,
             };
 
             if (server.lock_manager.state != .locked) {