Wayland: make fl_close_display() free more resources

This commit is contained in:
ManoloFLTK 2023-11-09 07:58:08 +01:00
parent 5989caf070
commit ff134f0081
3 changed files with 32 additions and 16 deletions

View File

@ -53,6 +53,7 @@ public:
struct wl_list buffers; // to list of fl_wld_buffer's from this pool
};
static const uint32_t wld_format;
static struct wl_shm_pool *current_pool;
void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc,
int srcx, int srcy) FL_OVERRIDE;
static struct wld_buffer *create_wld_buffer(int width, int height, bool with_shm = true);

View File

@ -29,7 +29,7 @@ extern "C" {
}
// used by create_shm_buffer and do_buffer_release
static struct wl_shm_pool *pool = NULL; // the current pool
struct wl_shm_pool *Fl_Wayland_Graphics_Driver::current_pool = NULL;
static void do_buffer_release(struct Fl_Wayland_Graphics_Driver::wld_buffer *);
@ -49,26 +49,25 @@ static const struct wl_buffer_listener buffer_listener = {
};
void Fl_Wayland_Graphics_Driver::create_shm_buffer(Fl_Wayland_Graphics_Driver::wld_buffer *buffer)
{
void Fl_Wayland_Graphics_Driver::create_shm_buffer(Fl_Wayland_Graphics_Driver::wld_buffer *buffer) {
int width = buffer->draw_buffer.width;
int stride = buffer->draw_buffer.stride;
int height = buffer->draw_buffer.data_size / stride;
const size_t 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;
size_t pool_size = pool ? pool_data->pool_size : default_pool_size; // current pool size
if (pool && !wl_list_empty(&pool_data->buffers)) {
struct wld_shm_pool_data *pool_data = current_pool ? // data record attached to current pool
(struct wld_shm_pool_data *)wl_shm_pool_get_user_data(current_pool) : NULL;
size_t pool_size = current_pool ? pool_data->pool_size : default_pool_size; // current pool size
if (current_pool && !wl_list_empty(&pool_data->buffers)) {
// last wld_buffer created from current pool
struct wld_buffer *record = wl_container_of(pool_data->buffers.next, record, link);
chunk_offset = ((char*)record->data - pool_data->pool_memory) +
record->draw_buffer.data_size;
}
if (!pool || chunk_offset + buffer->draw_buffer.data_size > pool_size) {
if (!current_pool || chunk_offset + buffer->draw_buffer.data_size > pool_size) {
// if true, a new pool is needed
if (pool && wl_list_empty(&pool_data->buffers)) {
wl_shm_pool_destroy(pool);
if (current_pool && wl_list_empty(&pool_data->buffers)) {
wl_shm_pool_destroy(current_pool);
/*int err = */munmap(pool_data->pool_memory, pool_data->pool_size);
// printf("create_shm_buffer munmap(%p)->%d\n", pool_data->pool_memory, err);
free(pool_data);
@ -89,18 +88,19 @@ void Fl_Wayland_Graphics_Driver::create_shm_buffer(Fl_Wayland_Graphics_Driver::w
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, (int32_t)pool_size);
current_pool = wl_shm_create_pool(scr_driver->wl_shm, fd, (int32_t)pool_size);
close(fd); // does not prevent the mmap'ed memory from being used
//printf("wl_shm_create_pool %p size=%lu\n",pool_data->pool_memory , pool_size);
pool_data->pool_size = pool_size;
wl_list_init(&pool_data->buffers);
wl_shm_pool_set_user_data(pool, pool_data);
wl_shm_pool_set_user_data(current_pool, pool_data);
}
buffer->wl_buffer = wl_shm_pool_create_buffer(pool, chunk_offset, width, height, stride, Fl_Wayland_Graphics_Driver::wld_format);
buffer->wl_buffer = wl_shm_pool_create_buffer(current_pool, chunk_offset,
width, height, stride, wld_format);
wl_buffer_add_listener(buffer->wl_buffer, &buffer_listener, buffer);
// 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->shm_pool = current_pool;
buffer->data = (void*)(pool_data->pool_memory + chunk_offset);
//fprintf(stderr, "last=%p chunk_offset=%d ", pool_data->buffers.next, chunk_offset);
//fprintf(stderr, "create_shm_buffer: %dx%d = %d\n", width, height, size);
@ -219,7 +219,7 @@ static void do_buffer_release(struct Fl_Wayland_Graphics_Driver::wld_buffer *buf
wl_buffer_destroy(buffer->wl_buffer);
// remove wld_buffer from list of pool's buffers
wl_list_remove(&buffer->link);
if (wl_list_empty(&pool_data->buffers) && my_pool != pool) {
if (wl_list_empty(&pool_data->buffers) && my_pool != Fl_Wayland_Graphics_Driver::current_pool) {
// all buffers from pool are gone
wl_shm_pool_destroy(my_pool);
/*int err = */munmap(pool_data->pool_memory, pool_data->pool_size);

View File

@ -1328,6 +1328,17 @@ void Fl_Wayland_Screen_Driver::close_display() {
seat->cursor_theme = NULL;
}
wl_compositor_destroy(wl_compositor); wl_compositor = NULL;
// wl_shm-related data
if (Fl_Wayland_Graphics_Driver::current_pool) {
struct Fl_Wayland_Graphics_Driver::wld_shm_pool_data *pool_data =
(struct Fl_Wayland_Graphics_Driver::wld_shm_pool_data*)
wl_shm_pool_get_user_data(Fl_Wayland_Graphics_Driver::current_pool);
wl_shm_pool_destroy(Fl_Wayland_Graphics_Driver::current_pool);
Fl_Wayland_Graphics_Driver::current_pool = NULL;
/*int err = */munmap(pool_data->pool_memory, pool_data->pool_size);
//printf("close_display munmap(%p)->%d\n", pool_data->pool_memory, err);
free(pool_data);
}
wl_shm_destroy(wl_shm); wl_shm = NULL;
if (seat->wl_keyboard) {
if (seat->xkb_state) {
@ -1359,7 +1370,7 @@ void Fl_Wayland_Screen_Driver::close_display() {
seat->data_device_manager = NULL;
wl_seat_destroy(seat->wl_seat); seat->wl_seat = NULL;
if (seat->name) free(seat->name);
delete seat; seat = NULL;
free(seat); seat = NULL;
if (libdecor_context) {
libdecor_unref(libdecor_context);
libdecor_context = NULL;
@ -1372,6 +1383,10 @@ void Fl_Wayland_Screen_Driver::close_display() {
wl_registry_destroy(wl_registry); wl_registry = NULL;
wl_display_disconnect(Fl_Wayland_Screen_Driver::wl_display);
Fl_Wayland_Screen_Driver::wl_display = NULL;
delete Fl_Display_Device::display_device()->driver();
delete Fl_Display_Device::display_device();
delete Fl::system_driver();
delete this;
}