Add the EGL_ANDROID_get_frame_timestamps extension
Change-Id: Ia7d1c10f0b8bd1f2f6dc7dc180764cb1b4fdbf6f
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index e793852..7a0cce4 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -84,6 +84,7 @@
"EGL_KHR_swap_buffers_with_damage "
"EGL_ANDROID_create_native_client_buffer "
"EGL_ANDROID_front_buffer_auto_refresh "
+ "EGL_ANDROID_get_frame_timestamps "
;
extern char const * const gExtensionString =
"EGL_KHR_image " // mandatory
@@ -207,6 +208,12 @@
(__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
{ "eglCreateStreamFromFileDescriptorKHR",
(__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
+
+ // EGL_ANDROID_get_frame_timestamps
+ { "eglGetFrameTimestampsANDROID",
+ (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
+ { "eglQueryTimestampSupportedANDROID",
+ (__eglMustCastToProperFunctionPointerType)&eglQueryTimestampSupportedANDROID },
};
/*
@@ -1196,7 +1203,7 @@
if (!_s.get())
return setError(EGL_BAD_SURFACE, EGL_FALSE);
- egl_surface_t const * const s = get_surface(surface);
+ egl_surface_t * const s = get_surface(surface);
if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
int err = native_window_set_auto_refresh(s->win.get(),
@@ -1205,6 +1212,11 @@
setError(EGL_BAD_SURFACE, EGL_FALSE);
}
+ if (attribute == EGL_TIMESTAMPS_ANDROID) {
+ s->enableTimestamps = value;
+ return EGL_TRUE;
+ }
+
if (s->cnx->egl.eglSurfaceAttrib) {
return s->cnx->egl.eglSurfaceAttrib(
dp->disp.dpy, s->surface, attribute, value);
@@ -1935,3 +1947,103 @@
return EGL_FALSE;
}
+
+EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
+ EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps,
+ EGLnsecsANDROID *values)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) {
+ setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ return EGL_FALSE;
+ }
+
+ SurfaceRef _s(dp.get(), surface);
+ if (!_s.get()) {
+ setError(EGL_BAD_SURFACE, EGL_FALSE);
+ return EGL_FALSE;
+ }
+
+ egl_surface_t const * const s = get_surface(surface);
+
+ if (!s->enableTimestamps) {
+ setError(EGL_BAD_SURFACE, EGL_FALSE);
+ return EGL_FALSE;
+ }
+
+ nsecs_t* postedTime = nullptr;
+ nsecs_t* acquireTime = nullptr;
+ nsecs_t* refreshStartTime = nullptr;
+ nsecs_t* GLCompositionDoneTime = nullptr;
+ nsecs_t* displayRetireTime = nullptr;
+ nsecs_t* releaseTime = nullptr;
+
+ for (int i = 0; i < numTimestamps; i++) {
+ switch (timestamps[i]) {
+ case EGL_QUEUE_TIME_ANDROID:
+ postedTime = &values[i];
+ break;
+ case EGL_RENDERING_COMPLETE_TIME_ANDROID:
+ acquireTime = &values[i];
+ break;
+ case EGL_COMPOSITION_START_TIME_ANDROID:
+ refreshStartTime = &values[i];
+ break;
+ case EGL_COMPOSITION_FINISHED_TIME_ANDROID:
+ GLCompositionDoneTime = &values[i];
+ break;
+ case EGL_DISPLAY_RETIRE_TIME_ANDROID:
+ displayRetireTime = &values[i];
+ break;
+ case EGL_READS_DONE_TIME_ANDROID:
+ releaseTime = &values[i];
+ break;
+ default:
+ setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ return EGL_FALSE;
+ }
+ }
+
+ status_t ret = native_window_get_frame_timestamps(s->win.get(), framesAgo,
+ postedTime, acquireTime, refreshStartTime, GLCompositionDoneTime,
+ displayRetireTime, releaseTime);
+
+ if (ret != NO_ERROR) {
+ setError(EGL_BAD_ACCESS, EGL_FALSE);
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}
+
+EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface,
+ EGLint timestamp)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) {
+ setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ return EGL_FALSE;
+ }
+
+ SurfaceRef _s(dp.get(), surface);
+ if (!_s.get()) {
+ setError(EGL_BAD_SURFACE, EGL_FALSE);
+ return EGL_FALSE;
+ }
+
+ switch (timestamp) {
+ case EGL_QUEUE_TIME_ANDROID:
+ case EGL_RENDERING_COMPLETE_TIME_ANDROID:
+ case EGL_COMPOSITION_START_TIME_ANDROID:
+ case EGL_COMPOSITION_FINISHED_TIME_ANDROID:
+ case EGL_DISPLAY_RETIRE_TIME_ANDROID:
+ case EGL_READS_DONE_TIME_ANDROID:
+ return EGL_TRUE;
+ default:
+ return EGL_FALSE;
+ }
+}
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 90f27d1..cfecf77 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -68,7 +68,7 @@
EGLNativeWindowType win, EGLSurface surface,
egl_connection_t const* cnx) :
egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx),
- connected(true)
+ enableTimestamps(false), connected(true)
{
if (win) {
getDisplay()->onWindowSurfaceCreated();
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 8f3b9cb..97eda4c 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -139,6 +139,7 @@
EGLConfig config;
sp<ANativeWindow> win;
egl_connection_t const* cnx;
+ bool enableTimestamps;
private:
bool connected;
void disconnect();