Load and draw background in compositor.
authorKristian Høgsberg <krh@redhat.com>
Sat, 22 Nov 2008 02:31:54 +0000 (21:31 -0500)
committerKristian Høgsberg <krh@redhat.com>
Sat, 22 Nov 2008 02:31:54 +0000 (21:31 -0500)
Makefile
egl-compositor.c

index 19519ed..f53e855 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -30,8 +30,8 @@ libwayland.so : $(libwayland_objs)
 $(compositors) $(clients) : CFLAGS += $(shell pkg-config --cflags libdrm)
 
 egl_compositor_objs = egl-compositor.o cairo-util.o
-egl-compositor.so : CFLAGS += $(EAGLE_CFLAGS) $(shell pkg-config --cflags libpng cairo)
-egl-compositor.so : LDLIBS += $(EAGLE_LDLIBS) $(shell pkg-config --libs libpng cairo) -rdynamic
+egl-compositor.so : CFLAGS += $(EAGLE_CFLAGS) $(shell pkg-config --cflags libpng cairo gdk-pixbuf-2.0)
+egl-compositor.so : LDLIBS += $(EAGLE_LDLIBS) $(shell pkg-config --libs libpng cairo gdk-pixbuf-2.0) -rdynamic
 
 egl-compositor.so : $(egl_compositor_objs)
 
index c618015..24f4733 100644 (file)
@@ -10,6 +10,8 @@
 #include <unistd.h>
 #include <signal.h>
 #include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <glib.h>
 #include <png.h>
 
 #include "wayland.h"
 
 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
 
