From: Kristian Høgsberg Date: Tue, 16 Dec 2008 01:35:24 +0000 (-0500) Subject: Redesign the compositor / server interface. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d2412e2c2ea463189550d5f7a5d95a7aab13a502;p=platform%2Fupstream%2Fweston.git Redesign the compositor / server interface. This lets the compositor directly provide the implementation of the RMI objects for the surface object and a new compositor object. We avoid the manual forwarding of requests into the compositor and the clumsy compositor interface struct. --- diff --git a/egl-compositor.c b/egl-compositor.c index e5fe679..2cf9ec1 100644 --- a/egl-compositor.c +++ b/egl-compositor.c @@ -89,10 +89,11 @@ struct egl_compositor { }; struct egl_surface { + struct wl_surface base; + struct egl_compositor *compositor; GLuint texture; struct wl_map map; EGLSurface surface; - struct wl_surface *wl_surface; int width, height; struct wl_list link; }; @@ -102,6 +103,10 @@ struct screenshooter { struct egl_compositor *ec; }; +struct screenshooter_interface { + void (*shoot)(struct wl_client *client, struct screenshooter *shooter); +}; + static void screenshooter_shoot(struct wl_client *client, struct screenshooter *shooter) { @@ -120,7 +125,7 @@ screenshooter_shoot(struct wl_client *client, struct screenshooter *shooter) } static const struct wl_method screenshooter_methods[] = { - { "shoot", screenshooter_shoot, "", NULL } + { "shoot", "", NULL } }; static const struct wl_interface screenshooter_interface = { @@ -129,6 +134,10 @@ static const struct wl_interface screenshooter_interface = { screenshooter_methods, }; +struct screenshooter_interface screenshooter_implementation = { + screenshooter_shoot +}; + static struct screenshooter * screenshooter_create(struct egl_compositor *ec) { @@ -139,6 +148,7 @@ screenshooter_create(struct egl_compositor *ec) return NULL; shooter->base.interface = &screenshooter_interface; + shooter->base.implementation = (void(**)(void)) &screenshooter_implementation; shooter->ec = ec; return shooter; @@ -498,7 +508,8 @@ repaint(void *data) clock_gettime(CLOCK_MONOTONIC, &ts); msecs = ts.tv_sec * 1000 + ts.tv_nsec / (1000 * 1000); - wl_display_post_frame(ec->wl_display, ec->current_frame, msecs); + wl_display_post_frame(ec->wl_display, &ec->base, + ec->current_frame, msecs); ec->current_frame++; wl_event_source_timer_update(ec->timer_source, 10); @@ -518,36 +529,13 @@ schedule_repaint(struct egl_compositor *ec) wl_event_loop_add_idle(loop, repaint, ec); } } - -static void -notify_surface_create(struct wl_compositor *compositor, - struct wl_surface *surface) -{ - struct egl_compositor *ec = (struct egl_compositor *) compositor; - struct egl_surface *es; - - es = malloc(sizeof *es); - if (es == NULL) - return; - - es->surface = EGL_NO_SURFACE; - es->wl_surface = surface; - wl_surface_set_data(surface, es); - wl_list_insert(ec->surface_list.prev, &es->link); - - glGenTextures(1, &es->texture); -} static void -notify_surface_destroy(struct wl_compositor *compositor, - struct wl_surface *surface) +surface_destroy(struct wl_client *client, + struct wl_surface *surface) { - struct egl_compositor *ec = (struct egl_compositor *) compositor; - struct egl_surface *es; - - es = wl_surface_get_data(surface); - if (es == NULL) - return; + struct egl_surface *es = (struct egl_surface *) surface; + struct egl_compositor *ec = es->compositor; wl_list_remove(&es->link); egl_surface_destroy(es, ec); @@ -556,16 +544,12 @@ notify_surface_destroy(struct wl_compositor *compositor, } static void -notify_surface_attach(struct wl_compositor *compositor, - struct wl_surface *surface, uint32_t name, - uint32_t width, uint32_t height, uint32_t stride) +surface_attach(struct wl_client *client, + struct wl_surface *surface, uint32_t name, + uint32_t width, uint32_t height, uint32_t stride) { - struct egl_compositor *ec = (struct egl_compositor *) compositor; - struct egl_surface *es; - - es = wl_surface_get_data(surface); - if (es == NULL) - return; + struct egl_surface *es = (struct egl_surface *) surface; + struct egl_compositor *ec = es->compositor; if (es->surface != EGL_NO_SURFACE) eglDestroySurface(ec->display, es->surface); @@ -584,30 +568,28 @@ notify_surface_attach(struct wl_compositor *compositor, } static void -notify_surface_map(struct wl_compositor *compositor, - struct wl_surface *surface, struct wl_map *map) +surface_map(struct wl_client *client, + struct wl_surface *surface, + int32_t x, int32_t y, int32_t width, int32_t height) { - struct egl_surface *es; + struct egl_surface *es = (struct egl_surface *) surface; - es = wl_surface_get_data(surface); - if (es == NULL) - return; - - es->map = *map; + es->map.x = x; + es->map.y = y; + es->map.width = width; + es->map.height = height; } static void -notify_surface_copy(struct wl_compositor *compositor, - struct wl_surface *surface, - int32_t dst_x, int32_t dst_y, - uint32_t name, uint32_t stride, - int32_t x, int32_t y, int32_t width, int32_t height) +surface_copy(struct wl_client *client, + struct wl_surface *surface, + int32_t dst_x, int32_t dst_y, + uint32_t name, uint32_t stride, + int32_t x, int32_t y, int32_t width, int32_t height) { - struct egl_compositor *ec = (struct egl_compositor *) compositor; + struct egl_surface *es = (struct egl_surface *) surface; + struct egl_compositor *ec = es->compositor; EGLSurface src; - struct egl_surface *es; - - es = wl_surface_get_data(surface); /* FIXME: glCopyPixels should work, but then we'll have to * call eglMakeCurrent to set up the src and dest surfaces @@ -623,23 +605,56 @@ notify_surface_copy(struct wl_compositor *compositor, } static void -notify_surface_damage(struct wl_compositor *compositor, - struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) +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. */ } -static uint32_t -notify_commit(struct wl_compositor *compositor) +const static struct wl_surface_interface surface_interface = { + surface_destroy, + surface_attach, + surface_map, + surface_copy, + surface_damage +}; + +static void +compositor_create_surface(struct wl_client *client, + struct wl_compositor *compositor, uint32_t id) { struct egl_compositor *ec = (struct egl_compositor *) compositor; + struct egl_surface *es; - schedule_repaint(ec); + es = malloc(sizeof *es); + if (es == NULL) + /* FIXME: Send OOM event. */ + return; - return ec->current_frame; + es->compositor = ec; + es->surface = EGL_NO_SURFACE; + wl_list_insert(ec->surface_list.prev, &es->link); + glGenTextures(1, &es->texture); + wl_client_add_surface(client, &es->base, + &surface_interface, id); +} + +static void +compositor_commit(struct wl_client *client, + struct wl_compositor *compositor, uint32_t key) +{ + struct egl_compositor *ec = (struct egl_compositor *) 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 struct egl_surface * pick_surface(struct egl_input_device *device) { @@ -677,7 +692,7 @@ notify_motion(struct egl_input_device *device, int x, int y) if (es) { sx = (x - es->map.x) * es->width / es->map.width; sy = (y - es->map.y) * es->height / es->map.height; - wl_surface_post_event(es->wl_surface, &device->base, + wl_surface_post_event(&es->base, &device->base, WL_INPUT_MOTION, x, y, sx, sy); } @@ -715,7 +730,7 @@ notify_button(struct egl_input_device *device, sy = (device->y - es->map.y) * es->height / es->map.height; /* FIXME: Swallow click on raise? */ - wl_surface_post_event(es->wl_surface, &device->base, + wl_surface_post_event(&es->base, &device->base, WL_INPUT_BUTTON, button, state, device->x, device->y, sx, sy); @@ -737,29 +752,16 @@ notify_key(struct egl_input_device *device, schedule_repaint(ec); } else if (!wl_list_empty(&ec->surface_list)) { if (device->focus_surface != NULL) - wl_surface_post_event(device->focus_surface->wl_surface, + wl_surface_post_event(&device->focus_surface->base, &device->base, WL_INPUT_KEY, key, state); } } -static const struct wl_compositor_interface interface = { - notify_surface_create, - notify_surface_destroy, - notify_surface_attach, - notify_surface_map, - notify_surface_copy, - notify_surface_damage, - notify_commit, -}; - struct evdev_input_device * evdev_input_device_create(struct egl_input_device *device, struct wl_display *display, const char *path); -void -egl_device_get_position(struct egl_input_device *device, int32_t *x, int32_t *y); - static void create_input_device(struct egl_compositor *ec, const char *glob) { @@ -984,7 +986,6 @@ egl_compositor_create(struct wl_display *display) if (ec == NULL) return NULL; - ec->base.interface = &interface; ec->wl_display = display; ec->display = eglCreateDisplayNative(gem_device, "i965"); @@ -1027,6 +1028,8 @@ egl_compositor_create(struct wl_display *display) glOrtho(0, ec->width, ec->height, 0, 0, 1000.0); glMatrixMode(GL_MODELVIEW); + wl_display_set_compositor(display, &ec->base, &compositor_interface); + wl_list_init(&ec->input_device_list); for (i = 0; option_input_devices[i]; i++) create_input_device(ec, option_input_devices[i]); @@ -1086,8 +1089,6 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - wl_display_set_compositor(display, &ec->base); - if (wl_display_add_socket(display, socket_name, sizeof socket_name)) { fprintf(stderr, "failed to add socket: %m\n"); exit(EXIT_FAILURE); diff --git a/flower.c b/flower.c index 9938297..21f10b1 100644 --- a/flower.c +++ b/flower.c @@ -104,7 +104,7 @@ draw_stuff(int width, int height) } struct flower { - struct wl_display *display; + struct wl_compositor *compositor; struct wl_surface *surface; int i; int x, y, width, height; @@ -118,7 +118,7 @@ move_flower(struct flower *flower) flower->y + sin(flower->i / 27.0) * 300 - flower->height / 2, flower->width, flower->height); flower->i++; - wl_display_commit(flower->display, 0); + wl_compositor_commit(flower->compositor, 0); } static void @@ -126,7 +126,7 @@ event_handler(struct wl_display *display, uint32_t object, uint32_t opcode, uint32_t size, uint32_t *p, void *data) { - if (object == 1 && opcode == 4) + if (object == 2 && opcode == 1) move_flower(data); } @@ -158,12 +158,12 @@ int main(int argc, char *argv[]) source = wl_glib_source_new(display); g_source_attach(source, NULL); - flower.display = display; + flower.compositor = wl_display_get_compositor(display); flower.x = 512; flower.y = 384; flower.width = 200; flower.height = 200; - flower.surface = wl_display_create_surface(display); + flower.surface = wl_compositor_create_surface(flower.compositor); clock_gettime(CLOCK_MONOTONIC, &ts); srandom(ts.tv_nsec); diff --git a/gears.c b/gears.c index 6149e12..4bf5475 100644 --- a/gears.c +++ b/gears.c @@ -47,6 +47,7 @@ struct gears { struct window *window; struct wl_display *wl_display; + struct wl_compositor *compositor; struct rectangle rectangle; EGLDisplay display; @@ -320,7 +321,7 @@ frame_handler(struct window *window, uint32_t frame, uint32_t timestamp, void *d &gears->rectangle, gears->buffer->name, gears->buffer->stride); - wl_display_commit(gears->wl_display, 0); + wl_compositor_commit(gears->compositor, 0); gears->angle += 1; } @@ -379,6 +380,8 @@ gears_create(struct wl_display *display, int fd) glEnable(GL_DEPTH_TEST); glClearColor(0, 0, 0, 0.92); + gears->compositor = wl_display_get_compositor(display); + draw_gears(gears); frame_handler(gears->window, 0, 0, gears); diff --git a/terminal.c b/terminal.c index 8087938..baee19c 100644 --- a/terminal.c +++ b/terminal.c @@ -53,6 +53,7 @@ static const char socket_name[] = "\0wayland"; struct terminal { struct window *window; struct wl_display *display; + struct wl_compositor *compositor; int redraw_scheduled, redraw_pending; char *data; int width, height, start, row, column; @@ -194,7 +195,7 @@ terminal_draw(struct terminal *terminal) window_draw(terminal->window); terminal_draw_contents(terminal); - wl_display_commit(terminal->display, 0); + wl_compositor_commit(terminal->compositor, 0); } static gboolean @@ -531,6 +532,7 @@ terminal_create(struct wl_display *display, int fd) terminal->redraw_scheduled = 1; terminal->margin = 5; + terminal->compositor = wl_display_get_compositor(display); window_set_resize_handler(terminal->window, resize_handler, terminal); window_set_acknowledge_handler(terminal->window, acknowledge_handler, terminal); window_set_key_handler(terminal->window, key_handler, terminal); diff --git a/wayland-client.c b/wayland-client.c index 26eebce..c51d9bd 100644 --- a/wayland-client.c +++ b/wayland-client.c @@ -64,6 +64,10 @@ struct wl_display { void *event_handler_data; }; +struct wl_compositor { + struct wl_proxy proxy; +}; + struct wl_surface { struct wl_proxy proxy; }; @@ -249,11 +253,28 @@ wl_display_write(struct wl_display *display, const void *data, size_t count) wl_connection_write(display->connection, data, count); } -#define WL_DISPLAY_CREATE_SURFACE 0 -#define WL_DISPLAY_COMMIT 1 +WL_EXPORT struct wl_compositor * +wl_display_get_compositor(struct wl_display *display) +{ + struct wl_compositor *compositor; + uint32_t id; + + id = wl_display_get_object_id(display, "compositor"); + if (id == 0) + return NULL; + + compositor = malloc(sizeof *compositor); + compositor->proxy.display = display; + compositor->proxy.id = id; + + return compositor; +} + +#define WL_COMPOSITOR_CREATE_SURFACE 0 +#define WL_COMPOSITOR_COMMIT 1 WL_EXPORT struct wl_surface * -wl_display_create_surface(struct wl_display *display) +wl_compositor_create_surface(struct wl_compositor *compositor) { struct wl_surface *surface; uint32_t request[3]; @@ -262,26 +283,28 @@ wl_display_create_surface(struct wl_display *display) if (surface == NULL) return NULL; - surface->proxy.id = wl_display_allocate_id(display); - surface->proxy.display = display; + surface->proxy.id = wl_display_allocate_id(compositor->proxy.display); + surface->proxy.display = compositor->proxy.display; - request[0] = display->proxy.id; - request[1] = WL_DISPLAY_CREATE_SURFACE | ((sizeof request) << 16); + request[0] = compositor->proxy.id; + request[1] = WL_COMPOSITOR_CREATE_SURFACE | ((sizeof request) << 16); request[2] = surface->proxy.id; - wl_connection_write(display->connection, request, sizeof request); + wl_connection_write(compositor->proxy.display->connection, + request, sizeof request); return surface; } WL_EXPORT void -wl_display_commit(struct wl_display *display, uint32_t key) +wl_compositor_commit(struct wl_compositor *compositor, uint32_t key) { uint32_t request[3]; - request[0] = display->proxy.id; - request[1] = WL_DISPLAY_COMMIT | ((sizeof request) << 16); + request[0] = compositor->proxy.id; + request[1] = WL_COMPOSITOR_COMMIT | ((sizeof request) << 16); request[2] = key; - wl_connection_write(display->connection, request, sizeof request); + wl_connection_write(compositor->proxy.display->connection, + request, sizeof request); } #define WL_SURFACE_DESTROY 0 diff --git a/wayland-client.h b/wayland-client.h index 52b8613..54889d4 100644 --- a/wayland-client.h +++ b/wayland-client.h @@ -56,10 +56,13 @@ void wl_display_set_event_handler(struct wl_display *display, wl_display_event_func_t handler, void *data); +struct wl_compositor * +wl_display_get_compositor(struct wl_display *display); + struct wl_surface * -wl_display_create_surface(struct wl_display *display); +wl_compositor_create_surface(struct wl_compositor *compositor); void -wl_display_commit(struct wl_display *display, uint32_t key); +wl_compositor_commit(struct wl_compositor *compositor, uint32_t key); void wl_surface_destroy(struct wl_surface *surface); void wl_surface_attach(struct wl_surface *surface, diff --git a/wayland.c b/wayland.c index 647e859..6b1d98b 100644 --- a/wayland.c +++ b/wayland.c @@ -43,7 +43,6 @@ struct wl_client { struct wl_display *display; struct wl_list object_list; struct wl_list link; - uint32_t pending_frame; }; struct wl_display { @@ -51,160 +50,18 @@ struct wl_display { struct wl_event_loop *loop; struct wl_hash *objects; - struct wl_object *pointer; - - struct wl_compositor *compositor; - struct wl_compositor_interface *compositor_interface; - - struct wl_list surface_list; - struct wl_list client_list; + struct wl_list pending_frame_list; uint32_t client_id_range; uint32_t id; struct wl_list global_list; }; -struct wl_surface { - struct wl_object base; - - struct wl_client *client; - /* provided by client */ - int width, height; - int buffer; - int stride; - - struct wl_map map; - struct wl_list link; - - /* how to convert buffer contents to pixels in screen format; - * yuv->rgb, indexed->rgb, svg->rgb, but mostly just rgb->rgb. */ - - /* how to transform/render rectangular contents to polygons. */ - - void *compositor_data; -}; - struct wl_object_ref { struct wl_object *object; struct wl_list link; }; -static void -wl_surface_destroy(struct wl_client *client, - struct wl_surface *surface) -{ - const struct wl_compositor_interface *interface; - - interface = client->display->compositor->interface; - interface->notify_surface_destroy(client->display->compositor, - surface); - wl_list_remove(&surface->link); -} - -static void -wl_surface_attach(struct wl_client *client, - struct wl_surface *surface, uint32_t name, - uint32_t width, uint32_t height, uint32_t stride) -{ - const struct wl_compositor_interface *interface; - - interface = client->display->compositor->interface; - interface->notify_surface_attach(client->display->compositor, - surface, name, width, height, stride); -} - -static void -wl_surface_map(struct wl_client *client, struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - const struct wl_compositor_interface *interface; - - /* FIXME: This needs to take a tri-mesh argument... - count - * and a list of tris. 0 tris means unmap. */ - - surface->map.x = x; - surface->map.y = y; - surface->map.width = width; - surface->map.height = height; - - interface = client->display->compositor->interface; - interface->notify_surface_map(client->display->compositor, - surface, &surface->map); -} - -static void -wl_surface_copy(struct wl_client *client, struct wl_surface *surface, - int32_t dst_x, int32_t dst_y, uint32_t name, uint32_t stride, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - const struct wl_compositor_interface *interface; - - interface = client->display->compositor->interface; - interface->notify_surface_copy(client->display->compositor, - surface, dst_x, dst_y, - name, stride, x, y, width, height); -} - -static void -wl_surface_damage(struct wl_client *client, struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - const struct wl_compositor_interface *interface; - - interface = client->display->compositor->interface; - interface->notify_surface_damage(client->display->compositor, - surface, x, y, width, height); -} - -static const struct wl_method surface_methods[] = { - { "destroy", wl_surface_destroy, "" }, - { "attach", wl_surface_attach, "uuuu" }, - { "map", wl_surface_map, "iiii" }, - { "copy", wl_surface_copy, "iiuuiiii" }, - { "damage", wl_surface_damage, "iiii" } -}; - -static const struct wl_interface surface_interface = { - "surface", 1, - ARRAY_LENGTH(surface_methods), - surface_methods, -}; - -static struct wl_surface * -wl_surface_create(struct wl_display *display, - struct wl_client *client, uint32_t id) -{ - struct wl_surface *surface; - const struct wl_compositor_interface *interface; - - surface = malloc(sizeof *surface); - if (surface == NULL) - return NULL; - - surface->base.id = id; - surface->base.interface = &surface_interface; - surface->client = client; - - wl_list_insert(display->surface_list.prev, &surface->link); - - interface = display->compositor->interface; - interface->notify_surface_create(display->compositor, surface); - - return surface; -} - -WL_EXPORT void -wl_surface_set_data(struct wl_surface *surface, void *data) -{ - surface->compositor_data = data; -} - -WL_EXPORT void * -wl_surface_get_data(struct wl_surface *surface) -{ - return surface->compositor_data; -} - void wl_client_destroy(struct wl_client *client); @@ -264,8 +121,9 @@ wl_client_marshal(struct wl_client *client, struct wl_object *sender, static void wl_client_demarshal(struct wl_client *client, struct wl_object *target, - const struct wl_method *method, size_t size) + uint32_t opcode, size_t size) { + const struct wl_method *method; ffi_type *types[20]; ffi_cif cif; uint32_t *p, result; @@ -279,7 +137,9 @@ wl_client_demarshal(struct wl_client *client, struct wl_object *target, void *args[20]; struct wl_object *object; uint32_t data[64]; + void (*func)(void); + method = &target->interface->methods[opcode]; count = strlen(method->signature) + 2; if (count > ARRAY_LENGTH(types)) { printf("too many args (%d)\n", count); @@ -341,22 +201,20 @@ wl_client_demarshal(struct wl_client *client, struct wl_object *target, args[i] = &values[i]; } + func = target->implementation[opcode]; ffi_prep_cif(&cif, FFI_DEFAULT_ABI, count, &ffi_type_uint32, types); - ffi_call(&cif, FFI_FN(method->func), &result, args); + ffi_call(&cif, func, &result, args); } #define WL_DISPLAY_INVALID_OBJECT 0 #define WL_DISPLAY_INVALID_METHOD 1 #define WL_DISPLAY_NO_MEMORY 2 -#define WL_DISPLAY_ACKNOWLEDGE 3 -#define WL_DISPLAY_FRAME 4 static void wl_client_connection_data(int fd, uint32_t mask, void *data) { struct wl_client *client = data; struct wl_connection *connection = client->connection; - const struct wl_method *method; struct wl_object *object; uint32_t p[2], opcode, size; uint32_t cmask = 0; @@ -397,8 +255,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) continue; } - method = &object->interface->methods[opcode]; - wl_client_demarshal(client, object, method, size); + wl_client_demarshal(client, object, opcode, size); wl_connection_consume(connection, size); len -= size; } @@ -455,6 +312,7 @@ wl_client_create(struct wl_display *display, int fd) wl_client_connection_update, client); wl_list_init(&client->object_list); + wl_list_init(&client->link); wl_connection_write(client->connection, &display->client_id_range, @@ -474,11 +332,19 @@ wl_client_create(struct wl_display *display, int fd) struct wl_object_ref, link); } - wl_list_insert(display->client_list.prev, &client->link); - return client; } +static void +wl_object_destroy(struct wl_object *object) +{ + const struct wl_surface_interface *interface = + (const struct wl_surface_interface *) object->implementation; + + /* FIXME: Need generic object destructor. */ + interface->destroy(NULL, (struct wl_surface *) object); +} + void wl_client_destroy(struct wl_client *client) { @@ -492,7 +358,7 @@ wl_client_destroy(struct wl_client *client) ref = container_of(client->object_list.next, struct wl_object_ref, link); wl_list_remove(&ref->link); - wl_surface_destroy(client, (struct wl_surface *) ref->object); + wl_object_destroy(ref->object); free(ref); } @@ -501,14 +367,33 @@ wl_client_destroy(struct wl_client *client) free(client); } -static int -wl_display_create_surface(struct wl_client *client, - struct wl_display *display, uint32_t id) +static const struct wl_method surface_methods[] = { + { "destroy", "" }, + { "attach", "uuuu" }, + { "map", "iiii" }, + { "copy", "iiuuiiii" }, + { "damage", "iiii" } +}; + +static const struct wl_interface surface_interface = { + "surface", 1, + ARRAY_LENGTH(surface_methods), + surface_methods, +}; + +WL_EXPORT int +wl_client_add_surface(struct wl_client *client, + struct wl_surface *surface, + const struct wl_surface_interface *implementation, + uint32_t id) { - struct wl_surface *surface; + struct wl_display *display = client->display; struct wl_object_ref *ref; - surface = wl_surface_create(display, client, id); + surface->base.id = id; + surface->base.interface = &surface_interface; + surface->base.implementation = (void (**)(void)) implementation; + surface->client = client; ref = malloc(sizeof *ref); if (ref == NULL) { @@ -524,39 +409,61 @@ wl_display_create_surface(struct wl_client *client, return 0; } -static int -wl_display_commit(struct wl_client *client, - struct wl_display *display, uint32_t key) +#define WL_COMPOSITOR_ACKNOWLEDGE 0 +#define WL_COMPOSITOR_FRAME 1 + +WL_EXPORT void +wl_client_send_acknowledge(struct wl_client *client, + struct wl_compositor *compositor, + uint32_t key, uint32_t frame) { - const struct wl_compositor_interface *interface; - uint32_t frame; + wl_list_remove(&client->link); + wl_list_insert(client->display->pending_frame_list.prev, + &client->link); + wl_client_marshal(client, &compositor->base, + WL_COMPOSITOR_ACKNOWLEDGE, key, frame); +} + +static const struct wl_method compositor_methods[] = { + { "create_surface", "n" }, + { "commit", "u" } +}; + +static const struct wl_event compositor_events[] = { + { "acknowledge", "uu" }, + { "frame", "uu" } +}; + +static const struct wl_interface compositor_interface = { + "compositor", 1, + ARRAY_LENGTH(compositor_methods), compositor_methods, + ARRAY_LENGTH(compositor_events), compositor_events, +}; - client->pending_frame = 1; +WL_EXPORT int +wl_display_set_compositor(struct wl_display *display, + struct wl_compositor *compositor, + const struct wl_compositor_interface *implementation) +{ + compositor->base.interface = &compositor_interface; + compositor->base.implementation = (void (**)(void)) implementation; - interface = display->compositor->interface; - frame = interface->notify_commit(display->compositor); - wl_client_marshal(client, &display->base, - WL_DISPLAY_ACKNOWLEDGE, key, frame); + wl_display_add_object(display, &compositor->base); + if (wl_display_add_global(display, &compositor->base)) + return -1; return 0; } -static const struct wl_method display_methods[] = { - { "create_surface", wl_display_create_surface, "n" }, - { "commit", wl_display_commit, "u" } -}; - static const struct wl_event display_events[] = { { "invalid_object", "u" }, { "invalid_method", "uu" }, { "no_memory", "" }, - { "acknowledge", "uu" }, - { "frame", "uu" } }; static const struct wl_interface display_interface = { "display", 1, - ARRAY_LENGTH(display_methods), display_methods, + 0, NULL, ARRAY_LENGTH(display_events), display_events, }; @@ -581,14 +488,14 @@ wl_display_create(void) return NULL; } - wl_list_init(&display->surface_list); - wl_list_init(&display->client_list); + wl_list_init(&display->pending_frame_list); wl_list_init(&display->global_list); display->client_id_range = 256; /* Gah, arbitrary... */ display->id = 1; display->base.interface = &display_interface; + display->base.implementation = NULL; wl_display_add_object(display, &display->base); if (wl_display_add_global(display, &display->base)) { wl_event_loop_destroy(display->loop); @@ -636,9 +543,6 @@ wl_surface_post_event(struct wl_surface *surface, struct wl_input_device { struct wl_object base; struct wl_display *display; - uint32_t button_state[16]; - uint32_t button_count; - int32_t x, y; }; static const struct wl_method input_device_methods[] = { @@ -666,29 +570,23 @@ wl_input_device_get_interface(void) WL_EXPORT void wl_display_post_frame(struct wl_display *display, + struct wl_compositor *compositor, uint32_t frame, uint32_t msecs) { struct wl_client *client; - client = container_of(display->client_list.next, + client = container_of(display->pending_frame_list.next, struct wl_client, link); - while (&client->link != &display->client_list) { - if (client->pending_frame) { - wl_client_marshal(client, &display->base, - WL_DISPLAY_FRAME, frame, msecs); - client->pending_frame = 0; - } + while (&client->link != &display->pending_frame_list) { + wl_client_marshal(client, &compositor->base, + WL_COMPOSITOR_FRAME, frame, msecs); client = container_of(client->link.next, struct wl_client, link); } -} -WL_EXPORT void -wl_display_set_compositor(struct wl_display *display, - struct wl_compositor *compositor) -{ - display->compositor = compositor; + wl_list_remove(&display->pending_frame_list); + wl_list_init(&display->pending_frame_list); } WL_EXPORT struct wl_event_loop * diff --git a/wayland.h b/wayland.h index cc19ab3..1af2aaa 100644 --- a/wayland.h +++ b/wayland.h @@ -73,7 +73,6 @@ struct wl_argument { struct wl_method { const char *name; - void *func; const char *signature; const void **types; }; @@ -94,10 +93,10 @@ struct wl_interface { struct wl_object { const struct wl_interface *interface; + void (**implementation)(void); uint32_t id; }; -struct wl_surface; struct wl_display; struct wl_input_device; @@ -105,9 +104,6 @@ struct wl_map { int32_t x, y, width, height; }; -void wl_surface_set_data(struct wl_surface *surface, void *data); -void *wl_surface_get_data(struct wl_surface *surface); - struct wl_display *wl_display_create(void); struct wl_event_loop *wl_display_get_event_loop(struct wl_display *display); int wl_display_add_socket(struct wl_display *display, const char *name, size_t name_size); @@ -121,50 +117,66 @@ wl_display_add_global(struct wl_display *display, struct wl_object *object); const struct wl_interface * wl_input_device_get_interface(void); -void -wl_display_post_frame(struct wl_display *display, - uint32_t frame, uint32_t msecs); - #define WL_INPUT_MOTION 0 #define WL_INPUT_BUTTON 1 #define WL_INPUT_KEY 2 +struct wl_compositor { + struct wl_object base; +}; + +struct wl_surface { + struct wl_object base; + struct wl_client *client; +}; + +struct wl_compositor_interface { + void (*create_surface)(struct wl_client *client, + struct wl_compositor *compositor, uint32_t id); + void (*commit)(struct wl_client *client, + struct wl_compositor *compositor, uint32_t key); +}; + +struct wl_surface_interface { + void (*destroy)(struct wl_client *client, + struct wl_surface *surface); + void (*attach)(struct wl_client *client, + struct wl_surface *surface, uint32_t name, + uint32_t width, uint32_t height, uint32_t stride); + void (*map)(struct wl_client *client, + struct wl_surface *surface, + int32_t x, int32_t y, int32_t width, int32_t height); + void (*copy)(struct wl_client *client, struct wl_surface *surface, + int32_t dst_x, int32_t dst_y, uint32_t name, uint32_t stride, + int32_t x, int32_t y, int32_t width, int32_t height); + void (*damage)(struct wl_client *client, struct wl_surface *surface, + int32_t x, int32_t y, int32_t width, int32_t height); +}; + void wl_surface_post_event(struct wl_surface *surface, struct wl_object *sender, uint32_t event, ...); -struct wl_compositor { - const struct wl_compositor_interface *interface; -}; +int +wl_display_set_compositor(struct wl_display *display, + struct wl_compositor *compositor, + const struct wl_compositor_interface *implementation); -struct wl_compositor_interface { - void (*notify_surface_create)(struct wl_compositor *compositor, - struct wl_surface *surface); - void (*notify_surface_destroy)(struct wl_compositor *compositor, - struct wl_surface *surface); - void (*notify_surface_attach)(struct wl_compositor *compositor, - struct wl_surface *surface, - uint32_t name, - uint32_t width, uint32_t height, - uint32_t stride); - void (*notify_surface_map)(struct wl_compositor *compositor, - struct wl_surface *surface, - struct wl_map *map); - void (*notify_surface_copy)(struct wl_compositor *compositor, - struct wl_surface *surface, - int32_t dst_x, int32_t dst_y, - uint32_t name, uint32_t stride, - int32_t x, int32_t y, - int32_t width, int32_t height); - void (*notify_surface_damage)(struct wl_compositor *compositor, - struct wl_surface *surface, - int32_t x, int32_t y, - int32_t width, int32_t height); - uint32_t (*notify_commit)(struct wl_compositor *compositor); -}; +int +wl_client_add_surface(struct wl_client *client, + struct wl_surface *surface, + const struct wl_surface_interface *implementation, + uint32_t id); + +void +wl_client_send_acknowledge(struct wl_client *client, + struct wl_compositor *compositor, + uint32_t key, uint32_t frame); -void wl_display_set_compositor(struct wl_display *display, - struct wl_compositor *compositor); +void +wl_display_post_frame(struct wl_display *display, + struct wl_compositor *compositor, + uint32_t frame, uint32_t msecs); #endif diff --git a/window.c b/window.c index bf83854..c765fe5 100644 --- a/window.c +++ b/window.c @@ -41,6 +41,7 @@ struct window { struct wl_display *display; + struct wl_compositor *compositor; struct wl_surface *surface; const char *title; int x, y, width, height; @@ -196,9 +197,9 @@ event_handler(struct wl_display *display, int location; int grip_size = 16; - /* FIXME: Object ID 1 is the display, for anything else we + /* FIXME: Object ID 2 is the compositor, for anything else we * assume it's an input device. */ - if (object == 1 && opcode == 3) { + if (object == 2 && opcode == 0) { uint32_t key = p[0]; /* Ignore acknowledge events for window move requests. */ @@ -218,7 +219,7 @@ event_handler(struct wl_display *display, (*window->acknowledge_handler)(window, key, window->user_data); - } else if (object == 1 && opcode == 4) { + } else if (object == 2 && opcode == 1) { /* The frame event means that the previous frame was * composited, and we can now send the request to copy * the frame we've rendered in the mean time into the @@ -244,7 +245,7 @@ event_handler(struct wl_display *display, window->y - window->margin, window->width + 2 * window->margin, window->height + 2 * window->margin); - wl_display_commit(window->display, 1); + wl_compositor_commit(window->compositor, 1); break; case WINDOW_RESIZING_LOWER_RIGHT: if (window->grab_device != object) @@ -387,7 +388,8 @@ window_create(struct wl_display *display, int fd, memset(window, 0, sizeof *window); window->display = display; window->title = strdup(title); - window->surface = wl_display_create_surface(display); + window->compositor = wl_display_get_compositor(display); + window->surface = wl_compositor_create_surface(window->compositor); window->x = x; window->y = y; window->minimum_width = 100;