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.
Kristian Høgsberg 13 years ago
parent 8f64ed0381
commit 1103a1a484
  1. 48
      clients/window.c

@ -133,6 +133,10 @@ struct window {
cairo_surface_t *cairo_surface, *pending_surface; 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_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;
@ -497,12 +501,14 @@ make_shm_pool(struct display *display, int size, void **data)
static cairo_surface_t * static cairo_surface_t *
display_create_shm_surface(struct display *display, 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 shm_surface_data *data;
struct wl_shm_pool *pool; struct wl_shm_pool *pool = NULL;
uint32_t format; uint32_t format;
cairo_surface_t *surface; cairo_surface_t *surface;
void *map;
int stride; int stride;
data = malloc(sizeof *data); data = malloc(sizeof *data);
@ -512,9 +518,15 @@ display_create_shm_surface(struct display *display,
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
rectangle->width); rectangle->width);
data->length = stride * rectangle->height; data->length = stride * rectangle->height;
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); 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, CAIRO_FORMAT_ARGB32,
rectangle->width, rectangle->width,
rectangle->height, rectangle->height,
@ -533,6 +545,7 @@ display_create_shm_surface(struct display *display,
rectangle->height, rectangle->height,
stride, format); stride, format);
if (map == data->map)
wl_shm_pool_destroy(pool); wl_shm_pool_destroy(pool);
return surface; return surface;
@ -550,7 +563,7 @@ display_create_shm_surface_from_file(struct display *display,
image = load_image(filename); image = load_image(filename);
surface = display_create_shm_surface(display, rect, 0); surface = display_create_shm_surface(display, rect, 0, NULL);
if (surface == NULL) { if (surface == NULL) {
pixman_image_unref(image); pixman_image_unref(image);
return NULL; return NULL;
@ -597,7 +610,7 @@ display_create_surface(struct display *display,
rectangle); rectangle);
} }
#endif #endif
return display_create_shm_surface(display, rectangle, flags); return display_create_shm_surface(display, rectangle, flags, NULL);
} }
static cairo_surface_t * static cairo_surface_t *
@ -867,7 +880,8 @@ window_create_surface(struct window *window)
#endif #endif
case WINDOW_BUFFER_TYPE_SHM: case WINDOW_BUFFER_TYPE_SHM:
surface = display_create_shm_surface(window->display, surface = display_create_shm_surface(window->display,
&window->allocation, flags); &window->allocation,
flags, window);
break; break;
default: default:
surface = NULL; surface = NULL;
@ -1345,7 +1359,9 @@ frame_button_handler(struct widget *widget,
{ {
struct frame *frame = data; struct frame *frame = data;
struct window *window = widget->window; struct window *window = widget->window;
struct display *display = window->display;
int location; int location;
location = frame_get_pointer_location(frame, input->sx, input->sy); location = frame_get_pointer_location(frame, input->sx, input->sy);
if (window->display->shell && button == BTN_LEFT && state == 1) { if (window->display->shell && button == BTN_LEFT && state == 1) {
@ -1370,6 +1386,18 @@ frame_button_handler(struct widget *widget,
if (!window->shell_surface) if (!window->shell_surface)
break; break;
input_ungrab(input, time); 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, wl_shell_surface_resize(window->shell_surface,
input_get_input_device(input), input_get_input_device(input),
time, location); time, location);
@ -1588,6 +1616,14 @@ input_handle_pointer_enter(void *data,
input->pointer_focus = wl_surface_get_user_data(surface); input->pointer_focus = wl_surface_get_user_data(surface);
window = input->pointer_focus; 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->sx = sx;
input->sy = sy; input->sy = sy;

Loading…
Cancel
Save