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:
parent
59b251cc39
commit
b8fa522ca4
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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_);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user