Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1585c4d9 authored by Andy McFadden's avatar Andy McFadden
Browse files

Pay attention to buffer timestamps

When acquiring a buffer, SurfaceFlinger now computes the expected
presentation time and passes it to the BufferQueue acquireBuffer()
method.  If it's not yet time to display the buffer, acquireBuffer()
returns PRESENT_LATER instead of a buffer.

The current implementation of the expected-present-time computation
uses approximations and guesswork.

Bug 7900302

Change-Id: If9345611c5983a11a811935aaf27d6388a5036f1
parent 06b6aed2
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -71,7 +71,8 @@ class BufferItemConsumer: public ConsumerBase
    //
    // If waitForFence is true, and the acquired BufferItem has a valid fence object,
    // acquireBuffer will wait on the fence with no timeout before returning.
    status_t acquireBuffer(BufferItem *item, bool waitForFence = true);
    status_t acquireBuffer(BufferItem *item, nsecs_t presentWhen,
        bool waitForFence = true);

    // Returns an acquired buffer to the queue, allowing it to be reused. Since
    // only a fixed number of buffers may be acquired at a time, old buffers
+8 −2
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ public:
    enum { NUM_BUFFER_SLOTS = 32 };
    enum { NO_CONNECTED_API = 0 };
    enum { INVALID_BUFFER_SLOT = -1 };
    enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE };
    enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE, PRESENT_LATER };

    // When in async mode we reserve two slots in order to guarantee that the
    // producer and consumer can run asynchronously.
@@ -284,7 +284,13 @@ public:
    // acquired then the BufferItem::mGraphicBuffer field of buffer is set to
    // NULL and it is assumed that the consumer still holds a reference to the
    // buffer.
    status_t acquireBuffer(BufferItem *buffer);
    //
    // If presentWhen is nonzero, it indicates the time when the buffer will
    // be displayed on screen.  If the buffer's timestamp is farther in the
    // future, the buffer won't be acquired, and PRESENT_LATER will be
    // returned.  The presentation time is in nanoseconds, and the time base
    // is CLOCK_MONOTONIC.
    status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen);

    // releaseBuffer releases a buffer slot from the consumer back to the
    // BufferQueue.  This may be done while the buffer's contents are still
+2 −1
Original line number Diff line number Diff line
@@ -152,7 +152,8 @@ protected:
    // initialization that must take place the first time a buffer is assigned
    // to a slot.  If it is overridden the derived class's implementation must
    // call ConsumerBase::acquireBufferLocked.
    virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item);
    virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item,
        nsecs_t presentWhen);

    // releaseBufferLocked relinquishes control over a buffer, returning that
    // control to the BufferQueue.
+2 −1
Original line number Diff line number Diff line
@@ -237,7 +237,8 @@ protected:

    // acquireBufferLocked overrides the ConsumerBase method to update the
    // mEglSlots array in addition to the ConsumerBase behavior.
    virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item);
    virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item,
        nsecs_t presentWhen);

    // releaseBufferLocked overrides the ConsumerBase method to update the
    // mEglSlots array in addition to the ConsumerBase.
+3 −2
Original line number Diff line number Diff line
@@ -47,14 +47,15 @@ void BufferItemConsumer::setName(const String8& name) {
    mBufferQueue->setConsumerName(name);
}

status_t BufferItemConsumer::acquireBuffer(BufferItem *item, bool waitForFence) {
status_t BufferItemConsumer::acquireBuffer(BufferItem *item,
        nsecs_t presentWhen, bool waitForFence) {
    status_t err;

    if (!item) return BAD_VALUE;

    Mutex::Autolock _l(mMutex);

    err = acquireBufferLocked(item);
    err = acquireBufferLocked(item, presentWhen);
    if (err != OK) {
        if (err != NO_BUFFER_AVAILABLE) {
            BI_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
Loading