surfaceflinger: return fence fd from RenderEngine::flush
The caller does not need to work with EGLSync after this chnage.
Test: SurfaceFlinger_test
Change-Id: I1cf7d11d3023d09be8a73001493c39b4309e7542
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 332f2e0..560f74e 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -247,8 +247,51 @@
drawMesh(mesh);
}
-void RenderEngine::flush() {
- glFlush();
+int RenderEngine::flush(bool wait) {
+ // Attempt to create a sync khr object that can produce a sync point. If that
+ // isn't available, create a non-dupable sync object in the fallback path and
+ // wait on it directly.
+ EGLSyncKHR sync;
+ if (!wait) {
+ EGLint syncFd = EGL_NO_NATIVE_FENCE_FD_ANDROID;
+
+ sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+ if (sync != EGL_NO_SYNC_KHR) {
+ // native fence fd will not be populated until flush() is done.
+ glFlush();
+
+ // get the sync fd
+ syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
+ if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ ALOGW("failed to dup sync khr object");
+ }
+
+ eglDestroySyncKHR(mEGLDisplay, sync);
+ }
+
+ if (syncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ return syncFd;
+ }
+ }
+
+ // fallback or explicit wait
+ sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
+ if (sync != EGL_NO_SYNC_KHR) {
+ EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
+ EGLint eglErr = eglGetError();
+ if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ ALOGW("fence wait timed out");
+ } else {
+ ALOGW_IF(eglErr != EGL_SUCCESS,
+ "error waiting on EGL fence: %#x", eglErr);
+ }
+ eglDestroySyncKHR(mEGLDisplay, sync);
+ } else {
+ ALOGW("error creating EGL fence: %#x", eglGetError());
+ }
+
+ return -1;
}
void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {