From 0ff31668a1117cf784e41331105d5c76f9bc441f Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Thu, 8 Sep 2022 16:11:53 +0200 Subject: Wayland: remove memory leak from missing wl_callback_destroy() call. This hopefully corresponds to the memory leak mentioned in fltk.general named "FLTK and Wayland". --- src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H | 3 ++- src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx | 13 ++++++------- src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx | 16 +++++++++++++++- 3 files changed, 23 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H index 9b2edba2a..855bce1c7 100644 --- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H +++ b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H @@ -78,7 +78,8 @@ public: virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc, int srcx, int srcy); static struct fl_wld_buffer *create_shm_buffer(int width, int height); static void buffer_release(struct wld_window *window); - static void buffer_commit(struct wld_window *window, const struct wl_callback_listener*); + static void buffer_commit(struct wld_window *window, const struct wl_callback_listener*, + bool need_damage = true); static void cairo_init(struct fl_wld_buffer *buffer, int width, int height, int stride, cairo_format_t format); virtual void *gc(); virtual void gc(void *gc); diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx index 031c44e40..e4632b4c5 100644 --- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx @@ -76,18 +76,16 @@ struct fl_wld_buffer *Fl_Wayland_Graphics_Driver::create_shm_buffer(int width, i void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window, - const struct wl_callback_listener *listener) { + const struct wl_callback_listener *listener, + bool need_damage) { cairo_surface_t *surf = cairo_get_target(window->buffer->cairo_); cairo_surface_flush(surf); memcpy(window->buffer->data, window->buffer->draw_buffer, window->buffer->data_size); wl_surface_attach(window->wl_surface, window->buffer->wl_buffer, 0, 0); wl_surface_set_buffer_scale(window->wl_surface, window->scale); - struct wl_callback *cb = wl_surface_frame(window->wl_surface); - if (listener) { - window->buffer->cb = cb; - wl_surface_damage_buffer(window->wl_surface, 0, 0, 1000000, 1000000); - wl_callback_add_listener(window->buffer->cb, listener, window); - } + window->buffer->cb = wl_surface_frame(window->wl_surface); + if (need_damage) wl_surface_damage_buffer(window->wl_surface, 0, 0, 1000000, 1000000); + wl_callback_add_listener(window->buffer->cb, listener, window); wl_surface_commit(window->wl_surface); window->buffer->draw_buffer_needs_commit = false; //fprintf(stderr,"buffer_commit %s\n", window->fl_win->parent()?"child":"top"); @@ -117,6 +115,7 @@ void Fl_Wayland_Graphics_Driver::cairo_init(struct fl_wld_buffer *buffer, int wi void Fl_Wayland_Graphics_Driver::buffer_release(struct wld_window *window) { if (window->buffer) { + if (window->buffer->cb) wl_callback_destroy(window->buffer->cb); wl_buffer_destroy(window->buffer->wl_buffer); delete[] window->buffer->draw_buffer; window->buffer->draw_buffer = NULL; diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx index 2692e8ae1..72430c86f 100644 --- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx @@ -382,6 +382,18 @@ void Fl_Wayland_Window_Driver::make_current() { } +// used to support regular drawing +static void surface_frame_one_shot(void *data, struct wl_callback *cb, uint32_t time) { + wl_callback_destroy(cb); + struct wld_window *window = (struct wld_window *)data; + window->buffer->cb = NULL; +} + +static const struct wl_callback_listener surface_frame_listener_one_shot = { + .done = surface_frame_one_shot, +}; + + void Fl_Wayland_Window_Driver::flush() { if (!pWindow->damage()) return; if (pWindow->as_gl_window()) { @@ -420,7 +432,9 @@ void Fl_Wayland_Window_Driver::flush() { Fl_Window_Driver::flush(); Fl_Wayland_Window_Driver::in_flush = false; - Fl_Wayland_Graphics_Driver::buffer_commit(window, NULL); + if (!window->buffer->cb) { + Fl_Wayland_Graphics_Driver::buffer_commit(window, &surface_frame_listener_one_shot, false); + } } -- cgit v1.2.3