Pass fence to HWC on first use of buffer

Also do a CPU-wait on the fence before using it for GL composition.

Change-Id: I0f645a42a44803276cae11b904e5a26d65871562
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6aba16a..5b9327d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -60,6 +60,7 @@
         mCurrentOpacity(true),
         mRefreshPending(false),
         mFrameLatencyNeeded(false),
+        mNeedHwcFence(false),
         mFrameLatencyOffset(0),
         mFormat(PIXEL_FORMAT_NONE),
         mGLExtensions(GLExtensions::getInstance()),
@@ -299,6 +300,20 @@
     // NOTE: buffer can be NULL if the client never drew into this
     // layer yet, or if we ran out of memory
     layer.setBuffer(buffer);
+
+    if (mNeedHwcFence) {
+        sp<Fence> fence = mSurfaceTexture->getCurrentFence();
+        if (fence.get()) {
+            int fenceFd = fence->dup();
+            if (fenceFd == -1) {
+                ALOGW("failed to dup layer fence, skipping sync: %d", errno);
+            }
+            layer.setAcquireFenceFd(fenceFd);
+        }
+        mNeedHwcFence = false;
+    } else {
+        layer.setAcquireFenceFd(-1);
+    }
 }
 
 void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
@@ -333,6 +348,15 @@
         return;
     }
 
+    // TODO: replace this with a server-side wait
+    sp<Fence> fence = mSurfaceTexture->getCurrentFence();
+    if (fence.get()) {
+        status_t err = fence->wait(Fence::TIMEOUT_NEVER);
+        ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
+        // Go ahead and draw the buffer anyway; no matter what we do the screen
+        // is probably going to have something visibly wrong.
+    }
+
     if (!isProtected()) {
         // TODO: we could be more subtle with isFixedSize()
         const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
@@ -627,6 +651,7 @@
 
         mRefreshPending = true;
         mFrameLatencyNeeded = true;
+        mNeedHwcFence = true;
         if (oldActiveBuffer == NULL) {
              // the first time we receive a buffer, we need to trigger a
              // geometry invalidation.