[weston v2 1/4] window: Allow hinting of a preference for RGB565 when creating a window

Kristian Høgsberg hoegsberg at gmail.com
Mon Jul 29 10:08:11 PDT 2013


On Thu, Jul 11, 2013 at 04:08:21PM +0200, Tomeu Vizoso wrote:
> And check if the renderer supports the RGB565 format for wl_shm buffers
> before creating the cairo surface and requesting the buffer.
> 
> It can save quite some memory with big surfaces such as desktop
> backgrounds.

That's a cool feature, makes sense.

> ---
>  clients/desktop-shell.c |  8 ++++----
>  clients/keyboard.c      |  2 +-
>  clients/tablet-shell.c  |  6 +++---
>  clients/window.c        | 49 +++++++++++++++++++++++++++++++++++++++++--------
>  clients/window.h        |  9 ++++++++-
>  clients/wscreensaver.c  |  2 +-
>  6 files changed, 58 insertions(+), 18 deletions(-)
> 
> diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
> index 1062901..3369a77 100644
> --- a/clients/desktop-shell.c
> +++ b/clients/desktop-shell.c
> @@ -516,7 +516,7 @@ panel_create(struct desktop *desktop)
>  	memset(panel, 0, sizeof *panel);
>  
>  	panel->base.configure = panel_configure;
> -	panel->window = window_create_custom(desktop->display);
> +	panel->window = window_create_custom(desktop->display, WINDOW_HINT_NONE);
>  	panel->widget = window_add_widget(panel->window, panel);
>  	wl_list_init(&panel->launcher_list);
>  
> @@ -846,7 +846,7 @@ unlock_dialog_create(struct desktop *desktop)
>  		return NULL;
>  	memset(dialog, 0, sizeof *dialog);
>  
> -	dialog->window = window_create_custom(display);
> +	dialog->window = window_create_custom(display, WINDOW_HINT_NONE);
>  	dialog->widget = frame_create(dialog->window, dialog);
>  	window_set_title(dialog->window, "Unlock your desktop");
>  
> @@ -993,7 +993,7 @@ background_create(struct desktop *desktop)
>  	memset(background, 0, sizeof *background);
>  
>  	background->base.configure = background_configure;
> -	background->window = window_create_custom(desktop->display);
> +	background->window = window_create_custom(desktop->display, WINDOW_HINT_PREFER_RGB565);
>  	background->widget = window_add_widget(background->window, background);
>  	window_set_user_data(background->window, background);
>  	widget_set_redraw_handler(background->widget, background_draw);
> @@ -1045,7 +1045,7 @@ grab_surface_create(struct desktop *desktop)
>  {
>  	struct wl_surface *s;
>  
> -	desktop->grab_window = window_create_custom(desktop->display);
> +	desktop->grab_window = window_create_custom(desktop->display, WINDOW_HINT_NONE);
>  	window_set_user_data(desktop->grab_window, desktop);
>  
>  	s = window_get_wl_surface(desktop->grab_window);
> diff --git a/clients/keyboard.c b/clients/keyboard.c
> index a2fbded..96f53f4 100644
> --- a/clients/keyboard.c
> +++ b/clients/keyboard.c
> @@ -840,7 +840,7 @@ keyboard_create(struct output *output, struct virtual_keyboard *virtual_keyboard
>  	memset(keyboard, 0, sizeof *keyboard);
>  
>  	keyboard->keyboard = virtual_keyboard;
> -	keyboard->window = window_create_custom(virtual_keyboard->display);
> +	keyboard->window = window_create_custom(virtual_keyboard->display, WINDOW_HINT_NONE);
>  	keyboard->widget = window_add_widget(keyboard->window, keyboard);
>  
>  	virtual_keyboard->keyboard = keyboard;
> diff --git a/clients/tablet-shell.c b/clients/tablet-shell.c
> index 3d5e79a..9a50131 100644
> --- a/clients/tablet-shell.c
> +++ b/clients/tablet-shell.c
> @@ -233,7 +233,7 @@ homescreen_create(struct tablet *tablet)
>  	homescreen = malloc (sizeof *homescreen);
>  	memset(homescreen, 0, sizeof *homescreen);
>  
> -	homescreen->window = window_create_custom(tablet->display);
> +	homescreen->window = window_create_custom(tablet->display, WINDOW_HINT_NONE);
>  	homescreen->widget =
>  		window_add_widget(homescreen->window, homescreen);
>  	window_set_user_data(homescreen->window, homescreen);
> @@ -251,7 +251,7 @@ lockscreen_create(struct tablet *tablet)
>  	lockscreen = malloc (sizeof *lockscreen);
>  	memset(lockscreen, 0, sizeof *lockscreen);
>  
> -	lockscreen->window = window_create_custom(tablet->display);
> +	lockscreen->window = window_create_custom(tablet->display, WINDOW_HINT_NONE);
>  	lockscreen->widget =
>  		window_add_widget(lockscreen->window, lockscreen);
>  	window_set_user_data(lockscreen->window, lockscreen);
> @@ -282,7 +282,7 @@ show_switcher(void *data, struct tablet_shell *tablet_shell)
>  {
>  	struct tablet *tablet = data;
>  
> -	tablet->switcher = window_create_custom(tablet->display);
> +	tablet->switcher = window_create_custom(tablet->display, WINDOW_HINT_NONE);
>  	window_set_user_data(tablet->switcher, tablet);
>  	tablet_shell_set_switcher(tablet->tablet_shell,
>  				  window_get_wl_surface(tablet->switcher));
> diff --git a/clients/window.c b/clients/window.c
> index cff7102..0cf9ffd 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -128,6 +128,8 @@ struct display {
>  	/* A hack to get text extents for tooltips */
>  	cairo_surface_t *dummy_surface;
>  	void *dummy_surface_data;
> +
> +	int has_rgb565;
>  };
>  
>  enum {
> @@ -237,6 +239,8 @@ struct window {
>  	int fullscreen_method;
>  	int configure_requests;
>  
> +	enum window_hint hints;
> +
>  	window_key_handler_t key_handler;
>  	window_keyboard_focus_handler_t keyboard_focus_handler;
>  	window_data_handler_t data_handler;
> @@ -794,6 +798,7 @@ display_create_shm_surface_from_pool(struct display *display,
>  	struct shm_surface_data *data;
>  	uint32_t format;
>  	cairo_surface_t *surface;
> +	cairo_format_t cairo_format;
>  	int stride, length, offset;
>  	void *map;
>  
> @@ -801,8 +806,12 @@ display_create_shm_surface_from_pool(struct display *display,
>  	if (data == NULL)
>  		return NULL;
>  
> -	stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
> -						rectangle->width);
> +	if (flags & SURFACE_HINT_RGB565 && display->has_rgb565)
> +		cairo_format = CAIRO_FORMAT_RGB16_565;
> +	else
> +		cairo_format = CAIRO_FORMAT_ARGB32;
> +
> +	stride = cairo_format_stride_for_width (cairo_format, rectangle->width);
>  	length = stride * rectangle->height;
>  	data->pool = NULL;
>  	map = shm_pool_allocate(pool, length, &offset);
> @@ -813,7 +822,7 @@ display_create_shm_surface_from_pool(struct display *display,
>  	}
>  
>  	surface = cairo_image_surface_create_for_data (map,
> -						       CAIRO_FORMAT_ARGB32,
> +						       cairo_format,
>  						       rectangle->width,
>  						       rectangle->height,
>  						       stride);
> @@ -821,10 +830,14 @@ display_create_shm_surface_from_pool(struct display *display,
>  	cairo_surface_set_user_data(surface, &shm_surface_data_key,
>  				    data, shm_surface_data_destroy);
>  
> -	if (flags & SURFACE_OPAQUE)
> -		format = WL_SHM_FORMAT_XRGB8888;
> -	else
> -		format = WL_SHM_FORMAT_ARGB8888;
> +	if (flags & SURFACE_HINT_RGB565 && display->has_rgb565)
> +		format = WL_SHM_FORMAT_RGB565;
> +	else {
> +		if (flags & SURFACE_OPAQUE)
> +			format = WL_SHM_FORMAT_XRGB8888;
> +		else
> +			format = WL_SHM_FORMAT_ARGB8888;
> +	}
>  
>  	data->buffer = wl_shm_pool_create_buffer(pool->pool, offset,
>  						 rectangle->width,
> @@ -1425,6 +1438,9 @@ window_create_main_surface(struct window *window)
>  	if (window->resizing)
>  		flags |= SURFACE_HINT_RESIZE;
>  
> +	if (window->hints & WINDOW_HINT_PREFER_RGB565)
> +		flags |= SURFACE_HINT_RGB565;
> +
>  	if (window->resize_edges & WINDOW_RESIZING_LEFT)
>  		dx = surface->server_allocation.width -
>  			surface->allocation.width;
> @@ -4202,6 +4218,7 @@ window_create_internal(struct display *display,
>  	window->type = type;
>  	window->fullscreen_method = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
>  	window->configure_requests = 0;
> +	window->hints = WINDOW_HINT_NONE;
>  
>  	if (display->argb_device)
>  #ifdef HAVE_CAIRO_EGL
> @@ -4240,7 +4257,7 @@ window_create(struct display *display)
>  }
>  
>  struct window *
> -window_create_custom(struct display *display)
> +window_create_custom(struct display *display, enum window_hint hints)
>  {
>  	struct window *window;
>  
> @@ -4248,6 +4265,8 @@ window_create_custom(struct display *display)
>  	if (!window)
>  		return NULL;
>  
> +	window->hints = hints;
> +
>  	return window;
>  }
>  
> @@ -4737,6 +4756,19 @@ init_workspace_manager(struct display *d, uint32_t id)
>  }
>  
>  static void
> +shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
> +{
> +	struct display *d = data;
> +
> +	if (format == WL_SHM_FORMAT_RGB565)
> +		d->has_rgb565 = 1;
> +}
> +
> +struct wl_shm_listener shm_listener = {
> +	shm_format
> +};
> +
> +static void
>  registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
>  		       const char *interface, uint32_t version)
>  {
> @@ -4761,6 +4793,7 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
>  					    id, &wl_shell_interface, 1);
>  	} else if (strcmp(interface, "wl_shm") == 0) {
>  		d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
> +		wl_shm_add_listener(d->shm, &shm_listener, d);
>  	} else if (strcmp(interface, "wl_data_device_manager") == 0) {
>  		d->data_device_manager =
>  			wl_registry_bind(registry, id,
> diff --git a/clients/window.h b/clients/window.h
> index a79b020..24bd257 100644
> --- a/clients/window.h
> +++ b/clients/window.h
> @@ -132,6 +132,8 @@ display_release_window_surface(struct display *display,
>  
>  #define SURFACE_HINT_RESIZE 0x10
>  
> +#define SURFACE_HINT_RGB565 0x100
> +
>  cairo_surface_t *
>  display_create_surface(struct display *display,
>  		       struct wl_surface *surface,
> @@ -226,13 +228,18 @@ typedef void (*widget_axis_handler_t)(struct widget *widget,
>  				      wl_fixed_t value,
>  				      void *data);
>  
> +enum window_hint {
> +	WINDOW_HINT_NONE = 1 << 0,
> +	WINDOW_HINT_PREFER_RGB565 = 1 << 1,
> +};
> +

I was going to say that WINDOW_HINT_NONE should be 0 and
WINDOW_HINT_PREFER_RGB565 should be 1 << 0, but I think I'd prefer either a
new

	window_set_hint(window, hint);

function or even simpler

	window_set_format(window, format);

with the assumption that the format is just a hint/best effort thing.

Kristian


>  struct window *
>  window_create(struct display *display);
>  struct window *
>  window_create_transient(struct display *display, struct window *parent,
>  			int32_t x, int32_t y, uint32_t flags);
>  struct window *
> -window_create_custom(struct display *display);
> +window_create_custom(struct display *display, enum window_hint hints);
>  
>  int
>  window_has_focus(struct window *window);
> diff --git a/clients/wscreensaver.c b/clients/wscreensaver.c
> index 9a2c47a..32e397a 100644
> --- a/clients/wscreensaver.c
> +++ b/clients/wscreensaver.c
> @@ -184,7 +184,7 @@ create_wscreensaver_instance(struct wscreensaver *screensaver,
>  	if (demo_mode)
>  		mi->window = window_create(screensaver->display);
>  	else
> -		mi->window = window_create_custom(screensaver->display);
> +		mi->window = window_create_custom(screensaver->display, WINDOW_HINT_NONE);
>  
>  	if (!mi->window) {
>  		fprintf(stderr, "%s: creating a window failed.\n", progname);
> -- 
> 1.8.3.1
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list