Introduce 'buffer' object for attaching, image cahce and cursor images

The buffer object is created by a 'drm' object, which encapsulates the
buffer sharing and authentication mechanism.  Once the buffer is created
it can be attached to a surface.
dev
Kristian Høgsberg 14 years ago
parent 5b0079aed5
commit 5fcd0aa58e
  1. 3
      Makefile
  2. 27
      clients/window.c
  3. 35
      compositor-drm.c
  4. 32
      compositor-x11.c
  5. 82
      compositor.c
  6. 23
      compositor.h
  7. 36
      protocol.xml
  8. 61
      wayland-client.c
  9. 16
      wayland-client.h
  10. 7
      wayland-util.h
  11. 76
      wayland.c
  12. 31
      wayland.h

@ -49,7 +49,8 @@ compositor : \
compositor-drm.o \ compositor-drm.o \
compositor-x11.o \ compositor-x11.o \
screenshooter.o \ screenshooter.o \
cairo-util.o cairo-util.o \
drm.o
compositor : CFLAGS += $(COMPOSITOR_CFLAGS) compositor : CFLAGS += $(COMPOSITOR_CFLAGS)
compositor : LDLIBS += ./libwayland-server.so $(COMPOSITOR_LIBS) -rdynamic -lrt -lEGL -lm compositor : LDLIBS += ./libwayland-server.so $(COMPOSITOR_LIBS) -rdynamic -lrt -lEGL -lm

