[Mesa-dev] [PATCH v3] egl/android: support for EGL_KHR_partial_update

Eric Engestrom eric.engestrom at imgtec.com
Tue Jun 6 14:09:21 UTC 2017


On Monday, 2017-06-05 19:37:55 +0530, Harish Krupo wrote:
> This patch adds support for the EGL_KHR_partial_update extension for
> android platform. It passes 36/37 tests in dEQP for EGL_KHR_partial_update.
> 1 test not supported.
> 
> v2: add fallback for eglSetDamageRegionKHR (Tapani)
> 
> v3: The native_window_set_surface_damage call is available only from
>     Android version 6.0. Reintroduce the ANDROID_VERSION guard and
>     advertise extension only if version is >= 6.0. (Emil Velikov)
> 
> Signed-off-by: Harish Krupo <harish.krupo.kps at intel.com>
> ---
>  Android.common.mk                       |  3 +-
>  Android.mk                              |  2 +
>  src/egl/drivers/dri2/egl_dri2.c         | 12 +++++
>  src/egl/drivers/dri2/egl_dri2.h         |  4 ++
>  src/egl/drivers/dri2/platform_android.c | 37 ++++++++++++++
>  src/egl/main/eglapi.c                   | 87 +++++++++++++++++++++++++++++++++
>  src/egl/main/eglapi.h                   |  2 +
>  src/egl/main/egldisplay.h               |  1 +
>  src/egl/main/eglentrypoint.h            |  1 +
>  src/egl/main/eglfallbacks.c             |  1 +
>  src/egl/main/eglsurface.c               |  8 +++
>  src/egl/main/eglsurface.h               | 12 +++++
>  12 files changed, 169 insertions(+), 1 deletion(-)
> 
[snip]
> diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c
> index 1ae779e59c..8e9530b7ed 100644
> --- a/src/egl/drivers/dri2/platform_android.c
> +++ b/src/egl/drivers/dri2/platform_android.c
> @@ -651,6 +651,39 @@ droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
>     return EGL_TRUE;
>  }
>  
> +static EGLBoolean
> +droid_set_damage_region(_EGLDriver *drv,
> +                        _EGLDisplay *disp,
> +                        _EGLSurface *draw, const EGLint* rects, EGLint n_rects)
> +{
> +   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> +   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
> +   android_native_rect_t* droid_rects = NULL;
> +   if (n_rects != 0)
> +      droid_rects = (android_native_rect_t *)
> +         calloc(n_rects, sizeof(android_native_rect_t));

if (n_rects == 0)
   return EGL_TRUE;

Nothing else will happen in this function when no rectangle is passed
in, so we might as well return right away, and carry on with the rest of
the code normally.
(Note that `native_window_set_surface_damage(..., NULL, 0)` has the same
effect as not calling it for the frame, ie. full damage.)

> +
> +   EGLint surfWidth = dri2_surf->base.Width;
> +   EGLint surfHeight = dri2_surf->base.Height;
> +   EGLint dIndex;
> +
> +   for (dIndex = 0; dIndex < n_rects; dIndex++) {
> +      EGLint i = dIndex * 4;
> +      droid_rects[dIndex].left = rects[i]; // left == x
> +      droid_rects[dIndex].bottom = rects[i + 1]; // bottom == y
> +      droid_rects[dIndex].right = rects[i] + rects[i + 2]; // left + width
> +      droid_rects[dIndex].top = rects[i + 1] + rects[i + 3]; // bottom + height
> +   }
> +
> +#if ANDROID_VERSION >= 0x600
> +   native_window_set_surface_damage(dri2_surf->window, droid_rects, n_rects);
> +#endif
> +
> +   free(droid_rects);
> +
> +   return EGL_TRUE;
> +}
> +
>  static _EGLImage *
>  droid_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx,
>                                       struct ANativeWindowBuffer *buf, int fd)
[snip]
> diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
> index 9cea2f41ff..0da07e6e1f 100644
> --- a/src/egl/main/eglapi.c
> +++ b/src/egl/main/eglapi.c
> @@ -1281,6 +1300,74 @@ eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface,
>     return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
>  }
>  
> +/*
> + * If the width of the passed rect is greater than the surface's
> + * width then it is clamped to the width of the surface. Same with
> + * height.
> + */
> +
> +static void
> +_eglSetDamageRegionKHRClampRects(_EGLDisplay* disp, _EGLSurface* surf,
> +                                 EGLint *rects, EGLint n_rects)
> +{
> +   EGLint i;
> +   EGLint surfHeight = surf->Height;
> +   EGLint surfWidth = surf->Width;
> +
> +   for (i = 0; i < (4 * n_rects); i += 4) {
> +      EGLint x, y, rectWidth, rectHeight;
> +      x = rects[i];
> +      y = rects[i + 1];
> +      rectWidth = rects[i + 2];
> +      rectHeight = rects[i + 3];
> +
> +      if (rectWidth + x > surfWidth)
> +         rects[i + 2] = surfWidth - x;
> +
> +      if (rectHeight + y > surfHeight)
> +         rects[i + 3] = surfHeight - y;
> +   }
> +}
> +
> +static EGLBoolean EGLAPIENTRY
> +eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
> +                      EGLint *rects, EGLint n_rects)
> +{
> +   _EGLDisplay *disp = _eglLockDisplay(dpy);
> +   _EGLSurface *surf = _eglLookupSurface(surface, disp);
> +   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
> +   _EGLContext *ctx = _eglGetCurrentContext();
> +   _EGLDriver *drv;
> +   EGLBoolean ret;
> +   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
> +
> +   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
> +       surf->Type != EGL_WINDOW_BIT || ctx->DrawSurface != surf ||
> +       surf->SwapBehavior != EGL_BUFFER_DESTROYED)
> +      RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
> +
> +   /* If the damage region is already set between
> +    * frame boundaries, throw bad access error
> +    */
> +   if (surf->SetDamageRegion)
> +      RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
> +
> +   /* If the buffer age has not been queried before
> +    * setting the damage region, between
> +    * frame boundaries, throw bad access error
> +    */
> +   if (! surf->BufferAgeRead)