-struct pointer {
-       struct wl_map map;
-       GLuint texture;
-};
-
 struct egl_compositor {
        struct wl_compositor base;
        EGLDisplay display;
@@ -34,10 +31,11 @@ struct egl_compositor {
        struct wl_display *wl_display;
        int gem_fd;
        int width, height;
-       struct pointer *pointer;
+       struct egl_surface *pointer;
+       struct egl_surface *background;
 };
 
-struct surface_data {
+struct egl_surface {
        GLuint texture;
        struct wl_map map;
        EGLSurface surface;
@@ -195,11 +193,11 @@ pointer_path(cairo_t *cr, int x, int y)
        cairo_close_path(cr);
 }
 
-static struct pointer *
+static struct egl_surface *
 pointer_create(int x, int y, int width, int height)
 {
        const int hotspot_x = 16, hotspot_y = 16;
-       struct pointer *pointer;
+       struct egl_surface *pointer;
        cairo_surface_t *surface;
        cairo_t *cr;
        int stride;
@@ -244,41 +242,87 @@ pointer_create(int x, int y, int width, int height)
        pointer->map.y = y;
        pointer->map.width = width;
        pointer->map.height = height;
+       pointer->surface = EGL_NO_SURFACE;
 
        return pointer;
 }
 
 static void
-pointer_destroy(struct pointer *pointer)
+egl_surface_destroy(struct egl_surface *es, struct egl_compositor *ec)
+{
+       glDeleteTextures(1, &es->texture);
+       if (es->surface != EGL_NO_SURFACE)
+               eglDestroySurface(ec->display, es->surface);
+       free(es);
+}
+
+static struct egl_surface *
+background_create(const char *filename, int width, int height)
 {
-       glDeleteTextures(1, &pointer->texture);
-       free(pointer);
+       struct egl_surface *background;
+       GdkPixbuf *pixbuf;
+       GError *error = NULL;
+       int pixbuf_width, pixbuf_height;
+       void *data;
+
+       background = malloc(sizeof *background);
+       if (background == NULL)
+               return NULL;
+       
+       g_type_init();
+
+       pixbuf = gdk_pixbuf_new_from_file(filename, &error);
+       if (error != NULL) {
+               free(background);
+               return NULL;
+       }
+
+       pixbuf_width = gdk_pixbuf_get_width(pixbuf);
+       pixbuf_height = gdk_pixbuf_get_height(pixbuf);
+       data = gdk_pixbuf_get_pixels(pixbuf);
+
+       glGenTextures(1, &background->texture);
+       glBindTexture(GL_TEXTURE_2D, background->texture);
+       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
+       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pixbuf_width, pixbuf_height, 0,
+                    GL_BGR, GL_UNSIGNED_BYTE, data);
+
+       background->map.x = 0;
+       background->map.y = 0;
+       background->map.width = width;
+       background->map.height = height;
+       background->surface = EGL_NO_SURFACE;
+
+       return background;
 }
 
 static void
-draw_surface(struct wl_map *map, GLuint texture)
+draw_surface(struct egl_surface *es)
 {
        GLint vertices[12];
        GLint tex_coords[12] = { 0, 0,  0, 1,  1, 0,  1, 1 };
        GLuint indices[4] = { 0, 1, 2, 3 };
 
-       vertices[0] = map->x;
-       vertices[1] = map->y;
+       vertices[0] = es->map.x;
+       vertices[1] = es->map.y;
        vertices[2] = 0;
 
-       vertices[3] = map->x;
-       vertices[4] = map->y + map->height;
+       vertices[3] = es->map.x;
+       vertices[4] = es->map.y + es->map.height;
        vertices[5] = 0;
 
-       vertices[6] = map->x + map->width;
-       vertices[7] = map->y;
+       vertices[6] = es->map.x + es->map.width;
+       vertices[7] = es->map.y;
        vertices[8] = 0;
 
-       vertices[9] = map->x + map->width;
-       vertices[10] = map->y + map->height;
+       vertices[9] = es->map.x + es->map.width;
+       vertices[10] = es->map.y + es->map.height;
        vertices[11] = 0;
 
-       glBindTexture(GL_TEXTURE_2D, texture);
+       glBindTexture(GL_TEXTURE_2D, es->texture);
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        /* Assume pre-multiplied alpha for now, this probably
@@ -298,19 +342,21 @@ repaint(void *data)
        struct egl_compositor *ec = data;
        struct wl_surface_iterator *iterator;
        struct wl_surface *surface;
-       struct surface_data *sd;
+       struct egl_surface *es;
+
+       draw_surface(ec->background);
 
        iterator = wl_surface_iterator_create(ec->wl_display, 0);
        while (wl_surface_iterator_next(iterator, &surface)) {
-               sd = wl_surface_get_data(surface);
-               if (sd == NULL)
+               es = wl_surface_get_data(surface);
+               if (es == NULL)
                        continue;
 
-               draw_surface(&sd->map, sd->texture);
+               draw_surface(es);
        }
        wl_surface_iterator_destroy(iterator);
 
-       draw_surface(&ec->pointer->map, ec->pointer->texture);
+       draw_surface(ec->pointer);
 
        eglSwapBuffers(ec->display, ec->surface);
 
@@ -339,16 +385,16 @@ static void
 notify_surface_create(struct wl_compositor *compositor,
                      struct wl_surface *surface)
 {
-       struct surface_data *sd;
+       struct egl_surface *es;
 
-       sd = malloc(sizeof *sd);
-       if (sd == NULL)
+       es = malloc(sizeof *es);
+       if (es == NULL)
                return;
 
-       sd->surface = EGL_NO_SURFACE;
-       wl_surface_set_data(surface, sd);
+       es->surface = EGL_NO_SURFACE;
+       wl_surface_set_data(surface, es);
 
-       glGenTextures(1, &sd->texture);
+       glGenTextures(1, &es->texture);
 }
                                   
 static void
@@ -356,18 +402,13 @@ notify_surface_destroy(struct wl_compositor *compositor,
                       struct wl_surface *surface)
 {
        struct egl_compositor *ec = (struct egl_compositor *) compositor;
-       struct surface_data *sd;
+       struct egl_surface *es;
 
-       sd = wl_surface_get_data(surface);
-       if (sd == NULL)
+       es = wl_surface_get_data(surface);
+       if (es == NULL)
                return;
 
-       if (sd->surface != EGL_NO_SURFACE)
-               eglDestroySurface(ec->display, sd->surface);
-
-       glDeleteTextures(1, &sd->texture);
-
-       free(sd);
+       egl_surface_destroy(es, ec);
 
        schedule_repaint(ec);
 }
@@ -378,27 +419,27 @@ notify_surface_attach(struct wl_compositor *compositor,
                      uint32_t width, uint32_t height, uint32_t stride)
 {
        struct egl_compositor *ec = (struct egl_compositor *) compositor;
-       struct surface_data *sd;
+       struct egl_surface *es;
 
-       sd = wl_surface_get_data(surface);
-       if (sd == NULL)
+       es = wl_surface_get_data(surface);
+       if (es == NULL)
                return;
 
-       if (sd->surface != EGL_NO_SURFACE)
-               eglDestroySurface(ec->display, sd->surface);
+       if (es->surface != EGL_NO_SURFACE)
+               eglDestroySurface(ec->display, es->surface);
 
        /* FIXME: We need to use a single buffer config without depth
         * or stencil buffers here to keep egl from creating auxillary
         * buffers for the pixmap here. */
-       sd->surface = eglCreateSurfaceForName(ec->display, ec->config,
+       es->surface = eglCreateSurfaceForName(ec->display, ec->config,
                                              name, width, height, stride, NULL);
 
-       glBindTexture(GL_TEXTURE_2D, sd->texture);
+       glBindTexture(GL_TEXTURE_2D, es->texture);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-       eglBindTexImage(ec->display, sd->surface, GL_TEXTURE_2D);
+       eglBindTexImage(ec->display, es->surface, GL_TEXTURE_2D);
 
        schedule_repaint(ec);
 }
@@ -408,13 +449,13 @@ notify_surface_map(struct wl_compositor *compositor,
                   struct wl_surface *surface, struct wl_map *map)
 {
        struct egl_compositor *ec = (struct egl_compositor *) compositor;
-       struct surface_data *sd;
+       struct egl_surface *es;
 
-       sd = wl_surface_get_data(surface);
-       if (sd == NULL)
+       es = wl_surface_get_data(surface);
+       if (es == NULL)
                return;
 
-       sd->map = *map;
+       es->map = *map;
 
        schedule_repaint(ec);
 }
@@ -428,9 +469,9 @@ notify_surface_copy(struct wl_compositor *compositor,
 {
        struct egl_compositor *ec = (struct egl_compositor *) compositor;
        EGLSurface src;
-       struct surface_data *sd;
+       struct egl_surface *es;
 
-       sd = wl_surface_get_data(surface);
+       es = wl_surface_get_data(surface);
 
        /* FIXME: glCopyPixels should work, but then we'll have to
         * call eglMakeCurrent to set up the src and dest surfaces
@@ -440,7 +481,7 @@ notify_surface_copy(struct wl_compositor *compositor,
        src = eglCreateSurfaceForName(ec->display, ec->config,
                                      name, x + width, y + height, stride, NULL);
 
-       eglCopyNativeBuffers(ec->display, sd->surface, GL_FRONT_LEFT, dst_x, dst_y,
+       eglCopyNativeBuffers(ec->display, es->surface, GL_FRONT_LEFT, dst_x, dst_y,
                             src, GL_FRONT_LEFT, x, y, width, height);
        schedule_repaint(ec);
 }
@@ -485,6 +526,7 @@ wl_compositor_create(struct wl_display *display)
        EGLConfig configs[64];
        EGLint major, minor, count;
        struct egl_compositor *ec;
+       const char *filename;
 
        ec = malloc(sizeof *ec);
        if (ec == NULL)
@@ -538,6 +580,10 @@ wl_compositor_create(struct wl_display *display)
        glMatrixMode(GL_MODELVIEW);
        glClearColor(0.0, 0.05, 0.2, 0.0);
 
+       filename = getenv("WAYLAND_BACKGROUND");
+       if (filename == NULL)
+               filename = "background.jpg";
+       ec->background = background_create(filename, 1280, 800);
        ec->pointer = pointer_create(100, 100, 64, 64);
 
        ec->gem_fd = open(gem_device, O_RDWR);