surfaceflinger: move SurfaceFlingerConsumer::mPendingRelease

Move it and related methods to the base class, BufferLayerConsumer.

Test: boots
Change-Id: Ibe4d180aefbeeb3662fa40ca044d9d6fdd3b5765
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 0303d94..110b7de 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -21,6 +21,7 @@
 
 #include "BufferLayerConsumer.h"
 
+#include "DispSync.h"
 #include "Layer.h"
 
 #include <inttypes.h>
@@ -149,7 +150,56 @@
     mContentsChangedListener = listener;
 }
 
-status_t BufferLayerConsumer::updateTexImage() {
+// We need to determine the time when a buffer acquired now will be
+// displayed.  This can be calculated:
+//   time when previous buffer's actual-present fence was signaled
+//    + current display refresh rate * HWC latency
+//    + a little extra padding
+//
+// Buffer producers are expected to set their desired presentation time
+// based on choreographer time stamps, which (coming from vsync events)
+// will be slightly later then the actual-present timing.  If we get a
+// desired-present time that is unintentionally a hair after the next
+// vsync, we'll hold the frame when we really want to display it.  We
+// need to take the offset between actual-present and reported-vsync
+// into account.
+//
+// If the system is configured without a DispSync phase offset for the app,
+// we also want to throw in a bit of padding to avoid edge cases where we
+// just barely miss.  We want to do it here, not in every app.  A major
+// source of trouble is the app's use of the display's ideal refresh time
+// (via Display.getRefreshRate()), which could be off of the actual refresh
+// by a few percent, with the error multiplied by the number of frames
+// between now and when the buffer should be displayed.
+//
+// If the refresh reported to the app has a phase offset, we shouldn't need
+// to tweak anything here.
+nsecs_t BufferLayerConsumer::computeExpectedPresent(const DispSync& dispSync) {
+    // The HWC doesn't currently have a way to report additional latency.
+    // Assume that whatever we submit now will appear right after the flip.
+    // For a smart panel this might be 1.  This is expressed in frames,
+    // rather than time, because we expect to have a constant frame delay
+    // regardless of the refresh rate.
+    const uint32_t hwcLatency = 0;
+
+    // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
+    const nsecs_t nextRefresh = dispSync.computeNextRefresh(hwcLatency);
+
+    // The DispSync time is already adjusted for the difference between
+    // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so
+    // we don't need to factor that in here.  Pad a little to avoid
+    // weird effects if apps might be requesting times right on the edge.
+    nsecs_t extraPadding = 0;
+    if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) {
+        extraPadding = 1000000; // 1ms (6% of 60Hz)
+    }
+
+    return nextRefresh + extraPadding;
+}
+
+status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
+                                             bool* autoRefresh, bool* queuedBuffer,
+                                             uint64_t maxFrameNumber) {
     ATRACE_CALL();
     BLC_LOGV("updateTexImage");
     Mutex::Autolock lock(mMutex);
@@ -170,29 +220,86 @@
     // Acquire the next buffer.
     // In asynchronous mode the list is guaranteed to be one buffer
     // deep, while in synchronous mode we use the oldest buffer.
-    err = acquireBufferLocked(&item, 0);
+    err = acquireBufferLocked(&item, computeExpectedPresent(dispSync), maxFrameNumber);
     if (err != NO_ERROR) {
         if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
-            // We always bind the texture even if we don't update its contents.
-            BLC_LOGV("updateTexImage: no buffers were available");
-            glBindTexture(sTexTarget, mTexName);
             err = NO_ERROR;
+        } else if (err == BufferQueue::PRESENT_LATER) {
+            // return the error, without logging
         } else {
             BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
         }
         return err;
     }
 
+    if (autoRefresh) {
+        *autoRefresh = item.mAutoRefresh;
+    }
+
+    if (queuedBuffer) {
+        *queuedBuffer = item.mQueuedBuffer;
+    }
+
+    // We call the rejecter here, in case the caller has a reason to
+    // not accept this buffer.  This is used by SurfaceFlinger to
+    // reject buffers which have the wrong size
+    int slot = item.mSlot;
+    if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
+        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
+        return BUFFER_REJECTED;
+    }
+
     // Release the previous buffer.
-    err = updateAndReleaseLocked(item);
+    err = updateAndReleaseLocked(item, &mPendingRelease);
     if (err != NO_ERROR) {
-        // We always bind the texture.
-        glBindTexture(sTexTarget, mTexName);
         return err;
     }
 
