Add support for latching unsignaled buffers in Skia RenderEngine.

When we re-added support for latching unsignaled buffers we forgot to
propagate this support to Skia RenderEngine, since we were assuming that
latching unsignaled buffers would no longer be supported.

Because partners are still relying on latching unsignaled buffers being
available for good performance in some use-cases, Skia RenderEngine
needs to wait on incoming buffer fences to prevent tearing.

Bug: 196201621
Bug: 195033578
Test: atest librenderengine_test
Change-Id: I1f3be882e55de20bdbfa3bf92bf0b8f88b8bc3ea
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 052c61f..cb686a6 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -424,14 +424,28 @@
     return fenceFd;
 }
 
-bool SkiaGLRenderEngine::waitFence(base::unique_fd fenceFd) {
+void SkiaGLRenderEngine::waitFence(base::borrowed_fd fenceFd) {
+    if (fenceFd.get() >= 0 && !waitGpuFence(fenceFd)) {
+        ATRACE_NAME("SkiaGLRenderEngine::waitFence");
+        sync_wait(fenceFd.get(), -1);
+    }
+}
+
+bool SkiaGLRenderEngine::waitGpuFence(base::borrowed_fd fenceFd) {
     if (!gl::GLExtensions::getInstance().hasNativeFenceSync() ||
         !gl::GLExtensions::getInstance().hasWaitSync()) {
         return false;
     }
 
+    // Duplicate the fence for passing to eglCreateSyncKHR.
+    base::unique_fd fenceDup(dup(fenceFd.get()));
+    if (fenceDup.get() < 0) {
+        ALOGE("failed to create duplicate fence fd: %d", fenceDup.get());
+        return false;
+    }
+
     // release the fd and transfer the ownership to EGLSync
-    EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd.release(), EGL_NONE};
+    EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceDup.release(), EGL_NONE};
     EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
     if (sync == EGL_NO_SYNC_KHR) {
         ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
@@ -727,14 +741,6 @@
         return;
     }
 
-    if (bufferFence.get() >= 0) {
-        // Duplicate the fence for passing to waitFence.
-        base::unique_fd bufferFenceDup(dup(bufferFence.get()));
-        if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) {
-            ATRACE_NAME("Waiting before draw");
-            sync_wait(bufferFence.get(), -1);
-        }
-    }
     if (buffer == nullptr) {
         ALOGE("No output buffer provided. Aborting GPU composition.");
         resultPromise->set_value({BAD_VALUE, base::unique_fd()});
@@ -760,6 +766,9 @@
                                                                true, mTextureCleanupMgr);
     }
 
+    // wait on the buffer to be ready to use prior to using it
+    waitFence(bufferFence);
+
     const ui::Dataspace dstDataspace =
             mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR;
     sk_sp<SkSurface> dstSurface = surfaceTextureRef->getOrCreateSurface(dstDataspace, grContext);
@@ -995,6 +1004,12 @@
                                                       false, mTextureCleanupMgr);
             }
 
+            // if the layer's buffer has a fence, then we must must respect the fence prior to using
+            // the buffer.
+            if (layer->source.buffer.fence != nullptr) {
+                waitFence(layer->source.buffer.fence->get());
+            }
+
             // isOpaque means we need to ignore the alpha in the image,
             // replacing it with the alpha specified by the LayerSettings. See
             // https://developer.android.com/reference/android/view/SurfaceControl.Builder#setOpaque(boolean)