@ -53,6 +53,7 @@ struct display {
struct wl_display *display; struct wl_display *display;
struct wl_compositor *compositor; struct wl_compositor *compositor;
struct wl_shell *shell; struct wl_shell *shell;
struct wl_drm *drm;
struct wl_output *output; struct wl_output *output;
struct rectangle screen_allocation; struct rectangle screen_allocation;
EGLDisplay dpy; EGLDisplay dpy;
@ -178,6 +179,8 @@ static void
window_attach_surface(struct window *window) window_attach_surface(struct window *window)
{ {
struct wl_visual *visual; struct wl_visual *visual;
struct display *display = window->display;
struct wl_buffer *buffer;
struct surface_data *data; struct surface_data *data;
EGLint name, stride; EGLint name, stride;
@ -192,14 +195,17 @@ window_attach_surface(struct window *window)
eglExportDRMImageMESA(window->display->dpy, eglExportDRMImageMESA(window->display->dpy,
data->image, &name, NULL, &stride); data->image, &name, NULL, &stride);
visual = wl_display_get_premultiplied_argb_visual(window->display->display); visual = wl_display_get_premultiplied_argb_visual(display->display);
wl_surface_attach(window->surface, buffer = wl_drm_create_buffer(display->drm,
name, name,
window->allocation.width, window->allocation.width,
window->allocation.height, window->allocation.height,
stride, stride,
visual); visual);
wl_surface_attach(window->surface, buffer);
wl_buffer_destroy(buffer);
wl_surface_map(window->surface, wl_surface_map(window->surface,
window->allocation.x, window->allocation.x,
window->allocation.y, window->allocation.y,
@ -679,15 +685,22 @@ window_create(struct display *display, const char *title,
} }
static void static void
display_handle_device(void *data, drm_handle_device(void *data, struct wl_drm *drm, const char *device)
struct wl_compositor *compositor,
const char *device)
{ {
struct display *d = data; struct display *d = data;
d->device_name = strdup(device); d->device_name = strdup(device);
} }
static void drm_handle_authenticated(void *data, struct wl_drm *drm)
{
}
static const struct wl_drm_listener drm_listener = {
drm_handle_device,
drm_handle_authenticated
};
static void static void
display_handle_acknowledge(void *data, display_handle_acknowledge(void *data,
struct wl_compositor *compositor, struct wl_compositor *compositor,
@ -726,7 +739,6 @@ display_handle_frame(void *data,
} }
static const struct wl_compositor_listener compositor_listener = { static const struct wl_compositor_listener compositor_listener = {
display_handle_device,
display_handle_acknowledge, display_handle_acknowledge,
display_handle_frame, display_handle_frame,
}; };
@ -785,6 +797,9 @@ display_handle_global(struct wl_display *display,
} else if (wl_object_implements(object, "shell", 1)) { } else if (wl_object_implements(object, "shell", 1)) {
d->shell = (struct wl_shell *) object; d->shell = (struct wl_shell *) object;
wl_shell_add_listener(d->shell, &shell_listener, d); wl_shell_add_listener(d->shell, &shell_listener, d);
} else if (wl_object_implements(object, "drm", 1)) {
d->drm = (struct wl_drm *) object;
wl_drm_add_listener(d->drm, &drm_listener, d);
} }
} }

@ -41,7 +41,6 @@ struct drm_compositor {
struct udev *udev; struct udev *udev;
struct wl_event_source *drm_source; struct wl_event_source *drm_source;
int drm_fd;
struct wl_event_source *term_signal_source; struct wl_event_source *term_signal_source;
@ -272,7 +271,7 @@ drm_compositor_present(struct wlsc_compositor *ec)
GL_RENDERBUFFER, GL_RENDERBUFFER,
output->rbo[output->current]); output->rbo[output->current]);
drmModePageFlip(c->drm_fd, output->crtc_id, drmModePageFlip(c->base.drm.fd, output->crtc_id,
output->fb_id[output->current ^ 1], output->fb_id[output->current ^ 1],
DRM_MODE_PAGE_FLIP_EVENT, output); DRM_MODE_PAGE_FLIP_EVENT, output);
} }
@ -305,22 +304,25 @@ static int
init_egl(struct drm_compositor *ec, struct udev_device *device) init_egl(struct drm_compositor *ec, struct udev_device *device)
{ {
EGLint major, minor; EGLint major, minor;
const char *extensions; const char *extensions, *filename;
int fd;
static const EGLint context_attribs[] = { static const EGLint context_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2, EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE EGL_NONE
}; };
ec->base.base.device = strdup(udev_device_get_devnode(device)); filename = udev_device_get_devnode(device);
ec->drm_fd = open(ec->base.base.device, O_RDWR); fd = open(filename, O_RDWR);
if (ec->drm_fd < 0) { if (fd < 0) {
/* Probably permissions error */ /* Probably permissions error */
fprintf(stderr, "couldn't open %s, skipping\n", fprintf(stderr, "couldn't open %s, skipping\n",
udev_device_get_devnode(device)); udev_device_get_devnode(device));
return -1; return -1;
} }
ec->base.display = eglGetDRMDisplayMESA(ec->drm_fd); wlsc_drm_init(&ec->base, fd, filename);
ec->base.display = eglGetDRMDisplayMESA(ec->base.drm.fd);
if (ec->base.display == NULL) { if (ec->base.display == NULL) {
fprintf(stderr, "failed to create display\n"); fprintf(stderr, "failed to create display\n");
return -1; return -1;
@ -390,7 +392,7 @@ create_output_for_connector(struct drm_compositor *ec,
else else
mode = &builtin_1024x768; mode = &builtin_1024x768;
encoder = drmModeGetEncoder(ec->drm_fd, connector->encoders[0]); encoder = drmModeGetEncoder(ec->base.drm.fd, connector->encoders[0]);
if (encoder == NULL) { if (encoder == NULL) {
fprintf(stderr, "No encoder for connector.\n"); fprintf(stderr, "No encoder for connector.\n");
return -1; return -1;
@ -428,7 +430,7 @@ create_output_for_connector(struct drm_compositor *ec,
eglExportDRMImageMESA(ec->base.display, output->image[i], eglExportDRMImageMESA(ec->base.display, output->image[i],
NULL, &handle, &stride); NULL, &handle, &stride);
ret = drmModeAddFB(ec->drm_fd, ret = drmModeAddFB(ec->base.drm.fd,
output->base.width, output->base.height, output->base.width, output->base.height,
32, 32, stride, handle, &output->fb_id[i]); 32, 32, stride, handle, &output->fb_id[i]);
if (ret) { if (ret) {
@ -442,7 +444,7 @@ create_output_for_connector(struct drm_compositor *ec,
GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, GL_RENDERBUFFER,
output->rbo[output->current]); output->rbo[output->current]);
ret = drmModeSetCrtc(ec->drm_fd, output->crtc_id, ret = drmModeSetCrtc(ec->base.drm.fd, output->crtc_id,
output->fb_id[output->current ^ 1], 0, 0, output->fb_id[output->current ^ 1], 0, 0,
&output->connector_id, 1, &output->mode); &output->connector_id, 1, &output->mode);
if (ret) { if (ret) {
@ -462,14 +464,14 @@ create_outputs(struct drm_compositor *ec)
drmModeRes *resources; drmModeRes *resources;
int i; int i;
resources = drmModeGetResources(ec->drm_fd); resources = drmModeGetResources(ec->base.drm.fd);
if (!resources) { if (!resources) {
fprintf(stderr, "drmModeGetResources failed\n"); fprintf(stderr, "drmModeGetResources failed\n");
return -1; return -1;
} }
for (i = 0; i < resources->count_connectors; i++) { for (i = 0; i < resources->count_connectors; i++) {
connector = drmModeGetConnector(ec->drm_fd, resources->connectors[i]); connector = drmModeGetConnector(ec->base.drm.fd, resources->connectors[i]);
if (connector == NULL) if (connector == NULL)
continue; continue;
@ -498,7 +500,7 @@ static void on_enter_vt(int signal_number, void *data)
struct drm_output *output; struct drm_output *output;
int ret; int ret;
ret = drmSetMaster(ec->drm_fd); ret = drmSetMaster(ec->base.drm.fd);
if (ret) { if (ret) {
fprintf(stderr, "failed to set drm master\n"); fprintf(stderr, "failed to set drm master\n");
kill(0, SIGTERM); kill(0, SIGTERM);
@ -511,7 +513,7 @@ static void on_enter_vt(int signal_number, void *data)
ec->vt_active = 1; ec->vt_active = 1;
wl_list_for_each(output, &ec->base.output_list, base.link) { wl_list_for_each(output, &ec->base.output_list, base.link) {
ret = drmModeSetCrtc(ec->drm_fd, output->crtc_id, ret = drmModeSetCrtc(ec->base.drm.fd, output->crtc_id,
output->fb_id[output->current ^ 1], 0, 0, output->fb_id[output->current ^ 1], 0, 0,
&output->connector_id, 1, &output->mode); &output->connector_id, 1, &output->mode);
if (ret) if (ret)
@ -526,7 +528,7 @@ static void on_leave_vt(int signal_number, void *data)
struct drm_compositor *ec = data; struct drm_compositor *ec = data;
int ret; int ret;
ret = drmDropMaster(ec->drm_fd); ret = drmDropMaster(ec->base.drm.fd);
if (ret) { if (ret) {
fprintf(stderr, "failed to drop drm master\n"); fprintf(stderr, "failed to drop drm master\n");
kill(0, SIGTERM); kill(0, SIGTERM);
@ -644,6 +646,7 @@ drm_compositor_create(struct wl_display *display)
return NULL; return NULL;
} }
ec->base.wl_display = display;
if (init_egl(ec, device) < 0) { if (init_egl(ec, device) < 0) {
fprintf(stderr, "failed to initialize egl\n"); fprintf(stderr, "failed to initialize egl\n");
return NULL; return NULL;
@ -662,7 +665,7 @@ drm_compositor_create(struct wl_display *display)
loop = wl_display_get_event_loop(ec->base.wl_display); loop = wl_display_get_event_loop(ec->base.wl_display);
ec->drm_source = ec->drm_source =
wl_event_loop_add_fd(loop, ec->drm_fd, wl_event_loop_add_fd(loop, ec->base.drm.fd,
WL_EVENT_READABLE, on_drm_input, ec); WL_EVENT_READABLE, on_drm_input, ec);
setup_tty(ec, loop); setup_tty(ec, loop);
ec->base.present = drm_compositor_present; ec->base.present = drm_compositor_present;

@ -50,7 +50,6 @@ struct x11_compositor {
xcb_cursor_t null_cursor; xcb_cursor_t null_cursor;
int dri2_major; int dri2_major;
int dri2_minor; int dri2_minor;
int drm_fd;
struct wl_event_source *xcb_source; struct wl_event_source *xcb_source;
struct { struct {
xcb_atom_t wm_protocols; xcb_atom_t wm_protocols;
@ -104,6 +103,8 @@ dri2_connect(struct x11_compositor *c)
xcb_dri2_connect_reply_t *connect; xcb_dri2_connect_reply_t *connect;
xcb_dri2_connect_cookie_t connect_cookie; xcb_dri2_connect_cookie_t connect_cookie;
xcb_generic_error_t *error; xcb_generic_error_t *error;
char path[256];
int fd;
xcb_prefetch_extension_data (c->conn, &xcb_xfixes_id); xcb_prefetch_extension_data (c->conn, &xcb_xfixes_id);
xcb_prefetch_extension_data (c->conn, &xcb_dri2_id); xcb_prefetch_extension_data (c->conn, &xcb_dri2_id);
@ -152,17 +153,19 @@ dri2_connect(struct x11_compositor *c)
return -1; return -1;
} }
c->base.base.device = snprintf(path, sizeof path, "%.*s",
strndup(xcb_dri2_connect_device_name (connect), xcb_dri2_connect_device_name_length (connect),
xcb_dri2_connect_device_name_length (connect)); xcb_dri2_connect_device_name (connect));
if (c->base.base.device == NULL) {
free(connect); free(connect);
fd = open(path, O_RDWR);
if (fd < 0) {
fprintf(stderr,
"DRI2: could not open %s (%s)", path, strerror(errno));
return -1; return -1;
} }
free(connect);
return 0; return wlsc_drm_init(&c->base, fd, path);
} }
static int static int
@ -172,7 +175,7 @@ dri2_authenticate(struct x11_compositor *c)
xcb_dri2_authenticate_cookie_t authenticate_cookie; xcb_dri2_authenticate_cookie_t authenticate_cookie;
drm_magic_t magic; drm_magic_t magic;
if (drmGetMagic(c->drm_fd, &magic)) { if (drmGetMagic(c->base.drm.fd, &magic)) {
fprintf(stderr, "DRI2: failed to get drm magic"); fprintf(stderr, "DRI2: failed to get drm magic");
return -1; return -1;
} }
@ -207,18 +210,10 @@ x11_compositor_init_egl(struct x11_compositor *c)
if (dri2_connect(c) < 0) if (dri2_connect(c) < 0)
return -1; return -1;
c->drm_fd = open(c->base.base.device, O_RDWR);
if (c->drm_fd == -1) {
fprintf(stderr,
"DRI2: could not open %s (%s)", c->base.base.device,
strerror(errno));
return -1;
}
if (dri2_authenticate(c) < 0) if (dri2_authenticate(c) < 0)
return -1; return -1;
c->base.display = eglGetDRMDisplayMESA(c->drm_fd); c->base.display = eglGetDRMDisplayMESA(c->base.drm.fd);
if (c->base.display == NULL) { if (c->base.display == NULL) {
fprintf(stderr, "failed to create display\n"); fprintf(stderr, "failed to create display\n");
return -1; return -1;
@ -641,6 +636,7 @@ x11_compositor_create(struct wl_display *display)
x11_compositor_get_resources(c); x11_compositor_get_resources(c);
c->base.wl_display = display;
x11_compositor_init_egl(c); x11_compositor_init_egl(c);
/* Can't init base class until we have a current egl context */ /* Can't init base class until we have a current egl context */

@ -30,13 +30,6 @@
#include <time.h> #include <time.h>
#include <linux/input.h> #include <linux/input.h>
#define GL_GLEXT_PROTOTYPES
#define EGL_EGLEXT_PROTOTYPES
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "wayland.h" #include "wayland.h"
#include "wayland-server-protocol.h" #include "wayland-server-protocol.h"
#include "cairo-util.h" #include "cairo-util.h"
@ -180,14 +173,15 @@ wlsc_surface_create_from_cairo_surface(struct wlsc_compositor *ec,
} }
static void static void
wlsc_surface_destroy(struct wlsc_surface *surface, destroy_surface(struct wl_resource *resource, struct wl_client *client)
struct wlsc_compositor *compositor)
{ {
struct wlsc_surface *surface =
container_of(resource, struct wlsc_surface, base.base);
struct wlsc_compositor *compositor = surface->compositor;
struct wlsc_listener *l; struct wlsc_listener *l;
wl_list_remove(&surface->link); wl_list_remove(&surface->link);
glDeleteTextures(1, &surface->texture); glDeleteTextures(1, &surface->texture);
wl_client_remove_surface(surface->base.client, &surface->base);
wl_list_for_each(l, &compositor->surface_destroy_listener_list, link) wl_list_for_each(l, &compositor->surface_destroy_listener_list, link)
l->func(l, surface); l->func(l, surface);
@ -427,73 +421,26 @@ surface_destroy(struct wl_client *client,
struct wl_surface *surface) struct wl_surface *surface)
{ {
struct wlsc_surface *es = (struct wlsc_surface *) surface; struct wlsc_surface *es = (struct wlsc_surface *) surface;
struct wlsc_compositor *ec = es->compositor;
wlsc_surface_destroy(es, ec); wl_resource_destroy(&surface->base, client);
wlsc_compositor_schedule_repaint(ec); wlsc_compositor_schedule_repaint(es->compositor);
} }
static void static void
surface_attach(struct wl_client *client, surface_attach(struct wl_client *client,
struct wl_surface *surface, uint32_t name, struct wl_surface *surface, struct wl_buffer *buffer_base)
int32_t width, int32_t height, uint32_t stride,
struct wl_visual *visual)
{ {
struct wlsc_surface *es = (struct wlsc_surface *) surface; struct wlsc_surface *es = (struct wlsc_surface *) surface;
struct wlsc_compositor *ec = es->compositor; struct wlsc_buffer *buffer = (struct wlsc_buffer *) buffer_base;
EGLImageKHR image;
EGLint attribs[] = {
EGL_WIDTH, 0,
EGL_HEIGHT, 0,
EGL_IMAGE_STRIDE_MESA, 0,
EGL_IMAGE_FORMAT_MESA, EGL_IMAGE_FORMAT_ARGB8888_MESA,
EGL_NONE
};
attribs[1] = width;
attribs[3] = height;
attribs[5] = stride / 4;
image = eglCreateImageKHR(ec->display, ec->context,
EGL_DRM_IMAGE_MESA,
(EGLClientBuffer) name, attribs);
if (image == NULL) {
/* FIXME: Define a real exception event instead of
* abusing this one */
wl_client_post_event(client, ec->wl_display,
WL_DISPLAY_INVALID_OBJECT, 0);
fprintf(stderr, "failed to create image for name %d\n", name);
return;
}
if (visual == &ec->argb_visual)
es->visual = &ec->argb_visual;
else if (visual == &ec->premultiplied_argb_visual)
es->visual = &ec->premultiplied_argb_visual;
else if (visual == &ec->rgb_visual)
es->visual = &ec->rgb_visual;
else {
/* FIXME: Define a real exception event instead of
* abusing this one */
wl_client_post_event(client, ec->display,
WL_DISPLAY_INVALID_OBJECT, 0);
fprintf(stderr, "invalid visual in surface_attach\n");
return;
}
glBindTexture(GL_TEXTURE_2D, es->texture); glBindTexture(GL_TEXTURE_2D, es->texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image);
if (es->image) es->visual = buffer->visual;
eglDestroyImageKHR(ec->display, es->image);
es->image = image;
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, es->image);
} }
static void static void
@ -577,13 +524,17 @@ compositor_create_surface(struct wl_client *client,
struct wlsc_surface *surface; struct wlsc_surface *surface;
surface = malloc(sizeof *surface); surface = malloc(sizeof *surface);
if (surface == NULL) if (surface == NULL) {
/* FIXME: Send OOM event. */ wl_client_post_event(client,
(struct wl_object *) ec->wl_display,
WL_DISPLAY_NO_MEMORY, 0);
return; return;
}
wlsc_surface_init(surface, ec, NULL, 0, 0, 0, 0); wlsc_surface_init(surface, ec, NULL, 0, 0, 0, 0);
wl_list_insert(ec->surface_list.prev, &surface->link); wl_list_insert(ec->surface_list.prev, &surface->link);
surface->base.base.destroy = destroy_surface;
wl_client_add_surface(client, &surface->base, wl_client_add_surface(client, &surface->base,
&surface_interface, id); &surface_interface, id);
} }
@ -921,6 +872,7 @@ wlsc_input_device_init(struct wlsc_input_device *device,
device->base.implementation = NULL; device->base.implementation = NULL;
wl_display_add_object(ec->wl_display, &device->base); wl_display_add_object(ec->wl_display, &device->base);
wl_display_add_global(ec->wl_display, &device->base, NULL); wl_display_add_global(ec->wl_display, &device->base, NULL);
device->x = 100; device->x = 100;
device->y = 100; device->y = 100;
device->ec = ec; device->ec = ec;

@ -26,6 +26,10 @@
#include "wayland.h" #include "wayland.h"
#include "wayland-util.h" #include "wayland-util.h"
#define GL_GLEXT_PROTOTYPES
#define EGL_EGLEXT_PROTOTYPES
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h> #include <EGL/egl.h>
#include <EGL/eglext.h> #include <EGL/eglext.h>
@ -93,10 +97,23 @@ struct wlsc_input_device {
struct wlsc_listener listener; struct wlsc_listener listener;
}; };
struct wlsc_drm {
struct wl_object base;
int fd;
char *filename;
};
struct wlsc_buffer {
struct wl_buffer base;
EGLImageKHR image;
struct wl_visual *visual;
};
struct wlsc_compositor { struct wlsc_compositor {
struct wl_compositor base; struct wl_compositor base;
struct wl_visual argb_visual, premultiplied_argb_visual, rgb_visual; struct wl_visual argb_visual, premultiplied_argb_visual, rgb_visual;
struct wlsc_drm drm;
EGLDisplay display; EGLDisplay display;
EGLContext context; EGLContext context;
GLuint fbo, vbo; GLuint fbo, vbo;
@ -124,6 +141,7 @@ struct wlsc_compositor {
uint32_t focus; uint32_t focus;
void (*authenticate)(struct wlsc_compositor *c, uint32_t id);
void (*present)(struct wlsc_compositor *c); void (*present)(struct wlsc_compositor *c);
}; };
@ -138,13 +156,12 @@ struct wlsc_vector {
struct wlsc_surface { struct wlsc_surface {
struct wl_surface base; struct wl_surface base;
struct wlsc_compositor *compositor; struct wlsc_compositor *compositor;
struct wl_visual *visual;
GLuint texture; GLuint texture;
EGLImageKHR image;
int32_t x, y, width, height; int32_t x, y, width, height;
struct wl_list link; struct wl_list link;
struct wlsc_matrix matrix; struct wlsc_matrix matrix;
struct wlsc_matrix matrix_inv; struct wlsc_matrix matrix_inv;
struct wl_visual *visual;
}; };
void void
@ -170,6 +187,8 @@ wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
void void
wlsc_input_device_init(struct wlsc_input_device *device, wlsc_input_device_init(struct wlsc_input_device *device,
struct wlsc_compositor *ec); struct wlsc_compositor *ec);
int
wlsc_drm_init(struct wlsc_compositor *ec, int fd, const char *filename);
struct wlsc_compositor * struct wlsc_compositor *
x11_compositor_create(struct wl_display *display); x11_compositor_create(struct wl_display *display);

@ -32,10 +32,6 @@
<arg name="key" type="uint"/> <arg name="key" type="uint"/>
</request> </request>
<event name="device">
<arg name="name" type="string"/>
</event>
<event name="acknowledge"> <event name="acknowledge">
<arg name="key" type="uint"/> <arg name="key" type="uint"/>
<arg name="frame" type="uint"/> <arg name="frame" type="uint"/>
@ -47,6 +43,32 @@
</event> </event>
</interface> </interface>
<interface name="drm" version="1">
<!-- dri2 auth and create buffer -->
<request name="authenticate">
<arg name="id" type="uint"/>
</request>
<request name="create_buffer">
<arg name="id" type="new_id"/>
<arg name="name" type="uint"/>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
<arg name="stride" type="uint"/>
<arg name="visual" type="visual"/>
</request>
<event name="device">
<arg name="name" type="string"/>
</event>
<event name="authenticated"/>
</interface>
<interface name="buffer" version="1">
<request name="destroy"/>
</interface>
<interface name="shell" version="1"> <interface name="shell" version="1">
<request name="move"> <request name="move">
<arg name="surface" type="surface"/> <arg name="surface" type="surface"/>
@ -78,11 +100,7 @@
<request name="destroy"/> <request name="destroy"/>
<request name="attach"> <request name="attach">
<arg name="name" type="uint"/> <arg name="buffer" type="buffer"/>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
<arg name="stride" type="uint"/>
<arg name="visual" type="visual"/>
</request> </request>
<request name="map"> <request name="map">

@ -87,6 +87,14 @@ struct wl_shell {
struct wl_proxy proxy; struct wl_proxy proxy;
}; };
struct wl_drm {
struct wl_proxy proxy;
};
struct wl_buffer {
struct wl_proxy proxy;
};
struct wl_input_device { struct wl_input_device {
struct wl_proxy proxy; struct wl_proxy proxy;
}; };
@ -258,6 +266,49 @@ wl_shell_resize(struct wl_shell *shell,
WL_SHELL_RESIZE, surface, device, time, edges); WL_SHELL_RESIZE, surface, device, time, edges);
} }
WL_EXPORT int
wl_drm_add_listener(struct wl_drm *drm,
const struct wl_drm_listener *listener,
void *data)
{
return wl_proxy_add_listener(&drm->proxy,
(void (**)(void)) listener, data);
}
WL_EXPORT void
wl_drm_authenticate(struct wl_drm *drm, uint32_t id)
{
wl_proxy_marshal(&drm->proxy, WL_DRM_AUTHENTICATE, id);
}
WL_EXPORT struct wl_buffer *
wl_drm_create_buffer(struct wl_drm *drm, uint32_t name,
int32_t width, int32_t height,
uint32_t stride, struct wl_visual *visual)
{
struct wl_buffer *buffer;
buffer = malloc(sizeof *buffer);
if (buffer == NULL)
return NULL;
buffer->proxy.base.interface = &wl_buffer_interface;
buffer->proxy.base.id = wl_display_allocate_id(drm->proxy.display);
buffer->proxy.display = drm->proxy.display;
wl_hash_table_insert(drm->proxy.display->objects,
drm->proxy.base.id, buffer);
wl_proxy_marshal(&drm->proxy, WL_DRM_CREATE_BUFFER,
buffer, name, width, height, stride, visual);
return buffer;
}
WL_EXPORT void
wl_buffer_destroy(struct wl_buffer *buffer)
{
wl_proxy_marshal(&buffer->proxy, WL_BUFFER_DESTROY);
}
static void static void
add_visual(struct wl_display *display, struct wl_global *global) add_visual(struct wl_display *display, struct wl_global *global)
{ {
@ -360,6 +411,9 @@ display_handle_global(void *data,
else if (strcmp(global->interface, "shell") == 0) else if (strcmp(global->interface, "shell") == 0)
wl_proxy_create_for_global(display, global, wl_proxy_create_for_global(display, global,
&wl_shell_interface); &wl_shell_interface);
else if (strcmp(global->interface, "drm") == 0)
wl_proxy_create_for_global(display, global,
&wl_drm_interface);
} }
static void static void
@ -589,12 +643,9 @@ wl_surface_destroy(struct wl_surface *surface)
} }
WL_EXPORT void WL_EXPORT void
wl_surface_attach(struct wl_surface *surface, uint32_t name, wl_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
int32_t width, int32_t height, uint32_t stride,
struct wl_visual *visual)
{ {
wl_proxy_marshal(&surface->proxy, WL_SURFACE_ATTACH, wl_proxy_marshal(&surface->proxy, WL_SURFACE_ATTACH, buffer);
name, width, height, stride, visual);
} }
WL_EXPORT void WL_EXPORT void

@ -88,10 +88,20 @@ wl_shell_resize(struct wl_shell *shell,
struct wl_surface *surface, struct wl_input_device *device, struct wl_surface *surface, struct wl_input_device *device,
uint32_t time, uint32_t edges); uint32_t time, uint32_t edges);
int
wl_drm_add_listener(struct wl_drm *drm,
const struct wl_drm_listener *listener,
void *data);
void
wl_drm_authenticate(struct wl_drm *drm, uint32_t id);
struct wl_buffer *
wl_drm_create_buffer(struct wl_drm *drm, uint32_t name,
int32_t width, int32_t height,
uint32_t stride, struct wl_visual *visual);
void wl_buffer_destroy(struct wl_buffer *buffer);
void wl_surface_destroy(struct wl_surface *surface); void wl_surface_destroy(struct wl_surface *surface);
void wl_surface_attach(struct wl_surface *surface, uint32_t name, void wl_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer);
int32_t width, int32_t height, uint32_t stride,
struct wl_visual *visual);
void wl_surface_map(struct wl_surface *surface, void wl_surface_map(struct wl_surface *surface,
int32_t x, int32_t y, int32_t width, int32_t height); int32_t x, int32_t y, int32_t width, int32_t height);
void wl_surface_damage(struct wl_surface *surface, void wl_surface_damage(struct wl_surface *surface,

@ -98,6 +98,13 @@ int wl_list_empty(struct wl_list *list);
&pos->member != (head); \ &pos->member != (head); \
pos = __container_of(pos->member.next, pos, member)) pos = __container_of(pos->member.next, pos, member))
#define wl_list_for_each_safe(pos, tmp, head, member) \
for (pos = __container_of((head)->next, pos, member), \
tmp = __container_of((pos)->member.next, tmp, member); \
&pos->member != (head); \
pos = tmp, \
tmp = __container_of(pos->member.next, tmp, member))
#define wl_list_for_each_reverse(pos, head, member) \ #define wl_list_for_each_reverse(pos, head, member) \
for (pos = __container_of((head)->prev, pos, member); \ for (pos = __container_of((head)->prev, pos, member); \
&pos->member != (head); \ &pos->member != (head); \

@ -42,7 +42,7 @@ struct wl_client {
struct wl_connection *connection; struct wl_connection *connection;
struct wl_event_source *source; struct wl_event_source *source;
struct wl_display *display; struct wl_display *display;
struct wl_list surface_list; struct wl_list resource_list;
struct wl_list link; struct wl_list link;
uint32_t id_count; uint32_t id_count;
}; };
@ -186,7 +186,7 @@ wl_client_create(struct wl_display *display, int fd)
client->connection = client->connection =
wl_connection_create(fd, wl_client_connection_update, client); wl_connection_create(fd, wl_client_connection_update, client);
wl_list_init(&client->surface_list); wl_list_init(&client->resource_list);
wl_list_init(&client->link); wl_list_init(&client->link);
wl_display_post_range(display, client); wl_display_post_range(display, client);
@ -205,30 +205,42 @@ wl_client_create(struct wl_display *display, int fd)
return client; return client;
} }
static void WL_EXPORT void
wl_object_destroy(struct wl_object *object) wl_client_add_resource(struct wl_client *client,
struct wl_resource *resource)
{
struct wl_display *display = client->display;
if (client->id_count-- < 64)
wl_display_post_range(display, client);
wl_hash_table_insert(client->display->objects,
resource->base.id, resource);
wl_list_insert(client->resource_list.prev, &resource->link);
}
WL_EXPORT void
wl_resource_destroy(struct wl_resource *resource, struct wl_client *client)
{ {
const struct wl_surface_interface *interface = struct wl_display *display = client->display;
(const struct wl_surface_interface *) object->implementation;
/* FIXME: Need generic object destructor. */ wl_list_remove(&resource->link);
interface->destroy(NULL, (struct wl_surface *) object); wl_hash_table_remove(display->objects, resource->base.id);
resource->destroy(resource, client);
} }
WL_EXPORT void WL_EXPORT void
wl_client_destroy(struct wl_client *client) wl_client_destroy(struct wl_client *client)
{ {
struct wl_surface *surface; struct wl_resource *resource, *tmp;
printf("disconnect from client %p\n", client); printf("disconnect from client %p\n", client);
wl_list_remove(&client->link); wl_list_remove(&client->link);
while (client->surface_list.next != &client->surface_list) { wl_list_for_each_safe(resource, tmp, &client->resource_list, link) {
surface = container_of(client->surface_list.next, wl_list_remove(&resource->link);
struct wl_surface, link); resource->destroy(resource, client);
wl_list_remove(&surface->link);
wl_object_destroy(&surface->base);
} }
wl_event_source_remove(client->source); wl_event_source_remove(client->source);
@ -242,32 +254,16 @@ wl_client_add_surface(struct wl_client *client,
const struct wl_surface_interface *implementation, const struct wl_surface_interface *implementation,
uint32_t id) uint32_t id)
{ {
struct wl_display *display = client->display; surface->base.base.id = id;
surface->base.base.interface = &wl_surface_interface;
if (client->id_count-- < 64) surface->base.base.implementation = (void (**)(void)) implementation;
wl_display_post_range(display, client);
surface->base.id = id;
surface->base.interface = &wl_surface_interface;
surface->base.implementation = (void (**)(void)) implementation;
surface->client = client; surface->client = client;
wl_hash_table_insert(display->objects, id, surface); wl_client_add_resource(client, &surface->base);
wl_list_insert(client->surface_list.prev, &surface->link);
return 0; return 0;
} }
WL_EXPORT void
wl_client_remove_surface(struct wl_client *client,
struct wl_surface *surface)
{
struct wl_display *display = client->display;
wl_hash_table_remove(display->objects, surface->base.id);
wl_list_remove(&surface->link);
}
WL_EXPORT void WL_EXPORT void
wl_client_send_acknowledge(struct wl_client *client, wl_client_send_acknowledge(struct wl_client *client,
struct wl_compositor *compositor, struct wl_compositor *compositor,
@ -280,16 +276,6 @@ wl_client_send_acknowledge(struct wl_client *client,
WL_COMPOSITOR_ACKNOWLEDGE, key, frame); WL_COMPOSITOR_ACKNOWLEDGE, key, frame);
} }
static void
post_compositor_device(struct wl_client *client, struct wl_object *global)
{
struct wl_compositor *compositor =
container_of(global, struct wl_compositor, base);
wl_client_post_event(client, global,
WL_COMPOSITOR_DEVICE, compositor->device);
}
WL_EXPORT int WL_EXPORT int
wl_display_set_compositor(struct wl_display *display, wl_display_set_compositor(struct wl_display *display,
struct wl_compositor *compositor, struct wl_compositor *compositor,
@ -299,7 +285,7 @@ wl_display_set_compositor(struct wl_display *display,
compositor->base.implementation = (void (**)(void)) implementation; compositor->base.implementation = (void (**)(void)) implementation;
wl_display_add_object(display, &compositor->base); wl_display_add_object(display, &compositor->base);
if (wl_display_add_global(display, &compositor->base, post_compositor_device)) if (wl_display_add_global(display, &compositor->base, NULL))
return -1; return -1;
return 0; return 0;

@ -70,14 +70,9 @@ struct wl_event_source *wl_event_loop_add_idle(struct wl_event_loop *loop,
void *data); void *data);
struct wl_client; struct wl_client;
struct wl_display; struct wl_display;
struct wl_input_device; struct wl_input_device;
struct wl_map {
int32_t x, y, width, height;
};
struct wl_display *wl_display_create(void); struct wl_display *wl_display_create(void);
struct wl_event_loop *wl_display_get_event_loop(struct wl_display *display); struct wl_event_loop *wl_display_get_event_loop(struct wl_display *display);
int wl_display_add_socket(struct wl_display *display, const char *name, size_t name_size); int wl_display_add_socket(struct wl_display *display, const char *name, size_t name_size);
@ -93,15 +88,24 @@ void wl_client_destroy(struct wl_client *client);
struct wl_compositor { struct wl_compositor {
struct wl_object base; struct wl_object base;
const char *device;
}; };
struct wl_surface { struct wl_resource {
struct wl_object base; struct wl_object base;
struct wl_client *client; void (*destroy)(struct wl_resource *resource,
struct wl_client *client);
struct wl_list link; struct wl_list link;
}; };
struct wl_buffer {
struct wl_resource base;
};
struct wl_surface {
struct wl_resource base;
struct wl_client *client;
};
void void
wl_client_post_event(struct wl_client *client, wl_client_post_event(struct wl_client *client,
struct wl_object *sender, struct wl_object *sender,
@ -123,10 +127,6 @@ wl_client_add_surface(struct wl_client *client,
const struct wl_surface_interface *implementation, const struct wl_surface_interface *implementation,
uint32_t id); uint32_t id);
void
wl_client_remove_surface(struct wl_client *client,
struct wl_surface *surface);
void void
wl_client_send_acknowledge(struct wl_client *client, wl_client_send_acknowledge(struct wl_client *client,
struct wl_compositor *compositor, struct wl_compositor *compositor,
@ -137,6 +137,13 @@ wl_display_post_frame(struct wl_display *display,
struct wl_compositor *compositor, struct wl_compositor *compositor,
uint32_t frame, uint32_t msecs); uint32_t frame, uint32_t msecs);
void
wl_client_add_resource(struct wl_client *client,
struct wl_resource *resource);
void
wl_resource_destroy(struct wl_resource *resource, struct wl_client *client);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

Loading…
Cancel
Save