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().
This commit is contained in:
ManoloFLTK 2023-09-25 16:40:01 +02:00
parent 59b251cc39
commit b8fa522ca4
4 changed files with 41 additions and 24 deletions

View File

@ -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 <tt>struct wld_window</tt> (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 <tt>struct wl_buffer</tt>
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 <tt>Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *,…)</tt> which calls
\c create_shm_buffer(). In contrast, standard shaped-cursors (e.g., FL_CURSOR_INSERT)
function <tt>Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *,…)</tt> 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.
- <tt>float gui_scale;</tt>. 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 <tt>struct cursor_image</tt> object has an associated
Function <tt>Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *rgb, int hotx, int hoty)</tt>
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 <tt>struct wl_cursor</tt> is essentially an array of \c wl_cursor_image objects
@ -1243,7 +1250,7 @@ to an \c Fl_Offscreen value.
\anchor wld_buffer
<h3>struct Fl_Wayland_Graphics_Driver::wld_buffer</h3>
Defined in file \c Fl_Wayland_Graphics_Driver.H.
One such record is created by \c Fl_Wayland_Graphics_Driver::create_shm_buffer() when
One such record is created by \c Fl_Wayland_Graphics_Driver::create_wld_buffer() when
an Fl_Window is show()'n or resized, when a custom cursor shape is created, or when
text is dragged.
<pre>

View File

@ -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);

View File

@ -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_);

View File

@ -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);
}