Replace commit/ack/frame protocol with simpler sync and frame callbacks

This commit is contained in:
Kristian Høgsberg 2010-09-03 14:46:38 -04:00
parent 13b8ae4986
commit 9d69f8e796
15 changed files with 257 additions and 188 deletions

View 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

View 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);

View 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);
draw_gears(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);
window_commit(gears->window, 10);
if (gears->resized)
resize_window(gears);
gears->angle = (GLfloat) (timestamp % 8192) * 360 / 8192.0;
draw_gears(gears);
gears->angle = (GLfloat) (time % 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;
}

View 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);
}

View 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

View 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

View 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
@ -933,20 +947,6 @@ window_set_button_handler(struct window *window,
window->button_handler = handler;
}
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)
@ -1022,48 +1022,6 @@ static const struct wl_drm_listener drm_listener = {
drm_handle_authenticated
};
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,
@ -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)
{

View 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
@ -146,6 +146,9 @@ window_copy_surface(struct window *window,
struct rectangle *rectangle,
cairo_surface_t *surface);
void
window_flush(struct window *window);
void
window_set_fullscreen(struct window *window, int fullscreen);
@ -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,
@ -188,10 +188,6 @@ void
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);

View 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

View 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;

View 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>
@ -21,26 +29,21 @@
<event name="range">
<arg name="base" type="uint"/>
</event>
<event name="sync">
<arg name="key" type="uint"/>
</event>
<event name="frame">
<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>
<request name="commit">
<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"/>
</event>
</interface>
<interface name="drm" version="1">

View 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)

View 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,

View 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 *

View 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,