mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-08 13:29:47 -05:00
Load and draw background in compositor.
This commit is contained in:
parent
4c9f2c9b1a
commit
aa5b5bed73
2 changed files with 105 additions and 59 deletions
4
Makefile
4
Makefile
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
160
egl-compositor.c
160
egl-compositor.c
|
|
@ -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…
Add table
Add a link
Reference in a new issue