Redesign the compositor / server interface.

This lets the compositor directly provide the implementation of the RMI
objects for the surface object and a new compositor object.  We avoid the
manual forwarding of requests into the compositor and the clumsy compositor
interface struct.
dev
Kristian Høgsberg 16 years ago
parent 0ea4710b3d
commit d2412e2c2e
  1. 165
      egl-compositor.c
  2. 10
      flower.c
  3. 5
      gears.c
  4. 4
      terminal.c
  5. 47
      wayland-client.c
  6. 7
      wayland-client.h
  7. 288
      wayland.c
  8. 90
      wayland.h
  9. 12
      window.c

@ -89,10 +89,11 @@ struct egl_compositor {
}; };
struct egl_surface { struct egl_surface {
struct wl_surface base;
struct egl_compositor *compositor;
GLuint texture; GLuint texture;
struct wl_map map; struct wl_map map;
EGLSurface surface; EGLSurface surface;
struct wl_surface *wl_surface;
int width, height; int width, height;
struct wl_list link; struct wl_list link;
}; };
@ -102,6 +103,10 @@ struct screenshooter {
struct egl_compositor *ec; struct egl_compositor *ec;
}; };
struct screenshooter_interface {
void (*shoot)(struct wl_client *client, struct screenshooter *shooter);
};
static void static void
screenshooter_shoot(struct wl_client *client, struct screenshooter *shooter) screenshooter_shoot(struct wl_client *client, struct screenshooter *shooter)
{ {
@ -120,7 +125,7 @@ screenshooter_shoot(struct wl_client *client, struct screenshooter *shooter)
} }
static const struct wl_method screenshooter_methods[] = { static const struct wl_method screenshooter_methods[] = {
{ "shoot", screenshooter_shoot, "", NULL } { "shoot", "", NULL }
}; };
static const struct wl_interface screenshooter_interface = { static const struct wl_interface screenshooter_interface = {
@ -129,6 +134,10 @@ static const struct wl_interface screenshooter_interface = {
screenshooter_methods, screenshooter_methods,
}; };
struct screenshooter_interface screenshooter_implementation = {
screenshooter_shoot
};
static struct screenshooter * static struct screenshooter *
screenshooter_create(struct egl_compositor *ec) screenshooter_create(struct egl_compositor *ec)
{ {
@ -139,6 +148,7 @@ screenshooter_create(struct egl_compositor *ec)
return NULL; return NULL;
shooter->base.interface = &screenshooter_interface; shooter->base.interface = &screenshooter_interface;
shooter->base.implementation = (void(**)(void)) &screenshooter_implementation;
shooter->ec = ec; shooter->ec = ec;
return shooter; return shooter;
@ -498,7 +508,8 @@ repaint(void *data)
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
msecs = ts.tv_sec * 1000 + ts.tv_nsec / (1000 * 1000); msecs = ts.tv_sec * 1000 + ts.tv_nsec / (1000 * 1000);
wl_display_post_frame(ec->wl_display, ec->current_frame, msecs); wl_display_post_frame(ec->wl_display, &ec->base,
ec->current_frame, msecs);
ec->current_frame++; ec->current_frame++;
wl_event_source_timer_update(ec->timer_source, 10); wl_event_source_timer_update(ec->timer_source, 10);
@ -518,36 +529,13 @@ schedule_repaint(struct egl_compositor *ec)
wl_event_loop_add_idle(loop, repaint, ec); wl_event_loop_add_idle(loop, repaint, ec);
} }
} }
static void
notify_surface_create(struct wl_compositor *compositor,
struct wl_surface *surface)
{
struct egl_compositor *ec = (struct egl_compositor *) compositor;
struct egl_surface *es;
es = malloc(sizeof *es);
if (es == NULL)
return;
es->surface = EGL_NO_SURFACE;
es->wl_surface = surface;
wl_surface_set_data(surface, es);
wl_list_insert(ec->surface_list.prev, &es->link);
glGenTextures(1, &es->texture);
}
static void static void
notify_surface_destroy(struct wl_compositor *compositor, surface_destroy(struct wl_client *client,
struct wl_surface *surface) struct wl_surface *surface)
{ {
struct egl_compositor *ec = (struct egl_compositor *) compositor; struct egl_surface *es = (struct egl_surface *) surface;
struct egl_surface *es; struct egl_compositor *ec = es->compositor;
es = wl_surface_get_data(surface);
if (es == NULL)
return;
wl_list_remove(&es->link); wl_list_remove(&es->link);
egl_surface_destroy(es, ec); egl_surface_destroy(es, ec);
@ -556,16 +544,12 @@ notify_surface_destroy(struct wl_compositor *compositor,
} }
static void static void
notify_surface_attach(struct wl_compositor *compositor, surface_attach(struct wl_client *client,
struct wl_surface *surface, uint32_t name, struct wl_surface *surface, uint32_t name,
uint32_t width, uint32_t height, uint32_t stride) uint32_t width, uint32_t height, uint32_t stride)
{ {
struct egl_compositor *ec = (struct egl_compositor *) compositor; struct egl_surface *es = (struct egl_surface *) surface;
struct egl_surface *es; struct egl_compositor *ec = es->compositor;
es = wl_surface_get_data(surface);
if (es == NULL)
return;
if (es->surface != EGL_NO_SURFACE) if (es->surface != EGL_NO_SURFACE)
eglDestroySurface(ec->display, es->surface); eglDestroySurface(ec->display, es->surface);
@ -584,30 +568,28 @@ notify_surface_attach(struct wl_compositor *compositor,
} }
static void static void
notify_surface_map(struct wl_compositor *compositor, surface_map(struct wl_client *client,
struct wl_surface *surface, struct wl_map *map) struct wl_surface *surface,
int32_t x, int32_t y, int32_t width, int32_t height)
{ {
struct egl_surface *es; struct egl_surface *es = (struct egl_surface *) surface;
es = wl_surface_get_data(surface); es->map.x = x;
if (es == NULL) es->map.y = y;
return; es->map.width = width;
es->map.height = height;
es->map = *map;
} }
static void static void
notify_surface_copy(struct wl_compositor *compositor, surface_copy(struct wl_client *client,
struct wl_surface *surface, struct wl_surface *surface,
int32_t dst_x, int32_t dst_y, int32_t dst_x, int32_t dst_y,
uint32_t name, uint32_t stride, uint32_t name, uint32_t stride,
int32_t x, int32_t y, int32_t width, int32_t height) int32_t x, int32_t y, int32_t width, int32_t height)
{ {
struct egl_compositor *ec = (struct egl_compositor *) compositor; struct egl_surface *es = (struct egl_surface *) surface;
struct egl_compositor *ec = es->compositor;
EGLSurface src; EGLSurface src;
struct egl_surface *es;
es = wl_surface_get_data(surface);
/* FIXME: glCopyPixels should work, but then we'll have to /* FIXME: glCopyPixels should work, but then we'll have to
* call eglMakeCurrent to set up the src and dest surfaces * call eglMakeCurrent to set up the src and dest surfaces
@ -623,23 +605,56 @@ notify_surface_copy(struct wl_compositor *compositor,
} }
static void static void
notify_surface_damage(struct wl_compositor *compositor, surface_damage(struct wl_client *client,
struct wl_surface *surface, 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)
{ {
/* FIXME: This need to take a damage region, of course. */ /* FIXME: This need to take a damage region, of course. */
} }
static uint32_t const static struct wl_surface_interface surface_interface = {
notify_commit(struct wl_compositor *compositor) surface_destroy,
surface_attach,
surface_map,
surface_copy,
surface_damage
};
static void
compositor_create_surface(struct wl_client *client,
struct wl_compositor *compositor, uint32_t id)
{ {
struct egl_compositor *ec = (struct egl_compositor *) compositor; struct egl_compositor *ec = (struct egl_compositor *) compositor;
struct egl_surface *es;
schedule_repaint(ec); es = malloc(sizeof *es);
if (es == NULL)
/* FIXME: Send OOM event. */
return;
return ec->current_frame; es->compositor = ec;
es->surface = EGL_NO_SURFACE;
wl_list_insert(ec->surface_list.prev, &es->link);
glGenTextures(1, &es->texture);
wl_client_add_surface(client, &es->base,
&surface_interface, id);
}
static void
compositor_commit(struct wl_client *client,
struct wl_compositor *compositor, uint32_t key)
{
struct egl_compositor *ec = (struct egl_compositor *) compositor;
schedule_repaint(ec);
wl_client_send_acknowledge(client, compositor, key, ec->current_frame);
} }
const static struct wl_compositor_interface compositor_interface = {
compositor_create_surface,
compositor_commit
};
static struct egl_surface * static struct egl_surface *
pick_surface(struct egl_input_device *device) pick_surface(struct egl_input_device *device)
{ {
@ -677,7 +692,7 @@ notify_motion(struct egl_input_device *device, int x, int y)
if (es) { if (es) {
sx = (x - es->map.x) * es->width / es->map.width; sx = (x - es->map.x) * es->width / es->map.width;
sy = (y - es->map.y) * es->height / es->map.height; sy = (y - es->map.y) * es->height / es->map.height;
wl_surface_post_event(es->wl_surface, &device->base, wl_surface_post_event(&es->base, &device->base,
WL_INPUT_MOTION, x, y, sx, sy); WL_INPUT_MOTION, x, y, sx, sy);
} }
@ -715,7 +730,7 @@ notify_button(struct egl_input_device *device,
sy = (device->y - es->map.y) * es->height / es->map.height; sy = (device->y - es->map.y) * es->height / es->map.height;
/* FIXME: Swallow click on raise? */ /* FIXME: Swallow click on raise? */
wl_surface_post_event(es->wl_surface, &device->base, wl_surface_post_event(&es->base, &device->base,
WL_INPUT_BUTTON, button, state, WL_INPUT_BUTTON, button, state,
device->x, device->y, sx, sy); device->x, device->y, sx, sy);
@ -737,29 +752,16 @@ notify_key(struct egl_input_device *device,
schedule_repaint(ec); schedule_repaint(ec);
} else if (!wl_list_empty(&ec->surface_list)) { } else if (!wl_list_empty(&ec->surface_list)) {
if (device->focus_surface != NULL) if (device->focus_surface != NULL)
wl_surface_post_event(device->focus_surface->wl_surface, wl_surface_post_event(&device->focus_surface->base,
&device->base, &device->base,
WL_INPUT_KEY, key, state); WL_INPUT_KEY, key, state);
} }
} }
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_commit,
};
struct evdev_input_device * struct evdev_input_device *
evdev_input_device_create(struct egl_input_device *device, evdev_input_device_create(struct egl_input_device *device,
struct wl_display *display, const char *path); struct wl_display *display, const char *path);
void
egl_device_get_position(struct egl_input_device *device, int32_t *x, int32_t *y);
static void static void
create_input_device(struct egl_compositor *ec, const char *glob) create_input_device(struct egl_compositor *ec, const char *glob)
{ {
@ -984,7 +986,6 @@ egl_compositor_create(struct wl_display *display)
if (ec == NULL) if (ec == NULL)
return NULL; return NULL;
ec->base.interface = &interface;
ec->wl_display = display; ec->wl_display = display;
ec->display = eglCreateDisplayNative(gem_device, "i965"); ec->display = eglCreateDisplayNative(gem_device, "i965");
@ -1027,6 +1028,8 @@ egl_compositor_create(struct wl_display *display)
glOrtho(0, ec->width, ec->height, 0, 0, 1000.0); glOrtho(0, ec->width, ec->height, 0, 0, 1000.0);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
wl_display_set_compositor(display, &ec->base, &compositor_interface);
wl_list_init(&ec->input_device_list); wl_list_init(&ec->input_device_list);
for (i = 0; option_input_devices[i]; i++) for (i = 0; option_input_devices[i]; i++)
create_input_device(ec, option_input_devices[i]); create_input_device(ec, option_input_devices[i]);
@ -1086,8 +1089,6 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
wl_display_set_compositor(display, &ec->base);
if (wl_display_add_socket(display, socket_name, sizeof socket_name)) { if (wl_display_add_socket(display, socket_name, sizeof socket_name)) {
fprintf(stderr, "failed to add socket: %m\n"); fprintf(stderr, "failed to add socket: %m\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

@ -104,7 +104,7 @@ draw_stuff(int width, int height)
} }
struct flower { struct flower {
struct wl_display *display; struct wl_compositor *compositor;
struct wl_surface *surface; struct wl_surface *surface;
int i; int i;
int x, y, width, height; int x, y, width, height;
@ -118,7 +118,7 @@ move_flower(struct flower *flower)
flower->y + sin(flower->i / 27.0) * 300 - flower->height / 2, flower->y + sin(flower->i / 27.0) * 300 - flower->height / 2,
flower->width, flower->height); flower->width, flower->height);
flower->i++; flower->i++;
wl_display_commit(flower->display, 0); wl_compositor_commit(flower->compositor, 0);
} }
static void static void
@ -126,7 +126,7 @@ event_handler(struct wl_display *display,
uint32_t object, uint32_t opcode, uint32_t object, uint32_t opcode,
uint32_t size, uint32_t *p, void *data) uint32_t size, uint32_t *p, void *data)
{ {
if (object == 1 && opcode == 4) if (object == 2 && opcode == 1)
move_flower(data); move_flower(data);
} }
@ -158,12 +158,12 @@ int main(int argc, char *argv[])
source = wl_glib_source_new(display); source = wl_glib_source_new(display);
g_source_attach(source, NULL); g_source_attach(source, NULL);
flower.display = display; flower.compositor = wl_display_get_compositor(display);
flower.x = 512; flower.x = 512;
flower.y = 384; flower.y = 384;
flower.width = 200; flower.width = 200;
flower.height = 200; flower.height = 200;
flower.surface = wl_display_create_surface(display); flower.surface = wl_compositor_create_surface(flower.compositor);
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
srandom(ts.tv_nsec); srandom(ts.tv_nsec);

@ -47,6 +47,7 @@ struct gears {
struct window *window; struct window *window;
struct wl_display *wl_display; struct wl_display *wl_display;
struct wl_compositor *compositor;
struct rectangle rectangle; struct rectangle rectangle;
EGLDisplay display; EGLDisplay display;
@ -320,7 +321,7 @@ frame_handler(struct window *window, uint32_t frame, uint32_t timestamp, void *d
&gears->rectangle, &gears->rectangle,
gears->buffer->name, gears->buffer->stride); gears->buffer->name, gears->buffer->stride);
wl_display_commit(gears->wl_display, 0); wl_compositor_commit(gears->compositor, 0);
gears->angle += 1; gears->angle += 1;
} }
@ -379,6 +380,8 @@ gears_create(struct wl_display *display, int fd)
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 0.92); glClearColor(0, 0, 0, 0.92);
gears->compositor = wl_display_get_compositor(display);
draw_gears(gears); draw_gears(gears);
frame_handler(gears->window, 0, 0, gears); frame_handler(gears->window, 0, 0, gears);

