diff options
author | Harish Krupo <[email protected]> | 2017-06-09 20:13:34 +0530 |
---|---|---|
committer | Eric Engestrom <[email protected]> | 2017-06-11 01:02:09 +0100 |
commit | 9827547313c7239486efbd4067529575f98f1622 (patch) | |
tree | d7480589edac8c714e0f689d6b5b00ed6eb4eaa2 /src/egl/main/eglapi.c | |
parent | f3c0bbe18ac65d22b2630f89fc1628bfe79695d4 (diff) |
egl/android: support for EGL_KHR_partial_update
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)
v4: use newly introduced ANDROID_API_LEVEL guard rather than
ANDROID_VERSION guard to advertise the extension.The extension
is advertised only if ANDROID_API_LEVEL >= 23 (Android 6.0 or
greater). Add fallback function for platforms other than Android.
Fix possible math overflow. (Emil Velikov)
Return immediately when n_rects is 0. Place function's entrypoint
in alphabetical order. (Eric Engestrom)
v5: Replace unnecessary calloc with malloc (Eric)
Check for BAD_ALLOC error (Emil)
Check for error in native_window_set_damage_region. (Emil, Tapani,
Eric).
Signed-off-by: Harish Krupo <[email protected]>
Reviewed-by: Emil Velikov <[email protected]>
Reviewed-by: Eric Engestrom <[email protected]>
Reviewed-by: Tapani Pälli <[email protected]>
Diffstat (limited to 'src/egl/main/eglapi.c')
-rw-r--r-- | src/egl/main/eglapi.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index e6355ace872..9b899d85244 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -506,6 +506,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) @@ -1235,6 +1236,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->SetDamageRegionCalled = EGL_FALSE; + surf->BufferAgeRead = EGL_FALSE; + } + RETURN_EGL_EVAL(disp, ret); } @@ -1259,6 +1269,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->SetDamageRegionCalled = EGL_FALSE; + surf->BufferAgeRead = EGL_FALSE; + } + RETURN_EGL_EVAL(disp, ret); } @@ -1282,6 +1301,70 @@ 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 surf_height = surf->Height; + EGLint surf_width = surf->Width; + + for (i = 0; i < (4 * n_rects); i += 4) { + EGLint x, y, rect_width, rect_height; + x = rects[i]; + y = rects[i + 1]; + rect_width = rects[i + 2]; + rect_height = rects[i + 3]; + + if (rect_width > surf_width - x) + rects[i + 2] = surf_width - x; + + if (rect_height > surf_height - y) + rects[i + 3] = surf_height - 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 or + * buffer age is not queried between + * frame boundaries, throw bad access error + */ + + if (surf->SetDamageRegionCalled || !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->SetDamageRegionCalled = EGL_TRUE; + + RETURN_EGL_EVAL(disp, ret); +} + EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) { |