Bunch of new stuff: simple compositor, cairo+gem use in client, events.

This commit is contained in:
Kristian Høgsberg 2008-10-07 10:10:36 -04:00
parent 33bea964ca
commit a67a71a7cf
9 changed files with 714 additions and 182 deletions

184
client.c
View file

@ -1,109 +1,135 @@
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <i915_drm.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <ctype.h>
#include <math.h>
#include <cairo.h>
#include "wayland-client.h"
static const char gem_device[] = "/dev/dri/card0";
static const char socket_name[] = "\0wayland";
struct method {
const char *name;
uint32_t opcode;
};
static const struct method display_methods[] = {
{ "get_interface", 0 },
{ "create_surface", 1 },
{ NULL }
};
static const struct method surface_methods[] = {
{ "get_interface", 0 },
{ "post", 1 },
{ NULL }
};
struct interface {
const char *name;
const struct method *methods;
};
static const struct interface interfaces[] = {
{ "display", display_methods },
{ "surface", surface_methods },
{ NULL },
};
int send_request(int sock, const char *buffer, int buffer_len)
static uint32_t name_cairo_surface(int fd, cairo_surface_t *surface)
{
const struct method *methods;
char interface[32], method[32];
uint32_t request[3], id, new_id;
int i;
struct drm_i915_gem_create create;
struct drm_gem_flink flink;
struct drm_i915_gem_pwrite pwrite;
int32_t width, height, stride;
if (sscanf(buffer, "%d/%32[^:]:%32s %d\n",
&id, interface, method, &new_id) != 4) {
printf("invalid input, expected <id>/<interface>:<method>\n");
return -1;
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;
}
printf("got object id %d, interface \"%s\", name \"%s\"\n",
id, interface, method);
for (i = 0; interfaces[i].name != NULL; i++) {
if (strcmp(interfaces[i].name, interface) == 0)
break;
}
if (interfaces[i].name == NULL) {
printf("unknown interface \"%s\"\n", interface);
return -1;
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;
}
methods = interfaces[i].methods;
for (i = 0; methods[i].name != NULL; i++) {
if (strcmp(methods[i].name, method) == 0)
break;
flink.handle = create.handle;
if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
fprintf(stderr, "gem flink failed: %m\n");
return 0;
}
if (methods[i].name == NULL) {
printf("unknown request \"%s\"\n", method);
return -1;
#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
request[0] = id;
request[1] = methods[i].opcode;
request[2] = new_id;
return flink.name;
}
return write(sock, request, sizeof request);
static void *
draw_stuff(int width, int height)
{
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
width, height);
cr = cairo_create(surface);
cairo_arc(cr, width / 2, height / 2, width / 2 - 10, 0, 2 * M_PI);
cairo_set_source_rgb(cr, 1, 0, 0);
cairo_fill_preserve(cr);
cairo_set_source_rgb(cr, 1, 1, 0);
cairo_stroke(cr);
cairo_arc(cr, width / 2, height / 2, width / 4 - 10, 0, 2 * M_PI);
cairo_set_source_rgb(cr, 0, 0, 1);
cairo_fill_preserve(cr);
cairo_set_source_rgb(cr, 1, 1, 0);
cairo_stroke(cr);
cairo_destroy(cr);
return surface;
}
int main(int argc, char *argv[])
{
struct sockaddr_un name;
socklen_t size;
int sock, len;
char buffer[256];
struct wl_connection *connection;
struct wl_display *display;
struct wl_surface *surface;
int width = 300, height = 300, fd;
uint32_t name;
cairo_surface_t *s;
sock = socket(PF_LOCAL, SOCK_STREAM, 0);
if (sock < 0)
fd = open(gem_device, O_RDWR);
if (fd < 0) {
fprintf(stderr, "drm open failed: %m\n");
return -1;
}
name.sun_family = AF_LOCAL;
memcpy(name.sun_path, socket_name, sizeof socket_name);
size = offsetof (struct sockaddr_un, sun_path) + sizeof socket_name;
if (connect (sock, (struct sockaddr *) &name, size) < 0)
connection = wl_connection_create(socket_name);
if (connection == NULL) {
fprintf(stderr, "failed to create connection: %m\n");
return -1;
}
while (len = read(STDIN_FILENO, buffer, sizeof buffer), len > 0)
if (send_request(sock, buffer, len) < 0)
break;
display = wl_connection_get_display(connection);
surface = wl_display_create_surface(display);
s = draw_stuff(width, height);
name = name_cairo_surface(fd, s);
wl_surface_attach(surface, name, width, height,
cairo_image_surface_get_stride(s));
if (wl_connection_flush(connection) < 0) {
fprintf(stderr, "flush error: %m\n");
return -1;
}
while (1)
wl_connection_iterate(connection);
return 0;
}