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. --- clients/desktop-shell.c | 8 ++++---- clients/keyboard.c | 2 +- clients/tablet-shell.c | 6 +++--- clients/window.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- clients/window.h | 4 +++- clients/wscreensaver.c | 2 +- 6 files changed, 53 insertions(+), 18 deletions(-) diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index 51ce3ec..dc375f8 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -534,7 +534,7 @@ panel_create(struct display *display) memset(panel, 0, sizeof *panel); panel->base.configure = panel_configure; - panel->window = window_create_custom(display); + panel->window = window_create_custom(display, 0); panel->widget = window_add_widget(panel->window, panel); wl_list_init(&panel->launcher_list); @@ -869,7 +869,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, 0); dialog->widget = frame_create(dialog->window, dialog); window_set_title(dialog->window, "Unlock your desktop"); @@ -1013,7 +1013,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, 1); background->widget = window_add_widget(background->window, background); window_set_user_data(background->window, background); widget_set_redraw_handler(background->widget, background_draw); @@ -1042,7 +1042,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, 0); 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..fe308dd 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, 0); 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..afbd0f8 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, 0); 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, 0); 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, 0); 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..78d74e8 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; + int prefer_rgb565; + 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->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->prefer_rgb565 = 0; 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, int prefer_rgb565) { struct window *window; @@ -4248,6 +4265,8 @@ window_create_custom(struct display *display) if (!window) return NULL; + window->prefer_rgb565 = prefer_rgb565; + 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..d495ce4 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, @@ -232,7 +234,7 @@ 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, int prefer_rgb565); int window_has_focus(struct window *window); diff --git a/clients/wscreensaver.c b/clients/wscreensaver.c index 9a2c47a..a0bc827 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, 0); if (!mi->window) { fprintf(stderr, "%s: creating a window failed.\n", progname); -- 1.8.3.1 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel