summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2012-04-03 12:00:48 -0400
committerKristian Høgsberg <krh@bitplanet.net>2012-04-03 12:00:48 -0400
commit1103a1a484999dc0d53eb6a42bc62f461a0a582d (patch)
treed9ae62ccd7dc2a21d2a1f64ca242744308696c33
parent8f64ed0381fef90e82de696a01ba467a2dd3677a (diff)
window: Use a persistent, big shm pool during resize
The biggest performance bottleneck while resizing is the continous setting up and tearing down of mmaps and faulting in pages. This commit introduces a per-window pool that we'll allocate buffers out of if it's available. Then we set initialize it to a big shm pool when we start resizing and free it when resizing is done.
-rw-r--r--clients/window.c52
1 files changed, 44 insertions, 8 deletions
diff --git a/clients/window.c b/clients/window.c
index de69003..73b7e88 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -133,6 +133,10 @@ struct window {
cairo_surface_t *cairo_surface, *pending_surface;
+ struct wl_shm_pool *pool;
+ size_t pool_size;
+ void *pool_data;
+
window_key_handler_t key_handler;
window_keyboard_focus_handler_t keyboard_focus_handler;
window_data_handler_t data_handler;
@@ -497,12 +501,14 @@ make_shm_pool(struct display *display, int size, void **data)
static cairo_surface_t *
display_create_shm_surface(struct display *display,
- struct rectangle *rectangle, uint32_t flags)
+ struct rectangle *rectangle, uint32_t flags,
+ struct window *window)
{
struct shm_surface_data *data;
- struct wl_shm_pool *pool;
+ struct wl_shm_pool *pool = NULL;
uint32_t format;
cairo_surface_t *surface;
+ void *map;
int stride;
data = malloc(sizeof *data);
@@ -512,9 +518,15 @@ display_create_shm_surface(struct display *display,
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
rectangle->width);
data->length = stride * rectangle->height;
- pool = make_shm_pool(display, data->length, &data->map);
+ if (window && window->pool && data->length < window->pool_size) {
+ pool = window->pool;
+ map = window->pool_data;
+ } else {
+ pool = make_shm_pool(display, data->length, &data->map);
+ map = data->map;
+ }
- surface = cairo_image_surface_create_for_data (data->map,
+ surface = cairo_image_surface_create_for_data (map,
CAIRO_FORMAT_ARGB32,
rectangle->width,
rectangle->height,
@@ -533,7 +545,8 @@ display_create_shm_surface(struct display *display,
rectangle->height,
stride, format);
- wl_shm_pool_destroy(pool);
+ if (map == data->map)
+ wl_shm_pool_destroy(pool);
return surface;
}
@@ -550,7 +563,7 @@ display_create_shm_surface_from_file(struct display *display,
image = load_image(filename);
- surface = display_create_shm_surface(display, rect, 0);
+ surface = display_create_shm_surface(display, rect, 0, NULL);
if (surface == NULL) {
pixman_image_unref(image);
return NULL;
@@ -597,7 +610,7 @@ display_create_surface(struct display *display,
rectangle);
}
#endif
- return display_create_shm_surface(display, rectangle, flags);
+ return display_create_shm_surface(display, rectangle, flags, NULL);
}
static cairo_surface_t *
@@ -867,7 +880,8 @@ window_create_surface(struct window *window)
#endif
case WINDOW_BUFFER_TYPE_SHM:
surface = display_create_shm_surface(window->display,
- &window->allocation, flags);
+ &window->allocation,
+ flags, window);
break;
default:
surface = NULL;
@@ -1345,7 +1359,9 @@ frame_button_handler(struct widget *widget,
{
struct frame *frame = data;
struct window *window = widget->window;
+ struct display *display = window->display;
int location;
+
location = frame_get_pointer_location(frame, input->sx, input->sy);
if (window->display->shell && button == BTN_LEFT && state == 1) {
@@ -1370,6 +1386,18 @@ frame_button_handler(struct widget *widget,
if (!window->shell_surface)
break;
input_ungrab(input, time);
+
+ if (!display->dpy) {
+ /* If we're using shm, allocate a big
+ pool to create buffers out of while
+ we resize. We should probably base
+ this number on the size of the output. */
+ window->pool_size = 6 * 1024 * 1024;
+ window->pool = make_shm_pool(display,
+ window->pool_size,
+ &window->pool_data);
+ }
+
wl_shell_surface_resize(window->shell_surface,
input_get_input_device(input),
time, location);
@@ -1588,6 +1616,14 @@ input_handle_pointer_enter(void *data,
input->pointer_focus = wl_surface_get_user_data(surface);
window = input->pointer_focus;
+ if (window->pool) {
+ wl_shm_pool_destroy(window->pool);
+ munmap(window->pool_data, window->pool_size);
+ window->pool = NULL;
+ /* Schedule a redraw to free the pool */
+ window_schedule_redraw(window);
+ }
+
input->sx = sx;
input->sy = sy;