summaryrefslogtreecommitdiff
path: root/gui-wm/wayfire/files/wayfire-0.11.0-snapshot-allocation-failure.patch
blob: 7ba264acb2f0acd7f054bda58fd2a6a16c40690a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
diff --git a/README.md b/README.md
index 7cddb47..2bdf8b2 100644
--- a/README.md
+++ b/README.md
@@ -203,3 +203,19 @@ stays. No dependency on the shell is introduced.
 `wayfire/exit` schedules shutdown of this compositor after its response, with
 core/exit's inhibited-output guard. Config monitoring follows atomically
 replaced symlink targets again.
+
+## 0.11.0-r79 (Hedron Sprint 3 follow-up)
+
+Closing an overlay no longer starts a snapshot render pass after auxiliary
+buffer allocation fails. The animate plugin tears down the closing animation
+and transformer, including when close interrupts an opening animation. Failed
+snapshots generate no draw instances; a missing texture is skipped safely.
+The public take_snapshot signature and compositor/plugin ABI are unchanged.
+
+A test-only allocator shim reproduces the old fatal assertion on installed r77.
+The new build survives four forced snapshot failures and then reopens/closes the
+menu normally. See ../../logs/s4/snapshot-final.log and ../../tools/snapshot-close-probe.py.
+The valid wlroots software mode (WLR_RENDERER_FORCE_SOFTWARE=1 with udmabuf access)
+still has a separate first-frame crash on this host; full software/VM acceptance
+remains pending. Do not use MESA_LOADER_DRIVER_OVERRIDE=kms_swrast on a DRM render
+node as an acceptance setup: it cannot allocate the required dumb buffers here.
diff --git a/plugins/animate/animate.cpp b/plugins/animate/animate.cpp
index a5b38fa..6da9aa7 100644
--- a/plugins/animate/animate.cpp
+++ b/plugins/animate/animate.cpp
@@ -424,12 +424,27 @@ class wayfire_animation : public wf::plugin_interface_t, private wf::per_output_
         auto& effect = effects_registry->effects[animation_name];
         if (view->has_data(cdata_name))
         {
-            view->get_data<animation_hook>(cdata_name)->set_animation_type(type);
+            auto hook = view->get_data<animation_hook>(cdata_name);
+            hook->set_animation_type(type);
+            if ((type == wf::animate::ANIMATION_TYPE_UNMAP) &&
+                !hook->unmapped_contents->has_snapshot())
+            {
+                view->erase_data(cdata_name);
+            }
+
             return;
         }
 
         auto hook = std::make_unique<animation_hook>(view, effect.generator(),
             duration, type, cdata_name, animation_name);
+        if ((type == wf::animate::ANIMATION_TYPE_UNMAP) &&
+            !hook->unmapped_contents->has_snapshot())
+        {
+            // Tear down the transformer and render hook together. Keeping an
+            // animation with empty contents would require another aux buffer.
+            return;
+        }
+
         used_hook_names.insert(cdata_name);
         view->store_data(std::move(hook), cdata_name);
     }
diff --git a/plugins/animate/unmapped-view-node.hpp b/plugins/animate/unmapped-view-node.hpp
index 3ae9968..8330648 100644
--- a/plugins/animate/unmapped-view-node.hpp
+++ b/plugins/animate/unmapped-view-node.hpp
@@ -21,8 +21,18 @@ class unmapped_view_snapshot_node : public wf::scene::node_t
         _view = view->weak_from_this();
     }
 
+    bool has_snapshot() const
+    {
+        return snapshot.get_buffer() != nullptr;
+    }
+
     wf::geometry_t get_bounding_box() override
     {
+        if (!snapshot.get_buffer())
+        {
+            return {0, 0, 0, 0};
+        }
+
         if (auto view = _view.lock())
         {
             auto current_bbox = view->get_surface_root_node()->get_bounding_box();
@@ -35,6 +45,11 @@ class unmapped_view_snapshot_node : public wf::scene::node_t
     void gen_render_instances(std::vector<scene::render_instance_uptr>& instances,
         scene::damage_callback push_damage, wf::output_t *shown_on) override
     {
+        if (!snapshot.get_buffer())
+        {
+            return;
+        }
+
         instances.push_back(std::make_unique<rinstance_t>(this, push_damage, shown_on));
     }
 
@@ -50,6 +65,11 @@ class unmapped_view_snapshot_node : public wf::scene::node_t
         using simple_render_instance_t::simple_render_instance_t;
         void render(const wf::scene::render_instruction_t& data)
         {
+            if (!self->snapshot.get_texture())
+            {
+                return;
+            }
+
             auto texture = wf::texture_t::from_aux(self->snapshot);
             data.pass->add_texture(texture, data.target, self->get_bounding_box(), data.damage);
         }
diff --git a/src/api/wayfire/view.hpp b/src/api/wayfire/view.hpp
index b70f6c5..a813ad1 100644
--- a/src/api/wayfire/view.hpp
+++ b/src/api/wayfire/view.hpp
@@ -179,6 +179,7 @@ class view_interface_t : public wf::signal::provider_t, public wf::object_base_t
 
     /**
      * A snapshot of the view is a copy of the view's contents into a framebuffer.
+     * If allocation fails, the buffer is empty and no render pass is started.
      */
     virtual void take_snapshot(wf::auxilliary_buffer_t& buffer);
 
diff --git a/src/view/view.cpp b/src/view/view.cpp
index daa50db..41c7e5a 100644
--- a/src/view/view.cpp
+++ b/src/view/view.cpp
@@ -96,8 +96,14 @@ void wf::view_interface_t::take_snapshot(wf::auxilliary_buffer_t& buffer)
     auto root_node = get_surface_root_node();
     const wf::geometry_t bbox = root_node->get_bounding_box();
     float scale = get_output()->handle->scale;
-    buffer.allocate(wf::dimensions(bbox), scale,
-        wf::buffer_allocation_hints_t{.hdr_linear = get_output() && get_output()->is_hdr()});
+    if (buffer.allocate(wf::dimensions(bbox), scale,
+        wf::buffer_allocation_hints_t{.hdr_linear = get_output() && get_output()->is_hdr()}) ==
+        wf::buffer_reallocation_result_t::FAILED)
+    {
+        // A closing view may disappear without an animation if memory or the
+        // allocator is unavailable. A render pass requires a valid buffer.
+        return;
+    }
 
     wf::render_target_t target{buffer};
     target.geometry = bbox;