|
|
|
@ -9,15 +9,22 @@ |
|
|
|
|
#include <fcntl.h> |
|
|
|
|
#include <unistd.h> |
|
|
|
|
#include <signal.h> |
|
|
|
|
#include <cairo.h> |
|
|
|
|
#include <png.h> |
|
|
|
|
|
|
|
|
|
#include "wayland.h" |
|
|
|
|
#include "cairo-util.h" |
|
|
|
|
|
|
|
|
|
#include <GL/gl.h> |
|
|
|
|
#include <eagle.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; |
|
|
|
@ -27,6 +34,7 @@ struct egl_compositor { |
|
|
|
|
struct wl_display *wl_display; |
|
|
|
|
int gem_fd; |
|
|
|
|
int width, height; |
|
|
|
|
struct pointer *pointer; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct surface_data { |
|
|
|
@ -171,6 +179,119 @@ screenshot(struct egl_compositor *ec) |
|
|
|
|
free(data); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
pointer_path(cairo_t *cr, int x, int y) |
|
|
|
|
{ |
|
|
|
|
const int end = 3, tx = 4, ty = 12, dx = 5, dy = 10; |
|
|
|
|
const int width = 16, height = 16; |
|
|
|
|
|
|
|
|
|
cairo_move_to(cr, x, y); |
|
|
|
|
cairo_line_to(cr, x + tx, y + ty); |
|
|
|
|
cairo_line_to(cr, x + dx, y + dy); |
|
|
|
|
cairo_line_to(cr, x + width - end, y + height); |
|
|
|
|
cairo_line_to(cr, x + width, y + height - end); |
|
|
|
|
cairo_line_to(cr, x + dy, y + dx); |
|
|
|
|
cairo_line_to(cr, x + ty, y + tx); |
|
|
|
|
cairo_close_path(cr); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static struct pointer * |
|
|
|
|
pointer_create(int x, int y, int width, int height) |
|
|
|
|
{ |
|
|
|
|
const int hotspot_x = 16, hotspot_y = 16; |
|
|
|
|
struct pointer *pointer; |
|
|
|
|
cairo_surface_t *surface; |
|
|
|
|
cairo_t *cr; |
|
|
|
|
int stride; |
|
|
|
|
void *data; |
|
|
|
|
|
|
|
|
|
pointer = malloc(sizeof *pointer); |
|
|
|
|
if (pointer == NULL) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, |
|
|
|
|
width, height); |
|
|
|
|
|
|
|
|
|
cr = cairo_create(surface); |
|
|
|
|
pointer_path(cr, hotspot_x + 5, hotspot_y + 4); |
|
|
|
|
cairo_set_line_width (cr, 2); |
|
|
|
|
cairo_set_source_rgb(cr, 0, 0, 0); |
|
|
|
|
cairo_stroke_preserve(cr); |
|
|
|
|
cairo_fill(cr); |
|
|
|
|
blur_surface(surface, width); |
|
|
|
|
|
|
|
|
|
pointer_path(cr, hotspot_x, hotspot_y); |
|
|
|
|
cairo_stroke_preserve(cr); |
|
|
|
|
cairo_set_source_rgb(cr, 1, 1, 1); |
|
|
|
|
cairo_fill(cr); |
|
|
|
|
cairo_destroy(cr); |
|
|
|
|
|
|
|
|
|
stride = cairo_image_surface_get_stride(surface); |
|
|
|
|
data = cairo_image_surface_get_data(surface); |
|
|
|
|
|
|
|
|
|
glGenTextures(1, &pointer->texture); |
|
|
|
|
glBindTexture(GL_TEXTURE_2D, pointer->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_RGBA, width, height, 0, |
|
|
|
|
GL_BGRA, GL_UNSIGNED_BYTE, data); |
|
|
|
|
|
|
|
|
|
cairo_surface_destroy(surface); |
|
|
|
|
|
|
|
|
|
pointer->map.x = x; |
|
|
|
|
pointer->map.y = y; |
|
|
|
|
pointer->map.width = width; |
|
|
|
|
pointer->map.height = height; |
|
|
|
|
|
|
|
|
|
return pointer; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
pointer_destroy(struct pointer *pointer) |
|
|
|
|
{ |
|
|
|
|
glDeleteTextures(1, &pointer->texture); |
|
|
|
|
free(pointer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
draw_surface(struct wl_map *map, GLuint texture) |
|
|
|
|
{ |
|
|
|
|
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[2] = 0; |
|
|
|
|
|
|
|
|
|
vertices[3] = map->x; |
|
|
|
|
vertices[4] = map->y + map->height; |
|
|
|
|
vertices[5] = 0; |
|
|
|
|
|
|
|
|
|
vertices[6] = map->x + map->width; |
|
|
|
|
vertices[7] = map->y; |
|
|
|
|
vertices[8] = 0; |
|
|
|
|
|
|
|
|
|
vertices[9] = map->x + map->width; |
|
|
|
|
vertices[10] = map->y + map->height; |
|
|
|
|
vertices[11] = 0; |
|
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texture); |
|
|
|
|
glEnable(GL_TEXTURE_2D); |
|
|
|
|
glEnable(GL_BLEND); |
|
|
|
|
/* Assume pre-multiplied alpha for now, this probably
|
|
|
|
|
* needs to be a wayland visual type of thing. */ |
|
|
|
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); |
|
|
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY); |
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
|
|
|
|
glVertexPointer(3, GL_INT, 0, vertices); |
|
|
|
|
glTexCoordPointer(2, GL_INT, 0, tex_coords); |
|
|
|
|
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, indices); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
repaint(void *data) |
|
|
|
|
{ |
|
|
|
@ -178,9 +299,6 @@ repaint(void *data) |
|
|
|
|
struct wl_surface_iterator *iterator; |
|
|
|
|
struct wl_surface *surface; |
|
|
|
|
struct surface_data *sd; |
|
|
|
|
GLint vertices[12]; |
|
|
|
|
GLint tex_coords[12] = { 0, 0, 0, 1, 1, 0, 1, 1 }; |
|
|
|
|
GLuint indices[4] = { 0, 1, 2, 3 }; |
|
|
|
|
|
|
|
|
|
iterator = wl_surface_iterator_create(ec->wl_display, 0); |
|
|
|
|
while (wl_surface_iterator_next(iterator, &surface)) { |
|
|
|
@ -188,37 +306,12 @@ repaint(void *data) |
|
|
|
|
if (sd == NULL) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
vertices[0] = sd->map.x; |
|
|
|
|
vertices[1] = sd->map.y; |
|
|
|
|
vertices[2] = 0; |
|
|
|
|
|
|
|
|
|
vertices[3] = sd->map.x; |
|
|
|
|
vertices[4] = sd->map.y + sd->map.height; |
|
|
|
|
vertices[5] = 0; |
|
|
|
|
|
|
|
|
|
vertices[6] = sd->map.x + sd->map.width; |
|
|
|
|
vertices[7] = sd->map.y; |
|
|
|
|
vertices[8] = 0; |
|
|
|
|
|
|
|
|
|
vertices[9] = sd->map.x + sd->map.width; |
|
|
|
|
vertices[10] = sd->map.y + sd->map.height; |
|
|
|
|
vertices[11] = 0; |
|
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, sd->texture); |
|
|
|
|
glEnable(GL_TEXTURE_2D); |
|
|
|
|
glEnable(GL_BLEND); |
|
|
|
|
/* Assume pre-multiplied alpha for now, this probably
|
|
|
|
|
* needs to be a wayland visual type of thing. */ |
|
|
|
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); |
|
|
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY); |
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
|
|
|
|
glVertexPointer(3, GL_INT, 0, vertices); |
|
|
|
|
glTexCoordPointer(2, GL_INT, 0, tex_coords); |
|
|
|
|
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, indices); |
|
|
|
|
draw_surface(&sd->map, sd->texture); |
|
|
|
|
} |
|
|
|
|
wl_surface_iterator_destroy(iterator); |
|
|
|
|
|
|
|
|
|
draw_surface(&ec->pointer->map, ec->pointer->texture); |
|
|
|
|
|
|
|
|
|
eglSwapBuffers(ec->display, ec->surface); |
|
|
|
|
|
|
|
|
|
if (do_screenshot) { |
|
|
|
@ -363,13 +456,25 @@ notify_surface_damage(struct wl_compositor *compositor, |
|
|
|
|
schedule_repaint(ec); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
notify_pointer_motion(struct wl_compositor *compositor, |
|
|
|
|
struct wl_object *source, int x, int y) |
|
|
|
|
{ |
|
|
|
|
struct egl_compositor *ec = (struct egl_compositor *) compositor; |
|
|
|
|
|
|
|
|
|
ec->pointer->map.x = x; |
|
|
|
|
ec->pointer->map.y = y; |
|
|
|
|
schedule_repaint(ec); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const struct wl_compositor_interface interface = { |
|
|
|
|
notify_surface_create, |
|
|
|
|
notify_surface_destroy, |
|
|
|
|
notify_surface_attach, |
|
|
|
|
notify_surface_map, |
|
|
|
|
notify_surface_copy, |
|
|
|
|
notify_surface_damage |
|
|
|
|
notify_surface_damage, |
|
|
|
|
notify_pointer_motion |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const char gem_device[] = "/dev/dri/card0"; |
|
|
|
@ -433,6 +538,8 @@ wl_compositor_create(struct wl_display *display) |
|
|
|
|
glMatrixMode(GL_MODELVIEW); |
|
|
|
|
glClearColor(0.0, 0.05, 0.2, 0.0); |
|
|
|
|
|
|
|
|
|
ec->pointer = pointer_create(100, 100, 64, 64); |
|
|
|
|
|
|
|
|
|
ec->gem_fd = open(gem_device, O_RDWR); |
|
|
|
|
if (ec->gem_fd < 0) { |
|
|
|
|
fprintf(stderr, "failed to open drm device\n"); |
|
|
|
|