diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 6e0aebf8..4b3c1aaf 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -28,6 +28,7 @@ struct wlr_output; enum wlr_scene_node_type { WLR_SCENE_NODE_ROOT, WLR_SCENE_NODE_SURFACE, + WLR_SCENE_NODE_RECT, }; struct wlr_scene_node_state { @@ -67,6 +68,13 @@ struct wlr_scene_surface { struct wl_listener surface_destroy; }; +/** A scene-graph node displaying a solid-colored rectangle */ +struct wlr_scene_rect { + struct wlr_scene_node node; + int width, height; + float color[4]; +}; + typedef void (*wlr_scene_node_iterator_func_t)(struct wlr_scene_node *node, int sx, int sy, void *data); @@ -134,4 +142,20 @@ void wlr_scene_render_output(struct wlr_scene *scene, struct wlr_output *output, struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent, struct wlr_surface *surface); +/** + * Add a node displaying a solid-colored rectangle to the scene-graph. + */ +struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_node *parent, + int width, int height, const float color[static 4]); + +/** + * Change the width and height of an existing rectangle node. + */ +void wlr_scene_rect_set_size(struct wlr_scene_rect *rect, int width, int height); + +/** + * Change the color of an existing rectangle node. + */ +void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[static 4]); + #endif diff --git a/types/wlr_scene.c b/types/wlr_scene.c index dfd221b2..aa5c5b36 100644 --- a/types/wlr_scene.c +++ b/types/wlr_scene.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -18,6 +19,12 @@ static struct wlr_scene_surface *scene_surface_from_node( return (struct wlr_scene_surface *)node; } +static struct wlr_scene_rect *scene_rect_from_node( + struct wlr_scene_node *node) { + assert(node->type == WLR_SCENE_NODE_RECT); + return (struct wlr_scene_rect *)node; +} + static void scene_node_state_init(struct wlr_scene_node_state *state) { wl_list_init(&state->children); wl_list_init(&state->link); @@ -71,6 +78,10 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wl_list_remove(&scene_surface->surface_destroy.link); free(scene_surface); break; + case WLR_SCENE_NODE_RECT:; + struct wlr_scene_rect *scene_rect = scene_rect_from_node(node); + free(scene_rect); + break; } } @@ -108,6 +119,31 @@ struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent return scene_surface; } +struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_node *parent, + int width, int height, const float color[static 4]) { + struct wlr_scene_rect *scene_rect = + calloc(1, sizeof(struct wlr_scene_rect)); + if (scene_rect == NULL) { + return NULL; + } + scene_node_init(&scene_rect->node, WLR_SCENE_NODE_RECT, parent); + + scene_rect->width = width; + scene_rect->height = height; + memcpy(scene_rect->color, color, sizeof(scene_rect->color)); + + return scene_rect; +} + +void wlr_scene_rect_set_size(struct wlr_scene_rect *rect, int width, int height) { + rect->width = width; + rect->height = height; +} + +void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[static 4]) { + memcpy(rect->color, color, sizeof(rect->color)); +} + void wlr_scene_node_set_enabled(struct wlr_scene_node *node, bool enabled) { node->state.enabled = enabled; } @@ -244,6 +280,27 @@ static void scissor_output(struct wlr_output *output, pixman_box32_t *rect) { wlr_renderer_scissor(renderer, &box); } +static void render_rect(struct wlr_output *output, + pixman_region32_t *output_damage, const float color[static 4], + const struct wlr_box *box, const float matrix[static 9]) { + struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend); + assert(renderer); + + pixman_region32_t damage; + pixman_region32_init(&damage); + pixman_region32_init_rect(&damage, box->x, box->y, box->width, box->height); + pixman_region32_intersect(&damage, &damage, output_damage); + + int nrects; + pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); + for (int i = 0; i < nrects; ++i) { + scissor_output(output, &rects[i]); + wlr_render_rect(renderer, box, color, matrix); + } + + pixman_region32_fini(&damage); +} + static void render_texture(struct wlr_output *output, pixman_region32_t *output_damage, struct wlr_texture *texture, const struct wlr_box *box, const float matrix[static 9]) { @@ -275,6 +332,10 @@ static void render_node_iterator(struct wlr_scene_node *node, struct render_data *data = _data; struct wlr_output *output = data->output; pixman_region32_t *output_damage = data->damage; + struct wlr_box box = { + .x = x, + .y = y, + }; switch (node->type) { case WLR_SCENE_NODE_ROOT:; @@ -289,12 +350,8 @@ static void render_node_iterator(struct wlr_scene_node *node, return; } - struct wlr_box box = { - .x = x, - .y = y, - .width = surface->current.width, - .height = surface->current.height, - }; + box.width = surface->current.width; + box.height = surface->current.height; scale_box(&box, output->scale); float matrix[9]; @@ -305,6 +362,16 @@ static void render_node_iterator(struct wlr_scene_node *node, render_texture(output, output_damage, texture, &box, matrix); break; + case WLR_SCENE_NODE_RECT:; + struct wlr_scene_rect *scene_rect = scene_rect_from_node(node); + + box.width = scene_rect->width; + box.height = scene_rect->height; + scale_box(&box, data->output->scale); + + render_rect(output, output_damage, scene_rect->color, &box, + output->transform_matrix); + break; } }