diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2023-06-05 11:00:33 +0200 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2023-06-05 11:00:33 +0200 |
| commit | 5be3fbf913210a8b81fe101c3927c141432fa724 (patch) | |
| tree | b79a0e6844573483dda34751ea47b60e130db308 /src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx | |
| parent | 5dfa51a8201ce0111220575956d2fb0db989fe90 (diff) | |
Improve re-use of client/compositor shared memory by Wayland buffers
Diffstat (limited to 'src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx')
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx | 68 |
1 files changed, 38 insertions, 30 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx index cfe1ff494..4a5351701 100644 --- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx @@ -27,53 +27,56 @@ extern "C" { # include "../../../libdecor/src/os-compatibility.h" // for os_create_anonymous_file() } +// used by create_shm_buffer and buffer_release +static struct wl_shm_pool *pool = NULL; // the current pool + struct fl_wld_buffer *Fl_Wayland_Graphics_Driver::create_shm_buffer(int width, int height) { struct fl_wld_buffer *buffer; int stride = cairo_format_stride_for_width(Fl_Cairo_Graphics_Driver::cairo_format, width); int size = stride * height; - static int pool_size = 10000000; // gets increased if necessary - static int chunk_offset = pool_size; - static int fd = -1; - static struct wl_shm_pool *pool = NULL; - if (chunk_offset + size > pool_size) { + const int default_pool_size = 10000000; // larger pools are possible if needed + int chunk_offset = 0; // offset to start of available memory in pool + struct wld_shm_pool_data *pool_data = pool ? // data record attached to current pool + (struct wld_shm_pool_data *)wl_shm_pool_get_user_data(pool) : NULL; + int pool_size = pool ? pool_data->pool_size : default_pool_size; // current pool size + if (pool) { + // last fl_wld_buffer created from current pool + struct fl_wld_buffer *record = wl_container_of(pool_data->buffers.next, record, link); + chunk_offset = ((char*)record->data - pool_data->pool_memory) + record->data_size; + } + if (!pool || chunk_offset + size > pool_size) { // if true, a new pool is needed chunk_offset = 0; - if (pool) { - struct wld_shm_pool_data *pool_data = - (struct wld_shm_pool_data *)wl_shm_pool_get_user_data(pool); - wl_shm_pool_destroy(pool); - close(fd); - pool_data->destroyed = true; - if (pool_data->use_count == 0) { - /*int err =*/ munmap(pool_data->pool_memory, pool_data->pool_size); -//printf("munmap(%p)->%d\n", pool_data->pool_memory, err); - free(pool_data); - } + pool_size = default_pool_size; + if (size > pool_size) pool_size = 2 * size; // a larger pool is needed + int fd = os_create_anonymous_file(pool_size); + if (fd < 0) { + Fl::fatal("os_create_anonymous_file failed: %s\n", strerror(errno)); } - if (size > pool_size) pool_size = 2 * size; - fd = os_create_anonymous_file(pool_size); - struct wld_shm_pool_data *pool_data = (struct wld_shm_pool_data*) - calloc(1, sizeof(struct wld_shm_pool_data)); - pool_data->pool_memory = (char*)mmap(NULL, pool_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + pool_data = (struct wld_shm_pool_data*)calloc(1, sizeof(struct wld_shm_pool_data)); + pool_data->pool_memory = (char*)mmap(NULL, pool_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); if (pool_data->pool_memory == MAP_FAILED) { close(fd); Fl::fatal("mmap failed: %s\n", strerror(errno)); } Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); pool = wl_shm_create_pool(scr_driver->wl_shm, fd, pool_size); + close(fd); // does not prevent the mmap'ed memory from being used +//puts("wl_shm_create_pool"); pool_data->pool_size = pool_size; + wl_list_init(&pool_data->buffers); wl_shm_pool_set_user_data(pool, pool_data); } buffer = (struct fl_wld_buffer*)calloc(1, sizeof(struct fl_wld_buffer)); buffer->stride = stride; buffer->wl_buffer = wl_shm_pool_create_buffer(pool, chunk_offset, width, height, stride, Fl_Wayland_Graphics_Driver::wld_format); - struct wld_shm_pool_data *pool_data = - (struct wld_shm_pool_data *)wl_shm_pool_get_user_data(pool); - pool_data->use_count++; - wl_buffer_set_user_data(buffer->wl_buffer, pool_data); + // add this buffer to head of list of current pool's buffers + wl_list_insert(&pool_data->buffers, &buffer->link); + buffer->shm_pool = pool; buffer->data = (void*)(pool_data->pool_memory + chunk_offset); - chunk_offset += size; +//fprintf(stderr, "last=%p chunk_offset=%d ", pool_data->buffers.next, chunk_offset); buffer->data_size = size; buffer->width = width; buffer->draw_buffer = new uchar[buffer->data_size]; @@ -174,15 +177,20 @@ void Fl_Wayland_Graphics_Driver::buffer_release(struct wld_window *window) { if (window->buffer) { if (window->buffer->cb) wl_callback_destroy(window->buffer->cb); + struct wl_shm_pool *my_pool = window->buffer->shm_pool; struct wld_shm_pool_data *pool_data = - (struct wld_shm_pool_data *)wl_buffer_get_user_data(window->buffer->wl_buffer); + (struct wld_shm_pool_data*)wl_shm_pool_get_user_data(my_pool); wl_buffer_destroy(window->buffer->wl_buffer); //printf("wl_buffer_destroy(%p)\n",window->buffer->wl_buffer); - pool_data->use_count--; - if (pool_data->destroyed && pool_data->use_count == 0) { - /*int err =*/ munmap(pool_data->pool_memory, pool_data->pool_size); + // remove fl_wld_buffer from list of pool's buffers + wl_list_remove(&window->buffer->link); +//printf("last=%p\n", wl_list_empty(&pool_data->buffers) ? NULL : pool_data->buffers.next); + if (wl_list_empty(&pool_data->buffers)) { // all buffers from pool are gone + wl_shm_pool_destroy(my_pool); + /*int err = */munmap(pool_data->pool_memory, pool_data->pool_size); //printf("munmap(%p)->%d\n", pool_data->pool_memory, err); free(pool_data); + if (my_pool == pool) pool = NULL; } delete[] window->buffer->draw_buffer; window->buffer->draw_buffer = NULL; |
