diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index ad324ba7..9bd0adeb 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -995,6 +995,8 @@ background_create(struct desktop *desktop) background->widget = window_add_widget(background->window, background); window_set_user_data(background->window, background); widget_set_redraw_handler(background->widget, background_draw); + window_set_preferred_format(background->window, + WINDOW_PREFERRED_FORMAT_RGB565); s = weston_config_get_section(desktop->config, "shell", NULL, NULL); weston_config_section_get_string(s, "background-image", diff --git a/clients/window.c b/clients/window.c index d9f7d5ae..b9045f34 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 preferred_format preferred_format; + 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->preferred_format == WINDOW_PREFERRED_FORMAT_RGB565) + flags |= SURFACE_HINT_RGB565; + if (window->resize_edges & WINDOW_RESIZING_LEFT) dx = surface->server_allocation.width - surface->allocation.width; @@ -4209,6 +4225,7 @@ window_create_internal(struct display *display, window->type = type; window->fullscreen_method = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT; window->configure_requests = 0; + window->preferred_format = WINDOW_PREFERRED_FORMAT_NONE; if (display->argb_device) #ifdef HAVE_CAIRO_EGL @@ -4432,6 +4449,13 @@ window_set_buffer_type(struct window *window, enum window_buffer_type type) window->main_surface->buffer_type = type; } +void +window_set_preferred_format(struct window *window, + enum preferred_format format) +{ + window->preferred_format = format; +} + struct widget * window_add_subsurface(struct window *window, void *data, enum subsurface_mode default_mode) @@ -4729,6 +4753,19 @@ init_workspace_manager(struct display *d, uint32_t id) d); } +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) @@ -4754,6 +4791,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 75be1651..e045b956 100644 --- a/clients/window.h +++ b/clients/window.h @@ -139,6 +139,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, @@ -383,6 +385,15 @@ window_get_title(struct window *window); void window_set_text_cursor_position(struct window *window, int32_t x, int32_t y); +enum preferred_format { + WINDOW_PREFERRED_FORMAT_NONE, + WINDOW_PREFERRED_FORMAT_RGB565 +}; + +void +window_set_preferred_format(struct window *window, + enum preferred_format format); + int widget_set_tooltip(struct widget *parent, char *entry, float x, float y);