From aa5b5bed73d1f12ebc5ab0a7885abda711b75122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 21 Nov 2008 21:31:54 -0500 Subject: [PATCH] Load and draw background in compositor. --- Makefile | 4 +- egl-compositor.c | 160 ++++++++++++++++++++++++++++++----------------- 2 files changed, 105 insertions(+), 59 deletions(-) diff --git a/Makefile b/Makefile index 19519ed0..f53e855c 100644 --- 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) diff --git a/egl-compositor.c b/egl-compositor.c index c6180155..24f47337 100644 --- a/egl-compositor.c +++ b/egl-compositor.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include "wayland.h" @@ -20,11 +22,6 @@ #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);