summaryrefslogtreecommitdiffstats
path: root/src/egl/main
diff options
context:
space:
mode:
authorHarish Krupo <[email protected]>2017-06-09 20:13:34 +0530
committerEric Engestrom <[email protected]>2017-06-11 01:02:09 +0100
commit9827547313c7239486efbd4067529575f98f1622 (patch)
treed7480589edac8c714e0f689d6b5b00ed6eb4eaa2 /src/egl/main
parentf3c0bbe18ac65d22b2630f89fc1628bfe79695d4 (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')
-rw-r--r--src/egl/main/eglapi.c83
-rw-r--r--src/egl/main/eglapi.h2
-rw-r--r--src/egl/main/egldisplay.h1
-rw-r--r--src/egl/main/eglentrypoint.h1
-rw-r--r--src/egl/main/eglfallbacks.c1
-rw-r--r--src/egl/main/eglsurface.c9
-rw-r--r--src/egl/main/eglsurface.h12
7 files changed, 109 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)
{
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index cab3e9605a0..852a34584ea 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 9685bed360c..a13ff5bb1b1 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -118,6 +118,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 b9dca7ceda2..f7fe77410d5 100644
--- a/src/egl/main/eglentrypoint.h
+++ b/src/egl/main/eglentrypoint.h
@@ -63,6 +63,7 @@ EGL_ENTRYPOINT(eglQuerySurface)
EGL_ENTRYPOINT(eglQueryWaylandBufferWL)
EGL_ENTRYPOINT(eglReleaseTexImage)
EGL_ENTRYPOINT(eglReleaseThread)
+EGL_ENTRYPOINT(eglSetDamageRegionKHR)
EGL_ENTRYPOINT(eglSignalSyncKHR)
EGL_ENTRYPOINT(eglSurfaceAttrib)
EGL_ENTRYPOINT(eglSwapBuffers)
diff --git a/src/egl/main/eglfallbacks.c b/src/egl/main/eglfallbacks.c
index 017d337133e..1575ab5f793 100644
--- a/src/egl/main/eglfallbacks.c
+++ b/src/egl/main/eglfallbacks.c
@@ -77,6 +77,7 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
drv->API.ReleaseTexImage = (void*) _eglReturnFalse;
drv->API.CopyBuffers = (void*) _eglReturnFalse;
drv->API.SwapBuffers = (void*) _eglReturnFalse;
+ drv->API.SetDamageRegion = (void*) _eglReturnFalse;
drv->API.SwapInterval = _eglSwapInterval;
drv->API.WaitClient = (void*) _eglReturnFalse;
diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
index 5b3e83ee92c..8094912ba12 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->SetDamageRegionCalled = EGL_FALSE;
+ surf->BufferAgeRead = EGL_FALSE;
/* the default swap interval is 1 */
_eglClampSwapInterval(surf, 1);
@@ -409,11 +411,18 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
_eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
return EGL_FALSE;
}
+ _EGLContext *ctx = _eglGetCurrentContext();
EGLint result = drv->API.QueryBufferAge(drv, dpy, surface);
/* error happened */
if (result < 0)
return EGL_FALSE;
+ if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
+ ctx->DrawSurface != surface) {
+ _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
+ return EGL_FALSE;
+ }
*value = result;
+ 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 f13cf49741b..c53e8d00671 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 SetDamageRegionCalled;
+
+ /* 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;