From de31d5ca6f2650da3c4e8c45acdcee73ed655602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 18 Dec 2008 17:55:33 -0500 Subject: [PATCH] Add preliminary visual support. --- egl-compositor.c | 85 +++++++++++++++++++++++++++++++++++++++--------- flower.c | 7 ++-- wayland-client.c | 57 ++++++++++++++++++++++++++++++-- wayland-client.h | 12 +++++-- wayland.c | 8 ++--- wayland.h | 3 +- window.c | 5 ++- 7 files changed, 148 insertions(+), 29 deletions(-) diff --git a/egl-compositor.c b/egl-compositor.c index 16c7fb00..ae646391 100644 --- a/egl-compositor.c +++ b/egl-compositor.c @@ -52,6 +52,10 @@ #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) +struct wl_visual { + struct wl_object base; +}; + struct egl_input_device { struct wl_object base; int32_t x, y; @@ -66,6 +70,8 @@ struct egl_input_device { struct egl_compositor { struct wl_compositor base; + struct wl_visual argb_visual, premultiplied_argb_visual, rgb_visual; + EGLDisplay display; EGLSurface surface; EGLContext context; @@ -91,6 +97,7 @@ struct egl_compositor { struct egl_surface { struct wl_surface base; struct egl_compositor *compositor; + struct wl_visual *visual; GLuint texture; struct wl_map map; EGLSurface surface; @@ -155,7 +162,8 @@ screenshooter_create(struct egl_compositor *ec) }; static struct egl_surface * -egl_surface_create_from_cairo_surface(cairo_surface_t *surface, +egl_surface_create_from_cairo_surface(struct egl_compositor *ec, + cairo_surface_t *surface, int x, int y, int width, int height) { struct egl_surface *es; @@ -178,11 +186,13 @@ egl_surface_create_from_cairo_surface(cairo_surface_t *surface, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, data); + es->compositor = ec; es->map.x = x; es->map.y = y; es->map.width = width; es->map.height = height; es->surface = EGL_NO_SURFACE; + es->visual = &ec->premultiplied_argb_visual; return es; } @@ -213,7 +223,7 @@ pointer_path(cairo_t *cr, int x, int y) } static struct egl_surface * -pointer_create(int x, int y, int width, int height) +pointer_create(struct egl_compositor *ec, int x, int y, int width, int height) { struct egl_surface *es; const int hotspot_x = 16, hotspot_y = 16; @@ -237,7 +247,8 @@ pointer_create(int x, int y, int width, int height) cairo_fill(cr); cairo_destroy(cr); - es = egl_surface_create_from_cairo_surface(surface, + es = egl_surface_create_from_cairo_surface(ec, + surface, x - hotspot_x, y - hotspot_y, width, height); @@ -248,7 +259,8 @@ pointer_create(int x, int y, int width, int height) } static struct egl_surface * -background_create(const char *filename, int width, int height) +background_create(struct egl_compositor *ec, + const char *filename, int width, int height) { struct egl_surface *background; GdkPixbuf *pixbuf; @@ -281,11 +293,13 @@ background_create(const char *filename, int width, int height) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pixbuf_width, pixbuf_height, 0, GL_BGR, GL_UNSIGNED_BYTE, data); + background->compositor = ec; background->map.x = 0; background->map.y = 0; background->map.width = width; background->map.height = height; background->surface = EGL_NO_SURFACE; + background->visual = &ec->rgb_visual; return background; } @@ -351,7 +365,7 @@ draw_button(cairo_t *cr, int x, int y, int width, int height, const char *text) } static struct egl_surface * -overlay_create(int x, int y, int width, int height) +overlay_create(struct egl_compositor *ec, int x, int y, int width, int height) { struct egl_surface *es; cairo_surface_t *surface; @@ -378,7 +392,8 @@ overlay_create(int x, int y, int width, int height) cairo_destroy(cr); - es = egl_surface_create_from_cairo_surface(surface, x, y, width, height); + es = egl_surface_create_from_cairo_surface(ec, surface, + x, y, width, height); cairo_surface_destroy(surface); @@ -388,6 +403,7 @@ overlay_create(int x, int y, int width, int height) static void draw_surface(struct egl_surface *es) { + struct egl_compositor *ec = es->compositor; GLint vertices[12]; GLint tex_coords[12] = { 0, 0, 0, 1, 1, 0, 1, 1 }; GLuint indices[4] = { 0, 1, 2, 3 }; @@ -408,13 +424,18 @@ draw_surface(struct egl_surface *es) vertices[10] = es->map.y + es->map.height; vertices[11] = 0; + if (es->visual == &ec->argb_visual) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + } else if (es->visual == &ec->premultiplied_argb_visual) { + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + } else { + glDisable(GL_BLEND); + } + glBindTexture(GL_TEXTURE_2D, es->texture); glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - /* Assume pre-multiplied alpha for now, this probably - * needs to be a wayland visual type of thing. */ - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(3, GL_INT, 0, vertices); @@ -549,7 +570,8 @@ surface_destroy(struct wl_client *client, static void surface_attach(struct wl_client *client, struct wl_surface *surface, uint32_t name, - uint32_t width, uint32_t height, uint32_t stride) + uint32_t width, uint32_t height, uint32_t stride, + struct wl_object *visual) { struct egl_surface *es = (struct egl_surface *) surface; struct egl_compositor *ec = es->compositor; @@ -561,6 +583,12 @@ surface_attach(struct wl_client *client, es->height = height; es->surface = eglCreateSurfaceForName(ec->display, ec->config, name, width, height, stride, NULL); + if (visual == &ec->argb_visual.base) + es->visual = &ec->argb_visual; + else if (visual == &ec->premultiplied_argb_visual.base) + es->visual = &ec->premultiplied_argb_visual; + else + /* FIXME: Smack client with an exception event */; glBindTexture(GL_TEXTURE_2D, es->texture); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); @@ -783,7 +811,8 @@ create_input_device(struct egl_compositor *ec, const char *glob) wl_display_add_object(ec->wl_display, &device->base); device->x = 100; device->y = 100; - device->pointer_surface = pointer_create(device->x, device->y, 64, 64); + device->pointer_surface = pointer_create(ec, + device->x, device->y, 64, 64); device->ec = ec; dir = opendir(by_path_dir); @@ -947,6 +976,31 @@ pick_config(struct egl_compositor *ec) return 0; } +static const struct wl_interface visual_interface = { + "visual", 1, +}; + +static void +add_visuals(struct egl_compositor *ec) +{ + ec->argb_visual.base.interface = &visual_interface; + ec->argb_visual.base.implementation = NULL; + wl_display_add_object(ec->wl_display, &ec->argb_visual.base); + wl_display_add_global(ec->wl_display, &ec->argb_visual.base); + + ec->premultiplied_argb_visual.base.interface = &visual_interface; + ec->premultiplied_argb_visual.base.implementation = NULL; + wl_display_add_object(ec->wl_display, + &ec->premultiplied_argb_visual.base); + wl_display_add_global(ec->wl_display, + &ec->premultiplied_argb_visual.base); + + ec->rgb_visual.base.interface = &visual_interface; + ec->rgb_visual.base.implementation = NULL; + wl_display_add_object(ec->wl_display, &ec->rgb_visual.base); + wl_display_add_global(ec->wl_display, &ec->rgb_visual.base); +} + static const char gem_device[] = "/dev/dri/card0"; static const char *macbook_air_default_input_device[] = { @@ -1025,15 +1079,16 @@ egl_compositor_create(struct wl_display *display) glClearColor(0, 0, 0.2, 1); wl_display_set_compositor(display, &ec->base, &compositor_interface); + add_visuals(ec); wl_list_init(&ec->input_device_list); for (i = 0; option_input_devices[i]; i++) create_input_device(ec, option_input_devices[i]); wl_list_init(&ec->surface_list); - ec->background = background_create(option_background, + ec->background = background_create(ec, option_background, ec->width, ec->height); - ec->overlay = overlay_create(0, ec->height, ec->width, 200); + ec->overlay = overlay_create(ec, 0, ec->height, ec->width, 200); ec->overlay_y = ec->height; ec->overlay_target = ec->height; ec->overlay_previous = ec->height; diff --git a/flower.c b/flower.c index 21f10b17..e9445327 100644 --- a/flower.c +++ b/flower.c @@ -133,6 +133,7 @@ event_handler(struct wl_display *display, int main(int argc, char *argv[]) { struct wl_display *display; + struct wl_visual *visual; int fd; cairo_surface_t *s; struct timespec ts; @@ -172,8 +173,10 @@ int main(int argc, char *argv[]) s = draw_stuff(flower.width, flower.height); buffer = buffer_create_from_cairo_surface(fd, s); - wl_surface_attach(flower.surface, buffer->name, flower.width, flower.height, - buffer->stride); + visual = wl_display_get_premultiplied_argb_visual(display); + wl_surface_attach(flower.surface, + buffer->name, flower.width, flower.height, + buffer->stride, visual); wl_display_set_event_handler(display, event_handler, &flower); move_flower(&flower); diff --git a/wayland-client.c b/wayland-client.c index c51d9bd7..37bf32ec 100644 --- a/wayland-client.c +++ b/wayland-client.c @@ -56,6 +56,7 @@ struct wl_display { uint32_t id; uint32_t mask; struct wl_list global_list; + struct wl_list visual_list; wl_display_update_func_t update; void *update_data; @@ -72,6 +73,11 @@ struct wl_surface { struct wl_proxy proxy; }; +struct wl_visual { + struct wl_proxy proxy; + struct wl_list link; +}; + static int connection_update(struct wl_connection *connection, uint32_t mask, void *data) @@ -86,6 +92,45 @@ connection_update(struct wl_connection *connection, return 0; } +static void +add_visual(struct wl_display *display, struct wl_global *global) +{ + struct wl_visual *visual; + + visual = malloc(sizeof *visual); + if (visual == NULL) + return; + + visual->proxy.display = display; + visual->proxy.id = global->id; + wl_list_insert(display->visual_list.prev, &visual->link); + + printf("added visual, id %d\n", global->id); +} + +WL_EXPORT struct wl_visual * +wl_display_get_argb_visual(struct wl_display *display) +{ + return container_of(display->visual_list.next, + struct wl_visual, link); +} + +WL_EXPORT struct wl_visual * +wl_display_get_premultiplied_argb_visual(struct wl_display *display) +{ + return container_of(display->visual_list.next->next, + struct wl_visual, link); +} + +WL_EXPORT struct wl_visual * +wl_display_get_rgb_visual(struct wl_display *display) +{ + /* FIXME: Where's cddar when you need it... */ + + return container_of(display->visual_list.next->next->next, + struct wl_visual, link); +} + WL_EXPORT struct wl_display * wl_display_create(const char *name, size_t name_size) { @@ -125,6 +170,7 @@ wl_display_create(const char *name, size_t name_size) read(display->fd, &count, sizeof count); wl_list_init(&display->global_list); + wl_list_init(&display->visual_list); for (i = 0; i < count; i++) { /* FIXME: actually discover advertised objects here. */ read(display->fd, &id, sizeof id); @@ -140,6 +186,9 @@ wl_display_create(const char *name, size_t name_size) memcpy(global->interface, buffer, length); global->interface[length] = '\0'; wl_list_insert(display->global_list.prev, &global->link); + + if (strcmp(global->interface, "visual") == 0) + add_visual(display, global); } display->proxy.display = display; @@ -327,9 +376,10 @@ 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) + int32_t width, int32_t height, uint32_t stride, + struct wl_visual *visual) { - uint32_t request[6]; + uint32_t request[7]; request[0] = surface->proxy.id; request[1] = WL_SURFACE_ATTACH | ((sizeof request) << 16); @@ -337,6 +387,9 @@ wl_surface_attach(struct wl_surface *surface, uint32_t name, request[3] = width; request[4] = height; request[5] = stride; + request[6] = visual->proxy.id; + + printf("attach, visual id is %d\n", visual->proxy.id); wl_connection_write(surface->proxy.display->connection, request, sizeof request); diff --git a/wayland-client.h b/wayland-client.h index 54889d4a..4f4adcca 100644 --- a/wayland-client.h +++ b/wayland-client.h @@ -32,6 +32,7 @@ struct wl_display; struct wl_surface; +struct wl_visual; #define WL_DISPLAY_READABLE 0x01 #define WL_DISPLAY_WRITABLE 0x02 @@ -58,6 +59,12 @@ void wl_display_set_event_handler(struct wl_display *display, struct wl_compositor * wl_display_get_compositor(struct wl_display *display); +struct wl_visual * +wl_display_get_argb_visual(struct wl_display *display); +struct wl_visual * +wl_display_get_premultiplied_argb_visual(struct wl_display *display); +struct wl_visual * +wl_display_get_rgb_visual(struct wl_display *display); struct wl_surface * wl_compositor_create_surface(struct wl_compositor *compositor); @@ -65,8 +72,9 @@ void 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, - uint32_t name, int32_t width, int32_t height, uint32_t stride); +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_map(struct wl_surface *surface, int32_t x, int32_t y, int32_t width, int32_t height); void wl_surface_copy(struct wl_surface *surface, int32_t dst_x, int32_t dst_y, diff --git a/wayland.c b/wayland.c index 6b1d98b4..e4022530 100644 --- a/wayland.c +++ b/wayland.c @@ -127,7 +127,7 @@ wl_client_demarshal(struct wl_client *client, struct wl_object *target, ffi_type *types[20]; ffi_cif cif; uint32_t *p, result; - int i, j, count; + int i, count; union { uint32_t uint32; const char *string; @@ -161,7 +161,6 @@ wl_client_demarshal(struct wl_client *client, struct wl_object *target, wl_connection_copy(client->connection, data, size); p = &data[2]; - j = 0; for (i = 2; i < count; i++) { switch (method->signature[i - 2]) { case 'u': @@ -180,11 +179,8 @@ wl_client_demarshal(struct wl_client *client, struct wl_object *target, object = wl_hash_lookup(client->display->objects, *p); if (object == NULL) printf("unknown object (%d)\n", *p); - if (object->interface != method->types[j]) - printf("wrong object type\n"); values[i].object = object; p++; - j++; break; case 'n': types[i] = &ffi_type_uint32; @@ -369,7 +365,7 @@ wl_client_destroy(struct wl_client *client) static const struct wl_method surface_methods[] = { { "destroy", "" }, - { "attach", "uuuu" }, + { "attach", "uuuuo" }, { "map", "iiii" }, { "copy", "iiuuiiii" }, { "damage", "iiii" } diff --git a/wayland.h b/wayland.h index 1af2aaaa..bac9c5b6 100644 --- a/wayland.h +++ b/wayland.h @@ -142,7 +142,8 @@ struct wl_surface_interface { 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); + uint32_t width, uint32_t height, uint32_t stride, + struct wl_object *visual); void (*map)(struct wl_client *client, struct wl_surface *surface, int32_t x, int32_t y, int32_t width, int32_t height); diff --git a/window.c b/window.c index c765fe56..1ff59c26 100644 --- a/window.c +++ b/window.c @@ -84,6 +84,7 @@ window_draw(struct window *window) int border = 2, radius = 5; cairo_text_extents_t extents; cairo_pattern_t *gradient, *outline, *bright, *dim; + struct wl_visual *visual; surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, window->width + window->margin * 2, @@ -156,11 +157,13 @@ window_draw(struct window *window) window->buffer = buffer_create_from_cairo_surface(window->fd, surface); cairo_surface_destroy(surface); + visual = wl_display_get_premultiplied_argb_visual(window->display); wl_surface_attach(window->surface, window->buffer->name, window->buffer->width, window->buffer->height, - window->buffer->stride); + window->buffer->stride, + visual); wl_surface_map(window->surface, window->x - window->margin,