[PATCH v3 xserver 2/2] xwayland: Cache globals to avoid multiple registry objects

Ander Conselvan de Oliveira conselvan2 at gmail.com
Fri Nov 23 01:09:35 PST 2012


On 11/22/2012 10:08 PM, Tiago Vignatti wrote:
> Signed-off-by: Tiago Vignatti <tiago.vignatti at intel.com>
> ---
>
> Hi Kristian, I guess that was the idea we discussed on IRC?
>
> I kept the same order of the interfaces being bound, without thinking whether
> their were the most efficient or something; we we'll have to overhaul the
> WM and X server binding anyway when the next protocol comes in so I hope this
> is okay for now.

[...]

> diff --git a/hw/xfree86/xwayland/xwayland-output.c b/hw/xfree86/xwayland/xwayland-output.c
> index 8f087f6..00b410b 100644
> --- a/hw/xfree86/xwayland/xwayland-output.c
> +++ b/hw/xfree86/xwayland/xwayland-output.c
> @@ -267,43 +267,33 @@ static const struct wl_output_listener output_listener = {
>   };
>
>   static void
> -global_handler(void *data, struct wl_registry *registry, uint32_t id,
> -	       const char *interface, uint32_t version)
> +xwl_output_bind(struct xwl_screen *xwl_screen)
>   {
> -    struct xwl_screen *xwl_screen = data;
> +    struct xwl_global *xwl_global = xwl_global_get(xwl_screen, "wl_output");

In the case of multiple outputs, the global handler would be called 
multiple times, but now xwl_global_get() will only return the first 
output. So with this change you only ever create one output.

 From a quick glance at the code, however, it doesn't look like it 
handled multiple outputs properly before.

Cheers,
Ander

>       struct xwl_output *xwl_output;
> +    int ret;
> +
> +    xwl_output = xwl_output_create(xwl_screen);
> +    xwl_output->output = wl_registry_bind(xwl_screen->registry, xwl_global->id,
> +                                          &wl_output_interface, 1);
> +    wl_output_add_listener(xwl_output->output, &output_listener, xwl_output);
>
> -    if (strcmp (interface, "wl_output") == 0) {
> -	xwl_output = xwl_output_create(xwl_screen);
> -	xwl_output->output = wl_registry_bind(registry, id,
> -	                                      &wl_output_interface, 1);
> -	wl_output_add_listener(xwl_output->output,
> -			       &output_listener, xwl_output);
> +    while (!xwl_screen->xwl_output) {
> +        ret = wl_display_roundtrip(xwl_screen->display);
> +        if (ret == -1)
> +            FatalError("failed to dispatch Wayland events: %s\n",
> +	               strerror(errno));
>       }
>   }
>
> -static const struct wl_registry_listener global_listener = {
> -    global_handler,
> -};
> -
>   void
>   xwayland_screen_preinit_output(struct xwl_screen *xwl_screen, ScrnInfoPtr scrninfo)
>   {
> -    int ret;
> -
>       xf86CrtcConfigInit(scrninfo, &config_funcs);
>
>       xf86CrtcSetSizeRange(scrninfo, 320, 200, 8192, 8192);
>
> -    xwl_screen->output_registry = wl_display_get_registry(xwl_screen->display);
> -    wl_registry_add_listener(xwl_screen->output_registry, &global_listener,
> -                             xwl_screen);
> -
> -    while (!xwl_screen->xwl_output) {
> -        ret = wl_display_roundtrip(xwl_screen->display);
> -        if (ret == -1)
> -            FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
> -    }
> +    xwl_output_bind(xwl_screen);
>
>       xf86InitialConfiguration(scrninfo, TRUE);
>   }
> diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h
> index 23263d0..2716ebe 100644
> --- a/hw/xfree86/xwayland/xwayland-private.h
> +++ b/hw/xfree86/xwayland/xwayland-private.h
> @@ -38,6 +38,14 @@ struct xwl_window {
>
>   struct xwl_output;
>
> +struct xwl_global {
> +    uint32_t			 id;
> +    char			*interface;
> +    uint32_t			 version;
> +
> +    struct xorg_list		 link;
> +};
> +
>   struct xwl_screen {
>       struct xwl_driver		*driver;
>       ScreenPtr			 screen;
> @@ -46,10 +54,10 @@ struct xwl_screen {
>       int				 wayland_fd;
>       struct xwl_output		*xwl_output;
>       struct wl_display		*display;
> +
> +    struct xorg_list		 global_list;
>       struct wl_registry          *registry;
> -    struct wl_registry          *drm_registry;
> -    struct wl_registry          *input_registry;
> -    struct wl_registry          *output_registry;
> +
>       struct wl_compositor	*compositor;
>       struct wl_drm		*drm;
>       struct wl_shm		*shm;
> @@ -100,6 +108,9 @@ struct xwl_seat {
>       CursorPtr                    x_cursor;
>   };
>
> +struct xwl_global *
> +xwl_global_get(struct xwl_screen *xwl_screen, const char *interface);
> +
>   struct xwl_screen *xwl_screen_get(ScreenPtr screen);
>
>   void xwayland_screen_preinit_output(struct xwl_screen *xwl_screen, ScrnInfoPtr scrninfo);
> @@ -111,12 +122,10 @@ struct xwl_output *xwl_output_create(struct xwl_screen *xwl_screen);
>
>   void xwl_input_teardown(pointer p);
>   pointer xwl_input_setup(pointer module, pointer opts, int *errmaj, int *errmin);
> -void xwl_input_init(struct xwl_screen *screen);
>
>   Bool xwl_drm_initialised(struct xwl_screen *screen);
>
> +void xwl_seat_bind(struct xwl_screen *screen);
>   void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
>
> -extern const struct xserver_listener xwl_server_listener;
> -
>   #endif /* _XWAYLAND_PRIVATE_H_ */
> diff --git a/hw/xfree86/xwayland/xwayland.c b/hw/xfree86/xwayland/xwayland.c
> index 98e036e..3396e5f 100644
> --- a/hw/xfree86/xwayland/xwayland.c
> +++ b/hw/xfree86/xwayland/xwayland.c
> @@ -68,12 +68,23 @@ xserver_listen_socket(void *data, struct xserver *xserver, int fd)
>       ListenOnOpenFD(fd, TRUE);
>   }
>
> -const struct xserver_listener xwl_server_listener = {
> +static const struct xserver_listener xwl_server_listener = {
>       xserver_client,
>       xserver_listen_socket
>   };
>
>   static void
> +xwl_xserver_bind(struct xwl_screen *xwl_screen)
> +{
> +    struct xwl_global *xwl_global = xwl_global_get(xwl_screen, "xserver");
> +
> +    xwl_screen->xorg_server = wl_registry_bind(xwl_screen->registry,
> +	                             xwl_global->id, &xserver_interface, 1);
> +    xserver_add_listener(xwl_screen->xorg_server, &xwl_server_listener,
> +                         xwl_screen);
> +}
> +
> +static void
>   xwl_input_delayed_init(void *data, struct wl_callback *callback, uint32_t time)
>   {
>       struct xwl_screen *xwl_screen = data;
> @@ -81,26 +92,59 @@ xwl_input_delayed_init(void *data, struct wl_callback *callback, uint32_t time)
>       ErrorF("xwl_input_delayed_init\n");
>
>       wl_callback_destroy(callback);
> -    xwl_input_init(xwl_screen);
> +
> +    xwl_seat_bind(xwl_screen);
> +    xwl_xserver_bind(xwl_screen);
>   }
>
>   static const struct wl_callback_listener delayed_init_listner = {
>   	xwl_input_delayed_init
>   };
>
> +struct xwl_global *
> +xwl_global_get(struct xwl_screen *xwl_screen, const char *interface)
> +{
> +    struct xwl_global *xwl_global = NULL;
> +
> +    xorg_list_for_each_entry(xwl_global,
> +                             &xwl_screen->global_list, link) {
> +        if (strcmp(xwl_global->interface, interface) == 0)
> +            return xwl_global;
> +    }
> +
> +    ErrorF("failed to find global object %s\n", interface);
> +    return NULL;
> +}
> +
>   static void
>   registry_global(void *data, struct wl_registry *registry, uint32_t id,
>   	        const char *interface, uint32_t version)
>   {
>       struct xwl_screen *xwl_screen = data;
> +    struct xwl_global *xwl_global;
>
>       if (strcmp (interface, "wl_compositor") == 0) {
>   	xwl_screen->compositor =
>               wl_registry_bind(registry, id, &wl_compositor_interface, 1);
> +	return;
>       } else if (strcmp(interface, "wl_shm") == 0) {
>           xwl_screen->shm =
>               wl_registry_bind(registry, id, &wl_shm_interface, 1);
> +	return;
>       }
> +
> +    /* cache list of globals, so we can bind the interfaces later in a desired
> +     * order */
> +    xwl_global = calloc(sizeof *xwl_global, 1);
> +    if (xwl_global == NULL) {
> +	ErrorF("registry_global ENOMEM\n");
> +	return ;
> +    }
> +    xwl_global->id = id;
> +    xwl_global->interface = strdup(interface);
> +    xwl_global->version = version;
> +
> +    xorg_list_add(&xwl_global->link, &xwl_screen->global_list);
>   }
>
>   static const struct wl_registry_listener registry_listener = {
> @@ -233,6 +277,7 @@ xwl_screen_pre_init(ScrnInfoPtr scrninfo, struct xwl_screen *xwl_screen,
>       xorg_list_init(&xwl_screen->seat_list);
>       xorg_list_init(&xwl_screen->damage_window_list);
>       xorg_list_init(&xwl_screen->window_list);
> +    xorg_list_init(&xwl_screen->global_list);
>       xwl_screen->scrninfo = scrninfo;
>       xwl_screen->driver = driver;
>       xwl_screen->flags = flags;
> @@ -287,6 +332,7 @@ void xwl_screen_close(struct xwl_screen *xwl_screen)
>   {
>       struct xwl_seat *xwl_seat, *itmp;
>       struct xwl_window *xwl_window, *wtmp;
> +    struct xwl_global *xwl_global, *gtmp;
>
>       if (xwl_screen->registry)
>           wl_registry_destroy(xwl_screen->registry);
> @@ -303,10 +349,16 @@ void xwl_screen_close(struct xwl_screen *xwl_screen)
>   	wl_surface_destroy(xwl_window->surface);
>   	free(xwl_window);
>       }
> +    xorg_list_for_each_entry_safe(xwl_global, gtmp,
> +				  &xwl_screen->global_list, link) {
> +	free(xwl_global->interface);
> +	free(xwl_global);
> +    }
>
>       xorg_list_init(&xwl_screen->seat_list);
>       xorg_list_init(&xwl_screen->damage_window_list);
>       xorg_list_init(&xwl_screen->window_list);
> +    xorg_list_init(&xwl_screen->global_list);
>
>       wl_display_roundtrip(xwl_screen->display);
>   }
>



More information about the wayland-devel mailing list