-    // Bind the new buffer to the GL texture, and wait until it's ready.
-    return bindTextureImageLocked();
+    if (!SyncFeatures::getInstance().useNativeFenceSync()) {
+        // Bind the new buffer to the GL texture.
+        //
+        // Older devices require the "implicit" synchronization provided
+        // by glEGLImageTargetTexture2DOES, which this method calls.  Newer
+        // devices will either call this in Layer::onDraw, or (if it's not
+        // a GL-composited layer) not at all.
+        err = bindTextureImageLocked();
+    }
+
+    return err;
+}
+
+void BufferLayerConsumer::setReleaseFence(const sp<Fence>& fence) {
+    if (!fence->isValid()) {
+        return;
+    }
+
+    auto slot = mPendingRelease.isPending ? mPendingRelease.currentTexture : mCurrentTexture;
+    if (slot == BufferQueue::INVALID_BUFFER_SLOT) {
+        return;
+    }
+
+    auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer
+                                            : mCurrentTextureImage->graphicBuffer();
+    auto err = addReleaseFence(slot, buffer, fence);
+    if (err != OK) {
+        BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err);
+    }
+}
+
+bool BufferLayerConsumer::releasePendingBuffer() {
+    if (!mPendingRelease.isPending) {
+        BLC_LOGV("Pending buffer already released");
+        return false;
+    }
+    BLC_LOGV("Releasing pending buffer");
+    Mutex::Autolock lock(mMutex);
+    status_t result =
+            releaseBufferLocked(mPendingRelease.currentTexture, mPendingRelease.graphicBuffer);
+    if (result < NO_ERROR) {
+        BLC_LOGE("releasePendingBuffer failed: %s (%d)", strerror(-result), result);
+    }
+    mPendingRelease = PendingRelease();
+    return true;
 }
 
 status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
@@ -351,16 +458,6 @@
     return NO_ERROR;
 }
 
