From b8fa522ca42407515f28dcdba4caddefe211ca27 Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Mon, 25 Sep 2023 16:40:01 +0200 Subject: [PATCH] New member function Fl_Wayland_Graphics_Driver::create_wld_buffer() The previous member Fl_Wayland_Graphics_Driver::create_shm_buffer() is now renamed to create_wld_buffer() and divided in 2 parts: - one is related to the draw buffer; - the other is related to the wl_buffer and is what is now called create_shm_buffer(). This allows to delay creation of the wl_buffer until absolutely necessary, done inside Fl_Wayland_Graphics_Driver::buffer_commit(). --- documentation/src/wayland.dox | 23 +++++++----- .../Wayland/Fl_Wayland_Graphics_Driver.H | 3 +- .../Wayland/Fl_Wayland_Graphics_Driver.cxx | 35 ++++++++++++------- .../Wayland/Fl_Wayland_Window_Driver.cxx | 4 +-- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/documentation/src/wayland.dox b/documentation/src/wayland.dox index 9842d59ac..066678ad7 100644 --- a/documentation/src/wayland.dox +++ b/documentation/src/wayland.dox @@ -532,8 +532,9 @@ CAIRO_FORMAT_ARGB32. FLTK calls function \c Fl_Wayland_Window_Driver::make_current() before drawing to any Fl_Window. Member \c buffer of this Fl_Window's struct wld_window (see \ref wld_window) is NULL when the -window has just been created or resized. In that case, FLTK calls member functions -\c create_shm_buffer() and \c cairo_init() of \c Fl_Wayland_Graphics_Driver to create +window has just been created or resized. In that case, FLTK calls +\c Fl_Wayland_Graphics_Driver::create_wld_buffer() which calls +\c create_shm_buffer() and \c cairo_init() to create - a Wayland buffer; - a Cairo image surface. @@ -560,7 +561,9 @@ All drawing operations to the Fl_Window then modify the content of the Cairo ima Function \c Fl_Wayland_Window_Driver::flush() is in charge of sending FLTK graphics data to the display. That is done by calling function \c -Fl_Wayland_Graphics_Driver::buffer_commit() which copies the byte array of the Cairo surface to +Fl_Wayland_Graphics_Driver::buffer_commit() which creates the struct wl_buffer +object calling \c create_shm_buffer() if that was not done before, +copies the byte array of the Cairo surface to the Wayland buffer's starting memory address, and calls functions \c wl_surface_attach() and \c wl_surface_commit(). Before calling Fl_Window::flush(), FLTK has computed a damaged region. If that region is not null, @@ -739,8 +742,10 @@ the previous mmap'ed section. Wayland uses also \c wl_buffer objects to support cursors. FLTK uses the "buffer factory" described here when creating custom cursors (see \ref custom-cursor) with -function Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *,…) which calls -\c create_shm_buffer(). In contrast, standard shaped-cursors (e.g., FL_CURSOR_INSERT) +function Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *,…) which +calls \c create_shm_buffer() via \c set_cursor_4args(), \c custom_offscreen() +and \c create_wld_buffer(). +In contrast, standard shaped-cursors (e.g., FL_CURSOR_INSERT) use their own "buffer factory" inside Wayland functions such as \c wl_cursor_theme_get_cursor(). Therefore, the fact that the \c wl_buffer objects behind standard cursors are never destroyed @@ -782,7 +787,7 @@ each system's display at startup time. Member function \c Fl_Wayland_Graphics_Driver::buffer_commit() informs the Wayland compositor of the value of \c wld_scale calling \c wl_surface_set_buffer_scale() which is enough to make FLTK apps HighDPI-aware. -Under the gnome desktop, this parameter is visible in the "Settings" app, +Under the gnome and KDE desktops, this parameter is visible in the "Settings" app, "Displays" section, "Scale" parameter which is 200% on HighDPI displays. - float gui_scale;. This other member variable is where FLTK's own GUI scaling mechanism with ctrl/+/-/0/ keystrokes and with environment variable FLTK_SCALING_FACTOR operates: @@ -919,7 +924,9 @@ It also shows that a struct cursor_image object has an associated Function Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *rgb, int hotx, int hoty) gives FLTK support of custom cursor shapes. It calls \c Fl_Wayland_Window_Driver::set_cursor_4args() that creates a \c cursor_image object, allocates the -corresponding \c wl_buffer by a call to \c Fl_Wayland_Graphics_Driver::create_shm_buffer() and draws +corresponding \c wl_buffer by a call to +\c Fl_Wayland_Graphics_Driver::create_shm_buffer() via \c custom_offscreen() +and \c create_wld_buffer() and draws the cursor shape into that buffer using the offscreen-drawing method of FLTK. The public type struct wl_cursor is essentially an array of \c wl_cursor_image objects @@ -1243,7 +1250,7 @@ to an \c Fl_Offscreen value. \anchor wld_buffer
diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H index 8dfef0a97..00bc6af4d 100644 --- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H +++ b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H @@ -54,7 +54,8 @@ public: }; static const uint32_t wld_format; 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_shm_buffer(int width, int height); + static struct wld_buffer *create_wld_buffer(int width, int height, bool with_shm = true); + static void create_shm_buffer(wld_buffer *buffer); static void buffer_release(struct wld_window *window); static void buffer_commit(struct wld_window *window, struct flCairoRegion *r = NULL); static void cairo_init(struct draw_buffer *buffer, int width, int height, int stride, cairo_format_t format); diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx index 399388e40..2e4aee842 100644 --- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx @@ -49,12 +49,11 @@ static const struct wl_buffer_listener buffer_listener = { }; -struct Fl_Wayland_Graphics_Driver::wld_buffer * - Fl_Wayland_Graphics_Driver::create_shm_buffer(int width, int height) -{ - struct wld_buffer *buffer; - int stride = cairo_format_stride_for_width(Fl_Cairo_Graphics_Driver::cairo_format, width); - int size = stride * height; +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 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 @@ -65,7 +64,8 @@ struct Fl_Wayland_Graphics_Driver::wld_buffer * 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 || 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); /*int err = */munmap(pool_data->pool_memory, pool_data->pool_size); @@ -74,7 +74,8 @@ struct Fl_Wayland_Graphics_Driver::wld_buffer * } chunk_offset = 0; pool_size = default_pool_size; - if (size > pool_size) pool_size = 2 * size; // a larger pool is needed + if (buffer->draw_buffer.data_size > pool_size) + pool_size = 2 * buffer->draw_buffer.data_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)); @@ -94,17 +95,24 @@ struct Fl_Wayland_Graphics_Driver::wld_buffer * wl_list_init(&pool_data->buffers); wl_shm_pool_set_user_data(pool, pool_data); } - buffer = (struct wld_buffer*)calloc(1, sizeof(struct wld_buffer)); buffer->wl_buffer = wl_shm_pool_create_buffer(pool, chunk_offset, width, height, stride, Fl_Wayland_Graphics_Driver::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->data = (void*)(pool_data->pool_memory + chunk_offset); //fprintf(stderr, "last=%p chunk_offset=%d ", pool_data->buffers.next, chunk_offset); - 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); +} + + +struct Fl_Wayland_Graphics_Driver::wld_buffer * + Fl_Wayland_Graphics_Driver::create_wld_buffer(int width, int height, bool with_shm) { + struct wld_buffer *buffer = (struct wld_buffer*)calloc(1, sizeof(struct wld_buffer)); + int stride = cairo_format_stride_for_width(cairo_format, width); + cairo_init(&buffer->draw_buffer, width, height, stride, cairo_format); + buffer->draw_buffer_needs_commit = true; + if (with_shm) create_shm_buffer(buffer); return buffer; } @@ -156,6 +164,7 @@ static void copy_region(struct wld_window *window, struct flCairoRegion *r) { void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window, struct flCairoRegion *r) { + if (!window->buffer->wl_buffer) create_shm_buffer(window->buffer); cairo_surface_t *surf = cairo_get_target(window->buffer->draw_buffer.cairo_); cairo_surface_flush(surf); if (r) copy_region(window, r); @@ -267,7 +276,7 @@ Fl_Wayland_Graphics_Driver::draw_buffer *Fl_Wayland_Graphics_Driver::offscreen_b Fl_Image_Surface *Fl_Wayland_Graphics_Driver::custom_offscreen(int w, int h, struct Fl_Wayland_Graphics_Driver::wld_buffer **p_off) { - struct wld_buffer *off = create_shm_buffer(w, h); + struct wld_buffer *off = create_wld_buffer(w, h); *p_off = off; cairo_set_user_data(off->draw_buffer.cairo_, &key, &off->draw_buffer, NULL); return new Fl_Image_Surface(w, h, 0, (Fl_Offscreen)off->draw_buffer.cairo_); diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx index b149cbe0b..2af93b973 100644 --- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx @@ -350,8 +350,8 @@ void Fl_Wayland_Window_Driver::make_current() { float f = Fl::screen_scale(pWindow->screen_num()); int wld_s = wld_scale(); if (!window->buffer) { - window->buffer = Fl_Wayland_Graphics_Driver::create_shm_buffer( - int(pWindow->w() * f) * wld_s, int(pWindow->h() * f) * wld_s); + window->buffer = Fl_Wayland_Graphics_Driver::create_wld_buffer( + int(pWindow->w() * f) * wld_s, int(pWindow->h() * f) * wld_s, false); ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->needs_commit_tag( &window->buffer->draw_buffer_needs_commit); }