mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-31 22:25:25 -04:00
Bunch of new stuff: simple compositor, cairo+gem use in client, events.
This commit is contained in:
parent
33bea964ca
commit
a67a71a7cf
9 changed files with 714 additions and 182 deletions
184
client.c
184
client.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue