diff options
| -rw-r--r-- | opengl/include/EGL/eglext.h | 18 | ||||
| -rw-r--r-- | opengl/libs/EGL/eglApi.cpp | 114 | ||||
| -rw-r--r-- | opengl/libs/EGL/egl_object.cpp | 2 | ||||
| -rw-r--r-- | opengl/libs/EGL/egl_object.h | 1 | ||||
| -rw-r--r-- | opengl/specs/EGL_ANDROID_get_frame_timestamps.txt | 145 | ||||
| -rw-r--r-- | opengl/specs/README | 9 |
6 files changed, 286 insertions, 3 deletions
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index bef5f02aa3..2e186985e6 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -621,6 +621,24 @@ typedef EGLAPI EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDRO #define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000 #endif +#ifndef EGL_ANDROID_get_frame_timestamps +#define EGL_ANDROID_get_frame_timestamps 1 +#define EGL_TIMESTAMPS_ANDROID 0x314D +#define EGL_QUEUE_TIME_ANDROID 0x314E +#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F +#define EGL_COMPOSITION_START_TIME_ANDROID 0x3430 +#define EGL_COMPOSITION_FINISHED_TIME_ANDROID 0x3431 +#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3432 +#define EGL_READS_DONE_TIME_ANDROID 0x3433 +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); +EGLAPI EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp); +#else +typedef EGLAPI EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); +typedef EGLAPI EGLBoolean (EGLAPIENTRYP PFNEGLQUERYTIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp); +#endif +#endif + #ifdef __cplusplus } #endif diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index e793852caa..7a0cce48b2 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -84,6 +84,7 @@ extern char const * const gBuiltinExtensionString = "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 @@ static const extention_map_t sExtensionMap[] = { (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR }, { "eglCreateStreamFromFileDescriptorKHR", (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR }, + + // EGL_ANDROID_get_frame_timestamps + { "eglGetFrameTimestampsANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID }, + { "eglQueryTimestampSupportedANDROID", + (__eglMustCastToProperFunctionPointerType)&eglQueryTimestampSupportedANDROID }, }; /* @@ -1196,7 +1203,7 @@ EGLBoolean eglSurfaceAttrib( 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 @@ EGLBoolean eglSurfaceAttrib( 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 @@ EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, 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 90f27d1c7d..cfecf77021 100644 --- a/opengl/libs/EGL/egl_object.cpp +++ b/opengl/libs/EGL/egl_object.cpp @@ -68,7 +68,7 @@ egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config, 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 8f3b9cb2b5..97eda4ce79 100644 --- a/opengl/libs/EGL/egl_object.h +++ b/opengl/libs/EGL/egl_object.h @@ -139,6 +139,7 @@ public: EGLConfig config; sp<ANativeWindow> win; egl_connection_t const* cnx; + bool enableTimestamps; private: bool connected; void disconnect(); diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt new file mode 100644 index 0000000000..30337ad7a9 --- /dev/null +++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt @@ -0,0 +1,145 @@ +Name + + ANDROID_get_frame_timestamps + +Name Strings + + EGL_ANDROID_get_frame_timestamps + +Contributors + + Pablo Ceballos + +Contact + + Pablo Ceballos, Google Inc. (pceballos 'at' google.com) + +Status + + Draft + +Version + + Version 1, May 31, 2016 + +Number + + EGL Extension #XXX + +Dependencies + + Requires EGL 1.2 + + This extension is written against the wording of the EGL 1.5 Specification + +Overview + + This extension allows querying various timestamps related to the composition + and display of window surfaces. + + Some examples of how this might be used: + - The display retire time can be used to calculate end-to-end latency of + the entire graphics pipeline. + - The queue time and rendering complete time can be used to determine + how long the application's rendering took to complete. Likewise, the + composition start time and finish time can be used to determine how + long the compositor's rendering work took. In combination these can be + used to help determine if the system is GPU or CPU bound. + +New Types + + /* + * EGLnsecsANDROID is a signed integer type for representing a time in + * nanoseconds. + */ + #include <khrplatform.h> + typedef khronos_stime_nanoseconds_t EGLnsecsANDROID; + +New Procedures and Functions + + EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, + EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, + EGLnsecsANDROID *values); + + EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface + surface, EGLint timestamp); + +New Tokens + + EGL_TIMESTAMPS_ANDROID 0x314D + EGL_QUEUE_TIME_ANDROID 0x314E + EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F + EGL_COMPOSITION_START_TIME_ANDROID 0x3430 + EGL_COMPOSITION_FINISHED_TIME_ANDROID 0x3431 + EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3432 + EGL_READS_DONE_TIME_ANDROID 0x3433 + +Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6 +"Surface Attributes", page 43: + + If attribute is EGL_TIMESTAMPS_ANDROID, then values specifies whether to + enable/disable timestamp collection for this surface. A value of EGL_TRUE + enables timestamp collection, while a value of EGL_FALSE disables it. The + initial value is false. If surface is not a window surface this has no + effect. + +Changes to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors) + + Add a new subsection under Section 3, + + "3.13 Composition and Display Timestamps + + The function + + EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface + surface, EGLint framesAgo, EGLint numTimestamps, + const EGLint *timestamps, EGLnsecsANDROID *values); + + allows querying various timestamps related to the composition and display of + a window surface. + + The framesAgo parameter indicates how many frames before the last posted + frame to query. So a value of zero would indicate that the query is for the + last posted frame. Note that the implementation maintains a limited history + of timestamp data. If a query is made for a frame whose timestamp history + no longer exists then EGL_BAD_ACCESS is generated. If timestamp collection + has not been enabled for the surface then EGL_BAD_SURFACE is generated. + Timestamps for events that will not occur or have not yet occurred will be + zero. Timestamp queries that are not supported will generate an + EGL_BAD_PARAMETER error. If any error is generated the function will return + EGL_FALSE. + + The eglGetFrameTimestampsANDROID function takes an array of timestamps to + query and returns timestamps in the corresponding indices of the values + array. The possible timestamps that can be queried are: + - EGL_QUEUE_TIME_ANDROID - The time this frame was queued by the + application. + - EGL_RENDERING_COMPLETE_TIME_ANDROID - The time when all of the + application's rendering to the surface was completed. + - EGL_COMPOSITION_START_TIME_ANDROID - The time at which the compositor + began preparing composition for this frame. + - EGL_COMPOSITION_FINISHED_TIME_ANDROID - The time at which the + compositor's rendering work for this frame finished. This will be zero + if composition was handled by the display and the compositor didn't do + any rendering. + - EGL_DISPLAY_RETIRE_TIME_ANDROID - The time at which this frame was + replaced by the next frame on-screen. + - EGL_READS_DONE_TIME_ANDROID - The time at which all reads for the + purpose of display/composition were completed for this frame. + + Not all implementations may support all off the above timestamp queries. The + function + + EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface + surface, EGLint timestamp); + + allows querying which timestamps are supported on the implementation." + +Issues + + None + +Revision History + +#1 (Pablo Ceballos, May 31, 2016) + - Initial draft. diff --git a/opengl/specs/README b/opengl/specs/README index 8f1eaf3cf6..f0c024ee66 100644 --- a/opengl/specs/README +++ b/opengl/specs/README @@ -19,4 +19,11 @@ for use by Android extensions. 0x314A EGL_IMAGE_CROP_RIGHT_ANDROID (EGL_ANDROID_image_crop) 0x314B EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop) 0x314C EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh) -0x314D - 0x314F (unused) +0x314D EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x314E EGL_QUEUE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x314F EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3430 EGL_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3431 EGL_COMPOSITION_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3432 EGL_DISPLAY_RETIRE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3433 EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3434 - 0x343F (unused) |