From 05eff51e413ff48c2edd2a2ab3ca9f9435c5c855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 7 Oct 2008 10:10:36 -0400 Subject: [PATCH] Add surface.map request. --- client.c | 7 ++-- compositor.c | 99 +++++++++++++++++++++++++++++++++++++++--------- wayland-client.c | 38 ++++++++++++++++++- wayland-client.h | 8 ++-- wayland.c | 58 +++++++++++++++++++++++----- wayland.h | 12 +++++- 6 files changed, 188 insertions(+), 34 deletions(-) diff --git a/client.c b/client.c index d01ed2cf..48294c0d 100644 --- 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; } diff --git a/compositor.c b/compositor.c index 711c42f7..d76d8f1e 100644 --- a/compositor.c +++ b/compositor.c @@ -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"; diff --git a/wayland-client.c b/wayland-client.c index 2e5bd18b..afa43c84 100644 --- a/wayland-client.c +++ b/wayland-client.c @@ -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; +} diff --git a/wayland-client.h b/wayland-client.h index ae62bcac..2d6c799a 100644 --- a/wayland-client.h +++ b/wayland-client.h @@ -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 diff --git a/wayland.c b/wayland.c index a9eaf497..2d7e226f 100644 --- 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); diff --git a/wayland.h b/wayland.h index c95fc578..fc8f0fc5 100644 --- 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);