Skip to content

Commit fdc0941

Browse files
committed
Fixed drop-shadow not being damaged when the reference buffer is damaged
Helps when the shadow is far from the reference buffer where the original buffer damage wouldn't reach the shadow node
1 parent f37930b commit fdc0941

File tree

3 files changed

+56
-17
lines changed

3 files changed

+56
-17
lines changed

include/scenefx/types/wlr_scene.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,10 @@ struct wlr_scene_shadow {
170170
float blur_sigma;
171171

172172
enum wlr_scene_shadow_type type;
173-
// Used to draw a drop-shadow. If NULL, falls-back to a box-shadow
174-
struct wlr_scene_buffer *reference_buffer;
173+
struct {
174+
// Used to draw a drop-shadow. If NULL, falls-back to a box-shadow
175+
struct wlr_scene_buffer *reference_buffer;
176+
} WLR_PRIVATE;
175177

176178
struct clipped_region clipped_region;
177179
};
@@ -253,6 +255,9 @@ struct wlr_scene_buffer {
253255
// If is_single_pixel_buffer is set, contains the color of the buffer
254256
// as {R, G, B, A} where the max value of each component is UINT32_MAX
255257
uint32_t single_pixel_buffer_color[4];
258+
259+
/** May be NULL. Used to know which shadow's linked to this scene_buffer */
260+
struct wlr_scene_shadow *linked_drop_shadow;
256261
} WLR_PRIVATE;
257262
};
258263

render/fx_renderer/fx_pass.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,12 +1163,11 @@ void fx_render_pass_add_drop_shadow(struct fx_gles_render_pass *pass,
11631163
dst_box.width + blur_sample_size * 2, dst_box.height + blur_sample_size * 2);
11641164
pixman_region32_intersect(&clip, &clip, tex_options->base.clip);
11651165

1166-
pixman_region32_t clip_scaled;
1167-
pixman_region32_init(&clip_scaled);
1168-
wlr_region_scale(&clip_scaled, &clip, drop_shadow_downscale);
11691166
pixman_region32_t clip_extended;
11701167
pixman_region32_init(&clip_extended);
1171-
wlr_region_expand(&clip_extended, &clip_scaled, blur_sample_size);
1168+
// Downsample and extend the region to increase the sample size
1169+
wlr_region_scale(&clip_extended, &clip, drop_shadow_downscale);
1170+
wlr_region_expand(&clip_extended, &clip_extended, blur_sample_size);
11721171

11731172
fx_framebuffer_bind(effects_buffer);
11741173

@@ -1186,7 +1185,7 @@ void fx_render_pass_add_drop_shadow(struct fx_gles_render_pass *pass,
11861185
glDisable(GL_SCISSOR_TEST);
11871186

11881187
// Initially Render to the effects buffer
1189-
tex_options->base.clip = &clip_scaled;
1188+
tex_options->base.clip = &clip_extended;
11901189
tex_options->clip_box = NULL;
11911190

11921191
scale_box(&tex_options->base.dst_box, drop_shadow_downscale);
@@ -1235,7 +1234,6 @@ void fx_render_pass_add_drop_shadow(struct fx_gles_render_pass *pass,
12351234
fx_render_pass_add_drop_shadow_final(pass, tex_options, color);
12361235

12371236
pixman_region32_fini(&clip_extended);
1238-
pixman_region32_fini(&clip_scaled);
12391237
pixman_region32_fini(&clip);
12401238
}
12411239

types/scene/wlr_scene.c

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@
4646
#define SCENE_RECT_SHOULD_BLUR(scene_rect, blur_data) \
4747
(scene_rect->backdrop_blur && is_scene_blur_enabled(blur_data) && \
4848
scene_rect->color[3] < 1.0f)
49+
#define SCENE_SHADOW_IS_DROP(scene_shadow) \
50+
(scene_shadow->type == WLR_SCENE_SHADOW_TYPE_DROP \
51+
&& scene_shadow->reference_buffer \
52+
&& scene_shadow->blur_sigma >= 0)
4953

5054
struct wlr_scene_tree *wlr_scene_tree_from_node(struct wlr_scene_node *node) {
5155
assert(node->type == WLR_SCENE_NODE_TREE);
@@ -186,6 +190,13 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) {
186190
&scene_tree->children, link) {
187191
wlr_scene_node_destroy(child);
188192
}
193+
} else if (node->type == WLR_SCENE_NODE_SHADOW) {
194+
// Remove the drop-shadows referenced buffers link to this node
195+
struct wlr_scene_shadow *scene_shadow = wlr_scene_shadow_from_node(node);
196+
if (scene_shadow->reference_buffer
197+
&& scene_shadow->reference_buffer->linked_drop_shadow == scene_shadow) {
198+
scene_shadow->reference_buffer->linked_drop_shadow = NULL;
199+
}
189200
}
190201

