Skip to content

Commit bc55ef5

Browse files
committed
Moved the drop shadow into its own scene node
1 parent 7ff309b commit bc55ef5

8 files changed

Lines changed: 317 additions & 157 deletions

File tree

examples/scene-graph.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,9 @@ static void surface_handle_commit(struct wl_listener *listener, void *data) {
100100
wlr_scene_rect_set_size(surface->border,
101101
surface->wlr->current.width + 2 * border_width,
102102
surface->wlr->current.height + 2 * border_width);
103-
const int blur_offset = wlr_scene_shadow_get_offset(surface->shadow);
104103
wlr_scene_shadow_set_size(surface->shadow,
105-
surface->wlr->current.width + 2 * (blur_offset + border_width),
106-
surface->wlr->current.height + 2 * (blur_offset + border_width));
104+
surface->wlr->current.width + 2 * (surface->shadow->blur_sigma + border_width),
105+
surface->wlr->current.height + 2 * (surface->shadow->blur_sigma + border_width));
107106
}
108107

109108
static void surface_handle_destroy(struct wl_listener *listener, void *data) {
@@ -140,9 +139,8 @@ static void server_handle_new_surface(struct wl_listener *listener,
140139
float blur_sigma = 20.0f;
141140
surface->shadow = wlr_scene_shadow_create(&server->scene->tree,
142141
0, 0, corner_radius, blur_sigma, (float[4]){ 1.0f, 0.f, 0.f, 1.0f });
143-
const int blur_offset = wlr_scene_shadow_get_offset(surface->shadow);
144142
wlr_scene_node_set_position(&surface->shadow->node,
145-
pos - blur_offset, pos - blur_offset);
143+
pos - blur_sigma, pos - blur_sigma);
146144
surface->scene_surface =
147145
wlr_scene_surface_create(&server->scene->tree, wlr_surface);
148146
wlr_scene_buffer_set_corner_radius(

include/scenefx/types/fx/blur_data.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <stdbool.h>
55
#include <wlr/util/addon.h>
66

7+
// Calculate the drop-shadows blur sample size
78
#define drop_shadow_calc_size(blur_sigma) (ceil(1.5f * blur_sigma) * 2)
89
#define drop_shadow_downscale 0.5
910

include/scenefx/types/linked_node.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ struct linked_node {
1616
.link = NULL \
1717
})
1818

19+
#define linked_node_initialized(node) ((node)->link != NULL)
20+
1921
bool linked_nodes_are_linked(struct linked_node *node_1,
2022
struct linked_node *node_2);
2123

include/scenefx/types/wlr_scene.h

Lines changed: 100 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ enum wlr_scene_node_type {
5858
WLR_SCENE_NODE_TREE,
5959
WLR_SCENE_NODE_RECT,
6060
WLR_SCENE_NODE_SHADOW,
61+
WLR_SCENE_NODE_DROP_SHADOW,
6162
WLR_SCENE_NODE_BUFFER,
6263
WLR_SCENE_NODE_OPTIMIZED_BLUR,
6364
WLR_SCENE_NODE_BLUR,
@@ -162,9 +163,20 @@ struct wlr_scene_shadow {
162163
float color[4];
163164
float blur_sigma;
164165

166+
struct clipped_region clipped_region;
167+
};
168+
169+
/** A scene-graph node displaying a dynamic drop-shadow */
170+
struct wlr_scene_drop_shadow {
171+
struct wlr_scene_node node;
172+
int width, height;
173+
float color[4];
174+
float blur_sigma;
175+
165176
struct {
166-
// Used to draw a drop-shadow
167-
struct linked_node buffer_link;
177+
float blur_sample_size;
178+
// Skips drawing if NULL
179+
struct linked_node buffer_source;
168180
} WLR_PRIVATE;
169181

170182
struct clipped_region clipped_region;
@@ -182,7 +194,9 @@ struct wlr_scene_blur {
182194

183195
bool should_only_blur_bottom_layer;
184196

185-
struct linked_node transparency_mask_source;
197+
struct {
198+
struct linked_node transparency_mask_source;
199+
} WLR_PRIVATE;
186200
};
187201

188202
/** A scene-graph node telling SceneFX to render the optimized blur */
@@ -261,7 +275,7 @@ struct wlr_scene_buffer {
261275

262276
struct linked_node blur;
263277
// Used to know which shadow's linked to this scene_buffer
264-
struct linked_node drop_shadow_link;
278+
struct linked_node drop_shadow;
265279
} WLR_PRIVATE;
266280
};
267281

@@ -496,6 +510,16 @@ struct wlr_scene_rect *wlr_scene_rect_from_node(struct wlr_scene_node *node);
496510
*/
497511
struct wlr_scene_shadow *wlr_scene_shadow_from_node(struct wlr_scene_node *node);
498512

513+
/**
514+
* If this node represents a wlr_scene_drop_shadow, that shadow will be returned. It
515+
* is not legal to feed a node that does not represent a wlr_scene_drop_shadow.
516+
*/
517+
struct wlr_scene_drop_shadow *wlr_scene_drop_shadow_from_node(struct wlr_scene_node *node);
518+
519+
/**
520+
* If this node represents a wlr_scene_blur node, that blur node will be returned.
521+
* It is not legal to feed a node that does not represent a wlr_scene_blur node.
522+
*/
499523
struct wlr_scene_blur *wlr_scene_blur_from_node(struct wlr_scene_node *node);
500524

501525
/**
@@ -547,8 +571,7 @@ void wlr_scene_rect_set_clipped_region(struct wlr_scene_rect *rect,
547571
void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[static 4]);
548572

549573
/**
550-
* Add a node displaying a shadow to the scene-graph. The shadow type created is
551-
* a regular box-shadow.
574+
* Add a node displaying a shadow to the scene-graph.
552575
*/
553576
struct wlr_scene_shadow *wlr_scene_shadow_create(struct wlr_scene_tree *parent,
554577
int width, int height, int corner_radius, float blur_sigma,
@@ -574,39 +597,97 @@ void wlr_scene_shadow_set_blur_sigma(struct wlr_scene_shadow *shadow, float blur
574597
*/
575598
void wlr_scene_shadow_set_color(struct wlr_scene_shadow *shadow, const float color[static 4]);
576599

600+
/**
601+
* Sets the region where to clip the shadow.
602+
*
603+
* For there to be corner rounding of the clipped region, the corner radius and
604+
* corners must be non-zero.
605+
*
606+
* NOTE: The positioning is node-relative.
607+
*/
608+
void wlr_scene_shadow_set_clipped_region(struct wlr_scene_shadow *shadow,
609+
struct clipped_region clipped_region);
610+
611+
/**
612+
* Add a node displaying a drop shadow to the scene-graph.
613+
*
614+
* It's recommended to use `wlr_scene_drop_shadow_calculate_offset` when first
615+
* setting the size and adjusting the nodes position.
616+
*
617+
* NOTE: A reference `wlr_scene_buffer` needs to be set using
618+
* `wlr_scene_drop_shadow_set_reference_buffer` for the shadow to render.
619+
*/
620+
struct wlr_scene_drop_shadow *wlr_scene_drop_shadow_create(struct wlr_scene_tree *parent,
621+
int width, int height, float blur_sigma, const float color[static 4]);
622+
623+
/**
624+
* Change the width and height of an existing drop shadow node.
625+
*
626+
* NOTE: The set size of the node doesn't include the blur sample size (offset),
627+
* It's recommended to include the offset in the calculations by using
628+
* `wlr_scene_drop_shadow_get_offset`.
629+
*
630+
* Proper Width example: `toplevel_width + offset * 2 = correctly_fitted_width`
631+
* Proper X Position example: `toplevel_x - offset = correctly_x_positioned`
632+
*/
633+
void wlr_scene_drop_shadow_set_size(struct wlr_scene_drop_shadow *shadow, int width, int height);
634+
635+
/**
636+
* Change the blur_sigma of an existing drop shadow node.
637+
*
638+
* NOTE: This adjusts the drop-shadows offset, so it's recommended to also
639+
* adjust the nodes size and position to compensate.
640+
*/
641+
void wlr_scene_drop_shadow_set_blur_sigma(struct wlr_scene_drop_shadow *shadow, float blur_sigma);
642+
643+
/**
644+
* Change the color of an existing drop shadow node.
645+
*/
646+
void wlr_scene_drop_shadow_set_color(struct wlr_scene_drop_shadow *shadow, const float color[static 4]);
647+
577648
/**
578649
* Change the reference scene_buffer.
579-
* NOTE: Will fallback to a box-shadow if the provided buffer is NULL.
650+
* NOTE: Will skip rendering if the provided buffer is NULL.
580651
*/
581-
void wlr_scene_shadow_set_reference_buffer(struct wlr_scene_shadow *shadow,
652+
void wlr_scene_drop_shadow_set_reference_buffer(struct wlr_scene_drop_shadow *shadow,
582653
struct wlr_scene_buffer *ref_buffer);
583654

584655
/**
585656
* Get the reference scene_buffer.
586657
*/
587-
struct wlr_scene_buffer *wlr_scene_shadow_get_reference_buffer(struct wlr_scene_shadow *shadow);
658+
struct wlr_scene_buffer *wlr_scene_drop_shadow_get_reference_buffer(struct wlr_scene_drop_shadow *shadow);
588659

589660
/**
590-
* Gets the sample size of the shadow. Can be used when setting the size of
591-
* the shadow node. Returns the correct size offset used depending on the
592-
* shadow-type. A drop-shadow returns a larger integer compared to the
593-
* box-shadow, so this can be used to dynamically adjust the size and position
594-
* depending on the shadow-type. Eg:
661+
* Gets the offset of a drop shadow, the recommended way. Can be used as an
662+
* offset for setting the correct size and position relative to a toplevel.
663+
* Proper Width example: `toplevel_width + offset * 2 = correctly_fitted_width`
664+
* Proper X Position example: `toplevel_x - offset = correctly_x_positioned`
595665
*
596-
* Scene Buffer size: 100 x 100px
597-
* Proper Shadow Node size: 100px + offset x 100px + offset = the correct size
666+
* This is the same as `wlr_scene_drop_shadow_calculate_offset`, but uses the
667+
* already cached offset instead of recalculating the offset.
598668
*/
599-
int wlr_scene_shadow_get_offset(struct wlr_scene_shadow *shadow);
669+
int wlr_scene_drop_shadow_get_offset(struct wlr_scene_drop_shadow *shadow);
600670

601671
/**
602-
* Sets the region where to clip the shadow.
672+
* Gets the sample size of a drop shadow.
673+
*
674+
* Tip: Recalculates the offset, so it's recommended to only use this function
675+
* to calculate the initial size and position of the node while using
676+
* `wlr_scene_drop_shadow_get_offset` in other cases.
677+
*/
678+
__always_inline float wlr_scene_drop_shadow_calculate_offset(int blur_sigma) {
679+
return drop_shadow_calc_size(blur_sigma);
680+
}
681+
682+
/**
683+
* Sets the region where to clip the drop shadow.
603684
*
604685
* For there to be corner rounding of the clipped region, the corner radius and
605686
* corners must be non-zero.
606687
*
607688
* NOTE: The positioning is node-relative.
608689
*/
609-
void wlr_scene_shadow_set_clipped_region(struct wlr_scene_shadow *shadow,
690+
void wlr_scene_drop_shadow_set_clipped_region(struct wlr_scene_drop_shadow *shadow,
610691
struct clipped_region clipped_region);
611692

612693
/**

render/fx_renderer/fx_framebuffer.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ void fx_framebuffer_get_or_create_custom(struct fx_renderer *renderer,
7979
int height = output->height;
8080
struct wlr_buffer *wlr_buffer = NULL;
8181

82-
// Try getting a format with alpha. One could use the outputs swapchain
82+
// TODO: Configure to use non-alpha to save some GPU memory :)
83+
// TODO: Cache this, don't find it at runtime
84+
// Try getting a format with alpha. We could use the outputs swapchain
8385
// format, but that one doesn't support alpha.
8486
const struct fx_pixel_format *pix_fmt =
8587
get_fx_format_from_gl(GL_RGBA, GL_UNSIGNED_BYTE, true);

tinywl/tinywl.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -613,13 +613,13 @@ static void xdg_toplevel_commit(struct wl_listener *listener, void *data) {
613613
.area = { BORDER_THICKNESS, BORDER_THICKNESS, geometry->width, geometry->height }
614614
});
615615

616-
const int blur_offset = wlr_scene_shadow_get_offset(toplevel->shadow);
616+
int blur_sigma = toplevel->shadow->blur_sigma;
617617
wlr_scene_shadow_set_size(toplevel->shadow,
618-
border_width + (blur_offset * 2),
619-
border_height + (blur_offset * 2));
618+
border_width + (blur_sigma * 2),
619+
border_height + (blur_sigma * 2));
620620
wlr_scene_shadow_set_clipped_region(toplevel->shadow, (struct clipped_region) {
621621
.corners = corner_radii_all(toplevel->corner_radius + BORDER_THICKNESS),
622-
.area = { blur_offset, blur_offset, border_width, border_height }
622+
.area = { blur_sigma, blur_sigma, border_width, border_height }
623623
});
624624
}
625625

@@ -966,9 +966,8 @@ static void server_new_xdg_toplevel(struct wl_listener *listener, void *data) {
966966
float blur_sigma = 20.0f;
967967
toplevel->shadow = wlr_scene_shadow_create(toplevel->scene_tree,
968968
0, 0, toplevel->corner_radius, blur_sigma, (float[4]){ 0.f, 1.0f, 0.f, 1.0f });
969-
const int blur_offset = wlr_scene_shadow_get_offset(toplevel->shadow);
970-
wlr_scene_node_set_position(&toplevel->shadow->node, -BORDER_THICKNESS - blur_offset,
971-
-BORDER_THICKNESS - blur_offset);
969+
wlr_scene_node_set_position(&toplevel->shadow->node, -BORDER_THICKNESS - blur_sigma,
970+
-BORDER_THICKNESS - blur_sigma);
972971

973972
// Lower the border below the XDG scene tree
974973
wlr_scene_node_lower_to_bottom(&toplevel->border->node);

types/scene/linked_node.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@ static struct link *link_init(struct linked_node *node_1,
3030

3131
bool linked_nodes_are_linked(struct linked_node *node_1,
3232
struct linked_node *node_2) {
33-
return node_1->link != NULL && node_2->link != NULL
33+
return linked_node_initialized(node_1) && linked_node_initialized(node_2)
3434
&& node_1->link == node_2->link;
3535
}
3636

3737
void linked_node_init_link(struct linked_node *node_1,
3838
struct linked_node *node_2) {
39-
if (node_1->link || node_2->link) {
39+
if (linked_node_initialized(node_1) || linked_node_initialized(node_2)) {
4040
assert(linked_nodes_are_linked(node_1, node_2));
4141
return;
4242
}
@@ -47,7 +47,7 @@ void linked_node_init_link(struct linked_node *node_1,
4747
}
4848

4949
struct linked_node *linked_node_get_sibling(struct linked_node *node) {
50-
if (node->link == NULL) {
50+
if (!linked_node_initialized(node)) {
5151
return NULL;
5252
}
5353
assert(node == node->link->node_1 || node == node->link->node_2);
@@ -70,7 +70,7 @@ void linked_node_unlink(struct linked_node *node_1,
7070
}
7171

7272
void linked_node_destroy(struct linked_node *node) {
73-
if (node->link == NULL) {
73+
if (!linked_node_initialized(node)) {
7474
return;
7575
}
7676
assert(node == node->link->node_1 || node == node->link->node_2);

0 commit comments

Comments
 (0)