output: fix performance issues with wlr_output_schedule_frame
This commit is contained in:
		
							parent
							
								
									a7cba7d83f
								
							
						
					
					
						commit
						704130cc11
					
				|  | @ -21,9 +21,10 @@ static void surface_frame_callback(void *data, struct wl_callback *cb, | ||||||
| 		uint32_t time) { | 		uint32_t time) { | ||||||
| 	struct wlr_wl_backend_output *output = data; | 	struct wlr_wl_backend_output *output = data; | ||||||
| 	assert(output); | 	assert(output); | ||||||
| 	wlr_output_send_frame(&output->wlr_output); |  | ||||||
| 	wl_callback_destroy(cb); | 	wl_callback_destroy(cb); | ||||||
| 	output->frame_callback = NULL; | 	output->frame_callback = NULL; | ||||||
|  | 
 | ||||||
|  | 	wlr_output_send_frame(&output->wlr_output); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct wl_callback_listener frame_listener = { | static struct wl_callback_listener frame_listener = { | ||||||
|  | @ -50,6 +51,11 @@ static bool wlr_wl_output_swap_buffers(struct wlr_output *wlr_output) { | ||||||
| 	struct wlr_wl_backend_output *output = | 	struct wlr_wl_backend_output *output = | ||||||
| 		(struct wlr_wl_backend_output *)wlr_output; | 		(struct wlr_wl_backend_output *)wlr_output; | ||||||
| 
 | 
 | ||||||
|  | 	if (output->frame_callback != NULL) { | ||||||
|  | 		wlr_log(L_ERROR, "Skipping buffer swap"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	output->frame_callback = wl_surface_frame(output->surface); | 	output->frame_callback = wl_surface_frame(output->surface); | ||||||
| 	wl_callback_add_listener(output->frame_callback, &frame_listener, output); | 	wl_callback_add_listener(output->frame_callback, &frame_listener, output); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -77,6 +77,8 @@ struct wlr_output { | ||||||
| 		struct wl_signal destroy; | 		struct wl_signal destroy; | ||||||
| 	} events; | 	} events; | ||||||
| 
 | 
 | ||||||
|  | 	struct wl_event_source *idle_frame; | ||||||
|  | 
 | ||||||
| 	struct wlr_surface *fullscreen_surface; | 	struct wlr_surface *fullscreen_surface; | ||||||
| 	struct wl_listener fullscreen_surface_commit; | 	struct wl_listener fullscreen_surface_commit; | ||||||
| 	struct wl_listener fullscreen_surface_destroy; | 	struct wl_listener fullscreen_surface_destroy; | ||||||
|  |  | ||||||
|  | @ -273,6 +273,8 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, | ||||||
| 
 | 
 | ||||||
| 	output->display_destroy.notify = handle_display_destroy; | 	output->display_destroy.notify = handle_display_destroy; | ||||||
| 	wl_display_add_destroy_listener(display, &output->display_destroy); | 	wl_display_add_destroy_listener(display, &output->display_destroy); | ||||||
|  | 
 | ||||||
|  | 	output->frame_pending = true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void wlr_output_destroy(struct wlr_output *output) { | void wlr_output_destroy(struct wlr_output *output) { | ||||||
|  | @ -466,6 +468,15 @@ surface_damage_finish: | ||||||
| 
 | 
 | ||||||
| bool wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when, | bool wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when, | ||||||
| 		pixman_region32_t *damage) { | 		pixman_region32_t *damage) { | ||||||
|  | 	if (output->frame_pending) { | ||||||
|  | 		wlr_log(L_ERROR, "Tried to swap buffers when a frame is pending"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	if (output->idle_frame != NULL) { | ||||||
|  | 		wl_event_source_remove(output->idle_frame); | ||||||
|  | 		output->idle_frame = NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	wl_signal_emit(&output->events.swap_buffers, damage); | 	wl_signal_emit(&output->events.swap_buffers, damage); | ||||||
| 
 | 
 | ||||||
| 	int width, height; | 	int width, height; | ||||||
|  | @ -522,18 +533,21 @@ void wlr_output_send_frame(struct wlr_output *output) { | ||||||
| 
 | 
 | ||||||
| static void schedule_frame_handle_idle_timer(void *data) { | static void schedule_frame_handle_idle_timer(void *data) { | ||||||
| 	struct wlr_output *output = data; | 	struct wlr_output *output = data; | ||||||
| 	wlr_output_send_frame(output); | 	output->idle_frame = NULL; | ||||||
|  | 	if (!output->frame_pending) { | ||||||
|  | 		wlr_output_send_frame(output); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void wlr_output_schedule_frame(struct wlr_output *output) { | void wlr_output_schedule_frame(struct wlr_output *output) { | ||||||
| 	if (output->frame_pending) { | 	if (output->frame_pending || output->idle_frame != NULL) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// TODO: ask the backend to send a frame event when appropriate instead
 | 	// TODO: ask the backend to send a frame event when appropriate instead
 | ||||||
| 	struct wl_event_loop *ev = wl_display_get_event_loop(output->display); | 	struct wl_event_loop *ev = wl_display_get_event_loop(output->display); | ||||||
| 	wl_event_loop_add_idle(ev, schedule_frame_handle_idle_timer, output); | 	output->idle_frame = | ||||||
| 	output->frame_pending = true; | 		wl_event_loop_add_idle(ev, schedule_frame_handle_idle_timer, output); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void wlr_output_set_gamma(struct wlr_output *output, | void wlr_output_set_gamma(struct wlr_output *output, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue