Add surface.map request.
authorKristian Høgsberg <krh@redhat.com>
Tue, 7 Oct 2008 14:10:36 +0000 (10:10 -0400)
committerKristian Høgsberg <krh@redhat.com>
Thu, 6 Nov 2008 15:51:43 +0000 (10:51 -0500)
client.c
compositor.c
wayland-client.c
wayland-client.h
wayland.c
wayland.h

index d01ed2c..48294c0 100644 (file)
--- a/client.c
+++ b/client.c
@@ -97,7 +97,8 @@ int main(int argc, char *argv[])
        struct wl_connection *connection;
        struct wl_display *display;
        struct wl_surface *surface;
-       int width = 300, height = 300, fd;
+       const int x = 400, y = 200, width = 300, height = 300;
+       int fd;
        uint32_t name;
        cairo_surface_t *s;
 
@@ -123,13 +124,13 @@ int main(int argc, char *argv[])
        wl_surface_attach(surface, name, width, height,
                          cairo_image_surface_get_stride(s));
 
+       wl_surface_map(surface, x, y, width, height);
        if (wl_connection_flush(connection) < 0) {
                fprintf(stderr, "flush error: %m\n");
                return -1;
        }
 
-       while (1)
-               wl_connection_iterate(connection);
+       wl_connection_iterate(connection);
 
        return 0;
 }
index 711c42f..d76d8f1 100644 (file)
@@ -18,21 +18,66 @@ struct lame_compositor {
        int gem_fd;
 };
 
+struct surface_data {
+       uint32_t handle;
+       int32_t width, height, stride;
+};
+
 void notify_surface_create(struct wl_compositor *compositor,
                           struct wl_surface *surface)
 {
+       struct surface_data *sd;
+
+       sd = malloc(sizeof *sd);
+       if (sd == NULL)
+               return;
+
+       sd->handle = 0;
+       wl_surface_set_data(surface, sd);
 }
                                   
+void notify_surface_destroy(struct wl_compositor *compositor,
+                           struct wl_surface *surface)
+{
+       struct lame_compositor *lc = (struct lame_compositor *) compositor;
+       struct surface_data *sd;
+       struct drm_gem_close close_arg;
+       int ret;
+
+       sd = wl_surface_get_data(surface);
+       if (sd == NULL || sd->handle == 0)
+               return;
+       
+       close_arg.handle = sd->handle;
+       ret = ioctl(lc->gem_fd, DRM_IOCTL_GEM_CLOSE, &close_arg);
+       if (ret != 0) {
+               fprintf(stderr, "failed to gem_close handle %d: %m\n", sd->handle);
+       }
+
+       free(sd);
+}
+
 void notify_surface_attach(struct wl_compositor *compositor,
                           struct wl_surface *surface, uint32_t name, 
                           uint32_t width, uint32_t height, uint32_t stride)
 {
        struct lame_compositor *lc = (struct lame_compositor *) compositor;
-       struct drm_i915_gem_pread pread;
+       struct surface_data *sd;
        struct drm_gem_open open_arg;
        struct drm_gem_close close_arg;
-       char *data, *dst;
-       int i, ret, x = 600, y = 200;
+       int ret;
+
+       sd = wl_surface_get_data(surface);
+       if (sd == NULL)
+               return;
+
+       if (sd->handle != 0) {
+               close_arg.handle = sd->handle;
+               ret = ioctl(lc->gem_fd, DRM_IOCTL_GEM_CLOSE, &close_arg);
+               if (ret != 0) {
+                       fprintf(stderr, "failed to gem_close name %d: %m\n", name);
+               }
+       }
 
        open_arg.name = name;
        ret = ioctl(lc->gem_fd, DRM_IOCTL_GEM_OPEN, &open_arg);
@@ -41,17 +86,41 @@ void notify_surface_attach(struct wl_compositor *compositor,
                return;
        }
 
-       data = malloc(open_arg.size);
+       sd->handle = open_arg.handle;
+       sd->width = width;
+       sd->height = height;
+       sd->stride = stride;
+}
+
+void notify_surface_map(struct wl_compositor *compositor,
+                       struct wl_surface *surface, struct wl_map *map)
+{
+       struct lame_compositor *lc = (struct lame_compositor *) compositor;
+       struct surface_data *sd;
+       struct drm_i915_gem_pread pread;
+       char *data, *dst;
+       uint32_t size;
+       int i;
+
+       /* This part is where we actually copy the buffer to screen.
+        * Needs to be part of the repaint loop, not in the notify_map
+        * handler. */
+
+       sd = wl_surface_get_data(surface);
+       if (sd == NULL)
+               return;
+
+       size = sd->height * sd->stride;
+       data = malloc(size);
        if (data == NULL) {
                fprintf(stderr, "swap buffers malloc failed\n");
                return;
        }
 
-       pread.size = open_arg.size;
-       pread.handle = open_arg.handle;
+       pread.handle = sd->handle;
        pread.pad = 0;
        pread.offset = 0;
-       pread.size = stride * height;
+       pread.size = size;
        pread.data_ptr = (long) data;
 
        if (ioctl(lc->gem_fd, DRM_IOCTL_I915_GEM_PREAD, &pread)) {
@@ -59,22 +128,18 @@ void notify_surface_attach(struct wl_compositor *compositor,
                return;
        }
 
-       dst = lc->fb + lc->stride * y + x * 4;
-       for (i = 0; i < height; i++)
-               memcpy(dst + lc->stride * i, data + stride * i, width * 4);
-
-       close_arg.handle = open_arg.handle;
-       ret = ioctl(lc->gem_fd, DRM_IOCTL_GEM_CLOSE, &close_arg);
-       if (ret != 0) {
-               fprintf(stderr, "failed to gem_close name %d: %m\n", name);
-       }
+       dst = lc->fb + lc->stride * map->y + map->x * 4;
+       for (i = 0; i < sd->height; i++)
+               memcpy(dst + lc->stride * i, data + sd->stride * i, sd->width * 4);
 
        free(data);
 }
 
 struct wl_compositor_interface interface = {
        notify_surface_create,
-       notify_surface_attach
+       notify_surface_destroy,
+       notify_surface_attach,
+       notify_surface_map
 };
 
 static const char fb_device[] = "/dev/fb";
index 2e5bd18..afa43c8 100644 (file)
@@ -192,7 +192,23 @@ wl_display_create_surface(struct wl_display *display)
        return surface;
 }
 
-#define WL_SURFACE_ATTACH 0
+#define WL_SURFACE_DESTROY     0
+#define WL_SURFACE_ATTACH      1
+#define WL_SURFACE_MAP         2
+
+void wl_surface_destroy(struct wl_surface *surface)
+{
+       uint32_t request[2];
+       struct wl_connection *connection;
+
+       request[0] = surface->proxy.id;
+       request[1] = WL_SURFACE_DESTROY | ((sizeof request) << 16);
+
+       connection = surface->proxy.connection;
+       memcpy(connection->out.data + connection->out.head,
+              request, sizeof request);
+       connection->out.head += sizeof request;
+}
 
 void wl_surface_attach(struct wl_surface *surface,
                       uint32_t name, int width, int height, int stride)
@@ -212,3 +228,23 @@ void wl_surface_attach(struct wl_surface *surface,
               request, sizeof request);
        connection->out.head += sizeof request;
 }
