scene: add wlr_scene_set_presentation()
This helper automates sending presentation feedback to clients based on the primary output of scene surfaces.
This commit is contained in:
		
							parent
							
								
									c0b120a30c
								
							
						
					
					
						commit
						07ccc6e0b3
					
				|  | @ -62,6 +62,12 @@ struct wlr_scene { | ||||||
| 	struct wlr_scene_node node; | 	struct wlr_scene_node node; | ||||||
| 
 | 
 | ||||||
| 	struct wl_list outputs; // wlr_scene_output.link
 | 	struct wl_list outputs; // wlr_scene_output.link
 | ||||||
|  | 
 | ||||||
|  | 	// private state
 | ||||||
|  | 
 | ||||||
|  | 	// May be NULL
 | ||||||
|  | 	struct wlr_presentation *presentation; | ||||||
|  | 	struct wl_listener presentation_destroy; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** A sub-tree in the scene-graph. */ | /** A sub-tree in the scene-graph. */ | ||||||
|  | @ -201,6 +207,14 @@ struct wlr_scene *wlr_scene_create(void); | ||||||
|  */ |  */ | ||||||
| void wlr_scene_render_output(struct wlr_scene *scene, struct wlr_output *output, | void wlr_scene_render_output(struct wlr_scene *scene, struct wlr_output *output, | ||||||
| 	int lx, int ly, pixman_region32_t *damage); | 	int lx, int ly, pixman_region32_t *damage); | ||||||
|  | /**
 | ||||||
|  |  * Handle presentation feedback for all surfaces in the scene, assuming that | ||||||
|  |  * scene outputs and the scene rendering functions are used. | ||||||
|  |  * | ||||||
|  |  * Asserts that a wlr_presentation hasn't already been set for the scene. | ||||||
|  |  */ | ||||||
|  | void wlr_scene_set_presentation(struct wlr_scene *scene, | ||||||
|  | 	struct wlr_presentation *presentation); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Add a node displaying nothing but its children. |  * Add a node displaying nothing but its children. | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include <wlr/render/wlr_renderer.h> | #include <wlr/render/wlr_renderer.h> | ||||||
| #include <wlr/types/wlr_matrix.h> | #include <wlr/types/wlr_matrix.h> | ||||||
| #include <wlr/types/wlr_output_damage.h> | #include <wlr/types/wlr_output_damage.h> | ||||||
|  | #include <wlr/types/wlr_presentation_time.h> | ||||||
| #include <wlr/types/wlr_scene.h> | #include <wlr/types/wlr_scene.h> | ||||||
| #include <wlr/types/wlr_surface.h> | #include <wlr/types/wlr_surface.h> | ||||||
| #include <wlr/util/log.h> | #include <wlr/util/log.h> | ||||||
|  | @ -101,6 +102,8 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { | ||||||
| 			wlr_scene_output_destroy(scene_output); | 			wlr_scene_output_destroy(scene_output); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		wl_list_remove(&scene->presentation_destroy.link); | ||||||
|  | 
 | ||||||
| 		free(scene); | 		free(scene); | ||||||
| 		break; | 		break; | ||||||
| 	case WLR_SCENE_NODE_TREE:; | 	case WLR_SCENE_NODE_TREE:; | ||||||
|  | @ -141,6 +144,7 @@ struct wlr_scene *wlr_scene_create(void) { | ||||||
| 	} | 	} | ||||||
| 	scene_node_init(&scene->node, WLR_SCENE_NODE_ROOT, NULL); | 	scene_node_init(&scene->node, WLR_SCENE_NODE_ROOT, NULL); | ||||||
| 	wl_list_init(&scene->outputs); | 	wl_list_init(&scene->outputs); | ||||||
|  | 	wl_list_init(&scene->presentation_destroy.link); | ||||||
| 	return scene; | 	return scene; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -767,6 +771,9 @@ static void render_texture(struct wlr_output *output, | ||||||
| struct render_data { | struct render_data { | ||||||
| 	struct wlr_output *output; | 	struct wlr_output *output; | ||||||
| 	pixman_region32_t *damage; | 	pixman_region32_t *damage; | ||||||
|  | 
 | ||||||
|  | 	// May be NULL
 | ||||||
|  | 	struct wlr_presentation *presentation; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void render_node_iterator(struct wlr_scene_node *node, | static void render_node_iterator(struct wlr_scene_node *node, | ||||||
|  | @ -808,6 +815,11 @@ static void render_node_iterator(struct wlr_scene_node *node, | ||||||
| 
 | 
 | ||||||
| 		render_texture(output, output_damage, texture, | 		render_texture(output, output_damage, texture, | ||||||
| 			&src_box, &dst_box, matrix); | 			&src_box, &dst_box, matrix); | ||||||
|  | 
 | ||||||
|  | 		if (data->presentation != NULL && scene_surface->primary_output == output) { | ||||||
|  | 			wlr_presentation_surface_sampled_on_output(data->presentation, | ||||||
|  | 				surface, output); | ||||||
|  | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case WLR_SCENE_NODE_RECT:; | 	case WLR_SCENE_NODE_RECT:; | ||||||
| 		struct wlr_scene_rect *scene_rect = scene_rect_from_node(node); | 		struct wlr_scene_rect *scene_rect = scene_rect_from_node(node); | ||||||
|  | @ -867,6 +879,7 @@ void wlr_scene_render_output(struct wlr_scene *scene, struct wlr_output *output, | ||||||
| 		struct render_data data = { | 		struct render_data data = { | ||||||
| 			.output = output, | 			.output = output, | ||||||
| 			.damage = damage, | 			.damage = damage, | ||||||
|  | 			.presentation = scene->presentation, | ||||||
| 		}; | 		}; | ||||||
| 		scene_node_for_each_node(&scene->node, -lx, -ly, | 		scene_node_for_each_node(&scene->node, -lx, -ly, | ||||||
| 			render_node_iterator, &data); | 			render_node_iterator, &data); | ||||||
|  | @ -876,6 +889,23 @@ void wlr_scene_render_output(struct wlr_scene *scene, struct wlr_output *output, | ||||||
| 	pixman_region32_fini(&full_region); | 	pixman_region32_fini(&full_region); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void scene_handle_presentation_destroy(struct wl_listener *listener, | ||||||
|  | 		void *data) { | ||||||
|  | 	struct wlr_scene *scene = | ||||||
|  | 		wl_container_of(listener, scene, presentation_destroy); | ||||||
|  | 	wl_list_remove(&scene->presentation_destroy.link); | ||||||
|  | 	wl_list_init(&scene->presentation_destroy.link); | ||||||
|  | 	scene->presentation = NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void wlr_scene_set_presentation(struct wlr_scene *scene, | ||||||
|  | 		struct wlr_presentation *presentation) { | ||||||
|  | 	assert(scene->presentation == NULL); | ||||||
|  | 	scene->presentation = presentation; | ||||||
|  | 	scene->presentation_destroy.notify = scene_handle_presentation_destroy; | ||||||
|  | 	wl_signal_add(&presentation->events.destroy, &scene->presentation_destroy); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void scene_output_handle_destroy(struct wlr_addon *addon) { | static void scene_output_handle_destroy(struct wlr_addon *addon) { | ||||||
| 	struct wlr_scene_output *scene_output = | 	struct wlr_scene_output *scene_output = | ||||||
| 		wl_container_of(addon, scene_output, addon); | 		wl_container_of(addon, scene_output, addon); | ||||||
|  | @ -1028,6 +1058,18 @@ static bool scene_output_scanout(struct wlr_scene_output *scene_output) { | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	struct wlr_presentation *presentation = scene_output->scene->presentation; | ||||||
|  | 	if (presentation != NULL && node->type == WLR_SCENE_NODE_SURFACE) { | ||||||
|  | 		struct wlr_scene_surface *scene_surface = | ||||||
|  | 			wlr_scene_surface_from_node(node); | ||||||
|  | 		// Since outputs may overlap, we still need to check this even though
 | ||||||
|  | 		// we know that the surface size matches the size of this output.
 | ||||||
|  | 		if (scene_surface->primary_output == output) { | ||||||
|  | 			wlr_presentation_surface_sampled_on_output(presentation, | ||||||
|  | 				scene_surface->surface, output); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return wlr_output_commit(output); | 	return wlr_output_commit(output); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue