From: Kristian Høgsberg Date: Fri, 3 Sep 2010 18:46:38 +0000 (-0400) Subject: Replace commit/ack/frame protocol with simpler sync and frame callbacks X-Git-Tag: 0.85.0~444 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9d69f8e7963965ec4301364a01d941b3615fa1a1;p=profile%2Fivi%2Fwayland.git Replace commit/ack/frame protocol with simpler sync and frame callbacks --- diff --git a/clients/dnd.c b/clients/dnd.c index df4d8c5..9095672 100644 --- a/clients/dnd.c +++ b/clients/dnd.c @@ -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 diff --git a/clients/flower.c b/clients/flower.c index 54d54f2..3a06bf9 100644 --- a/clients/flower.c +++ b/clients/flower.c @@ -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); diff --git a/clients/gears.c b/clients/gears.c index 0426f20..f8c77ec 100644 --- a/clients/gears.c +++ b/clients/gears.c @@ -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; } diff --git a/clients/image.c b/clients/image.c index fa23520..b359a94 100644 --- a/clients/image.c +++ b/clients/image.c @@ -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); } diff --git a/clients/terminal.c b/clients/terminal.c index 1bb496d..c841ef2 100644 --- a/clients/terminal.c +++ b/clients/terminal.c @@ -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 diff --git a/clients/view.c b/clients/view.c index 0c8ce5a..ace838d 100644 --- a/clients/view.c +++ b/clients/view.c @@ -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 diff --git a/clients/window.c b/clients/window.c index 5a2f247..0aa319d 100644 --- a/clients/window.c +++ b/clients/window.c @@ -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) { diff --git a/clients/window.h b/clients/window.h index 1b4285f..343d536 100644 --- a/clients/window.h +++ b/clients/window.h @@ -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); diff --git a/compositor.c b/compositor.c index 175e5a7..a805f8c 100644 --- a/compositor.c +++ b/compositor.c @@ -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 diff --git a/compositor.h b/compositor.h index 097cdc6..2cbdf8e 100644 --- a/compositor.h +++ b/compositor.h @@ -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; diff --git a/protocol.xml b/protocol.xml index 0f2bd98..9da4b49 100644 --- a/protocol.xml +++ b/protocol.xml @@ -1,6 +1,14 @@ + + + + + + + + @@ -21,28 +29,23 @@ - - - - - - - + - - - - - - - + + + + + + + + diff --git a/wayland-client.c b/wayland-client.c index dd0500f..2d731b0 100644 --- a/wayland-client.c +++ b/wayland-client.c @@ -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) diff --git a/wayland-client.h b/wayland-client.h index 68e5936..4fcb00b 100644 --- a/wayland-client.h +++ b/wayland-client.h @@ -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, diff --git a/wayland-server.c b/wayland-server.c index 1c91353..db8bf74 100644 --- a/wayland-server.c +++ b/wayland-server.c @@ -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 * diff --git a/wayland-server.h b/wayland-server.h index 5bd4b75..bb99cb8 100644 --- a/wayland-server.h +++ b/wayland-server.h @@ -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,