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

Commit e5b755a0 authored by Pablo Ceballos's avatar Pablo Ceballos
Browse files

BQ: Get rid of setBufferCount

- Remove setBufferCount from BufferQueueProducer and
  IGraphicsBufferQueueProducer.
- Get rid of the unit tests for it.
- In Surface, convert setBufferCount calls into calls to
  setMaxDequeuedBufferCount.
- Change mOverrideMaxBufferCount to a boolean since it can now be
  derived from mMaxAcquiredBufferCount, mMaxDequeuedBufferCount, and
  mAsyncMode.

Bug 13174928

Change-Id: Ia0adc737fae9e13f186df832b8428a0829041bf9
parent fa455354
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -192,13 +192,6 @@ private:
    // a buffer attached
    std::list<int> mFreeBuffers;

    // mOverrideMaxBufferCount is the limit on the number of buffers that will
    // be allocated at one time. This value is set by the producer by calling
    // setBufferCount. The default is 0, which means that the producer doesn't
    // care about the number of buffers in the pool. In that case,
    // mDefaultMaxBufferCount is used as the limit.
    int mOverrideMaxBufferCount;

    // mDequeueCondition is a condition variable used for dequeueBuffer in
    // synchronous mode.
    mutable Condition mDequeueCondition;
@@ -247,6 +240,13 @@ private:
    // via setMaxDequeuedBufferCount.
    int mMaxDequeuedBufferCount;

    // mOverrideMaxBufferCount defaults to false and is set to true once the
    // producer has called setMaxDequeuedBufferCount or setAsyncMode. Once it is
    // set mDefaultMaxBufferCount is ignored and the max buffer count is
    // calculated based on mMaxAcquiredBufferCount, mMaxDequeuedBufferCount, and
    // mAsyncMode.
    bool mOverrideMaxBufferCount;

    // mBufferHasBeenQueued is true once a buffer has been queued. It is reset
    // when something causes all buffers to be freed (e.g., changing the buffer
    // count).
+0 −17
Original line number Diff line number Diff line
@@ -39,23 +39,6 @@ public:
    // flags indicating that previously-returned buffers are no longer valid.
    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);

    // setBufferCount updates the number of available buffer slots.  If this
    // method succeeds, buffer slots will be both unallocated and owned by
    // the BufferQueue object (i.e. they are not owned by the producer or
    // consumer).
    //
    // This will fail if the producer has dequeued any buffers, or if
    // bufferCount is invalid.  bufferCount must generally be a value
    // between the minimum undequeued buffer count (exclusive) and NUM_BUFFER_SLOTS
    // (inclusive).  It may also be set to zero (the default) to indicate
    // that the producer does not wish to set a value.  The minimum value
    // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
    // ...).
    //
    // This may only be called by the producer.  The consumer will be told
    // to discard buffers through the onBuffersReleased callback.
    virtual status_t setBufferCount(int bufferCount);

    // see IGraphicsBufferProducer::setMaxDequeuedBufferCount
    virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);

+0 −22
Original line number Diff line number Diff line
@@ -80,28 +80,6 @@ public:
    //              * buffer specified by the slot is not dequeued
    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;

    // setBufferCount sets the number of buffer slots available. Calling this
    // will also cause all buffer slots to be emptied. The caller should empty
    // its mirrored copy of the buffer slots when calling this method.
    //
    // This function should not be called when there are any dequeued buffer
    // slots, doing so will result in a BAD_VALUE error returned.
    //
    // The buffer count should be at most NUM_BUFFER_SLOTS (inclusive), but at least
    // the minimum undequeued buffer count (exclusive). The minimum value
    // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS).
    // In particular the range is (minUndequeudBuffers, NUM_BUFFER_SLOTS].
    //
    // The buffer count may also be set to 0 (the default), to indicate that
    // the producer does not wish to set a value.
    //
    // Return of a value other than NO_ERROR means an error has occurred:
    // * NO_INIT - the buffer queue has been abandoned.
    // * BAD_VALUE - one of the below conditions occurred:
    //              * bufferCount was out of range (see above)
    //              * client has one or more buffers dequeued
    virtual status_t setBufferCount(int bufferCount) = 0;

    // setMaxDequeuedBufferCount sets the maximum number of buffers that can be
    // dequeued by the producer at one time. If this method succeeds, buffer
    // slots will be both unallocated and owned by the BufferQueue object (i.e.
+6 −4
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
    mQueue(),
    mFreeSlots(),
    mFreeBuffers(),
    mOverrideMaxBufferCount(0),
    mDequeueCondition(),
    mUseAsyncBuffer(true),
    mDequeueBufferCannotBlock(false),
@@ -66,6 +65,7 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
    mDefaultMaxBufferCount(2),
    mMaxAcquiredBufferCount(1),
    mMaxDequeuedBufferCount(1),
    mOverrideMaxBufferCount(false),
    mBufferHasBeenQueued(false),
    mFrameCounter(0),
    mTransformHint(0),