-void BufferLayerConsumer::setReleaseFence(const sp<Fence>& fence) {
-    if (fence->isValid() && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
-        status_t err =
-                addReleaseFence(mCurrentTexture, mCurrentTextureImage->graphicBuffer(), fence);
-        if (err != OK) {
-            BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err);
-        }
-    }
-}
-
 status_t BufferLayerConsumer::syncForReleaseLocked(EGLDisplay dpy) {
     BLC_LOGV("syncForReleaseLocked");
 
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index b8b3874..0da73d1 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -33,6 +33,7 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
+class DispSync;
 class Layer;
 class String8;
 
@@ -54,6 +55,16 @@
  */
 class BufferLayerConsumer : public ConsumerBase {
 public:
+    static const status_t BUFFER_REJECTED = UNKNOWN_ERROR + 8;
+
+    class BufferRejecter {
+        friend class BufferLayerConsumer;
+        virtual bool reject(const sp<GraphicBuffer>& buf, const BufferItem& item) = 0;
+
+    protected:
+        virtual ~BufferRejecter() {}
+    };
+
     struct ContentsChangedListener : public FrameAvailableListener {
         virtual void onSidebandStreamChanged() = 0;
     };
@@ -67,6 +78,8 @@
     // ConsumerBase::setFrameAvailableListener().
     void setContentsChangedListener(const wp<ContentsChangedListener>& listener);
 
+    nsecs_t computeExpectedPresent(const DispSync& dispSync);
+
     // updateTexImage acquires the most recently queued buffer, and sets the
     // image contents of the target texture to it.
     //
@@ -74,14 +87,22 @@
     // target texture belongs is bound to the calling thread.
     //
     // This calls doGLFenceWait to ensure proper synchronization.
-    status_t updateTexImage();
+    //
+    // This version of updateTexImage() takes a functor that may be used to
+    // reject the newly acquired buffer.  Unlike the GLConsumer version,
+    // this does not guarantee that the buffer has been bound to the GL
+    // texture.
+    status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync, bool* autoRefresh,
+                            bool* queuedBuffer, uint64_t maxFrameNumber);
 
     // setReleaseFence stores a fence that will signal when the current buffer
     // is no longer being read. This fence will be returned to the producer
     // when the current buffer is released by updateTexImage(). Multiple
     // fences can be set for a given buffer; they will be merged into a single
     // union fence.
-    virtual void setReleaseFence(const sp<Fence>& fence);
+    void setReleaseFence(const sp<Fence>& fence);
+
+    bool releasePendingBuffer();
 
     // getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
     // associated with the texture image set by the most recent call to
@@ -384,6 +405,10 @@
     // that no buffer is bound to the texture. A call to setBufferCount will
     // reset mCurrentTexture to INVALID_BUFFER_SLOT.
     int mCurrentTexture;
+
+    // A release that is pending on the receipt of a new release fence from
+    // presentDisplay
+    PendingRelease mPendingRelease;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 38b0057..1bb9028 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -33,80 +33,6 @@
 
 // ---------------------------------------------------------------------------
 
-status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
-        const DispSync& dispSync, bool* autoRefresh, bool* queuedBuffer,
-        uint64_t maxFrameNumber)
-{
-    ATRACE_CALL();
-    ALOGV("updateTexImage");
-    Mutex::Autolock lock(mMutex);
-
-    if (mAbandoned) {
-        ALOGE("updateTexImage: BufferLayerConsumer is abandoned!");
-        return NO_INIT;
-    }
-
-    // Make sure the EGL state is the same as in previous calls.
-    status_t err = checkAndUpdateEglStateLocked();
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    BufferItem item;
-
-    // Acquire the next buffer.
-    // In asynchronous mode the list is guaranteed to be one buffer
-    // deep, while in synchronous mode we use the oldest buffer.
-    err = acquireBufferLocked(&item, computeExpectedPresent(dispSync),
-            maxFrameNumber);
-    if (err != NO_ERROR) {
-        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
-            err = NO_ERROR;
-        } else if (err == BufferQueue::PRESENT_LATER) {
-            // return the error, without logging
-        } else {
-            ALOGE("updateTexImage: acquire failed: %s (%d)",
-                strerror(-err), err);
-        }
-        return err;
-    }
-
-    if (autoRefresh) {
-        *autoRefresh = item.mAutoRefresh;
-    }
-
-    if (queuedBuffer) {
-        *queuedBuffer = item.mQueuedBuffer;
-    }
-
-    // We call the rejecter here, in case the caller has a reason to
-    // not accept this buffer.  This is used by SurfaceFlinger to
-    // reject buffers which have the wrong size
-    int slot = item.mSlot;
-    if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
-        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
-        return BUFFER_REJECTED;
-    }
-
-    // Release the previous buffer.
-    err = updateAndReleaseLocked(item, &mPendingRelease);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    if (!SyncFeatures::getInstance().useNativeFenceSync()) {
-        // Bind the new buffer to the GL texture.
-        //
-        // Older devices require the "implicit" synchronization provided
-        // by glEGLImageTargetTexture2DOES, which this method calls.  Newer
-        // devices will either call this in Layer::onDraw, or (if it's not
-        // a GL-composited layer) not at all.
-        err = bindTextureImageLocked();
-    }
-
-    return err;
-}
-
 status_t SurfaceFlingerConsumer::bindTextureImage()
 {
     Mutex::Autolock lock(mMutex);
@@ -134,91 +60,11 @@
     return mSurfaceDamage;
 }
 
-// We need to determine the time when a buffer acquired now will be
-// displayed.  This can be calculated:
-//   time when previous buffer's actual-present fence was signaled
-//    + current display refresh rate * HWC latency
-//    + a little extra padding
-//
-// Buffer producers are expected to set their desired presentation time
-// based on choreographer time stamps, which (coming from vsync events)
-// will be slightly later then the actual-present timing.  If we get a
-// desired-present time that is unintentionally a hair after the next
-// vsync, we'll hold the frame when we really want to display it.  We
-// need to take the offset between actual-present and reported-vsync
-// into account.
-//
-// If the system is configured without a DispSync phase offset for the app,
-// we also want to throw in a bit of padding to avoid edge cases where we
-// just barely miss.  We want to do it here, not in every app.  A major
-// source of trouble is the app's use of the display's ideal refresh time
-// (via Display.getRefreshRate()), which could be off of the actual refresh
-// by a few percent, with the error multiplied by the number of frames
-// between now and when the buffer should be displayed.
-//
-// If the refresh reported to the app has a phase offset, we shouldn't need
-// to tweak anything here.
-nsecs_t SurfaceFlingerConsumer::computeExpectedPresent(const DispSync& dispSync)
-{
-    // The HWC doesn't currently have a way to report additional latency.
-    // Assume that whatever we submit now will appear right after the flip.
-    // For a smart panel this might be 1.  This is expressed in frames,
-    // rather than time, because we expect to have a constant frame delay
-    // regardless of the refresh rate.
-    const uint32_t hwcLatency = 0;
-
-    // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
-    const nsecs_t nextRefresh = dispSync.computeNextRefresh(hwcLatency);
-
-    // The DispSync time is already adjusted for the difference between
-    // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so
-    // we don't need to factor that in here.  Pad a little to avoid
-    // weird effects if apps might be requesting times right on the edge.
-    nsecs_t extraPadding = 0;
-    if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) {
-        extraPadding = 1000000;        // 1ms (6% of 60Hz)
-    }
-
-    return nextRefresh + extraPadding;
-}
-
 sp<Fence> SurfaceFlingerConsumer::getPrevFinalReleaseFence() const {
     Mutex::Autolock lock(mMutex);
     return ConsumerBase::mPrevFinalReleaseFence;
 }
 
