From 5a27f3e6a787be874e0415eda184b0ee01b95a39 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Sun, 2 Nov 2008 10:55:25 -0500 Subject: [PATCH] Add a new client that draws a pointer. --- Makefile | 3 +- egl-compositor.c | 2 +- pointer.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ wayland-client.c | 26 ++++++--- wayland-client.h | 10 ++++ 5 files changed, 195 insertions(+), 8 deletions(-) create mode 100644 pointer.c diff --git a/Makefile b/Makefile index 42d6765..84b65aa 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CFLAGS += -Wall -g $(shell pkg-config --cflags libffi libdrm) LDLIBS += $(shell pkg-config --libs libffi libdrm) -clients = flower +clients = flower pointer all : wayland $(clients) @@ -18,6 +18,7 @@ libwayland.so : $(libwayland_objs) gcc -o $@ $(libwayland_objs) -shared flower_objs = flower.o +pointer_objs = pointer.o $(clients) : CFLAGS += $(shell pkg-config --cflags cairo) $(clients) : LDLIBS += $(shell pkg-config --libs cairo) diff --git a/egl-compositor.c b/egl-compositor.c index 6f501e1..3489215 100644 --- a/egl-compositor.c +++ b/egl-compositor.c @@ -40,7 +40,7 @@ repaint(void *data) struct wl_surface *surface; struct surface_data *sd; GLint vertices[12]; - GLint tex_coords[8] = { 1, 0, 1, 1, 0, 0, 0, 1 }; + GLint tex_coords[12] = { 0, 0, 0, 1, 1, 0, 1, 1 }; GLuint indices[4] = { 0, 1, 2, 3 }; /* This part is where we actually copy the buffer to screen. diff --git a/pointer.c b/pointer.c new file mode 100644 index 0000000..9571358 --- /dev/null +++ b/pointer.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wayland-client.h" + +static const char gem_device[] = "/dev/dri/card0"; +static const char socket_name[] = "\0wayland"; + +static uint32_t name_cairo_surface(int fd, cairo_surface_t *surface) +{ + struct drm_i915_gem_create create; + struct drm_gem_flink flink; + struct drm_i915_gem_pwrite pwrite; + int32_t width, height, stride; + + width = cairo_image_surface_get_width(surface); + height = cairo_image_surface_get_height(surface); + stride = cairo_image_surface_get_stride(surface); + + memset(&create, 0, sizeof(create)); + create.size = height * stride; + + if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) { + fprintf(stderr, "gem create failed: %m\n"); + return 0; + } + + pwrite.handle = create.handle; + pwrite.offset = 0; + pwrite.size = height * stride; + pwrite.data_ptr = (uint64_t) (uintptr_t) + cairo_image_surface_get_data(surface); + if (ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite) < 0) { + fprintf(stderr, "gem pwrite failed: %m\n"); + return 0; + } + + flink.handle = create.handle; + if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) { + fprintf(stderr, "gem flink failed: %m\n"); + return 0; + } + +#if 0 + /* We need to hold on to the handle until the server has received + * the attach request... we probably need a confirmation event. + * I guess the breadcrumb idea will suffice. */ + struct drm_gem_close close; + close.handle = create.handle; + if (ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close) < 0) { + fprintf(stderr, "gem close failed: %m\n"); + return 0; + } +#endif + + return flink.name; +} + +static void * +draw_pointer(int width, int height) +{ + const int d = 2, end = 4, tx = 2, ty = 6, dx = 5, dy = 4; + cairo_surface_t *surface; + cairo_t *cr; + + surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, + width, height); + + cr = cairo_create(surface); + cairo_set_line_width (cr, d); + cairo_move_to(cr, d, d); + cairo_line_to(cr, d + tx, d + ty); + cairo_line_to(cr, d + dx, d + dy); + cairo_line_to(cr, width - end, height - d); + cairo_line_to(cr, width - d, height - end); + cairo_line_to(cr, d + dy, d + dx); + cairo_line_to(cr, d + ty, d + tx); + cairo_close_path(cr); + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_stroke_preserve(cr); + cairo_set_source_rgb(cr, 1, 0, 0); + cairo_fill(cr); + + cairo_destroy(cr); + + return surface; +} + +static int +connection_update(struct wl_connection *connection, + uint32_t mask, void *data) +{ + return 0; +} + +struct pointer { + int width, height; + struct wl_surface *surface; +}; + +void event_handler(struct wl_display *display, + uint32_t opcode, + uint32_t arg1, uint32_t arg2, void *data) +{ + struct pointer *pointer = data; + + wl_surface_map(pointer->surface, arg1, arg2, pointer->width, pointer->height); + +} + +int main(int argc, char *argv[]) +{ + struct wl_display *display; + struct pointer pointer; + int fd; + uint32_t name; + cairo_surface_t *s; + + srandom(time(NULL)); + + fd = open(gem_device, O_RDWR); + if (fd < 0) { + fprintf(stderr, "drm open failed: %m\n"); + return -1; + } + + display = wl_display_create(socket_name, + connection_update, NULL); + if (display == NULL) { + fprintf(stderr, "failed to create display: %m\n"); + return -1; + } + + pointer.width = 16; + pointer.height = 16; + pointer.surface = wl_display_create_surface(display); + + s = draw_pointer(pointer.width, pointer.height); + name = name_cairo_surface(fd, s); + + wl_surface_attach(pointer.surface, name, + pointer.width, pointer.height, + cairo_image_surface_get_stride(s)); + + wl_display_set_event_handler(display, event_handler, &pointer); + + while (1) + wl_display_iterate(display, + WL_CONNECTION_WRITABLE | + WL_CONNECTION_READABLE); + + return 0; +} diff --git a/wayland-client.c b/wayland-client.c index a12e36b..8f673cc 100644 --- a/wayland-client.c +++ b/wayland-client.c @@ -25,6 +25,9 @@ struct wl_display { struct wl_connection *connection; int fd; uint32_t id; + + wl_display_event_func_t event_handler; + void *event_handler_data; }; struct wl_surface { @@ -96,14 +99,15 @@ wl_display_get_fd(struct wl_display *display) } static void -handle_event(struct wl_connection *connection, uint32_t opcode, uint32_t size) +handle_event(struct wl_display *display, uint32_t opcode, uint32_t size) { uint32_t p[4]; - wl_connection_copy(connection, p, size); - printf("signal from object %d, opcode %d, size %d, args: %d, %d\n", - p[0], opcode, size, p[2], p[3]); - wl_connection_consume(connection, size); + wl_connection_copy(display->connection, p, size); + if (display->event_handler != NULL) + display->event_handler(display, opcode, p[2], p[3], + display->event_handler_data); + wl_connection_consume(display->connection, size); } void @@ -123,7 +127,7 @@ wl_display_iterate(struct wl_display *display, uint32_t mask) if (len < size) break; - handle_event(display->connection, opcode, size); + handle_event(display, opcode, size); len -= size; } @@ -133,6 +137,16 @@ wl_display_iterate(struct wl_display *display, uint32_t mask) } } +void +wl_display_set_event_handler(struct wl_display *display, + wl_display_event_func_t handler, + void *data) +{ + /* FIXME: This needs something more generic... */ + display->event_handler = handler; + display->event_handler_data = data; +} + #define WL_DISPLAY_CREATE_SURFACE 0 struct wl_surface * diff --git a/wayland-client.h b/wayland-client.h index 843b43f..ce33b7b 100644 --- a/wayland-client.h +++ b/wayland-client.h @@ -12,6 +12,16 @@ void wl_display_destroy(struct wl_display *display); int wl_display_get_fd(struct wl_display *display); void wl_display_iterate(struct wl_display *display, uint32_t mask); +typedef void (*wl_display_event_func_t)(struct wl_display *display, + uint32_t opcode, + uint32_t arg1, uint32_t arg2, + void *data); + +void wl_display_set_event_handler(struct wl_display *display, + wl_display_event_func_t handler, + void *data); + + struct wl_surface * wl_display_create_surface(struct wl_display *display); -- 2.7.4