Introduce 'buffer' object for attaching, image cahce and cursor images
authorKristian Høgsberg <krh@bitplanet.net>
Mon, 9 Aug 2010 18:43:33 +0000 (14:43 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Mon, 9 Aug 2010 18:43:33 +0000 (14:43 -0400)
The buffer object is created by a 'drm' object, which encapsulates the
buffer sharing and authentication mechanism.  Once the buffer is created
it can be attached to a surface.

12 files changed:
Makefile
clients/window.c
compositor-drm.c
compositor-x11.c
compositor.c
compositor.h
protocol.xml
wayland-client.c
wayland-client.h
wayland-util.h
wayland.c
wayland.h

index cf449be..3de68cb 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -49,7 +49,8 @@ compositor :                                  \
        compositor-drm.o                        \
        compositor-x11.o                        \
        screenshooter.o                         \
-       cairo-util.o
+       cairo-util.o                            \
+       drm.o
 
 compositor : CFLAGS += $(COMPOSITOR_CFLAGS)
 compositor : LDLIBS += ./libwayland-server.so $(COMPOSITOR_LIBS) -rdynamic -lrt -lEGL -lm
index b2c4f03..864a5e4 100644 (file)
@@ -53,6 +53,7 @@ struct display {
        struct wl_display *display;
        struct wl_compositor *compositor;
        struct wl_shell *shell;
+       struct wl_drm *drm;
        struct wl_output *output;
        struct rectangle screen_allocation;
        EGLDisplay dpy;
@@ -178,6 +179,8 @@ static void
 window_attach_surface(struct window *window)
 {
        struct wl_visual *visual;
+       struct display *display = window->display;
+       struct wl_buffer *buffer;
        struct surface_data *data;
        EGLint name, stride;
 
@@ -192,13 +195,16 @@ window_attach_surface(struct window *window)
        eglExportDRMImageMESA(window->display->dpy,
                              data->image, &name, NULL, &stride);
 
-       visual = wl_display_get_premultiplied_argb_visual(window->display->display);
-       wl_surface_attach(window->surface,
-                         name,
-                         window->allocation.width,
-                         window->allocation.height,
-                         stride,
-                         visual);
+       visual = wl_display_get_premultiplied_argb_visual(display->display);
+       buffer = wl_drm_create_buffer(display->drm,
+                                     name,
+                                     window->allocation.width,
+                                     window->allocation.height,
+                                     stride,
+                                     visual);
+
+       wl_surface_attach(window->surface, buffer);
+       wl_buffer_destroy(buffer);
 
        wl_surface_map(window->surface,
                       window->allocation.x,
@@ -679,15 +685,22 @@ window_create(struct display *display, const char *title,
 }
 
 static void
-display_handle_device(void *data,
-                     struct wl_compositor *compositor,
-                     const char *device)
+drm_handle_device(void *data, struct wl_drm *drm, const char *device)
 {
        struct display *d = data;
 
        d->device_name = strdup(device);
 }
 
+static void drm_handle_authenticated(void *data, struct wl_drm *drm)
+{
+}
+
+static const struct wl_drm_listener drm_listener = {
+       drm_handle_device,
+       drm_handle_authenticated
+};
+
 static void
 display_handle_acknowledge(void *data,
                           struct wl_compositor *compositor,
@@ -726,7 +739,6 @@ display_handle_frame(void *data,
 }
 
 static const struct wl_compositor_listener compositor_listener = {
-       display_handle_device,
        display_handle_acknowledge,
        display_handle_frame,
 };
@@ -785,6 +797,9 @@ display_handle_global(struct wl_display *display,
        } else if (wl_object_implements(object, "shell", 1)) {
                d->shell = (struct wl_shell *) object;
                wl_shell_add_listener(d->shell, &shell_listener, d);
+       } else if (wl_object_implements(object, "drm", 1)) {
+               d->drm = (struct wl_drm *) object;
+               wl_drm_add_listener(d->drm, &drm_listener, d);
        }
 }
 
index b893fc4..6d156bb 100644 (file)
@@ -41,7 +41,6 @@ struct drm_compositor {
 
        struct udev *udev;
        struct wl_event_source *drm_source;
-       int drm_fd;
 
        struct wl_event_source *term_signal_source;
 
@@ -272,7 +271,7 @@ drm_compositor_present(struct wlsc_compositor *ec)
                                          GL_RENDERBUFFER,
                                          output->rbo[output->current]);
 
-               drmModePageFlip(c->drm_fd, output->crtc_id,
+               drmModePageFlip(c->base.drm.fd, output->crtc_id,
                                output->fb_id[output->current ^ 1],
                                DRM_MODE_PAGE_FLIP_EVENT, output);
        }       
@@ -305,22 +304,25 @@ static int
 init_egl(struct drm_compositor *ec, struct udev_device *device)
 {
        EGLint major, minor;
-       const char *extensions;
+       const char *extensions, *filename;
+       int fd;
        static const EGLint context_attribs[] = {
                EGL_CONTEXT_CLIENT_VERSION, 2,
                EGL_NONE
        };
 
-       ec->base.base.device = strdup(udev_device_get_devnode(device));
-       ec->drm_fd = open(ec->base.base.device, O_RDWR);
-       if (ec->drm_fd < 0) {
+       filename = udev_device_get_devnode(device);
+       fd = open(filename, O_RDWR);
+       if (fd < 0) {
                /* Probably permissions error */
                fprintf(stderr, "couldn't open %s, skipping\n",
                        udev_device_get_devnode(device));
                return -1;
        }
 
-       ec->base.display = eglGetDRMDisplayMESA(ec->drm_fd);
+       wlsc_drm_init(&ec->base, fd, filename);
+
+       ec->base.display = eglGetDRMDisplayMESA(ec->base.drm.fd);
        if (ec->base.display == NULL) {
                fprintf(stderr, "failed to create display\n");
                return -1;
@@ -390,7 +392,7 @@ create_output_for_connector(struct drm_compositor *ec,
        else
                mode = &builtin_1024x768;
 
-       encoder = drmModeGetEncoder(ec->drm_fd, connector->encoders[0]);
+       encoder = drmModeGetEncoder(ec->base.drm.fd, connector->encoders[0]);
        if (encoder == NULL) {
                fprintf(stderr, "No encoder for connector.\n");
                return -1;
@@ -428,7 +430,7 @@ create_output_for_connector(struct drm_compositor *ec,
                eglExportDRMImageMESA(ec->base.display, output->image[i],
                                      NULL, &handle, &stride);
 
-               ret = drmModeAddFB(ec->drm_fd,
+               ret = drmModeAddFB(ec->base.drm.fd,
                                   output->base.width, output->base.height,
                                   32, 32, stride, handle, &output->fb_id[i]);
                if (ret) {
@@ -442,7 +444,7 @@ create_output_for_connector(struct drm_compositor *ec,
                                  GL_COLOR_ATTACHMENT0,
                                  GL_RENDERBUFFER,
                                  output->rbo[output->current]);
-       ret = drmModeSetCrtc(ec->drm_fd, output->crtc_id,
+       ret = drmModeSetCrtc(ec->base.drm.fd, output->crtc_id,
                             output->fb_id[output->current ^ 1], 0, 0,
                             &output->connector_id, 1, &output->mode);
        if (ret) {
@@ -462,14 +464,14 @@ create_outputs(struct drm_compositor *ec)
        drmModeRes *resources;
        int i;
 
-       resources = drmModeGetResources(ec->drm_fd);
+       resources = drmModeGetResources(ec->base.drm.fd);
        if (!resources) {
                fprintf(stderr, "drmModeGetResources failed\n");
                return -1;
        }
 
        for (i = 0; i < resources->count_connectors; i++) {
-               connector = drmModeGetConnector(ec->drm_fd, resources->connectors[i]);
+               connector = drmModeGetConnector(ec->base.drm.fd, resources->connectors[i]);
                if (connector == NULL)
                        continue;
 
@@ -498,7 +500,7 @@ static void on_enter_vt(int signal_number, void *data)
        struct drm_output *output;
        int ret;
 
-       ret = drmSetMaster(ec->drm_fd);
+       ret = drmSetMaster(ec->base.drm.fd);
        if (ret) {
                fprintf(stderr, "failed to set drm master\n");
                kill(0, SIGTERM);
@@ -511,7 +513,7 @@ static void on_enter_vt(int signal_number, void *data)
        ec->vt_active = 1;
 
        wl_list_for_each(output, &ec->base.output_list, base.link) {
-               ret = drmModeSetCrtc(ec->drm_fd, output->crtc_id,
+               ret = drmModeSetCrtc(ec->base.drm.fd, output->crtc_id,
                                     output->fb_id[output->current ^ 1], 0, 0,
                                     &output->connector_id, 1, &output->mode);
                if (ret)
@@ -526,7 +528,7 @@ static void on_leave_vt(int signal_number, void *data)
        struct drm_compositor *ec = data;
        int ret;
 
-       ret = drmDropMaster(ec->drm_fd);
+       ret = drmDropMaster(ec->base.drm.fd);
        if (ret) {
                fprintf(stderr, "failed to drop drm master\n");
                kill(0, SIGTERM);
@@ -644,6 +646,7 @@ drm_compositor_create(struct wl_display *display)
                return NULL;
        }
 
+       ec->base.wl_display = display;
        if (init_egl(ec, device) < 0) {
                fprintf(stderr, "failed to initialize egl\n");
                return NULL;
@@ -662,7 +665,7 @@ drm_compositor_create(struct wl_display *display)
 
        loop = wl_display_get_event_loop(ec->base.wl_display);
        ec->drm_source =
-               wl_event_loop_add_fd(loop, ec->drm_fd,
+               wl_event_loop_add_fd(loop, ec->base.drm.fd,
                                     WL_EVENT_READABLE, on_drm_input, ec);
        setup_tty(ec, loop);
        ec->base.present = drm_compositor_present;
index 9c4f845..27bf328 100644 (file)
@@ -50,7 +50,6 @@ struct x11_compositor {
        xcb_cursor_t             null_cursor;
        int                      dri2_major;
        int                      dri2_minor;
-       int                      drm_fd;
        struct wl_event_source  *xcb_source;
        struct {
                xcb_atom_t               wm_protocols;
@@ -104,6 +103,8 @@ dri2_connect(struct x11_compositor *c)
        xcb_dri2_connect_reply_t *connect;
        xcb_dri2_connect_cookie_t connect_cookie;
        xcb_generic_error_t *error;
+       char path[256];
+       int fd;
 
        xcb_prefetch_extension_data (c->conn, &xcb_xfixes_id);
        xcb_prefetch_extension_data (c->conn, &xcb_dri2_id);
@@ -152,17 +153,19 @@ dri2_connect(struct x11_compositor *c)
                return -1;
        }
 
-       c->base.base.device =
-               strndup(xcb_dri2_connect_device_name (connect),
-                       xcb_dri2_connect_device_name_length (connect));
-                  
-       if (c->base.base.device == NULL) {
-               free(connect);
+       snprintf(path, sizeof path, "%.*s",
+                xcb_dri2_connect_device_name_length (connect),
+                xcb_dri2_connect_device_name (connect));
+       free(connect);
+
+       fd = open(path, O_RDWR);
+       if (fd < 0) {
+               fprintf(stderr,
+                       "DRI2: could not open %s (%s)", path, strerror(errno));
                return -1;
        }
-       free(connect);
 
-       return 0;
+       return wlsc_drm_init(&c->base, fd, path);
 }
 
 static int
@@ -172,7 +175,7 @@ dri2_authenticate(struct x11_compositor *c)
        xcb_dri2_authenticate_cookie_t authenticate_cookie;
        drm_magic_t magic;
 
-       if (drmGetMagic(c->drm_fd, &magic)) {
+       if (drmGetMagic(c->base.drm.fd, &magic)) {
                fprintf(stderr, "DRI2: failed to get drm magic");
                return -1;
        }
@@ -207,18 +210,10 @@ x11_compositor_init_egl(struct x11_compositor *c)
        if (dri2_connect(c) < 0)
                return -1;
 
-       c->drm_fd = open(c->base.base.device, O_RDWR);
-       if (c->drm_fd == -1) {
-               fprintf(stderr,
-                       "DRI2: could not open %s (%s)", c->base.base.device,
-                       strerror(errno));
-               return -1;
-       }
-
        if (dri2_authenticate(c) < 0)
                return -1;
 
-       c->base.display = eglGetDRMDisplayMESA(c->drm_fd);
+       c->base.display = eglGetDRMDisplayMESA(c->base.drm.fd);
        if (c->base.display == NULL) {
                fprintf(stderr, "failed to create display\n");
                return -1;
@@ -641,6 +636,7 @@ x11_compositor_create(struct wl_display *display)
 
        x11_compositor_get_resources(c);
 
+       c->base.wl_display = display;
        x11_compositor_init_egl(c);
 
        /* Can't init base class until we have a current egl context */
index 6d7a627..8f50aef 100644 (file)
 #include <time.h>
 #include <linux/input.h>
 
-#define GL_GLEXT_PROTOTYPES
-#define EGL_EGLEXT_PROTOTYPES
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
 #include "wayland.h"
 #include "wayland-server-protocol.h"
 #include "cairo-util.h"
@@ -180,14 +173,15 @@ wlsc_surface_create_from_cairo_surface(struct wlsc_compositor *ec,
 }
 
 static void
-wlsc_surface_destroy(struct wlsc_surface *surface,
-                    struct wlsc_compositor *compositor)
+destroy_surface(struct wl_resource *resource, struct wl_client *client)
 {
+       struct wlsc_surface *surface =
+               container_of(resource, struct wlsc_surface, base.base);
+       struct wlsc_compositor *compositor = surface->compositor;
        struct wlsc_listener *l;
 
        wl_list_remove(&surface->link);
        glDeleteTextures(1, &surface->texture);
-       wl_client_remove_surface(surface->base.client, &surface->base);
 
        wl_list_for_each(l, &compositor->surface_destroy_listener_list, link)
                l->func(l, surface);
@@ -427,73 +421,26 @@ surface_destroy(struct wl_client *client,
                struct wl_surface *surface)
 {
        struct wlsc_surface *es = (struct wlsc_surface *) surface;
-       struct wlsc_compositor *ec = es->compositor;
 
-       wlsc_surface_destroy(es, ec);
+       wl_resource_destroy(&surface->base, client);
 
-       wlsc_compositor_schedule_repaint(ec);
+       wlsc_compositor_schedule_repaint(es->compositor);
 }
 
 static void
 surface_attach(struct wl_client *client,
-              struct wl_surface *surface, uint32_t name,
-              int32_t width, int32_t height, uint32_t stride,
-              struct wl_visual *visual)
+              struct wl_surface *surface, struct wl_buffer *buffer_base)
 {
        struct wlsc_surface *es = (struct wlsc_surface *) surface;
-       struct wlsc_compositor *ec = es->compositor;
-       EGLImageKHR image;
-       EGLint attribs[] = {
-               EGL_WIDTH,              0,
-               EGL_HEIGHT,             0,
-               EGL_IMAGE_STRIDE_MESA,  0,
-               EGL_IMAGE_FORMAT_MESA,  EGL_IMAGE_FORMAT_ARGB8888_MESA,
-               EGL_NONE
-       };
-
-       attribs[1] = width;
-       attribs[3] = height;
-       attribs[5] = stride / 4;
-
-       image = eglCreateImageKHR(ec->display, ec->context,
-                                 EGL_DRM_IMAGE_MESA,
-                                 (EGLClientBuffer) name, attribs);
-       if (image == NULL) {
-               /* FIXME: Define a real exception event instead of
-                * abusing this one */
-               wl_client_post_event(client, ec->wl_display,
-                                    WL_DISPLAY_INVALID_OBJECT, 0);
-               fprintf(stderr, "failed to create image for name %d\n", name);
-               return;
-       }
-
-       if (visual == &ec->argb_visual)
-               es->visual = &ec->argb_visual;
-       else if (visual == &ec->premultiplied_argb_visual)
-               es->visual = &ec->premultiplied_argb_visual;
-       else if (visual == &ec->rgb_visual)
-               es->visual = &ec->rgb_visual;
-       else {
-               /* FIXME: Define a real exception event instead of
-                * abusing this one */
-               wl_client_post_event(client, ec->display,
-                                    WL_DISPLAY_INVALID_OBJECT, 0);
-               fprintf(stderr, "invalid visual in surface_attach\n");
-               return;
-       }
+       struct wlsc_buffer *buffer = (struct wlsc_buffer *) buffer_base;
 
        glBindTexture(GL_TEXTURE_2D, es->texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-       if (es->image)
-               eglDestroyImageKHR(ec->display, es->image);
-
-       es->image = image;
-
-       glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, es->image);
+       glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image);
+       es->visual = buffer->visual;
 }
 
 static void
@@ -577,13 +524,17 @@ compositor_create_surface(struct wl_client *client,
        struct wlsc_surface *surface;
 
        surface = malloc(sizeof *surface);
-       if (surface == NULL)
-               /* FIXME: Send OOM event. */
+       if (surface == NULL) {
+               wl_client_post_event(client,
+                                    (struct wl_object *) ec->wl_display,
+                                    WL_DISPLAY_NO_MEMORY, 0);
                return;
+       }
 
        wlsc_surface_init(surface, ec, NULL, 0, 0, 0, 0);
 
        wl_list_insert(ec->surface_list.prev, &surface->link);
+       surface->base.base.destroy = destroy_surface;
        wl_client_add_surface(client, &surface->base,
                              &surface_interface, id);
 }
@@ -921,6 +872,7 @@ wlsc_input_device_init(struct wlsc_input_device *device,
        device->base.implementation = NULL;
        wl_display_add_object(ec->wl_display, &device->base);
        wl_display_add_global(ec->wl_display, &device->base, NULL);
+
        device->x = 100;
        device->y = 100;
        device->ec = ec;
index f1ffbd9..fe9779e 100644 (file)
 #include "wayland.h"
 #include "wayland-util.h"
 
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
@@ -93,10 +97,23 @@ struct wlsc_input_device {
        struct wlsc_listener listener;
 };
 
+struct wlsc_drm {
+       struct wl_object base;
+       int fd;
+       char *filename;
+};
+
+struct wlsc_buffer {
+       struct wl_buffer base;
+       EGLImageKHR image;
+       struct wl_visual *visual;
+};
+
 struct wlsc_compositor {
        struct wl_compositor base;
        struct wl_visual argb_visual, premultiplied_argb_visual, rgb_visual;
 
+       struct wlsc_drm drm;
        EGLDisplay display;
        EGLContext context;
        GLuint fbo, vbo;
@@ -124,6 +141,7 @@ struct wlsc_compositor {
 
        uint32_t focus;
 
+       void (*authenticate)(struct wlsc_compositor *c, uint32_t id);
        void (*present)(struct wlsc_compositor *c);
 };
 
@@ -138,13 +156,12 @@ struct wlsc_vector {
 struct wlsc_surface {
        struct wl_surface base;
        struct wlsc_compositor *compositor;
-       struct wl_visual *visual;
        GLuint texture;
-       EGLImageKHR image;
        int32_t x, y, width, height;
        struct wl_list link;
        struct wlsc_matrix matrix;
        struct wlsc_matrix matrix_inv;
+       struct wl_visual *visual;
 };
 
 void
@@ -170,6 +187,8 @@ wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
 void
 wlsc_input_device_init(struct wlsc_input_device *device,
                       struct wlsc_compositor *ec);
+int
+wlsc_drm_init(struct wlsc_compositor *ec, int fd, const char *filename);
 
 struct wlsc_compositor *
 x11_compositor_create(struct wl_display *display);
index 50a3480..63927be 100644 (file)
       <arg name="key" type="uint"/>
     </request>
 
-    <event name="device">
-      <arg name="name" type="string"/>
-    </event>
-
     <event name="acknowledge">
       <arg name="key" type="uint"/>
       <arg name="frame" type="uint"/>
     </event>
   </interface>
 
+  <interface name="drm" version="1">
+    <!-- dri2 auth and create buffer -->
+    <request name="authenticate">
+      <arg name="id" type="uint"/>
+    </request>
+
+    <request name="create_buffer">
+      <arg name="id" type="new_id"/>
+      <arg name="name" type="uint"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="stride" type="uint"/>
+      <arg name="visual" type="visual"/>
+    </request>
+
+    <event name="device">
+      <arg name="name" type="string"/>
+    </event>
+
+    <event name="authenticated"/>
+  </interface>
+
+  <interface name="buffer" version="1">
+    <request name="destroy"/>
+  </interface>
+
   <interface name="shell" version="1">
     <request name="move">
       <arg name="surface" type="surface"/>
     <request name="destroy"/>
 
     <request name="attach">
-      <arg name="name" type="uint"/>
-      <arg name="width" type="int"/>
-      <arg name="height" type="int"/>
-      <arg name="stride" type="uint"/>
-      <arg name="visual" type="visual"/>
+      <arg name="buffer" type="buffer"/>
     </request>
 
     <request name="map">
index b55511e..8fcc809 100644 (file)
@@ -87,6 +87,14 @@ struct wl_shell {
        struct wl_proxy proxy;
 };
 
+struct wl_drm {
+       struct wl_proxy proxy;
+};
+
+struct wl_buffer {
+       struct wl_proxy proxy;
+};
+
 struct wl_input_device {
        struct wl_proxy proxy;
 };
@@ -258,6 +266,49 @@ wl_shell_resize(struct wl_shell *shell,
                         WL_SHELL_RESIZE, surface, device, time, edges);
 }
 
+WL_EXPORT int
+wl_drm_add_listener(struct wl_drm *drm,
+                   const struct wl_drm_listener *listener,
+                   void *data)
+{
+       return wl_proxy_add_listener(&drm->proxy,
+                                    (void (**)(void)) listener, data);
+}
+
+WL_EXPORT void
+wl_drm_authenticate(struct wl_drm *drm, uint32_t id)
+{
+       wl_proxy_marshal(&drm->proxy, WL_DRM_AUTHENTICATE, id);
+}
+
+WL_EXPORT struct wl_buffer *
+wl_drm_create_buffer(struct wl_drm *drm, uint32_t name,
+                    int32_t width, int32_t height,
+                    uint32_t stride, struct wl_visual *visual)
+{
+       struct wl_buffer *buffer;
+
+       buffer = malloc(sizeof *buffer);
+       if (buffer == NULL)
+               return NULL;
+
+       buffer->proxy.base.interface = &wl_buffer_interface;
+       buffer->proxy.base.id = wl_display_allocate_id(drm->proxy.display);
+       buffer->proxy.display = drm->proxy.display;
+       wl_hash_table_insert(drm->proxy.display->objects,
+                            drm->proxy.base.id, buffer);
+       wl_proxy_marshal(&drm->proxy, WL_DRM_CREATE_BUFFER,
+                        buffer, name, width, height, stride, visual);
+
+       return buffer;
+}
+
+WL_EXPORT void
+wl_buffer_destroy(struct wl_buffer *buffer)
+{
+       wl_proxy_marshal(&buffer->proxy, WL_BUFFER_DESTROY);
+}
+
 static void
 add_visual(struct wl_display *display, struct wl_global *global)
 {
@@ -360,6 +411,9 @@ display_handle_global(void *data,
        else if (strcmp(global->interface, "shell") == 0)
                wl_proxy_create_for_global(display, global,
                                           &wl_shell_interface);
+       else if (strcmp(global->interface, "drm") == 0)
+               wl_proxy_create_for_global(display, global,
+                                          &wl_drm_interface);
 }
 
 static void
@@ -589,12 +643,9 @@ wl_surface_destroy(struct wl_surface *surface)
 }
 
 WL_EXPORT void
-wl_surface_attach(struct wl_surface *surface, uint32_t name,
-                 int32_t width, int32_t height, uint32_t stride,
-                 struct wl_visual *visual)
+wl_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
 {
-       wl_proxy_marshal(&surface->proxy, WL_SURFACE_ATTACH,
-                        name, width, height, stride, visual);
+       wl_proxy_marshal(&surface->proxy, WL_SURFACE_ATTACH, buffer);
 }
 
 WL_EXPORT void
index 4f94a8b..572adc0 100644 (file)
@@ -88,10 +88,20 @@ wl_shell_resize(struct wl_shell *shell,
                struct wl_surface *surface, struct wl_input_device *device,
                uint32_t time, uint32_t edges);
 
+int
+wl_drm_add_listener(struct wl_drm *drm,
+                   const struct wl_drm_listener *listener,
+                   void *data);
+void
+wl_drm_authenticate(struct wl_drm *drm, uint32_t id);
+struct wl_buffer *
+wl_drm_create_buffer(struct wl_drm *drm, uint32_t name,
+                    int32_t width, int32_t height,
+                    uint32_t stride, struct wl_visual *visual);
+void wl_buffer_destroy(struct wl_buffer *buffer);
+
 void wl_surface_destroy(struct wl_surface *surface);
-void wl_surface_attach(struct wl_surface *surface, uint32_t name,
-                      int32_t width, int32_t height, uint32_t stride,
-                      struct wl_visual *visual);
+void wl_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer);
 void wl_surface_map(struct wl_surface *surface,
                    int32_t x, int32_t y, int32_t width, int32_t height);
 void wl_surface_damage(struct wl_surface *surface,
index 6ccc56a..575e657 100644 (file)
@@ -98,6 +98,13 @@ int wl_list_empty(struct wl_list *list);
             &pos->member != (head);                                    \
             pos = __container_of(pos->member.next, pos, member))
 
+#define wl_list_for_each_safe(pos, tmp, head, member)                  \
+       for (pos = __container_of((head)->next, pos, member),           \
+            tmp = __container_of((pos)->member.next, tmp, member);     \
+            &pos->member != (head);                                    \
+            pos = tmp,                                                 \
+            tmp = __container_of(pos->member.next, tmp, member))
+
 #define wl_list_for_each_reverse(pos, head, member)                    \
        for (pos = __container_of((head)->prev, pos, member);           \
             &pos->member != (head);                                    \
index ee7150c..78059d4 100644 (file)
--- a/wayland.c
+++ b/wayland.c
@@ -42,7 +42,7 @@ struct wl_client {
        struct wl_connection *connection;
        struct wl_event_source *source;
        struct wl_display *display;
-       struct wl_list surface_list;
+       struct wl_list resource_list;
        struct wl_list link;
        uint32_t id_count;
 };
@@ -186,7 +186,7 @@ wl_client_create(struct wl_display *display, int fd)
        client->connection =
                wl_connection_create(fd, wl_client_connection_update, client);
 
-       wl_list_init(&client->surface_list);
+       wl_list_init(&client->resource_list);
        wl_list_init(&client->link);
 
        wl_display_post_range(display, client);
@@ -205,30 +205,42 @@ wl_client_create(struct wl_display *display, int fd)
        return client;
 }
 
-static void
-wl_object_destroy(struct wl_object *object)
+WL_EXPORT void
+wl_client_add_resource(struct wl_client *client,
+                      struct wl_resource *resource)
+{
+       struct wl_display *display = client->display;
+
+       if (client->id_count-- < 64)
+               wl_display_post_range(display, client);
+
+       wl_hash_table_insert(client->display->objects,
+                            resource->base.id, resource);
+       wl_list_insert(client->resource_list.prev, &resource->link);
+}
+
+WL_EXPORT void
+wl_resource_destroy(struct wl_resource *resource, struct wl_client *client)
 {
-       const struct wl_surface_interface *interface =
-               (const struct wl_surface_interface *) object->implementation;
+       struct wl_display *display = client->display;
 
-       /* FIXME: Need generic object destructor. */
-       interface->destroy(NULL, (struct wl_surface *) object);
+       wl_list_remove(&resource->link);
+       wl_hash_table_remove(display->objects, resource->base.id);
+       resource->destroy(resource, client);
 }
 
 WL_EXPORT void
 wl_client_destroy(struct wl_client *client)
 {
-       struct wl_surface *surface;
+       struct wl_resource *resource, *tmp;
 
        printf("disconnect from client %p\n", client);
 
        wl_list_remove(&client->link);
 
-       while (client->surface_list.next != &client->surface_list) {
-               surface = container_of(client->surface_list.next,
-                                      struct wl_surface, link);
-               wl_list_remove(&surface->link);
-               wl_object_destroy(&surface->base);
+       wl_list_for_each_safe(resource, tmp, &client->resource_list, link) {
+               wl_list_remove(&resource->link);
+               resource->destroy(resource, client);
        }
 
        wl_event_source_remove(client->source);
@@ -242,33 +254,17 @@ wl_client_add_surface(struct wl_client *client,
                      const struct wl_surface_interface *implementation, 
                      uint32_t id)
 {
-       struct wl_display *display = client->display;
-
-       if (client->id_count-- < 64)
-               wl_display_post_range(display, client);
-
-       surface->base.id = id;
-       surface->base.interface = &wl_surface_interface;
-       surface->base.implementation = (void (**)(void)) implementation;
+       surface->base.base.id = id;
+       surface->base.base.interface = &wl_surface_interface;
+       surface->base.base.implementation = (void (**)(void)) implementation;
        surface->client = client;
 
-       wl_hash_table_insert(display->objects, id, surface);
-       wl_list_insert(client->surface_list.prev, &surface->link);
+       wl_client_add_resource(client, &surface->base);
 
        return 0;
 }
 
 WL_EXPORT void
-wl_client_remove_surface(struct wl_client *client,
-                        struct wl_surface *surface)
-{
-       struct wl_display *display = client->display;
-
-       wl_hash_table_remove(display->objects, surface->base.id);
-       wl_list_remove(&surface->link);
-}
-
-WL_EXPORT void
 wl_client_send_acknowledge(struct wl_client *client,
                           struct wl_compositor *compositor,
                           uint32_t key, uint32_t frame)
@@ -280,16 +276,6 @@ wl_client_send_acknowledge(struct wl_client *client,
                             WL_COMPOSITOR_ACKNOWLEDGE, key, frame);
 }
 
-static void
-post_compositor_device(struct wl_client *client, struct wl_object *global)
-{
-       struct wl_compositor *compositor =
-               container_of(global, struct wl_compositor, base);
-
-       wl_client_post_event(client, global,
-                            WL_COMPOSITOR_DEVICE, compositor->device);
-}
-
 WL_EXPORT int
 wl_display_set_compositor(struct wl_display *display,
                          struct wl_compositor *compositor,
@@ -299,7 +285,7 @@ wl_display_set_compositor(struct wl_display *display,
        compositor->base.implementation = (void (**)(void)) implementation;
 
        wl_display_add_object(display, &compositor->base);
-       if (wl_display_add_global(display, &compositor->base, post_compositor_device))
+       if (wl_display_add_global(display, &compositor->base, NULL))
                return -1;
 
        return 0;
index 96df34f..71869cd 100644 (file)
--- a/wayland.h
+++ b/wayland.h
@@ -70,14 +70,9 @@ struct wl_event_source *wl_event_loop_add_idle(struct wl_event_loop *loop,
                                               void *data);
 
 struct wl_client;
-
 struct wl_display;
 struct wl_input_device;
 
-struct wl_map {
-       int32_t x, y, width, height;
-};
-
 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);
@@ -93,15 +88,24 @@ void wl_client_destroy(struct wl_client *client);
 
 struct wl_compositor {
        struct wl_object base;
-       const char *device;
 };
 
-struct wl_surface {
+struct wl_resource {
        struct wl_object base;
-       struct wl_client *client;
+       void (*destroy)(struct wl_resource *resource,
+                       struct wl_client *client);
        struct wl_list link;
 };
 
+struct wl_buffer {
+       struct wl_resource base;
+};
+
+struct wl_surface {
+       struct wl_resource base;
+       struct wl_client *client;
+};
+
 void
 wl_client_post_event(struct wl_client *client,
                      struct wl_object *sender,
@@ -124,10 +128,6 @@ wl_client_add_surface(struct wl_client *client,
                      uint32_t id);
 
 void
-wl_client_remove_surface(struct wl_client *client,
-                        struct wl_surface *surface);
-
-void
 wl_client_send_acknowledge(struct wl_client *client,
                           struct wl_compositor *compositor,
                           uint32_t key, uint32_t frame);
@@ -137,6 +137,13 @@ wl_display_post_frame(struct wl_display *display,
                      struct wl_compositor *compositor,
                      uint32_t frame, uint32_t msecs);
 
+void
+wl_client_add_resource(struct wl_client *client,
+                      struct wl_resource *resource);
+
+void
+wl_resource_destroy(struct wl_resource *resource, struct wl_client *client);
+
 #ifdef  __cplusplus
 }
 #endif