bufferqueues: Move the gl fence wait from dequeue to releaseBuffer

Bug: 339705065
Flag: com.android.graphics.libgui.flags.bq_gl_fence_cleanup
Test: old tests

Change-Id: I429118e2f23691c8858100343f40b8cc156133ea
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index d0607bf..9855b5b 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -28,6 +28,10 @@
 #define VALIDATE_CONSISTENCY()
 #endif
 
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
 #include <gui/BufferItem.h>
 #include <gui/BufferQueueConsumer.h>
 #include <gui/BufferQueueCore.h>
@@ -486,6 +490,27 @@
         return BAD_VALUE;
     }
 
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+    if (eglFence != EGL_NO_SYNC_KHR) {
+        // Most platforms will be using native fences, so it's unlikely that we'll ever have to
+        // process an eglFence. Ideally we can remove this code eventually. In the mean time, do our
+        // best to wait for it so the buffer stays valid, otherwise return an error to the caller.
+        //
+        // EGL_SYNC_FLUSH_COMMANDS_BIT_KHR so that we don't wait forever on a fence that hasn't
+        // shown up on the GPU yet.
+        EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
+                                             1000000000);
+        if (result == EGL_FALSE) {
+            BQ_LOGE("releaseBuffer: error %#x waiting for fence", eglGetError());
+            return UNKNOWN_ERROR;
+        } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+            BQ_LOGE("releaseBuffer: timeout waiting for fence");
+            return UNKNOWN_ERROR;
+        }
+        eglDestroySyncKHR(eglDisplay, eglFence);
+    }
+#endif
+
     sp<IProducerListener> listener;
     { // Autolock scope
         std::lock_guard<std::mutex> lock(mCore->mMutex);
@@ -507,8 +532,10 @@
             return BAD_VALUE;
         }
 
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
         mSlots[slot].mEglDisplay = eglDisplay;
         mSlots[slot].mEglFence = eglFence;
+#endif
         mSlots[slot].mFence = releaseFence;
         mSlots[slot].mBufferState.release();