summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2022-04-13 17:26:57 -0700
committerVito Caputo <vcaputo@pengaru.com>2022-04-13 17:29:27 -0700
commitf29bc4f4a3f2d316113263731962b783fff8690d (patch)
tree36fff26df5ad2a07c0ac22d8a9dea588dbd50c65
parent8cfe3854ff7f6fbce48ba80061f7a0f2d2959e84 (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--.gitmodules1
m---------rototiller0
-rw-r--r--src/gtk_fb.c39
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;
© All Rights Reserved