Load and draw background in compositor.
This commit is contained in:
parent
4c9f2c9b1a
commit
aa5b5bed73
4
Makefile
4
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)
|
||||
|
||||
|
160
egl-compositor.c
160
egl-compositor.c
@ -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"
|
||||
@ -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, &pointer->texture);
|
||||
free(pointer);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user