summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2012-03-05 19:50:08 -0500
committerKristian Høgsberg <krh@bitplanet.net>2012-03-05 19:50:15 -0500
commit7dbf5e2ea744bde56b65ba45b935b77df4a783e1 (patch)
tree71f9b0390e1e774e788625e1ba010e93644d9169
parent7ea10864c2fc7370f5ada88a3fc91ab5f188da00 (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.c65
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;