summaryrefslogtreecommitdiff
path: root/src/drivers/Wayland
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-09-22 11:51:24 +0200
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-09-22 11:51:24 +0200
commit220dd47bea588e65416faa2a51663304f8d0a8bc (patch)
tree01a63c78bfe184370ee0144f1086c62147ac634b /src/drivers/Wayland
parentcee69943e5986f471d49b1378311cb06e1487733 (diff)
Increase reuse of mmap'ed data by FLTK Wayland buffer factory
Diffstat (limited to 'src/drivers/Wayland')
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H10
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx70
2 files changed, 57 insertions, 23 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H
index 9991bd99f..8dfef0a97 100644
--- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H
+++ b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H
@@ -30,20 +30,22 @@
class Fl_Wayland_Graphics_Driver : public Fl_Cairo_Graphics_Driver {
public:
struct draw_buffer {
+ unsigned char *buffer;
+ cairo_t *cairo_;
size_t data_size; // of wl_buffer and buffer
int stride;
int width;
- unsigned char *buffer;
- cairo_t *cairo_;
};
struct wld_buffer {
struct draw_buffer draw_buffer;
+ struct wl_list link; // links all buffers from the same wl_shm_pool
struct wl_buffer *wl_buffer;
void *data;
struct wl_callback *cb;
- bool draw_buffer_needs_commit;
struct wl_shm_pool *shm_pool;
- struct wl_list link; // links all buffers from the same wl_shm_pool
+ bool draw_buffer_needs_commit;
+ bool in_use; // true while being committed
+ bool released; // true after buffer_release() was called
};
struct wld_shm_pool_data { // one record attached to each wl_shm_pool object
char *pool_memory; // start of mmap'ed memory encapsulated by the wl_shm_pool
diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
index f738a88a5..399388e40 100644
--- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
@@ -32,6 +32,23 @@ extern "C" {
static struct wl_shm_pool *pool = NULL; // the current pool
+static void do_buffer_release(struct Fl_Wayland_Graphics_Driver::wld_buffer *);
+
+
+static void buffer_release_listener(void *user_data, struct wl_buffer *wl_buffer)
+{
+ struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer =
+ (struct Fl_Wayland_Graphics_Driver::wld_buffer*)user_data;
+ buffer->in_use = false;
+ if (buffer->released) do_buffer_release(buffer);
+}
+
+
+static const struct wl_buffer_listener buffer_listener = {
+ buffer_release_listener
+};
+
+
struct Fl_Wayland_Graphics_Driver::wld_buffer *
Fl_Wayland_Graphics_Driver::create_shm_buffer(int width, int height)
{
@@ -43,12 +60,18 @@ struct Fl_Wayland_Graphics_Driver::wld_buffer *
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) {
+ if (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 + size > pool_size) { // if true, a new pool is needed
+ if (pool && wl_list_empty(&pool_data->buffers)) {
+ wl_shm_pool_destroy(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);
+ }
chunk_offset = 0;
pool_size = default_pool_size;
if (size > pool_size) pool_size = 2 * size; // a larger pool is needed
@@ -66,7 +89,7 @@ struct Fl_Wayland_Graphics_Driver::wld_buffer *
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");
+//printf("wl_shm_create_pool %p size=%d\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);
@@ -81,6 +104,7 @@ struct Fl_Wayland_Graphics_Driver::wld_buffer *
buffer->draw_buffer_needs_commit = true;
//fprintf(stderr, "create_shm_buffer: %dx%d = %d\n", width, height, size);
cairo_init(&buffer->draw_buffer, width, height, stride, Fl_Cairo_Graphics_Driver::cairo_format);
+ wl_buffer_add_listener(buffer->wl_buffer, &buffer_listener, buffer);
return buffer;
}
@@ -139,6 +163,7 @@ void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window,
memcpy(window->buffer->data, window->buffer->draw_buffer.buffer, window->buffer->draw_buffer.data_size);
wl_surface_damage_buffer(window->wl_surface, 0, 0, 1000000, 1000000);
}
+ window->buffer->in_use = true;
wl_surface_attach(window->wl_surface, window->buffer->wl_buffer, 0, 0);
wl_surface_set_buffer_scale(window->wl_surface,
Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale());
@@ -174,29 +199,36 @@ void Fl_Wayland_Graphics_Driver::cairo_init(struct Fl_Wayland_Graphics_Driver::d
}
+// runs when buffer->in_use is false and buffer->released is true
+static void do_buffer_release(
+ struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer) {
+ struct wl_shm_pool *my_pool = buffer->shm_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(my_pool);
+ wl_buffer_destroy(buffer->wl_buffer);
+ // remove wld_buffer from list of pool's buffers
+ wl_list_remove(&buffer->link);
+ free(buffer);
+ if (wl_list_empty(&pool_data->buffers) && my_pool != pool) {
+ // all buffers from pool are gone
+ wl_shm_pool_destroy(my_pool);
+ /*int err = */munmap(pool_data->pool_memory, pool_data->pool_size);
+//printf("do_buffer_release munmap(%p)->%d\n", pool_data->pool_memory, err);
+ free(pool_data);
+ }
+}
+
+
void Fl_Wayland_Graphics_Driver::buffer_release(struct wld_window *window)
{
- if (window->buffer) {
+ if (window->buffer && !window->buffer->released) {
+ window->buffer->released = true;
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_shm_pool_get_user_data(my_pool);
- wl_buffer_destroy(window->buffer->wl_buffer);
-//printf("wl_buffer_destroy(%p)\n",window->buffer->wl_buffer);
- // remove 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.buffer;
window->buffer->draw_buffer.buffer = NULL;
cairo_destroy(window->buffer->draw_buffer.cairo_);
- free(window->buffer);
+ if (!window->buffer->in_use) do_buffer_release(window->buffer);
window->buffer = NULL;
}
}