@ -53,6 +53,7 @@ static const char socket_name[] = "\0wayland";
struct terminal { struct terminal {
struct window *window; struct window *window;
struct wl_display *display; struct wl_display *display;
struct wl_compositor *compositor;
int redraw_scheduled, redraw_pending; int redraw_scheduled, redraw_pending;
char *data; char *data;
int width, height, start, row, column; int width, height, start, row, column;
@ -194,7 +195,7 @@ terminal_draw(struct terminal *terminal)
window_draw(terminal->window); window_draw(terminal->window);
terminal_draw_contents(terminal); terminal_draw_contents(terminal);
wl_display_commit(terminal->display, 0); wl_compositor_commit(terminal->compositor, 0);
} }
static gboolean static gboolean
@ -531,6 +532,7 @@ terminal_create(struct wl_display *display, int fd)
terminal->redraw_scheduled = 1; terminal->redraw_scheduled = 1;
terminal->margin = 5; terminal->margin = 5;
terminal->compositor = wl_display_get_compositor(display);
window_set_resize_handler(terminal->window, resize_handler, terminal); window_set_resize_handler(terminal->window, resize_handler, terminal);
window_set_acknowledge_handler(terminal->window, acknowledge_handler, terminal); window_set_acknowledge_handler(terminal->window, acknowledge_handler, terminal);
window_set_key_handler(terminal->window, key_handler, terminal); window_set_key_handler(terminal->window, key_handler, terminal);

