Redesign the compositor / server interface.
authorKristian Høgsberg <krh@redhat.com>
Tue, 16 Dec 2008 01:35:24 +0000 (20:35 -0500)
committerKristian Høgsberg <krh@redhat.com>
Tue, 16 Dec 2008 01:35:24 +0000 (20:35 -0500)
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.

egl-compositor.c
flower.c
gears.c
terminal.c
wayland-client.c
wayland-client.h
wayland.c
wayland.h
window.c

index e5fe679..2cf9ec1 100644 (file)
@@ -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);
index 9938297..21f10b1 100644 (file)
--- 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 (file)
--- 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);
index 8087938..baee19c 100644 (file)
@@ -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);
index 26eebce..c51d9bd 100644 (file)
@@ -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
index 52b8613..54889d4 100644 (file)
@@ -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,
index 647e859..6b1d98b 100644 (file)
--- 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 *
index cc19ab3..1af2aaa 100644 (file)
--- 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
index bf83854..c765fe5 100644 (file)
--- 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;