Skip to content

Commit c1bed08

Browse files
committed
showrepaint: use new render-agnostic APIs in core
1 parent c8963d4 commit c1bed08

File tree

1 file changed

+78
-104
lines changed

1 file changed

+78
-104
lines changed

src/showrepaint.cpp

Lines changed: 78 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,6 @@ class wayfire_showrepaint : public wf::per_output_plugin_instance_t
4545
public:
4646
void init() override
4747
{
48-
if (!wf::get_core().is_gles2())
49-
{
50-
LOGE("showrepaint plugin requires GLES2 renderer!");
51-
return;
52-
}
53-
5448
active = false;
5549
egl_swap_buffers_with_damage =
5650
egl_extension_supported("EGL_KHR_swap_buffers_with_damage") ||
@@ -64,25 +58,40 @@ class wayfire_showrepaint : public wf::per_output_plugin_instance_t
6458
output->render->damage_whole();
6559
};
6660

67-
wf::activator_callback toggle_cb = [=] (auto)
61+
void set_active_status(bool status)
6862
{
69-
active = !active;
63+
if (this->active == status)
64+
{
65+
return;
66+
}
7067

71-
if (active)
68+
if (status)
7269
{
7370
output->render->add_effect(&overlay_hook, wf::OUTPUT_EFFECT_OVERLAY);
71+
output->render->add_effect(&on_main_pass_done, wf::OUTPUT_EFFECT_PASS_DONE);
7472
} else
7573
{
7674
output->render->rem_effect(&overlay_hook);
75+
output->render->rem_effect(&on_main_pass_done);
7776
}
7877

79-
output->render->damage_whole();
78+
this->active = status;
79+
}
8080

81+
wf::activator_callback toggle_cb = [=] (auto)
82+
{
83+
set_active_status(!active);
84+
output->render->damage_whole();
8185
return true;
8286
};
8387

8488
bool egl_extension_supported(std::string ext)
8589
{
90+
if (!wf::get_core().is_gles2())
91+
{
92+
return false;
93+
}
94+
8695
std::string extensions;
8796
wf::gles::run_in_context([&]
8897
{
@@ -101,22 +110,20 @@ class wayfire_showrepaint : public wf::per_output_plugin_instance_t
101110

102111
void get_random_color(wf::color_t& color)
103112
{
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));
110116
color.a = 0.25;
111117
}
112118

113119
wf::effect_hook_t overlay_hook = [=] ()
114120
{
115121
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+
117125
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};
120127
wf::region_t inverted_damage;
121128
wf::region_t damage;
122129

@@ -130,99 +137,66 @@ class wayfire_showrepaint : public wf::per_output_plugin_instance_t
130137
wf::color_t color;
131138
get_random_color(color);
132139
damage = scheduled_damage.empty() ? swap_damage : scheduled_damage;
140+
inverted_damage = output_region ^ damage;
133141

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+
}
137154

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)
139157
{
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);
220194
};
221195

222196
void fini() override
223197
{
224198
output->rem_binding(&toggle_cb);
225-
output->render->rem_effect(&overlay_hook);
199+
set_active_status(false);
226200
}
227201
};
228202

0 commit comments

Comments
 (0)