@@ -45,12 +45,6 @@ class wayfire_showrepaint : public wf::per_output_plugin_instance_t
45
45
public:
46
46
void init () override
47
47
{
48
- if (!wf::get_core ().is_gles2 ())
49
- {
50
- LOGE (" showrepaint plugin requires GLES2 renderer!" );
51
- return ;
52
- }
53
-
54
48
active = false ;
55
49
egl_swap_buffers_with_damage =
56
50
egl_extension_supported (" EGL_KHR_swap_buffers_with_damage" ) ||
@@ -64,25 +58,40 @@ class wayfire_showrepaint : public wf::per_output_plugin_instance_t
64
58
output->render ->damage_whole ();
65
59
};
66
60
67
- wf::activator_callback toggle_cb = [=] ( auto )
61
+ void set_active_status ( bool status )
68
62
{
69
- active = !active;
63
+ if (this ->active == status)
64
+ {
65
+ return ;
66
+ }
70
67
71
- if (active )
68
+ if (status )
72
69
{
73
70
output->render ->add_effect (&overlay_hook, wf::OUTPUT_EFFECT_OVERLAY);
71
+ output->render ->add_effect (&on_main_pass_done, wf::OUTPUT_EFFECT_PASS_DONE);
74
72
} else
75
73
{
76
74
output->render ->rem_effect (&overlay_hook);
75
+ output->render ->rem_effect (&on_main_pass_done);
77
76
}
78
77
79
- output->render ->damage_whole ();
78
+ this ->active = status;
79
+ }
80
80
81
+ wf::activator_callback toggle_cb = [=] (auto )
82
+ {
83
+ set_active_status (!active);
84
+ output->render ->damage_whole ();
81
85
return true ;
82
86
};
83
87
84
88
bool egl_extension_supported (std::string ext)
85
89
{
90
+ if (!wf::get_core ().is_gles2 ())
91
+ {
92
+ return false ;
93
+ }
94
+
86
95
std::string extensions;
87
96
wf::gles::run_in_context ([&]
88
97
{
@@ -101,22 +110,20 @@ class wayfire_showrepaint : public wf::per_output_plugin_instance_t
101
110
102
111
void get_random_color (wf::color_t & color)
103
112
{
104
- color.r = 0.15 + static_cast <float >(rand ()) /
105
- (static_cast <float >(RAND_MAX / 0.25 ));
106
- color.g = 0.15 + static_cast <float >(rand ()) /
107
- (static_cast <float >(RAND_MAX / 0.25 ));
108
- color.b = 0.15 + static_cast <float >(rand ()) /
109
- (static_cast <float >(RAND_MAX / 0.25 ));
113
+ color.r = 0.15 + static_cast <float >(rand ()) / (static_cast <float >(RAND_MAX / 0.25 ));
114
+ color.g = 0.15 + static_cast <float >(rand ()) / (static_cast <float >(RAND_MAX / 0.25 ));
115
+ color.b = 0.15 + static_cast <float >(rand ()) / (static_cast <float >(RAND_MAX / 0.25 ));
110
116
color.a = 0.25 ;
111
117
}
112
118
113
119
wf::effect_hook_t overlay_hook = [=] ()
114
120
{
115
121
auto target_fb = output->render ->get_target_framebuffer ();
116
- wf::region_t swap_damage = output->render ->get_swap_damage ();
122
+ wf::region_t swap_damage = target_fb.geometry_region_from_framebuffer_region (
123
+ output->render ->get_swap_damage ());
124
+
117
125
wf::region_t scheduled_damage = output->render ->get_scheduled_damage ();
118
- wlr_box fbg = {0 , 0 , target_fb.get_size ().width , target_fb.get_size ().height };
119
- wf::region_t output_region{fbg};
126
+ wf::region_t output_region{target_fb.geometry };
120
127
wf::region_t inverted_damage;
121
128
wf::region_t damage;
122
129
@@ -130,99 +137,66 @@ class wayfire_showrepaint : public wf::per_output_plugin_instance_t
130
137
wf::color_t color;
131
138
get_random_color (color);
132
139
damage = scheduled_damage.empty () ? swap_damage : scheduled_damage;
140
+ inverted_damage = output_region ^ damage;
133
141
134
- last_buffer.allocate ({fbg.width , fbg.height });
135
- GLuint last_buffer_fb_id = wf::gles::ensure_render_buffer_fb_id (last_buffer.get_renderbuffer ());
136
- GLuint target_fb_fb_id = wf::gles::ensure_render_buffer_fb_id (target_fb);
142
+ auto rpass = output->render ->get_current_pass ();
143
+ rpass->add_rect (color, target_fb, target_fb.geometry , damage);
144
+ if (reduce_flicker)
145
+ {
146
+ /* Show swap damage. It might be possible that we blit right over this but in the case of cube
147
+ * and expo, it shows client and swap damage in contrast. This makes sense since the idea is to
148
+ * show damage as colored regions. We don't do this if the reduce_flicker option isn't set because
149
+ * we don't repaint the inverted damage from the last buffer in this case, so we would keep
150
+ * painting it with different colors until it is white. */
151
+ get_random_color (color);
152
+ rpass->add_rect (color, target_fb, target_fb.geometry , inverted_damage);
153
+ }
137
154
138
- output->render ->get_current_pass ()->custom_gles_subpass ([&]
155
+ /* If swap_buffers_with_damage is supported, we do not need the following to be executed. */
156
+ if (egl_swap_buffers_with_damage || !reduce_flicker)
139
157
{
140
- wf::gles::bind_render_buffer (target_fb);
141
- for (const auto & b : damage)
142
- {
143
- OpenGL::render_rectangle (wlr_box_from_pixman_box (b), color,
144
- wf::gles::render_target_orthographic_projection (target_fb));
145
- }
146
-
147
- if (reduce_flicker)
148
- {
149
- /* Show swap damage. It might be possible that we blit right over this
150
- * but in the case of cube and expo, it shows client and swap damage in
151
- * contrast. This makes sense since the idea is to show damage as colored
152
- * regions. We don't do this if the reduce_flicker option isn't set
153
- * because
154
- * we don't repaint the inverted damage from the last buffer in this
155
- * case,
156
- * so we would keep painting it with different colors until it is white.
157
- * */
158
- get_random_color (color);
159
- inverted_damage = output_region ^ damage;
160
- for (const auto & b : inverted_damage)
161
- {
162
- OpenGL::render_rectangle (wlr_box_from_pixman_box (b), color,
163
- wf::gles::render_target_orthographic_projection (target_fb));
164
- }
165
- }
166
-
167
- /* If swap_buffers_with_damage is supported, we do not need the
168
- * following to be executed. */
169
- if (egl_swap_buffers_with_damage)
170
- {
171
- return ;
172
- }
173
-
174
- /* User option. */
175
- if (!reduce_flicker)
176
- {
177
- return ;
178
- }
179
-
180
- /* Repaint the inverted damage region with the last buffer contents.
181
- * We only want to see what actually changed on screen. If we don't
182
- * do this, things like mouse and keyboard input cause buffer swaps
183
- * which only make the screen flicker between buffers, without showing
184
- * any actual damage changes. If swap_buffers_with_damage is supported,
185
- * we do not need to do this since the damage region that is passed to
186
- * swap is only repainted. If it isn't supported, the entire buffer is
187
- * repainted.
188
- */
189
- GL_CALL (glBindFramebuffer (GL_READ_FRAMEBUFFER, last_buffer_fb_id));
190
- GL_CALL (glBindFramebuffer (GL_DRAW_FRAMEBUFFER, target_fb_fb_id));
191
- damage = swap_damage.empty () ? scheduled_damage : swap_damage;
192
- output_region *= target_fb.scale ;
193
- inverted_damage = output_region ^ damage;
194
- inverted_damage *= 1.0 / target_fb.scale ;
195
- for (const auto & rect : inverted_damage)
196
- {
197
- pixman_box32_t b = pixman_box_from_wlr_box (
198
- target_fb.framebuffer_box_from_geometry_box (
199
- wlr_box_from_pixman_box (rect)));
200
- GL_CALL (glBlitFramebuffer (
201
- b.x1 , b.y1 ,
202
- b.x2 , b.y2 ,
203
- b.x1 , b.y1 ,
204
- b.x2 , b.y2 ,
205
- GL_COLOR_BUFFER_BIT, GL_LINEAR));
206
- }
207
-
208
- /* Save the current buffer to last buffer so we can render the
209
- * inverted damage from the last buffer to the current buffer
210
- * on next frame. We have to save the entire buffer because we
211
- * don't know what the next frame damage will be.
212
- */
213
- GL_CALL (glBindFramebuffer (GL_READ_FRAMEBUFFER, target_fb_fb_id));
214
- GL_CALL (glBindFramebuffer (GL_DRAW_FRAMEBUFFER, last_buffer_fb_id));
215
- GL_CALL (glBlitFramebuffer (
216
- 0 , 0 , fbg.width , fbg.height ,
217
- 0 , 0 , fbg.width , fbg.height ,
218
- GL_COLOR_BUFFER_BIT, GL_LINEAR));
219
- });
158
+ return ;
159
+ }
160
+
161
+ /* Repaint the inverted damage region with the last buffer contents.
162
+ * We only want to see what actually changed on screen. If we don't do this, things like mouse and
163
+ * keyboard input cause buffer swaps which only make the screen flicker between buffers, without
164
+ * showing any actual damage changes. If swap_buffers_with_damage is supported, we do not need to do
165
+ * this since the damage region that is passed to swap is only repainted. If it isn't supported, the
166
+ * entire buffer is repainted.
167
+ */
168
+ if (last_buffer.get_size ().width > 0 )
169
+ {
170
+ wf::texture_t texture;
171
+ texture.texture = last_buffer.get_texture ();
172
+ texture.transform = target_fb.wl_transform ;
173
+ rpass->add_texture (texture, target_fb, target_fb.geometry , inverted_damage);
174
+ }
175
+ };
176
+
177
+ wf::effect_hook_t on_main_pass_done = [=] ()
178
+ {
179
+ if (!reduce_flicker || egl_swap_buffers_with_damage)
180
+ {
181
+ return ;
182
+ }
183
+
184
+ /*
185
+ * Save the current buffer to last buffer so we can render the
186
+ * inverted damage from the last buffer to the current buffer
187
+ * on next frame. We have to save the entire buffer because we
188
+ * don't know what the next frame damage will be.
189
+ */
190
+ auto target_fb = output->render ->get_target_framebuffer ();
191
+ last_buffer.allocate (target_fb.get_size ());
192
+ wlr_box full = wf::construct_box ({0 , 0 }, target_fb.get_size ());
193
+ last_buffer.get_renderbuffer ().blit (target_fb, wf::geometry_to_fbox (full), full);
220
194
};
221
195
222
196
void fini () override
223
197
{
224
198
output->rem_binding (&toggle_cb);
225
- output-> render -> rem_effect (&overlay_hook );
199
+ set_active_status ( false );
226
200
}
227
201
};
228
202
0 commit comments