[Mesa-dev] [PATCH v2] egl/wayland: Support for KHR_partial_update

Eric Engestrom eric.engestrom at imgtec.com
Fri Oct 20 18:07:33 UTC 2017


On Friday, 2017-10-20 11:35:40 +0000, Harish Krupo wrote:
> This passes 33/37 deqp tests related to partial_update, 4 are not
> supported. Tests not supported:
> dEQP-EGL.functional.negative_partial_update.not_postable_surface
> dEQP-EGL.functional.negative_partial_update.not_current_surface
> dEQP-EGL.functional.negative_partial_update.buffer_preserved
> dEQP-EGL.functional.negative_partial_update.not_current_surface2
> Reason: No matching egl config found.
> 
> v2: Remove unnecessary return statement. Keep function names
>     consistent.  (Emil Velikov)
>     Add not supported list to commit message. (Eric Engestrom)
> 
> Signed-off-by: Harish Krupo <harish.krupo.kps at intel.com>
> ---
>  src/egl/drivers/dri2/platform_wayland.c | 67 ++++++++++++++++++++++++++++-----
>  1 file changed, 58 insertions(+), 9 deletions(-)
> 
> diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
> index b38eb1c335..daa148380b 100644
> --- a/src/egl/drivers/dri2/platform_wayland.c
> +++ b/src/egl/drivers/dri2/platform_wayland.c
> @@ -809,15 +809,38 @@ try_damage_buffer(struct dri2_egl_surface *dri2_surf,
>     }
>     return EGL_TRUE;
>  }
> +
>  /**
> - * Called via eglSwapBuffers(), drv->API.SwapBuffers().
> + * Called via eglSetDamageRegionKHR(), drv->API.SetDamageRegion().
>   */
>  static EGLBoolean
> -dri2_wl_swap_buffers_with_damage(_EGLDriver *drv,
> -                                 _EGLDisplay *disp,
> -                                 _EGLSurface *draw,
> -                                 const EGLint *rects,
> -                                 EGLint n_rects)
> +dri2_wl_set_damage_region(_EGLDriver *drv,
> +                     _EGLDisplay *dpy,
> +                     _EGLSurface *surf,
> +                     const EGLint *rects,
> +                     EGLint n_rects)
> +{
> +   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
> +
> +   /* The spec doesn't mention what should be returned in case of
> +    * failure in setting the damage buffer with the window system, so
> +    * setting the damage to maximum surface area
> +    */
> +   if (!n_rects || !try_damage_buffer(dri2_surf, rects, n_rects)) {
> +      wl_surface_damage(dri2_surf->wl_surface_wrapper,
> +                        0, 0, INT32_MAX, INT32_MAX);
> +   }
> +
> +   return EGL_TRUE;
> +}
> +
> +static EGLBoolean
> +dri2_wl_swap_buffers_common(_EGLDriver *drv,
> +                            _EGLDisplay *disp,
> +                            _EGLSurface *draw,
> +                            const EGLint *rects,
> +                            EGLint n_rects,
> +                            EGLBoolean with_damage)
>  {
>     struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
>     struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
> @@ -875,7 +898,17 @@ dri2_wl_swap_buffers_with_damage(_EGLDriver *drv,
>     /* If the compositor doesn't support damage_buffer, we deliberately
>      * ignore the damage region and post maximum damage, due to
>      * https://bugs.freedesktop.org/78190 */
> -   if (!n_rects || !try_damage_buffer(dri2_surf, rects, n_rects))
> +
> +   if (!with_damage) {
> +
> +      /* If called from swapBuffers, check if the damage region
> +       * is already set, if not set to full damage
> +       */
> +      if (!dri2_surf->base.SetDamageRegionCalled)
> +         wl_surface_damage(dri2_surf->wl_surface_wrapper,
> +                           0, 0, INT32_MAX, INT32_MAX);
> +   }
> +   else if (!n_rects || !try_damage_buffer(dri2_surf, rects, n_rects))
>        wl_surface_damage(dri2_surf->wl_surface_wrapper,
>                          0, 0, INT32_MAX, INT32_MAX);

Per spec [1]:
> If <n_rects> is 0 then <rects> is ignored and the entire
> surface is implicitly damaged and the behaviour is equivalent
> to calling eglSwapBuffers.

I interpret this as "the entire surface is implicitly damaged" being
overridden by "the behaviour is equivalent to calling eglSwapBuffers",
as the former was just a reiteration of the latter before
EGL_KHR_partial_update.
In other words: SwapBuffers() == SwapBuffersWithDamage(NULL, 0)

One could argue that the "the entire surface is implicitly damaged" is
more important, in which case the behaviour counter-intuitive IMO:

SetDamage(rect)
SwapBuffersWithDamage(NULL, 0)

would result in the whole screen being redrawn, which doesn't sound like
what the client wanted.


Since SwapBuffers() works by calling SwapBuffersWithDamage(NULL, 0),
`with_damage == !n_rects` and can be dropped.

Your dri2_wl_set_damage_region() correctly handles the `!n_rects` case
already, so the whole above `if {} else if {}` block can be replaced
with:

   if (n_rects != 0 || !dri2_surf->base.SetDamageRegionCalled)
      dri2_wl_set_damage_region(drv, dpy, surf, rects, n_rects);

[1] https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_swap_buffers_with_damage.txt

>  
> @@ -911,6 +944,20 @@ dri2_wl_swap_buffers_with_damage(_EGLDriver *drv,
>     return EGL_TRUE;
>  }
>  
> +/**
> + * Called via eglSwapBuffers(), drv->API.SwapBuffers().

This was already wrong before, you only moved it, but you might as well
fix it :)
* Called via eglSwapBuffersWithDamage{KHR,EXT}(), drv->API.SwapBuffersWithDamageEXT().

> + */
> +static EGLBoolean
> +dri2_wl_swap_buffers_with_damage(_EGLDriver *drv,
> +                                 _EGLDisplay *disp,
> +                                 _EGLSurface *draw,
> +                                 const EGLint *rects,
> +                                 EGLint n_rects)
> +{
> +   return dri2_wl_swap_buffers_common(drv, disp, draw,
> +                                      rects, n_rects, EGL_TRUE);
> +}
> +
>  static EGLint
>  dri2_wl_query_buffer_age(_EGLDriver *drv,
>                           _EGLDisplay *disp, _EGLSurface *surface)
> @@ -928,7 +975,8 @@ dri2_wl_query_buffer_age(_EGLDriver *drv,
>  static EGLBoolean
>  dri2_wl_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
>  {
> -   return dri2_wl_swap_buffers_with_damage(drv, disp, draw, NULL, 0);
> +   return dri2_wl_swap_buffers_common(drv, disp, draw,
> +                                      NULL, 0, EGL_FALSE);
>  }
>  
>  static struct wl_buffer *
> @@ -1166,7 +1214,7 @@ static const struct dri2_egl_display_vtbl dri2_wl_display_vtbl = {
>     .swap_buffers = dri2_wl_swap_buffers,
>     .swap_buffers_with_damage = dri2_wl_swap_buffers_with_damage,
>     .swap_buffers_region = dri2_fallback_swap_buffers_region,
> -   .set_damage_region = dri2_fallback_set_damage_region,
> +   .set_damage_region = dri2_wl_set_damage_region,
>     .post_sub_buffer = dri2_fallback_post_sub_buffer,
>     .copy_buffers = dri2_fallback_copy_buffers,
>     .query_buffer_age = dri2_wl_query_buffer_age,
> @@ -1378,6 +1426,7 @@ dri2_initialize_wayland_drm(_EGLDriver *drv, _EGLDisplay *disp)
>     disp->Extensions.EXT_buffer_age = EGL_TRUE;
>  
>     disp->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE;
> +   disp->Extensions.KHR_partial_update = EGL_TRUE;
>  
>     /* Fill vtbl last to prevent accidentally calling virtual function during
>      * initialization.
> -- 
> 2.14.2
> 


More information about the mesa-dev mailing list