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

Tapani Pälli tapani.palli at intel.com
Thu Jun 1 06:16:30 UTC 2017


Hi Harish;

One thing left for the basic plumbing, sorry I did not mention this 
earlier. Please add a "_eglReturnFalse" fallback for 
eglSetDamageRegionKHR (see _eglInitDriverFallbacks).

Also see one small but significant change below in 'ClampRects' ..

On 06/01/2017 07:42 AM, 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.
>
> Signed-off-by: Harish Krupo <harish.krupo.kps at intel.com>
> ---
>   src/egl/drivers/dri2/egl_dri2.c         | 12 +++++
>   src/egl/drivers/dri2/egl_dri2.h         |  4 ++
>   src/egl/drivers/dri2/platform_android.c | 33 +++++++++++++
>   src/egl/main/eglapi.c                   | 85 +++++++++++++++++++++++++++++++++
>   src/egl/main/eglapi.h                   |  2 +
>   src/egl/main/egldisplay.h               |  1 +
>   src/egl/main/eglentrypoint.h            |  1 +
>   src/egl/main/eglsurface.c               |  8 ++++
>   src/egl/main/eglsurface.h               | 12 +++++
>   9 files changed, 158 insertions(+)
>
> diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
> index 0be7132ac5..c58efbf4d6 100644
> --- a/src/egl/drivers/dri2/egl_dri2.c
> +++ b/src/egl/drivers/dri2/egl_dri2.c
> @@ -1464,6 +1464,17 @@ dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
>   }
>   
>   static EGLBoolean
> +dri2_set_damage_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
> +                       EGLint *rects, EGLint n_rects)
> +{
> +   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
> +   if (dri2_dpy->vtbl->set_damage_region)
> +      return dri2_dpy->vtbl->set_damage_region(drv, dpy, surf, rects, n_rects);
> +
> +   return EGL_FALSE;
> +}
> +
> +static EGLBoolean
>   dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
>                        EGLint x, EGLint y, EGLint width, EGLint height)
>   {
> @@ -2958,6 +2969,7 @@ _eglBuiltInDriverDRI2(const char *args)
>      dri2_drv->base.API.SwapBuffers = dri2_swap_buffers;
>      dri2_drv->base.API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage;
>      dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
> +   dri2_drv->base.API.SetDamageRegion = dri2_set_damage_region;
>      dri2_drv->base.API.PostSubBufferNV = dri2_post_sub_buffer;
>      dri2_drv->base.API.CopyBuffers = dri2_copy_buffers,
>      dri2_drv->base.API.QueryBufferAge = dri2_query_buffer_age;
> diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
> index fdeffb3a85..d2aeda2c83 100644
> --- a/src/egl/drivers/dri2/egl_dri2.h
> +++ b/src/egl/drivers/dri2/egl_dri2.h
> @@ -118,6 +118,10 @@ struct dri2_egl_display_vtbl {
>                                             _EGLSurface *surface,
>                                             const EGLint *rects, EGLint n_rects);
>   
> +   EGLBoolean (*set_damage_region)(_EGLDriver *drv, _EGLDisplay *dpy,
> +                                   _EGLSurface *surface,
> +                                   const EGLint *rects, EGLint n_rects);
> +
>      EGLBoolean (*swap_buffers_region)(_EGLDriver *drv, _EGLDisplay *dpy,
>                                        _EGLSurface *surf, EGLint numRects,
>                                        const EGLint *rects);
> diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c
> index 1ae779e59c..0752e330b4 100644
> --- a/src/egl/drivers/dri2/platform_android.c
> +++ b/src/egl/drivers/dri2/platform_android.c
> @@ -651,6 +651,37 @@ 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));
> +
> +   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
> +   }
> +
> +   native_window_set_surface_damage(dri2_surf->window, droid_rects, n_rects);
> +
> +   free(droid_rects);
> +
> +   return EGL_TRUE;
> +}
> +
>   static _EGLImage *
>   droid_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx,
>                                        struct ANativeWindowBuffer *buf, int fd)
> @@ -1101,6 +1132,7 @@ static struct dri2_egl_display_vtbl droid_display_vtbl = {
>      .swap_buffers = droid_swap_buffers,
>      .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
>      .swap_buffers_region = dri2_fallback_swap_buffers_region,
> +   .set_damage_region = droid_set_damage_region,
>      .post_sub_buffer = dri2_fallback_post_sub_buffer,
>      .copy_buffers = dri2_fallback_copy_buffers,
>      .query_buffer_age = droid_query_buffer_age,
> @@ -1201,6 +1233,7 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy)
>      dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
>      dpy->Extensions.ANDROID_recordable = EGL_TRUE;
>      dpy->Extensions.EXT_buffer_age = EGL_TRUE;
> +   dpy->Extensions.KHR_partial_update = EGL_TRUE;
>   
>      /* Fill vtbl last to prevent accidentally calling virtual function during
>       * initialization.
> diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
> index 9cea2f41ff..444ea45e51 100644
> --- a/src/egl/main/eglapi.c
> +++ b/src/egl/main/eglapi.c
> @@ -505,6 +505,7 @@ _eglCreateExtensionsString(_EGLDisplay *dpy)
>      _EGL_CHECK_EXTENSION(KHR_image_base);
>      _EGL_CHECK_EXTENSION(KHR_image_pixmap);
>      _EGL_CHECK_EXTENSION(KHR_no_config_context);
> +   _EGL_CHECK_EXTENSION(KHR_partial_update);
>      _EGL_CHECK_EXTENSION(KHR_reusable_sync);
>      _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
>      if (dpy->Extensions.EXT_swap_buffers_with_damage)
> @@ -1234,6 +1235,15 @@ eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
>   
>      ret = drv->API.SwapBuffers(drv, disp, surf);
>   
> +   /* EGL_KHR_partial_update
> +    * Frame boundary successfully reached,
> +    * reset damage region and reset BufferAgeRead
> +    */
> +   if (ret) {
> +      surf->SetDamageRegion = EGL_FALSE;
> +      surf->BufferAgeRead = EGL_FALSE;
> +   }
> +
>      RETURN_EGL_EVAL(disp, ret);
>   }
>   
> @@ -1258,6 +1268,15 @@ _eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf,
>   
>      ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects);
>   
> +   /* EGL_KHR_partial_update
> +    * Frame boundary successfully reached,
> +    * reset damage region and reset BufferAgeRead
> +    */
> +   if (ret) {
> +      surf->SetDamageRegion = EGL_FALSE;
> +      surf->BufferAgeRead = EGL_FALSE;
> +   }
> +
>      RETURN_EGL_EVAL(disp, ret);
>   }
>   
> @@ -1281,6 +1300,72 @@ 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)

