[PATCH weston] westoy: Add an option to explicitly disable cairo on a widget

Pekka Paalanen ppaalanen at gmail.com
Thu Dec 19 08:46:05 PST 2013


On Thu, 19 Dec 2013 16:17:12 +0000
Neil Roberts <neil at linux.intel.com> wrote:

> This problem was found while looking at the following bug:
> 
> https://bugs.freedesktop.org/show_bug.cgi?id=72612
> 
> It turns out the patch doesn't help to fix the bug but I think it
> would be a good thing to do anyway.
> 
> ------- >8 --------------- (use git am --scissors to
> automatically chop here)
> 
> The subsurfaces example creates a subsurface widget and uses EGL
> to render to it directly rather than using the cairo context from
> the widget. In theory this shouldn't cause any problems because
> the westoy window code lazily creates the cairo surface when an
> application creates a cairo context. However commit fdca95c7
> changed the behaviour to force the lazy creation at the beginning
> of each surface redraw. This ends up making the triangle surface
> get two attaches – one from Cairo and one from the direct EGL.

Oh yeah, I had forgotten all about how the lazy creation worked
when doing that commit. Or that it even existed.

> It looks like it would be difficult to reinstate the lazy surface
> creation behaviour whilst still maintaining the error handling for
> surface creation because none of the redraw handlers in the
> example clients are designed to cope with that. Instead, this
> patch adds an explicit option on a widget to disable creating the
> Cairo surface and the subsurface example now uses that.

Yeah, the lazy creation would need changes in all demos and is
implicit behaviour. I like explicit better, and it avoids the need
to fix all demos.

> ---
>  clients/subsurfaces.c |  1 +
>  clients/window.c      | 18 +++++++++++++++++-
>  clients/window.h      |  2 ++
>  3 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/clients/subsurfaces.c b/clients/subsurfaces.c
> index 0f11009..45cc44b 100644
> --- a/clients/subsurfaces.c
> +++ b/clients/subsurfaces.c
> @@ -498,6 +498,7 @@ triangle_create(struct window *window, struct
> egl_state *egl) tri->egl = egl;
>  	tri->widget = window_add_subsurface(window, tri,
>  		int_to_mode(option_triangle_mode));
> +	widget_set_use_cairo(tri->widget, 0);
>  	widget_set_resize_handler(tri->widget,
> triangle_resize_handler); widget_set_redraw_handler(tri->widget,
> triangle_redraw_handler); 
> diff --git a/clients/window.c b/clients/window.c
> index 43761ca..5a8df43 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -285,6 +285,11 @@ struct widget {
>  	int opaque;
>  	int tooltip_count;
>  	int default_cursor;
> +	/* If this is set to false then no cairo surface will be
> +	 * created before redrawing the surface. This is useful
> if the
> +	 * redraw handler is going to do completely custom
> rendering
> +	 * such as using EGL directly */
> +	int use_cairo;
>  };
>  
>  struct touch_point {
> @@ -1608,6 +1613,7 @@ widget_create(struct window *window, struct
> surface *surface, void *data) widget->tooltip = NULL;
>  	widget->tooltip_count = 0;
>  	widget->default_cursor = CURSOR_LEFT_PTR;
> +	widget->use_cairo = 1;
>  
>  	return widget;
>  }
> @@ -1706,6 +1712,8 @@ widget_get_cairo_surface(struct widget
> *widget) struct surface *surface = widget->surface;
>  	struct window *window = widget->window;
>  
> +	assert(widget->use_cairo);
> +
>  	if (!surface->cairo_surface) {
>  		if (surface == window->main_surface)
>  			window_create_main_surface(window);
> @@ -1938,6 +1946,13 @@ widget_schedule_redraw(struct widget
> *widget) window_schedule_redraw_task(widget->window);
>  }
>  
> +void
> +widget_set_use_cairo(struct widget *widget,
> +		     int use_cairo)
> +{
> +	widget->use_cairo = use_cairo;
> +}
> +
>  cairo_surface_t *
>  window_get_surface(struct window *window)
>  {
> @@ -3942,7 +3957,8 @@ surface_redraw(struct surface *surface)
>  		wl_callback_destroy(surface->frame_cb);
>  	}
>  
> -	if (!widget_get_cairo_surface(surface->widget)) {
> +	if (surface->widget->use_cairo &&
> +	    !widget_get_cairo_surface(surface->widget)) {
>  		DBG_OBJ(surface->surface, "cancelled due buffer
> failure\n"); return -1;
>  	}
> diff --git a/clients/window.h b/clients/window.h
> index cf8fc6c..1e12374 100644
> --- a/clients/window.h
> +++ b/clients/window.h
> @@ -507,6 +507,8 @@ widget_set_axis_handler(struct widget *widget,
>  			widget_axis_handler_t handler);
>  void
>  widget_schedule_redraw(struct widget *widget);
> +void
> +widget_set_use_cairo(struct widget *widget, int use_cairo);
>  
>  struct widget *
>  window_frame_create(struct window *window, void *data);

Looks good to me!


Thanks,
pq


More information about the wayland-devel mailing list