Load and draw background in compositor.

dev
Kristian Høgsberg 16 years ago
parent 4c9f2c9b1a
commit aa5b5bed73
  1. 4
      Makefile
  2. 160
      egl-compositor.c

@ -30,8 +30,8 @@ libwayland.so : $(libwayland_objs)
$(compositors) $(clients) : CFLAGS += $(shell pkg-config --cflags libdrm) $(compositors) $(clients) : CFLAGS += $(shell pkg-config --cflags libdrm)
egl_compositor_objs = egl-compositor.o cairo-util.o egl_compositor_objs = egl-compositor.o cairo-util.o
egl-compositor.so : CFLAGS += $(EAGLE_CFLAGS) $(shell pkg-config --cflags libpng cairo) 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) -rdynamic egl-compositor.so : LDLIBS += $(EAGLE_LDLIBS) $(shell pkg-config --libs libpng cairo gdk-pixbuf-2.0) -rdynamic
egl-compositor.so : $(egl_compositor_objs) egl-compositor.so : $(egl_compositor_objs)

@ -10,6 +10,8 @@
#include <unistd.h> #include <unistd.h>
#include <signal.h> #include <signal.h>
#include <cairo.h> #include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <glib.h>
#include <png.h> #include <png.h>
#include "wayland.h" #include "wayland.h"
@ -20,11 +22,6 @@
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
struct pointer {
struct wl_map map;
GLuint texture;
};
struct egl_compositor { struct egl_compositor {
struct wl_compositor base; struct wl_compositor base;
EGLDisplay display; EGLDisplay display;
@ -34,10 +31,11 @@ struct egl_compositor {
struct wl_display *wl_display; struct wl_display *wl_display;
int gem_fd; int gem_fd;
int width, height; int width, height;
struct pointer *pointer; struct egl_surface *pointer;
struct egl_surface *background;
}; };
struct surface_data { struct egl_surface {
GLuint texture; GLuint texture;
struct wl_map map; struct wl_map map;
EGLSurface surface; EGLSurface surface;
@ -195,11 +193,11 @@ pointer_path(cairo_t *cr, int x, int y)
cairo_close_path(cr); cairo_close_path(cr);
} }
static struct pointer * static struct egl_surface *
pointer_create(int x, int y, int width, int height) pointer_create(int x, int y, int width, int height)
{ {
const int hotspot_x = 16, hotspot_y = 16; const int hotspot_x = 16, hotspot_y = 16;
struct pointer *pointer; struct egl_surface *pointer;
cairo_surface_t *surface; cairo_surface_t *surface;
cairo_t *cr; cairo_t *cr;
int stride; int stride;
@ -244,41 +242,87 @@ pointer_create(int x, int y, int width, int height)
pointer->map.y = y; pointer->map.y = y;
pointer->map.width = width; pointer->map.width = width;
pointer->map.height = height; pointer->map.height = height;
pointer->surface = EGL_NO_SURFACE;
return pointer; return pointer;
} }
static void static void
pointer_destroy(struct pointer *pointer) egl_surface_destroy(struct egl_surface *es, struct egl_compositor *ec)
{ {
glDeleteTextures(1, &pointer->texture); glDeleteTextures(1, &es->texture);
free(pointer); 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)
{
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 static void
draw_surface(struct wl_map *map, GLuint texture) draw_surface(struct egl_surface *es)
{ {
GLint vertices[12]; GLint vertices[12];
GLint tex_coords[12] = { 0, 0, 0, 1, 1, 0, 1, 1 }; GLint tex_coords[12] = { 0, 0, 0, 1, 1, 0, 1, 1 };
GLuint indices[4] = { 0, 1, 2, 3 }; GLuint indices[4] = { 0, 1, 2, 3 };
vertices[0] = map->x; vertices[0] = es->map.x;
vertices[1] = map->y; vertices[1] = es->map.y;
vertices[2] = 0; vertices[2] = 0;
vertices[3] = map->x; vertices[3] = es->map.x;
vertices[4] = map->y + map->height; vertices[4] = es->map.y + es->map.height;
vertices[5] = 0; vertices[5] = 0;
vertices[6] = map->x + map->width; vertices[6] = es->map.x + es->map.width;
vertices[7] = map->y; vertices[7] = es->map.y;
vertices[8] = 0; vertices[8] = 0;
vertices[9] = map->x + map->width; vertices[9] = es->map.x + es->map.width;
vertices[10] = map->y + map->height; vertices[10] = es->map.y + es->map.height;
vertices[11] = 0; vertices[11] = 0;
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, es->texture);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND); glEnable(GL_BLEND);
/* Assume pre-multiplied alpha for now, this probably /* Assume pre-multiplied alpha for now, this probably
@ -298,19 +342,21 @@ repaint(void *data)
struct egl_compositor *ec = data; struct egl_compositor *ec = data;
struct wl_surface_iterator *iterator; struct wl_surface_iterator *iterator;
struct wl_surface *surface; 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); iterator = wl_surface_iterator_create(ec->wl_display, 0);
while (wl_surface_iterator_next(iterator, &surface)) { while (wl_surface_iterator_next(iterator, &surface)) {
sd = wl_surface_get_data(surface); es = wl_surface_get_data(surface);
if (sd == NULL) if (es == NULL)
continue; continue;
draw_surface(&sd->map, sd->texture); draw_surface(es);
} }
wl_surface_iterator_destroy(iterator); wl_surface_iterator_destroy(iterator);
draw_surface(&ec->pointer->map, ec->pointer->texture); draw_surface(ec->pointer);
eglSwapBuffers(ec->display, ec->surface); eglSwapBuffers(ec->display, ec->surface);
@ -339,16 +385,16 @@ static void
notify_surface_create(struct wl_compositor *compositor, notify_surface_create(struct wl_compositor *compositor,
struct wl_surface *surface) struct wl_surface *surface)
{ {
struct surface_data *sd; struct egl_surface *es;
sd = malloc(sizeof *sd); es = malloc(sizeof *es);
if (sd == NULL) if (es == NULL)
return; return;
sd->surface = EGL_NO_SURFACE; es->surface = EGL_NO_SURFACE;
wl_surface_set_data(surface, sd); wl_surface_set_data(surface, es);
glGenTextures(1, &sd->texture); glGenTextures(1, &es->texture);
} }
static void static void
@ -356,18 +402,13 @@ notify_surface_destroy(struct wl_compositor *compositor,
struct wl_surface *surface) struct wl_surface *surface)
{ {
struct egl_compositor *ec = (struct egl_compositor *) compositor; struct egl_compositor *ec = (struct egl_compositor *) compositor;
struct surface_data *sd; struct egl_surface *es;
sd = wl_surface_get_data(surface); es = wl_surface_get_data(surface);
if (sd == NULL) if (es == NULL)
return; return;
if (sd->surface != EGL_NO_SURFACE) egl_surface_destroy(es, ec);
eglDestroySurface(ec->display, sd->surface);
glDeleteTextures(1, &sd->texture);
free(sd);
schedule_repaint(ec); schedule_repaint(ec);
} }
@ -378,27 +419,27 @@ notify_surface_attach(struct wl_compositor *compositor,
uint32_t width, uint32_t height, uint32_t stride) uint32_t width, uint32_t height, uint32_t stride)
{ {
struct egl_compositor *ec = (struct egl_compositor *) compositor; struct egl_compositor *ec = (struct egl_compositor *) compositor;
struct surface_data *sd; struct egl_surface *es;
sd = wl_surface_get_data(surface); es = wl_surface_get_data(surface);
if (sd == NULL) if (es == NULL)
return; return;
if (sd->surface != EGL_NO_SURFACE) if (es->surface != EGL_NO_SURFACE)
eglDestroySurface(ec->display, sd->surface); eglDestroySurface(ec->display, es->surface);
/* FIXME: We need to use a single buffer config without depth /* FIXME: We need to use a single buffer config without depth
* or stencil buffers here to keep egl from creating auxillary * or stencil buffers here to keep egl from creating auxillary
* buffers for the pixmap here. */ * buffers for the pixmap here. */
sd->surface = eglCreateSurfaceForName(ec->display, ec->config, es->surface = eglCreateSurfaceForName(ec->display, ec->config,
name, width, height, stride, NULL); 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); 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_WRAP_R, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_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); schedule_repaint(ec);
} }
@ -408,13 +449,13 @@ notify_surface_map(struct wl_compositor *compositor,
struct wl_surface *surface, struct wl_map *map) struct wl_surface *surface, struct wl_map *map)
{ {
struct egl_compositor *ec = (struct egl_compositor *) compositor; struct egl_compositor *ec = (struct egl_compositor *) compositor;
struct surface_data *sd; struct egl_surface *es;
sd = wl_surface_get_data(surface); es = wl_surface_get_data(surface);
if (sd == NULL) if (es == NULL)
return; return;
sd->map = *map; es->map = *map;
schedule_repaint(ec); schedule_repaint(ec);
} }
@ -428,9 +469,9 @@ notify_surface_copy(struct wl_compositor *compositor,
{ {
struct egl_compositor *ec = (struct egl_compositor *) compositor; struct egl_compositor *ec = (struct egl_compositor *) compositor;
EGLSurface src; 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 /* FIXME: glCopyPixels should work, but then we'll have to
* call eglMakeCurrent to set up the src and dest surfaces * 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, src = eglCreateSurfaceForName(ec->display, ec->config,
name, x + width, y + height, stride, NULL); 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); src, GL_FRONT_LEFT, x, y, width, height);
schedule_repaint(ec); schedule_repaint(ec);
} }
@ -485,6 +526,7 @@ wl_compositor_create(struct wl_display *display)
EGLConfig configs[64]; EGLConfig configs[64];
EGLint major, minor, count; EGLint major, minor, count;
struct egl_compositor *ec; struct egl_compositor *ec;
const char *filename;
ec = malloc(sizeof *ec); ec = malloc(sizeof *ec);
if (ec == NULL) if (ec == NULL)
@ -538,6 +580,10 @@ wl_compositor_create(struct wl_display *display)
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glClearColor(0.0, 0.05, 0.2, 0.0); 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->pointer = pointer_create(100, 100, 64, 64);
ec->gem_fd = open(gem_device, O_RDWR); ec->gem_fd = open(gem_device, O_RDWR);

Loading…
Cancel
Save