am fd6b64f6: Merge "SurfaceTexture: Fix to return the oldest of free buffers to Client on Dequeue call" into ics-mr1

* commit 'fd6b64f6ad040b4d550a5219a2576997e2c0e85d':
  SurfaceTexture: Fix to return the oldest of free buffers to Client on Dequeue call
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index d7dd4d6..27d863d 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -271,7 +271,8 @@
               mRequestBufferCalled(false),
               mTransform(0),
               mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
-              mTimestamp(0) {
+              mTimestamp(0),
+              mFrameNumber(0) {
             mCrop.makeInvalid();
         }
 
@@ -340,6 +341,10 @@
         // mTimestamp is the current timestamp for this buffer slot. This gets
         // to set by queueBuffer each time this slot is queued.
         int64_t mTimestamp;
+
+        // mFrameNumber is the number of the queued frame for this slot.
+        uint64_t mFrameNumber;
+
     };
 
     // mSlots is the array of buffer slots that must be mirrored on the client
@@ -476,6 +481,12 @@
     // around a GL driver limitation on the number of FBO attachments, which the
     // browser's tile cache exceeds.
     const GLenum mTexTarget;
+
+    // mFrameCounter is the free running counter, incremented for every buffer queued
+    // with the surface Texture.
+    uint64_t mFrameCounter;
+
+
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 374f3c5..ee54bf4 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -116,7 +116,8 @@
     mAllowSynchronousMode(allowSynchronousMode),
     mConnectedApi(NO_CONNECTED_API),
     mAbandoned(false),
-    mTexTarget(texTarget) {
+    mTexTarget(texTarget),
+    mFrameCounter(0) {
     // Choose a name using the PID and a process-unique ID.
     mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
 
@@ -264,7 +265,8 @@
 
     status_t returnFlags(OK);
 
-    int found, foundSync;
+    int found = -1;
+    int foundSync = -1;
     int dequeuedCount = 0;
     bool tryAgain = true;
     while (tryAgain) {
@@ -337,9 +339,14 @@
                 }
             } else {
                 if (state == BufferSlot::FREE) {
-                    foundSync = i;
-                    found = i;
-                    break;
+                    /** For Asynchronous mode, we need to return the oldest of free buffers
+                    * There is only one instance when the Framecounter overflows, this logic
+                    * might return the earlier buffer to client. Which is a negligible impact
+                    **/
+                    if (found < 0 || mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
+                        foundSync = i;
+                        found = i;
+                    }
                 }
             }
         }
@@ -531,6 +538,9 @@
         mSlots[buf].mTransform = mNextTransform;
         mSlots[buf].mScalingMode = mNextScalingMode;
         mSlots[buf].mTimestamp = timestamp;
+        mFrameCounter++;
+        mSlots[buf].mFrameNumber = mFrameCounter;
+
         mDequeueCondition.signal();
 
         *outWidth = mDefaultWidth;
@@ -564,6 +574,7 @@
         return;
     }
     mSlots[buf].mBufferState = BufferSlot::FREE;
+    mSlots[buf].mFrameNumber = 0;
     mDequeueCondition.signal();
 }
 
@@ -897,6 +908,7 @@
 void SurfaceTexture::freeBufferLocked(int i) {
     mSlots[i].mGraphicBuffer = 0;
     mSlots[i].mBufferState = BufferSlot::FREE;
+    mSlots[i].mFrameNumber = 0;
     if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
         eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
         mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;