|
46 | 46 | #define SCENE_RECT_SHOULD_BLUR(scene_rect, blur_data) \ |
47 | 47 | (scene_rect->backdrop_blur && is_scene_blur_enabled(blur_data) && \ |
48 | 48 | 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) |
49 | 53 |
|
50 | 54 | struct wlr_scene_tree *wlr_scene_tree_from_node(struct wlr_scene_node *node) { |
51 | 55 | assert(node->type == WLR_SCENE_NODE_TREE); |
@@ -186,6 +190,13 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { |
186 | 190 | &scene_tree->children, link) { |
187 | 191 | wlr_scene_node_destroy(child); |
188 | 192 | } |
| 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 | + } |
189 | 200 | } |
190 | 201 |
|
191 | 202 | 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, |
1039 | 1050 | "Please change its type before calling this function"); |
1040 | 1051 | return; |
1041 | 1052 | } |
| 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 | + |
1042 | 1062 | if (ref_buffer == shadow->reference_buffer) { |
1043 | 1063 | return; |
1044 | 1064 | } |
@@ -1244,6 +1264,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, |
1244 | 1264 | scene_buffer->backdrop_blur_optimized = false; |
1245 | 1265 | scene_buffer->backdrop_blur_ignore_transparent = true; |
1246 | 1266 | scene_buffer->corners = CORNER_LOCATION_NONE; |
| 1267 | + scene_buffer->linked_drop_shadow = NULL; |
1247 | 1268 |
|
1248 | 1269 | scene_buffer_set_buffer(scene_buffer, buffer); |
1249 | 1270 | 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 |
1392 | 1413 | pixman_region32_intersect(&output_damage, &output_damage, &cull_region); |
1393 | 1414 | pixman_region32_fini(&cull_region); |
1394 | 1415 |
|
| 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 | + |
1395 | 1438 | // Expand the damage when committed to, fixes blur artifacts |
1396 | 1439 | if (SCENE_BUFFER_SHOULD_BLUR(scene_buffer, &scene->blur_data)) { |
1397 | 1440 | wlr_region_expand(&output_damage, &output_damage, |
@@ -2814,18 +2857,11 @@ static bool scene_output_has_blur(int list_len, |
2814 | 2857 | break; |
2815 | 2858 | case WLR_SCENE_NODE_SHADOW:; |
2816 | 2859 | 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)) { |
2820 | 2861 | goto fini; |
2821 | 2862 | } |
2822 | 2863 | 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); |
2829 | 2865 | break; |
2830 | 2866 | default: |
2831 | 2867 | goto fini; |
|
0 commit comments