Replace commit/ack/frame protocol with simpler sync and frame callbacks
authorKristian Høgsberg <krh@bitplanet.net>
Fri, 3 Sep 2010 18:46:38 +0000 (14:46 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Fri, 3 Sep 2010 18:46:38 +0000 (14:46 -0400)
15 files changed:
clients/dnd.c
clients/flower.c
clients/gears.c
clients/image.c
clients/terminal.c
clients/view.c
clients/window.c
clients/window.h
compositor.c
compositor.h
protocol.xml
wayland-client.c
wayland-client.h
wayland-server.c
wayland-server.h

index df4d8c5..9095672 100644 (file)
@@ -183,8 +183,8 @@ dnd_draw(struct dnd *dnd)
        cairo_destroy(cr);
 
        window_copy_surface(dnd->window, &rectangle, surface);
-       window_commit(dnd->window, dnd->key);
        cairo_surface_destroy(surface);
+       window_flush(dnd->window);
 }
 
 static void
index 54d54f2..3a06bf9 100644 (file)
@@ -98,21 +98,22 @@ draw_stuff(cairo_surface_t *surface, int width, int height)
 }
 
 struct flower {
+       struct display *display;
        struct window *window;
        int x, y, width, height;
        int offset;
 };
 
 static void
-handle_frame(struct window *window,
-            uint32_t frame, uint32_t timestamp, void *data)
+frame_callback(void *data, uint32_t time)
 {
        struct flower *flower = data;
 
        window_move(flower->window, 
-                   flower->x + cos((flower->offset + timestamp) / 400.0) * 400 - flower->width / 2,
-                   flower->y + sin((flower->offset + timestamp) / 320.0) * 300 - flower->height / 2);
-       window_commit(flower->window, 0);
+                   flower->x + cos((flower->offset + time) / 400.0) * 400 - flower->width / 2,
+                   flower->y + sin((flower->offset + time) / 320.0) * 300 - flower->height / 2);
+       wl_display_frame_callback(display_get_display(flower->display),
+                                 frame_callback, flower);
 }
 
 int main(int argc, char *argv[])
@@ -128,6 +129,7 @@ int main(int argc, char *argv[])
        flower.y = 384;
        flower.width = 200;
        flower.height = 200;
+       flower.display = d;
        flower.window = window_create(d, "flower", flower.x, flower.y,
                                      flower.width, flower.height);
 
@@ -145,10 +147,11 @@ int main(int argc, char *argv[])
 
        draw_stuff(s, flower.width, flower.height);
        cairo_surface_flush(s);
+       window_flush(flower.window);
 
        window_set_user_data(flower.window, &flower);
-       window_set_frame_handler(flower.window, handle_frame);
-       window_commit(flower.window, 0);
+       wl_display_frame_callback(display_get_display(d),
+                                 frame_callback, &flower);
 
        display_run(d);
 
index 0426f20..f8c77ec 100644 (file)
@@ -317,31 +317,21 @@ keyboard_focus_handler(struct window *window,
 }
 
 static void
-acknowledge_handler(struct window *window,
-                   uint32_t key, uint32_t frame,
-                   void *data)
+frame_callback(void *data, uint32_t time)
 {
        struct gears *gears = data;
 
-       if (key == 10) {
-               if (gears->resized)
-                       resize_window(gears);
+       window_copy_image(gears->window, &gears->rectangle, gears->image);
 
-               draw_gears(gears);
-       }
-}
+       if (gears->resized)
+               resize_window(gears);
 
-static void
-frame_handler(struct window *window,
-             uint32_t frame, uint32_t timestamp, void *data)
-{
-       struct gears *gears = data;
-
-       window_copy_image(gears->window, &gears->rectangle, gears->image);
+       draw_gears(gears);
 
-       window_commit(gears->window, 10);
+       gears->angle = (GLfloat) (time % 8192) * 360 / 8192.0;
 
-       gears->angle = (GLfloat) (timestamp % 8192) * 360 / 8192.0;
+       wl_display_frame_callback(display_get_display(gears->d),
+                                 frame_callback, gears);
 }
 
 static struct gears *