@ -64,6 +64,10 @@ struct wl_display {
void *event_handler_data; void *event_handler_data;
}; };
struct wl_compositor {
struct wl_proxy proxy;
};
struct wl_surface { struct wl_surface {
struct wl_proxy proxy; struct wl_proxy proxy;
}; };
@ -249,11 +253,28 @@ wl_display_write(struct wl_display *display, const void *data, size_t count)
wl_connection_write(display->connection, data, count); wl_connection_write(display->connection, data, count);
} }
#define WL_DISPLAY_CREATE_SURFACE 0 WL_EXPORT struct wl_compositor *
#define WL_DISPLAY_COMMIT 1 wl_display_get_compositor(struct wl_display *display)
{
struct wl_compositor *compositor;
uint32_t id;
id = wl_display_get_object_id(display, "compositor");
if (id == 0)
return NULL;
compositor = malloc(sizeof *compositor);
compositor->proxy.display = display;
compositor->proxy.id = id;
return compositor;
}
#define WL_COMPOSITOR_CREATE_SURFACE 0
#define WL_COMPOSITOR_COMMIT 1
WL_EXPORT struct wl_surface * WL_EXPORT struct wl_surface *
wl_display_create_surface(struct wl_display *display) wl_compositor_create_surface(struct wl_compositor *compositor)
{ {
struct wl_surface *surface; struct wl_surface *surface;
uint32_t request[3]; uint32_t request[3];
@ -262,26 +283,28 @@ wl_display_create_surface(struct wl_display *display)
if (surface == NULL) if (surface == NULL)
return NULL; return NULL;
surface->proxy.id = wl_display_allocate_id(display); surface->proxy.id = wl_display_allocate_id(compositor->proxy.display);
surface->proxy.display = display; surface->proxy.display = compositor->proxy.display;
request[0] = display->proxy.id; request[0] = compositor->proxy.id;
request[1] = WL_DISPLAY_CREATE_SURFACE | ((sizeof request) << 16); request[1] = WL_COMPOSITOR_CREATE_SURFACE | ((sizeof request) << 16);
request[2] = surface->proxy.id; request[2] = surface->proxy.id;
wl_connection_write(display->connection, request, sizeof request); wl_connection_write(compositor->proxy.display->connection,
request, sizeof request);
return surface; return surface;
} }
WL_EXPORT void WL_EXPORT void
wl_display_commit(struct wl_display *display, uint32_t key) wl_compositor_commit(struct wl_compositor *compositor, uint32_t key)
{ {
uint32_t request[3]; uint32_t request[3];
request[0] = display->proxy.id; request[0] = compositor->proxy.id;
request[1] = WL_DISPLAY_COMMIT | ((sizeof request) << 16); request[1] = WL_COMPOSITOR_COMMIT | ((sizeof request) << 16);
request[2] = key; request[2] = key;
wl_connection_write(display->connection, request, sizeof request); wl_connection_write(compositor->proxy.display->connection,
request, sizeof request);
} }
#define WL_SURFACE_DESTROY 0 #define WL_SURFACE_DESTROY 0

