diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2012-03-05 19:50:08 -0500 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2012-03-05 19:50:15 -0500 |
commit | 7dbf5e2ea744bde56b65ba45b935b77df4a783e1 (patch) | |
tree | 71f9b0390e1e774e788625e1ba010e93644d9169 | |
parent | 7ea10864c2fc7370f5ada88a3fc91ab5f188da00 (diff) |
compositor: Only process input once per frame
When we're repainting, there's no point in polling for input events.
We just read input events once before each repaint and send out events
as needed. The input events come with an accurate timestamp, so this
doesn't affect the timing information and client should always look at
the event timestamps if they're trying to determine pointer motion
speed or double click speed. If we go idle (stop repainting) we add the
input devices back into the primary main loop and wait for the next event.
This avoids waking up the compositor separately (one or more times per
frame) to handle input events. We also avoid updating cursor position
and other compositor state after the client has rendered its new
frame, reducing lag between what the client renders and the pointer
position.
-rw-r--r-- | src/compositor.c | 65 |
1 files changed, 37 insertions, 28 deletions
diff --git a/src/compositor.c b/src/compositor.c index 62277b9..0e33971 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -973,25 +973,46 @@ weston_output_repaint(struct weston_output *output, int msecs) animation->frame(animation, output, msecs); } -static void -idle_repaint(void *data) +static int +weston_compositor_read_input(int fd, uint32_t mask, void *data) { - struct weston_output *output = data; + struct weston_compositor *compositor = data; - /* An idle repaint may have been cancelled by vt switching away. */ - if (output->repaint_needed) - weston_output_repaint(output, weston_compositor_get_time()); - else - output->repaint_scheduled = 0; + wl_event_loop_dispatch(compositor->input_loop, 0); + + return 1; } WL_EXPORT void weston_output_finish_frame(struct weston_output *output, int msecs) { - if (output->repaint_needed) + struct weston_compositor *compositor = output->compositor; + struct wl_event_loop *loop = + wl_display_get_event_loop(compositor->wl_display); + int fd; + + wl_event_loop_dispatch(compositor->input_loop, 0); + if (output->repaint_needed) { weston_output_repaint(output, msecs); - else - output->repaint_scheduled = 0; + return; + } + + output->repaint_scheduled = 0; + if (compositor->input_loop_source) + return; + + fd = wl_event_loop_get_fd(compositor->input_loop); + compositor->input_loop_source = + wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, + weston_compositor_read_input, compositor); +} + +static void +idle_repaint(void *data) +{ + struct weston_output *output = data; + + weston_output_finish_frame(output, weston_compositor_get_time()); } WL_EXPORT void @@ -1019,6 +1040,11 @@ weston_compositor_schedule_repaint(struct weston_compositor *compositor) wl_event_loop_add_idle(loop, idle_repaint, output); output->repaint_scheduled = 1; } + + if (compositor->input_loop_source) { + wl_event_source_remove(compositor->input_loop_source); + compositor->input_loop_source = NULL; + } } WL_EXPORT void @@ -2268,16 +2294,6 @@ compositor_bind(struct wl_client *client, &compositor_interface, id, compositor); } -static int -weston_compositor_read_input(int fd, uint32_t mask, void *data) -{ - struct weston_compositor *compositor = data; - - wl_event_loop_dispatch(compositor->input_loop, 0); - - return 1; -} - WL_EXPORT int weston_compositor_init(struct weston_compositor *ec, struct wl_display *display) { @@ -2349,13 +2365,6 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display) ec->input_loop = wl_event_loop_create(); - ec->input_loop_source = - wl_event_loop_add_fd(loop, - wl_event_loop_get_fd(ec->input_loop), - WL_EVENT_READABLE, - weston_compositor_read_input, ec); - - weston_compositor_schedule_repaint(ec); return 0; |