[PATCH weston 4/4] gl-renderer: Use EXT_buffer_age and don't assume double buffering

Pekka Paalanen ppaalanen at gmail.com
Wed Mar 6 00:24:28 PST 2013


On Tue,  5 Mar 2013 17:30:30 +0200
Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>
wrote:

> Now that we have EXT_buffer_age in mesa, we should stop assuming double
> buffering and use the buffer age instead.
> 
> Note: this will cause system without the extension to repaint the whole
> screen every frame.

Ok, that might hurt the rpi backend when it is using GL to composite.
It makes the extra step to set EGL_SWAP_BEHAVIOR to
EGL_BUFFER_PRESERVED, so it can support the old double-buffering assumption.
I do not recall if it has EXT_buffer_age, but I would assume it doesn't.

Would it be easy to add a flag to get the strictly double-buffered
behaviour if a backend wishes so?

If not, then don't worry about it.


Thanks,
pq

> ---
>  src/gl-renderer.c |   86 ++++++++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 66 insertions(+), 20 deletions(-)
> 
> diff --git a/src/gl-renderer.c b/src/gl-renderer.c
> index 4c1bc23..fdde9ae 100644
> --- a/src/gl-renderer.c
> +++ b/src/gl-renderer.c
> @@ -46,10 +46,11 @@ struct gl_shader {
>  	GLint color_uniform;
>  };
>  
> +#define BUFFER_DAMAGE_COUNT 2
> +
>  struct gl_output_state {
>  	EGLSurface egl_surface;
> -	int current_buffer;
> -	pixman_region32_t buffer_damage[2];
> +	pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
>  };
>  
>  struct gl_surface_state {
> @@ -95,6 +96,8 @@ struct gl_renderer {
>  
>  	int has_egl_image_external;
>  
> +	int has_egl_buffer_age;
> +
>  	struct gl_shader texture_shader_rgba;
>  	struct gl_shader texture_shader_rgbx;
>  	struct gl_shader texture_shader_egl_external;
> @@ -742,12 +745,10 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
>  	struct weston_compositor *ec = es->compositor;
>  	struct gl_renderer *gr = get_renderer(ec);
>  	struct gl_surface_state *gs = get_surface_state(es);
> -	struct gl_output_state *go = get_output_state(output);
>  	/* repaint bounding region in global coordinates: */
>  	pixman_region32_t repaint;
>  	/* non-opaque region in surface coordinates: */
>  	pixman_region32_t surface_blend;
> -	pixman_region32_t *buffer_damage;
>  	GLint filter;
>  	int i;
>  
> @@ -759,9 +760,6 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
>  	if (!pixman_region32_not_empty(&repaint))
>  		goto out;
>  
> -	buffer_damage = &go->buffer_damage[go->current_buffer];
> -	pixman_region32_subtract(buffer_damage, buffer_damage, &repaint);
> -
>  	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
>  
>  	if (ec->fan_debug) {
> @@ -948,6 +946,51 @@ draw_border(struct weston_output *output)
>  }
>  
>  static void
> +output_get_buffer_damage(struct weston_output *output,
> +			 pixman_region32_t *buffer_damage)
> +{
> +	struct gl_output_state *go = get_output_state(output);
> +	struct gl_renderer *gr = get_renderer(output->compositor);
> +	EGLint buffer_age = 0;
> +	EGLBoolean ret;
> +	int i;
> +
> +	if (gr->has_egl_buffer_age) {
> +		ret = eglQuerySurface(gr->egl_display, go->egl_surface,
> +				      EGL_BUFFER_AGE_EXT, &buffer_age);
> +		if (ret == EGL_FALSE) {
> +			weston_log("buffer age query failed.\n");
> +			gl_renderer_print_egl_error_state();
> +		}
> +	}
> +
> +	if (buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT)
> +		pixman_region32_copy(buffer_damage, &output->region);
> +	else
> +		for (i = 0; i < buffer_age - 1; i++)
> +			pixman_region32_union(buffer_damage, buffer_damage,
> +					      &go->buffer_damage[i]);
> +}
> +
> +static void
> +output_rotate_damage(struct weston_output *output,
> +		     pixman_region32_t *output_damage)
> +{
> +	struct gl_output_state *go = get_output_state(output);
> +	struct gl_renderer *gr = get_renderer(output->compositor);
> +	int i;
> +
> +	if (!gr->has_egl_buffer_age)
> +		return;
> +
> +	for (i = BUFFER_DAMAGE_COUNT - 1; i >= 1; i--)
> +		pixman_region32_copy(&go->buffer_damage[i],
> +				     &go->buffer_damage[i - 1]);
> +
> +	pixman_region32_copy(&go->buffer_damage[0], output_damage);
> +}
> +
> +static void
>  gl_renderer_repaint_output(struct weston_output *output,
>  			      pixman_region32_t *output_damage)
>  {
> @@ -956,8 +999,8 @@ gl_renderer_repaint_output(struct weston_output *output,
>  	struct gl_renderer *gr = get_renderer(compositor);
>  	EGLBoolean ret;
>  	static int errored;
> -	int32_t width, height, i;
> -	pixman_region32_t total_damage;
> +	int32_t width, height;
> +	pixman_region32_t buffer_damage, total_damage;
>  
>  	width = output->current->width +
>  		output->border.left + output->border.right;
> @@ -983,18 +1026,18 @@ gl_renderer_repaint_output(struct weston_output *output,
>  		pixman_region32_fini(&undamaged);
>  	}
>  
> -	for (i = 0; i < 2; i++)
> -		pixman_region32_union(&go->buffer_damage[i],
> -				      &go->buffer_damage[i],
> -				      output_damage);
> -
>  	pixman_region32_init(&total_damage);
> -	pixman_region32_copy(&total_damage,
> -			     &go->buffer_damage[go->current_buffer]);
> +	pixman_region32_init(&buffer_damage);
> +
> +	output_get_buffer_damage(output, &buffer_damage);
> +	output_rotate_damage(output, output_damage);
> +
> +	pixman_region32_union(&total_damage, &buffer_damage, output_damage);
>  
>  	repaint_surfaces(output, &total_damage);
>  
>  	pixman_region32_fini(&total_damage);
> +	pixman_region32_fini(&buffer_damage);
>  
>  	if (gr->border.texture)
>  		draw_border(output);
> @@ -1009,8 +1052,6 @@ gl_renderer_repaint_output(struct weston_output *output,
>  		gl_renderer_print_egl_error_state();
>  	}
>  
> -	go->current_buffer ^= 1;
> -
>  }
>  
>  static int
> @@ -1620,8 +1661,7 @@ gl_renderer_output_create(struct weston_output *output,
>  			return -1;
>  		}
>  
> -	go->current_buffer = 0;
> -	for (i = 0; i < 2; i++)
> +	for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
>  		pixman_region32_init(&go->buffer_damage[i]);
>  
>  	output->renderer_state = go;
> @@ -1931,6 +1971,12 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
>  			gr->has_bind_display = 0;
>  	}
>  
> +	if (strstr(extensions, "EGL_EXT_buffer_age"))
> +		gr->has_egl_buffer_age = 1;
> +	else
> +		weston_log("warning: EGL_EXT_buffer_age not supported. "
> +			   "Performance could be affected.\n");
> +
>  	glActiveTexture(GL_TEXTURE0);
>  
>  	if (compile_shaders(ec))



More information about the wayland-devel mailing list