@@ -417,13 +407,13 @@ gears_create(struct display *display)
 
        resize_window(gears);
        draw_gears(gears);
-       frame_handler(gears->window, 0, 0, gears);
 
        window_set_user_data(gears->window, gears);
        window_set_resize_handler(gears->window, resize_handler);
        window_set_keyboard_focus_handler(gears->window, keyboard_focus_handler);
-       window_set_acknowledge_handler(gears->window, acknowledge_handler);
-       window_set_frame_handler(gears->window, frame_handler);
+
+       wl_display_frame_callback(display_get_display(gears->d),
+                                 frame_callback, gears);
 
        return gears;
 }
index fa23520..b359a94 100644 (file)
@@ -176,7 +176,7 @@ image_draw(struct image *image)
        g_object_unref(pb);
 
        window_copy_surface(image->window, &rectangle, surface);
-       window_commit(image->window, image->key);
+       window_flush(image->window);
        cairo_surface_destroy(surface);
 }
 
index 1bb496d..c841ef2 100644 (file)
@@ -215,7 +215,7 @@ terminal_draw(struct terminal *terminal)
 
        window_draw(terminal->window);
        terminal_draw_contents(terminal);
-       window_commit(terminal->window, 0);
+       window_flush(terminal->window);
 }
 
 static void
index 0c8ce5a..ace838d 100644 (file)
@@ -101,8 +101,7 @@ view_draw(struct view *view)
        poppler_page_render(page, cr);
        cairo_destroy(cr);
        g_object_unref(G_OBJECT(page));
-
-       window_commit(view->window, 0);
+       window_flush(view->window);
 }
 
 static void
index 5a2f247..0aa319d 100644 (file)
@@ -98,8 +98,6 @@ struct window {
        window_key_handler_t key_handler;
        window_button_handler_t button_handler;
        window_keyboard_focus_handler_t keyboard_focus_handler;
-       window_acknowledge_handler_t acknowledge_handler;
-       window_frame_handler_t frame_handler;
        window_motion_handler_t motion_handler;
 
        void *user_data;
@@ -331,6 +329,21 @@ display_get_pointer_surface(struct display *display, int pointer,
        return cairo_surface_reference(surface);
 }
 
+
+static void
+window_attach_surface(struct window *window);
+
+static void
+free_surface(void *data)
+{
+       struct window *window = data;
+
+       cairo_surface_destroy(window->pending_surface);
+       window->pending_surface = NULL;
+       if (window->cairo_surface)
+               window_attach_surface(window);
+}
+
 static void
 window_attach_surface(struct window *window)
 {
@@ -353,17 +366,14 @@ window_attach_surface(struct window *window)
                       window->allocation.width,
                       window->allocation.height);
 
-       wl_compositor_commit(window->display->compositor, 0);
+       wl_display_sync_callback(display->display, free_surface, window);
 }
 
 void
-window_commit(struct window *window, uint32_t key)
+window_flush(struct window *window)
 {
-       if (window->cairo_surface) {
-               window_attach_surface(window);
-       } else {
-               wl_compositor_commit(window->display->compositor, key);
-       }
+       if (window->cairo_surface)
+              window_attach_surface(window);
 }
 
 static void
@@ -848,6 +858,10 @@ window_copy_surface(struct window *window,
 
        cairo_paint (cr);
        cairo_destroy (cr);
+
+       wl_surface_damage(window->surface,
+                         rectangle->x, rectangle->y,
+                         rectangle->width, rectangle->height);
 }
 
 static gboolean
@@ -934,20 +948,6 @@ window_set_button_handler(struct window *window,
 }
 
 void
