[PATCH weston v2] gl-renderer: If an XRGB format is requested but unavailable, try ARGB

Pekka Paalanen ppaalanen at gmail.com
Mon May 11 06:57:34 PDT 2015


On Tue,  5 May 2015 16:22:22 -0500
Derek Foreman <derekf at osg.samsung.com> wrote:

> Recent versions of Mesa have stopped exposing XRGB visuals for gl on
> some Intel GPUs.  While this may be changed in Mesa eventually, it's
> not impossible that some other hardware in the future won't provide
> XRGB visuals either.
> 
> Let's try again with an ARGB visual if XRGB is unavailable.  Since
> we're not changing the scanout buffer format, and our current
> rendering loop always results in saturated alpha in the frame buffer,
> it should be Just Fine(tm) - and probably better than just exiting.
> 
> Signed-off-by: Derek Foreman <derekf at osg.samsung.com>
> ---
> 
> Dima Ryazanov called me out for fallback_format() not working on all endians,
> and I've reworked the loop to be a single loop instead of two, similar to
> Daniel's suggestion (but still keeping the NULL visual_id means "give me the
> first match" semantic of the original)
> 
> I've also replaced calloc with aloca so I don't have to worry about freeing
> the array on return, which simplifies things a little bit.  I didn't bother
> zeroing out the array, since it's filled in by eglChooseConfig.
> 
> It's still an ugly function. :)
> 
>  src/gl-renderer.c | 57 +++++++++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 43 insertions(+), 14 deletions(-)
> 
> diff --git a/src/gl-renderer.c b/src/gl-renderer.c
> index ae3122f..a4fd3a0 100644
> --- a/src/gl-renderer.c
> +++ b/src/gl-renderer.c
> @@ -934,6 +934,14 @@ output_rotate_damage(struct weston_output *output,
>  	go->border_damage[go->buffer_damage_index] = border_status;
>  }
>  
> +/* NOTE: We now allow falling back to ARGB  gl visual ids when XRGB is
> + * unavailable, so we're assuming the background has no transparency
> + * and that everything with a blend, like drop shadows, will have something
> + * opaque (like the background) drawn underneath it.
> + *
> + * Depending on the underlying hardware, violating that assumption could
> + * result in seeing through to another display plane.
> + */
>  static void
>  gl_renderer_repaint_output(struct weston_output *output,
>  			      pixman_region32_t *output_damage)
> @@ -1897,6 +1905,15 @@ log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
>  		weston_log_continue(" unknown\n");
>  }
>  
> +static EGLint
> +fallback_format(EGLint format)
> +{
> +	if ((format & 0xFF) != 'X')
> +		return 0;
> +
> +	return (format & 0xFFFFFF00) | 'A';
> +}

I read the function name, I read the code, and I repeat that 6 times
before I figure out the right interpretation. That's pretty awesome. In
a not fun way. :-P

How about calling it get_fallback_format_for()?

Are you sure this works for X11 Visuals too? Oh, but x11-backend
doesn't pass any visual in, so that saves you.

What about GBM visuals (drmfourccs) like RA24 or BA24? Oh, but this
actually a GBM format code, which is hand-picked and cannot just
whatever, so this works.

There's so much fun going on, that I'd like to have big comment
explaining it all, please. :-)

With all these assumptions around, you might as well just hardcode a
switch-statement and say in comments where the funny numbers come from.

Or, even better, extend the gl_renderer_create() API to have the
fallback format passed in explicitly from the backend, which can then
use the proper #defined names. Or go even further, if there is a list
of acceptable visuals.

It's a question of how far you want to go...

> +
>  static int
>  egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
>  		  const EGLint *visual_id,
> @@ -1904,41 +1921,53 @@ egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
>  {
>  	EGLint count = 0;
>  	EGLint matched = 0;
> +	EGLint fallback_id;
>  	EGLConfig *configs;
> +	EGLConfig fallback_config = 0;
>  	int i;
>  
>  	if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
>  		return -1;
>  
> -	configs = calloc(count, sizeof *configs);
> +	configs = alloca(count * sizeof *configs);

The number of eglconfigs could be large, so maybe alloca isn't quite
right here...

>  	if (!configs)
>  		return -1;

Can't test this with alloca.

>  
>  	if (!eglChooseConfig(gr->egl_display, attribs, configs,
>  			      count, &matched))
> -		goto out;
> +		return -1;
> +
> +	if (!matched)
> +		return -1;
>  
> +	if (!visual_id) {
> +		*config_out = configs[0];
> +		return 0;
> +	}
> +
> +	fallback_id = fallback_format(*visual_id);
>  	for (i = 0; i < matched; ++i) {
>  		EGLint id;
>  
> -		if (visual_id) {
> -			if (!eglGetConfigAttrib(gr->egl_display,
> -					configs[i], EGL_NATIVE_VISUAL_ID,
> -					&id))
> -				continue;
> +		if (!eglGetConfigAttrib(gr->egl_display,
> +				configs[i], EGL_NATIVE_VISUAL_ID,
> +				&id))
> +			continue;
>  
> -			if (id != 0 && id != *visual_id)
> -				continue;
> +		if (id == *visual_id) {
> +			*config_out = configs[i];
> +			return 0;
>  		}
> +		if (id == fallback_id)
> +			fallback_config = configs[i];
> +	}

Hmm, but if we end up with the fallback_config, we will get the last
config that matches fallback. Usually we prefer the first config that
matches. Would it make sense to use the first fallback-matching config
in that case?

>  
> -		*config_out = configs[i];
> -
> -		free(configs);
> +	if (fallback_config) {
> +		weston_log("Falling back to ARGB visual\n");
> +		*config_out = fallback_config;
>  		return 0;
>  	}
>  
> -out:
> -	free(configs);
>  	return -1;
>  }
>  

Thanks,
pq


More information about the wayland-devel mailing list