[PATCH 2/2] compositor: add a masking mechanism to weston_layer

Ander Conselvan de Oliveira conselvan2 at gmail.com
Tue Jan 28 08:21:40 PST 2014


On 01/27/2014 09:46 PM, Giulio Camuffo wrote:
> this adds a mechanism to mask the views belonging to a layer
> to an arbitrary rect, in the global space. The parts that don't fit
> in that rect will be clipped away.
> Implemented in the gl and pixman renderers only for now.
> ---
>   src/compositor.c      | 26 +++++++++++++++++++++++++-
>   src/compositor.h      |  7 +++++++
>   src/gl-renderer.c     |  4 ++++
>   src/pixman-renderer.c |  4 ++++
>   4 files changed, 40 insertions(+), 1 deletion(-)
>
> diff --git a/src/compositor.c b/src/compositor.c
> index 9a269e5..25068b8 100644

[...]

> diff --git a/src/gl-renderer.c b/src/gl-renderer.c
> index 0e5afbe..899c280 100644
> --- a/src/gl-renderer.c
> +++ b/src/gl-renderer.c
> @@ -521,6 +521,10 @@ draw_view(struct weston_view *ev, struct weston_output *output,
>   	pixman_region32_intersect(&repaint,
>   				  &ev->transform.boundingbox, damage);
>   	pixman_region32_subtract(&repaint, &repaint, &ev->clip);
> +	pixman_region32_t mask;
> +	pixman_region32_init_with_extents(&mask, &ev->layer_link.layer->mask);
> +	pixman_region32_intersect(&repaint, &repaint, &mask);
> +	pixman_region32_fini(&mask);

There are more things you need to consider in order to clip properly.

1) Opaque region. This is used to avoid rendering obscured parts of 
surfaces. In compositor_accumulate_damage(), a clip region for each 
surface is determined as the union of the opaque regions of the surfaces 
on top of it. That way, the parts of the surface that are covered by 
other opaque content is not rendered.

You can see the effect of this relatively easily. Patch desktop-shell to 
set a clip for the workspace layer that is smaller than the screen. Then 
running Weston with the X11 backend (or just make sure you have a 
software rendered cursor), open a weston-terminal and move it so that it 
crosses the border of the clipped region. Then move the mouse over the 
region that should be part of the terminal but is clipped away. Notice 
how the background is not redrawn properly.

In order to fix this, the opaque region used for calculating the surface 
clip also needs to be clipped.

2) Sprite planes. There's another path through which content can get to 
the screen. When a view is put on a sprite plane, it complete bypasses 
the renderer. During the repaint process, the core gives the backend a 
chance to move views to different planes. At that moment, the backend 
could configure the sprite plane to clip the surface or just decide to 
not to use a sprite plane for it. However, it needs the clipping 
information to make that decision.

If I understand correctly, the rpi backend relies heavily on planes. The 
DRM backend has support for sprite planes too, but it is disabled since 
it can't work correctly without a patched kernel. You can try it (with a 
regular kernel) by pressing mod-shift-space followed by 'v'. If you run 
weston-simple-egl -o, you'll notice the clipping won't work when the 
surface is in a sprite plane.


Given the points above, I believe it would be better to keep the 
information related to clipping in the weston_view structure. That way 
the backend and the renderer can be completely unaware of the existence 
of layers. The clipping information can be propagated from the layers to 
the views in the beginning of weston_output_repaint() and/or as part of 
weston_view_update_transform().


Cheers,
Ander



>
>   	if (!pixman_region32_not_empty(&repaint))
>   		goto out;
> diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
> index 26f6f27..511dd8b 100644
> --- a/src/pixman-renderer.c
> +++ b/src/pixman-renderer.c
> @@ -374,6 +374,10 @@ draw_view(struct weston_view *ev, struct weston_output *output,
>   	pixman_region32_intersect(&repaint,
>   				  &ev->transform.boundingbox, damage);
>   	pixman_region32_subtract(&repaint, &repaint, &ev->clip);
> +	pixman_region32_t mask;
> +	pixman_region32_init_with_extents(&mask, &ev->layer_link.layer->mask);
> +	pixman_region32_intersect(&repaint, &repaint, &mask);
> +	pixman_region32_fini(&mask);
>
>   	if (!pixman_region32_not_empty(&repaint))
>   		goto out;
>



More information about the wayland-devel mailing list