diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2022-04-13 17:26:57 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2022-04-13 17:29:27 -0700 |
commit | f29bc4f4a3f2d316113263731962b783fff8690d (patch) | |
tree | 36fff26df5ad2a07c0ac22d8a9dea588dbd50c65 | |
parent | 8cfe3854ff7f6fbce48ba80061f7a0f2d2959e84 (diff) |
gtk_fb: WIP switch to using GtkDrawingArea
I still need to dig into which is preferable from a performance
perspective, but the existing GtkImage integration with setting
its cairo surface for the page flip seems to cause lots of
size-allocations and errors on wayland as-is.
Note this also bumps the rototiller submodule to a different branch
for til_fb_context().
-rw-r--r-- | .gitmodules | 1 | ||||
m--------- | rototiller | 0 | ||||
-rw-r--r-- | src/gtk_fb.c | 39 |
3 files changed, 26 insertions, 14 deletions
diff --git a/.gitmodules b/.gitmodules index 904b734..6ce2cdd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "rototiller"] path = rototiller url = https://git.pengaru.com/rototiller + branch = fbcontext diff --git a/rototiller b/rototiller -Subproject 4351afc62b3dd1c7fb7f0bc563dae22ee0ec73d +Subproject 2c01f07385db88fa92f3a3789457c68db0d7d49 diff --git a/src/gtk_fb.c b/src/gtk_fb.c index f9fd015..3faad8f 100644 --- a/src/gtk_fb.c +++ b/src/gtk_fb.c @@ -26,7 +26,8 @@ typedef struct gtk_fb_t { GtkWidget *window; - GtkWidget *image; + GtkWidget *area; + cairo_t *cairo; unsigned width, height; unsigned fullscreen:1; unsigned resized:1; @@ -39,13 +40,13 @@ struct gtk_fb_page_t { }; -/* called on "size-allocate" for the fb's gtk image */ +/* called on "size-allocate" for the fb's gtk area */ static void resized(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data) { gtk_fb_t *c = user_data; GtkAllocation alloc; - gtk_widget_get_allocation(c->image, &alloc); + gtk_widget_get_allocation(c->area, &alloc); if (c->width != alloc.width || c->height != alloc.height) { @@ -133,18 +134,24 @@ static void gtk_fb_shutdown(til_fb_t *fb, void *context) static gboolean draw_cb(GtkWidget *widget, cairo_t *cr, gpointer user_data) { til_fb_t *fb = user_data; + gtk_fb_t *c = til_fb_context(fb); + + /* this is icky but we need to pass the cr to gtk_fb_page_flip(), til_fb_t is + * the convenient via. + */ + c->cairo = cr; til_fb_flip(fb); return FALSE; } -/* this just queues drawing the image on the "tick" */ +/* this just queues drawing the area on the "tick" */ static gboolean queue_draw_cb(GtkWidget *widget, GdkFrameClock *frame_clock, gpointer user_data) { gtk_fb_t *c = user_data; - gtk_widget_queue_draw(c->image); + gtk_widget_queue_draw(c->area); return G_SOURCE_CONTINUE; } @@ -158,12 +165,13 @@ static int gtk_fb_acquire(til_fb_t *fb, void *context, void *page) if (!c->window) return -EPIPE; - c->image = gtk_image_new_from_surface(p->surface); - g_signal_connect_after(c->image, "size-allocate", G_CALLBACK(resized), c); - g_signal_connect(c->image, "draw", G_CALLBACK(draw_cb), fb); - gtk_widget_set_size_request(c->image, c->width, c->height); - gtk_widget_add_tick_callback(c->image, queue_draw_cb, c, NULL); - gtk_container_add(GTK_CONTAINER(c->window), c->image); + c->area = gtk_drawing_area_new(); + /* XXX: copy from p->surface to c->area */ + gtk_widget_set_size_request(c->area, c->width, c->height); + g_signal_connect_after(c->area, "size-allocate", G_CALLBACK(resized), c); + g_signal_connect(c->area, "draw", G_CALLBACK(draw_cb), fb); + gtk_widget_add_tick_callback(c->area, queue_draw_cb, c, NULL); + gtk_container_add(GTK_CONTAINER(c->window), c->area); gtk_widget_show_all(c->window); return 0; @@ -175,7 +183,7 @@ static void gtk_fb_release(til_fb_t *fb, void *context) gtk_fb_t *c = context; if (c->window) - gtk_widget_destroy(c->image); + gtk_widget_destroy(c->area); } @@ -227,7 +235,7 @@ static int gtk_fb_page_free(til_fb_t *fb, void *context, void *page) /* XXX: due to gtk's event-driven nature, this isn't a vsync-synchronous page flip, * so til_fb_flip() must be scheduled independently to not just spin. - * The "draw" signal on the image is used to drive til_fb_flip() on frameclock "ticks", + * The "draw" signal on the area is used to drive til_fb_flip() on frameclock "ticks", * a method suggested by Christian Hergert, thanks! */ static int gtk_fb_page_flip(til_fb_t *fb, void *context, void *page) @@ -239,7 +247,10 @@ static int gtk_fb_page_flip(til_fb_t *fb, void *context, void *page) return -EPIPE; cairo_surface_mark_dirty(p->surface); - gtk_image_set_from_surface(GTK_IMAGE(c->image), p->surface); + cairo_set_source_surface(c->cairo, p->surface, 0, 0); + cairo_set_operator(c->cairo, CAIRO_OPERATOR_SOURCE); + cairo_rectangle(c->cairo, 0, 0, c->width, c->height); + cairo_fill(c->cairo); if (c->resized) { c->resized = 0; |