@ -56,10 +56,13 @@ void wl_display_set_event_handler(struct wl_display *display,
wl_display_event_func_t handler, wl_display_event_func_t handler,
void *data); void *data);
struct wl_compositor *
wl_display_get_compositor(struct wl_display *display);
struct wl_surface * struct wl_surface *
wl_display_create_surface(struct wl_display *display); wl_compositor_create_surface(struct wl_compositor *compositor);
void void
wl_display_commit(struct wl_display *display, uint32_t key); wl_compositor_commit(struct wl_compositor *compositor, uint32_t key);
void wl_surface_destroy(struct wl_surface *surface); void wl_surface_destroy(struct wl_surface *surface);
void wl_surface_attach(struct wl_surface *surface, void wl_surface_attach(struct wl_surface *surface,

@ -43,7 +43,6 @@ struct wl_client {
struct wl_display *display; struct wl_display *display;
struct wl_list object_list; struct wl_list object_list;
struct wl_list link; struct wl_list link;
uint32_t pending_frame;
}; };
struct wl_display { struct wl_display {
@ -51,160 +50,18 @@ struct wl_display {
struct wl_event_loop *loop; struct wl_event_loop *loop;
struct wl_hash *objects; struct wl_hash *objects;
struct wl_object *pointer; struct wl_list pending_frame_list;
struct wl_compositor *compositor;
struct wl_compositor_interface *compositor_interface;
struct wl_list surface_list;
struct wl_list client_list;
uint32_t client_id_range; uint32_t client_id_range;
uint32_t id; uint32_t id;
struct wl_list global_list; struct wl_list global_list;
}; };
struct wl_surface {
struct wl_object base;
struct wl_client *client;
/* provided by client */
int width, height;
int buffer;
int stride;
struct wl_map map;
struct wl_list link;
/* how to convert buffer contents to pixels in screen format;
* yuv->rgb, indexed->rgb, svg->rgb, but mostly just rgb->rgb. */
/* how to transform/render rectangular contents to polygons. */
void *compositor_data;
};
struct wl_object_ref { struct wl_object_ref {
struct wl_object *object; struct wl_object *object;
struct wl_list link; struct wl_list link;
}; };
static void
wl_surface_destroy(struct wl_client *client,
struct wl_surface *surface)
{
const struct wl_compositor_interface *interface;
interface = client->display->compositor->interface;
interface->notify_surface_destroy(client->display->compositor,
surface);
wl_list_remove(&surface->link);
}
static void
wl_surface_attach(struct wl_client *client,
struct wl_surface *surface, uint32_t name,
uint32_t width, uint32_t height, uint32_t stride)
{
const struct wl_compositor_interface *interface;
interface = client->display->compositor->interface;
interface->notify_surface_attach(client->display->compositor,
surface, name, width, height, stride);
}
static void
wl_surface_map(struct wl_client *client, struct wl_surface *surface,
int32_t x, int32_t y, int32_t width, int32_t height)
{
const struct wl_compositor_interface *interface;
/* FIXME: This needs to take a tri-mesh argument... - count
* and a list of tris. 0 tris means unmap. */
surface->map.x = x;
surface->map.y = y;
surface->map.width = width;
surface->map.height = height;
interface = client->display->compositor->interface;
interface->notify_surface_map(client->display->compositor,
surface, &surface->map);
}
static void
wl_surface_copy(struct wl_client *client, struct wl_surface *surface,
int32_t dst_x, int32_t dst_y, uint32_t name, uint32_t stride,
int32_t x, int32_t y, int32_t width, int32_t height)
{
const struct wl_compositor_interface *interface;
interface = client->display->compositor->interface;
interface->notify_surface_copy(client->display->compositor,
surface, dst_x, dst_y,
name, stride, x, y, width, height);
}
static void
wl_surface_damage(struct wl_client *client, struct wl_surface *surface,
int32_t x, int32_t y, int32_t width, int32_t height)
{
const struct wl_compositor_interface *interface;
interface = client->display->compositor->interface;
interface->notify_surface_damage(client->display->compositor,
surface, x, y, width, height);
}
static const struct wl_method surface_methods[] = {
{ "destroy", wl_surface_destroy, "" },
{ "attach", wl_surface_attach, "uuuu" },
{ "map", wl_surface_map, "iiii" },
{ "copy", wl_surface_copy, "iiuuiiii" },
{ "damage", wl_surface_damage, "iiii" }
};
static const struct wl_interface surface_interface = {
"surface", 1,
ARRAY_LENGTH(surface_methods),
surface_methods,
};
static struct wl_surface *
wl_surface_create(struct wl_display *display,
struct wl_client *client, uint32_t id)
{
struct wl_surface *surface;
const struct wl_compositor_interface *interface;
surface = malloc(sizeof *surface);
if (surface == NULL)
return NULL;
surface->base.id = id;
surface->base.interface = &surface_interface;
surface->client = client;
wl_list_insert(display->surface_list.prev, &surface->link);
interface = display->compositor->interface;
interface->notify_surface_create(display->compositor, surface);
return surface;
}
WL_EXPORT void
wl_surface_set_data(struct wl_surface *surface, void *data)
{
surface->compositor_data = data;
}
WL_EXPORT void *
wl_surface_get_data(struct wl_surface *surface)
{
return surface->compositor_data;
}
void void
wl_client_destroy(struct wl_client *client); wl_client_destroy(struct wl_client *client);
@ -264,8 +121,9 @@ wl_client_marshal(struct wl_client *client, struct wl_object *sender,
static void static void
wl_client_demarshal(struct wl_client *client, struct wl_object *target, wl_client_demarshal(struct wl_client *client, struct wl_object *target,
const struct wl_method *method, size_t size) uint32_t opcode, size_t size)
{ {
const struct wl_method *method;
ffi_type *types[20]; ffi_type *types[20];
ffi_cif cif; ffi_cif cif;
uint32_t *p, result; uint32_t *p, result;
@ -279,7 +137,9 @@ wl_client_demarshal(struct wl_client *client, struct wl_object *target,
void *args[20]; void *args[20];
struct wl_object *object; struct wl_object *object;
uint32_t data[64]; uint32_t data[64];
void (*func)(void);
method = &target->interface->methods[opcode];
count = strlen(method->signature) + 2; count = strlen(method->signature) + 2;
if (count > ARRAY_LENGTH(types)) { if (count > ARRAY_LENGTH(types)) {
printf("too many args (%d)\n", count); printf("too many args (%d)\n", count);
@ -341,22 +201,20 @@ wl_client_demarshal(struct wl_client *client, struct wl_object *target,
args[i] = &values[i]; args[i] = &values[i];
} }
func = target->implementation[opcode];
ffi_prep_cif(&cif, FFI_DEFAULT_ABI, count, &ffi_type_uint32, types); ffi_prep_cif(&cif, FFI_DEFAULT_ABI, count, &ffi_type_uint32, types);
ffi_call(&cif, FFI_FN(method->func), &result, args); ffi_call(&cif, func, &result, args);
} }
#define WL_DISPLAY_INVALID_OBJECT 0 #define WL_DISPLAY_INVALID_OBJECT 0
#define WL_DISPLAY_INVALID_METHOD 1 #define WL_DISPLAY_INVALID_METHOD 1
#define WL_DISPLAY_NO_MEMORY 2 #define WL_DISPLAY_NO_MEMORY 2
#define WL_DISPLAY_ACKNOWLEDGE 3
#define WL_DISPLAY_FRAME 4
static void static void
wl_client_connection_data(int fd, uint32_t mask, void *data) wl_client_connection_data(int fd, uint32_t mask, void *data)
{ {
struct wl_client *client = data; struct wl_client *client = data;
struct wl_connection *connection = client->connection; struct wl_connection *connection = client->connection;
const struct wl_method *method;
struct wl_object *object; struct wl_object *object;
uint32_t p[2], opcode, size; uint32_t p[2], opcode, size;
uint32_t cmask = 0; uint32_t cmask = 0;
@ -397,8 +255,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
continue; continue;
} }
method = &object->interface->methods[opcode]; wl_client_demarshal(client, object, opcode, size);
wl_client_demarshal(client, object, method, size);
wl_connection_consume(connection, size); wl_connection_consume(connection, size);
len -= size; len -= size;
} }
@ -455,6 +312,7 @@ wl_client_create(struct wl_display *display, int fd)
wl_client_connection_update, wl_client_connection_update,
client); client);
wl_list_init(&client->object_list); wl_list_init(&client->object_list);
wl_list_init(&client->link);
wl_connection_write(client->connection, wl_connection_write(client->connection,
&display->client_id_range, &display->client_id_range,
@ -474,11 +332,19 @@ wl_client_create(struct wl_display *display, int fd)
struct wl_object_ref, link); struct wl_object_ref, link);
} }
wl_list_insert(display->client_list.prev, &client->link);
return client; return client;
} }
static void
wl_object_destroy(struct wl_object *object)
{
const struct wl_surface_interface *interface =
(const struct wl_surface_interface *) object->implementation;
/* FIXME: Need generic object destructor. */
interface->destroy(NULL, (struct wl_surface *) object);
}
void void
wl_client_destroy(struct wl_client *client) wl_client_destroy(struct wl_client *client)
{ {
@ -492,7 +358,7 @@ wl_client_destroy(struct wl_client *client)
ref = container_of(client->object_list.next, ref = container_of(client->object_list.next,
struct wl_object_ref, link); struct wl_object_ref, link);
wl_list_remove(&ref->link); wl_list_remove(&ref->link);
wl_surface_destroy(client, (struct wl_surface *) ref->object); wl_object_destroy(ref->object);
free(ref); free(ref);
} }
@ -501,14 +367,33 @@ wl_client_destroy(struct wl_client *client)
free(client); free(client);
} }
static int static const struct wl_method surface_methods[] = {
wl_display_create_surface(struct wl_client *client, { "destroy", "" },
struct wl_display *display, uint32_t id) { "attach", "uuuu" },
{ "map", "iiii" },
{ "copy", "iiuuiiii" },
{ "damage", "iiii" }
};
static const struct wl_interface surface_interface = {
"surface", 1,
ARRAY_LENGTH(surface_methods),
surface_methods,
};
WL_EXPORT int
wl_client_add_surface(struct wl_client *client,
struct wl_surface *surface,
const struct wl_surface_interface *implementation,
uint32_t id)
{ {
struct wl_surface *surface; struct wl_display *display = client->display;
struct wl_object_ref *ref; struct wl_object_ref *ref;
surface = wl_surface_create(display, client, id); surface->base.id = id;
surface->base.interface = &surface_interface;
surface->base.implementation = (void (**)(void)) implementation;
surface->client = client;
ref = malloc(sizeof *ref); ref = malloc(sizeof *ref);
if (ref == NULL) { if (ref == NULL) {
@ -524,39 +409,61 @@ wl_display_create_surface(struct wl_client *client,
return 0; return 0;
} }
static int #define WL_COMPOSITOR_ACKNOWLEDGE 0
wl_display_commit(struct wl_client *client, #define WL_COMPOSITOR_FRAME 1
struct wl_display *display, uint32_t key)
WL_EXPORT void
wl_client_send_acknowledge(struct wl_client *client,
struct wl_compositor *compositor,
uint32_t key, uint32_t frame)
{ {
const struct wl_compositor_interface *interface; wl_list_remove(&client->link);
uint32_t frame; wl_list_insert(client->display->pending_frame_list.prev,
&client->link);
wl_client_marshal(client, &compositor->base,
WL_COMPOSITOR_ACKNOWLEDGE, key, frame);
}
static const struct wl_method compositor_methods[] = {
{ "create_surface", "n" },
{ "commit", "u" }
};
static const struct wl_event compositor_events[] = {
{ "acknowledge", "uu" },
{ "frame", "uu" }
};
static const struct wl_interface compositor_interface = {
"compositor", 1,
ARRAY_LENGTH(compositor_methods), compositor_methods,
ARRAY_LENGTH(compositor_events), compositor_events,
};
client->pending_frame = 1; WL_EXPORT int
wl_display_set_compositor(struct wl_display *display,
struct wl_compositor *compositor,
const struct wl_compositor_interface *implementation)
{
compositor->base.interface = &compositor_interface;
compositor->base.implementation = (void (**)(void)) implementation;
interface = display->compositor->interface; wl_display_add_object(display, &compositor->base);
frame = interface->notify_commit(display->compositor); if (wl_display_add_global(display, &compositor->base))
wl_client_marshal(client, &display->base, return -1;
WL_DISPLAY_ACKNOWLEDGE, key, frame);
return 0; return 0;
} }
static const struct wl_method display_methods[] = {
{ "create_surface", wl_display_create_surface, "n" },
{ "commit", wl_display_commit, "u" }
};
static const struct wl_event display_events[] = { static const struct wl_event display_events[] = {
{ "invalid_object", "u" }, { "invalid_object", "u" },
{ "invalid_method", "uu" }, { "invalid_method", "uu" },
{ "no_memory", "" }, { "no_memory", "" },
{ "acknowledge", "uu" },
{ "frame", "uu" }
}; };
static const struct wl_interface display_interface = { static const struct wl_interface display_interface = {
"display", 1, "display", 1,
ARRAY_LENGTH(display_methods), display_methods, 0, NULL,
ARRAY_LENGTH(display_events), display_events, ARRAY_LENGTH(display_events), display_events,
}; };
@ -581,14 +488,14 @@ wl_display_create(void)
return NULL; return NULL;
} }
wl_list_init(&display->surface_list); wl_list_init(&display->pending_frame_list);
wl_list_init(&display->client_list);
wl_list_init(&display->global_list); wl_list_init(&display->global_list);
display->client_id_range = 256; /* Gah, arbitrary... */ display->client_id_range = 256; /* Gah, arbitrary... */
display->id = 1; display->id = 1;
display->base.interface = &display_interface; display->base.interface = &display_interface;
display->base.implementation = NULL;
wl_display_add_object(display, &display->base); wl_display_add_object(display, &display->base);
if (wl_display_add_global(display, &display->base)) { if (wl_display_add_global(display, &display->base)) {
wl_event_loop_destroy(display->loop); wl_event_loop_destroy(display->loop);
@ -636,9 +543,6 @@ wl_surface_post_event(struct wl_surface *surface,
struct wl_input_device { struct wl_input_device {
struct wl_object base; struct wl_object base;
struct wl_display *display; struct wl_display *display;
uint32_t button_state[16];
uint32_t button_count;
int32_t x, y;
}; };
static const struct wl_method input_device_methods[] = { static const struct wl_method input_device_methods[] = {
@ -666,29 +570,23 @@ wl_input_device_get_interface(void)
WL_EXPORT void WL_EXPORT void
wl_display_post_frame(struct wl_display *display, wl_display_post_frame(struct wl_display *display,
struct wl_compositor *compositor,
uint32_t frame, uint32_t msecs) uint32_t frame, uint32_t msecs)
{ {
struct wl_client *client; struct wl_client *client;
client = container_of(display->client_list.next, client = container_of(display->pending_frame_list.next,
struct wl_client, link); struct wl_client, link);
while (&client->link != &display->client_list) { while (&client->link != &display->pending_frame_list) {
if (client->pending_frame) { wl_client_marshal(client, &compositor->base,
wl_client_marshal(client, &display->base, WL_COMPOSITOR_FRAME, frame, msecs);
WL_DISPLAY_FRAME, frame, msecs);
client->pending_frame = 0;
}
client = container_of(client->link.next, client = container_of(client->link.next,
struct wl_client, link); struct wl_client, link);
} }
}
WL_EXPORT void wl_list_remove(&display->pending_frame_list);
wl_display_set_compositor(struct wl_display *display, wl_list_init(&display->pending_frame_list);
struct wl_compositor *compositor)
{
display->compositor = compositor;
} }
WL_EXPORT struct wl_event_loop * WL_EXPORT struct wl_event_loop *

@ -73,7 +73,6 @@ struct wl_argument {
struct wl_method { struct wl_method {
const char *name; const char *name;
void *func;
const char *signature; const char *signature;
const void **types; const void **types;
}; };
@ -94,10 +93,10 @@ struct wl_interface {
struct wl_object { struct wl_object {
const struct wl_interface *interface; const struct wl_interface *interface;
void (**implementation)(void);
uint32_t id; uint32_t id;
}; };
struct wl_surface;
struct wl_display; struct wl_display;
struct wl_input_device; struct wl_input_device;
@ -105,9 +104,6 @@ struct wl_map {
int32_t x, y, width, height; int32_t x, y, width, height;
}; };
void wl_surface_set_data(struct wl_surface *surface, void *data);
void *wl_surface_get_data(struct wl_surface *surface);
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);
@ -121,50 +117,66 @@ wl_display_add_global(struct wl_display *display, struct wl_object *object);
const struct wl_interface * const struct wl_interface *
wl_input_device_get_interface(void); wl_input_device_get_interface(void);
void
wl_display_post_frame(struct wl_display *display,
uint32_t frame, uint32_t msecs);
#define WL_INPUT_MOTION 0 #define WL_INPUT_MOTION 0
#define WL_INPUT_BUTTON 1 #define WL_INPUT_BUTTON 1
#define WL_INPUT_KEY 2 #define WL_INPUT_KEY 2
struct wl_compositor {
struct wl_object base;
};
struct wl_surface {
struct wl_object base;
struct wl_client *client;
};
struct wl_compositor_interface {
void (*create_surface)(struct wl_client *client,
struct wl_compositor *compositor, uint32_t id);
void (*commit)(struct wl_client *client,
struct wl_compositor *compositor, uint32_t key);
};
struct wl_surface_interface {
void (*destroy)(struct wl_client *client,
struct wl_surface *surface);
void (*attach)(struct wl_client *client,
struct wl_surface *surface, uint32_t name,
uint32_t width, uint32_t height, uint32_t stride);
void (*map)(struct wl_client *client,
struct wl_surface *surface,
int32_t x, int32_t y, int32_t width, int32_t height);
void (*copy)(struct wl_client *client, struct wl_surface *surface,
int32_t dst_x, int32_t dst_y, uint32_t name, uint32_t stride,
int32_t x, int32_t y, int32_t width, int32_t height);
void (*damage)(struct wl_client *client, struct wl_surface *surface,
int32_t x, int32_t y, int32_t width, int32_t height);
};
void void
wl_surface_post_event(struct wl_surface *surface, wl_surface_post_event(struct wl_surface *surface,
struct wl_object *sender, struct wl_object *sender,
uint32_t event, ...); uint32_t event, ...);
struct wl_compositor { int
const struct wl_compositor_interface *interface; wl_display_set_compositor(struct wl_display *display,
}; struct wl_compositor *compositor,
const struct wl_compositor_interface *implementation);
struct wl_compositor_interface { int
void (*notify_surface_create)(struct wl_compositor *compositor, wl_client_add_surface(struct wl_client *client,
struct wl_surface *surface); struct wl_surface *surface,
void (*notify_surface_destroy)(struct wl_compositor *compositor, const struct wl_surface_interface *implementation,
struct wl_surface *surface); uint32_t id);
void (*notify_surface_attach)(struct wl_compositor *compositor,
struct wl_surface *surface, void
uint32_t name, wl_client_send_acknowledge(struct wl_client *client,
uint32_t width, uint32_t height, struct wl_compositor *compositor,
uint32_t stride); uint32_t key, uint32_t frame);
void (*notify_surface_map)(struct wl_compositor *compositor,
struct wl_surface *surface,
struct wl_map *map);
void (*notify_surface_copy)(struct wl_compositor *compositor,
struct wl_surface *surface,
int32_t dst_x, int32_t dst_y,
uint32_t name, uint32_t stride,
int32_t x, int32_t y,
int32_t width, int32_t height);
void (*notify_surface_damage)(struct wl_compositor *compositor,
struct wl_surface *surface,
int32_t x, int32_t y,
int32_t width, int32_t height);
uint32_t (*notify_commit)(struct wl_compositor *compositor);
};
void wl_display_set_compositor(struct wl_display *display, void
struct wl_compositor *compositor); wl_display_post_frame(struct wl_display *display,
struct wl_compositor *compositor,
uint32_t frame, uint32_t msecs);
#endif #endif

@ -41,6 +41,7 @@
struct window { struct window {
struct wl_display *display; struct wl_display *display;
struct wl_compositor *compositor;
struct wl_surface *surface; struct wl_surface *surface;
const char *title; const char *title;
int x, y, width, height; int x, y, width, height;
@ -196,9 +197,9 @@ event_handler(struct wl_display *display,
int location; int location;
int grip_size = 16; int grip_size = 16;
/* FIXME: Object ID 1 is the display, for anything else we /* FIXME: Object ID 2 is the compositor, for anything else we
* assume it's an input device. */ * assume it's an input device. */
if (object == 1 && opcode == 3) { if (object == 2 && opcode == 0) {
uint32_t key = p[0]; uint32_t key = p[0];
/* Ignore acknowledge events for window move requests. */ /* Ignore acknowledge events for window move requests. */
@ -218,7 +219,7 @@ event_handler(struct wl_display *display,
(*window->acknowledge_handler)(window, key, (*window->acknowledge_handler)(window, key,
window->user_data); window->user_data);
} else if (object == 1 && opcode == 4) { } else if (object == 2 && opcode == 1) {
/* The frame event means that the previous frame was /* The frame event means that the previous frame was
* composited, and we can now send the request to copy * composited, and we can now send the request to copy
* the frame we've rendered in the mean time into the * the frame we've rendered in the mean time into the
@ -244,7 +245,7 @@ event_handler(struct wl_display *display,
window->y - window->margin, window->y - window->margin,
window->width + 2 * window->margin, window->width + 2 * window->margin,
window->height + 2 * window->margin); window->height + 2 * window->margin);
wl_display_commit(window->display, 1); wl_compositor_commit(window->compositor, 1);
break; break;
case WINDOW_RESIZING_LOWER_RIGHT: case WINDOW_RESIZING_LOWER_RIGHT:
if (window->grab_device != object) if (window->grab_device != object)
@ -387,7 +388,8 @@ window_create(struct wl_display *display, int fd,
memset(window, 0, sizeof *window); memset(window, 0, sizeof *window);
window->display = display; window->display = display;
window->title = strdup(title); window->title = strdup(title);
window->surface = wl_display_create_surface(display); window->compositor = wl_display_get_compositor(display);
window->surface = wl_compositor_create_surface(window->compositor);
window->x = x; window->x = x;
window->y = y; window->y = y;
window->minimum_width = 100; window->minimum_width = 100;

Loading…
Cancel
Save