window: Allow hinting of a preference for RGB565 when creating a window

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.
This commit is contained in:
Tomeu Vizoso
2013-08-06 20:05:54 +02:00
committed by Kristian Høgsberg
parent 0ff7908767
commit bee45a14cd
3 changed files with 58 additions and 7 deletions
+2
View File
@@ -995,6 +995,8 @@ background_create(struct desktop *desktop)
background->widget = window_add_widget(background->window, background); background->widget = window_add_widget(background->window, background);
window_set_user_data(background->window, background); window_set_user_data(background->window, background);
widget_set_redraw_handler(background->widget, background_draw); 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); s = weston_config_get_section(desktop->config, "shell", NULL, NULL);
weston_config_section_get_string(s, "background-image", weston_config_section_get_string(s, "background-image",
+41 -3
View File
@@ -128,6 +128,8 @@ struct display {
/* A hack to get text extents for tooltips */ /* A hack to get text extents for tooltips */
cairo_surface_t *dummy_surface; cairo_surface_t *dummy_surface;
void *dummy_surface_data; void *dummy_surface_data;
int has_rgb565;
}; };
enum { enum {
@@ -237,6 +239,8 @@ struct window {
int fullscreen_method; int fullscreen_method;
int configure_requests; int configure_requests;
enum preferred_format preferred_format;
window_key_handler_t key_handler; window_key_handler_t key_handler;
window_keyboard_focus_handler_t keyboard_focus_handler; window_keyboard_focus_handler_t keyboard_focus_handler;
window_data_handler_t data_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; struct shm_surface_data *data;
uint32_t format; uint32_t format;
cairo_surface_t *surface; cairo_surface_t *surface;
cairo_format_t cairo_format;
int stride, length, offset; int stride, length, offset;
void *map; void *map;
@@ -801,8 +806,12 @@ display_create_shm_surface_from_pool(struct display *display,
if (data == NULL) if (data == NULL)
return NULL; return NULL;
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, if (flags & SURFACE_HINT_RGB565 && display->has_rgb565)
rectangle->width); 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; length = stride * rectangle->height;
data->pool = NULL; data->pool = NULL;
map = shm_pool_allocate(pool, length, &offset); 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, surface = cairo_image_surface_create_for_data (map,
CAIRO_FORMAT_ARGB32, cairo_format,
rectangle->width, rectangle->width,
rectangle->height, rectangle->height,
stride); stride);
@@ -821,10 +830,14 @@ display_create_shm_surface_from_pool(struct display *display,
cairo_surface_set_user_data(surface, &shm_surface_data_key, cairo_surface_set_user_data(surface, &shm_surface_data_key,
data, shm_surface_data_destroy); data, shm_surface_data_destroy);
if (flags & SURFACE_HINT_RGB565 && display->has_rgb565)
format = WL_SHM_FORMAT_RGB565;
else {
if (flags & SURFACE_OPAQUE) if (flags & SURFACE_OPAQUE)
format = WL_SHM_FORMAT_XRGB8888; format = WL_SHM_FORMAT_XRGB8888;
else else
format = WL_SHM_FORMAT_ARGB8888; format = WL_SHM_FORMAT_ARGB8888;
}
data->buffer = wl_shm_pool_create_buffer(pool->pool, offset, data->buffer = wl_shm_pool_create_buffer(pool->pool, offset,
rectangle->width, rectangle->width,
@@ -1425,6 +1438,9 @@ window_create_main_surface(struct window *window)
if (window->resizing) if (window->resizing)
flags |= SURFACE_HINT_RESIZE; flags |= SURFACE_HINT_RESIZE;
if (window->preferred_format == WINDOW_PREFERRED_FORMAT_RGB565)
flags |= SURFACE_HINT_RGB565;
if (window->resize_edges & WINDOW_RESIZING_LEFT) if (window->resize_edges & WINDOW_RESIZING_LEFT)
dx = surface->server_allocation.width - dx = surface->server_allocation.width -
surface->allocation.width; surface->allocation.width;
@@ -4209,6 +4225,7 @@ window_create_internal(struct display *display,
window->type = type; window->type = type;
window->fullscreen_method = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT; window->fullscreen_method = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
window->configure_requests = 0; window->configure_requests = 0;
window->preferred_format = WINDOW_PREFERRED_FORMAT_NONE;
if (display->argb_device) if (display->argb_device)
#ifdef HAVE_CAIRO_EGL #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; window->main_surface->buffer_type = type;
} }
void
window_set_preferred_format(struct window *window,
enum preferred_format format)
{
window->preferred_format = format;
}
struct widget * struct widget *
window_add_subsurface(struct window *window, void *data, window_add_subsurface(struct window *window, void *data,
enum subsurface_mode default_mode) enum subsurface_mode default_mode)
@@ -4729,6 +4753,19 @@ init_workspace_manager(struct display *d, uint32_t id)
d); 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 static void
registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version) 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); id, &wl_shell_interface, 1);
} else if (strcmp(interface, "wl_shm") == 0) { } else if (strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); 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) { } else if (strcmp(interface, "wl_data_device_manager") == 0) {
d->data_device_manager = d->data_device_manager =
wl_registry_bind(registry, id, wl_registry_bind(registry, id,
+11
View File
@@ -139,6 +139,8 @@ display_release_window_surface(struct display *display,
#define SURFACE_HINT_RESIZE 0x10 #define SURFACE_HINT_RESIZE 0x10
#define SURFACE_HINT_RGB565 0x100
cairo_surface_t * cairo_surface_t *
display_create_surface(struct display *display, display_create_surface(struct display *display,
struct wl_surface *surface, struct wl_surface *surface,
@@ -383,6 +385,15 @@ window_get_title(struct window *window);
void void
window_set_text_cursor_position(struct window *window, int32_t x, int32_t y); 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 int
widget_set_tooltip(struct widget *parent, char *entry, float x, float y); widget_set_tooltip(struct widget *parent, char *entry, float x, float y);