Add preliminary visual support.
authorKristian Høgsberg <krh@redhat.com>
Thu, 18 Dec 2008 22:55:33 +0000 (17:55 -0500)
committerKristian Høgsberg <krh@redhat.com>
Thu, 18 Dec 2008 22:55:33 +0000 (17:55 -0500)
egl-compositor.c
flower.c
wayland-client.c
wayland-client.h
wayland.c
wayland.h
window.c

index 16c7fb0..ae64639 100644 (file)
 
 #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;
index 21f10b1..e944532 100644 (file)
--- 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);
 
index c51d9bd..37bf32e 100644 (file)
@@ -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);
index 54889d4..4f4adcc 100644 (file)
@@ -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,
index 6b1d98b..e402253 100644 (file)
--- 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" }
index 1af2aaa..bac9c5b 100644 (file)
--- 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);
index c765fe5..1ff59c2 100644 (file)
--- 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,