summaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
authorWilliam McKinnon <[email protected]>2023-05-16 02:26:01 -0400
committerGitHub <[email protected]>2023-05-16 02:26:01 -0400
commit2c4fe20456851b6b8dc14b6bdc0cf9bee527a9ee (patch)
treec9e8a650da8a23c849516a6ac54dd59527681693 /sway
parent479cc4e7456a93aed1a89bef8d83c1f8c43bd291 (diff)
Blur damage tracking simplification (#155)
* suplified conditional in find_con_effect_iterator * removed has_blur * simplified optimized blur check * moved damage expansion to output.c * removed extraneous fx_renderer_scissor * cleaned up render_output * removed unneeded damage scale * moved workspace optimized check function to workspace.c * renamed ws iterator function * added back region expansion * removed uneeded parameter from get_main_buffer_blur * returned extended damage * moved get_blur_size back to original spot (reduce diff size) * Fixed blur artifacting * Fixed damage highlight not clearing correct framebuffer * removed unneeded conditional * moved initial damage expansion to output.c * moved extended damage to the top of output_render * moved blur damage to damage_surface_iterator * ensure damage doesnt expand beyond output size * removed stdint import --------- Co-authored-by: Erik Reider <[email protected]>
Diffstat (limited to 'sway')
-rw-r--r--sway/config.c8
-rw-r--r--sway/desktop/output.c21
-rw-r--r--sway/desktop/render.c200
-rw-r--r--sway/tree/workspace.c15
4 files changed, 89 insertions, 155 deletions
diff --git a/sway/config.c b/sway/config.c
index 85e53679..04c75171 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -1084,3 +1084,11 @@ void translate_keysyms(struct input_config *input_config) {
sway_log(SWAY_DEBUG, "Translated keysyms using config for device '%s'",
input_config->identifier);
}
+
+int config_get_blur_size() {
+ return pow(2, config->blur_params.num_passes) * config->blur_params.radius;
+}
+
+bool config_should_parameters_blur() {
+ return config->blur_params.radius > 0 && config->blur_params.num_passes > 0;
+}
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 45c2f1c4..45bbf0b8 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -689,6 +689,16 @@ static void damage_surface_iterator(struct sway_output *output,
ceil(output->wlr_output->scale) - surface->current.scale);
}
pixman_region32_translate(&damage, box.x, box.y);
+
+ if (view) {
+ int blur_size = view->container->blur_enabled ? config_get_blur_size() : 0;
+ wlr_region_expand(&damage, &damage, blur_size);
+ box.x -= blur_size;
+ box.y -= blur_size;
+ box.width += blur_size * 2;
+ box.height += blur_size * 2;
+ }
+
if (wlr_damage_ring_add(&output->damage_ring, &damage)) {
wlr_output_schedule_frame(output->wlr_output);
}
@@ -745,12 +755,14 @@ static void damage_child_views_iterator(struct sway_container *con,
void output_damage_whole_container(struct sway_output *output,
struct sway_container *con) {
+ int shadow_sigma = con->shadow_enabled ? config->shadow_blur_sigma : 0;
+
// Pad the box by 1px, because the width is a double and might be a fraction
struct wlr_box box = {
- .x = con->current.x - output->lx - 1,
- .y = con->current.y - output->ly - 1,
- .width = con->current.width + 2,
- .height = con->current.height + 2,
+ .x = con->current.x - output->lx - 1 - shadow_sigma,
+ .y = con->current.y - output->ly - 1 - shadow_sigma,
+ .width = con->current.width + 2 + shadow_sigma * 2,
+ .height = con->current.height + 2 + shadow_sigma * 2,
};
scale_box(&box, output->wlr_output->scale);
if (wlr_damage_ring_add_box(&output->damage_ring, &box)) {
@@ -973,7 +985,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {
transaction_commit_dirty();
- // From sway upstream (fixes damage_ring bounds being INT_MAX)
int width, height;
wlr_output_transformed_resolution(output->wlr_output, &width, &height);
wlr_damage_ring_set_bounds(&output->damage_ring, width, height);
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index b566489e..fb47007f 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -38,13 +38,6 @@ struct render_data {
struct decoration_data deco_data;
};
-struct workspace_effect_info {
- bool container_wants_blur;
- bool container_wants_shadow;
- bool should_render_optimized_blur;
- int expanded_size;
-};
-
struct decoration_data get_undecorated_decoration_data() {
return (struct decoration_data) {
.alpha = 1.0f,
@@ -57,13 +50,6 @@ struct decoration_data get_undecorated_decoration_data() {
};
}
-int get_blur_size() {
- return pow(2, config->blur_params.num_passes) * config->blur_params.radius;
-}
-
-bool should_parameters_blur() {
- return config->blur_params.radius > 0 && config->blur_params.num_passes > 0;
-}
// TODO: contribute wlroots function to allow creating an fbox from a box?
struct wlr_fbox wlr_fbox_from_wlr_box(struct wlr_box *box) {
@@ -241,7 +227,7 @@ void render_blur_segments(struct fx_renderer *renderer,
// Blurs the main_buffer content and returns the blurred framebuffer
struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct sway_output *output,
- pixman_region32_t *original_damage, const float box_matrix[static 9], const struct wlr_box *box) {
+ pixman_region32_t *original_damage, const struct wlr_box *box) {
struct wlr_output *wlr_output = output->wlr_output;
struct wlr_box monitor_box = get_monitor_box(wlr_output);
@@ -255,9 +241,9 @@ struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_copy(&damage, original_damage);
- wlr_region_transform(&damage, &damage, transform,
- monitor_box.width, monitor_box.height);
- wlr_region_expand(&damage, &damage, get_blur_size());
+ wlr_region_transform(&damage, &damage, transform, monitor_box.width, monitor_box.height);
+
+ wlr_region_expand(&damage, &damage, config_get_blur_size());
// Initially blur main_buffer content into the effects_buffers
struct fx_framebuffer *current_buffer = &renderer->main_buffer;
@@ -352,8 +338,7 @@ void render_blur(bool optimized, struct sway_output *output,
pixman_region32_intersect(&inverse_opaque, &inverse_opaque, &damage);
// Render the blur into its own buffer
- buffer = get_main_buffer_blur(renderer, output, &inverse_opaque,
- wlr_output->transform_matrix, dst_box);
+ buffer = get_main_buffer_blur(renderer, output, &inverse_opaque, dst_box);
}
// Draw the blurred texture
@@ -408,7 +393,7 @@ static void render_surface_iterator(struct sway_output *output,
deco_data.corner_radius *= wlr_output->scale;
// render blur (view->surface == surface excludes blurring subsurfaces)
- if (deco_data.blur && should_parameters_blur() && view->surface == surface) {
+ if (deco_data.blur && config_should_parameters_blur() && view->surface == surface) {
pixman_region32_t opaque_region;
pixman_region32_init(&opaque_region);
@@ -497,7 +482,7 @@ void render_whole_output(struct fx_renderer *renderer, struct wlr_output *wlr_ou
render_texture(wlr_output, output_damage, texture, NULL, &monitor_box, matrix, get_undecorated_decoration_data());
}
-void render_monitor_blur(struct sway_output *output, pixman_region32_t *damage) {
+void render_output_blur(struct sway_output *output, pixman_region32_t *damage) {
struct wlr_output *wlr_output = output->wlr_output;
struct fx_renderer *renderer = output->renderer;
@@ -506,8 +491,7 @@ void render_monitor_blur(struct sway_output *output, pixman_region32_t *damage)
pixman_region32_init_rect(&fake_damage, 0, 0, monitor_box.width, monitor_box.height);
// Render the blur
- struct fx_framebuffer *buffer = get_main_buffer_blur(renderer, output, &fake_damage,
- wlr_output->transform_matrix, &monitor_box);
+ struct fx_framebuffer *buffer = get_main_buffer_blur(renderer, output, &fake_damage, &monitor_box);
// Render the newly blurred content into the blur_buffer
fx_framebuffer_create(&renderer->blur_buffer,
@@ -799,7 +783,7 @@ static void render_saved_view(struct sway_view *view, struct sway_output *output
deco_data.corner_radius *= wlr_output->scale;
// render blur
- if (deco_data.blur && should_parameters_blur()) {
+ if (deco_data.blur && config_should_parameters_blur()) {
struct wlr_gles2_texture_attribs attribs;
wlr_gles2_texture_get_attribs(saved_buf->buffer->texture, &attribs);
@@ -1750,75 +1734,6 @@ static void render_seatops(struct sway_output *output,
}
}
-struct find_effect_iter_data {
- struct workspace_effect_info *effect_info;
- bool blur_buffer_dirty;
-};
-
-static bool find_con_effect_iterator(struct sway_container *con, void* _data) {
- struct sway_view *view = con->view;
- struct find_effect_iter_data *data = _data;
- struct workspace_effect_info *effect_info = data->effect_info;
-
- if (!view) {
- return false;
- }
-
- if (con->blur_enabled && !view->surface->opaque) {
- effect_info->container_wants_blur = true;
-
- bool is_floating = container_is_floating(con);
- // Check if we should render optimized blur
- if (data->blur_buffer_dirty
- // Only test floating windows when xray is enabled
- && (!is_floating || (is_floating && config->blur_xray))) {
- effect_info->should_render_optimized_blur = true;
- }
- }
- if (con->shadow_enabled) {
- effect_info->container_wants_shadow = true;
- }
-
- // Stop the iteration if all of the effects have been found.
- // Ensures that no effect is skipped if returning early
- return effect_info->container_wants_blur
- && effect_info->container_wants_shadow
- && effect_info->should_render_optimized_blur;
-}
-
-static struct workspace_effect_info get_workspace_effect_info(struct sway_output *sway_output) {
- struct fx_renderer *renderer = sway_output->renderer;
- struct sway_workspace *workspace = sway_output->current.active_workspace;
-
- struct workspace_effect_info effect_info = {
- .container_wants_blur = false,
- .container_wants_shadow = false,
- .should_render_optimized_blur = false,
- .expanded_size = 0
- };
-
- if (!workspace_is_visible(workspace)) {
- return effect_info;
- }
-
- // Iterate through the workspace containers and check if any effects are requested
- struct find_effect_iter_data iter_data = {
- .effect_info = &effect_info,
- .blur_buffer_dirty = renderer->blur_buffer_dirty
- };
- workspace_find_container(workspace, find_con_effect_iterator, &iter_data);
-
- // Set the expanded damage region
- bool shadow_enabled = effect_info.container_wants_shadow || config->shadow_enabled;
- int shadow_sigma = shadow_enabled ? config->shadow_blur_sigma : 0;
- bool blur_enabled = effect_info.container_wants_blur || config->blur_enabled;
- int blur_size = blur_enabled ? get_blur_size() : 0;
- // +1 as a margin of error
- effect_info.expanded_size = MAX(shadow_sigma, blur_size) + 1;
-
- return effect_info;
-}
-
void output_render(struct sway_output *output, struct timespec *when,
pixman_region32_t *damage) {
struct wlr_output *wlr_output = output->wlr_output;
@@ -1829,12 +1744,18 @@ void output_render(struct sway_output *output, struct timespec *when,
return;
}
+ /* we need to track extended damage for blur (as it is expanded in output.c),
+ before we expand it again later in this function
+ */
+ pixman_region32_t extended_damage;
+ pixman_region32_init(&extended_damage);
+ pixman_region32_copy(&extended_damage, damage);
+
struct sway_container *fullscreen_con = root->fullscreen_global;
if (!fullscreen_con) {
fullscreen_con = workspace->current.fullscreen;
}
-
struct wlr_box monitor_box = get_monitor_box(wlr_output);
wlr_box_transform(&monitor_box, &monitor_box,
wlr_output_transform_invert(wlr_output->transform),
@@ -1842,54 +1763,22 @@ void output_render(struct sway_output *output, struct timespec *when,
fx_renderer_begin(renderer, monitor_box.width, monitor_box.height);
- int width, height;
- wlr_output_transformed_resolution(wlr_output, &width, &height);
+ int output_width, output_height;
+ wlr_output_transformed_resolution(wlr_output, &output_width, &output_height);
+
if (debug.damage == DAMAGE_RERENDER) {
- pixman_region32_union_rect(damage, damage, 0, 0, width, height);
+ pixman_region32_union_rect(damage, damage, 0, 0, output_width, output_height);
}
- bool has_blur = false;
- bool blur_optimize_should_render = false;
- bool damage_not_empty = pixman_region32_not_empty(damage);
- pixman_region32_t extended_damage;
- pixman_region32_init(&extended_damage);
- if (!fullscreen_con && !server.session_lock.locked && damage_not_empty) {
- // Check if there are any windows to blur
- struct workspace_effect_info effect_info = get_workspace_effect_info(output);
- has_blur = effect_info.container_wants_blur || config->blur_enabled;
- if (effect_info.should_render_optimized_blur) {
- blur_optimize_should_render = true;
- // Damage the whole output
- pixman_region32_union_rect(damage, damage, 0, 0, width, height);
- }
-
- // Extend the damaged region
- int expanded_size = effect_info.expanded_size;
- if (expanded_size > 0) {
- int32_t damage_width = damage->extents.x2 - damage->extents.x1;
- int32_t damage_height = damage->extents.y2 - damage->extents.y1;
- // Limit the damage extent to the size of the monitor to prevent overflow
- if (damage_width > width || damage_height > height) {
- pixman_region32_intersect_rect(damage, damage, 0, 0, width, height);
- }
-
- wlr_region_expand(damage, damage, expanded_size);
- pixman_region32_copy(&extended_damage, damage);
- wlr_region_expand(damage, damage, expanded_size);
- } else {
- pixman_region32_copy(&extended_damage, damage);
- }
- } else {
- pixman_region32_copy(&extended_damage, damage);
+ if (!pixman_region32_not_empty(damage)) {
+ // Output isn't damaged but needs buffer swap
+ goto renderer_end;
}
- if (debug.damage == DAMAGE_HIGHLIGHT && damage_not_empty) {
+ if (debug.damage == DAMAGE_HIGHLIGHT) {
+ fx_framebuffer_bind(&renderer->wlr_buffer);
fx_renderer_clear((float[]){1, 1, 0, 1});
- }
-
- if (!damage_not_empty) {
- // Output isn't damaged but needs buffer swap
- goto renderer_end;
+ fx_framebuffer_bind(&renderer->main_buffer);
}
if (server.session_lock.locked) {
@@ -1965,6 +1854,19 @@ void output_render(struct sway_output *output, struct timespec *when,
render_unmanaged(output, damage, &root->xwayland_unmanaged);
#endif
} else {
+ bool should_render_blur = should_workspace_have_blur(workspace);
+ if (should_render_blur) {
+ // ensure that the damage isn't expanding past the output's size
+ int32_t damage_width = damage->extents.x2 - damage->extents.x1;
+ int32_t damage_height = damage->extents.y2 - damage->extents.y1;
+ if (damage_width > output_width || damage_height > output_height) {
+ pixman_region32_intersect_rect(damage, damage, 0, 0, output_width, output_height);
+ pixman_region32_intersect_rect(&extended_damage, &extended_damage, 0, 0, output_width, output_height);
+ } else {
+ wlr_region_expand(damage, damage, config_get_blur_size());
+ }
+ }
+
float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
int nrects;
@@ -1979,9 +1881,10 @@ void output_render(struct sway_output *output, struct timespec *when,
render_layer_toplevel(output, damage,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
- bool blur_enabled = has_blur && should_parameters_blur();
- if (blur_enabled && blur_optimize_should_render && renderer->blur_buffer_dirty) {
- render_monitor_blur(output, damage);
+ // check if the background needs to be blurred
+ if (config_should_parameters_blur() && renderer->blur_buffer_dirty && should_render_blur) {
+ pixman_region32_union_rect(damage, damage, 0, 0, output_width, output_height);
+ render_output_blur(output, damage);
}
render_workspace(output, damage, workspace, workspace->current.focused);
@@ -2029,6 +1932,7 @@ render_overlay:
renderer_end:
// Draw the contents of our buffer into the wlr buffer
fx_framebuffer_bind(&renderer->wlr_buffer);
+
float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
if (pixman_region32_not_empty(&extended_damage)) {
int nrects;
@@ -2038,34 +1942,30 @@ renderer_end:
fx_renderer_clear(clear_color);
}
}
+
render_whole_output(renderer, wlr_output, &extended_damage, &renderer->main_buffer.texture);
- fx_renderer_scissor(NULL);
fx_renderer_end(renderer);
+ fx_renderer_scissor(NULL);
+
// Draw the software cursors
wlr_renderer_begin(output->server->wlr_renderer, wlr_output->width, wlr_output->height);
wlr_output_render_software_cursors(wlr_output, damage);
wlr_renderer_end(output->server->wlr_renderer);
- fx_renderer_scissor(NULL);
pixman_region32_t frame_damage;
pixman_region32_init(&frame_damage);
enum wl_output_transform transform = wlr_output_transform_invert(wlr_output->transform);
- /*
- * Extend the frame damage by the blur size to properly calc damage for the
- * next buffer swap. Thanks Emersion for your excellent damage tracking blog-post!
- */
- wlr_region_transform(&frame_damage, &extended_damage, transform, width, height);
+ wlr_region_transform(&frame_damage, &extended_damage, transform, output_width, output_height);
+ pixman_region32_fini(&extended_damage);
- if (debug.damage != DAMAGE_DEFAULT || blur_optimize_should_render) {
+ if (debug.damage != DAMAGE_DEFAULT) {
pixman_region32_union_rect(&frame_damage, &frame_damage,
0, 0, wlr_output->width, wlr_output->height);
}
wlr_output_set_damage(wlr_output, &frame_damage);
-
- pixman_region32_fini(&extended_damage);
pixman_region32_fini(&frame_damage);
if (!wlr_output_commit(wlr_output)) {
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index ee940466..161b1e9c 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -690,6 +690,21 @@ void workspace_detect_urgent(struct sway_workspace *workspace) {
}
}
+static bool find_blurred_con_iterator(struct sway_container *con, void *data) {
+ struct sway_view *view = con->view;
+ if (!view) {
+ return false;
+ }
+ return con->blur_enabled && !view->surface->opaque;
+}
+
+bool should_workspace_have_blur(struct sway_workspace *ws) {
+ if (!workspace_is_visible(ws)) {
+ return false;
+ }
+ return (bool)workspace_find_container(ws, find_blurred_con_iterator, NULL);
+}
+
void workspace_for_each_container(struct sway_workspace *ws,
void (*f)(struct sway_container *con, void *data), void *data) {
// Tiling