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