@@ -164,9 +164,11 @@ int BufferQueueCore::getMaxBufferCountLocked(bool async) const {
    int minMaxBufferCount = getMinMaxBufferCountLocked(async);

    int maxBufferCount = max(mDefaultMaxBufferCount, minMaxBufferCount);
    if (mOverrideMaxBufferCount != 0) {
        assert(mOverrideMaxBufferCount >= minMaxBufferCount);
        maxBufferCount = mOverrideMaxBufferCount;
    if (mOverrideMaxBufferCount) {
        int bufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
                (async ? 1 : 0);
        assert(bufferCount >= minMaxBufferCount);
        maxBufferCount = bufferCount;
    }

    // Any buffers that are dequeued by the producer or sitting in the queue
+9 −105
Original line number Diff line number Diff line
@@ -72,66 +72,6 @@ status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
    return NO_ERROR;
}

status_t BufferQueueProducer::setBufferCount(int bufferCount) {
    ATRACE_CALL();
    BQ_LOGV("setBufferCount: count = %d", bufferCount);

    sp<IConsumerListener> listener;
    { // Autolock scope
        Mutex::Autolock lock(mCore->mMutex);
        mCore->waitWhileAllocatingLocked();

        if (mCore->mIsAbandoned) {
            BQ_LOGE("setBufferCount: BufferQueue has been abandoned");
            return NO_INIT;
        }

        if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
            BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
                    bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
            return BAD_VALUE;
        }

        // There must be no dequeued buffers when changing the buffer count.
        for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
            if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
                BQ_LOGE("setBufferCount: buffer owned by producer");
                return BAD_VALUE;
            }
        }

        if (bufferCount == 0) {
            mCore->mOverrideMaxBufferCount = 0;
            mCore->mDequeueCondition.broadcast();
            return NO_ERROR;
        }

        const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
        if (bufferCount < minBufferSlots) {
            BQ_LOGE("setBufferCount: requested buffer count %d is less than "
                    "minimum %d", bufferCount, minBufferSlots);
            return BAD_VALUE;
        }

        // Here we are guaranteed that the producer doesn't have any dequeued
        // buffers and will release all of its buffer references. We don't
        // clear the queue, however, so that currently queued buffers still
        // get displayed.
        mCore->freeAllBuffersLocked();
        mCore->mMaxDequeuedBufferCount = bufferCount - minBufferSlots + 1;
        mCore->mOverrideMaxBufferCount = bufferCount;
        mCore->mDequeueCondition.broadcast();
        listener = mCore->mConsumerListener;
    } // Autolock scope

    // Call back without lock held
    if (listener != NULL) {
        listener->onBuffersReleased();
    }

    return NO_ERROR;
}

status_t BufferQueueProducer::setMaxDequeuedBufferCount(
        int maxDequeuedBuffers) {
    ATRACE_CALL();
@@ -181,7 +121,7 @@ status_t BufferQueueProducer::setMaxDequeuedBufferCount(
        // get displayed.
        mCore->freeAllBuffersLocked();
        mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
        mCore->mOverrideMaxBufferCount = bufferCount;
        mCore->mOverrideMaxBufferCount = true;
        mCore->mDequeueCondition.broadcast();
        listener = mCore->mConsumerListener;
    } // Autolock scope
@@ -217,6 +157,7 @@ status_t BufferQueueProducer::setAsyncMode(bool async) {
        }

        mCore->mAsyncMode = async;
        mCore->mOverrideMaxBufferCount = true;
        mCore->mDequeueCondition.broadcast();
        listener = mCore->mConsumerListener;
    } // Autolock scope
@@ -238,16 +179,6 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
        }

        const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
        if (async && mCore->mOverrideMaxBufferCount) {
            // FIXME: Some drivers are manually setting the buffer count
            // (which they shouldn't), so we do this extra test here to
            // handle that case. This is TEMPORARY until we get this fixed.
            if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
                BQ_LOGE("%s: async mode is invalid with buffer count override",
                        caller);
                return BAD_VALUE;
            }
        }

        // Free up any buffers that are in slots beyond the max buffer count
        for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
@@ -273,33 +204,16 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
            }
        }

        // Producers are not allowed to dequeue more than one buffer if they
        // did not set a buffer count
        if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
            BQ_LOGE("%s: can't dequeue multiple buffers without setting the "
                    "buffer count", caller);
        // Producers are not allowed to dequeue more than
        // mMaxDequeuedBufferCount buffers.
        // This check is only done if a buffer has already been queued
        if (mCore->mBufferHasBeenQueued &&
                dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
            BQ_LOGE("%s: attempting to exceed the max dequeued buffer count "
                    "(%d)", caller, mCore->mMaxDequeuedBufferCount);
            return INVALID_OPERATION;
        }

        // See whether a buffer has been queued since the last
        // setBufferCount so we know whether to perform the min undequeued
        // buffers check below
        if (mCore->mBufferHasBeenQueued) {
            // Make sure the producer is not trying to dequeue more buffers
            // than allowed
            const int newUndequeuedCount =
                maxBufferCount - (dequeuedCount + 1);
            const int minUndequeuedCount =
                mCore->getMinUndequeuedBufferCountLocked(async);
            if (newUndequeuedCount < minUndequeuedCount) {
                BQ_LOGE("%s: min undequeued buffer count (%d) exceeded "
                        "(dequeued=%d undequeued=%d)",
                        caller, minUndequeuedCount,
                        dequeuedCount, newUndequeuedCount);
                return INVALID_OPERATION;
            }
        }

        *found = BufferQueueCore::INVALID_BUFFER_SLOT;

        // If we disconnect and reconnect quickly, we can be in a state where
@@ -683,16 +597,6 @@ status_t BufferQueueProducer::queueBuffer(int slot,
        }

        const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
        if (async && mCore->mOverrideMaxBufferCount) {
            // FIXME: Some drivers are manually setting the buffer count
            // (which they shouldn't), so we do this extra test here to
            // handle that case. This is TEMPORARY until we get this fixed.
            if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
                BQ_LOGE("queueBuffer: async mode is invalid with "
                        "buffer count override");
                return BAD_VALUE;
            }
        }

        if (slot < 0 || slot >= maxBufferCount) {
            BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
Loading