191202
assert(wl_list_empty(&node->events.destroy.listener_list));
@@ -1039,6 +1050,15 @@ void wlr_scene_shadow_set_reference_buffer(struct wlr_scene_shadow *shadow,
10391050
"Please change its type before calling this function");
10401051
return;
10411052
}
1053+
1054+
// Unlink the other drop shadow from the reference buffer if it exists
1055+
if (shadow->reference_buffer) {
1056+
shadow->reference_buffer->linked_drop_shadow = NULL;
1057+
}
1058+
if (ref_buffer) {
1059+
ref_buffer->linked_drop_shadow = shadow;
1060+
}
1061+
10421062
if (ref_buffer == shadow->reference_buffer) {
10431063
return;
10441064
}
@@ -1244,6 +1264,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent,
12441264
scene_buffer->backdrop_blur_optimized = false;
12451265
scene_buffer->backdrop_blur_ignore_transparent = true;
12461266
scene_buffer->corners = CORNER_LOCATION_NONE;
1267+
scene_buffer->linked_drop_shadow = NULL;
12471268

12481269
scene_buffer_set_buffer(scene_buffer, buffer);
12491270
scene_node_update(&scene_buffer->node, NULL);
@@ -1392,6 +1413,28 @@ void wlr_scene_buffer_set_buffer_with_options(struct wlr_scene_buffer *scene_buf
13921413
pixman_region32_intersect(&output_damage, &output_damage, &cull_region);
13931414
pixman_region32_fini(&cull_region);
13941415

1416+
// Also damage the linked drop-shadow
1417+
struct wlr_scene_shadow *scene_shadow = scene_buffer->linked_drop_shadow;
1418+
if (scene_shadow && SCENE_SHADOW_IS_DROP(scene_shadow)) {
1419+
int shadow_lx, shadow_ly;
1420+
if (wlr_scene_node_coords(&scene_shadow->node, &shadow_lx, &shadow_ly)) {
1421+
const int shadow_size = drop_shadow_calc_size(scene_shadow->blur_sigma);
1422+
1423+
// Copy the damaged region, translate it to the shadow nodes
1424+
// position, and add it to the original damage
1425+
pixman_region32_t shadow_damage;
1426+
pixman_region32_init(&shadow_damage);
1427+
pixman_region32_copy(&shadow_damage, &output_damage);
1428+
pixman_region32_translate(&shadow_damage,
1429+
((shadow_lx + shadow_size) - lx) * output_scale,
1430+
((shadow_ly + shadow_size) - ly) * output_scale);
1431+
wlr_region_expand(&shadow_damage, &shadow_damage,
1432+
drop_shadow_calc_size(scene_shadow->blur_sigma));
1433+
1434+
pixman_region32_union(&output_damage, &output_damage, &shadow_damage);
1435+
}
1436+
}
1437+
13951438
// Expand the damage when committed to, fixes blur artifacts
13961439
if (SCENE_BUFFER_SHOULD_BLUR(scene_buffer, &scene->blur_data)) {
13971440
wlr_region_expand(&output_damage, &output_damage,
@@ -2814,18 +2857,11 @@ static bool scene_output_has_blur(int list_len,
28142857
break;
28152858
case WLR_SCENE_NODE_SHADOW:;
28162859
struct wlr_scene_shadow *scene_shadow = wlr_scene_shadow_from_node(node);
2817-
if (scene_shadow->type != WLR_SCENE_SHADOW_TYPE_DROP
2818-
|| !scene_shadow->reference_buffer
2819-
|| scene_shadow->blur_sigma < 0) {
2860+
if (!SCENE_SHADOW_IS_DROP(scene_shadow)) {
28202861
goto fini;
28212862
}
28222863
node_blur_region(node, scene_output, &node_region);
2823-
const int shadow_size = drop_shadow_calc_size(scene_shadow->blur_sigma);
2824-
// Make sure to re-render the shadow due to it extending past
2825-
// the buffer
2826-
wlr_region_expand(&node_region, &node_region, shadow_size);
2827-
2828-
blur_size = shadow_size;
2864+
blur_size = drop_shadow_calc_size(scene_shadow->blur_sigma);
28292865
break;
28302866
default:
28312867
goto fini;

0 commit comments

Comments
 (0)