+
+
+void wl_surface_map(struct wl_surface *surface,
+                   int32_t x, int32_t y, int32_t width, int32_t height)
+{
+       uint32_t request[6];
+       struct wl_connection *connection;
+
+       request[0] = surface->proxy.id;
+       request[1] = WL_SURFACE_MAP | ((sizeof request) << 16);
+       request[2] = x;
+       request[3] = y;
+       request[4] = width;
+       request[5] = height;
+
+       connection = surface->proxy.connection;
+       memcpy(connection->out.data + connection->out.head,
+              request, sizeof request);
+       connection->out.head += sizeof request;
+}
index ae62bca..2d6c799 100644 (file)
@@ -21,8 +21,10 @@ wl_connection_get_display(struct wl_connection *connection);
 struct wl_surface *
 wl_display_create_surface(struct wl_display *display);
 
-void
-wl_surface_attach(struct wl_surface *surface,
-                 uint32_t name, int width, int height, int stride);
+void wl_surface_destroy(struct wl_surface *surface);
+void wl_surface_attach(struct wl_surface *surface,
+                      uint32_t name, int width, int height, int stride);
+void wl_surface_map(struct wl_surface *surface,
+                   int32_t x, int32_t y, int32_t width, int32_t height);
 
 #endif
index a9eaf49..2d7e226 100644 (file)
--- a/wayland.c
+++ b/wayland.c
@@ -43,16 +43,27 @@ struct wl_surface {
        int buffer;
        int stride;
        
-       /* these are used by the wayland server, not set from client */
-       void (*screen_to_surface)(int sx, int sy, int *wx, int *wy);
-       void (*surface_to_screen)(int sx, int sy, int *wx, int *wy);
+       struct wl_map map;
 
        /* 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;
 };
 
+                                  
+static void
+wl_surface_destroy(struct wl_client *client,
+                  struct wl_surface *surface)
+{
+       struct wl_compositor_interface *interface;
+
+       interface = client->display->compositor->interface;
+       interface->notify_surface_destroy(client->display->compositor, surface);
+}
+
 static void
 wl_surface_attach(struct wl_client *client,
                  struct wl_surface *surface, uint32_t name, 
@@ -73,21 +84,38 @@ static const struct wl_argument attach_arguments[] = {
 };
 
 void
-wl_surface_update(struct wl_surface *surface,
-                 uint32_t source_name, struct wl_region *region)
+wl_surface_map(struct wl_client *client, struct wl_surface *surface,
+              int32_t x, int32_t y, int32_t width, int32_t height)
 {
-       /* FIXME: how to demarshal region? */
-       /* copy region from buffer into current window contents. */
+       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 const struct wl_argument update_arguments[] = {
+static const struct wl_argument map_arguments[] = {
+       { WL_ARGUMENT_UINT32 },
+       { WL_ARGUMENT_UINT32 },
        { WL_ARGUMENT_UINT32 },
        { WL_ARGUMENT_UINT32 },
 };
 
 static const struct wl_method surface_methods[] = {
+       { "destroy", wl_surface_destroy,
+         0, NULL },
        { "attach", wl_surface_attach,
-         ARRAY_LENGTH(attach_arguments), attach_arguments }
+         ARRAY_LENGTH(attach_arguments), attach_arguments },
+       { "map", wl_surface_map,
+         ARRAY_LENGTH(map_arguments), map_arguments }
 };
 
 static const struct wl_interface surface_interface = {
@@ -115,6 +143,18 @@ wl_surface_create(struct wl_display *display, uint32_t id)
        return surface;
 }
 
+void
+wl_surface_set_data(struct wl_surface *surface, void *data)
+{
+       surface->compositor_data = data;
+}
+
+void *
+wl_surface_get_data(struct wl_surface *surface)
+{
+       return surface->compositor_data;
+}
+
 static void
 wl_client_data(int fd, uint32_t mask, void *data);
 
index c95fc57..fc8f0fc 100644 (file)
--- a/wayland.h
+++ b/wayland.h
@@ -77,6 +77,13 @@ struct wl_object {
 struct wl_surface;
 struct wl_display;
 
+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_compositor {
        struct wl_compositor_interface *interface;
 };
@@ -84,10 +91,13 @@ struct wl_compositor {
 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);
 };
 
 struct wl_compositor *wl_compositor_create(void);