From bc10638cd97a332468993e982e1a122a16531504 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Wed, 10 Oct 2012 12:49:31 +0300 Subject: [PATCH] compositor, clients: apply wl_surface.frame on commit Apply wl_surface.frame request only on the next wl_surface.commit according to the new protocol. This makes it explicit, which repaint actually triggered the frame callback, since commit schedules a repaint. Otherwise, something causing a repaint before a commit could trigger the frame callback too early. Ensure all demo clients send commit after wl_surface.frame. Note, that GL apps rely on eglSwapBuffers() sending commit. In toytoolkit, it is assumed that window_flush() always does a commit. compositor-wayland assumes renderer->repaint_output does a commit. Signed-off-by: Pekka Paalanen --- clients/simple-egl.c | 4 ++-- clients/simple-shm.c | 2 +- clients/window.c | 16 ++++++++-------- src/compositor-wayland.c | 4 +--- src/compositor.c | 17 +++++++++++++---- src/compositor.h | 3 +++ 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/clients/simple-egl.c b/clients/simple-egl.c index 42c22b0a..af5c7005 100644 --- a/clients/simple-egl.c +++ b/clients/simple-egl.c @@ -410,10 +410,10 @@ redraw(void *data, struct wl_callback *callback, uint32_t time) wl_region_destroy(region); } - eglSwapBuffers(window->display->egl.dpy, window->egl_surface); - window->callback = wl_surface_frame(window->surface); wl_callback_add_listener(window->callback, &frame_listener, window); + + eglSwapBuffers(window->display->egl.dpy, window->egl_surface); } static const struct wl_callback_listener frame_listener = { diff --git a/clients/simple-shm.c b/clients/simple-shm.c index 66b3772d..92286fb8 100644 --- a/clients/simple-shm.c +++ b/clients/simple-shm.c @@ -217,13 +217,13 @@ redraw(void *data, struct wl_callback *callback, uint32_t time) paint_pixels(window->shm_data, 20, window->width, window->height, time); wl_surface_damage(window->surface, 20, 20, window->width - 40, window->height - 40); - wl_surface_commit(window->surface); if (callback) wl_callback_destroy(callback); window->callback = wl_surface_frame(window->surface); wl_callback_add_listener(window->callback, &frame_listener, window); + wl_surface_commit(window->surface); } static const struct wl_callback_listener frame_listener = { diff --git a/clients/window.c b/clients/window.c index 2d0efc50..13363f80 100644 --- a/clients/window.c +++ b/clients/window.c @@ -2670,14 +2670,14 @@ pointer_surface_frame_callback(void *data, struct wl_callback *callback, else i = wl_cursor_frame(cursor, time - input->cursor_anim_start); - input_set_pointer_image_index(input, i); - - if (cursor->image_count == 1) - return; + if (cursor->image_count > 1) { + input->cursor_frame_cb = + wl_surface_frame(input->pointer_surface); + wl_callback_add_listener(input->cursor_frame_cb, + &pointer_surface_listener, input); + } - input->cursor_frame_cb = wl_surface_frame(input->pointer_surface); - wl_callback_add_listener(input->cursor_frame_cb, - &pointer_surface_listener, input); + input_set_pointer_image_index(input, i); } static const struct wl_callback_listener pointer_surface_listener = { @@ -2973,12 +2973,12 @@ idle_redraw(struct task *task, uint32_t events) window_create_surface(window); widget_redraw(window->widget); - window_flush(window); window->redraw_needed = 0; wl_list_init(&window->redraw_task.link); window->frame_cb = wl_surface_frame(window->surface); wl_callback_add_listener(window->frame_cb, &listener, window); + window_flush(window); } void diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index 805137d5..eed9d5c4 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -307,12 +307,10 @@ wayland_output_repaint(struct weston_output *output_base, struct weston_compositor *ec = output->base.compositor; struct wl_callback *callback; - ec->renderer->repaint_output(&output->base, damage); - callback = wl_surface_frame(output->parent.surface); wl_callback_add_listener(callback, &frame_listener, output); - return; + ec->renderer->repaint_output(&output->base, damage); } static void diff --git a/src/compositor.c b/src/compositor.c index eb3e6323..4dd6d277 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -266,6 +266,7 @@ weston_surface_create(struct weston_compositor *compositor) pixman_region32_init(&surface->pending.damage); pixman_region32_init(&surface->pending.opaque); region_init_infinite(&surface->pending.input); + wl_list_init(&surface->pending.frame_callback_list); return surface; } @@ -767,6 +768,10 @@ destroy_surface(struct wl_resource *resource) if (weston_surface_is_mapped(surface)) weston_surface_unmap(surface); + wl_list_for_each_safe(cb, next, + &surface->pending.frame_callback_list, link) + wl_resource_destroy(&cb->resource); + pixman_region32_fini(&surface->pending.input); pixman_region32_fini(&surface->pending.opaque); pixman_region32_fini(&surface->pending.damage); @@ -990,7 +995,6 @@ weston_output_repaint(struct weston_output *output, uint32_t msecs) wl_callback_send_done(&cb->resource, msecs); wl_resource_destroy(&cb->resource); } - wl_list_init(&frame_callback_list); wl_list_for_each_safe(animation, next, &output->animation_list, link) { animation->frame_counter++; @@ -1170,14 +1174,14 @@ surface_frame(struct wl_client *client, struct wl_resource *resource, uint32_t callback) { struct weston_frame_callback *cb; - struct weston_surface *es = resource->data; + struct weston_surface *surface = resource->data; cb = malloc(sizeof *cb); if (cb == NULL) { wl_resource_post_no_memory(resource); return; } - + cb->resource.object.interface = &wl_callback_interface; cb->resource.object.id = callback; cb->resource.destroy = destroy_frame_callback; @@ -1185,7 +1189,7 @@ surface_frame(struct wl_client *client, cb->resource.data = cb; wl_client_add_resource(client, &cb->resource); - wl_list_insert(es->frame_callback_list.prev, &cb->link); + wl_list_insert(surface->pending.frame_callback_list.prev, &cb->link); } static void @@ -1258,6 +1262,11 @@ surface_commit(struct wl_client *client, struct wl_resource *resource) pixman_region32_intersect(&surface->input, &surface->input, &surface->pending.input); + /* wl_surface.frame */ + wl_list_insert_list(&surface->frame_callback_list, + &surface->pending.frame_callback_list); + wl_list_init(&surface->pending.frame_callback_list); + weston_surface_schedule_repaint(surface); } diff --git a/src/compositor.h b/src/compositor.h index d5bb5728..4c61db7f 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -483,6 +483,9 @@ struct weston_surface { /* wl_surface.set_input_region */ pixman_region32_t input; + + /* wl_surface.frame */ + struct wl_list frame_callback_list; } pending; /*