#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;
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;
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;
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
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);
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
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);
}
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);
}
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);
}
{
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
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);
}
EGLConfig configs[64];
EGLint major, minor, count;
struct egl_compositor *ec;
+ const char *filename;
ec = malloc(sizeof *ec);
if (ec == NULL)
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);