summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2011-08-19 16:57:48 -0400
committerKristian Høgsberg <krh@bitplanet.net>2011-08-27 12:06:11 -0400
commitcc6fd94d6a5743eb94b52f1887557305784525c9 (patch)
tree31455a407711ddbaa2994182a32892b76857c523
parentc4774d55e91a722e29326c30ab49dcc3850e0a00 (diff)
Always allocate a new wl_resource when binding an object
Previously we would bind some resources into multiple client hash tables.
-rw-r--r--protocol/wayland.xml6
-rw-r--r--src/wayland-server.c209
-rw-r--r--src/wayland-server.h23
-rw-r--r--src/wayland-shm.c24
-rw-r--r--src/wayland-util.h2
5 files changed, 151 insertions, 113 deletions
diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index ac1e2e5..70b505d 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -66,8 +66,8 @@
server will always announce an object before the object sends
out events. -->
<event name="global">
- <arg name="id" type="uint" interface="wl_object"/>
- <arg name="name" type="string"/>
+ <arg name="name" type="uint" interface="wl_object"/>
+ <arg name="interface" type="string"/>
<arg name="version" type="uint"/>
</event>
@@ -109,7 +109,7 @@
</enum>
<event name="token_visual">
- <arg name="visual" type="new_id" interface="wl_visual"/>
+ <arg name="name" type="uint"/>
<arg name="token" type="uint"/>
</event>
</interface>
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 337ac0b..0f15afd 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -57,7 +57,7 @@ struct wl_client {
struct wl_connection *connection;
struct wl_event_source *source;
struct wl_display *display;
- struct wl_resource display_resource;
+ struct wl_resource *display_resource;
struct wl_list resource_list;
uint32_t id_count;
uint32_t mask;
@@ -80,7 +80,9 @@ struct wl_display {
};
struct wl_global {
- struct wl_object *object;
+ const struct wl_interface *interface;
+ uint32_t name;
+ void *data;
wl_global_bind_func_t bind;
struct wl_list link;
};
@@ -119,7 +121,7 @@ wl_client_post_error(struct wl_client *client, struct wl_object *object,
vsnprintf(buffer, sizeof buffer, msg, ap);
va_end(ap);
- wl_resource_post_event(&client->display_resource,
+ wl_resource_post_event(client->display_resource,
WL_DISPLAY_ERROR, object, code, buffer);
}
@@ -242,17 +244,20 @@ wl_client_get_display(struct wl_client *client)
static void
wl_display_post_range(struct wl_display *display, struct wl_client *client)
{
- wl_resource_post_event(&client->display_resource,
+ wl_resource_post_event(client->display_resource,
WL_DISPLAY_RANGE, display->client_id_range);
display->client_id_range += 256;
client->id_count += 256;
}
+static void
+bind_display(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id);
+
WL_EXPORT struct wl_client *
wl_client_create(struct wl_display *display, int fd)
{
struct wl_client *client;
- struct wl_global *global;
client = malloc(sizeof *client);
if (client == NULL)
@@ -277,22 +282,12 @@ wl_client_create(struct wl_display *display, int fd)
return NULL;
}
- client->display_resource.object = display->resource.object;
- client->display_resource.client = client;
- client->display_resource.data = &display->resource;
-
- wl_hash_table_insert(client->objects,
- client->display_resource.object.id,
- &client->display_resource);
+ bind_display(client, display, 1, 1);
wl_list_insert(display->client_list.prev, &client->link);
wl_list_init(&client->resource_list);
- wl_display_post_range(display, client);
-
- wl_list_for_each(global, &display->global_list, link)
- wl_client_post_global(client, global->object);
return client;
}
@@ -321,16 +316,6 @@ wl_client_post_no_memory(struct wl_client *client)
}
WL_EXPORT void
-wl_client_post_global(struct wl_client *client, struct wl_object *object)
-{
- wl_resource_post_event(&client->display_resource,
- WL_DISPLAY_GLOBAL,
- object->id,
- object->interface->name,
- object->interface->version);
-}
-
-WL_EXPORT void
wl_resource_destroy(struct wl_resource *resource, uint32_t time)
{
struct wl_client *client = resource->client;
@@ -551,17 +536,15 @@ display_bind(struct wl_client *client,
struct wl_display *display = resource->data;
wl_list_for_each(global, &display->global_list, link)
- if (global->object->id == name)
+ if (global->name == name)
break;
if (&global->link == &display->global_list)
wl_client_post_error(client, &client->display->resource.object,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"invalid global %d", name);
- else if (global->bind)
- global->bind(client, global->object, version, id);
-
- wl_hash_table_insert(client->objects, id, global->object);
+ else
+ global->bind(client, global->data, version, id);
}
static void
@@ -582,6 +565,26 @@ struct wl_display_interface display_interface = {
display_sync,
};
+static void
+bind_display(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id)
+{
+ struct wl_display *display = data;
+ struct wl_global *global;
+
+ client->display_resource =
+ wl_client_add_object(client, &wl_display_interface,
+ &display_interface, id, display);
+
+ wl_display_post_range(display, client);
+
+ wl_list_for_each(global, &display->global_list, link)
+ wl_resource_post_event(client->display_resource,
+ WL_DISPLAY_GLOBAL,
+ global->name,
+ global->interface->name,
+ global->interface->version);
+}
WL_EXPORT struct wl_display *
wl_display_create(void)
@@ -611,12 +614,9 @@ wl_display_create(void)
display->client_id_range = 256; /* Gah, arbitrary... */
display->id = 1;
- display->resource.object.interface = &wl_display_interface;
- display->resource.object.implementation =
- (void (**)(void)) &display_interface;
- display->resource.data = display;
- if (wl_display_add_global(display, &display->resource.object, NULL)) {
+ if (!wl_display_add_global(display, &wl_display_interface,
+ display, bind_display)) {
wl_event_loop_destroy(display->loop);
free(display);
return NULL;
@@ -646,46 +646,36 @@ wl_display_destroy(struct wl_display *display)
free(display);
}
-WL_EXPORT int
+WL_EXPORT struct wl_global *
wl_display_add_global(struct wl_display *display,
- struct wl_object *object, wl_global_bind_func_t bind)
+ const struct wl_interface *interface,
+ void *data, wl_global_bind_func_t bind)
{
struct wl_global *global;
global = malloc(sizeof *global);
if (global == NULL)
- return -1;
+ return NULL;
- object->id = display->id++;
- global->object = object;
+ global->name = display->id++;
+ global->interface = interface;
+ global->data = data;
global->bind = bind;
wl_list_insert(display->global_list.prev, &global->link);
- return 0;
+ return global;
}
-WL_EXPORT int
-wl_display_remove_global(struct wl_display *display,
- struct wl_object *object)
+WL_EXPORT void
+wl_display_remove_global(struct wl_display *display, struct wl_global *global)
{
- struct wl_global *global;
struct wl_client *client;
- wl_list_for_each(global, &display->global_list, link)
- if (global->object == object)
- break;
-
- if (&global->link == &display->global_list)
- return -1;
-
wl_list_for_each(client, &display->client_list, link)
- wl_resource_post_event(&client->display_resource,
- WL_DISPLAY_GLOBAL_REMOVE,
- global->object->id);
+ wl_resource_post_event(client->display_resource,
+ WL_DISPLAY_GLOBAL_REMOVE, global->name);
wl_list_remove(&global->link);
free(global);
-
- return 0;
}
WL_EXPORT struct wl_event_loop *
@@ -845,30 +835,66 @@ wl_display_add_socket(struct wl_display *display, const char *name)
return 0;
}
+WL_EXPORT struct wl_resource *
+wl_client_add_object(struct wl_client *client,
+ const struct wl_interface *interface,
+ const void *implementation,
+ uint32_t id, void *data)
+{
+ struct wl_resource *resource;
+
+ resource = malloc(sizeof *resource);
+ if (resource == NULL) {
+ wl_client_post_no_memory(client);
+ return NULL;
+ }
+
+ resource->object.interface = interface;
+ resource->object.implementation = implementation;
+ resource->object.id = id;
+ resource->client = client;
+ resource->data = data;
+ resource->destroy = (void *) free;
+ wl_list_init(&resource->destroy_listener_list);
+
+ wl_hash_table_insert(client->objects, resource->object.id, resource);
+
+ return resource;
+}
+
static void
compositor_bind(struct wl_client *client,
- struct wl_object *global, uint32_t version, uint32_t id)
+ void *data, uint32_t version, uint32_t id)
{
- struct wl_compositor *compositor =
- container_of(global, struct wl_compositor, resource.object);
+ struct wl_compositor *compositor = data;
+ struct wl_resource *resource;
- compositor->resource.client = client;
- compositor->resource.object.id = id;
+ resource = wl_client_add_object(client, &wl_compositor_interface,
+ compositor->interface, id, compositor);
- wl_resource_post_event(&compositor->resource,
+ wl_resource_post_event(resource,
WL_COMPOSITOR_TOKEN_VISUAL,
- &compositor->argb_visual.object,
+ compositor->argb_visual.name,
WL_COMPOSITOR_VISUAL_ARGB32);
- wl_resource_post_event(&compositor->resource,
+ wl_resource_post_event(resource,
WL_COMPOSITOR_TOKEN_VISUAL,
- &compositor->premultiplied_argb_visual.object,
+ compositor->premultiplied_argb_visual.name,
WL_COMPOSITOR_VISUAL_PREMULTIPLIED_ARGB32);
- wl_resource_post_event(&compositor->resource,
+ wl_resource_post_event(resource,
WL_COMPOSITOR_TOKEN_VISUAL,
- &compositor->rgb_visual.object,
+ compositor->rgb_visual.name,
WL_COMPOSITOR_VISUAL_XRGB32);
+
+ wl_list_insert(client->resource_list.prev, &resource->link);
+}
+
+static void
+bind_visual(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id)
+{
+ wl_client_add_object(client, &wl_visual_interface, NULL, id, data);
}
WL_EXPORT int
@@ -876,33 +902,32 @@ wl_compositor_init(struct wl_compositor *compositor,
const struct wl_compositor_interface *interface,
struct wl_display *display)
{
- compositor->resource.object.interface = &wl_compositor_interface;
- compositor->resource.object.implementation =
- (void (**)(void)) interface;
- compositor->resource.data = compositor;
- if (wl_display_add_global(display, &compositor->resource.object,
- compositor_bind))
+ struct wl_global *global;
+
+ compositor->interface = interface;
+ global = wl_display_add_global(display, &wl_compositor_interface,
+ compositor, compositor_bind);
+ if (!global)
return -1;
- compositor->argb_visual.object.interface = &wl_visual_interface;
- compositor->argb_visual.object.implementation = NULL;
- if (wl_display_add_global(display,
- &compositor->argb_visual.object, NULL))
+ global = wl_display_add_global(display, &wl_visual_interface,
+ &compositor->argb_visual, bind_visual);
+ if (!global)
+ return -1;
+ compositor->argb_visual.name = global->name;
+
+ global = wl_display_add_global(display, &wl_visual_interface,
+ &compositor->premultiplied_argb_visual,
+ bind_visual);
+ if (!global)
return -1;
+ compositor->premultiplied_argb_visual.name = global->name;
- compositor->premultiplied_argb_visual.object.interface =
- &wl_visual_interface;
- compositor->premultiplied_argb_visual.object.implementation = NULL;
- if (wl_display_add_global(display,
- &compositor->premultiplied_argb_visual.object,
- NULL))
- return -1;
-
- compositor->rgb_visual.object.interface = &wl_visual_interface;
- compositor->rgb_visual.object.implementation = NULL;
- if (wl_display_add_global(display,
- &compositor->rgb_visual.object, NULL))
- return -1;
+ global = wl_display_add_global(display, &wl_visual_interface,
+ &compositor->rgb_visual, bind_visual);
+ if (!global)
+ return -1;
+ compositor->rgb_visual.name = global->name;
return 0;
}
diff --git a/src/wayland-server.h b/src/wayland-server.h
index 2ef4899..c2b2a17 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -85,25 +85,29 @@ void wl_display_run(struct wl_display *display);
void wl_display_add_object(struct wl_display *display,
struct wl_object *object);
-typedef void (*wl_global_bind_func_t)(struct wl_client *client,
- struct wl_object *global,
+typedef void (*wl_global_bind_func_t)(struct wl_client *client, void *data,
uint32_t version, uint32_t id);
-int wl_display_add_global(struct wl_display *display,
- struct wl_object *object,
- wl_global_bind_func_t bind);
+struct wl_global *wl_display_add_global(struct wl_display *display,
+ const struct wl_interface *interface,
+ void *data,
+ wl_global_bind_func_t bind);
-int wl_display_remove_global(struct wl_display *display,
- struct wl_object *object);
+void wl_display_remove_global(struct wl_display *display,
+ struct wl_global *global);
struct wl_client *wl_client_create(struct wl_display *display, int fd);
void wl_client_destroy(struct wl_client *client);
void wl_client_post_error(struct wl_client *client, struct wl_object *object,
uint32_t code, const char *msg, ...);
void wl_client_post_no_memory(struct wl_client *client);
-void wl_client_post_global(struct wl_client *client, struct wl_object *object);
void wl_client_flush(struct wl_client *client);
+struct wl_resource *
+wl_client_add_object(struct wl_client *client,
+ const struct wl_interface *interface,
+ const void *implementation, uint32_t id, void *data);
+
struct wl_resource {
struct wl_object object;
void (*destroy)(struct wl_resource *resource);
@@ -115,6 +119,7 @@ struct wl_resource {
struct wl_visual {
struct wl_object object;
+ uint32_t name;
};
struct wl_shm_callbacks {
@@ -128,7 +133,7 @@ struct wl_shm_callbacks {
};
struct wl_compositor {
- struct wl_resource resource;
+ const struct wl_compositor_interface *interface;
struct wl_visual argb_visual;
struct wl_visual premultiplied_argb_visual;
struct wl_visual rgb_visual;
diff --git a/src/wayland-shm.c b/src/wayland-shm.c
index f9ca327..0324168 100644
--- a/src/wayland-shm.c
+++ b/src/wayland-shm.c
@@ -34,7 +34,6 @@
#include "wayland-server.h"
struct wl_shm {
- struct wl_resource resource;
const struct wl_shm_callbacks *callbacks;
};
@@ -123,7 +122,7 @@ shm_create_buffer(struct wl_client *client, struct wl_resource *resource,
void *data;
if (!visual || visual->object.interface != &wl_visual_interface) {
- wl_client_post_error(client, &shm->resource.object,
+ wl_client_post_error(client, &resource->object,
WL_SHM_ERROR_INVALID_VISUAL,
"invalid visual");
close(fd);
@@ -131,7 +130,7 @@ shm_create_buffer(struct wl_client *client, struct wl_resource *resource,
}
if (width < 0 || height < 0 || stride < width) {
- wl_client_post_error(client, &shm->resource.object,
+ wl_client_post_error(client, &resource->object,
WL_SHM_ERROR_INVALID_STRIDE,
"invalid width, height or stride (%dx%d, %u)",
width, height, stride);
@@ -144,7 +143,7 @@ shm_create_buffer(struct wl_client *client, struct wl_resource *resource,
close(fd);
if (data == MAP_FAILED) {
- wl_client_post_error(client, &shm->resource.object,
+ wl_client_post_error(client, &resource->object,
WL_SHM_ERROR_INVALID_FD,
"failed mmap fd %d", fd);
return;
@@ -166,6 +165,13 @@ const static struct wl_shm_interface shm_interface = {
shm_create_buffer
};
+static void
+bind_shm(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id)
+{
+ wl_client_add_object(client,
+ &wl_shm_interface, &shm_interface, id, data);
+}
WL_EXPORT struct wl_shm *
wl_shm_init(struct wl_display *display,
@@ -177,10 +183,12 @@ wl_shm_init(struct wl_display *display,
if (!shm)
return NULL;
- shm->resource.object.interface = &wl_shm_interface;
- shm->resource.object.implementation = (void (**)(void)) &shm_interface;
- shm->resource.data = shm;
- wl_display_add_global(display, &shm->resource.object, NULL);
+ if (!wl_display_add_global(display,
+ &wl_shm_interface, shm, bind_shm)) {
+
+ free(shm);
+ return NULL;
+ }
shm->callbacks = callbacks;
diff --git a/src/wayland-util.h b/src/wayland-util.h
index f46da10..96dc74d 100644
--- a/src/wayland-util.h
+++ b/src/wayland-util.h
@@ -61,7 +61,7 @@ struct wl_interface {
struct wl_object {
const struct wl_interface *interface;
- void (**implementation)(void);
+ void (* const * implementation)(void);
uint32_t id;
};