scene: add RECT node type
RECT is a solid-colored rectangle, useful for simple borders or other decoration. This can be rendered directly using the wlr_renderer, without needing to create a surface.
This commit is contained in:
		
							parent
							
								
									526652a554
								
							
						
					
					
						commit
						b7cd06e8fa
					
				|  | @ -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 | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| #include <assert.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <wlr/backend.h> | ||||
| #include <wlr/render/wlr_renderer.h> | ||||
| #include <wlr/types/wlr_matrix.h> | ||||
|  | @ -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; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue