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 <[email protected]>
---
 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 2150a41..37c36dc 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 c4daadd..9c46b94 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 b8f4d5a..30fc858 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -2632,14 +2632,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 = {
@@ -2935,12 +2935,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 8ddebf2..d38f8d5 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -306,12 +306,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 eb3e632..4dd6d27 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 d5bb572..4c61db7 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;
 
        /*
-- 
1.7.8.6

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to