Nit: remove space after `!`.

> +      RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
> +
> +   _eglSetDamageRegionKHRClampRects(disp, surf, rects, n_rects);
> +   ret = drv->API.SetDamageRegion(drv, disp, surf, rects, n_rects);
> +
> +   if (ret)
> +      surf->SetDamageRegion = EGL_TRUE;

Please give this a different name than the function.
`SetDamageRegionCalled` for instance.

> +
> +   RETURN_EGL_EVAL(disp, ret);
> +}
> +
>  EGLBoolean EGLAPIENTRY
>  eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
>  {
[snip]
> diff --git a/src/egl/main/eglentrypoint.h b/src/egl/main/eglentrypoint.h
> index e6318b9311..ea97e86291 100644
> --- a/src/egl/main/eglentrypoint.h
> +++ b/src/egl/main/eglentrypoint.h
> @@ -67,6 +67,7 @@ EGL_ENTRYPOINT(eglSwapBuffers)
>  EGL_ENTRYPOINT(eglSwapBuffersRegionNOK)
>  EGL_ENTRYPOINT(eglSwapBuffersWithDamageEXT)
>  EGL_ENTRYPOINT(eglSwapBuffersWithDamageKHR)
> +EGL_ENTRYPOINT(eglSetDamageRegionKHR)

This list needs to be kept in alphabetical order, or the entrypoint
won't be accessible.
Please run `make check` to make sure you move it to the correct place.

>  EGL_ENTRYPOINT(eglSwapInterval)
>  EGL_ENTRYPOINT(eglTerminate)
>  EGL_ENTRYPOINT(eglUnbindWaylandDisplayWL)


More information about the mesa-dev mailing list