-window_set_acknowledge_handler(struct window *window,
-                              window_acknowledge_handler_t handler)
-{
-       window->acknowledge_handler = handler;
-}
-
-void
-window_set_frame_handler(struct window *window,
-                        window_frame_handler_t handler)
-{
-       window->frame_handler = handler;
-}
-
-void
 window_set_motion_handler(struct window *window,
                          window_motion_handler_t handler)
 {
@@ -1023,48 +1023,6 @@ static const struct wl_drm_listener drm_listener = {
 };
 
 static void
-display_handle_acknowledge(void *data,
-                          struct wl_compositor *compositor,
-                          uint32_t key, uint32_t frame)
-{
-       struct display *d = data;
-       struct window *window;
-               
-       /* The acknowledge event means that the server processed our
-        * last commit request and we can now safely free the old
-        * window buffer if we resized and render the next frame into
-        * our back buffer.. */
-       wl_list_for_each(window, &d->window_list, link) {
-               cairo_surface_destroy(window->pending_surface);
-               window->pending_surface = NULL;
-               if (window->cairo_surface)
-                       window_attach_surface(window);
-               if (window->acknowledge_handler)
-                       (*window->acknowledge_handler)(window, key, frame, window->user_data);
-       }
-}
-
-static void
-display_handle_frame(void *data,
-                    struct wl_compositor *compositor,
-                    uint32_t frame, uint32_t timestamp)
-{
-       struct display *d = data;
-       struct window *window;
-
-       wl_list_for_each(window, &d->window_list, link) {
-               if (window->frame_handler)
-                       (*window->frame_handler)(window, frame,
-                                                timestamp, window->user_data);
-       }
-}
-
-static const struct wl_compositor_listener compositor_listener = {
-       display_handle_acknowledge,
-       display_handle_frame,
-};
-
-static void
 display_handle_geometry(void *data,
                        struct wl_output *output,
                        int32_t width, int32_t height)
@@ -1111,8 +1069,6 @@ display_handle_global(struct wl_display *display, uint32_t id,
 
        if (strcmp(interface, "compositor") == 0) {
                d->compositor = wl_compositor_create(display, id);
-               wl_compositor_add_listener(d->compositor,
-                                          &compositor_listener, d);
        } else if (strcmp(interface, "output") == 0) {
                d->output = wl_output_create(display, id);
                wl_output_add_listener(d->output, &output_listener, d);
@@ -1290,6 +1246,12 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries)
        return d;
 }
 
+struct wl_display *
+display_get_display(struct display *display)
+{
+       return display->display;
+}
+
 struct wl_compositor *
 display_get_compositor(struct display *display)
 {
index 1b4285f..343d536 100644 (file)
@@ -38,6 +38,9 @@ struct input;
 struct display *
 display_create(int *argc, char **argv[], const GOptionEntry *option_entries);
 
+struct wl_display *
+display_get_display(struct display *display);
+
 struct wl_compositor *
 display_get_compositor(struct display *display);
 
@@ -96,7 +99,6 @@ enum pointer_type {
 typedef void (*window_resize_handler_t)(struct window *window, void *data);
 typedef void (*window_redraw_handler_t)(struct window *window, void *data);
 typedef void (*window_frame_handler_t)(struct window *window, uint32_t frame, uint32_t timestamp, void *data);
-typedef void (*window_acknowledge_handler_t)(struct window *window, uint32_t key, uint32_t frame, void *data);
 typedef void (*window_key_handler_t)(struct window *window, uint32_t key, uint32_t unicode,
                                     uint32_t state, uint32_t modifiers, void *data);
 typedef void (*window_keyboard_focus_handler_t)(struct window *window,
@@ -121,8 +123,6 @@ window_create(struct display *display, const char *title,
 void
 window_draw(struct window *window);
 void
-window_commit(struct window *window, uint32_t key);
-void
 window_get_child_rectangle(struct window *window,
                           struct rectangle *rectangle);
 void
@@ -147,6 +147,9 @@ window_copy_surface(struct window *window,
                    cairo_surface_t *surface);
 
 void
+window_flush(struct window *window);
+
+void
 window_set_fullscreen(struct window *window, int fullscreen);
 
 void
@@ -168,9 +171,6 @@ window_set_resize_handler(struct window *window,
 void
 window_set_frame_handler(struct window *window,
                         window_frame_handler_t handler);
-void
-window_set_acknowledge_handler(struct window *window,
-                              window_acknowledge_handler_t handler);
 
 void
 window_set_key_handler(struct window *window,
@@ -189,10 +189,6 @@ window_set_keyboard_focus_handler(struct window *window,
                                  window_keyboard_focus_handler_t handler);
 
 void
-window_set_acknowledge_handler(struct window *window,
-                              window_acknowledge_handler_t handler);
-
-void
 window_set_frame_handler(struct window *window,
                         window_frame_handler_t handler);
 
index 175e5a7..a805f8c 100644 (file)
@@ -349,12 +349,8 @@ wlsc_surface_update_matrix(struct wlsc_surface *es)
 void
 wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs)
 {
-       wl_display_post_frame(compositor->wl_display,
-                             &compositor->base,
-                             compositor->current_frame, msecs);
-
+       wl_display_post_frame(compositor->wl_display, msecs);
        wl_event_source_timer_update(compositor->timer_source, 5);
-       compositor->current_frame++;
 }
 
 static void
@@ -426,6 +422,7 @@ surface_attach(struct wl_client *client,
        glBindTexture(GL_TEXTURE_2D, es->texture);
        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image);
        es->visual = buffer->visual;
+       wlsc_compositor_schedule_repaint(es->compositor);
 }
 
 static void
@@ -441,6 +438,7 @@ surface_map(struct wl_client *client,
        es->height = height;
 
        wlsc_surface_update_matrix(es);
+       wlsc_compositor_schedule_repaint(es->compositor);
 }
 
 static void
@@ -448,7 +446,9 @@ surface_damage(struct wl_client *client,
               struct wl_surface *surface,
               int32_t x, int32_t y, int32_t width, int32_t height)
 {
-       /* FIXME: This need to take a damage region, of course. */
+       struct wlsc_surface *es = (struct wlsc_surface *) surface;
+
+       wlsc_compositor_schedule_repaint(es->compositor);
 }
 
 const static struct wl_surface_interface surface_interface = {
@@ -640,19 +640,8 @@ compositor_create_surface(struct wl_client *client,
        wl_client_add_resource(client, &surface->base.base);
 }
 
-static void
-compositor_commit(struct wl_client *client,
-                 struct wl_compositor *compositor, uint32_t key)
-{
-       struct wlsc_compositor *ec = (struct wlsc_compositor *) compositor;
-
-       wlsc_compositor_schedule_repaint(ec);
-       wl_client_send_acknowledge(client, compositor, key, ec->current_frame);
-}
-
 const static struct wl_compositor_interface compositor_interface = {
        compositor_create_surface,
-       compositor_commit
 };
 
 static void
index 097cdc6..2cbdf8e 100644 (file)
@@ -154,7 +154,6 @@ struct wlsc_compositor {
        int repaint_needed;
        int repaint_on_timeout;
        struct timespec previous_swap;
-       uint32_t current_frame;
 
        uint32_t focus;
 
index 0f2bd98..9da4b49 100644 (file)
@@ -1,6 +1,14 @@
 <protocol>
 
   <interface name="display" version="1">
+    <request name="sync">
+      <arg name="key" type="uint"/>
+    </request>
+
+    <request name="frame">
+      <arg name="key" type="uint"/>
+    </request>
+
     <event name="invalid_object">
       <arg name="object_id" type="uint"/>
     </event>
     <event name="range">
       <arg name="base" type="uint"/>
     </event>
-  </interface>
-
-  <interface name="compositor" version="1">
-    <request name="create_surface">
-      <arg name="id" type="new_id" interface="surface"/>
-    </request>
 
-    <request name="commit">
+    <event name="sync">
       <arg name="key" type="uint"/>
-    </request>
-
-    <event name="acknowledge">
-      <arg name="key" type="uint"/>
-      <arg name="frame" type="uint"/>
     </event>
 
     <event name="frame">
-      <arg name="frame" type="uint"/>
-      <arg name="timestamp" type="uint"/>
+      <arg name="key" type="uint"/>
+      <arg name="time" type="uint"/>
     </event>
   </interface>
 
+  <interface name="compositor" version="1">
+    <request name="create_surface">
+      <arg name="id" type="new_id" interface="surface"/>
+    </request>
+  </interface>
+
   <interface name="drm" version="1">
     <!-- dri2 auth and create buffer -->
     <request name="authenticate">
index dd0500f..2d731b0 100644 (file)
@@ -59,6 +59,20 @@ struct wl_proxy {
        void *user_data;
 };
 
+struct wl_sync_handler {
+       wl_display_sync_func_t func;
+       uint32_t key;
+       void *data;
+       struct wl_list link;
+};
+
+struct wl_frame_handler {
+       wl_display_frame_func_t func;
+       uint32_t key;
+       void *data;
+       struct wl_list link;
+};
+
 struct wl_display {
        struct wl_proxy proxy;
        struct wl_connection *connection;
@@ -78,6 +92,9 @@ struct wl_display {
 
        wl_display_global_func_t global_handler;
        void *global_handler_data;
+
+       struct wl_list sync_list, frame_list;
+       uint32_t key;
 };
 
 static int
@@ -270,12 +287,49 @@ display_handle_range(void *data,
        display->next_range = range;
 }
 
+static void
+display_handle_sync(void *data, struct wl_display *display, uint32_t key)
+{
+       struct wl_sync_handler *handler;
+
+       handler = container_of(display->sync_list.next,
+                              struct wl_sync_handler, link);
+       if (handler->key != key) {
+               fprintf(stderr, "unsolicited sync event, client gone?\n");
+               return;
+       }
+
+       wl_list_remove(&handler->link);
+       handler->func(handler->data);
+       free(handler);
+}
+
+static void
+display_handle_frame(void *data,
+                    struct wl_display *display, uint32_t key, uint32_t time)
+{
+       struct wl_frame_handler *handler;
+
+       handler = container_of(display->frame_list. next,
+                              struct wl_frame_handler, link);
+       if (handler->key != key) {
+               fprintf(stderr, "unsolicited frame event, client gone?\n");
+               return;
+       }
+
+       wl_list_remove(&handler->link);
+       handler->func(handler->data, time);
+       free(handler);
+}
+
 static const struct wl_display_listener display_listener = {
        display_handle_invalid_object,
        display_handle_invalid_method,
        display_handle_no_memory,
        display_handle_global,
-       display_handle_range
+       display_handle_range,
+       display_handle_sync,
+       display_handle_frame
 };
 
 WL_EXPORT struct wl_display *
@@ -315,6 +369,9 @@ wl_display_create(const char *name, size_t name_size)
        display->proxy.display = display;
        wl_list_init(&display->proxy.listener_list);
 
+       wl_list_init(&display->sync_list);
+       wl_list_init(&display->frame_list);
+
        display->listener.implementation = (void(**)(void)) &display_listener;
        wl_list_insert(display->proxy.listener_list.prev, &display->listener.link);
 
@@ -345,6 +402,46 @@ wl_display_get_fd(struct wl_display *display,
        return display->fd;
 }
 
+WL_EXPORT int
+wl_display_sync_callback(struct wl_display *display,
+                        wl_display_sync_func_t func, void *data)
+{
+       struct wl_sync_handler *handler;
+
+       handler = malloc(sizeof *handler);
+       if (handler == NULL)
+               return -1;
+
+       handler->func = func;
+       handler->key = display->key++;
+       handler->data = data;
+
+       wl_list_insert(display->sync_list.prev, &handler->link);
+       wl_display_sync(display, handler->key);
+
+       return 0;
+}
+
+WL_EXPORT int
+wl_display_frame_callback(struct wl_display *display,
+                         wl_display_frame_func_t func, void *data)
+{
+       struct wl_frame_handler *handler;
+
+       handler = malloc(sizeof *handler);
+       if (handler == NULL)
+               return -1;
+
+       handler->func = func;
+       handler->key = display->key++;
+       handler->data = data;
+
+       wl_list_insert(display->frame_list.prev, &handler->link);
+       wl_display_frame(display, handler->key);
+
+       return 0;
+}
+
 static void
 handle_event(struct wl_display *display,
             uint32_t id, uint32_t opcode, uint32_t size)
index 68e5936..4fcb00b 100644 (file)
@@ -34,6 +34,8 @@ extern "C" {
 #define WL_DISPLAY_WRITABLE 0x02
 
 typedef int (*wl_display_update_func_t)(uint32_t mask, void *data);
+typedef void (*wl_display_sync_func_t)(void *data);
+typedef void (*wl_display_frame_func_t)(void *data, uint32_t time);
 
 struct wl_display *wl_display_create(const char *name, size_t name_size);
 void wl_display_destroy(struct wl_display *display);
@@ -41,6 +43,10 @@ int wl_display_get_fd(struct wl_display *display,
                      wl_display_update_func_t update, void *data);
 uint32_t wl_display_allocate_id(struct wl_display *display);
 void wl_display_iterate(struct wl_display *display, uint32_t mask);
+int wl_display_sync_callback(struct wl_display *display,
+                            wl_display_sync_func_t func, void *data);
+int wl_display_frame_callback(struct wl_display *display,
+                             wl_display_frame_func_t func, void *data);
 
 struct wl_global_listener;
 typedef void (*wl_display_global_func_t)(struct wl_display *display,
index 1c91353..db8bf74 100644 (file)
@@ -43,7 +43,6 @@ struct wl_client {
        struct wl_event_source *source;
        struct wl_display *display;
        struct wl_list resource_list;
-       struct wl_list link;
        uint32_t id_count;
 };
 
@@ -52,13 +51,20 @@ struct wl_display {
        struct wl_event_loop *loop;
        struct wl_hash_table *objects;
 
-       struct wl_list pending_frame_list;
+       struct wl_list frame_list;
        uint32_t client_id_range;
        uint32_t id;
 
        struct wl_list global_list;
 };
 
+struct wl_frame_listener {
+       struct wl_resource resource;
+       struct wl_client *client;
+       uint32_t key;
+       struct wl_list link;
+};
+
 struct wl_global {
        struct wl_object *object;
        wl_client_connect_func_t func;
@@ -200,7 +206,6 @@ wl_client_create(struct wl_display *display, int fd)
                wl_connection_create(fd, wl_client_connection_update, client);
 
        wl_list_init(&client->resource_list);
-       wl_list_init(&client->link);
 
        wl_display_post_range(display, client);
 
@@ -257,7 +262,8 @@ wl_resource_destroy(struct wl_resource *resource, struct wl_client *client)
        struct wl_display *display = client->display;
 
        wl_list_remove(&resource->link);
-       wl_hash_table_remove(display->objects, resource->base.id);
+       if (resource->base.id > 0)
+               wl_hash_table_remove(display->objects, resource->base.id);
        resource->destroy(resource, client);
 }
 
@@ -268,30 +274,14 @@ wl_client_destroy(struct wl_client *client)
 
        printf("disconnect from client %p\n", client);
 
-       wl_list_remove(&client->link);
-
-       wl_list_for_each_safe(resource, tmp, &client->resource_list, link) {
-               wl_list_remove(&resource->link);
-               resource->destroy(resource, client);
-       }
+       wl_list_for_each_safe(resource, tmp, &client->resource_list, link)
+               wl_resource_destroy(resource, client);
 
        wl_event_source_remove(client->source);
        wl_connection_destroy(client->connection);
        free(client);
 }
 
-WL_EXPORT void
-wl_client_send_acknowledge(struct wl_client *client,
-                          struct wl_compositor *compositor,
-                          uint32_t key, uint32_t frame)
-{
-       wl_list_remove(&client->link);
-       wl_list_insert(client->display->pending_frame_list.prev,
-                      &client->link);
-       wl_client_post_event(client, &compositor->base,
-                            WL_COMPOSITOR_ACKNOWLEDGE, key, frame);
-}
-
 WL_EXPORT int
 wl_display_set_compositor(struct wl_display *display,
                          struct wl_compositor *compositor,
@@ -307,6 +297,51 @@ wl_display_set_compositor(struct wl_display *display,
        return 0;
 }
 
+static void
+display_sync(struct wl_client *client,
+              struct wl_display *display, uint32_t key)
+{
+       wl_client_post_event(client, &display->base, WL_DISPLAY_SYNC, key);
+}
+
+static void
+destroy_frame_listener(struct wl_resource *resource, struct wl_client *client)
+{
+       struct wl_frame_listener *listener =
+               container_of(resource, struct wl_frame_listener, resource);
+
+       wl_list_remove(&listener->link);
+       free(listener);
+}
+
+static void
+display_frame(struct wl_client *client,
+             struct wl_display *display, uint32_t key)
+{
+       struct wl_frame_listener *listener;
+
+       listener = malloc(sizeof *listener);
+       if (listener == NULL) {
+               wl_client_post_no_memory(client);
+               return;
+       }
+
+       /* The listener is a resource so we destroy it when the client
+        * goes away. */
+       listener->resource.destroy = destroy_frame_listener;
+       listener->resource.base.id = 0;
+       listener->client = client;
+       listener->key = key;
+       wl_list_insert(client->resource_list.prev, &listener->resource.link);
+       wl_list_insert(display->frame_list.prev, &listener->link);
+}
+
+struct wl_display_interface display_interface = {
+       display_sync,
+       display_frame
+};
+
+
 WL_EXPORT struct wl_display *
 wl_display_create(void)
 {
@@ -328,22 +363,22 @@ wl_display_create(void)
                return NULL;
        }
 
-       wl_list_init(&display->pending_frame_list);
+       wl_list_init(&display->frame_list);
        wl_list_init(&display->global_list);
 
        display->client_id_range = 256; /* Gah, arbitrary... */
 
        display->id = 1;
        display->base.interface = &wl_display_interface;
-       display->base.implementation = NULL;
+       display->base.implementation = (void (**)(void)) &display_interface;
        wl_display_add_object(display, &display->base);
        if (wl_display_add_global(display, &display->base, NULL)) {
                wl_event_loop_destroy(display->loop);
                free(display);
                return NULL;
-       }               
+       }
 
-       return display;         
+       return display;
 }
 
 WL_EXPORT void
@@ -388,18 +423,15 @@ wl_surface_post_event(struct wl_surface *surface,
 }
 
 WL_EXPORT void
-wl_display_post_frame(struct wl_display *display,
-                     struct wl_compositor *compositor,
-                     uint32_t frame, uint32_t msecs)
+wl_display_post_frame(struct wl_display *display, uint32_t time)
 {
-       struct wl_client *client;
+       struct wl_frame_listener *listener, *next;
 
-       wl_list_for_each(client, &display->pending_frame_list, link)
-               wl_client_post_event(client, &compositor->base,
-                                    WL_COMPOSITOR_FRAME, frame, msecs);
-
-       wl_list_remove(&display->pending_frame_list);
-       wl_list_init(&display->pending_frame_list);
+       wl_list_for_each_safe(listener, next, &display->frame_list, link) {
+               wl_client_post_event(listener->client, &display->base,
+                                    WL_DISPLAY_FRAME, listener->key, time);
+               wl_resource_destroy(&listener->resource, listener->client);
+       }
 }
 
 WL_EXPORT struct wl_event_loop *
index 5bd4b75..bb99cb8 100644 (file)
@@ -159,14 +159,7 @@ wl_display_set_compositor(struct wl_display *display,
                          const struct wl_compositor_interface *implementation);
 
 void
-wl_client_send_acknowledge(struct wl_client *client,
-                          struct wl_compositor *compositor,
-                          uint32_t key, uint32_t frame);
-
-void
-wl_display_post_frame(struct wl_display *display,
-                     struct wl_compositor *compositor,
-                     uint32_t frame, uint32_t msecs);
+wl_display_post_frame(struct wl_display *display, uint32_t msecs);
 
 void
 wl_client_add_resource(struct wl_client *client,