-void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence)
-{
-    if (!mPendingRelease.isPending) {
-        BufferLayerConsumer::setReleaseFence(fence);
-        return;
-    }
-    auto currentTexture = mPendingRelease.currentTexture;
-    if (fence->isValid() &&
-            currentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
-        status_t result = addReleaseFence(currentTexture,
-                mPendingRelease.graphicBuffer, fence);
-        ALOGE_IF(result != NO_ERROR, "setReleaseFence: failed to add the"
-                " fence: %s (%d)", strerror(-result), result);
-    }
-}
-
-bool SurfaceFlingerConsumer::releasePendingBuffer()
-{
-    if (!mPendingRelease.isPending) {
-        ALOGV("Pending buffer already released");
-        return false;
-    }
-    ALOGV("Releasing pending buffer");
-    Mutex::Autolock lock(mMutex);
-    status_t result = releaseBufferLocked(mPendingRelease.currentTexture,
-            mPendingRelease.graphicBuffer);
-    ALOGE_IF(result < NO_ERROR, "releasePendingBuffer failed: %s (%d)",
-            strerror(-result), result);
-    mPendingRelease = PendingRelease();
-    return true;
-}
-
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index 3a6beae..f4c594a 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -32,34 +32,15 @@
  */
 class SurfaceFlingerConsumer : public BufferLayerConsumer {
 public:
-    static const status_t BUFFER_REJECTED = UNKNOWN_ERROR + 8;
-
     SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
             uint32_t tex, Layer* layer)
         : BufferLayerConsumer(consumer, tex, layer),
           mTransformToDisplayInverse(false), mSurfaceDamage()
     {}
 
-    class BufferRejecter {
-        friend class SurfaceFlingerConsumer;
-        virtual bool reject(const sp<GraphicBuffer>& buf,
-                const BufferItem& item) = 0;
-
-    protected:
-        virtual ~BufferRejecter() { }
-    };
-
     virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen,
             uint64_t maxFrameNumber = 0) override;
 
-    // This version of updateTexImage() takes a functor that may be used to
-    // reject the newly acquired buffer.  Unlike the BufferLayerConsumer version,
-    // this does not guarantee that the buffer has been bound to the GL
-    // texture.
-    status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
-            bool* autoRefresh, bool* queuedBuffer,
-            uint64_t maxFrameNumber);
-
     // See BufferLayerConsumer::bindTextureImageLocked().
     status_t bindTextureImage();
 
@@ -68,11 +49,7 @@
     // must be called from SF main thread
     const Region& getSurfaceDamage() const;
 
-    nsecs_t computeExpectedPresent(const DispSync& dispSync);
-
     sp<Fence> getPrevFinalReleaseFence() const;
-    virtual void setReleaseFence(const sp<Fence>& fence) override;
-    bool releasePendingBuffer();
 
 private:
     // Indicates this buffer must be transformed by the inverse transform of the screen
@@ -82,10 +59,6 @@
 
     // The portion of this surface that has changed since the previous frame
     Region mSurfaceDamage;
-
-    // A release that is pending on the receipt of a new release fence from
-    // presentDisplay
-    PendingRelease mPendingRelease;
 };
 
 // ----------------------------------------------------------------------------