this line exceeds 80 chars, please fix

> +{
> +   EGLint i;
> +   EGLint surfHeight = surf->Height;
> +   EGLint surfWidth = surf->Width;
> +
> +   for (i = 0; i < (4 * n_rects); i =+ 4) {

i += 4, right? I do wonder how tests passed with this unless they always 
submit just one rect?

> +      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)
> +      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;
> +
> +   RETURN_EGL_EVAL(disp, ret);
> +}
> +
>   EGLBoolean EGLAPIENTRY
>   eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
>   {
> diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
> index 710c5d860a..ebd31da3e5 100644
> --- a/src/egl/main/eglapi.h
> +++ b/src/egl/main/eglapi.h
> @@ -110,6 +110,8 @@ struct _egl_api
>                                _EGLSurface *draw);
>      EGLBoolean (*CopyBuffers)(_EGLDriver *drv, _EGLDisplay *dpy,
>                                _EGLSurface *surface, void *native_pixmap_target);
> +   EGLBoolean (*SetDamageRegion)(_EGLDriver *drv, _EGLDisplay *dpy,
> +                                 _EGLSurface *surface, EGLint *rects, EGLint n_rects);
>   
>      /* misc functions */
>      EGLBoolean (*WaitClient)(_EGLDriver *drv, _EGLDisplay *dpy,
> diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
> index 4d3d96e174..d3c48ace5c 100644
> --- a/src/egl/main/egldisplay.h
> +++ b/src/egl/main/egldisplay.h
> @@ -117,6 +117,7 @@ struct _egl_extensions
>      EGLBoolean KHR_image_base;
>      EGLBoolean KHR_image_pixmap;
>      EGLBoolean KHR_no_config_context;
> +   EGLBoolean KHR_partial_update;
>      EGLBoolean KHR_reusable_sync;
>      EGLBoolean KHR_surfaceless_context;
>      EGLBoolean KHR_wait_sync;
> 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)
>   EGL_ENTRYPOINT(eglSwapInterval)
>   EGL_ENTRYPOINT(eglTerminate)
>   EGL_ENTRYPOINT(eglUnbindWaylandDisplayWL)
> diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
> index e935c83271..e42e815828 100644
> --- a/src/egl/main/eglsurface.c
> +++ b/src/egl/main/eglsurface.c
> @@ -317,6 +317,8 @@ _eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
>      surf->AspectRatio = EGL_UNKNOWN;
>   
>      surf->PostSubBufferSupportedNV = EGL_FALSE;
> +   surf->SetDamageRegion = EGL_FALSE;
> +   surf->BufferAgeRead = EGL_FALSE;
>   
>      /* the default swap interval is 1 */
>      _eglClampSwapInterval(surf, 1);
> @@ -409,7 +411,13 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
>            _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
>            return EGL_FALSE;
>         }
> +      _EGLContext *ctx = _eglGetCurrentContext();
> +      if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || ctx->DrawSurface != surface) {
> +         _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
> +         return EGL_FALSE;
> +      }
>         *value = drv->API.QueryBufferAge(drv, dpy, surface);
> +      surface->BufferAgeRead = EGL_TRUE;
>         break;
>      default:
>         _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
> diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h
> index f13cf49741..c7be4088a1 100644
> --- a/src/egl/main/eglsurface.h
> +++ b/src/egl/main/eglsurface.h
> @@ -82,6 +82,18 @@ struct _egl_surface
>   
>      EGLint SwapInterval;
>   
> +   /* EGL_KHR_partial_update
> +    * True if the damage region is already set
> +    * between frame boundaries.
> +    */
> +   EGLBoolean SetDamageRegion;
> +
> +   /* EGL_KHR_partial_update
> +    * True if the buffer age is read by the client
> +    * between frame boundaries.
> +    */
> +   EGLBoolean BufferAgeRead;
> +
>      /* True if the surface is bound to an OpenGL ES texture */
>      EGLBoolean BoundToTexture;
>   




More information about the mesa-dev mailing list