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) {
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index bd5eac2..074e97c 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -77,7 +77,8 @@
     virtual void dump(String8& result);
 
     // helpers
-    void flush();
+    // flush returns -1 or a valid native fence fd owned by the caller
+    int flush(bool wait);
     void clearWithColor(float red, float green, float blue, float alpha);
     void fillRegionWithColor(const Region& region, uint32_t height,
             float red, float green, float blue, float alpha);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8d87788..c34854b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4584,7 +4584,6 @@
         return PERMISSION_DENIED;
     }
 
-    int syncFd = -1;
     // create an EGLImage from the buffer so we can later
     // turn it into a texture
     EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
@@ -4610,43 +4609,7 @@
     // dependent on the context's EGLConfig.
     renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform);
 
-    // 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 = EGL_NO_SYNC_KHR;
-    if (!DEBUG_SCREENSHOTS) {
-       sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
-       // native fence fd will not be populated until flush() is done.
-       getRenderEngine().flush();
-    }
-
-    if (sync != EGL_NO_SYNC_KHR) {
-        // get the sync fd
-        syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
-        if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
-            ALOGW("captureScreen: failed to dup sync khr object");
-            syncFd = -1;
-        }
-        eglDestroySyncKHR(mEGLDisplay, sync);
-    } else {
-        // fallback path
-        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("captureScreen: fence wait timed out");
-            } else {
-                ALOGW_IF(eglErr != EGL_SUCCESS,
-                        "captureScreen: error waiting on EGL fence: %#x", eglErr);
-            }
-            eglDestroySyncKHR(mEGLDisplay, sync);
-        } else {
-            ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
-        }
-    }
-    *outSyncFd = syncFd;
+    *outSyncFd = getRenderEngine().flush(DEBUG_SCREENSHOTS);
 
     if (DEBUG_SCREENSHOTS) {
         const auto reqWidth = renderArea.getReqWidth();